fix github issue #354 - stealarm() impossible

A thieving monster could be killed while the hero was busy taking
off armor which needs multiple turns (normally a suit) and if that
happened on the same turn as the take-off finished, the warning
"stealarm(): dead monster stealing" was issued.  Cited case was
having the thief be killed by a stinking cloud but it could happen
if the death was caused by a pet or by some other monster trying
to attack the hero.  If the thief died sooner, the situation was
silently ignored.  So this could have been fixed by just getting
rid of the impossible() feedback.

'stealmid' and 'stealoid' should have been static in steal.c rather
than global and as such should have been moved into 'struct g'.
This moves them there and then takes advantage of having access to
'stealmid' outside of steal.c.  That's just a minor optimization
since m_detach() could call new thiefdead() unconditionally and the
latter could check whether the dead monster matches 'stealmid'.

Fixes #354
This commit is contained in:
PatR
2020-06-01 06:17:07 -07:00
parent ac364b3e20
commit 503df6823d
7 changed files with 80 additions and 47 deletions

View File

@@ -1,4 +1,4 @@
$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.227 $ $NHDT-Date: 1590879610 2020/05/30 23:00:10 $
$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.228 $ $NHDT-Date: 1591017415 2020/06/01 13:16:55 $
General Fixes and Modified Features
-----------------------------------
@@ -190,6 +190,8 @@ when hold_another_object fails while hero is swallowed, drop the item into
change mkclass() to usually honor (always honor for L class) the hell-only and
never-in-hell monster creation flags; no more achi-lich in the Castle
(nor master lich there unless demilich gets a potion of gain level)
thieving monster could be killed while hero was removing armor, triggering
warning "stealarm(): dead monster stealing" when taking-off finished
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 decl.h $NHDT-Date: 1589326665 2020/05/12 23:37:45 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.236 $ */
/* NetHack 3.6 decl.h $NHDT-Date: 1591017415 2020/06/01 13:16:55 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.237 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2007. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1142,6 +1142,10 @@ struct instance_globals {
int spl_sortmode; /* index into spl_sortchoices[] */
int *spl_orderindx; /* array of g.spl_book[] indices */
/* steal.c */
unsigned int stealoid; /* object to be stolen */
unsigned int stealmid; /* monster doing the stealing */
/* teleport.c */
struct obj *telescroll; /* non-null when teleporting via this scroll */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1590904081 2020/05/31 05:48:01 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.847 $ */
/* NetHack 3.6 extern.h $NHDT-Date: 1591017416 2020/06/01 13:16:56 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.848 $ */
/* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2536,9 +2536,11 @@ E void FDECL(initialspell, (struct obj *));
#ifdef USE_TRAMPOLI
E int NDECL(stealarm);
E void NDECL(unstolenarm);
#endif
E long FDECL(somegold, (long));
E void FDECL(stealgold, (struct monst *));
E void NDECL(thiefdead);
E void FDECL(remove_worn_item, (struct obj *, BOOLEAN_P));
E int FDECL(steal, (struct monst *, char *));
E int FDECL(mpickobj, (struct monst *, struct obj *));

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 decl.c $NHDT-Date: 1589326673 2020/05/12 23:37:53 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.212 $ */
/* NetHack 3.6 decl.c $NHDT-Date: 1591017417 2020/06/01 13:16:57 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.213 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2009. */
/* NetHack may be freely redistributed. See license for details. */
@@ -647,6 +647,10 @@ const struct instance_globals g_init = {
0, /* spl_sortmode */
NULL, /* spl_orderindx */
/* steal.c */
0, /* stealoid */
0, /* stealmid */
/* teleport.c */
NULL, /* telescroll */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 mon.c $NHDT-Date: 1586091449 2020/04/05 12:57:29 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.333 $ */
/* NetHack 3.6 mon.c $NHDT-Date: 1591017419 2020/06/01 13:16:59 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.337 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1977,6 +1977,8 @@ struct permonst *mptr; /* reflects mtmp->data _prior_ to mtmp's death */
/* to prevent an infinite relobj-flooreffects-hmon-killed loop */
mtmp->mtrapped = 0;
mtmp->mhp = 0; /* simplify some tests: force mhp to 0 */
if (mtmp->m_id == g.stealmid)
thiefdead();
relobj(mtmp, 0, FALSE);
if (onmap || mtmp == g.level.monsters[0][0]) {
if (mtmp->wormno)

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 steal.c $NHDT-Date: 1570566382 2019/10/08 20:26:22 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.75 $ */
/* NetHack 3.6 steal.c $NHDT-Date: 1591017420 2020/06/01 13:17:00 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.82 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -6,26 +6,20 @@
#include "hack.h"
static int NDECL(stealarm);
static int NDECL(unstolenarm);
static const char *FDECL(equipname, (struct obj *));
static const char *
equipname(otmp)
register struct obj *otmp;
{
return ((otmp == uarmu)
? "shirt"
: (otmp == uarmf)
? "boots"
: (otmp == uarms)
? "shield"
: (otmp == uarmg)
? "gloves"
: (otmp == uarmc)
? cloak_simple_name(otmp)
: (otmp == uarmh)
? helm_simple_name(otmp)
: suit_simple_name(otmp));
return ((otmp == uarmu) ? shirt_simple_name(otmp)
: (otmp == uarmf) ? boots_simple_name(otmp)
: (otmp == uarms) ? shield_simple_name(otmp)
: (otmp == uarmg) ? gloves_simple_name(otmp)
: (otmp == uarmc) ? cloak_simple_name(otmp)
: (otmp == uarmh) ? helm_simple_name(otmp)
: suit_simple_name(otmp));
}
/* proportional subset of gold; return value actually fits in an int */
@@ -139,9 +133,35 @@ register struct monst *mtmp;
}
}
/* steal armor after you finish taking it off */
unsigned int stealoid; /* object to be stolen */
unsigned int stealmid; /* monster doing the stealing */
/* monster who was stealing from hero has just died */
void
thiefdead()
{
/* hero is busy taking off an item of armor which takes multiple turns */
g.stealmid = 0;
if (g.afternmv == stealarm)
g.afternmv = unstolenarm;
}
/* called via (*g.afternmv)() when hero finishes taking off armor that
was slated to be stolen but the thief died in the interim */
static int
unstolenarm(VOID_ARGS)
{
struct obj *obj;
/* find the object before clearing stealoid; it has already become
not-worn and is still in hero's inventory */
for (obj = g.invent; obj; obj = obj->nobj)
if (obj->o_id == g.stealoid)
break;
g.stealoid = 0;
if (obj) {
g.nomovemsg = (char *) 0;
You("finish taking off your %s.", equipname(obj));
}
return 0;
}
static int
stealarm(VOID_ARGS)
@@ -149,10 +169,13 @@ stealarm(VOID_ARGS)
register struct monst *mtmp;
register struct obj *otmp;
if (!g.stealoid || !g.stealmid)
goto botm;
for (otmp = g.invent; otmp; otmp = otmp->nobj) {
if (otmp->o_id == stealoid) {
if (otmp->o_id == g.stealoid) {
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (mtmp->m_id == stealmid) {
if (mtmp->m_id == g.stealmid) {
if (DEADMONSTER(mtmp))
impossible("stealarm(): dead monster stealing");
if (!dmgtype(mtmp->data, AD_SITM)) /* polymorphed */
@@ -174,7 +197,7 @@ stealarm(VOID_ARGS)
}
}
botm:
stealoid = 0;
g.stealoid = g.stealmid = 0; /* in case only one has been reset so far */
return 0;
}
@@ -236,10 +259,10 @@ boolean unchain_ball; /* whether to unpunish or just unwield */
}
}
/* Returns 1 when something was stolen (or at least, when N should flee now)
* Returns -1 if the monster died in the attempt
* Avoid stealing the object stealoid
* Nymphs and monkeys won't steal coins
/* Returns 1 when something was stolen (or at least, when N should flee now),
* returns -1 if the monster died in the attempt.
* Avoid stealing the object 'stealoid'.
* Nymphs and monkeys won't steal coins.
*/
int
steal(mtmp, objnambuf)
@@ -326,7 +349,7 @@ char *objnambuf;
otmp = uarm;
gotobj:
if (otmp->o_id == stealoid)
if (otmp->o_id == g.stealoid)
return 0;
if (otmp->otyp == BOULDER && !throws_rocks(mtmp->data)) {
@@ -434,12 +457,8 @@ char *objnambuf;
remove_worn_item(otmp, TRUE);
otmp->cursed = curssv;
if (g.multi < 0) {
/*
multi = 0;
afternmv = 0;
*/
stealoid = otmp->o_id;
stealmid = mtmp->m_id;
g.stealoid = otmp->o_id;
g.stealmid = mtmp->m_id;
g.afternmv = stealarm;
return 0;
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 uhitm.c $NHDT-Date: 1586807928 2020/04/13 19:58:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.230 $ */
/* NetHack 3.6 uhitm.c $NHDT-Date: 1591017421 2020/06/01 13:17:01 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.236 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1522,7 +1522,7 @@ steal_it(mdef, mattk)
struct monst *mdef;
struct attack *mattk;
{
struct obj *otmp, *gold = 0, *stealoid, **minvent_ptr;
struct obj *otmp, *gold = 0, *ustealo, **minvent_ptr;
long unwornmask;
otmp = mdef->minvent;
@@ -1530,25 +1530,25 @@ struct attack *mattk;
return; /* nothing to take */
/* look for worn body armor */
stealoid = (struct obj *) 0;
ustealo = (struct obj *) 0;
if (could_seduce(&g.youmonst, mdef, mattk)) {
/* find armor, and move it to end of inventory in the process */
minvent_ptr = &mdef->minvent;
while ((otmp = *minvent_ptr) != 0)
if (otmp->owornmask & W_ARM) {
if (stealoid)
if (ustealo)
panic("steal_it: multiple worn suits");
*minvent_ptr = otmp->nobj; /* take armor out of minvent */
stealoid = otmp;
stealoid->nobj = (struct obj *) 0;
ustealo = otmp;
ustealo->nobj = (struct obj *) 0;
} else {
minvent_ptr = &otmp->nobj;
}
*minvent_ptr = stealoid; /* put armor back into minvent */
*minvent_ptr = ustealo; /* put armor back into minvent */
}
gold = findgold(mdef->minvent);
if (stealoid) { /* we will be taking everything */
if (ustealo) { /* we will be taking everything */
char heshe[20];
/* 3.7: this uses hero's base gender rather than nymph feminimity
@@ -1590,7 +1590,7 @@ struct attack *mattk;
move instead of waiting until it picks something up */
mdef->misc_worn_check |= I_SPECIAL;
if (otmp == stealoid) /* special message for final item */
if (otmp == ustealo) /* special message for final item */
pline("%s finishes taking off %s suit.", Monnam(mdef),
mhis(mdef));
}
@@ -1611,7 +1611,7 @@ struct attack *mattk;
break; /* can't continue stealing */
}
if (!stealoid)
if (!ustealo)
break; /* only taking one item */
/* take gold out of minvent before making next selection; if it