OSDN Git Service

add missing "#ifdef X11LARGETILE"
[jnethack/source.git] / src / vault.c
index 509b8da..fe514a7 100644 (file)
@@ -1,23 +1,25 @@
-/* NetHack 3.6 vault.c $NHDT-Date: 1452132199 2016/01/07 02:03:19 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.42 $ */
+/* NetHack 3.6 vault.c $NHDT-Date: 1549921171 2019/02/11 21:39:31 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.62 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2011. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
-/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016            */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020            */
 /* JNetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
 
-STATIC_DCL struct monst *NDECL(findgd);
-
 STATIC_DCL boolean FDECL(clear_fcorr, (struct monst *, BOOLEAN_P));
 STATIC_DCL void FDECL(blackout, (int, int));
 STATIC_DCL void FDECL(restfakecorr, (struct monst *));
+STATIC_DCL void FDECL(parkguard, (struct monst *));
 STATIC_DCL boolean FDECL(in_fcorridor, (struct monst *, int, int));
+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)
@@ -26,8 +28,8 @@ struct monst *mtmp;
     if (!mtmp->mextra)
         mtmp->mextra = newmextra();
     if (!EGD(mtmp)) {
-        EGD(mtmp) = (struct egd *) alloc(sizeof(struct egd));
-        (void) memset((genericptr_t) EGD(mtmp), 0, sizeof(struct egd));
+        EGD(mtmp) = (struct egd *) alloc(sizeof (struct egd));
+        (void) memset((genericptr_t) EGD(mtmp), 0, sizeof (struct egd));
     }
 }
 
@@ -42,6 +44,9 @@ struct monst *mtmp;
     mtmp->isgd = 0;
 }
 
+/* try to remove the temporary corridor (from vault to rest of map) being
+   maintained by guard 'grd'; if guard is still in it, removal will fail,
+   to be tried again later */
 STATIC_OVL boolean
 clear_fcorr(grd, forceshow)
 struct monst *grd;
@@ -49,7 +54,8 @@ boolean forceshow;
 {
     register int fcx, fcy, fcbeg;
     struct monst *mtmp;
-    boolean sawcorridor = FALSE;
+    boolean sawcorridor = FALSE,
+            silently = program_state.stopprint ? TRUE : FALSE;
     struct egd *egrd = EGD(grd);
     struct trap *trap;
     struct rm *lev;
@@ -57,12 +63,16 @@ boolean forceshow;
     if (!on_level(&egrd->gdlevel, &u.uz))
         return TRUE;
 
+    /* note: guard remains on 'fmons' list (alive or dead, at off-map
+       coordinate <0,0>), until temporary corridor from vault back to
+       civilization has been removed */
     while ((fcbeg = egrd->fcbeg) < egrd->fcend) {
         fcx = egrd->fakecorr[fcbeg].fx;
         fcy = egrd->fakecorr[fcbeg].fy;
-        if ((grd->mhp <= 0 || !in_fcorridor(grd, u.ux, u.uy)) && egrd->gddone)
+        if ((DEADMONSTER(grd) || !in_fcorridor(grd, u.ux, u.uy))
+            && egrd->gddone)
             forceshow = TRUE;
-        if ((u.ux == fcx && u.uy == fcy && grd->mhp > 0)
+        if ((u.ux == fcx && u.uy == fcy && !DEADMONSTER(grd))
             || (!forceshow && couldsee(fcx, fcy))
             || (Punished && !carried(uball) && uball->ox == fcx
                 && uball->oy == fcy))
@@ -74,7 +84,8 @@ boolean forceshow;
             } else if (!in_fcorridor(grd, u.ux, u.uy)) {
                 if (mtmp->mtame)
                     yelp(mtmp);
-                (void) rloc(mtmp, FALSE);
+                if (!rloc(mtmp, TRUE))
+                    m_into_limbo(mtmp);
             }
         }
         lev = &levl[fcx][fcy];
@@ -97,12 +108,16 @@ boolean forceshow;
         vision_full_recalc = 1;
         egrd->fcbeg++;
     }
-    if (sawcorridor)
+    if (sawcorridor && !silently)
 /*JP
         pline_The("corridor disappears.");
 */
         pline("\92Ê\98H\82Í\8fÁ\82¦\82½\81D");
-    if (IS_ROCK(levl[u.ux][u.uy].typ))
+    /* only give encased message if hero is still alive (might get here
+       via paygd() -> mongone() -> grddead() when game is over;
+       died: no message, quit: message) */
+    if (IS_ROCK(levl[u.ux][u.uy].typ) && (Upolyd ? u.mh : u.uhp) > 0
+        && !silently)
 /*JP
         You("are encased in rock.");
 */
