extended object sanity checking

When sanity checking is enabled, check objects for bits used as
temporary flags that should always be cleared by the time that a
sanity check pass gets made:  o.in_use, o.bypass, and o.nomerge.

Also, fix glob checking.  It was unintentionally placed within
the braces of ``if (obj->owornmask) { ... }'' so didn't actually
check globs except for the unlikely case when wielded in one of
the uwep/uswapwep/uquiver slots.
This commit is contained in:
PatR
2021-08-18 17:17:14 -07:00
parent aaf78cea4e
commit f74121d1ce
+31 -17
View File
@@ -1,4 +1,4 @@
/* NetHack 3.7 mkobj.c $NHDT-Date: 1620923920 2021/05/13 16:38:40 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.200 $ */ /* NetHack 3.7 mkobj.c $NHDT-Date: 1629332223 2021/08/19 00:17:03 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.204 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */ /*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -12,6 +12,7 @@ static void container_weight(struct obj *);
static struct obj *save_mtraits(struct obj *, struct monst *); static struct obj *save_mtraits(struct obj *, struct monst *);
static void objlist_sanity(struct obj *, int, const char *); static void objlist_sanity(struct obj *, int, const char *);
static void mon_obj_sanity(struct monst *, const char *); static void mon_obj_sanity(struct monst *, const char *);
static void insane_obj_bits(struct obj *, struct monst *);
static const char *where_name(struct obj *); static const char *where_name(struct obj *);
static void insane_object(struct obj *, const char *, const char *, static void insane_object(struct obj *, const char *, const char *,
struct monst *); struct monst *);
@@ -1387,7 +1388,9 @@ bcsign(struct obj* otmp)
/* set the object's bless/curse-state known flag */ /* set the object's bless/curse-state known flag */
void void
set_bknown(struct obj* obj, unsigned int onoff /* 1 or 0 */) set_bknown(
struct obj *obj,
unsigned int onoff) /* 1 or 0 */
{ {
if (obj->bknown != onoff) { if (obj->bknown != onoff) {
obj->bknown = onoff; obj->bknown = onoff;
@@ -1738,7 +1741,7 @@ is_rottable(struct obj* otmp)
} }
/* /*
* These routines maintain the single-linked lists headed in g.level.objects[][] * These routines maintain the single-linked lists headed in level.objects[][]
* and threaded through the nexthere fields in the object-instance structure. * and threaded through the nexthere fields in the object-instance structure.
*/ */
@@ -2187,7 +2190,7 @@ dealloc_obj(struct obj* obj)
int int
hornoplenty( hornoplenty(
struct obj *horn, struct obj *horn,
boolean tipping) /* caller emptying entire contents; affects shop handling */ boolean tipping) /* caller emptying entire contents; affects shop mesgs */
{ {
int objcount = 0; int objcount = 0;
@@ -2273,13 +2276,6 @@ obj_sanity_check(void)
int x, y; int x, y;
struct obj *obj; struct obj *obj;
/*
* TODO:
* Should check whether the obj->bypass and/or obj->nomerge bits
* are set. Those are both used for temporary purposes and should
* be clear between moves.
*/
objlist_sanity(fobj, OBJ_FLOOR, "floor sanity"); objlist_sanity(fobj, OBJ_FLOOR, "floor sanity");
/* check that the map's record of floor objects is consistent; /* check that the map's record of floor objects is consistent;
@@ -2372,9 +2368,13 @@ objlist_sanity(struct obj* objlist, int wheretype, const char * mesg)
} }
break; break;
} }
}
if (obj->globby) if (obj->globby)
check_glob(obj, mesg); check_glob(obj, mesg);
} /* temporary flags that might have been set but which should
be clear by the time this sanity check is taking place */
if (obj->in_use || obj->bypass || obj->nomerge)
insane_obj_bits(obj, (struct monst *) 0);
} }
} }
@@ -2403,16 +2403,30 @@ mon_obj_sanity(struct monst* monlist, const char* mesg)
if (obj->globby) if (obj->globby)
check_glob(obj, mesg); check_glob(obj, mesg);
check_contained(obj, mesg); check_contained(obj, mesg);
if (obj->in_use || obj->bypass || obj->nomerge)
insane_obj_bits(obj, mon);
} }
} }
} }
static void
insane_obj_bits(struct obj *obj, struct monst *mon)
{
char infobuf[QBUFSZ];
Sprintf(infobuf, "flagged%s%s%s",
obj->in_use ? " in_use" : "",
obj->bypass ? " bypass" : "",
obj->nomerge ? " nomerge" : "");
insane_object(obj, ofmt0, infobuf, mon);
}
/* This must stay consistent with the defines in obj.h. */ /* This must stay consistent with the defines in obj.h. */
static const char *obj_state_names[NOBJ_STATES] = { "free", "floor", static const char *const obj_state_names[NOBJ_STATES] = {
"contained", "invent", "free", "floor", "contained", "invent",
"minvent", "migrating", "minvent", "migrating", "buried", "onbill",
"buried", "onbill", "luafree"
"luafree" }; };
static const char * static const char *
where_name(struct obj *obj) where_name(struct obj *obj)