Skip to content

Commit a5114ee

Browse files
Fix: portal to quest would sometimes not spawn if entry portal spawned on Aphrodite's Garden or the Desolate Forest levels.
This was a weird one, initially caught while fuzzing. This started out as an issue with a gold vault spawning on either Aphrodite's garden level or the desolate forest level, and that vault being chosen to spawn a portal to Fort Ludios. Fixed that (I think 😁) and then noticed some more weirdness with the number of rooms spawning on those levels not being as high as they should be. One thing led to another, discovered I did not have to have a special ordinary room spawn on either of those special levels, a portal to the quest could generate just fine without it. Then started to see 'portal on top of portal??' impossible messages when a quest portal would spawn on those special levels - sometimes, but not all the time. This meant there was a non-zero chance that the game could become unwinnable under certain, albeit rare, conditions. This went from a nuicance during fuzzing to a serious issue. Took a bit of doing, but terrapin and I narrowed it down to some issues in the somexyspace() function. Discovered that the creation of grass in those special level rooms would mess with portal generation. Added a couple exclusions for grass (and sand while there), and while poking around in somexyspace(), noticed that the check for (xy_flags & 2) was slightly wrong, and had been this way for a looooong time. So long story short - fixed quest portal placement for those special levels, normal rooms are no longer required there, fixed somexyspace(). I need a drink. Co-authored-by: saltwaterterrapin <[email protected]>
1 parent 56fdf14 commit a5114ee

File tree

6 files changed

+35
-17
lines changed

6 files changed

+35
-17
lines changed

dat/forest.des

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ OBJECT:random, random
3636
}
3737

3838
# normal room, in case of branch portal/stairs placement
39-
ROOM: "ordinary", random, random, random, random
39+
ROOM: "forest", random, random, random, random
4040
{
4141
[30%]:TERRAIN:random, 't'
4242
[30%]:TERRAIN:random, 't'

dat/nymph.des

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ OBJECT:random, random
6363
}
6464

6565
# normal room, in case of branch portal/stairs placement
66-
ROOM: "ordinary", random, random, random, random
66+
ROOM: "garden", random, random, random, random
6767
{
6868
[30%]:TERRAIN:random, 'T'
6969
[30%]:TERRAIN:random, 'T'

doc/evilhack-changelog.md

+2
Original file line numberDiff line numberDiff line change
@@ -4360,4 +4360,6 @@ The following changes to date are:
43604360
- Fix: impossible "trying to break non-equipped glass obj?" when
43614361
attacking with certain objects
43624362
- Fix: grammar feedback when spells like barkskin or stoneskin wear off
4363+
- Fix: portal to quest would sometimes not spawn if entry portal spawned
4364+
on Aphrodite's Garden or the Desolate Forest levels
43634365

src/mklev.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -1342,9 +1342,7 @@ coord *mp;
13421342

13431343
if (!somexyspace(croom, mp, 2)) {
13441344
if (!somexyspace(croom, mp, 0)
1345-
&& !In_hell(&u.uz)
1346-
&& !Is_nymph(&u.uz)
1347-
&& !Is_forest(&u.uz))
1345+
&& !In_hell(&u.uz))
13481346
impossible("Can't place branch!");
13491347
}
13501348
}
@@ -2227,6 +2225,8 @@ xchar x, y;
22272225
return;
22282226

22292227
if (!(u.uz.dnum == oracle_level.dnum /* in main dungeon */
2228+
&& u.uz.dnum == nymph_level.dnum /* Aphrodite's garden */
2229+
&& u.uz.dnum == forest_level.dnum /* Desolate Forest */
22302230
&& !at_dgn_entrance("The Quest") /* but not Quest's entry */
22312231
&& (u_depth = depth(&u.uz)) > 10 /* beneath 10 */
22322232
&& u_depth < depth(&medusa_level))) /* and above Medusa */

src/mkmaze.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,7 @@ d_level *lev;
365365
u_on_newpos(x, y);
366366
break;
367367
case LR_PORTAL:
368-
if (!(rtype == GARDEN || rtype == FOREST))
369-
mkportal(x, y, lev->dnum, lev->dlevel);
368+
mkportal(x, y, lev->dnum, lev->dlevel);
370369
break;
371370
case LR_DOWNSTAIR:
372371
case LR_UPSTAIR:

