From: Pasi Kallinen Date: Sat, 12 Feb 2022 14:30:39 +0000 (+0200) Subject: Add paranoid:swim to prevent typoing into water or lava X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=03c715f17960efde6c121631bffa61cff25fddb6;p=nethack Add paranoid:swim to prevent typoing into water or lava In the name of accessibility: Prevent moving into dangerous liquids. Now with themed rooms, water and lava are more common, and it's unreasonable to expect blind players to check every step for those. With paranoid:swim, just prevent normal walking into those liquids, unless you prefix the movement with 'm', or if the liquid would not harm you. Doesn't completely prevent an accidental dunking - for example if the hero is impaired or couldn't see the liquid. This comes from xNetHack by copperwater with some changes to the code. --- diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 8ec66c3c3..dc6d2e0a0 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -4054,6 +4054,8 @@ than immediately praying; on by default; .PL Remove require selection from inventory for \(oqR\(cq and \(oqT\(cq commands even when wearing just one applicable item. +.PL swim +prevent walking into water or lava. .PL all turn on all of the above. .PE @@ -5508,6 +5510,8 @@ If this is the case, disable the .op number_pad option and use the traditional Rogue-like commands. +.lp paranoid_confirmation:swim +Prevent walking into water or lava. .lp autodescribe Automatically describe the terrain under the cursor when targeting. .lp mention_walls diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 05ef29167..e25cf1e81 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -4430,6 +4430,8 @@ than immediately praying; on by default; \item[{\tt Remove~}] require selection from inventory for `{\tt R}' and `{\tt T}' commands even when wearing just one applicable item. +\item[{\tt swim~~~}] +prevent walking into water or lava. \item[{\tt all~~~~}] turn on all of the above. \elist @@ -6054,6 +6056,9 @@ A lot of speech access programs use the number-pad to review the screen. If this is the case, disable the number\verb+_+pad option and use the traditional Rogue-like commands. %.lp +\item[\ib{paranoid\verb+_+confirmation:swim}] +Prevent walking into water or lava. +%.lp \item[\ib{autodescribe}] Automatically describe the terrain under the cursor when targeting. %.lp diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 52ca674d8..4e6bea5e0 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1410,6 +1410,7 @@ reading a blessed scroll of light has a chance to improve bless/curse state of wielded Sunsword or worn gold dragon scales/mail similar to dipping those into holy water; cursed scroll has chance to worsen the state added a chronicle of major events, and optional live logging of those +paranoid:swim to prevent accidental dunking into dangerous liquids Platform- and/or Interface-Specific New Features diff --git a/include/context.h b/include/context.h index c9a36fb19..fa7f79c39 100644 --- a/include/context.h +++ b/include/context.h @@ -150,6 +150,7 @@ struct context_info { boolean botlx; /* print an entirely new bottom line */ boolean door_opened; /* set to true if door was opened during test_move */ boolean enhance_tip; /* player is informed about #enhance */ + boolean swim_tip; /* player was informed about walking into water */ struct dig_info digging; struct victual_info victual; struct engrave_info engraving; diff --git a/include/flag.h b/include/flag.h index 553def53d..0636cd72d 100644 --- a/include/flag.h +++ b/include/flag.h @@ -78,6 +78,7 @@ struct flag { #define PARANOID_BREAKWAND 0x0080 #define PARANOID_WERECHANGE 0x0100 #define PARANOID_EATING 0x0200 +#define PARANOID_SWIM 0x0400 int pickup_burden; /* maximum burden before prompt */ int pile_limit; /* controls feedback when walking over objects */ char discosort; /* order of dodiscovery/doclassdisco output: o,s,c,a */ @@ -466,6 +467,8 @@ enum runmode_types { /* continue eating: prompt given _after_first_bite_ when eating something while satiated */ #define ParanoidEating ((flags.paranoia_bits & PARANOID_EATING) != 0) +/* Prevent going into lava or water without explicitly forcing it */ +#define ParanoidSwim ((flags.paranoia_bits & PARANOID_SWIM) != 0) /* command parsing, mainly dealing with number_pad handling; not saved and restored */ diff --git a/include/mondata.h b/include/mondata.h index e7b84721d..ba8760113 100644 --- a/include/mondata.h +++ b/include/mondata.h @@ -38,6 +38,7 @@ #define is_floater(ptr) ((ptr)->mlet == S_EYE || (ptr)->mlet == S_LIGHT) /* clinger: piercers, mimics, wumpus -- generally don't fall down holes */ #define is_clinger(ptr) (((ptr)->mflags1 & M1_CLING) != 0L) +#define grounded(ptr) (!is_flyer(ptr) && !is_floater(ptr) && !is_clinger(ptr)) #define is_swimmer(ptr) (((ptr)->mflags1 & M1_SWIM) != 0L) #define breathless(ptr) (((ptr)->mflags1 & M1_BREATHLESS) != 0L) #define amphibious(ptr) \ diff --git a/include/patchlevel.h b/include/patchlevel.h index 5cb1e8bc4..64ec9f08c 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -17,7 +17,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 49 +#define EDITLEVEL 50 /* * Development status possibilities. diff --git a/src/hack.c b/src/hack.c index ef61908bd..69d0011c1 100644 --- a/src/hack.c +++ b/src/hack.c @@ -13,6 +13,7 @@ static void dosinkfall(void); static boolean findtravelpath(int); static boolean trapmove(int, int, struct trap *); static void check_buried_zombies(xchar, xchar); +static boolean swim_move_danger(xchar x, xchar y); static void domove_core(void); static void maybe_smudge_engr(int, int, int, int); static struct monst *monstinroom(struct permonst *, int); @@ -1519,6 +1520,46 @@ check_buried_zombies(xchar x, xchar y) } } +/* Is it dangerous for hero to move to x,y due to water or lava? */ +static boolean +swim_move_danger(xchar x, xchar y) +{ + if (!Levitation && !Flying && grounded(g.youmonst.data) && !Stunned + && !Confusion && levl[x][y].seenv + && ((is_pool(x, y) && !is_pool(u.ux, u.uy)) + || (is_lava(x, y) && !is_lava(u.ux, u.uy)))) { + boolean known_wwalking, known_lwalking; + + known_wwalking = (uarmf && uarmf->otyp == WATER_WALKING_BOOTS + && objects[WATER_WALKING_BOOTS].oc_name_known + && !u.usteed); + known_lwalking = (known_wwalking && Fire_resistance && + uarmf->oerodeproof && uarmf->rknown); + /* FIXME: This can be exploited to identify the ring of fire resistance + * if the player is wearing it unidentified and has identified + * fireproof boots of water walking and is walking over lava. However, + * this is such a marginal case that it may not be worth fixing. */ + if ((is_pool(x, y) && !known_wwalking) + || (is_lava(x, y) && !known_lwalking)) { + if (g.context.nopick) { + /* moving with m-prefix */ + g.context.swim_tip = TRUE; + return FALSE; + } else if (ParanoidSwim) { + You("avoid stepping into the %s.", + waterbody_name(x, y)); + if (!g.context.swim_tip) { + pline("(Use '%s' prefix to step in if you really want to.)", + visctrl(cmd_from_func(do_reqmenu))); + g.context.swim_tip = TRUE; + } + return TRUE; + } + } + } + return FALSE; +} + void domove(void) { @@ -1946,6 +1987,13 @@ domove_core(void) return; } + /* Is it dangerous to swim in water or lava? */ + if (swim_move_danger(x, y)) { + g.context.move = 0; + nomul(0); + return; + } + /* Move ball and chain. */ if (Punished) if (!drag_ball(x, y, &bc_control, &ballx, &bally, &chainx, &chainy, diff --git a/src/options.c b/src/options.c index 6b73b64a1..ba4b5e8ad 100644 --- a/src/options.c +++ b/src/options.c @@ -154,6 +154,8 @@ static const struct paranoia_opts { "y to pray (supersedes old \"prayconfirm\" option)" }, { PARANOID_REMOVE, "Remove", 1, "Takeoff", 1, "always pick from inventory for Remove and Takeoff" }, + { PARANOID_SWIM, "swim", 1, 0, 0, + "avoid walking into lava or water" }, /* for config file parsing; interactive menu skips these */ { 0, "none", 4, 0, 0, 0 }, /* require full word match */ { ~0, "all", 3, 0, 0, 0 }, /* ditto */