]> granicus.if.org Git - nethack/commitdiff
more shop damage repair
authorPatR <rankin@nethack.org>
Sat, 9 Apr 2022 22:55:21 +0000 (15:55 -0700)
committerPatR <rankin@nethack.org>
Sat, 9 Apr 2022 22:55:21 +0000 (15:55 -0700)
Stop attempting to catch up for lost time for shop damage repair
when getlev() loads a previousl visited level.  Normal shopkeeper
behavior will take care of that.

Also, fixes the display related aspects of shop damage repair
interacting with ball and chain.  They don't happen when its done
while the map is being shown.

doc/fixes3-7-0.txt
include/extern.h
src/allmain.c
src/bones.c
src/do.c
src/restore.c
src/shk.c

index 23f01b8d7fa6642fb527ab76443a9a9b2c0ac49d..7e76d7abcb7fbe2df6817fb6e4ea382710daf7c0 100644 (file)
@@ -1,4 +1,4 @@
-NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.870 $ $NHDT-Date: 1649530942 2022/04/09 19:02:22 $
+HDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.870 $ $NHDT-Date: 1649530942 2022/04/09 19:02:22 $
 
 General Fixes and Modified Features
 -----------------------------------
@@ -875,6 +875,8 @@ avoid "the Lord Surtur's corpse glows iridescently" when shk_your() or the()
 restoring while attached ball or chain is on floor in a breach of a shop wall
        could have it be moved out of wall gap as that gets repaired, then
        might trigger an impossible about being positioned too far from hero
+don't try to catch up for lost time for shop damage repair in restdamage()
+       called from getlev(); let normal shopkeeper movement take care of it
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index 0ad900f2b6a850b36191332ee9761452cdeb6fa1..7e09175f2977b27af14be9bede88bb3a5eb94a22 100644 (file)
@@ -2436,7 +2436,8 @@ extern void sellobj(struct obj *, xchar, xchar);
 extern int doinvbill(int);
 extern struct monst *shkcatch(struct obj *, xchar, xchar);
 extern void add_damage(xchar, xchar, long);
-extern int repair_damage(struct monst *, struct damage *, boolean);
+extern int repair_damage(struct monst *, struct damage *);
+extern void fix_shop_damage(void);
 extern int shk_move(struct monst *);
 extern void after_shk_move(struct monst *);
 extern boolean is_fshk(struct monst *);
index 2b637509bd7c54995d8692b6fe39bfed28d7fc14..ef75a7eb640393a01bdb33edc6a30c8bebe0ad6c 100644 (file)
@@ -68,6 +68,7 @@ moveloop_preamble(boolean resuming)
     g.context.botlx = TRUE; /* for STATUS_HILITES */
     if (resuming) { /* restoring old game */
         read_engr_at(u.ux, u.uy); /* subset of pickup() */
+        fix_shop_damage();
     }
 
     (void) encumber_msg(); /* in case they auto-picked up something */
index 5326e08df5f58052923fdda5e961fafbbc3397a6..5d11ffd15e92dee3c4433a0653cda91c8e4c93f0 100644 (file)
@@ -660,6 +660,7 @@ getbones(void)
             }
             resetobjs(fobj, TRUE);
             resetobjs(g.level.buriedobjlist, TRUE);
+            fix_shop_damage();
         }
     }
     close_nhfile(nhfp);