@@ -147,6 +162,26 @@ struct monst *grd;
     }
 }
 
+/* move guard--dead to alive--to <0,0> until temporary corridor is removed */
+STATIC_OVL void
+parkguard(grd)
+struct monst *grd;
+{
+    /* either guard is dead or will now be treated as if so;
+       monster traversal loops should skip it */
+    if (grd == context.polearm.hitmon)
+        context.polearm.hitmon = 0;
+    if (grd->mx) {
+        remove_monster(grd->mx, grd->my);
+        newsym(grd->mx, grd->my);
+        place_monster(grd, 0, 0);
+        /* [grd->mx,my just got set to 0,0 by place_monster(), so this
+           just sets EGD(grd)->ogx,ogy to 0,0 too; is that what we want?] */
+        EGD(grd)->ogx = grd->mx;
+        EGD(grd)->ogy = grd->my;
+    }
+}
+
 /* called in mon.c */
 boolean
 grddead(grd)
@@ -157,16 +192,8 @@ struct monst *grd;
     if (!dispose) {
         /* destroy guard's gold; drop any other inventory */
         relobj(grd, 0, FALSE);
-        /* guard is dead; monster traversal loops should skip it */
         grd->mhp = 0;
-        if (grd == context.polearm.hitmon)
-            context.polearm.hitmon = 0;
-        /* see comment by newpos in gd_move() */
-        remove_monster(grd->mx, grd->my);
-        newsym(grd->mx, grd->my);
-        place_monster(grd, 0, 0);
-        EGD(grd)->ogx = grd->mx;
-        EGD(grd)->ogy = grd->my;
+        parkguard(grd);
         dispose = clear_fcorr(grd, TRUE);
     }
     if (dispose)
@@ -188,7 +215,6 @@ int x, y;
     return FALSE;
 }
 
-STATIC_OVL
 struct monst *
 findgd()
 {
@@ -222,6 +248,74 @@ char *array;
     return '\0';
 }
 
+/* hero has teleported out of vault while a guard is active */
+void
+uleftvault(grd)
+struct monst *grd;
+{
+    /* only called if caller has checked vault_occupied() and findgd() */
+    if (!grd || !grd->isgd || DEADMONSTER(grd)) {
+        impossible("escaping vault without guard?");
+        return;
+    }
+    /* if carrying gold and arriving anywhere other than next to the guard,
+       set the guard loose */
+    if ((money_cnt(invent) || hidden_gold())
+        && um_dist(grd->mx, grd->my, 1)) {
+        if (grd->mpeaceful) {
+            if (canspotmon(grd)) /* see or sense via telepathy */
+/*JP
+                pline("%s becomes irate.", Monnam(grd));
+*/
+                pline("%s\82Í\8c\83\93{\82µ\82½\81D", Monnam(grd));
+            grd->mpeaceful = 0; /* bypass setmangry() */
+        }
+        /* if arriving outside guard's temporary corridor, give the
+           guard an extra move to deliver message(s) and to teleport
+           out of and remove that corridor */
+        if (!in_fcorridor(grd, u.ux, u.uy))
+            (void) gd_move(grd);
+    }
+}
+
+STATIC_OVL boolean
+find_guard_dest(guard, rx, ry)
+struct monst *guard;
+xchar *rx, *ry;
+{
+    register int x, y, dd, lx = 0, ly = 0;
+
+    for (dd = 2; (dd < ROWNO || dd < COLNO); dd++) {
+        for (y = u.uy - dd; y <= u.uy + dd; ly = y, y++) {
+            if (y < 0 || y > ROWNO - 1)
+                continue;
+            for (x = u.ux - dd; x <= u.ux + dd; lx = x, x++) {
+                if (y != u.uy - dd && y != u.uy + dd && x != u.ux - dd)
+                    x = u.ux + dd;
+                if (x < 1 || x > COLNO - 1)
+                    continue;
+                if (guard && ((x == guard->mx && y == guard->my)
+                              || (guard->isgd && in_fcorridor(guard, x, y))))
+                    continue;
+                if (levl[x][y].typ == CORR) {
+                    lx = (x < u.ux) ? x + 1 : (x > u.ux) ? x - 1 : x;
+                    ly = (y < u.uy) ? y + 1 : (y > u.uy) ? y - 1 : y;
+                    if (levl[lx][ly].typ != STONE && levl[lx][ly].typ != CORR)
+                        goto incr_radius;
+                    *rx = x;
+                    *ry = y;
+                    return TRUE;
+                }
+            }
+        }
+ incr_radius:
+        ;
+    }
+    impossible("Not a single corridor on this level?");
+    tele();
+    return FALSE;
+}
+
 void
 invault()
 {
@@ -236,56 +330,20 @@ invault()
         u.uinvault = 0;
         return;
     }
