fix #H9272 - "object lost" panic

when polymorph causes loss of levitation boots or water walking boots
while over water.  If discarding stuff while trying to crawl out got
rid of the taken-off boots, they wouldn't be in inventory any more
when break_armor() tried to drop them after taking them off.
This commit is contained in:
PatR
2019-10-04 16:12:08 -07:00
parent 8fa38ec8fb
commit f3bc5e5c78
2 changed files with 46 additions and 11 deletions

View File

@@ -1,4 +1,4 @@
$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.122 $ $NHDT-Date: 1570227405 2019/10/04 22:16:45 $
$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.123 $ $NHDT-Date: 1570230710 2019/10/04 23:11:50 $
This fixes36.3 file is here to capture information about updates in the 3.6.x
lineage following the release of 3.6.2 in May 2019. Please note, however,
@@ -168,6 +168,9 @@ ball and chain could end up too far from punished hero (triggering b&c warning
water failed because dropping stuff left hero overly encumbered and
hero was life saved--or player declined to die--if the hero got
teleported one step further from ball and chain's current location
avoid 'object lost' panic when polymorph causes loss of levitation boots or
water walking boots which dumps hero into water where emergency
disrobing/dropping in order to crawl out chooses to drop those boots
Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 polyself.c $NHDT-Date: 1559664952 2019/06/04 16:15:52 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.133 $ */
/* NetHack 3.6 polyself.c $NHDT-Date: 1570230710 2019/10/04 23:11:50 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.134 $ */
/* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */
@@ -23,6 +23,7 @@
STATIC_DCL void FDECL(check_strangling, (BOOLEAN_P));
STATIC_DCL void FDECL(polyman, (const char *, const char *));
STATIC_DCL void FDECL(dropp, (struct obj *));
STATIC_DCL void NDECL(break_armor);
STATIC_DCL void FDECL(drop_weapon, (int));
STATIC_DCL int FDECL(armor_to_dragon, (int));
@@ -858,6 +859,33 @@ int mntmp;
return 1;
}
/* dropx() jacket for break_armor() */
STATIC_OVL void
dropp(obj)
struct obj *obj;
{
struct obj *otmp;
/*
* Dropping worn armor while polymorphing might put hero into water
* (loss of levitation boots or water walking boots that the new
* form can't wear), where emergency_disrobe() could remove it from
* inventory. Without this, dropx() could trigger an 'object lost'
* panic. Right now, boots are the only armor which might encounter
* this situation, but handle it for all armor.
*
* Hypothetically, 'obj' could have merged with something (not
* applicable for armor) and no longer be a valid pointer, so scan
* inventory for it instead of trusting obj->where.
*/
for (otmp = invent; otmp; otmp = otmp->nobj) {
if (otmp == obj) {
dropx(obj);
break;
}
}
}
STATIC_OVL void
break_armor()
{
@@ -876,7 +904,7 @@ break_armor()
if (otmp->oartifact) {
Your("%s falls off!", cloak_simple_name(otmp));
(void) Cloak_off();
dropx(otmp);
dropp(otmp);
} else {
Your("%s tears apart!", cloak_simple_name(otmp));
(void) Cloak_off();
@@ -893,7 +921,7 @@ break_armor()
cancel_don();
Your("armor falls around you!");
(void) Armor_gone();
dropx(otmp);
dropp(otmp);
}
if ((otmp = uarmc) != 0) {
if (is_whirly(youmonst.data))
@@ -901,7 +929,7 @@ break_armor()
else
You("shrink out of your %s!", cloak_simple_name(otmp));
(void) Cloak_off();
dropx(otmp);
dropp(otmp);
}
if ((otmp = uarmu) != 0) {
if (is_whirly(youmonst.data))
@@ -909,7 +937,7 @@ break_armor()
else
You("become much too small for your shirt!");
setworn((struct obj *) 0, otmp->owornmask & W_ARMU);
dropx(otmp);
dropp(otmp);
}
}
if (has_horns(youmonst.data)) {
@@ -927,7 +955,7 @@ break_armor()
Your("%s falls to the %s!", helm_simple_name(otmp),
surface(u.ux, u.uy));
(void) Helmet_off();
dropx(otmp);
dropp(otmp);
}
}
}
@@ -939,12 +967,12 @@ break_armor()
You("drop your gloves%s!", uwep ? " and weapon" : "");
drop_weapon(0);
(void) Gloves_off();
dropx(otmp);
dropp(otmp);
}
if ((otmp = uarms) != 0) {
You("can no longer hold your shield!");
(void) Shield_off();
dropx(otmp);
dropp(otmp);
}
if ((otmp = uarmh) != 0) {
if (donning(otmp))
@@ -952,7 +980,7 @@ break_armor()
Your("%s falls to the %s!", helm_simple_name(otmp),
surface(u.ux, u.uy));
(void) Helmet_off();
dropx(otmp);
dropp(otmp);
}
}
if (nohands(youmonst.data) || verysmall(youmonst.data)
@@ -966,7 +994,7 @@ break_armor()
Your("boots %s off your feet!",
verysmall(youmonst.data) ? "slide" : "are pushed");
(void) Boots_off();
dropx(otmp);
dropp(otmp);
}
}
}
@@ -1019,6 +1047,10 @@ int alone;
updateinv = FALSE;
else if (candropwep)
dropx(otmp);
/* [note: dropp vs dropx -- if heart of ahriman is wielded, we
might be losing levitation by dropping it; but that won't
happen until the drop, unlike Boots_off() dumping hero into
water and triggering emergency_disrobe() before dropx()] */
if (updateinv)
update_inventory();