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:
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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 *));
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
83
src/steal.c
83
src/steal.c
@@ -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;
|
||||
}
|
||||
|
||||
20
src/uhitm.c
20
src/uhitm.c
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user