-
     vaultroom -= ROOMOFFSET;
 
     guard = findgd();
     if (++u.uinvault % VAULT_GUARD_TIME == 0 && !guard) {
         /* if time ok and no guard now. */
-        char buf[BUFSZ] = DUMMY;
-        register int x, y, dd, gx, gy;
-        int lx = 0, ly = 0;
+        char buf[BUFSZ];
+        register int x, y, gx, gy;
+        xchar rx, ry;
         long umoney;
 
         /* first find the goal for the guard */
-        for (dd = 2; (dd < ROWNO || dd < COLNO); dd++) {
-            for (y = u.uy - dd; y <= u.uy + dd; ly = y, y++) {
-                if (y < 0 || y > ROWNO - 1)
-                    continue;
-                for (x = u.ux - dd; x <= u.ux + dd; lx = x, x++) {
-                    if (y != u.uy - dd && y != u.uy + dd && x != u.ux - dd)
-                        x = u.ux + dd;
-                    if (x < 1 || x > COLNO - 1)
-                        continue;
-                    if (levl[x][y].typ == CORR) {
-                        if (x < u.ux)
-                            lx = x + 1;
-                        else if (x > u.ux)
-                            lx = x - 1;
-                        else
-                            lx = x;
-                        if (y < u.uy)
-                            ly = y + 1;
-                        else if (y > u.uy)
-                            ly = y - 1;
-                        else
-                            ly = y;
-                        if (levl[lx][ly].typ != STONE
-                            && levl[lx][ly].typ != CORR)
-                            goto incr_radius;
-                        goto fnd;
-                    }
-                }
-            }
-        incr_radius:
-            ;
-        }
-        impossible("Not a single corridor on this level??");
-        tele();
-        return;
-    fnd:
-        gx = x;
-        gy = y;
+        if (!find_guard_dest((struct monst *)0, &rx, &ry))
+            return;
+        gx = rx, gy = ry;
 
         /* next find a good place for a door in the wall */
         x = u.ux;
@@ -355,7 +413,7 @@ invault()
         reset_faint(); /* if fainted - wake up */
         gsensed = !canspotmon(guard);
         if (!gsensed)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             pline("Suddenly one of the Vault's %s enters!",
                   makeplural(guard->data->mname));
 #else
@@ -369,10 +427,11 @@ invault()
         newsym(guard->mx, guard->my);
         if (u.uswallow) {
             /* can't interrogate hero, don't interrogate engulfer */
+            if (!Deaf)
 /*JP
-            if (!Deaf) verbalize("What's going on here?");
+                verbalize("What's going on here?");
 */
-            if (!Deaf) verbalize("\82±\82±\82Å\89½\82ð\82µ\82Ä\82¢\82é\82ñ\82¾\81H");
+                verbalize("\82±\82±\82Å\89½\82ð\82µ\82Ä\82¢\82é\82ñ\82¾\81H");
             if (gsensed)
 /*JP
                 pline_The("other presence vanishes.");
@@ -381,15 +440,16 @@ invault()
             mongone(guard);
             return;
         }
-        if (youmonst.m_ap_type == M_AP_OBJECT || u.uundetected) {
-            if (youmonst.m_ap_type == M_AP_OBJECT
+        if (U_AP_TYPE == M_AP_OBJECT || u.uundetected) {
+            if (U_AP_TYPE == M_AP_OBJECT
                 && youmonst.mappearance != GOLD_PIECE)
-#if 0 /*JP*/
-                if (!Deaf) verbalize("Hey! Who left that %s in here?",
-                                    mimic_obj_name(&youmonst));
+                if (!Deaf)
+#if 0 /*JP:T*/
+                    verbalize("Hey!  Who left that %s in here?",
+                              mimic_obj_name(&youmonst));
 #else
-                if (!Deaf) verbalize("\82¨\82¢\81I\82¾\82ê\82ª\82±\82Ì%s\82ð\82±\82±\82É\92u\82¢\82Ä\8ds\82Á\82½\82ñ\82¾\81H",
-                                    mimic_obj_name(&youmonst));
+                    verbalize("\82¨\82¢\81I\82¾\82ê\82ª\82±\82Ì%s\82ð\82±\82±\82É\92u\82¢\82Ä\8ds\82Á\82½\82ñ\82¾\81H",
+                              mimic_obj_name(&youmonst));
 #endif
             /* You're mimicking some object or you're hidden. */
 /*JP
@@ -404,12 +464,15 @@ invault()
                been given in order to vary it upon repeat visits, but
                discarding the monster and its egd data renders that hard] */
             if (Deaf)
+/*JP
                 pline("%s huffs and turns to leave.", noit_Monnam(guard));
+*/
+                pline("%s\82Í\95s\8b@\8c\99\82É\82È\82Á\82Ä\81C\8b\8e\82Á\82Ä\82¢\82Á\82½\81D", noit_Monnam(guard));
             else
 /*JP
-            verbalize("I'll be back when you're ready to speak to me!");
+                verbalize("I'll be back when you're ready to speak to me!");
 */
-            verbalize("\98b\82¹\82é\82æ\82¤\82É\82È\82Á\82½\82ç\96ß\82Á\82Ä\82«\82Ä\82â\82é\81I");
+                verbalize("\98b\82¹\82é\82æ\82¤\82É\82È\82Á\82½\82ç\96ß\82Á\82Ä\82«\82Ä\82â\82é\81I");
             mongone(guard);
             return;
         }
@@ -419,9 +482,10 @@ invault()
             nomul(0);
             unmul((char *) 0);
         }
