owornmask sanity_check fix and enhancement

Thinko fix:  sanity checking for owornmask was mis-treating
OBJ_MIGRATING as OBJ_MINVENT of migrating monsters rather than as
unattended objects and would have had problems similar to obfree's
inappropriate impossible check.

Sanity checking for objects worn in invalid slots (amulet worn in
a ring slot and so forth) is extended to items worn by monsters.
Also add a check for wielded coins since the loophole that let them
become wielded has been closed.
This commit is contained in:
PatR
2015-05-03 16:57:09 -07:00
parent 505f6246b5
commit 3fa8ff9d62

View File

@@ -1,4 +1,4 @@
/* NetHack 3.5 mkobj.c $NHDT-Date: 1430559882 2015/05/02 09:44:42 $ $NHDT-Branch: master $:$NHDT-Revision: 1.96 $ */
/* NetHack 3.5 mkobj.c $NHDT-Date: 1430697424 2015/05/03 23:57:04 $ $NHDT-Branch: master $:$NHDT-Revision: 1.97 $ */
/* NetHack 3.5 mkobj.c $Date: 2012/03/10 02:49:08 $ $Revision: 1.70 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2032,9 +2032,12 @@ const char *mesg;
switch (obj->where) {
case OBJ_INVENT:
case OBJ_MINVENT:
case OBJ_MIGRATING:
sanity_check_worn(obj);
break;
case OBJ_MIGRATING:
/* migrating objects overload the owornmask field
with a destination code; skip attempt to check it */
break;
case OBJ_FLOOR:
/* note: ball and chain can also be OBJ_FREE, but not across
turns so this sanity check shouldn't encounter that */
@@ -2180,6 +2183,7 @@ struct obj *obj;
/* [W_ART,W_ARTI are property bits for items which aren't worn] */
};
char maskbuf[60];
const char *what;
unsigned long owornmask, allmask = 0L;
int i, n = 0;
@@ -2212,8 +2216,7 @@ struct obj *obj;
insane_object(obj, ofmt0, maskbuf, (struct monst *)0);
}
if (n == 1 && (carried(obj) || (owornmask & (W_BALL|W_CHAIN)) != 0L)) {
const char *what = 0;
what = 0;
/* verify that obj in hero's invent (or ball/chain elsewhere)
with owornmask of W_foo is the object pointed to by ufoo */
switch (owornmask) {
@@ -2257,11 +2260,24 @@ struct obj *obj;
Sprintf(maskbuf, "worn mask 0x%08lx != %s", obj->owornmask, what);
insane_object(obj, ofmt0, maskbuf, (struct monst *)0);
}
}
if (n == 1 && (carried(obj) || (owornmask & (W_BALL|W_CHAIN)) != 0L
|| mcarried(obj))) {
/* check for items worn in invalid slots; practically anything can
be wielded/alt-wielded/quivered, so skip obj if it's one of those */
be wielded/alt-wielded/quivered, so tests on those are limited */
what = 0;
if (owornmask & W_ARMOR) {
if (obj->oclass != ARMOR_CLASS) what = "armor";
} else if (owornmask & (W_WEP|W_SWAPWEP|W_QUIVER)) {
/* monsters don't maintain alternate weapon or quiver */
if (mcarried(obj) && (owornmask & (W_SWAPWEP|W_QUIVER)) != 0L)
what = (owornmask & W_SWAPWEP) != 0L ? "monst alt weapon?"
: "monst quiver?";
/* hero can quiver gold but not wield it (hence not alt-wield
it either); also catches monster wielding gold */
else if (obj->oclass == COIN_CLASS
&& (owornmask & (W_WEP|W_SWAPWEP)) != 0L)
what = (owornmask & W_WEP) != 0L ? "weapon" : "alt weapon";
} else if (owornmask & W_AMUL) {
if (obj->oclass != AMULET_CLASS) what = "amulet";
} else if (owornmask & W_RING) {
@@ -2274,16 +2290,19 @@ struct obj *obj;
if (obj->oclass != BALL_CLASS) what = "chained ball";
} else if (owornmask & W_CHAIN) {
if (obj->oclass != CHAIN_CLASS) what = "chain";
} else if (owornmask & W_SADDLE) {
if (obj->otyp != SADDLE) what = "saddle";
}
if (what) {
char oclassname[30];
struct monst *mon = mcarried(obj) ? obj->ocarry : 0;
/* if we've found a potion worn in the amulet slot,
this yields "worn (potion amulet)" */
Strcpy(oclassname, def_oc_syms[(uchar)obj->oclass].name);
Sprintf(maskbuf, "worn (%s %s)",
makesingular(oclassname), what);
insane_object(obj, ofmt0, maskbuf, (struct monst *)0);
insane_object(obj, ofmt0, maskbuf, mon);
}
}
#else /* not (BETA || DEBUG) */