]> granicus.if.org Git - nethack/commitdiff
fix #H2582 - seemingly angry peaceful vault guard
authorPatR <rankin@nethack.org>
Thu, 20 Dec 2018 01:36:14 +0000 (17:36 -0800)
committerPatR <rankin@nethack.org>
Thu, 20 Dec 2018 01:36:14 +0000 (17:36 -0800)
Another one from nearly 7 years ago.  Hero kicked embedded gold out
of a wall while following the guard away from the vault and got
  "The guard calms down and picks up the gold."
and player thought it was odd because the guard was peaceful.  It is
odd, but guards have an agitation state (0..7) when peaceful and it
is always non-zero when this event occurs.  Suppress the "calms down"
part unless the agitation is close to making the guard turn hostile.
[Agitation is set to 5 after that event, so it isn't very calming.]

Also, the guard was picking up gold from underneath the hero while
two steps away.  Move him adjacent (although it doesn't knock other
monsters out of the way if there's no room) prior to the message,
then back again after.  That's how if works for gold that's not at
the guard's location and not at the hero's location, although that
case does knock another monster out of the way if one is on the gold.

doc/fixes36.2
src/vault.c

index 5985270475dead1768d2e36dede408cd79ba1fe2..b4437d63a34fa13b441250a350acc2b78af5464b 100644 (file)
@@ -290,6 +290,9 @@ apply fix from grunthack to prevent panic "fakecorr overflow" when vault guard
        couldn't figure out how to lead the hero from vault to civilization;
        fixes longstanding bug C343-23
 vibrating square is not really a trap so monsters don't need to avoid it
+if hero kicks some embedded gold out of a wall while following vault gaurd
+       away from vault, don't report "the guard _calms_down_and_ picks up
+       the gold" unless he's on brink of going ballistic
 
 
 Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository
index c23f555953dba7301b629df741ad1a192a657a86..3945f215de65ca8fc7164a3fab402c5238be041f 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 vault.c $NHDT-Date: 1545217597 2018/12/19 11:06:37 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.58 $ */
+/* NetHack 3.6 vault.c $NHDT-Date: 1545269451 2018/12/20 01:30:51 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.59 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -15,6 +15,7 @@ STATIC_DCL boolean FDECL(find_guard_dest, (struct monst *, xchar *, xchar *));
 STATIC_DCL void FDECL(move_gold, (struct obj *, int));
 STATIC_DCL void FDECL(wallify_vault, (struct monst *));
 STATIC_DCL void FDECL(gd_mv_monaway, (struct monst *, int, int));
+STATIC_OVL void FDECL(gd_pick_corridor_gold, (struct monst *, int, int));
 
 void
 newegd(mtmp)
@@ -604,9 +605,9 @@ struct monst *grd;
 }
 
 STATIC_OVL void
-gd_mv_monaway(grd, nx,ny)
+gd_mv_monaway(grd, nx, ny)
 register struct monst *grd;
-int nx,ny;
+int nx, ny;
 {
     if (MON_AT(nx, ny) && !(nx == grd->mx && ny == grd->my)) {
         if (!Deaf)
@@ -616,6 +617,97 @@ int nx,ny;
     }
 }
 
+/* have guard pick gold off the floor, possibly moving to the gold's
+   position before message and back to his current spot after */
+STATIC_OVL void
+gd_pick_corridor_gold(grd, goldx, goldy)
+struct monst *grd;
+int goldx, goldy; /* <gold->ox, gold->oy> */
+{
+    struct obj *gold;
+    coord newcc, bestcc;
+    int gdelta, newdelta, bestdelta, tryct,
+        guardx = grd->mx, guardy = grd->my;
+    boolean under_u = (goldx == u.ux && goldy == u.uy),
+            see_it = cansee(goldx, goldy);
+
+    if (under_u) {
+        /* Grab the gold from between the hero's feet.
+           If guard is two or more steps away; bring him closer first. */
+        gold = g_at(goldx, goldy);
+        if (!gold) {
+            impossible("vault guard: no gold at hero's feet?");
+            return;
+        }
+        gdelta = distu(guardx, guardy);
+        if (gdelta > 2 && see_it) { /* skip if player won't see it */
+            bestdelta = gdelta;
+            bestcc.x = (xchar) guardx, bestcc.y = (xchar) guardy;
+            tryct = 9;
+            do {
+                /* pick an available spot nearest the hero and also try
+                   to find the one meeting that criterium which is nearest
+                   the guard's current location */
+                if (enexto(&newcc, goldx, goldy, grd->data)) {
+                    if ((newdelta = distu(newcc.x, newcc.y)) < bestdelta
+                        || (newdelta == bestdelta
+                            && dist2(newcc.x, newcc.y, guardx, guardy)
+                               < dist2(bestcc.x, bestcc.y, guardx, guardy))) {
+                        bestdelta = newdelta;
+                        bestcc = newcc;
+                    }
+                }
+            } while (--tryct >= 0);
+
+            if (bestdelta < gdelta) {
+                remove_monster(guardx, guardy);
+                newsym(guardx, guardy);
+                place_monster(grd, (int) bestcc.x, (int) bestcc.y);
+                newsym(grd->mx, grd->my);
+            }
+        }
+        obj_extract_self(gold);
+        add_to_minv(grd, gold);
+        newsym(goldx, goldy);
+
+    /* guard is already at gold's location */
+    } else if (goldx == guardx && goldy == guardy) {
+        mpickgold(grd); /* does a newsym */
+
+    /* gold is at some third spot, neither guard's nor hero's */
+    } else {
+        /* just for insurance... */
+        gd_mv_monaway(grd, goldx, goldy); /* make room for guard */
+        if (see_it) { /* skip if player won't see the message */
+            remove_monster(grd->mx, grd->my);
+            newsym(grd->mx, grd->my);
+            place_monster(grd, goldx, goldy); /* sets <grd->mx, grd->my> */
+        }
+        mpickgold(grd); /* does a newsym */
+    }
+
+    if (see_it) { /* cansee(goldx, goldy) */
+        char monnambuf[BUFSZ];
+
+        Strcpy(monnambuf, Monnam(grd));
+        if (!strcmpi(monnambuf, "It"))
+            Strcpy(monnambuf, "Someone");
+        pline("%s%s picks up the gold%s.", monnambuf,
+              (grd->mpeaceful && EGD(grd)->warncnt > 5)
+                 ? " calms down and" : "",
+              under_u ? " from beneath you" : "");
+    }
+
+    /* if guard was moved to get the gold, move him back */
+    if (grd->mx != guardx || grd->my != guardy) {
+        remove_monster(grd->mx, grd->my);
+        newsym(grd->mx, grd->my);
+        place_monster(grd, guardx, guardy);
+        newsym(guardx, guardy);
+    }
+    return;
+}
+
 /*
  * return  1: guard moved,  0: guard didn't,  -1: let m_move do it,  -2: died
  */
@@ -774,35 +866,12 @@ register struct monst *grd;
             m = egrd->fakecorr[fci].fx;
             n = egrd->fakecorr[fci].fy;
             goldincorridor = TRUE;
+            break;
         }
+    /* new gold can appear if it was embedded in stone and hero kicks it
+       (on even via wish and drop) so don't assume hero has been warned */
     if (goldincorridor && !egrd->gddone) {
-        x = grd->mx;
-        y = grd->my;
-        if (m == u.ux && n == u.uy) {
-            struct obj *gold = g_at(m, n);
-            /* Grab the gold from between the hero's feet.  */
-            obj_extract_self(gold);
-            add_to_minv(grd, gold);
-            newsym(m, n);
-        } else if (m == x && n == y) {
-            mpickgold(grd); /* does a newsym */
-        } else {
-            /* just for insurance... */
-            gd_mv_monaway(grd, m,n);
-            remove_monster(grd->mx, grd->my);
-            newsym(grd->mx, grd->my);
-            place_monster(grd, m, n);
-            mpickgold(grd); /* does a newsym */
-        }
-        if (cansee(m, n))
-            pline("%s%s picks up the gold.", Monnam(grd),
-                  grd->mpeaceful ? " calms down and" : "");
-        if (x != grd->mx || y != grd->my) {
-            remove_monster(grd->mx, grd->my);
-            newsym(grd->mx, grd->my);
-            place_monster(grd, x, y);
-            newsym(x, y);
-        }
+        gd_pick_corridor_gold(grd, m, n);
         if (!grd->mpeaceful)
             return -1;
         egrd->warncnt = 5;