+        buf[0] = '\0';
         trycount = 5;
         do {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             getlin(Deaf ? "You are required to supply your name. -"
                         : "\"Hello stranger, who are you?\" -", buf);
 #else
@@ -441,32 +505,40 @@ invault()
             adjalign(-1); /* Liar! */
         }
 
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos")
-            || !strcmpi(buf, "Creosote")) {
+            || !strcmpi(buf, "Creosote")) { /* Discworld */
 #else
-    if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos")
-        || !strcmpi(buf, "Creosote")
-        || !strcmp(buf, "\83N\83\8d\83C\83\\83X") || !strcmp(buf, "\83N\83\8c\83I\83\\81[\83g")) {
+        if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos")
+            || !strcmpi(buf, "Creosote") /* Discworld */
+            || !strcmp(buf, "\83N\83\8d\83C\83\\83X") || !strcmp(buf, "\83N\83\8c\83I\83\\81[\83g")) {
 #endif
             if (!mvitals[PM_CROESUS].died) {
                 if (Deaf) {
                     if (!Blind)
+/*JP
                         pline("%s waves goodbye.", noit_Monnam(guard));
+*/
+                        pline("%s\82Í\82³\82æ\82È\82ç\82Æ\8eè\82ð\90U\82Á\82½\81D", noit_Monnam(guard));
                 } else {
                     verbalize(
 /*JP
-                    "Oh, yes, of course.  Sorry to have disturbed you.");
+                         "Oh, yes, of course.  Sorry to have disturbed you.");
 */
-                    "\82¢\82â\81C\82±\82è\82á\81C\82¦\81[\82Æ\81C\82¨\91\9b\82ª\82¹\82µ\82Ü\82µ\82½\81D");
+                         "\82¢\82â\81C\82±\82è\82á\81C\82¦\81[\82Æ\81C\82¨\91\9b\82ª\82¹\82µ\82Ü\82µ\82½\81D");
                 }
                 mongone(guard);
             } else {
                 setmangry(guard, FALSE);
                 if (Deaf) {
                    if (!Blind)
+#if 0 /*JP:T*/
                         pline("%s mouths something and looks very angry!",
                               noit_Monnam(guard));
+#else
+                        pline("%s\82Í\89½\82©\82ð\8c¾\82Á\82Ä\82¢\82é\81D\82Æ\82Ä\82à\93{\82Á\82Ä\82¢\82é\82æ\82¤\82¾\81I",
+                              noit_Monnam(guard));
+#endif
                 } else {
 #if 0 /*JP:T*/
                    verbalize(
@@ -485,51 +557,72 @@ invault()
             return;
         }
         if (Deaf)
+#if 0 /*JP:T*/
             pline("%s doesn't %srecognize you.", noit_Monnam(guard),
                     (Blind) ? "" : "appear to ");
+#else
+            pline("%s\82Í\82 \82È\82½\82Ì\82±\82Æ\82ª\95ª\82©\82ç\82È\82¢\82æ\82¤\82¾\81D", noit_Monnam(guard));
+#endif
         else
 /*JP
-        verbalize("I don't know you.");
+            verbalize("I don't know you.");
 */
-        verbalize("\92m\82ç\82ñ\82È\81D");
+            verbalize("\92m\82ç\82ñ\82È\81D");
         umoney = money_cnt(invent);
         if (!umoney && !hidden_gold()) {
             if (Deaf)
+#if 0 /*JP:T*/
                 pline("%s stomps%s.", noit_Monnam(guard),
                       (Blind) ? "" : " and beckons");
+#else
+                pline("%s\82Í\91«\82ð\93¥\82Ý\96Â\82ç\82µ%s\82½\81D", noit_Monnam(guard),
+                      (Blind) ? "" : "\82Ä\8eè\8fµ\82«\82µ");
+#endif
             else
 /*JP
-            verbalize("Please follow me.");
+                verbalize("Please follow me.");
 */
-            verbalize("\8e\84\82Ì\8cã\82É\82Â\82¢\82Ä\82«\82È\82³\82¢\81D");
+                verbalize("\8e\84\82Ì\8cã\82É\82Â\82¢\82Ä\82«\82È\82³\82¢\81D");
         } else {
             if (!umoney) {
                 if (Deaf) {
                     if (!Blind)
+#if 0 /*JP:T*/
                         pline("%s glares at you%s.", noit_Monnam(guard),
                               invent ? "r stuff" : "");
+#else
+                        pline("%s\82Í\82 \82È\82½%s\82ð\82É\82ç\82Ý\82Â\82¯\82½\81D", noit_Monnam(guard),
+                              invent ? "\82Ì\8e\9d\82¿\95¨" : "");
+#endif
                 } else {
 /*JP
-                verbalize("You have hidden gold.");
+                   verbalize("You have hidden gold.");
 */
-                verbalize("\82Ü\82¾\8bà\89Ý\82ð\89B\82µ\82Ä\82é\82È\81D");
+                   verbalize("\82Ü\82¾\8bà\89Ý\82ð\89B\82µ\82Ä\82é\82È\81D");
                 }
             }
             if (Deaf) {
                 if (!Blind)
+#if 0 /*JP:T*/
                     pline(
                        "%s holds out %s palm and beckons with %s other hand.",
-                          noit_Monnam(guard), mhis(guard), mhis(guard));
+                          noit_Monnam(guard), noit_mhis(guard),
+                          noit_mhis(guard));
+#else
+                    pline(
+                       "%s\82Í\95Ð\8eè\82ð\8d·\82µ\8fo\82µ\81C\82à\82¤\95Ð\8eè\82Å\8eè\8fµ\82«\82µ\82½\81D",
+                          noit_Monnam(guard));
+#endif
             } else {
                 verbalize(
 /*JP
-                "Most likely all your gold was stolen from this vault.");
+                    "Most likely all your gold was stolen from this vault.");
 */
-                "\91q\8cÉ\82©\82ç\93\90\82ñ\82¾\8bà\89Ý\82ª\82 \82é\82¾\82ë\82¤\81D");
+                    "\91q\8cÉ\82©\82ç\93\90\82ñ\82¾\8bà\89Ý\82ª\82 \82é\82¾\82ë\82¤\81D");
 /*JP
-            verbalize("Please drop that gold and follow me.");
+                verbalize("Please drop that gold and follow me.");
 */
-            verbalize("\82»\82ê\82ð\82»\82Á\82­\82è\96ß\82µ\82Ä\82©\82ç\81C\8e\84\82Ì\8cã\82É\82Â\82¢\82Ä\82«\82È\82³\82¢\81D");
+                verbalize("\82»\82ê\82ð\82»\82Á\82­\82è\96ß\82µ\82Ä\82©\82ç\81C\8e\84\82Ì\8cã\82É\82Â\82¢\82Ä\82«\82È\82³\82¢\81D");
             }
         }
         EGD(guard)->gdx = gx;
