From: nhmall Date: Sat, 18 May 2019 20:24:48 +0000 (-0400) Subject: further improve additional glob interaction scenarios within a shop X-Git-Tag: NetHack-3.7.0_WIP~411^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=670fc9ca3493dfbc369a1b6da9a1b918563558d7;p=nethack further improve additional glob interaction scenarios within a shop Scenarios: 1. shop_owned glob merging into shop_owned glob 2. player_owned glob merging into shop_owned glob 3. shop_owned glob merging into player_owned glob 4. player_owned glob merging into player_owned glob --- diff --git a/doc/fixes36.3 b/doc/fixes36.3 index f935c3bdc..d85086092 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -19,6 +19,7 @@ glob pricing did not consider weight properly Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository ------------------------------------------------------------------ +glob shop interaction improved to handle more of the expected scenarios Platform- and/or Interface-Specific Fixes or Features diff --git a/src/invent.c b/src/invent.c index 13c6eed67..51c505375 100644 --- a/src/invent.c +++ b/src/invent.c @@ -3581,11 +3581,7 @@ register struct obj *otmp, *obj; if (obj->oclass == COIN_CLASS) return TRUE; - if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe - || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed - || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken - || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit - || obj->bypass != otmp->bypass) + if (obj->bypass != otmp->bypass) return FALSE; if (obj->globby) @@ -3594,6 +3590,12 @@ register struct obj *otmp, *obj; * or don't inhibit their merger. */ + if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe + || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed + || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken + || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit) + return FALSE; + if (obj->oclass == FOOD_CLASS && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten)) return FALSE; diff --git a/src/mkobj.c b/src/mkobj.c index 2428aec49..94370c96d 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -2786,10 +2786,7 @@ struct obj **obj1, **obj2; otmp1 = *obj1; otmp2 = *obj2; if (otmp1 && otmp2 && otmp1 != otmp2) { - if (otmp1->unpaid || otmp2->unpaid) - globby_bill_fixup(otmp1, otmp2); - else if (costly_spot(otmp1->ox, otmp1->oy)) - globby_donation(otmp1, otmp2); + globby_bill_fixup(otmp1, otmp2); if (otmp1->bknown != otmp2->bknown) otmp1->bknown = otmp2->bknown = 0; if (otmp1->rknown != otmp2->rknown) @@ -2823,7 +2820,10 @@ struct obj **obj1, **obj2; } /* - * Causes the heavier object to absorb the lighter object; + * Causes the heavier object to absorb the lighter object in + * most cases, but if one object is OBJ_FREE and the other is + * on the floor, the floor object goes first. + * * wrapper for obj_absorb so that floor_effects works more * cleanly (since we don't know which we want to stay around) */ @@ -2837,8 +2837,9 @@ struct obj **obj1, **obj2; otmp1 = *obj1; otmp2 = *obj2; if (otmp1 && otmp2 && otmp1 != otmp2) { - if (otmp1->owt > otmp2->owt - || (otmp1->owt == otmp2->owt && rn2(2))) { + if (!(otmp2->where == OBJ_FLOOR && otmp1->where == OBJ_FREE) && + (otmp1->owt > otmp2->owt + || (otmp1->owt == otmp2->owt && rn2(2)))) { return obj_absorb(obj1, obj2); } return obj_absorb(obj2, obj1); diff --git a/src/objnam.c b/src/objnam.c index a684f163c..e8bb71c14 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -1228,7 +1228,7 @@ unsigned doname_flags; nochrg ? "contents" : "for sale", globwt(obj, globbuf), price, currency(price)); else if (nochrg > 0) - Strcat(bp, " (no charge)"); + Sprintf(eos(bp), " (%sno charge)", globwt(obj, globbuf)); } if (!strncmp(prefix, "a ", 2)) { /* save current prefix, without "a "; might be empty */ @@ -1242,7 +1242,8 @@ unsigned doname_flags; /* show weight for items (debug tourist info) * aum is stolen from Crawl's "Arbitrary Unit of Measure" */ if (wizard && iflags.wizweight) { - Sprintf(eos(bp), " (%d aum)", obj->owt); + if (!obj->globby) /* aum already apparent for globs */ + Sprintf(eos(bp), " (%d aum)", obj->owt); } bp = strprepend(bp, prefix); return bp; diff --git a/src/shk.c b/src/shk.c index 18a2599e0..470253570 100644 --- a/src/shk.c +++ b/src/shk.c @@ -4801,91 +4801,108 @@ sasc_bug(struct obj *op, unsigned x) #endif /* - * When one glob is absorbed by another glob, the two become - * indistinguishable and the remaining glob grows in mass, - * the product of both. + * The caller is about to make obj_absorbed go away. + * + * There's no way for you (or a shopkeeper) to prevent globs + * from merging with each other on the floor due to the + * inherent nature of globs so it irretrievably becomes part + * of the floor glob mass. When one glob is absorbed by another + * glob, the two become indistinguishable and the remaining + * glob object grows in mass, the product of both. + * + * billing admin, player compensation, shopkeeper compensation + * all need to be considered. * - * The original billed item is lost to the absorption and the - * original billed amount for the object being absorbed gets - * added to the cost owing for the absorber, and the separate - * cost for the absorbed object goes away. + * Any original billed item is lost to the absorption so the + * original billed amount for the object being absorbed must + * get added to the cost owing for the absorber, and the + * separate cost for the object being absorbed goes away. + * + * There are four scenarios to deal with: + * 1. shop_owned glob merging into shop_owned glob + * 2. player_owned glob merging into shop_owned glob + * 3. shop_owned glob merging into player_owned glob + * 4. player_owned glob merging into player_owned glob */ void globby_bill_fixup(obj_absorber, obj_absorbed) struct obj *obj_absorber, *obj_absorbed; { + int x, y; struct bill_x *bp, *bp_absorber = (struct bill_x *) 0; struct monst *shkp = 0; + struct eshk *eshkp; + long amount, per_unit_cost = set_cost(obj_absorbed, shkp); + boolean floor_absorber = (obj_absorber->where == OBJ_FLOOR); if (!obj_absorber->globby) impossible("globby_bill_fixup called for non-globby object"); + if (floor_absorber) { + x = obj_absorber->ox, y = obj_absorber->oy; + } if (obj_absorber->unpaid) { /* look for a shopkeeper who owns this object */ for (shkp = next_shkp(fmon, TRUE); shkp; shkp = next_shkp(shkp->nmon, TRUE)) if (onbill(obj_absorber, shkp, TRUE)) break; + } else if (obj_absorbed->unpaid) { + if (obj_absorbed->where == OBJ_FREE + && floor_absorber && costly_spot(x, y)) { + shkp = shop_keeper(*in_rooms(x, y, SHOPBASE)); + } } /* sanity check, in case obj is on bill but not marked 'unpaid' */ if (!shkp) shkp = shop_keeper(*u.ushops); + if (!shkp) + return; + bp_absorber = onbill(obj_absorber, shkp, FALSE); + bp = onbill(obj_absorbed, shkp, FALSE); + eshkp = ESHK(shkp); - if ((bp_absorber = onbill(obj_absorber, shkp, FALSE)) != 0) { - bp = onbill(obj_absorbed, shkp, FALSE); - if (bp) { - bp_absorber->price += bp->price; - ESHK(shkp)->billct--; + /************************************************************** + * Scenario 1. Shop-owned glob absorbing into shop-owned glob + **************************************************************/ + if (bp && (!obj_absorber->no_charge + || billable(&shkp, obj_absorber, eshkp->shoproom, FALSE))) { + /* the glob being absorbed has a billing record */ + amount = bp->price; + eshkp->billct--; #ifdef DUMB - { - /* DRS/NS 2.2.6 messes up -- Peter Kendell */ - int indx = ESHK(shkp)->billct; + { + /* DRS/NS 2.2.6 messes up -- Peter Kendell */ + int indx = eshkp->billct; - *bp = ESHK(shkp)->bill_p[indx]; - } + *bp = eshkp->bill_p[indx]; + } #else - *bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct]; + *bp = eshkp->bill_p[eshkp->billct]; #endif - clear_unpaid_obj(shkp, obj_absorbed); + clear_unpaid_obj(shkp, obj_absorbed); + + if (bp_absorber) { + /* the absorber has a billing record */ + bp_absorber->price += amount; } else { - /* should never happen */ - bp_absorber->price += get_cost(obj_absorbed, shkp) - * get_pricing_units(obj_absorbed); + /* the absorber has no billing record */ + ; } + return; } -} - -/* - * The caller is about to make obj_absorbed go away. - * - * There's no way for you (or a shopkeeper) to prevent globs - * from merging with each other on the floor due to the - * inherent nature of globs so it irretrievably becomes part - * of the floor glob mass. - * - * globby_donation() needs to handle whether/how to - * compensate you for that. - * - * unpaid globs don't end up here. - */ -void -globby_donation(obj_absorber, obj_absorbed) -struct obj *obj_absorber, *obj_absorbed; -{ - if (obj_absorber->where == OBJ_FLOOR - && costly_spot(obj_absorber->ox, obj_absorber->oy)) { - int x = obj_absorber->ox, y = obj_absorber->oy; - struct monst *shkp = shop_keeper(*in_rooms(x, y, SHOPBASE)); - struct eshk *eshkp = ESHK(shkp); - long amount, per_unit_cost = get_cost(obj_absorbed, shkp); - + /************************************************************** + * Scenario 2. Player-owned glob absorbing into shop-owned glob + **************************************************************/ + if (!bp_absorber && !bp && !obj_absorber->no_charge) { + /* there are no billing records */ + amount = get_pricing_units(obj_absorbed) * per_unit_cost; if (saleable(shkp, obj_absorbed)) { - amount = get_pricing_units(obj_absorbed) * per_unit_cost; if (eshkp->debit >= amount) { if (eshkp->loan) { /* you carry shop's gold */ - if (eshkp->loan >= amount) + if (eshkp->loan >= amount) eshkp->loan -= amount; - else + else eshkp->loan = 0L; } eshkp->debit -= amount; @@ -4913,7 +4930,34 @@ struct obj *obj_absorber, *obj_absorbed; eshkp->credit, currency(eshkp->credit)); } } + return; + } else if (bp_absorber) { + /* absorber has a billing record */ + bp_absorber->price += per_unit_cost * get_pricing_units(obj_absorbed); + return; + } + /************************************************************** + * Scenario 3. shop_owned glob merging into player_owned glob + **************************************************************/ + if (bp && + (obj_absorber->no_charge + || (floor_absorber && !costly_spot(x, y)))) { + amount = bp->price; + bill_dummy_object(obj_absorbed); + verbalize( + "You owe me %ld %s for my %s that %s with your%s", + amount, currency(amount), obj_typename(obj_absorbed->otyp), + ANGRY(shkp) ? "had the audacity to mix" : + "just mixed", + ANGRY(shkp) ? " stinking batch!" : + "s."); + return; } + /************************************************************** + * Scenario 4. player_owned glob merging into player_owned glob + **************************************************************/ + + return; } /*shk.c*/