diff --git a/dat/soko1-1.lua b/dat/soko1-1.lua index bd90ecdc4..ba5a9dfd7 100644 --- a/dat/soko1-1.lua +++ b/dat/soko1-1.lua @@ -59,6 +59,8 @@ des.object("boulder", 09, 12); -- des.object("boulder", 03, 14); +-- prevent monster generation over the (filled) holes +des.exclusion({ type = "monster-generation", region = { 08,01, 23,01 } }); -- Traps des.trap("hole", 08, 01); des.trap("hole", 09, 01); diff --git a/dat/soko1-2.lua b/dat/soko1-2.lua index aff446df5..2ff3a9feb 100644 --- a/dat/soko1-2.lua +++ b/dat/soko1-2.lua @@ -60,6 +60,8 @@ des.object("boulder",10,08); des.object("boulder",12,09); des.object("boulder",11,10); +-- prevent monster generation over the (filled) holes +des.exclusion({ type = "monster-generation", region = { 05,01, 22,01 } }); -- Traps des.trap("hole",05,01) des.trap("hole",06,01) diff --git a/dat/soko2-1.lua b/dat/soko2-1.lua index 42cdcc5dd..eb66e0fbf 100644 --- a/dat/soko2-1.lua +++ b/dat/soko2-1.lua @@ -46,6 +46,8 @@ des.object("boulder",03,09) des.object("boulder",05,07) des.object("boulder",06,06) +-- prevent monster generation over the (filled) holes +des.exclusion({ type = "monster-generation", region = { 07,09, 18,09 } }); -- Traps des.trap("hole",08,09) des.trap("hole",09,09) diff --git a/dat/soko2-2.lua b/dat/soko2-2.lua index 27af1df10..1302a1b5e 100644 --- a/dat/soko2-2.lua +++ b/dat/soko2-2.lua @@ -46,6 +46,8 @@ des.object("boulder",06,09) des.object("boulder",05,10) des.object("boulder",05,11) +-- prevent monster generation over the (filled) holes +des.exclusion({ type = "monster-generation", region = { 06,11, 18,11 } }); -- Traps des.trap("hole",07,11) des.trap("hole",08,11) diff --git a/dat/soko3-1.lua b/dat/soko3-1.lua index bf14fbfad..2515ffca1 100644 --- a/dat/soko3-1.lua +++ b/dat/soko3-1.lua @@ -52,6 +52,8 @@ des.object("boulder",09,09) des.object("boulder",10,07) des.object("boulder",10,10) +-- prevent monster generation over the (filled) holes +des.exclusion({ type = "monster-generation", region = { 11,10, 27,10 } }); -- Traps des.trap("hole",12,10) des.trap("hole",13,10) diff --git a/dat/soko3-2.lua b/dat/soko3-2.lua index 855575552..1015125d6 100644 --- a/dat/soko3-2.lua +++ b/dat/soko3-2.lua @@ -47,6 +47,8 @@ des.object("boulder",07,10) des.object("boulder",10,10) des.object("boulder",03,11) +-- prevent monster generation over the (filled) holes +des.exclusion({ type = "monster-generation", region = { 12,10, 24,10 } }); -- Traps des.trap("hole",12,10) des.trap("hole",13,10) diff --git a/dat/soko4-1.lua b/dat/soko4-1.lua index 0998220f5..4c8f6d162 100644 --- a/dat/soko4-1.lua +++ b/dat/soko4-1.lua @@ -72,6 +72,8 @@ des.object("boulder",09,09) des.object("boulder",08,10) des.object("boulder",10,10) +-- prevent monster generation over the (filled) pits +des.exclusion({ type = "monster-generation", region = { 01,06, 07,11 } }); -- Traps des.trap("pit",03,06) des.trap("pit",04,06) diff --git a/dat/soko4-2.lua b/dat/soko4-2.lua index 6b994a95a..de749ad37 100644 --- a/dat/soko4-2.lua +++ b/dat/soko4-2.lua @@ -41,6 +41,9 @@ des.object("boulder",08,08) des.object("boulder",09,08) des.object("boulder",10,08) +-- prevent monster generation over the (filled) pits +des.exclusion({ type = "monster-generation", region = { 01,01, 01,09 } }); +des.exclusion({ type = "monster-generation", region = { 01,08, 07,09 } }); -- Traps des.trap("pit",01,02) des.trap("pit",01,03) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 13910d97b..d6059729b 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1237,7 +1237,7 @@ when a werecreature in human form attacked hero, it could transform to critter status highlighting for hit points didn't work as intended for up or down HP changes; 'up' rule was used for both, 'down' rule was ignored unhide an unseen water monster using a polymorph trap on land -allow defining random-teleport exclusion zones in lua +allow defining random-teleport or monster-generation exclusion zones in lua if Magicbane cancelled a shapeshifter, forcing it to 'unshift', subsequent messages continued to refer to the shifted form a pet that was poison resistant but not stoning resistant would eat Medusa's @@ -1473,6 +1473,7 @@ interactively setting a status highlight for hunger with 'O' and choosing use C++ regex processing but not for tty+posixregex a pet with the hides-under attribute could "move reluctantly over" a cursed object and then hide under it +prevent monster generation in the sokoban trap hallway Fixes to 3.7.0-x General Problems Exposed Via git Repository diff --git a/doc/lua.adoc b/doc/lua.adoc index 84758dc3f..66983807d 100644 --- a/doc/lua.adoc +++ b/doc/lua.adoc @@ -531,9 +531,10 @@ Example: === exclusion Exclude an area of the map from being randomly chosen target when -falling or teleporting into the level. Multiple exclusions per level are allowed. +falling or teleporting into the level, or creating a monster. +Multiple exclusions per level are allowed. -* type is one of "teleport", "teleport-up", or "teleport-down". +* type is one of "teleport", "teleport-up", "teleport-down", or "monster-generation". Example: diff --git a/include/dungeon.h b/include/dungeon.h index 09ea8dd0e..288b15b58 100644 --- a/include/dungeon.h +++ b/include/dungeon.h @@ -39,7 +39,8 @@ enum level_region_types { LR_BRANCH, LR_TELE, LR_UPTELE, - LR_DOWNTELE + LR_DOWNTELE, + LR_MONGEN, }; typedef struct dest_area { /* non-stairway level change identifier */ diff --git a/include/extern.h b/include/extern.h index 046045e7c..3b3d28f32 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1552,6 +1552,7 @@ extern void bound_digging(void); extern void mkportal(coordxy, coordxy, xint16, xint16); extern boolean bad_location(coordxy, coordxy, coordxy, coordxy, coordxy, coordxy); +extern boolean is_exclusion_zone(xint16, coordxy, coordxy); /* dungeon.c u_on_rndspot() passes NULL final arg to place_lregion() */ extern void place_lregion(coordxy, coordxy, coordxy, coordxy, coordxy, coordxy, coordxy, coordxy, xint16, d_level *) NO_NNARGS; @@ -3075,6 +3076,8 @@ extern boolean goodpos(coordxy, coordxy, struct monst *, mmflags_nht) NO_NNARGS; extern boolean enexto(coord *, coordxy, coordxy, struct permonst *) NONNULLARG1; +extern boolean enexto_gpflags(coord *, coordxy, coordxy, struct permonst *, + mmflags_nht) NONNULLARG1; extern boolean enexto_core(coord *, coordxy, coordxy, struct permonst *, mmflags_nht) NONNULLARG1; extern void teleds(coordxy, coordxy, int); diff --git a/src/makemon.c b/src/makemon.c index 828328ab2..ae32e8f39 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -129,7 +129,7 @@ m_initgrp( * are peaceful and some are not, the result will just be a * smaller group. */ - if (enexto(&mm, mm.x, mm.y, mtmp->data)) { + if (enexto_gpflags(&mm, mm.x, mm.y, mtmp->data, mmflags)) { mon = makemon(mtmp->data, mm.x, mm.y, (mmflags | MM_NOGRP)); if (mon) { mon->mpeaceful = FALSE; diff --git a/src/mkmaze.c b/src/mkmaze.c index d485dabdf..4237e00e9 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -26,7 +26,6 @@ staticfn void stolen_booty(void); staticfn boolean maze_inbounds(coordxy, coordxy); staticfn void maze_remove_deadends(xint16); staticfn void populate_maze(void); -staticfn boolean is_exclusion_zone(xint16, coordxy, coordxy); /* adjust a coordinate one step in the specified direction */ #define mz_move(X, Y, dir) \ @@ -302,7 +301,7 @@ maze0xy(coord *cc) return; } -staticfn boolean +boolean is_exclusion_zone(xint16 type, coordxy x, coordxy y) { struct exclusion_zone *ez = sve.exclusion_zones; diff --git a/src/sp_lev.c b/src/sp_lev.c index 0796757bd..5e7be44e7 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -5446,10 +5446,10 @@ int lspo_exclusion(lua_State *L) { static const char *const ez_types[] = { - "teleport", "teleport-up", "teleport-down", NULL + "teleport", "teleport-up", "teleport-down", "monster-generation", NULL }; static const int ez_types2i[] = { - LR_TELE, LR_UPTELE, LR_DOWNTELE, 0 + LR_TELE, LR_UPTELE, LR_DOWNTELE, LR_MONGEN, 0 }; struct exclusion_zone *ez = (struct exclusion_zone *) alloc(sizeof *ez); lua_Integer x1,y1,x2,y2; diff --git a/src/teleport.c b/src/teleport.c index e4aeedbe3..5b51a3a0a 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -172,6 +172,9 @@ goodpos( /* skip boulder locations for most creatures */ if (sobj_at(BOULDER, x, y) && (!mdat || !throws_rocks(mdat))) return FALSE; + /* pretend GP_AVOID_MONPOS == monster creation */ + if (avoid_monpos && is_exclusion_zone(LR_MONGEN, x, y)) + return FALSE; return TRUE; } @@ -194,6 +197,17 @@ enexto( || enexto_core(cc, xx, yy, mdat, NO_MM_FLAGS)); } +boolean +enexto_gpflags( + coord *cc, + coordxy xx, coordxy yy, + struct permonst *mdat, + mmflags_nht entflags) +{ + return (enexto_core(cc, xx, yy, mdat, GP_CHECKSCARY | entflags) + || enexto_core(cc, xx, yy, mdat, entflags)); +} + #ifdef NEW_ENEXTO boolean