fix issue #1339 - shop purchase warnings

Issue reported by ars3niy:  with the relatively new container
handling, buying multiple items when some were inside a container
sometimes triggered impossible "unpaid_cost: object wasn't on any
bill" warnings and not buy all intended items.  Once that occurred,
subsequent inventory display would repeat the warning.

A couple weeks back, I managed to produce a save file which would
reproduce the problem when 'p' was issued, but failed to figure
out why that was happening.  I accidentally deleted that save file
and it took quite a lot of further attempts to get another one.

I still don't understand why this fix is needed, but with it in
place the save file no longer triggers any problems.  I'm marking
the issue fixed but that could be premature.

Fixes #1339
This commit is contained in:
PatR
2024-12-30 03:12:06 -08:00
parent 50aff17f94
commit ecbb7cff4d
2 changed files with 14 additions and 3 deletions

View File

@@ -2081,6 +2081,8 @@ farlook of /e or /E stopped reporting engraving and headstone text after a fix
for the situation where // or ; reported such text when there was an
object or monster in the way
message was garbled when lightning or acid breath hit iron bars
shop bug: buying a container with unpaid items in it could produce impossible
"unpaid_cost: object not on any bill" warnings
Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository

View File

@@ -27,7 +27,7 @@ enum billitem_status {
KnownContainer = 5, /* container->cknown==1, holding unpaid item(s) */
UndisclosedContainer = 6, /* container->cknown==0 */
};
/* this is similar to sortloot; the shop bill gets converted into a array of
/* this is similar to sortloot; the shop bill gets converted into an array of
struct sortbill_item so that sorting and traversal don't need to access
the original bill or even the shk; the array gets sorted by usedup vs
unpaid and by cost within each of those two categories */
@@ -1570,7 +1570,8 @@ make_itemized_bill(
}
ibill[n].bidx = -1; /* end of list; not strictly needed */
/* ibill[0..n-1] contains data, ibill[n] has Null obj and -1 bidx */
/* ibill[0..n-1] contains data, ibill[n] has Null obj and -1 bidx and
is excluded from the sort */
if (n > 1)
qsort((genericptr_t) ibill, n, sizeof *ibill, sortbill_cmp);
return n;
@@ -2116,9 +2117,13 @@ update_bill(
}
newebillct = eshkp->billct - 1;
*bp = eshkp->bill_p[newebillct];
#if 0 /* [this is responsible for github issue #1339; it's not clear why] */
for (j = 0; j < ibillct; ++j)
if (ibill[j].bidx == newebillct)
ibill[j].bidx = bidx;
#else
nhUse(bidx);
#endif
eshkp->billct = newebillct; /* eshkp->billct - 1 */
}
return;
@@ -2294,9 +2299,13 @@ buy_container(
otmp = bp_to_obj(bp);
buy = dopayobj(shkp, bp, otmp, 1, FALSE, sightunseen);
if (buy != PAY_BUY)
if (buy != PAY_BUY) {
impossible("Buying %s contents failed unexpectedly (#%u %d).",
simpleonames(container), otmp->o_id, buy);
continue;
}
/* [updating cost here is not necessary but useful when debugging] */
ibill[indx].cost -= (bp->price * bp->bquan); /* update container */
update_bill(indx, ibillct, ibill, eshkp, bp, otmp);
++buycount;
}