From 2646688e2db64f0d8257bae53aa064395c43941f Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 15 May 2023 01:08:04 -0700 Subject: [PATCH] back_on_ground() Replace a couple of hardcoded "back on solid ground" messages with something more versatile. Also, make life-saving handling for failed rescue from drowning similar to that of failed rescue immolation by lava. If there are any cases where more than two tries is needed, they elude me. The new code doesn't confer temporary water walking if emergency teleport fails; perhaps it should. --- include/extern.h | 3 +- src/pray.c | 5 +-- src/trap.c | 88 +++++++++++++++++++++++++++++++----------------- 3 files changed, 63 insertions(+), 33 deletions(-) diff --git a/include/extern.h b/include/extern.h index e7c009385..caaaeb0c2 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 extern.h $NHDT-Date: 1674294830 2023/01/21 09:53:50 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1223 $ */ +/* NetHack 3.7 extern.h $NHDT-Date: 1684138080 2023/05/15 08:08:00 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1263 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2911,6 +2911,7 @@ extern void acid_damage(struct obj *); extern int water_damage(struct obj *, const char *, boolean); extern void water_damage_chain(struct obj *, boolean); extern boolean rnd_nextto_goodpos(coordxy *, coordxy *, struct monst *); +extern void back_on_ground(int); extern boolean drown(void); extern void drain_en(int, boolean); extern int dountrap(void); diff --git a/src/pray.c b/src/pray.c index e231716ce..b8231a300 100644 --- a/src/pray.c +++ b/src/pray.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 pray.c $NHDT-Date: 1683832328 2023/05/11 19:12:08 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.193 $ */ +/* NetHack 3.7 pray.c $NHDT-Date: 1684138081 2023/05/15 08:08:01 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.194 $ */ /* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -383,10 +383,11 @@ fix_worst_trouble(int trouble) gc.context.botl = 1; break; case TROUBLE_LAVA: - You("are back on solid ground."); /* teleport should always succeed, but if not, just untrap them */ if (!safe_teleds(TELEDS_NO_FLAGS)) reset_utrap(TRUE); + back_on_ground(DISSOLVED); /* DISSOLVED: pending cause of death + * if trouble didn't get cured */ break; case TROUBLE_STARVING: /* temporarily lost strength recovery now handled by init_uhunger() */ diff --git a/src/trap.c b/src/trap.c index 7d0ccee36..fddeddf4f 100644 --- a/src/trap.c +++ b/src/trap.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 trap.c $NHDT-Date: 1683333758 2023/05/06 00:42:38 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.531 $ */ +/* NetHack 3.7 trap.c $NHDT-Date: 1684138083 2023/05/15 08:08:03 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.535 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -4495,7 +4495,53 @@ rnd_nextto_goodpos(coordxy *x, coordxy *y, struct monst *mtmp) return FALSE; } -/* return TRUE iff player relocated */ +/* life-saving or divine rescue has attempted to get the hero out of hostile + terrain and put hero in an unexpected spot or failed due to overfull level + and just prevented death so "back on solid ground" may be inappropriate */ +void +back_on_ground(int how) +{ + static const char find_yourself[] = "find yourself"; + struct rm *lev = &levl[u.ux][u.uy]; + boolean mesggiven = FALSE; + + switch (how) { + case DROWNING: + if (is_pool(u.ux, u.uy)) { + You("%s %s of %s.", find_yourself, + (Is_waterlevel(&u.uz) || IS_WATERWALL(lev->typ)) + ? "in the midst" : "on top", + hliquid("water")); + mesggiven = TRUE; + } else if (IS_AIR(lev->typ)) { + You("%s in %s.", find_yourself, + Is_waterlevel(&u.uz) ? "an air bubble" : "mid air"); + mesggiven = TRUE; + } + break; + case BURNING: /* moved onto lava without fire resistance */ + case DISSOLVED: /* sunk into lava while fire resistant */ + if (is_pool(u.ux, u.uy)) { + You("%s %s %s.", find_yourself, + u.uinwater ? "in" : "on", hliquid("water")); + mesggiven = TRUE; + } else if (is_lava(u.ux, u.uy)) { + You("%s on top of %s.", find_yourself, hliquid("molten lava")); + mesggiven = TRUE; + } + break; + default: + break; + } + if (!mesggiven) + You("%s back on solid %s.", find_yourself, surface(u.ux, u.uy)); + + iflags.last_msg = PLNMSG_BACK_ON_GROUND; /* for describe_decor() */ + /* feedback just disclosed this */ + iflags.prev_decor = gl.lastseentyp[u.ux][u.uy] = lev->typ; +} + +/* return TRUE iff player relocated */ boolean drown(void) { @@ -4526,9 +4572,9 @@ drown(void) water_damage_chain(gi.invent, FALSE); - if (u.umonnum == PM_GREMLIN && rn2(3)) + if (u.umonnum == PM_GREMLIN && rn2(3)) { (void) split_mon(&gy.youmonst, (struct monst *) 0); - else if (u.umonnum == PM_IRON_GOLEM) { + } else if (u.umonnum == PM_IRON_GOLEM) { You("rust!"); i = Maybe_Half_Phys(d(2, 6)); if (u.mhmax > i) @@ -4610,7 +4656,10 @@ drown(void) } set_uinwater(1); /* u.uinwater = 1 */ urgent_pline("You drown."); - for (i = 0; i < 5; i++) { /* arbitrary number of loops */ + /* first pass is survivable by using up an amulet of life-saving or by + answering no to "Die?" in explore|wizard mode; second pass can only + be survivable via the latter */ + for (i = 0; i < 2; i++) { /* killer format and name are reconstructed every iteration because lifesaving resets them */ pool_of_water = waterbody_name(u.ux, u.uy); @@ -4626,11 +4675,10 @@ drown(void) /* nowhere safe to land; repeat drowning loop... */ pline("You're still drowning."); } - if (u.uinwater) { + + if (u.uinwater) set_uinwater(0); /* u.uinwater = 0 */ - You("find yourself back %s.", - Is_waterlevel(&u.uz) ? "in an air bubble" : "on land"); - } + back_on_ground(DROWNING); return TRUE; } @@ -6255,28 +6303,8 @@ lava_effects(void) set_itimeout(&HWwalking, 5L); goto burn_stuff; } + back_on_ground(BURNING); - /* - * 3.7: this used to be unconditional "back on solid " - * but surface() could return a lot of things where that ends up - * sounding silly. Deal with water, ignore furniture; assume - * surface types 'air' and 'cloud' won't be present on same level - * as lava so don't need to be catered for. - * - * Made it out of the lava. We know that hero isn't levitating - * or flying but life-saving plus fireproof water walking boots - * (and no fire resistance) could put hero on water rather than - * "on solid ground"; likewise if poly'd into an aquatic form. - */ - if (is_pool(u.ux, u.uy)) - You("find yourself %s %s.", u.uinwater ? "in" : "on", - hliquid("water")); - else - You("find yourself back on solid %s.", surface(u.ux, u.uy)); - iflags.last_msg = PLNMSG_BACK_ON_GROUND; /* for describe_decor(); - * use for on-water too */ - /* surface() just disclosed this */ - iflags.prev_decor = gl.lastseentyp[u.ux][u.uy] = levl[u.ux][u.uy].typ; /* normally done via safe_teleds() -> teleds() -> spoteffects() but spoteffects() was no-op when called with nonzero in_lava_effects */ spoteffects(FALSE); /* suppress auto-pickup for this landing... */