index 04525b8ea65dd61eb17c407d442102df0fd20ea7..079b163d54175a522ff6aba6ce39173f16b3b9d1 100644 (file)
--- a/src/do.c
+++ b/src/do.c
@@ -1805,6 +1805,11 @@ goto_level(
 
     /* assume this will always return TRUE when changing level */
     (void) in_out_region(u.ux, u.uy);
+    /* shop repair is normally done when shopkeepers move, but we may
+       need to catch up for lost time here; do this before maybe dying
+       so bones map will include it */
+    if (!new)
+        fix_shop_damage();
 
     /* fall damage? */
     if (do_fall_dmg) {
index 21b21e899dabfd2c1b7f60a7f1e3b946a17889ca..5ded5580dcd76a14abd545f14bd0dade0ba10715 100644 (file)
@@ -154,51 +154,22 @@ restdamage(NHFILE* nhfp)
     boolean ghostly = (nhfp->ftype == NHF_BONESFILE);
 
     if (nhfp->structlevel)
-        mread(nhfp->fd, (genericptr_t) &dmgcount, sizeof(dmgcount));
+        mread(nhfp->fd, (genericptr_t) &dmgcount, sizeof dmgcount);
     counter = (int) dmgcount;
 
     if (!counter)
         return;
-    tmp_dam = (struct damage *) alloc(sizeof(struct damage));
-    while (--counter >= 0) {
-        char damaged_shops[5], *shp = (char *) 0;
-
+    do {
+        tmp_dam = (struct damage *) alloc(sizeof *tmp_dam);
         if (nhfp->structlevel)
-            mread(nhfp->fd, (genericptr_t) tmp_dam, sizeof(*tmp_dam));
+            mread(nhfp->fd, (genericptr_t) tmp_dam, sizeof *tmp_dam);
 
         if (ghostly)
             tmp_dam->when += (g.moves - g.omoves);
 
-        /*
-         * This should be removed and handled separately when returning
-         * to a level.  It's a holdover from when restore would catch up
-         * for lost time on any level as it went through all the levels
-         * instead of just splitting the save file into individual level
-         * files.
-         */
-        Strcpy(damaged_shops,
-               in_rooms(tmp_dam->place.x, tmp_dam->place.y, SHOPBASE));
-        if (u.uz.dlevel) {
-            /* when restoring, there are two passes over the current
-             * level.  the first time, u.uz isn't set, so neither is
-             * shop_keeper().  just wait and process the damage on
-             * the second pass.
-             */
-            for (shp = damaged_shops; *shp; shp++) {
-                struct monst *shkp = shop_keeper(*shp);
-
-                if (shkp && inhishop(shkp)
-                    && repair_damage(shkp, tmp_dam, TRUE))
-                    break;
-            }
-        }
-        if (!shp || !*shp) {
-            tmp_dam->next = g.level.damagelist;
-            g.level.damagelist = tmp_dam;
-            tmp_dam = (struct damage *) alloc(sizeof(*tmp_dam));
-        }
-    }
-    free((genericptr_t) tmp_dam);
+        tmp_dam->next = g.level.damagelist;
+        g.level.damagelist = tmp_dam;
+    } while (--counter > 0);
 }
 
 /* restore one object */
index cb7431ef7ca3d55abc3d9b4ad859a748a61d8569..6927a3c475474172e39cf6c00246b0cb3c442877 100644 (file)
--- a/src/shk.c
+++ b/src/shk.c
@@ -156,7 +156,7 @@ money2u(struct monst* mon, long amount)
 }
 
 static struct monst *
-next_shkp(register struct monst* shkp, register boolean withbill)
+next_shkp(register struct monst *shkp, boolean withbill)
 {
     for (; shkp; shkp = shkp->nmon) {
         if (DEADMONSTER(shkp))
@@ -1983,9 +1983,11 @@ find_oid(unsigned int id)
 /* Returns the price of an arbitrary item in the shop,
    0 if the item doesn't belong to a shopkeeper or hero is not in the shop. */
 long
-get_cost_of_shop_item(register struct obj* obj, int* nochrg)
-             /* alternate return value: 1: no charge, 0: shop owned,        */
-{            /* -1: not in a shop (so should't be formatted as "no charge") */
+get_cost_of_shop_item(
+    struct obj *obj,
+    int *nochrg) /* alternate return value: 1: no charge, 0: shop owned,
+                  * -1: not in a shop (so don't format as "no charge") */
+{
     struct monst *shkp;
     struct obj *top;
     xchar x, y;
@@ -3632,7 +3634,7 @@ discard_damage_owned_by(struct monst *shkp)
 
 /* Shopkeeper tries to repair damage belonging to them */
 static void
-shk_fixes_damage(struct monstshkp)
+shk_fixes_damage(struct monst *shkp)
 {
     struct damage *dam = find_damage(shkp);
     boolean shk_closeby;
@@ -3649,7 +3651,7 @@ shk_fixes_damage(struct monst* shkp)
     else if (!Deaf && shk_closeby)
         You_hear("someone muttering an incantation.");
 
-    (void) repair_damage(shkp, dam, FALSE);
+    (void) repair_damage(shkp, dam);
 
     discard_damage_struct(dam);
 }
@@ -3769,19 +3771,19 @@ litter_newsyms(xchar *litter, xchar x, xchar y)
 int
 repair_damage(
     struct monst *shkp,
-    struct damage *tmp_dam,
-    boolean catchup) /* restoring a level */
+    struct damage *tmp_dam)
 {
     xchar x, y;
     xchar *litter;
     struct obj *otmp;
     struct trap *ttmp;
     int k, disposition = 1;
-    boolean stop_picking = FALSE;
+    boolean catchup, stop_picking = FALSE;
 
     if (!repairable_damage(tmp_dam, shkp))
         return 0;
 
+    catchup = g.moves > tmp_dam->when + REPAIR_DELAY;
     x = tmp_dam->place.x;
     y = tmp_dam->place.y;
 
@@ -3873,11 +3875,25 @@ repair_damage(
     return disposition;
 }
 
+/* normally repair is done when a shopkeeper moves, but we also try to
+   catch up for lost time when reloading a previously visited level */
+void
+fix_shop_damage(void)
+{
+    struct monst *shkp;
+
+    for (shkp = next_shkp(fmon, FALSE); shkp;
+         shkp = next_shkp(shkp->nmon, FALSE)) {
+        if (shkp->mcanmove && inhishop(shkp))
+            shk_fixes_damage(shkp);
+    }
+}
+
 /*
  * shk_move: return 1: moved  0: didn't  -1: let m_move do it  -2: died
  */
 int
-shk_move(struct monstshkp)
+shk_move(struct monst *shkp)
 {
     xchar gx, gy, omx, omy;
     int udist;