From f12635ccd91b21bf8038880043a5244b3e0371d8 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Fri, 18 Oct 2024 13:26:43 +0300 Subject: [PATCH] Prevent monster generation in the sokoban trap hallway Makes Sokoban far less tedious when you don't have to worry about monsters randomly popping up in the trap hallway while you're pushing the boulder. Adds a new exclusion zone for monster generation, and the goodpos routine avoids the zones when GP_AVOID_MONPOS is used. --- dat/soko1-1.lua | 2 ++ dat/soko1-2.lua | 2 ++ dat/soko2-1.lua | 2 ++ dat/soko2-2.lua | 2 ++ dat/soko3-1.lua | 2 ++ dat/soko3-2.lua | 2 ++ dat/soko4-1.lua | 2 ++ dat/soko4-2.lua | 3 +++ doc/fixes3-7-0.txt | 3 ++- doc/lua.adoc | 5 +++-- include/dungeon.h | 3 ++- include/extern.h | 3 +++ src/makemon.c | 2 +- src/mkmaze.c | 3 +-- src/sp_lev.c | 4 ++-- src/teleport.c | 14 ++++++++++++++ 16 files changed, 45 insertions(+), 9 deletions(-) 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