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.
This commit is contained in:
PatR
2023-05-15 01:08:04 -07:00
parent b4f3a0fac2
commit 2646688e2d
3 changed files with 63 additions and 33 deletions

View File

@@ -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);

View File

@@ -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() */

View File

@@ -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 <surface>"
* 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... */