diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index e4aec2f8d..9472d54b1 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -46,7 +46,7 @@ .ds f0 \*(vr .ds f1 \" empty .\"DO NOT REMOVE NH_DATESUB .ds f2 DATE(%B %-d, %Y) -.ds f2 July 29, 2024 +.ds f2 August 11, 2024 . .\" A note on some special characters: .\" \(lq = left double quote @@ -1696,6 +1696,9 @@ In normal play you can view the explored portion of the current level's map without monsters; without monsters and objects; or without monsters, objects, and traps. .lp "" +If there are visible clouds of gas in view, they are treated like traps +when deciding whether to show them or the floor underneath them. +.lp "" In explore mode, you can choose to view the full map rather than just its explored portion. In debug mode there are additional choices. @@ -4323,7 +4326,8 @@ symbols for the various object types. Any omitted types are filled in at the end from the previous order. .lp paranoid_confirmation A space separated list of specific situations where alternate -prompting is desired. The default is \(lqparanoid_confirmation:pray swim trap\(rq. +prompting is desired. +The default is \(lqparanoid_confirmation:pray swim trap\(rq. .PS Were-change .PL Confirm for any prompts which are set to require \(lqyes\(rq rather than \(oqy\(cq, @@ -4357,6 +4361,8 @@ than immediately praying; on by default; .PL trap require \(oqy\(cq to confirm an attempt to move into or onto a known trap, unless doing so is considered to be harmless; +when enabled, this confirmation is also used for moving into visible +gas cloud regions; (to require \(lqyes\(rq rather than just \(oqy\(cq, set Confirm too); confirmation can be skipped by using the \(oq\f(CRm\fP\(cq movement prefix; .PL swim @@ -4373,7 +4379,7 @@ commands even when wearing just one applicable item; .PL all turn on all of the above. .PE -By default, the pray and swim choices are enabled, the others disabled. +By default, the pray, swim, and trap choices are enabled, the others disabled. To disable them without setting any of the other choices, use \f(CRparanoid_confirmation:none\fP. To keep them enabled while setting any of the others, you can diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 5d66c9c1c..6524dd281 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -48,7 +48,7 @@ \author{Original version - Eric S. Raymond\\ (Edited and expanded for 3.7.0 by Mike Stephenson and others)} %DO NOT REMOVE NH_DATESUB \date{DATE(%B %-d, %Y)} -\date{July 29, 2024} +\date{August 11, 2024} \maketitle @@ -1804,6 +1804,9 @@ In normal play you can view the explored portion of the current level's map without monsters; without monsters and objects; or without monsters, objects, and traps.\\ %.lp "" +If there are visible clouds of gas in view, they are treated like traps +when deciding whether to show them or the floor underneath them.\\ +%.lp "" In explore mode, you can choose to view the full map rather than just its explored portion. In debug mode there are additional choices.\\ @@ -4752,6 +4755,8 @@ than immediately praying; on by default; \item[{\tt trap~~~}] require `{\tt y}' to confirm an attempt to move into or onto a known trap, unless doing so is considered to be harmless; +when enabled, this confirmation is also used for moving into visible +gas cloud regions; (to require ``yes'' rather than just `y', set Confirm too); confirmation can be skipped by using the `{\tt m}' movement prefix; \item[{\tt swim~~~}] @@ -4770,7 +4775,7 @@ turn on all of the above. \elist %.ei %.ed -By default, the pray and swim choices are enabled, the others disabled. +By default, the pray, swim, and trap choices are enabled, the others disabled. To disable them without setting any of the other choices, use ``{\it paranoid\verb+_+confirmation:none}''. To keep them enabled while setting any of the others, you can diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 372527e9c..88a089184 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1,4 +1,4 @@ -NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1457 $ $NHDT-Date: 1721684298 2024/07/22 21:38:18 $ +NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1460 $ $NHDT-Date: 1723410638 2024/08/11 21:10:38 $ General Fixes and Modified Features ----------------------------------- @@ -2546,6 +2546,8 @@ paranoid_confirm:swim to prevent accidental dunking into dangerous liquids; paranoid_confirm:trap to confirm entering a known trap unless it is harmless; like revised paranoid_confirm:pray, requires y/n response; add paranoid_confirm:Confirm to require yes/no instead +extend 'paranoid_confirm:trap' to request confirmation when entering visible + gas cloud regions paranoid_confirm:Autoall to confirm picking 'A' in menustyle:Full filter menu looking at a monster will indicate whether it is asleep, and waking up a monster yields a message diff --git a/include/extern.h b/include/extern.h index 27c308019..62e286f4a 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 extern.h $NHDT-Date: 1722116044 2024/07/27 21:34:04 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1433 $ */ +/* NetHack 3.7 extern.h $NHDT-Date: 1723410638 2024/08/11 21:10:38 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1434 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2574,6 +2574,8 @@ extern boolean in_out_region(coordxy, coordxy); extern boolean m_in_out_region(struct monst *, coordxy, coordxy) NONNULLARG1; extern void update_player_regions(void); extern void update_monster_region(struct monst *) NONNULLARG1; +extern int reg_damg(NhRegion *) NONNULLARG1; +extern boolean any_visible_region(void); extern NhRegion *visible_region_at(coordxy, coordxy); extern void show_region(NhRegion *, coordxy, coordxy) NONNULLARG1; extern void save_regions(NHFILE *) NONNULLARG1; diff --git a/src/hack.c b/src/hack.c index 8a47f5b69..f59e26eb7 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 hack.c $NHDT-Date: 1720128165 2024/07/04 21:22:45 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.449 $ */ +/* NetHack 3.7 hack.c $NHDT-Date: 1723410639 2024/08/11 21:10:39 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.452 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2517,11 +2517,12 @@ domove_core(void) { struct monst *mtmp; struct rm *tmpr; + NhRegion *newreg, *oldreg; coordxy x, y; struct trap *trap = NULL; int glyph; coordxy chainx = 0, chainy = 0, - ballx = 0, bally = 0; /* ball&chain new positions */ + ballx = 0, bally = 0; /* ball&chain new positions */ int bc_control = 0; /* control for ball&chain */ boolean cause_delay = FALSE, /* dragging ball will skip a move */ displaceu = FALSE; /* involuntary swap */ @@ -2624,10 +2625,14 @@ domove_core(void) return; /* maybe ask player for confirmation before walking into known traps */ - if (ParanoidTrap && (trap = t_at(x, y)) != 0 && trap->tseen + if (ParanoidTrap && !Stunned && !Confusion + /* skip if player used 'm' prefix or is moving recklessly */ && (!svc.context.nopick || svc.context.run) - && !Stunned && !Confusion + /* check for discovered trap */ + && (trap = t_at(x, y)) != 0 && trap->tseen + /* check whether attempted move will be viable */ && test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE) + /* override confirmation if the trap is harmless to the hero */ && (immune_to_trap(&gy.youmonst, trap->ttyp) != TRAP_CLEARLY_IMMUNE /* Hallucination: all traps still show as ^, but the hero can't tell what they are, so treat as dangerous */ @@ -2662,6 +2667,33 @@ domove_core(void) return; } } + /* treat entering a visible region like entering a trap */ + if (ParanoidTrap && !Blind && !Stunned && !Confusion && !Hallucination + /* skip if player used 'm' prefix or is moving recklessly */ + && (!svc.context.nopick || svc.context.run) + /* check for region(s) */ + && (newreg = visible_region_at(x, y)) != 0 + && ((oldreg = visible_region_at(u.ux, u.uy)) == 0 + /* if moving from one region into another, only ask for + confirmation if the one potentially being entered inflicts + damage (poison gas) and the one being exited doesn't (vapor) */ + || (reg_damg(newreg) > 0 && reg_damg(oldreg) == 0)) + /* check whether attempted move will be viable */ + && test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE) + /* we don't override confirmation for poison resistance since the + region also hinders hero's vision even if/when no damage is done */ + ) { + char qbuf[QBUFSZ]; + + Snprintf(qbuf, sizeof qbuf, "%s into that %s cloud?", + locomotion(gy.youmonst.data, "step"), + (reg_damg(newreg) > 0) ? "poison gas" : "vapor"); + if (!paranoid_query(ParanoidConfirm, upstart(qbuf))) { + nomul(0); + svc.context.move = 0; + return; + } + } if (u.utrap) { boolean moved = trapmove(x, y, trap); diff --git a/src/region.c b/src/region.c index 43383ea2f..cbabf4885 100644 --- a/src/region.c +++ b/src/region.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 region.c $NHDT-Date: 1707462965 2024/02/09 07:16:05 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.89 $ */ +/* NetHack 3.7 region.c $NHDT-Date: 1723410640 2024/08/11 21:10:40 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.97 $ */ /* Copyright (c) 1996 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -628,6 +628,29 @@ remove_mon_from_regions(struct monst *mon) #endif /*0*/ +/* per-turn damaeg inflicted by visible region; hides details from caller */ +int +reg_damg(NhRegion *reg) +{ + int damg = (!reg->visible || reg->ttl == -2L) ? 0 : reg->arg.a_int; + + return damg; +} + +/* check whether current level has any visible regions */ +boolean +any_visible_region(void) +{ + int i; + + for (i = 0; i < svn.n_regions; i++) { + if (!gr.regions[i]->visible || gr.regions[i]->ttl == -2L) + continue; + return TRUE; + } + return FALSE; +} + /* * Check if a spot is under a visible region (eg: gas cloud). * Returns NULL if not, otherwise returns region. @@ -666,8 +689,8 @@ save_regions(NHFILE *nhfp) goto skip_lots; if (nhfp->structlevel) { /* timestamp */ - bwrite(nhfp->fd, (genericptr_t) &svm.moves, sizeof (svm.moves)); - bwrite(nhfp->fd, (genericptr_t) &svn.n_regions, sizeof (svn.n_regions)); + bwrite(nhfp->fd, (genericptr_t) &svm.moves, sizeof svm.moves); + bwrite(nhfp->fd, (genericptr_t) &svn.n_regions, sizeof svn.n_regions); } for (i = 0; i < svn.n_regions; i++) { r = gr.regions[i]; @@ -747,11 +770,11 @@ rest_regions(NHFILE *nhfp) tmstamp = (svm.moves - tmstamp); if (nhfp->structlevel) - mread(nhfp->fd, (genericptr_t) &svn.n_regions, sizeof (svn.n_regions)); + mread(nhfp->fd, (genericptr_t) &svn.n_regions, sizeof svn.n_regions); gm.max_regions = svn.n_regions; if (svn.n_regions > 0) - gr.regions = (NhRegion **) alloc(sizeof (NhRegion *) * svn.n_regions); + gr.regions = (NhRegion **) alloc(svn.n_regions * sizeof (NhRegion *)); for (i = 0; i < svn.n_regions; i++) { r = gr.regions[i] = (NhRegion *) alloc(sizeof (NhRegion)); if (nhfp->structlevel) {