check obj->unpaid and obj->no_charge for shop sanity; caller has verified that at least one of them is set */
| 3131 | /* check obj->unpaid and obj->no_charge for shop sanity; caller has |
| 3132 | verified that at least one of them is set */ |
| 3133 | staticfn void |
| 3134 | shop_obj_sanity(struct obj *obj, const char *mesg) |
| 3135 | { |
| 3136 | struct obj *otop; |
| 3137 | struct monst *shkp; |
| 3138 | const char *why; |
| 3139 | boolean costly, costlytoo; |
| 3140 | coordxy x = 0, y = 0; |
| 3141 | |
| 3142 | /* if contained, get top-most container; we needs its location */ |
| 3143 | otop = obj; |
| 3144 | while (otop->where == OBJ_CONTAINED) |
| 3145 | otop = otop->ocontainer; |
| 3146 | /* get obj's or its container's location; do not update obj->ox,oy |
| 3147 | or otop->ox,oy because that would cause sanity checking to |
| 3148 | produce side-effects that won't occur when not sanity checking; |
| 3149 | no need for CONTAINED_TOO because we have a top level container */ |
| 3150 | (void) get_obj_location(otop, &x, &y, BURIED_TOO); |
| 3151 | |
| 3152 | /* these will always be needed for the normal case, so don't bother |
| 3153 | waiting until we find an insanity to fetch them */ |
| 3154 | shkp = find_objowner(obj, x, y); |
| 3155 | if (shkp && obj->where == OBJ_ONBILL) |
| 3156 | x = shkp->mx, y = shkp->my; |
| 3157 | costly = costly_spot(x, y); |
| 3158 | costlytoo = costly_adjacent(shkp, x, y); |
| 3159 | |
| 3160 | why = (const char *) 0; |
| 3161 | if (obj->no_charge && obj->unpaid) { |
| 3162 | why = "%s obj both unpaid and no_charge! %s %s: %s"; |
| 3163 | } else if (obj->unpaid) { |
| 3164 | /* unpaid is only applicable for directly carried objects, for |
| 3165 | objects inside carried containers, for used up items on the |
| 3166 | billobjs list, and for floor items outside the shop proper |
| 3167 | but within the shop boundary (walls, door, "free spot") and |
| 3168 | for objects moved from such spots into the shop proper by |
| 3169 | repair of shop walls or items buried while on boundary */ |
| 3170 | if (otop->where != OBJ_INVENT |
| 3171 | && obj->where != OBJ_ONBILL /* when on bill, obj==otop */ |
| 3172 | && ((otop->where != OBJ_FLOOR && obj->where != OBJ_BURIED) |
| 3173 | || !(costly || costlytoo))) |
| 3174 | why = "%s unpaid obj not carried! %s %s: %s"; |
| 3175 | else if (!costly && !costlytoo) |
| 3176 | why = "%s unpaid obj not inside tended shop! %s %s: %s"; |
| 3177 | else if (!shkp) |
| 3178 | why = "%s unpaid obj inside untended shop! %s %s: %s"; |
| 3179 | else if (!onshopbill(obj, shkp, TRUE)) |
| 3180 | why = "%s unpaid obj not on shop bill! %s %s: %s"; |
| 3181 | } else if (obj->no_charge) { |
| 3182 | /* no_charge is only applicable for floor objects in shops, for |
| 3183 | objects inside floor containers in shops, and for objects buried |
| 3184 | beneath the shop floor or carried by a monster (usually pet) */ |
| 3185 | if (otop->where != OBJ_FLOOR |
| 3186 | && otop->where != OBJ_BURIED |
| 3187 | && otop->where != OBJ_MINVENT) |
| 3188 | why = "%s no_charge obj not on floor! %s %s: %s"; |
| 3189 | else if (!costly && !costlytoo) |
| 3190 | why = "%s no_charge obj not inside tended shop! %s %s: %s"; |
no test coverage detected