more owornmask sanity_check
Fix the problem with erroneously detecting wielded or quivered chained ball which legitimately has more than one mask bit set. Add an additional check for valid wornmask of an item somehow worn in an invalid slot (such as an amulet in one of the ring slots). Only lightly tested; it really needs debugger assistance to force various invalid situations but I don't know gdb well enough for that.
This commit is contained in:
58
src/mkobj.c
58
src/mkobj.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.5 mkobj.c $NHDT-Date: 1430472720 2015/05/01 09:32:00 $ $NHDT-Branch: master $:$NHDT-Revision: 1.95 $ */
|
||||
/* 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 $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. */
|
||||
@@ -2180,32 +2180,44 @@ struct obj *obj;
|
||||
/* [W_ART,W_ARTI are property bits for items which aren't worn] */
|
||||
};
|
||||
char maskbuf[60];
|
||||
unsigned long allmask = 0L;
|
||||
unsigned long owornmask, allmask = 0L;
|
||||
int i, n = 0;
|
||||
|
||||
/* use owornmask for testing and bit twiddling, but use original
|
||||
obj->owornmask for printing */
|
||||
owornmask = obj->owornmask;
|
||||
/* figure out how many bits are set, and also which are viable */
|
||||
for (i = 0; wearbits[i]; ++i) {
|
||||
if ((owornmask & wearbits[i]) != 0L) ++n;
|
||||
allmask |= wearbits[i];
|
||||
if ((obj->owornmask & wearbits[i]) != 0L) ++n;
|
||||
}
|
||||
if (n == 2 && carried(obj) && obj == uball && (owornmask & W_BALL) != 0L
|
||||
&& (owornmask & (W_WEP|W_SWAPWEP|W_QUIVER)) != 0L) {
|
||||
/* chained ball can be wielded/alt-wielded/quivered; if so,
|
||||
pretend it's not chained in order to check the weapon pointer
|
||||
(we've already verified the ball pointer by successfully passing
|
||||
the if-condition to get here...) */
|
||||
owornmask &= ~W_BALL;
|
||||
n = 1;
|
||||
}
|
||||
if (n > 1) {
|
||||
/* multiple bits set */
|
||||
Sprintf(maskbuf, "worn mask (multiple) 0x%08lx", obj->owornmask);
|
||||
insane_object(obj, ofmt0, maskbuf, (struct monst *)0);
|
||||
}
|
||||
if ((obj->owornmask & ~allmask) != 0L
|
||||
|| (carried(obj) && (obj->owornmask & W_SADDLE) != 0L)) {
|
||||
if ((owornmask & ~allmask) != 0L
|
||||
|| (carried(obj) && (owornmask & W_SADDLE) != 0L)) {
|
||||
/* non-wearable bit(s) set */
|
||||
Sprintf(maskbuf, "worn mask (bogus)) 0x%08lx", obj->owornmask);
|
||||
insane_object(obj, ofmt0, maskbuf, (struct monst *)0);
|
||||
}
|
||||
if (n == 1 && (carried(obj)
|
||||
|| (obj->owornmask & (W_BALL|W_CHAIN)) != 0L)) {
|
||||
if (n == 1 && (carried(obj) || (owornmask & (W_BALL|W_CHAIN)) != 0L)) {
|
||||
const char *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 (obj->owornmask) {
|
||||
case W_ARM: if (obj != uarm) what = "armor"; /* suit */
|
||||
switch (owornmask) {
|
||||
case W_ARM: if (obj != uarm) what = "suit";
|
||||
break;
|
||||
case W_ARMC: if (obj != uarmc) what = "cloak";
|
||||
break;
|
||||
@@ -2245,6 +2257,34 @@ struct obj *obj;
|
||||
Sprintf(maskbuf, "worn mask 0x%08lx != %s", obj->owornmask, what);
|
||||
insane_object(obj, ofmt0, maskbuf, (struct monst *)0);
|
||||
}
|
||||
/* check for items worn in invalid slots; practically anything can
|
||||
be wielded/alt-wielded/quivered, so skip obj if it's one of those */
|
||||
what = 0;
|
||||
if (owornmask & W_ARMOR) {
|
||||
if (obj->oclass != ARMOR_CLASS) what = "armor";
|
||||
} else if (owornmask & W_AMUL) {
|
||||
if (obj->oclass != AMULET_CLASS) what = "amulet";
|
||||
} else if (owornmask & W_RING) {
|
||||
if (obj->oclass != RING_CLASS && obj->otyp != MEAT_RING)
|
||||
what = "ring";
|
||||
} else if (owornmask & W_TOOL) {
|
||||
if (obj->otyp != BLINDFOLD && obj->otyp != TOWEL
|
||||
&& obj->otyp != LENSES) what = "blindfold";
|
||||
} else if (owornmask & W_BALL) {
|
||||
if (obj->oclass != BALL_CLASS) what = "chained ball";
|
||||
} else if (owornmask & W_CHAIN) {
|
||||
if (obj->oclass != CHAIN_CLASS) what = "chain";
|
||||
}
|
||||
if (what) {
|
||||
char oclassname[30];
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
#else /* not (BETA || DEBUG) */
|
||||
/* dummy use of obj to avoid "arg not used" complaint */
|
||||
|
||||
Reference in New Issue
Block a user