]> granicus.if.org Git - nethack/commitdiff
shop theft/breakage (trunk only)
authornethack.rankin <nethack.rankin>
Thu, 22 Jun 2006 04:08:40 +0000 (04:08 +0000)
committernethack.rankin <nethack.rankin>
Thu, 22 Jun 2006 04:08:40 +0000 (04:08 +0000)
     The recent fix for "breaking glass wand in tool shop" looked suspect,
adding a call to costly_alteration after an existing call to stolen_value.
Either one or the other ought to suffice.  (For items on the floor,
costly_alteration() calls stolen_value(); for items in inventory, or just
released from inventory and not placed on floor yet, costly_alteration()
adds a usage fee to the shop bill but doesn't annoy the shopkeeper into
adding surcharges to prices or summoning the kops if already hostile.)

     In 3.4.3, stolen_value() wasn't smart enough to charge for an out-of-
shk's-field item (like a wand in a tool shop) taken from a shop container,
and that's the problem the user was reporting.  But the post-3.4.3 code was
changed to handle that by checking billable() instead of saleable(); this
bug should have been gone.  Unfortunately, billable() treats items already
on the bill as not interesting--from the perspective of adding things to
the bill--so the change accidentally resulted in stolen_value() no longer
handling objects which are marked unpaid, triggering the same symptom for
a different reason.  (Other events besides the breakage of thrown objects
suffered from the bug's new incarnation since various places deliberately
call stolen_value() for unpaid objects.)  This updates stolen_value() and
stolen_container() to account for the behavior of billable().  And a few
calls to subfrombill() go away since stolen_value() now takes care of that.

src/dokick.c
src/dothrow.c
src/potion.c
src/shk.c

index ba110ecb0870139a9b0c1d1ea1de9d8f3465e3ff..e9f7d294976a341628367f54101e0c73b21609a7 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)dokick.c   3.5     2005/12/02      */
+/*     SCCS Id: @(#)dokick.c   3.5     2006/06/21      */
 /* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1337,7 +1337,6 @@ boolean shop_floor_obj;
 
        if(unpaid || shop_floor_obj) {
            if(unpaid) {
-               subfrombill(otmp, shop_keeper(*u.ushops));
                (void)stolen_value(otmp, u.ux, u.uy, TRUE, FALSE);
            } else {
                ox = otmp->ox;
index fae5d3404749caad3f01b386a2b9519a3d5c9c7f..ccb89e0e6a19ad5d7ff2b77e8d2f9b19f2041593 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)dothrow.c  3.5     2006/04/14      */
+/*     SCCS Id: @(#)dothrow.c  3.5     2006/06/21      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -700,31 +700,24 @@ register boolean broken;
        if(!shkp) return;
 
        if(broken) {
-               if (obj->unpaid) {
+               if (obj->unpaid)
                    (void)stolen_value(obj, u.ux, u.uy,
                                       (boolean)shkp->mpeaceful, FALSE);
-                   costly_alteration(obj, COST_DSTROY);
-                   /* costly_alteration() probably already called
-                      subfrombill() for the object, but just in case it
-                      didn't, call it again. If it did, this is a NOOP. */
-                   subfrombill(obj, shkp);
-               }
                obj->no_charge = 1;
                return;
        }
 
        if (!costly_spot(x, y) || *in_rooms(x, y, SHOPBASE) != *u.ushops) {
                /* thrown out of a shop or into a different shop */
-               if (obj->unpaid) {
+               if (obj->unpaid)
                    (void)stolen_value(obj, u.ux, u.uy,
                                       (boolean)shkp->mpeaceful, FALSE);
-                   subfrombill(obj, shkp);
-               }
        } else {
                if (costly_spot(u.ux, u.uy) && costly_spot(x, y)) {
-                   if(obj->unpaid) subfrombill(obj, shkp);
-                   else if(!(x == shkp->mx && y == shkp->my))
-                           sellobj(obj, x, y);
+                   if (obj->unpaid)
+                       subfrombill(obj, shkp);
+                   else if (x != shkp->mx || y != shkp->my)
+                       sellobj(obj, x, y);
                }
        }
 }
index 8fb596bec072a53b4e6a18b86de3cfd9a04460bf..4f3c5528134c4f2f0c801ccff14bde3812b257fe 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)potion.c   3.5     2005/12/05      */
+/*     SCCS Id: @(#)potion.c   3.5     2006/06/21      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1317,16 +1317,14 @@ boolean your_fault;
                   !objects[obj->otyp].oc_uname && cansee(mon->mx,mon->my))
                docall(obj);
        if(*u.ushops && obj->unpaid) {
-               register struct monst *shkp =
-                       shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
+               struct monst *shkp =
+                               shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
 
-               if(!shkp)
-                   obj->unpaid = 0;
-               else {
+               if (shkp)
                    (void)stolen_value(obj, u.ux, u.uy,
                                 (boolean)shkp->mpeaceful, FALSE);
-                   subfrombill(obj, shkp);
-               }
+               else
+                   obj->unpaid = 0;
        }
        obfree(obj, (struct obj *)0);
 }
index e32c8848df6b8fb4455afa05aca8c285df0c8b40..ca48c33a2ad37c6a3ebfded6ed8b98c63eecde94 100644 (file)
--- a/src/shk.c
+++ b/src/shk.c
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)shk.c      3.5     2006/06/17      */
+/*     SCCS Id: @(#)shk.c      3.5     2006/06/21      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -2438,7 +2438,15 @@ boolean ininv;
        /* the price of contained objects, if any */
        for(otmp = obj->cobj; otmp; otmp = otmp->nobj) {
            if (otmp->oclass == COIN_CLASS) continue;
-           if (!billable(&shkp, otmp, ESHK(shkp)->shoproom, TRUE)) continue;
+           if (!billable(&shkp, otmp, ESHK(shkp)->shoproom, TRUE)) {
+               /* billable() returns false for objects already on bill */
+               if (!onbill(obj, shkp, FALSE)) continue;
+               /* this assumes that we're being called by stolen_value()
+                  (or by a recursive call to self on behalf of it) where
+                  the cost of this object is about to be added to shop
+                  debt in place of having it remain on the current bill */
+               subfrombill(obj, shkp); /* avoid doubling billing */
+           }
 
            if (!Has_contents(otmp)) {
                if (otmp->unpaid || !ininv)
@@ -2460,8 +2468,13 @@ boolean peaceful, silent;
        char roomno = *in_rooms(x, y, SHOPBASE);
        struct monst *shkp = 0;
 
-       if (!billable(&shkp, obj, roomno, FALSE))
-           return 0L;
+       if (!billable(&shkp, obj, roomno, FALSE)) {
+           /* things already on the bill yield a not-billable result, so
+              we need to check bill before deciding that shk doesn't care */
+           if (!onbill(obj, shkp, FALSE)) return 0L;
+           /* shk does care; take obj off bill to avoid double billing */
+           subfrombill(obj, shkp);
+       }
 
        if(obj->oclass == COIN_CLASS) {
            gvalue += obj->quan;