Skip to content

Commit

Permalink
Fix: issues with portal placement on nymph level.
Browse files Browse the repository at this point in the history
This wasn't an issue until the rooms on the nymph level transitioned
from 'ordinary' to 'garden' type rooms, so this isn't an issue with past
versions. The nymph level will now have one ordinary room for portal
placement in case the sokoban stairs or quest level portal happens to
generate on the same level as the nymph level.

Nymph level appearance spread is now levels 8-20, inclusive.

Named the nymph level 'Aphrodite's Garden', did some code formatting
cleanup here as well.
  • Loading branch information
k21971 committed Sep 30, 2024
1 parent 9920bb4 commit 2137a42
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 51 deletions.
2 changes: 1 addition & 1 deletion dat/dungeon.def
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ CHAINBRANCH: "Sokoban" "oracle" + (1, 0) up
RNDLEVEL: "bigrm" "B" @ (10, 3) 40 10
CHAINBRANCH: "The Quest" "oracle" + (6, 2) portal
BRANCH: "Fort Ludios" @ (18, 4) portal
LEVEL: "nymph" "N" @ (8, 15) 45
LEVEL: "nymph" "N" @ (8, 12) 45
RNDLEVEL: "medusa" "none" @ (-5, 4) 4
LEVALIGN: chaotic
CHAINBRANCH: "The Ice Queen's Realm" "medusa" + (-1, 0) portal
Expand Down
37 changes: 18 additions & 19 deletions dat/nymph.des
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
LEVEL: "nymph"
ROOM: "garden", unlit, random, random, (12,07)
{
[30%]:TERRAIN: random, 'T'
[30%]:TERRAIN: random, 'T'
[30%]:TERRAIN: random, 'T'
[30%]:TERRAIN: random, 'T'
FOUNTAIN:random
[30%]:TERRAIN:random, 'T'
[30%]:TERRAIN:random, 'T'
[30%]:TERRAIN:random, 'T'
[30%]:TERRAIN:random, 'T'
FOUNTAIN:(06,03)
TRAP:"board",random
TRAP:"board",random
OBJECT:('(',"chest"),random
Expand Down Expand Up @@ -62,33 +62,33 @@ TRAP:random, random
OBJECT:random, random
}

ROOM: "garden", random, random, random, random
# normal room, in case of branch portal/stairs placement
ROOM: "ordinary", random, random, random, random
{
[30%]:TERRAIN:random, 'T'
[30%]:TERRAIN:random, 'T'
[30%]:TERRAIN:random, 'T'
[30%]:TERRAIN:random, 'T'
FOUNTAIN:random
TRAP:"board",random
TRAP:random, random
OBJECT:random, random
OBJECT:random, random
IF [50%] {
IF [75%] {
MONSTER:('s',"centipede"), random, hostile
} ELSE {
MONSTER:('S',"snake"), random, hostile
}
}
MONSTER:'n', random, hostile
MONSTER:'n', random, hostile
}

ROOM: "garden", random, random, random, random
{
TRAP:"board",random
TRAP:random, random
OBJECT:random, random
OBJECT:random, random
IF [50%] {
IF [75%] {
MONSTER:('s',"centipede"), random, hostile
} ELSE {
MONSTER:('S',"pit viper"), random, hostile
MONSTER:('S',"snake"), random, hostile
}
}

}

ROOM: "garden", random, random, random, random
Expand All @@ -100,10 +100,9 @@ IF [50%] {
IF [75%] {
MONSTER:('s',"centipede"), random, hostile
} ELSE {
MONSTER:('s',"scorpion"), random, hostile
MONSTER:('S',"pit viper"), random, hostile
}
}

}

RANDOM_CORRIDORS
1 change: 1 addition & 0 deletions doc/evilhack-changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3642,4 +3642,5 @@ The following changes to date are:
'what' used (windows compile)
- Fix: error: for tile 89 (numbered 89) of other.txt, found 'swallow
top left' while expecting 'cmap 89'
- Fix: issues with portal placement on nymph level