src/mkroom.c

+27-10
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,9 @@ struct mkroom *croom; /* NULL == choose random room */
688688
continue;
689689

690690
sroom->rtype = GARDEN;
691+
maderoom = TRUE;
692+
level.flags.has_garden = 1;
693+
691694
/* create grass */
692695
for (pos.x = sroom->lx; pos.x <= sroom->hx; pos.x++) {
693696
for (pos.y = sroom->ly; pos.y <= sroom->hy; pos.y++) {
@@ -696,8 +699,6 @@ struct mkroom *croom; /* NULL == choose random room */
696699
levl[pos.x][pos.y].typ = GRASS;
697700
}
698701
}
699-
maderoom = TRUE;
700-
level.flags.has_garden = 1;
701702

702703
/* create trees/fountains */
703704
tried = 0;
@@ -769,6 +770,9 @@ struct mkroom *croom; /* NULL == choose random room */
769770
continue;
770771

771772
sroom->rtype = FOREST;
773+
maderoom = TRUE;
774+
level.flags.has_forest = 1;
775+
772776
/* create grass */
773777
for (pos.x = sroom->lx; pos.x <= sroom->hx; pos.x++) {
774778
for (pos.y = sroom->ly; pos.y <= sroom->hy; pos.y++) {
@@ -777,8 +781,6 @@ struct mkroom *croom; /* NULL == choose random room */
777781
levl[pos.x][pos.y].typ = GRASS;
778782
}
779783
}
780-
maderoom = TRUE;
781-
level.flags.has_forest = 1;
782784

783785
/* create dead trees and shallow water */
784786
tried = 0;
@@ -1068,26 +1070,41 @@ int xy_flags;
10681070
{
10691071
int tryct = 0;
10701072
boolean isok;
1073+
10711074
do {
10721075
isok = TRUE;
10731076
if (croom && !somexy(croom, pos))
10741077
isok = FALSE;
10751078
if ((xy_flags & 16))
10761079
mazexy(pos);
1077-
if ((xy_flags & 1) && (IS_POOL(levl[pos->x][pos->y].typ)
1078-
|| IS_FURNITURE(levl[pos->x][pos->y].typ)))
1080+
if ((xy_flags & 1)
1081+
&& (IS_POOL(levl[pos->x][pos->y].typ)
1082+
|| IS_FURNITURE(levl[pos->x][pos->y].typ)))
10791083
isok = FALSE;
1080-
if (((xy_flags & 2) && (levl[pos->x][pos->y].typ != CORR))
1081-
|| (levl[pos->x][pos->y].typ != ROOM))
1084+
if ((xy_flags & 2)
1085+
&& ((levl[pos->x][pos->y].typ != CORR)
1086+
|| (levl[pos->x][pos->y].typ != ROOM)
1087+
|| (levl[pos->x][pos->y].typ != SAND)
1088+
|| (levl[pos->x][pos->y].typ != GRASS)))
10821089
isok = FALSE;
10831090
if ((xy_flags & 4) && (sobj_at(BOULDER, pos->x, pos->y)))
10841091
isok = FALSE;
10851092
if ((xy_flags & 8) && bydoor(pos->x, pos->y))
10861093
isok = FALSE;
10871094
} while ((!isok || !SPACE_POS(levl[pos->x][pos->y].typ)
1088-
|| occupied(pos->x, pos->y)) && (++tryct < 500));
1089-
if ((tryct < 500) && isok)
1095+
|| !(levl[pos->x][pos->y].typ == ROOM
1096+
|| levl[pos->x][pos->y].typ == CORR
1097+
|| levl[pos->x][pos->y].typ == ICE
1098+
|| levl[pos->x][pos->y].typ == SAND
1099+
|| levl[pos->x][pos->y].typ == GRASS)
1100+
|| occupied(pos->x, pos->y))
1101+
&& (++tryct < 2000));
1102+
1103+
/* make tryct greater than the total number of possible
1104+
tile spaces on any given map */
1105+
if ((tryct < 2000) && isok)
10901106
return TRUE;
1107+
10911108
return FALSE;
10921109
}
10931110

0 commit comments

Comments
 (0)