fix bullwhip-induced panic

While testing some corpse/statue name manipulation changes I managed
to trigger a panic during end-of-game cleanup.  Using a bullwhip to
snatch a wielded cockatrice corpse from a monster's inventory into
the hero's inventory and being turned to stone due to lack of gloves
took the corpse out of the monster's inventory but didn't place it
anywhere.  If no life-saving took place, it led to an "obj_is_local"
panic during timer cleanup when freeing the level.

This patch includes some of the stuff I've been testing rather than
just the fix for the panic (which is the very last bit of the diff).
This commit is contained in:
PatR
2021-06-15 18:42:30 -07:00
parent 7088f6a846
commit f6e60c7516
2 changed files with 28 additions and 17 deletions

View File

@@ -1,4 +1,4 @@
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.568 $ $NHDT-Date: 1623282330 2021/06/09 23:45:30 $
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.571 $ $NHDT-Date: 1623807747 2021/06/16 01:42:27 $
General Fixes and Modified Features
-----------------------------------
@@ -542,6 +542,9 @@ change attendant (healer quest) monster from lawful to neutral
quit is not longer bound to M-q
change default value of autopickup to off and color to on
resurrected corpse of mon could end up with different gender from original mon
using a bullwhip to snatch a wielded cockatrice corpse from a monster when not
wearing gloves and without life-saving could trigger "obj_is_local"
panic during final cleanup
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 apply.c $NHDT-Date: 1621387861 2021/05/19 01:31:01 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.344 $ */
/* NetHack 3.7 apply.c $NHDT-Date: 1623807747 2021/06/16 01:42:27 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.345 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -271,7 +271,7 @@ its_dead(int rx, int ry, int *resp)
humanoid(mptr) ? "person" : "creature");
what = buf;
} else {
what = pmname(mptr, NEUTRAL);
what = obj_pmname(statue);
if (!type_is_pname(mptr))
what = The(what);
}
@@ -1920,6 +1920,7 @@ static void
use_tinning_kit(struct obj *obj)
{
struct obj *corpse, *can;
struct permonst *mptr;
/* This takes only 1 move. If this is to be changed to take many
* moves, we've got to deal with decaying corpses...
@@ -1934,29 +1935,28 @@ use_tinning_kit(struct obj *obj)
You("cannot tin %s which is partly eaten.", something);
return;
}
if (touch_petrifies(&mons[corpse->corpsenm]) && !Stone_resistance
&& !uarmg) {
mptr = &mons[corpse->corpsenm];
if (touch_petrifies(mptr) && !Stone_resistance && !uarmg) {
char kbuf[BUFSZ];
const char *corpse_name = an(cxname(corpse));
if (poly_when_stoned(g.youmonst.data))
You("tin %s without wearing gloves.",
an(mons[corpse->corpsenm].pmnames[NEUTRAL]));
else {
if (poly_when_stoned(g.youmonst.data)) {
You("tin %s without wearing gloves.", corpse_name);
} else {
pline("Tinning %s without wearing gloves is a fatal mistake...",
an(mons[corpse->corpsenm].pmnames[NEUTRAL]));
Sprintf(kbuf, "trying to tin %s without gloves",
an(mons[corpse->corpsenm].pmnames[NEUTRAL]));
corpse_name);
Sprintf(kbuf, "trying to tin %s without gloves", corpse_name);
}
instapetrify(kbuf);
}
if (is_rider(&mons[corpse->corpsenm])) {
if (is_rider(mptr)) {
if (revive_corpse(corpse))
verbalize("Yes... But War does not preserve its enemies...");
else
pline_The("corpse evades your grasp.");
return;
}
if (mons[corpse->corpsenm].cnutrit == 0) {
if (mptr->cnutrit == 0) {
pline("That's too insubstantial to tin.");
return;
}
@@ -2141,7 +2141,7 @@ fig_transform(anything *arg, long timeout)
char monnambuf[BUFSZ], carriedby[BUFSZ];
if (!figurine) {
debugpline0("null figurine in fig_transform()");
impossible("null figurine in fig_transform()");
return;
}
silent = (timeout != g.monstermoves); /* happened while away */
@@ -2908,10 +2908,18 @@ use_whip(struct obj *obj)
&& polymon(PM_STONE_GOLEM))) {
char kbuf[BUFSZ];
Sprintf(kbuf, "%s corpse",
an(mons[otmp->corpsenm].pmnames[NEUTRAL]));
Strcpy(kbuf, (otmp->quan == 1L) ? an(onambuf)
: onambuf);
pline("Snatching %s is a fatal mistake.", kbuf);
/* corpse probably has a rot timer but is now
OBJ_FREE; end of game cleanup will panic if
it isn't part of current level; plus it would
be missing from bones, so put it on the floor */
place_object(otmp, u.ux, u.uy); /* but don't stack */
instapetrify(kbuf);
/* life-saved; free the corpse again */
obj_extract_self(otmp);
}
(void) hold_another_object(otmp, "You drop %s!",
doname(otmp), (const char *) 0);