fix #K3514 - unpaid_cost() impossible
Fix the reported bug of using Passes_walls to carry an unpaid item from inside a shop into the wall it shares with another shop producing a situation where examining inventory issued an impossible "unpaid_cost: object wasn't on any bill" when trying to append the cost to the formatted inventory line. u.ushops[], u.ushops0[], and others are lists that can have up to four entries and the relevant code was only checking the first one. Not mentioned in the report: continuing another step into the other shop didn't get recognized as robbing the first shop, for a similar reason. For either of these bugs, digging a breach in the wall, paying off the miffed shopkeeper, then stepping into the breach before it gets repaired will probably trigger the same results without the need for polymorphing into a xorn or earth elemental. But not on the tourist goal level test case since walls there are undiggable. I didn't go looking for other instances of not checking all relevant shopkeepers. It wouldn't surprise me if there are some more.
This commit is contained in:
@@ -738,6 +738,13 @@ getting wounded in one leg when the other was already wounded miraculously
|
|||||||
when parsing config file entry "BINDINGS=key1:cmd1,key2:cmd2,key3:cmd3" allow
|
when parsing config file entry "BINDINGS=key1:cmd1,key2:cmd2,key3:cmd3" allow
|
||||||
keyN to be either a naked comma or backslash+comma instead requiring
|
keyN to be either a naked comma or backslash+comma instead requiring
|
||||||
that comma's numeric value be used to bind comma to a command
|
that comma's numeric value be used to bind comma to a command
|
||||||
|
when two or more shops share a wall and hero uses Passes_walls to carry an
|
||||||
|
unpaid item from inside a shop into the shared wall, it could yield
|
||||||
|
impossible "unpaid_cost: object wasn't on any bill" when examining
|
||||||
|
inventory if the shop code picked wrong shopkeeper to determine cost
|
||||||
|
when two or more shops share a wall and hero uses Passes_walls to carry an
|
||||||
|
unpaid item through the shared wall into another shop, theft of that
|
||||||
|
unpaid item from the first shop wasn't noticed
|
||||||
|
|
||||||
|
|
||||||
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
|
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
|
||||||
|
|||||||
19
src/shk.c
19
src/shk.c
@@ -385,7 +385,7 @@ inside_shop(register xchar x, register xchar y)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
u_left_shop(char* leavestring, boolean newlev)
|
u_left_shop(char *leavestring, boolean newlev)
|
||||||
{
|
{
|
||||||
struct monst *shkp;
|
struct monst *shkp;
|
||||||
struct eshk *eshkp;
|
struct eshk *eshkp;
|
||||||
@@ -400,7 +400,7 @@ u_left_shop(char* leavestring, boolean newlev)
|
|||||||
if (!*leavestring && (!levl[u.ux][u.uy].edge || levl[u.ux0][u.uy0].edge))
|
if (!*leavestring && (!levl[u.ux][u.uy].edge || levl[u.ux0][u.uy0].edge))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
shkp = shop_keeper(*u.ushops0);
|
shkp = shop_keeper(*leavestring ? *leavestring : *u.ushops0);
|
||||||
if (!shkp || !inhishop(shkp))
|
if (!shkp || !inhishop(shkp))
|
||||||
return; /* shk died, teleported, changed levels... */
|
return; /* shk died, teleported, changed levels... */
|
||||||
|
|
||||||
@@ -2422,19 +2422,20 @@ unpaid_cost(
|
|||||||
struct bill_x *bp = (struct bill_x *) 0;
|
struct bill_x *bp = (struct bill_x *) 0;
|
||||||
struct monst *shkp;
|
struct monst *shkp;
|
||||||
long amt = 0L;
|
long amt = 0L;
|
||||||
|
|
||||||
|
#if 0 /* if two shops share a wall, this might find wrong shk */
|
||||||
xchar ox, oy;
|
xchar ox, oy;
|
||||||
|
|
||||||
if (!get_obj_location(unp_obj, &ox, &oy, BURIED_TOO | CONTAINED_TOO))
|
if (!get_obj_location(unp_obj, &ox, &oy, BURIED_TOO | CONTAINED_TOO))
|
||||||
ox = u.ux, oy = u.uy; /* (shouldn't happen) */
|
ox = u.ux, oy = u.uy; /* (shouldn't happen) */
|
||||||
if ((shkp = shop_keeper(*in_rooms(ox, oy, SHOPBASE))) != 0) {
|
if ((shkp = shop_keeper(*in_rooms(ox, oy, SHOPBASE))) != 0) {
|
||||||
bp = onbill(unp_obj, shkp, TRUE);
|
bp = onbill(unp_obj, shkp, TRUE);
|
||||||
} else {
|
} else /* didn't find shk? try searching bills */
|
||||||
/* didn't find shk? try searching bills */
|
#endif
|
||||||
for (shkp = next_shkp(fmon, TRUE); shkp;
|
for (shkp = next_shkp(fmon, TRUE); shkp;
|
||||||
shkp = next_shkp(shkp->nmon, TRUE))
|
shkp = next_shkp(shkp->nmon, TRUE))
|
||||||
if ((bp = onbill(unp_obj, shkp, TRUE)) != 0)
|
if ((bp = onbill(unp_obj, shkp, TRUE)) != 0)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* onbill() gave no message if unexpected problem occurred */
|
/* onbill() gave no message if unexpected problem occurred */
|
||||||
if (!shkp || (unp_obj->unpaid && !bp)) {
|
if (!shkp || (unp_obj->unpaid && !bp)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user