]> granicus.if.org Git - nethack/commitdiff
yet more shop sanity checking
authorPatR <rankin@nethack.org>
Tue, 6 Dec 2022 07:05:20 +0000 (23:05 -0800)
committerPatR <rankin@nethack.org>
Tue, 6 Dec 2022 07:05:20 +0000 (23:05 -0800)
Reconcile boulder pushing with no_charge sanity checking.  The hack.c
part comes from entrez.

Pushing a for-sale boulder from inside the shop to the shop's boundary
("free spot", doorway, or gap in wall) adds it to the shop bill even
though it's still on the floor.  Leaving the shop without paying for
it is a robbery.  Also, pushing an unpaid boulder that's on the shop
boundary to any spot that's all the way outside the shop is robbery.

src/hack.c
src/mkobj.c

index 497ee35828f723f0458aca028645192e8a62334c..636ee7ab3974360f7cd10fae59e3be604c5f7a38 100644 (file)
@@ -243,7 +243,7 @@ moverock(void)
                 || doorless_door(rx, ry)) && !sobj_at(BOULDER, rx, ry)) {
             ttmp = t_at(rx, ry);
             mtmp = m_at(rx, ry);
-            costly = (!otmp->no_charge && costly_spot(sx, sy)
+            costly = (costly_spot(sx, sy)
                       && shop_keeper(*in_rooms(sx, sy, SHOPBASE)));
 
             /* KMH -- Sokoban doesn't let you push boulders diagonally */
@@ -383,7 +383,7 @@ moverock(void)
                         (void) rloco(otmp);
                     } else {
                         if (costly)
-                            addtobill(otmp, FALSE, FALSE, FALSE);
+                            stolen_value(otmp, rx, ry, !ttmp->tseen, FALSE);
                         obj_extract_self(otmp);
                         add_to_migration(otmp);
                         get_level(&dest, newlev);
@@ -451,6 +451,12 @@ moverock(void)
                            != 0)
                        && onshopbill(otmp, shkp, TRUE)) {
                 subfrombill(otmp, shkp);
+            } else if (otmp->unpaid && !*in_rooms(rx, ry, SHOPBASE)
+                       && *in_rooms(sx, sy, SHOPBASE)) {
+                /* 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 */
+                stolen_value(otmp, sx, sy, TRUE, FALSE);
             }
         } else {
  nopushmsg:
index 8461369ef2e857430f999bdbeb4bbf6739009a69..38b9675254ce9d8f3fc989a111f0ab7a30c17c4f 100644 (file)
@@ -2463,6 +2463,11 @@ add_to_migration(struct obj *obj)
     if (obj->where != OBJ_FREE)
         panic("add_to_migration: obj not free");
 
+    if (obj->unpaid) /* caller should have changed unpaid item to stolen */
+        impossible("unpaid object migrating to another level? [%s]",
+                   simpleonames(obj));
+    obj->no_charge = 0; /* was only relevant while inside a shop */
+
     /* lock picking context becomes stale if it's for this object */
     if (Is_container(obj))
         maybe_reset_pick(obj);
@@ -2830,7 +2835,7 @@ shop_obj_sanity(struct obj *obj, const char *mesg)
            and for objects inside floor containers in shops */
         if (otop->where != OBJ_FLOOR)
             why = "%s no_charge obj not on floor! %s %s: %s";
-        else if (!costly)
+        else if (!costly && !costlytoo)
             why = "%s no_charge obj not inside tended shop! %s %s: %s";
         else if (!shkp)
             why = "%s no_charge obj inside untended shop! %s %s: %s";