From 05117fa84f1dadd73a35f06b1c0f0f99e8ccc31c Mon Sep 17 00:00:00 2001 From: Michael Meyer Date: Tue, 6 Dec 2022 20:52:13 -0500 Subject: [PATCH] Fix: billing shop boulder pushed thru shared wall I realized that the "move the boulder billing to 'used-up items'" part of 20392a6 didn't properly handle boulder movement from one shop to another via a gap in a shared wall, becuase it wasn't looking at the complete in_rooms() array (plus, it only triggered if the new spot wasn't in any shops at all). When I tried to fix that, I realized that stolen_value() was similarly not working reliably when passed a location shared between two shops, and for the same reason: it was only using the first character of the in_rooms() array. I think this patch fixes both those things, but it would be worth examining the change to stolen_value() carefully, to ensure getting the roomno via the shkp won't change anything about its normal functioning. I'm not totally sure about that -- I didn't notice any problems in some brief tests of typical stolen_value() uses, but it seems like it probably has some tricky edge cases. At the very least, passing a boulder fully through a shared wall between two shops one way, then back the other way, no longer triggers an unpaid obj sanity check in my testing. --- src/hack.c | 6 ++++-- src/shk.c | 11 +++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/hack.c b/src/hack.c index 2b3f14d5a..f425f8127 100644 --- a/src/hack.c +++ b/src/hack.c @@ -462,8 +462,10 @@ moverock(void) != 0) && onshopbill(otmp, shkp, TRUE)) { subfrombill(otmp, shkp); - } else if (otmp->unpaid && !*in_rooms(rx, ry, SHOPBASE) - && *in_rooms(sx, sy, SHOPBASE)) { + } else if (otmp->unpaid + && (shkp = find_objowner(otmp, sx, sy)) != 0 + && !strchr(in_rooms(rx, ry, SHOPBASE), + ESHK(shkp)->shoproom)) { /* once the boulder is fully out of the shop, so that it's * impossible to change your mind and push it back in without * leaving and triggering Kops, switch it to stolen_value */ diff --git a/src/shk.c b/src/shk.c index ecdb48bda..2f7606fb2 100644 --- a/src/shk.c +++ b/src/shk.c @@ -3036,12 +3036,18 @@ stolen_value( boolean silent) { long value = 0L, gvalue = 0L, billamt = 0L; - char roomno = *in_rooms(x, y, SHOPBASE); + char roomno; struct bill_x *bp; - struct monst *shkp = 0; + struct monst *shkp; boolean was_unpaid; long c_count = 0L, u_count = 0L; + if ((shkp = find_objowner(obj, x, y)) != (struct monst *) 0) { + roomno = ESHK(shkp)->shoproom; + } else { + roomno = *in_rooms(x, y, SHOPBASE); + } + /* gather information for message(s) prior to manipulating bill */ was_unpaid = obj->unpaid ? TRUE : FALSE; if (Has_contents(obj)) { @@ -3049,6 +3055,7 @@ stolen_value( u_count = count_contents(obj, TRUE, FALSE, FALSE, FALSE); } + shkp = (struct monst *) 0; if (!billable(&shkp, obj, roomno, TRUE)) { /* things already on the bill yield a not-billable result, so we need to check bill before deciding that shk doesn't care */