From a7b714ec5cb52be7a806ea5c8f5de25f65e719c0 Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 4 Dec 2022 08:59:22 -0800 Subject: [PATCH] no_charge items sanity - shop theft More unpaid/no_charge sanity checking. If a shop contained any no_charge objects and was robbed, they would be left no_charge and trigger sanity check warnings (no_charge in "untended shop") once the shopkeeper got past any Kops in the way and exited the shop. Earlier testing didn't wait around long enough for that exit to happen. Clear no_charge as soon as the robbery is detected. --- src/shk.c | 67 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/src/shk.c b/src/shk.c index 3ae0ca2c2..6bb0368d6 100644 --- a/src/shk.c +++ b/src/shk.c @@ -178,7 +178,7 @@ next_shkp(register struct monst *shkp, boolean withbill) /* called in mon.c */ void -shkgone(struct monst* mtmp) +shkgone(struct monst *mtmp) { struct eshk *eshk = ESHK(mtmp); struct mkroom *sroom = &gr.rooms[eshk->shoproom - ROOMOFFSET]; @@ -215,7 +215,7 @@ shkgone(struct monst* mtmp) } void -set_residency(register struct monst* shkp, register boolean zero_out) +set_residency(struct monst *shkp, boolean zero_out) { if (on_level(&(ESHK(shkp)->shoplevel), &u.uz)) gr.rooms[ESHK(shkp)->shoproom - ROOMOFFSET].resident = @@ -223,7 +223,7 @@ set_residency(register struct monst* shkp, register boolean zero_out) } void -replshk(register struct monst* mtmp, register struct monst* mtmp2) +replshk(struct monst *mtmp, struct monst *mtmp2) { gr.rooms[ESHK(mtmp2)->shoproom - ROOMOFFSET].resident = mtmp2; if (inhishop(mtmp) && *u.ushops == ESHK(mtmp)->shoproom) { @@ -233,7 +233,7 @@ replshk(register struct monst* mtmp, register struct monst* mtmp2) /* do shopkeeper specific structure munging -dlc */ void -restshk(struct monst* shkp, boolean ghostly) +restshk(struct monst *shkp, boolean ghostly) { if (u.uz.dlevel) { struct eshk *eshkp = ESHK(shkp); @@ -250,19 +250,54 @@ restshk(struct monst* shkp, boolean ghostly) } } -/* Clear the unpaid bit on a single object and its contents. */ +/* Clear the unpaid and no_charge bits on a single object and its contents. */ static void -clear_unpaid_obj(struct monst* shkp, struct obj* otmp) +clear_unpaid_obj(struct monst *shkp, struct obj *otmp) { if (Has_contents(otmp)) clear_unpaid(shkp, otmp->cobj); if (onbill(otmp, shkp, TRUE)) otmp->unpaid = 0; + + if (otmp->no_charge) { + struct monst *rm_shkp; + int rno; + coordxy x, y; + + /* + * Clear no_charge if + * not located somewhere that we expect no_charge (which is + * floor [of shop] or inside container [on shop floor]) + * or can't find object's map coordinates (should never happen + * for floor or contained; conceivable if on shop bill somehow + * but would have failed the floor-or-contained test since + * containers get emptied before going onto bill) + * or fails location sanity check (should always be good when + * location successfully found) + * or not inside any room + * or the room isn't a shop + * or the shop has no shopkeeper (deserted) + * or shopkeeper is the current one (to avoid clearing no_charge + * for items located in some rival's shop). + * + * no_charge items in a shop which is only temporarily deserted + * become owned by the shop now and will be for-sale once the shk + * returns. + */ + if ((otmp->where != OBJ_FLOOR && otmp->where != OBJ_CONTAINED) + || !get_obj_location(otmp, &x, &y, OBJ_CONTAINED | OBJ_BURIED) + || !isok(x, y) + || (rno = levl[x][y].roomno) < ROOMOFFSET + || !IS_SHOP(rno - ROOMOFFSET) + || (rm_shkp = gr.rooms[rno - ROOMOFFSET].resident) == 0 + || rm_shkp == shkp) + otmp->no_charge = 0; + } } /* Clear the unpaid bit on all of the objects in the list. */ static void -clear_unpaid(struct monst* shkp, struct obj* list) +clear_unpaid(struct monst *shkp, struct obj *list) { while (list) { clear_unpaid_obj(shkp, list); @@ -272,7 +307,7 @@ clear_unpaid(struct monst* shkp, struct obj* list) /* either you paid or left the shop or the shopkeeper died */ void -setpaid(register struct monst* shkp) +setpaid(register struct monst *shkp) { register struct obj *obj; register struct monst *mtmp; @@ -302,11 +337,11 @@ setpaid(register struct monst* shkp) } static long -addupbill(register struct monst* shkp) +addupbill(struct monst *shkp) { - register int ct = ESHK(shkp)->billct; - register struct bill_x *bp = ESHK(shkp)->bill_p; - register long total = 0L; + int ct = ESHK(shkp)->billct; + struct bill_x *bp = ESHK(shkp)->bill_p; + long total = 0L; while (ct--) { total += bp->price * bp->bquan; @@ -316,10 +351,10 @@ addupbill(register struct monst* shkp) } static void -call_kops(register struct monst* shkp, register boolean nearshop) +call_kops(struct monst *shkp, boolean nearshop) { /* Keystone Kops srt@ucla */ - register boolean nokops; + boolean nokops; if (!shkp) return; @@ -373,9 +408,9 @@ call_kops(register struct monst* shkp, register boolean nearshop) /* x,y is strictly inside shop */ char -inside_shop(register coordxy x, register coordxy y) +inside_shop(coordxy x, coordxy y) { - register char rno; + char rno; rno = levl[x][y].roomno; if ((rno < ROOMOFFSET) || levl[x][y].edge || !IS_SHOP(rno - ROOMOFFSET))