@@ -537,9 +630,9 @@ invault()
         EGD(guard)->fcbeg = 0;
         EGD(guard)->fakecorr[0].fx = x;
         EGD(guard)->fakecorr[0].fy = y;
-        if (IS_WALL(levl[x][y].typ))
+        if (IS_WALL(levl[x][y].typ)) {
             EGD(guard)->fakecorr[0].ftyp = levl[x][y].typ;
-        else { /* the initial guard location is a dug door */
+        else { /* the initial guard location is a dug door */
             int vlt = EGD(guard)->vroom;
             xchar lowx = rooms[vlt].lx, hix = rooms[vlt].hx;
             xchar lowy = rooms[vlt].ly, hiy = rooms[vlt].hy;
@@ -661,6 +754,120 @@ struct monst *grd;
     }
 }
 
+STATIC_OVL void
+gd_mv_monaway(grd, nx, ny)
+register struct monst *grd;
+int nx, ny;
+{
+    if (MON_AT(nx, ny) && !(nx == grd->mx && ny == grd->my)) {
+        if (!Deaf)
+/*JP
+            verbalize("Out of my way, scum!");
+*/
+            verbalize("\96Ú\82Ì\91O\82©\82ç\8fÁ\82¦\82ë\81C\83N\83\\82Á\82½\82ê\81I");
+        if (!rloc(m_at(nx, ny), FALSE) || MON_AT(nx, ny))
+            m_into_limbo(m_at(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");
+#if 0 /*JP:T*/
+        pline("%s%s picks up the gold%s.", monnambuf,
+              (grd->mpeaceful && EGD(grd)->warncnt > 5)
+                 ? " calms down and" : "",
+              under_u ? " from beneath you" : "");
+#else
+        pline("%s\82Í%s%s\8bà\89Ý\82ð\8fE\82Á\82½\81D", monnambuf,
+              (grd->mpeaceful && EGD(grd)->warncnt > 5)
+                 ? "\93{\82è\82ð\90Ã\82ß" : "",
+              under_u ? "\82 \82È\82½\82Ì\91«\8c³\82Ì" : "");
+#endif
+    }
+
+    /* 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
  */
@@ -669,35 +876,38 @@ gd_move(grd)
 register struct monst *grd;
 {
     int x, y, nx, ny, m, n;
-    int dx, dy, gx, gy, fci;
+    int dx, dy, gx = 0, gy = 0, fci;
     uchar typ;
+    struct rm *crm;
     struct fakecorridor *fcp;
     register struct egd *egrd = EGD(grd);
-    struct rm *crm;
-    boolean goldincorridor = FALSE,
-            u_in_vault = vault_occupied(u.urooms) ? TRUE : FALSE,
-            grd_in_vault = *in_rooms(grd->mx, grd->my, VAULT) ? TRUE : FALSE;
-    boolean disappear_msg_seen = FALSE, semi_dead = (grd->mhp <= 0);
-    long umoney = money_cnt(invent);
-    register boolean u_carry_gold = ((umoney + hidden_gold()) > 0L);
-    boolean see_guard, newspot = FALSE;
+    long umoney = 0L;
+    boolean goldincorridor = FALSE, u_in_vault = FALSE, grd_in_vault = FALSE,
+            disappear_msg_seen = FALSE, semi_dead = DEADMONSTER(grd),
+            u_carry_gold = FALSE, newspot = FALSE, see_guard;
 
     if (!on_level(&(egrd->gdlevel), &u.uz))
         return -1;
     nx = ny = m = n = 0;
+    if (semi_dead || !grd->mx || egrd->gddone) {
+        egrd->gddone = 1;
+        goto cleanup;
+    }
+    debugpline1("gd_move: %s guard", grd->mpeaceful ? "peaceful" : "hostile");
+
+    u_in_vault = vault_occupied(u.urooms) ? TRUE : FALSE;
+    grd_in_vault = *in_rooms(grd->mx, grd->my, VAULT) ? TRUE : FALSE;
     if (!u_in_vault && !grd_in_vault)
         wallify_vault(grd);
+
     if (!grd->mpeaceful) {
-        if (semi_dead) {
-            egrd->gddone = 1;
-            goto newpos;
-        }
         if (!u_in_vault
             && (grd_in_vault || (in_fcorridor(grd, grd->mx, grd->my)
                                  && !in_fcorridor(grd, u.ux, u.uy)))) {
-            (void) rloc(grd, FALSE);
+            (void) rloc(grd, TRUE);
             wallify_vault(grd);
-            (void) clear_fcorr(grd, TRUE);
+            if (!in_fcorridor(grd, grd->mx, grd->my))
+                (void) clear_fcorr(grd, TRUE);
             goto letknow;
         }
         if (!in_fcorridor(grd, grd->mx, grd->my))
@@ -709,7 +919,7 @@ register struct monst *grd;
 
     if (egrd->witness) {
         if (!Deaf)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             verbalize("How dare you %s that gold, scoundrel!",
                       (egrd->witness & GD_EATGOLD) ? "consume" : "destroy");
 #else
@@ -720,10 +930,13 @@ register struct monst *grd;
         grd->mpeaceful = 0;
         return -1;
     }
+
+    umoney = money_cnt(invent);
+    u_carry_gold = umoney > 0L || hidden_gold() > 0L;
     if (egrd->fcend == 1) {
         if (u_in_vault && (u_carry_gold || um_dist(grd->mx, grd->my, 1))) {
             if (egrd->warncnt == 3 && !Deaf)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 verbalize("I repeat, %sfollow me!",
                           u_carry_gold
                               ? (!umoney ? "drop that hidden money and "
@@ -764,14 +977,21 @@ register struct monst *grd;
                 levl[m][n].typ = egrd->fakecorr[0].ftyp;
                 newsym(m, n);
                 grd->mpeaceful = 0;
           letknow:
+ letknow:
                 if (!cansee(grd->mx, grd->my) || !mon_visible(grd))
-/*JP
-                    You_hear("the shrill sound of a guard's whistle.");
-*/
-                    You_hear("\94Ô\95º\82Ì\89s\82¢\93J\82Ì\89¹\82ð\95·\82¢\82½\81D");
+#if 0 /*JP:T*/
+                    You_hear("%s.",
+                             m_carrying(grd, TIN_WHISTLE)
+                                 ? "the shrill sound of a guard's whistle"
+                                 : "angry shouting");
+#else
+                    You_hear("%s\82ð\95·\82¢\82½\81D",
+                             m_carrying(grd, TIN_WHISTLE)
+                                 ? "\94Ô\95º\82Ì\89s\82¢\93J\82Ì\89¹"
+                                 : "\93{\82è\82Ì\8b©\82Ñ");
+#endif
                 else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                     You(um_dist(grd->mx, grd->my, 2)
                             ? "see %s approaching."
                             : "are confronted by %s.",
@@ -790,7 +1010,6 @@ register struct monst *grd;
                     verbalize("Well, begone.");
 */
                     verbalize("\97§\82¿\8b\8e\82ê\81D");
-                wallify_vault(grd);
                 egrd->gddone = 1;
                 goto cleanup;
             }
@@ -820,8 +1039,13 @@ register struct monst *grd;
                 egrd->warncnt = 6;
                 if (Deaf) {
                     if (!Blind)
+#if 0 /*JP:T*/
                         pline("%s holds out %s palm demandingly!",
-                              noit_Monnam(grd), mhis(grd));
+                              noit_Monnam(grd), noit_mhis(grd));
+#else
+                        pline("%s\82Í\8cµ\82µ\82¢\92²\8eq\82Å\8eè\82Ì\82Ð\82ç\82ð\8d·\82µ\8fo\82µ\82½\81I",
+                              noit_Monnam(grd));
+#endif
                 } else {
 /*JP
                     verbalize("Drop all your gold, scoundrel!");
@@ -832,8 +1056,13 @@ register struct monst *grd;
             } else {
                 if (Deaf) {
                     if (!Blind)
+#if 0 /*JP:T*/
                         pline("%s rubs %s hands with enraged delight!",
-                              noit_Monnam(grd), mhis(grd));
+                              noit_Monnam(grd), noit_mhis(grd));
+#else
+                        pline("%s\82Í\93{\82è\82È\82ª\82ç\8eè\82ð\82·\82è\82 \82í\82¹\82½\81I",
+                              noit_Monnam(grd));
+#endif
                 } else {
 /*JP
                     verbalize("So be it, rogue!");
@@ -850,47 +1079,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... */
-            if (MON_AT(m, n) && m != grd->mx && n != grd->my) {
-                if (!Deaf)
-/*JP
-                    verbalize("Out of my way, scum!");
-*/
-                    verbalize("\96Ú\82Ì\91O\82©\82ç\8fÁ\82¦\82ë\81C\83N\83\\82Á\82½\82ê\81I");
-                (void) rloc(m_at(m, n), FALSE);
-            }
-            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))
-#if 0 /*JP*/
-            pline("%s%s picks up the gold.", Monnam(grd),
-                  grd->mpeaceful ? " calms down and" : "");
-#else
-            pline("%s\82Í%s\8bà\89Ý\82ð\8fE\82Á\82½\81D", Monnam(grd),
-                  grd->mpeaceful ? "\93{\82è\82ð\90Ã\82ß" : "");
-#endif
-        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;
@@ -942,10 +1136,10 @@ register struct monst *grd;
                     goto proceed;
                 }
             }
       nextnxy:
+ nextnxy:
             ;
         }
-nextpos:
+ nextpos:
     nx = x;
     ny = y;
     gx = egrd->gdx;
@@ -986,19 +1180,34 @@ nextpos:
         break;
     }
     crm->typ = CORR;
-proceed:
+ proceed:
     newspot = TRUE;
     unblock_point(nx, ny); /* doesn't block light */
     if (cansee(nx, ny))
         newsym(nx, ny);
 
-    fcp = &(egrd->fakecorr[egrd->fcend]);
-    if (egrd->fcend++ == FCSIZ)
-        panic("fakecorr overflow");
-    fcp->fx = nx;
-    fcp->fy = ny;
-    fcp->ftyp = typ;
-newpos:
+    if ((nx != gx || ny != gy) || (grd->mx != gx || grd->my != gy)) {
+        fcp = &(egrd->fakecorr[egrd->fcend]);
+        if (egrd->fcend++ == FCSIZ)
+            panic("fakecorr overflow");
+        fcp->fx = nx;
+        fcp->fy = ny;
+        fcp->ftyp = typ;
+    } else if (!egrd->gddone) {
+        /* We're stuck, so try to find a new destination. */
+        if (!find_guard_dest(grd, &egrd->gdx, &egrd->gdy)
+            || (egrd->gdx == gx && egrd->gdy == gy)) {
+/*JP
+            pline("%s, confused, disappears.", Monnam(grd));
+*/
+            pline("%s\82Í\8d¬\97\90\82µ\81C\8fÁ\82¦\82½\81D", Monnam(grd));
+            disappear_msg_seen = TRUE;
+            goto cleanup;
+        } else
+            goto nextpos;
+    }
+ newpos:
+    gd_mv_monaway(grd, nx, ny);
     if (egrd->gddone) {
         /* The following is a kludge.  We need to keep    */
         /* the guard around in order to be able to make   */
@@ -1009,18 +1218,15 @@ newpos:
         /* to avoid a check at the top of this function.  */
         /* At the end of the process, the guard is killed */
         /* in restfakecorr().                             */
-    cleanup:
-        x = grd->mx;
-        y = grd->my;
-
+ cleanup:
+        x = grd->mx, y = grd->my;
         see_guard = canspotmon(grd);
+        parkguard(grd); /* move to <0,0> */
         wallify_vault(grd);
-        remove_monster(grd->mx, grd->my);
-        newsym(grd->mx, grd->my);
-        place_monster(grd, 0, 0);
-        egrd->ogx = grd->mx;
-        egrd->ogy = grd->my;
         restfakecorr(grd);
+        debugpline2("gd_move: %scleanup%s",
+                    grd->isgd ? "" : "final ",
+                    grd->isgd ? " attempt" : "");
         if (!semi_dead && (in_fcorridor(grd, u.ux, u.uy) || cansee(x, y))) {
             if (!disappear_msg_seen && see_guard)
 /*JP
@@ -1053,7 +1259,8 @@ newpos:
 
 /* Routine when dying or quitting with a vault guard around */
 void
-paygd()
+paygd(silently)
+boolean silently;
 {
     register struct monst *grd = findgd();
     long umoney = money_cnt(invent);
@@ -1065,28 +1272,29 @@ paygd()
         return;
 
     if (u.uinvault) {
-#if 0 /*JP*/
-        Your("%ld %s goes into the Magic Memory Vault.", umoney,
-             currency(umoney));
+        if (!silently)
+#if 0 /*JP:T*/
+            Your("%ld %s goes into the Magic Memory Vault.",
+                 umoney, currency(umoney));
 #else
-        Your("%ld%s\82Í\96\82\96@\82Ì\8bL\94O\91q\8cÉ\82É\93ü\82Á\82½\81D", umoney,
-             currency(umoney));
+            Your("%ld%s\82Í\96\82\96@\82Ì\8bL\94O\91q\8cÉ\82É\93ü\82Á\82½\81D",
+                 umoney, currency(umoney));
 #endif
         gx = u.ux;
         gy = u.uy;
     } else {
-        if (grd->mpeaceful) { /* guard has no "right" to your gold */
-            mongone(grd);
-            return;
-        }
+        if (grd->mpeaceful) /* peaceful guard has no "right" to your gold */
+            goto remove_guard;
+
         mnexto(grd);
+        if (!silently)
 /*JP
-        pline("%s remits your gold to the vault.", Monnam(grd));
+            pline("%s remits your gold to the vault.", Monnam(grd));
 */
-        pline("%s\82Í\82 \82È\82½\82Ì\8bà\89Ý\82ð\91q\8cÉ\82É\91\97\82Á\82½\81D", Monnam(grd));
+            pline("%s\82Í\82 \82È\82½\82Ì\8bà\89Ý\82ð\91q\8cÉ\82É\91\97\82Á\82½\81D", Monnam(grd));
         gx = rooms[EGD(grd)->vroom].lx + rn2(2);
         gy = rooms[EGD(grd)->vroom].ly + rn2(2);
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         Sprintf(buf, "To Croesus: here's the gold recovered from %s the %s.",
                 plname, mons[u.umonster].mname);
 #else
@@ -1103,7 +1311,9 @@ paygd()
             stackobj(coins);
         }
     }
+ remove_guard:
     mongone(grd);
+    return;
 }
 
 long