2 changes: 2 additions & 0 deletions include/decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ E struct dgn_topology { /* special dungeon levels for speed */
xchar d_mines_dnum, d_quest_dnum;
d_level d_qstart_level, d_qlocate_level, d_nemesis_level;
d_level d_knox_level;
d_level d_nymph_level;
d_level d_mineend_level;
d_level d_minetn_level;
d_level d_sokoend_level;
Expand Down Expand Up @@ -106,6 +107,7 @@ E struct dgn_topology { /* special dungeon levels for speed */
#define qlocate_level (dungeon_topology.d_qlocate_level)
#define nemesis_level (dungeon_topology.d_nemesis_level)
#define knox_level (dungeon_topology.d_knox_level)
#define nymph_level (dungeon_topology.d_nymph_level)
#define mineend_level (dungeon_topology.d_mineend_level)
#define minetn_level (dungeon_topology.d_minetn_level)
#define sokoend_level (dungeon_topology.d_sokoend_level)
Expand Down
3 changes: 3 additions & 0 deletions include/dungeon.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ typedef struct branch {
#define Is_qlocate(x) (Lcheck(x, &qlocate_level))
#define Is_nemesis(x) (Lcheck(x, &nemesis_level))
#define Is_knox(x) (Lcheck(x, &knox_level))
#define Is_nymph(x) (Lcheck(x, &nymph_level))
#define Is_mineend_level(x) (Lcheck(x, &mineend_level))
#define Is_minetn_level(x) (Lcheck(x, &minetn_level))
#define Is_sokoend_level(x) (Lcheck(x, &sokoend_level))
Expand Down Expand Up @@ -228,6 +229,7 @@ typedef struct mapseen {
Bitfield(ngrave, 2);
Bitfield(ntree, 2);
Bitfield(ndeadtree, 2);
Bitfield(ngrass, 2);
Bitfield(water, 2);
Bitfield(lava, 2);

Expand All @@ -248,6 +250,7 @@ typedef struct mapseen {
Bitfield(oracle, 1);
Bitfield(sokosolved, 1);
Bitfield(bigroom, 1);
Bitfield(nymph, 1);
Bitfield(castle, 1);
Bitfield(castletune, 1); /* add tune hint to castle annotation */

Expand Down
1 change: 1 addition & 0 deletions src/detect.c
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,7 @@ static const struct {
} level_detects[] = {
{ "Delphi", &oracle_level },
{ "Medusa's lair", &medusa_level },
{ "Aphrodite's garden", &nymph_level },
{ "a castle", &stronghold_level },
{ "the Wizard of Yendor's tower", &wiz1_level },
};
Expand Down
28 changes: 20 additions & 8 deletions src/dungeon.c
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ struct level_map {
{ "hellc", &hellc_level },
{ "knox", &knox_level },
{ "medusa", &medusa_level },
{ "nymph", &nymph_level },
{ "oracle", &oracle_level },
{ "orcus", &orcus_level },
{ "rogue", &rogue_level },
Expand Down Expand Up @@ -2397,10 +2398,11 @@ d_level *lev;
}
}

#define INTEREST(feat) \
((feat).nfount || (feat).nsink || (feat).nthrone || (feat).naltar \
|| (feat).ngrave || (feat).ntree || (feat).nshop || (feat).ntemple \
|| (feat).nforge || (feat).ndeadtree || (feat).nmagicchest)
#define INTEREST(feat) \
((feat).nfount || (feat).nsink || (feat).nthrone || (feat).naltar \
|| (feat).ngrave || (feat).ntree || (feat).nshop || (feat).ntemple \
|| (feat).nforge || (feat).ndeadtree || (feat).ngrass \
|| (feat).nmagicchest)
/* || (feat).water || (feat).ice || (feat).lava */

/* returns true if this level has something interesting to print out */
Expand All @@ -2413,9 +2415,10 @@ mapseen *mptr;
if (mptr->flags.unreachable || mptr->flags.forgot)
return FALSE;
/* level is of interest if it has an auto-generated annotation */
if (mptr->flags.oracle || mptr->flags.bigroom || mptr->flags.roguelevel
|| mptr->flags.castle || mptr->flags.valley || mptr->flags.msanctum
|| mptr->flags.quest_summons || mptr->flags.questing)
if (mptr->flags.oracle || mptr->flags.bigroom || mptr->flags.nymph
|| mptr->flags.roguelevel || mptr->flags.castle || mptr->flags.valley
|| mptr->flags.msanctum || mptr->flags.quest_summons
|| mptr->flags.questing)
return TRUE;
/* when in Sokoban, list all sokoban levels visited; when not in it,
list any visited Sokoban level which remains unsolved (will usually
Expand Down Expand Up @@ -2486,6 +2489,7 @@ recalc_mapseen()
mptr->flags.bigroom = Is_bigroom(&u.uz);
else if (mptr->flags.forgot)
mptr->flags.bigroom = 0;
mptr->flags.nymph = Is_nymph(&u.uz);
mptr->flags.roguelevel = Is_rogue_level(&u.uz);
mptr->flags.oracle = 0; /* recalculated during room traversal below */
mptr->flags.castletune = 0;
Expand Down Expand Up @@ -2598,6 +2602,11 @@ recalc_mapseen()
if (count <= 3)
mptr->feat.ndeadtree = count;
break;
case GRASS:
count = mptr->feat.ngrass + 1;
if (count <= 2)
mptr->feat.ngrass = count;
break;
case FOUNTAIN:
count = mptr->feat.nfount + 1;
if (count <= 3)
Expand Down Expand Up @@ -2955,7 +2964,7 @@ char *outbuf;
do { \
if (var) \
Sprintf(eos(buf), "%s%s %s%s", COMMA, seen_string((var), (nam)), \
(nam), plur(var)); \
(nam), (var == mptr->feat.ngrass) ? "" : plur(var)); \
} while (0)
#define ADDTOBUF(nam, var) \
do { \
Expand Down Expand Up @@ -3066,6 +3075,7 @@ boolean printdun;
ADDNTOBUF("grave", mptr->feat.ngrave);
ADDNTOBUF("tree", mptr->feat.ntree);
ADDNTOBUF("dead tree", mptr->feat.ndeadtree);
ADDNTOBUF("grass", mptr->feat.ngrass);
#if 0
ADDTOBUF("water", mptr->feat.water);
ADDTOBUF("lava", mptr->feat.lava);
Expand All @@ -3088,6 +3098,8 @@ boolean printdun;
mptr->flags.sokosolved ? "Solved" : "Unsolved");
} else if (mptr->flags.bigroom) {
Sprintf(buf, "%sA very big room.", PREFIX);
} else if (mptr->flags.nymph) {
Sprintf(buf, "%sAphrodite's Garden.", PREFIX);
} else if (mptr->flags.roguelevel) {
Sprintf(buf, "%sA primitive area.", PREFIX);
} else if (on_level(&mptr->lev, &qstart_level)) {
Expand Down
7 changes: 4 additions & 3 deletions src/mklev.c
Original file line number Diff line number Diff line change
Expand Up @@ -975,10 +975,10 @@ makelevel()
mkroom(BARRACKS);
else if (u_depth > 15 && !rn2(6))
mkroom(SWAMP);
else if (u_depth > 16 && !rn2(8)
else if (u_depth > 15 && !rn2(8)
&& !(mvitals[PM_COCKATRICE].mvflags & G_GONE))
mkroom(COCKNEST);
else if (u_depth > 17 && !rn2(7)
else if (u_depth > 16 && !rn2(6)
&& !(mvitals[PM_MIND_FLAYER_LARVA].mvflags & G_GONE))
mkroom(NURSERY);
}
Expand Down Expand Up @@ -1336,7 +1336,8 @@ coord *mp;
croom = &rooms[rn2(nroom)];

if (!somexyspace(croom, mp, 2)) {
if (!somexyspace(croom, mp, 0) && !In_hell(&u.uz))
if (!somexyspace(croom, mp, 0)
&& !In_hell(&u.uz) && !Is_nymph(&u.uz))
impossible("Can't place branch!");
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/mkmaze.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,12 @@ xchar x, y;
xchar lx, ly, hx, hy;
{
return (boolean) (occupied(x, y)
|| is_open_air(x, y)
|| within_bounded_area(x, y, lx, ly, hx, hy)
|| !((levl[x][y].typ == CORR && level.flags.is_maze_lev)
|| levl[x][y].typ == ROOM
|| levl[x][y].typ == GRASS
|| levl[x][y].typ == ICE
|| levl[x][y].typ == AIR));
}

Expand Down Expand Up @@ -361,7 +363,8 @@ d_level *lev;
u_on_newpos(x, y);
break;
case LR_PORTAL:
mkportal(x, y, lev->dnum, lev->dlevel);
if (rtype != GARDEN)
mkportal(x, y, lev->dnum, lev->dlevel);
break;
case LR_DOWNSTAIR:
case LR_UPSTAIR:
Expand Down
39 changes: 24 additions & 15 deletions src/mkroom.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ mkshop()
mktemple();
return;
}
if (*ep == 'n') {
if (*ep == 'n' || *ep == 'N') {
mkgarden((struct mkroom *) 0);
return;
}
Expand Down Expand Up @@ -659,46 +659,53 @@ STATIC_OVL void
mkgarden(croom)
struct mkroom *croom; /* NULL == choose random room */
{
register int tryct = 0;
boolean maderoom = FALSE;
coord pos;
register int i, tried;
int i, tried, tryct = 0;

while ((tryct++ < 25) && !maderoom) {
register struct mkroom *sroom = croom ? croom : &rooms[rn2(nroom)];
struct mkroom *sroom = croom ? croom : &rooms[rn2(nroom)];

if (sroom->hx < 0
|| (!croom && (sroom->rtype != OROOM || !sroom->rlit
|| has_upstairs(sroom) || has_dnstairs(sroom))))
continue;

sroom->rtype = GARDEN;
/* create grass */
for (pos.x = sroom->lx; pos.x <= sroom->hx; pos.x++) {
for (pos.y = sroom->ly; pos.y <= sroom->hy; pos.y++) {
if (levl[pos.x][pos.y].typ == ROOM)
if (levl[pos.x][pos.y].typ == ROOM
&& !t_at(pos.x, pos.y))
levl[pos.x][pos.y].typ = GRASS;
}
}
maderoom = TRUE;
level.flags.has_garden = 1;

/* create nymphs */
tried = 0;
i = rnd(2);
while ((tried++ < 50) && (i >= 0) && somexy(sroom, &pos)) {
struct permonst *pmon;

if (!MON_AT(pos.x, pos.y) && (pmon = mkclass(S_NYMPH, 0))) {
struct monst *mtmp = makemon(pmon, pos.x,pos.y, NO_MM_FLAGS);
if (!OBJ_AT(pos.x, pos.y) && !MON_AT(pos.x, pos.y)
&& !t_at(pos.x, pos.y) && (pmon = mkclass(S_NYMPH, 0))) {
struct monst *mtmp = makemon(pmon, pos.x, pos.y, NO_MM_FLAGS);

if (rn2(2))
mtmp->msleeping = 1;
i--;
}
}

/* create trees/fountains */
tried = 0;
i = rn1(3, 3);
while ((tried++ < 50) && (i >= 0) && somexy(sroom, &pos)) {
if (levl[pos.x][pos.y].typ == GRASS && !MON_AT(pos.x, pos.y)
&& !nexttodoor(pos.x, pos.y)) {
if (levl[pos.x][pos.y].typ == GRASS
&& !OBJ_AT(pos.x, pos.y) && !MON_AT(pos.x, pos.y)
&& !t_at(pos.x, pos.y) && !nexttodoor(pos.x, pos.y)) {
if (rn2(5)) {
levl[pos.x][pos.y].typ = TREE;
} else {
Expand All @@ -725,19 +732,19 @@ mkswamp() /* Michiel Huisjes & Fred de Wilde */

/* satisfied; make a swamp */
sroom->rtype = SWAMP;
for (sx = sroom->lx; sx <= sroom->hx; sx++)
for (sy = sroom->ly; sy <= sroom->hy; sy++)
for (sx = sroom->lx; sx <= sroom->hx; sx++) {
for (sy = sroom->ly; sy <= sroom->hy; sy++) {
if (!OBJ_AT(sx, sy) && !MON_AT(sx, sy) && !t_at(sx, sy)
&& !nexttodoor(sx, sy)) {
if ((sx + sy) % 2) {
levl[sx][sy].typ = POOL;
if (!eelct || !rn2(4)) {
/* mkclass() won't do, as we might get kraken */
(void) makemon(rn2(5)
? &mons[PM_GIANT_EEL]
: rn2(2)
? &mons[PM_PIRANHA]
: &mons[PM_ELECTRIC_EEL],
? &mons[PM_GIANT_EEL]
: rn2(2)
? &mons[PM_PIRANHA]
: &mons[PM_ELECTRIC_EEL],
sx, sy, NO_MM_FLAGS);
if (!rn2(50))
(void) makemon(&mons[PM_SEA_DRAGON],
Expand All @@ -753,6 +760,8 @@ mkswamp() /* Michiel Huisjes & Fred de Wilde */
sx, sy, NO_MM_FLAGS);
}
}
}
}
level.flags.has_swamp = 1;
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/objnam.c
Original file line number Diff line number Diff line change
Expand Up @@ -2643,7 +2643,7 @@ static const char *const as_is[] = {
"moose", "ninja", "sheep", "ronin", "roshi",
"shito", "tengu", "ki-rin", "Nazgul", "gunyoki",
"piranha", "samurai", "shuriken", "eldritch ki-rin",
"drow", "undead", 0,
"drow", "undead", 0,
/* Note: "fish" and "piranha" are collective plurals, suitable
for "wiped out all <foo>". For "3 <foo>", they should be
"fishes" and "piranhas" instead. We settle for collective
Expand Down Expand Up @@ -2680,9 +2680,9 @@ const char *const *alt_as_is; /* another set like as_is[] */
if ((baselen > 5) && (!BSTRCMPI(basestr, endstring - 5, "craft")))
return TRUE;
/* avoid false hit on one_off[].plur == "lice" or .sing == "goose";
if more of these turn up, one_off[] entries will need to flagged
as to which are whole words and which are matchable as suffices
then matching in the loop below will end up becoming more complex */
if more of these turn up, one_off[] entries will need to flagged
as to which are whole words and which are matchable as suffices
then matching in the loop below will end up becoming more complex */
if (!strcmpi(basestr, "slice")
|| !strcmpi(basestr, "mongoose")) {
if (to_plural)
Expand Down

0 comments on commit 2137a42

Please sign in to comment.