more shop billing object sanity

Used up items moved to the billobjs list still have obj->unpaid set.
That should probably be cleared since it has no meaning there, but
this hasn't done that.

For those keeping score:  unpaid checking has triggered three false
positives (so far) and found one bug.
This commit is contained in:
PatR
2022-12-01 02:23:01 -08:00
parent 4ede5f1cd4
commit 2f09bcba31
2 changed files with 27 additions and 14 deletions

View File

@@ -2800,6 +2800,8 @@ shop_obj_sanity(struct obj *obj, const char *mesg)
/* these will always be needed for the normal case, so don't bother
waiting until we find an insanity to fetch them */
shkp = find_objowner(obj, x, y);
if (shkp && obj->where == OBJ_ONBILL)
x = shkp->mx, y = shkp->my;
costly = costly_spot(x, y);
costlytoo = costly_adjacent(shkp, x, y);
@@ -2808,11 +2810,13 @@ shop_obj_sanity(struct obj *obj, const char *mesg)
why = "%s obj both unpaid and no_charge! %s %s: %s";
} else if (obj->unpaid) {
/* unpaid is only applicable for directly carried objects, for
objects inside carried containers, and for floor items outside
the shop proper but within the shop boundary (walls, door, "free
spot") and for objects moved from such spots into the shop proper
by repair of shop walls */
objects inside carried containers, for used up items on the
billobjs list, and for floor items outside the shop proper
but within the shop boundary (walls, door, "free spot") and
for objects moved from such spots into the shop proper by
repair of shop walls */
if (otop->where != OBJ_INVENT
&& obj->where != OBJ_ONBILL /* when on bill, obj==otop */
&& (otop->where != OBJ_FLOOR || (!costly && !costlytoo)))
why = "%s unpaid obj not carried! %s %s: %s";
else if (!costly && !costlytoo)

View File

@@ -872,19 +872,28 @@ find_objowner(
* they shouldn't be modified */
{
struct monst *shkp, *deflt_shkp = 0;
char *roomindx, *where = in_rooms(x, y, SHOPBASE);
/* conceptually object could be inside up to four rooms simultaneously;
in practice it will usually be one room but can sometimes be two;
check shk and bill for each room rather than just the first;
fallback to the first shk if obj isn't on the relevant bill(s) */
for (roomindx = where; *roomindx; ++roomindx)
if ((shkp = shop_keeper(*roomindx)) != 0) {
if (obj->where == OBJ_ONBILL) {
/* used up item; bill obj coordinates are useless and so are x,y */
for (shkp = next_shkp(fmon, TRUE); shkp;
shkp = next_shkp(shkp->nmon, TRUE))
if (onshopbill(obj, shkp, TRUE))
return shkp;
if (!deflt_shkp)
deflt_shkp = shkp;
}
} else {
char *roomindx, *where = in_rooms(x, y, SHOPBASE);
/* conceptually object could be inside up to 4 rooms simultaneously;
in practice it will usually be one room but can sometimes be two;
check shk and bill for each room rather than just the first;
fallback to the first shk if obj isn't on the relevant bill(s) */
for (roomindx = where; *roomindx; ++roomindx)
if ((shkp = shop_keeper(*roomindx)) != 0) {
if (onshopbill(obj, shkp, TRUE))
return shkp;
if (!deflt_shkp)
deflt_shkp = shkp;
}
}
return deflt_shkp;
}