OSDN Git Service

version++
[jnethack/source.git] / src / vault.c
1 /* NetHack 3.6  vault.c $NHDT-Date: 1446078792 2015/10/29 00:33:12 $  $NHDT-Branch: master $:$NHDT-Revision: 1.39 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016            */
8 /* JNetHack may be freely redistributed.  See license for details. */
9
10 #include "hack.h"
11
12 STATIC_DCL struct monst *NDECL(findgd);
13
14 STATIC_DCL boolean FDECL(clear_fcorr, (struct monst *, BOOLEAN_P));
15 STATIC_DCL void FDECL(blackout, (int, int));
16 STATIC_DCL void FDECL(restfakecorr, (struct monst *));
17 STATIC_DCL boolean FDECL(in_fcorridor, (struct monst *, int, int));
18 STATIC_DCL void FDECL(move_gold, (struct obj *, int));
19 STATIC_DCL void FDECL(wallify_vault, (struct monst *));
20
21 void
22 newegd(mtmp)
23 struct monst *mtmp;
24 {
25     if (!mtmp->mextra)
26         mtmp->mextra = newmextra();
27     if (!EGD(mtmp)) {
28         EGD(mtmp) = (struct egd *) alloc(sizeof(struct egd));
29         (void) memset((genericptr_t) EGD(mtmp), 0, sizeof(struct egd));
30     }
31 }
32
33 void
34 free_egd(mtmp)
35 struct monst *mtmp;
36 {
37     if (mtmp->mextra && EGD(mtmp)) {
38         free((genericptr_t) EGD(mtmp));
39         EGD(mtmp) = (struct egd *) 0;
40     }
41     mtmp->isgd = 0;
42 }
43
44 STATIC_OVL boolean
45 clear_fcorr(grd, forceshow)
46 struct monst *grd;
47 boolean forceshow;
48 {
49     register int fcx, fcy, fcbeg;
50     struct monst *mtmp;
51     boolean sawcorridor = FALSE;
52     struct egd *egrd = EGD(grd);
53     struct trap *trap;
54     struct rm *lev;
55
56     if (!on_level(&egrd->gdlevel, &u.uz))
57         return TRUE;
58
59     while ((fcbeg = egrd->fcbeg) < egrd->fcend) {
60         fcx = egrd->fakecorr[fcbeg].fx;
61         fcy = egrd->fakecorr[fcbeg].fy;
62         if ((grd->mhp <= 0 || !in_fcorridor(grd, u.ux, u.uy)) && egrd->gddone)
63             forceshow = TRUE;
64         if ((u.ux == fcx && u.uy == fcy && grd->mhp > 0)
65             || (!forceshow && couldsee(fcx, fcy))
66             || (Punished && !carried(uball) && uball->ox == fcx
67                 && uball->oy == fcy))
68             return FALSE;
69
70         if ((mtmp = m_at(fcx, fcy)) != 0) {
71             if (mtmp->isgd) {
72                 return FALSE;
73             } else if (!in_fcorridor(grd, u.ux, u.uy)) {
74                 if (mtmp->mtame)
75                     yelp(mtmp);
76                 (void) rloc(mtmp, FALSE);
77             }
78         }
79         lev = &levl[fcx][fcy];
80         if (lev->typ == CORR && cansee(fcx, fcy))
81             sawcorridor = TRUE;
82         lev->typ = egrd->fakecorr[fcbeg].ftyp;
83         if (IS_STWALL(lev->typ)) {
84             /* destroy any trap here (pit dug by you, hole dug via
85                wand while levitating or by monster, bear trap or land
86                mine via object, spun web) when spot reverts to stone */
87             if ((trap = t_at(fcx, fcy)) != 0)
88                 deltrap(trap);
89             /* undo scroll/wand/spell of light affecting this spot */
90             if (lev->typ == STONE)
91                 blackout(fcx, fcy);
92         }
93         map_location(fcx, fcy, 1); /* bypass vision */
94         if (!ACCESSIBLE(lev->typ))
95             block_point(fcx, fcy);
96         vision_full_recalc = 1;
97         egrd->fcbeg++;
98     }
99     if (sawcorridor)
100 /*JP
101         pline_The("corridor disappears.");
102 */
103         pline("\92Ê\98H\82Í\8fÁ\82¦\82½\81D");
104     if (IS_ROCK(levl[u.ux][u.uy].typ))
105 /*JP
106         You("are encased in rock.");
107 */
108         You("\90Î\82É\82Â\82Â\82Ü\82ê\82½\81D");
109     return TRUE;
110 }
111
112 /* as a temporary corridor is removed, set stone locations and adjacent
113    spots to unlit; if player used scroll/wand/spell of light while inside
114    the corridor, we don't want the light to reappear if/when a new tunnel
115    goes through the same area */
116 STATIC_OVL void
117 blackout(x, y)
118 int x, y;
119 {
120     struct rm *lev;
121     int i, j;
122
123     for (i = x - 1; i <= x + 1; ++i)
124         for (j = y - 1; j <= y + 1; ++j) {
125             if (!isok(i, j))
126                 continue;
127             lev = &levl[i][j];
128             /* [possible bug: when (i != x || j != y), perhaps we ought
129                to check whether the spot on the far side is lit instead
130                of doing a blanket blackout of adjacent locations] */
131             if (lev->typ == STONE)
132                 lev->lit = lev->waslit = 0;
133             /* mark <i,j> as not having been seen from <x,y> */
134             unset_seenv(lev, x, y, i, j);
135         }
136 }
137
138 STATIC_OVL void
139 restfakecorr(grd)
140 struct monst *grd;
141 {
142     /* it seems you left the corridor - let the guard disappear */
143     if (clear_fcorr(grd, FALSE)) {
144         grd->isgd = 0; /* dmonsfree() should delete this mon */
145         mongone(grd);
146     }
147 }
148
149 /* called in mon.c */
150 boolean
151 grddead(grd)
152 struct monst *grd;
153 {
154     boolean dispose = clear_fcorr(grd, TRUE);
155
156     if (!dispose) {
157         /* destroy guard's gold; drop any other inventory */
158         relobj(grd, 0, FALSE);
159         /* guard is dead; monster traversal loops should skip it */
160         grd->mhp = 0;
161         if (grd == context.polearm.hitmon)
162             context.polearm.hitmon = 0;
163         /* see comment by newpos in gd_move() */
164         remove_monster(grd->mx, grd->my);
165         newsym(grd->mx, grd->my);
166         place_monster(grd, 0, 0);
167         EGD(grd)->ogx = grd->mx;
168         EGD(grd)->ogy = grd->my;
169         dispose = clear_fcorr(grd, TRUE);
170     }
171     if (dispose)
172         grd->isgd = 0; /* for dmonsfree() */
173     return dispose;
174 }
175
176 STATIC_OVL boolean
177 in_fcorridor(grd, x, y)
178 struct monst *grd;
179 int x, y;
180 {
181     register int fci;
182     struct egd *egrd = EGD(grd);
183
184     for (fci = egrd->fcbeg; fci < egrd->fcend; fci++)
185         if (x == egrd->fakecorr[fci].fx && y == egrd->fakecorr[fci].fy)
186             return TRUE;
187     return FALSE;
188 }
189
190 STATIC_OVL
191 struct monst *
192 findgd()
193 {
194     register struct monst *mtmp;
195
196     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
197         if (DEADMONSTER(mtmp))
198             continue;
199         if (mtmp->isgd && on_level(&(EGD(mtmp)->gdlevel), &u.uz))
200             return mtmp;
201     }
202     return (struct monst *) 0;
203 }
204
205 char
206 vault_occupied(array)
207 char *array;
208 {
209     register char *ptr;
210
211     for (ptr = array; *ptr; ptr++)
212         if (rooms[*ptr - ROOMOFFSET].rtype == VAULT)
213             return *ptr;
214     return '\0';
215 }
216
217 void
218 invault()
219 {
220 #ifdef BSD_43_BUG
221     int dummy; /* hack to avoid schain botch */
222 #endif
223     struct monst *guard;
224     boolean gsensed;
225     int trycount, vaultroom = (int) vault_occupied(u.urooms);
226
227     if (!vaultroom) {
228         u.uinvault = 0;
229         return;
230     }
231
232     vaultroom -= ROOMOFFSET;
233
234     guard = findgd();
235     if (++u.uinvault % 30 == 0 && !guard) { /* if time ok and no guard now. */
236         char buf[BUFSZ];
237         register int x, y, dd, gx, gy;
238         int lx = 0, ly = 0;
239         long umoney;
240
241         /* first find the goal for the guard */
242         for (dd = 2; (dd < ROWNO || dd < COLNO); dd++) {
243             for (y = u.uy - dd; y <= u.uy + dd; ly = y, y++) {
244                 if (y < 0 || y > ROWNO - 1)
245                     continue;
246                 for (x = u.ux - dd; x <= u.ux + dd; lx = x, x++) {
247                     if (y != u.uy - dd && y != u.uy + dd && x != u.ux - dd)
248                         x = u.ux + dd;
249                     if (x < 1 || x > COLNO - 1)
250                         continue;
251                     if (levl[x][y].typ == CORR) {
252                         if (x < u.ux)
253                             lx = x + 1;
254                         else if (x > u.ux)
255                             lx = x - 1;
256                         else
257                             lx = x;
258                         if (y < u.uy)
259                             ly = y + 1;
260                         else if (y > u.uy)
261                             ly = y - 1;
262                         else
263                             ly = y;
264                         if (levl[lx][ly].typ != STONE
265                             && levl[lx][ly].typ != CORR)
266                             goto incr_radius;
267                         goto fnd;
268                     }
269                 }
270             }
271         incr_radius:
272             ;
273         }
274         impossible("Not a single corridor on this level??");
275         tele();
276         return;
277     fnd:
278         gx = x;
279         gy = y;
280
281         /* next find a good place for a door in the wall */
282         x = u.ux;
283         y = u.uy;
284         if (levl[x][y].typ != ROOM) { /* player dug a door and is in it */
285             if (levl[x + 1][y].typ == ROOM)
286                 x = x + 1;
287             else if (levl[x][y + 1].typ == ROOM)
288                 y = y + 1;
289             else if (levl[x - 1][y].typ == ROOM)
290                 x = x - 1;
291             else if (levl[x][y - 1].typ == ROOM)
292                 y = y - 1;
293             else if (levl[x + 1][y + 1].typ == ROOM) {
294                 x = x + 1;
295                 y = y + 1;
296             } else if (levl[x - 1][y - 1].typ == ROOM) {
297                 x = x - 1;
298                 y = y - 1;
299             } else if (levl[x + 1][y - 1].typ == ROOM) {
300                 x = x + 1;
301                 y = y - 1;
302             } else if (levl[x - 1][y + 1].typ == ROOM) {
303                 x = x - 1;
304                 y = y + 1;
305             }
306         }
307         while (levl[x][y].typ == ROOM) {
308             register int dx, dy;
309
310             dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
311             dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
312             if (abs(gx - x) >= abs(gy - y))
313                 x += dx;
314             else
315                 y += dy;
316         }
317         if (x == u.ux && y == u.uy) {
318             if (levl[x + 1][y].typ == HWALL || levl[x + 1][y].typ == DOOR)
319                 x = x + 1;
320             else if (levl[x - 1][y].typ == HWALL
321                      || levl[x - 1][y].typ == DOOR)
322                 x = x - 1;
323             else if (levl[x][y + 1].typ == VWALL
324                      || levl[x][y + 1].typ == DOOR)
325                 y = y + 1;
326             else if (levl[x][y - 1].typ == VWALL
327                      || levl[x][y - 1].typ == DOOR)
328                 y = y - 1;
329             else
330                 return;
331         }
332
333         /* make something interesting happen */
334         if (!(guard = makemon(&mons[PM_GUARD], x, y, MM_EGD)))
335             return;
336         guard->isgd = 1;
337         guard->mpeaceful = 1;
338         set_malign(guard);
339         EGD(guard)->gddone = 0;
340         EGD(guard)->ogx = x;
341         EGD(guard)->ogy = y;
342         assign_level(&(EGD(guard)->gdlevel), &u.uz);
343         EGD(guard)->vroom = vaultroom;
344         EGD(guard)->warncnt = 0;
345
346         reset_faint(); /* if fainted - wake up */
347         gsensed = !canspotmon(guard);
348         if (!gsensed)
349 #if 0 /*JP*/
350             pline("Suddenly one of the Vault's %s enters!",
351                   makeplural(guard->data->mname));
352 #else
353             pline("\93Ë\91R\81C\91q\8cÉ\82Ì\94Ô\95º\82ª\93ü\82Á\82Ä\82«\82½\81I");
354 #endif
355         else
356 /*JP
357             pline("Someone else has entered the Vault.");
358 */
359             pline("\92N\82©\82ª\91q\8cÉ\82É\93ü\82Á\82Ä\82«\82½\81D");
360         newsym(guard->mx, guard->my);
361         if (u.uswallow) {
362             /* can't interrogate hero, don't interrogate engulfer */
363 /*JP
364             verbalize("What's going on here?");
365 */
366             verbalize("\82±\82±\82Å\89½\82ð\82µ\82Ä\82¢\82é\82ñ\82¾\81H");
367             if (gsensed)
368 /*JP
369                 pline_The("other presence vanishes.");
370 */
371                 pline("\91¼\90l\82Ì\8bC\94z\82Í\8fÁ\82¦\82½\81D");
372             mongone(guard);
373             return;
374         }
375         if (youmonst.m_ap_type == M_AP_OBJECT || u.uundetected) {
376             if (youmonst.m_ap_type == M_AP_OBJECT
377                 && youmonst.mappearance != GOLD_PIECE)
378 /*JP
379                 verbalize("Hey! Who left that %s in here?",
380 */
381                 verbalize("\82¨\82¢\81I\82¾\82ê\82ª\82±\82Ì%s\82ð\82±\82±\82É\92u\82¢\82Ä\8ds\82Á\82½\82ñ\82¾\81H",
382                           mimic_obj_name(&youmonst));
383             /* You're mimicking some object or you're hidden. */
384 /*JP
385             pline("Puzzled, %s turns around and leaves.", mhe(guard));
386 */
387             pline("%s\82Í\8d¢\98f\82µ\82È\82ª\82ç\81C\8cü\82«\92¼\82Á\82Ä\8b\8e\82Á\82Ä\82¢\82Á\82½\81D", mhe(guard));
388             mongone(guard);
389             return;
390         }
391         if (Strangled || is_silent(youmonst.data) || multi < 0) {
392             /* [we ought to record whether this this message has already
393                been given in order to vary it upon repeat visits, but
394                discarding the monster and its egd data renders that hard] */
395 /*JP
396             verbalize("I'll be back when you're ready to speak to me!");
397 */
398             verbalize("\98b\82¹\82é\82æ\82¤\82É\82È\82Á\82½\82ç\96ß\82Á\82Ä\82«\82Ä\82â\82é\81I");
399             mongone(guard);
400             return;
401         }
402
403         stop_occupation(); /* if occupied, stop it *now* */
404         if (multi > 0) {
405             nomul(0);
406             unmul((char *) 0);
407         }
408         trycount = 5;
409         do {
410 /*JP
411             getlin("\"Hello stranger, who are you?\" -", buf);
412 */
413             getlin("\81u\8c©\82È\82¢\8aç\82¾\82È\81C\82¨\82Ü\82¦\82Í\92N\82¾\81H\81v-", buf);
414             (void) mungspaces(buf);
415 #if 0 /*JP*/
416         } while (!letter(buf[0]) && --trycount > 0);
417 #else
418         } while (!letter(buf[0]) && !is_kanji(buf[0]) && --trycount > 0);
419 #endif
420
421         if (u.ualign.type == A_LAWFUL
422             /* ignore trailing text, in case player includes rank */
423             && strncmpi(buf, plname, (int) strlen(plname)) != 0) {
424             adjalign(-1); /* Liar! */
425         }
426
427 #if 0 /*JP*/
428         if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos")
429             || !strcmpi(buf, "Creosote")) {
430 #else
431     if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos")
432         || !strcmpi(buf, "Creosote")
433         || !strcmp(buf, "\83N\83\8d\83C\83\\83X") || !strcmp(buf, "\83N\83\8c\83I\83\\81[\83g")) {
434 #endif
435             if (!mvitals[PM_CROESUS].died) {
436                 verbalize(
437 /*JP
438                     "Oh, yes, of course.  Sorry to have disturbed you.");
439 */
440                     "\82¢\82â\81C\82±\82è\82á\81C\82¦\81[\82Æ\81C\82¨\91\9b\82ª\82¹\82µ\82Ü\82µ\82½\81D");
441                 mongone(guard);
442             } else {
443                 setmangry(guard);
444 /*JP
445                 verbalize("Back from the dead, are you?  I'll remedy that!");
446 */
447                 verbalize("\82Ù\82¤\81I\8e\80\82Ì\90¢\8aE\82©\82ç\96ß\82Á\82Ä\82«\82½\82Ì\82©\81H\82¤\82»\82È\82ç\8fã\8eè\82É\82Â\82¯\81I");
448                 /* don't want guard to waste next turn wielding a weapon */
449                 if (!MON_WEP(guard)) {
450                     guard->weapon_check = NEED_HTH_WEAPON;
451                     (void) mon_wield_item(guard);
452                 }
453             }
454             return;
455         }
456 /*JP
457         verbalize("I don't know you.");
458 */
459         verbalize("\92m\82ç\82ñ\82È\81D");
460         umoney = money_cnt(invent);
461         if (Deaf) {
462             ;
463         } else if (!umoney && !hidden_gold()) {
464 /*JP
465             verbalize("Please follow me.");
466 */
467             verbalize("\8e\84\82Ì\8cã\82É\82Â\82¢\82Ä\82«\82È\82³\82¢\81D");
468         } else {
469             if (!umoney)
470 /*JP
471                 verbalize("You have hidden gold.");
472 */
473                 verbalize("\82Ü\82¾\8bà\89Ý\82ð\89B\82µ\82Ä\82é\82È\81D");
474             verbalize(
475 /*JP
476                 "Most likely all your gold was stolen from this vault.");
477 */
478                 "\91q\8cÉ\82©\82ç\93\90\82ñ\82¾\8bà\89Ý\82ª\82 \82é\82¾\82ë\82¤\81D");
479 /*JP
480             verbalize("Please drop that gold and follow me.");
481 */
482             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");
483         }
484         EGD(guard)->gdx = gx;
485         EGD(guard)->gdy = gy;
486         EGD(guard)->fcbeg = 0;
487         EGD(guard)->fakecorr[0].fx = x;
488         EGD(guard)->fakecorr[0].fy = y;
489         if (IS_WALL(levl[x][y].typ))
490             EGD(guard)->fakecorr[0].ftyp = levl[x][y].typ;
491         else { /* the initial guard location is a dug door */
492             int vlt = EGD(guard)->vroom;
493             xchar lowx = rooms[vlt].lx, hix = rooms[vlt].hx;
494             xchar lowy = rooms[vlt].ly, hiy = rooms[vlt].hy;
495
496             if (x == lowx - 1 && y == lowy - 1)
497                 EGD(guard)->fakecorr[0].ftyp = TLCORNER;
498             else if (x == hix + 1 && y == lowy - 1)
499                 EGD(guard)->fakecorr[0].ftyp = TRCORNER;
500             else if (x == lowx - 1 && y == hiy + 1)
501                 EGD(guard)->fakecorr[0].ftyp = BLCORNER;
502             else if (x == hix + 1 && y == hiy + 1)
503                 EGD(guard)->fakecorr[0].ftyp = BRCORNER;
504             else if (y == lowy - 1 || y == hiy + 1)
505                 EGD(guard)->fakecorr[0].ftyp = HWALL;
506             else if (x == lowx - 1 || x == hix + 1)
507                 EGD(guard)->fakecorr[0].ftyp = VWALL;
508         }
509         levl[x][y].typ = DOOR;
510         levl[x][y].doormask = D_NODOOR;
511         unblock_point(x, y); /* doesn't block light */
512         EGD(guard)->fcend = 1;
513         EGD(guard)->warncnt = 1;
514     }
515 }
516
517 STATIC_OVL void
518 move_gold(gold, vroom)
519 struct obj *gold;
520 int vroom;
521 {
522     xchar nx, ny;
523
524     remove_object(gold);
525     newsym(gold->ox, gold->oy);
526     nx = rooms[vroom].lx + rn2(2);
527     ny = rooms[vroom].ly + rn2(2);
528     place_object(gold, nx, ny);
529     stackobj(gold);
530     newsym(nx, ny);
531 }
532
533 STATIC_OVL void
534 wallify_vault(grd)
535 struct monst *grd;
536 {
537     int x, y, typ;
538     int vlt = EGD(grd)->vroom;
539     char tmp_viz;
540     xchar lox = rooms[vlt].lx - 1, hix = rooms[vlt].hx + 1,
541           loy = rooms[vlt].ly - 1, hiy = rooms[vlt].hy + 1;
542     struct monst *mon;
543     struct obj *gold;
544     struct trap *trap;
545     boolean fixed = FALSE;
546     boolean movedgold = FALSE;
547
548     for (x = lox; x <= hix; x++)
549         for (y = loy; y <= hiy; y++) {
550             /* if not on the room boundary, skip ahead */
551             if (x != lox && x != hix && y != loy && y != hiy)
552                 continue;
553
554             if (!IS_WALL(levl[x][y].typ) && !in_fcorridor(grd, x, y)) {
555                 if ((mon = m_at(x, y)) != 0 && mon != grd) {
556                     if (mon->mtame)
557                         yelp(mon);
558                     (void) rloc(mon, FALSE);
559                 }
560                 if ((gold = g_at(x, y)) != 0) {
561                     move_gold(gold, EGD(grd)->vroom);
562                     movedgold = TRUE;
563                 }
564                 if ((trap = t_at(x, y)) != 0)
565                     deltrap(trap);
566                 if (x == lox)
567                     typ =
568                         (y == loy) ? TLCORNER : (y == hiy) ? BLCORNER : VWALL;
569                 else if (x == hix)
570                     typ =
571                         (y == loy) ? TRCORNER : (y == hiy) ? BRCORNER : VWALL;
572                 else /* not left or right side, must be top or bottom */
573                     typ = HWALL;
574                 levl[x][y].typ = typ;
575                 levl[x][y].doormask = 0;
576                 /*
577                  * hack: player knows walls are restored because of the
578                  * message, below, so show this on the screen.
579                  */
580                 tmp_viz = viz_array[y][x];
581                 viz_array[y][x] = IN_SIGHT | COULD_SEE;
582                 newsym(x, y);
583                 viz_array[y][x] = tmp_viz;
584                 block_point(x, y);
585                 fixed = TRUE;
586             }
587         }
588
589     if (movedgold || fixed) {
590         if (in_fcorridor(grd, grd->mx, grd->my) || cansee(grd->mx, grd->my))
591 /*JP
592             pline("%s whispers an incantation.", noit_Monnam(grd));
593 */
594             pline("%s\82Í\8eô\95\82ð\82³\82³\82â\82¢\82½\81D", noit_Monnam(grd));
595         else
596 /*JP
597             You_hear("a distant chant.");
598 */
599             You_hear("\89\93\95û\82Å\82Ì\8eô\95\82ð\95·\82¢\82½\81D");
600         if (movedgold)
601 /*JP
602             pline("A mysterious force moves the gold into the vault.");
603 */
604             pline("\95s\8ev\8bc\82È\97Í\82ª\8bà\89Ý\82ð\91q\8cÉ\82Ö\89^\82ñ\82¾\81D");
605         if (fixed)
606 /*JP
607             pline_The("damaged vault's walls are magically restored!");
608 */
609             pline("\8f\9d\82Â\82¢\82½\91q\8cÉ\82Ì\95Ç\82Í\96\82\96@\82Å\95\9c\8c³\82³\82ê\82½\81I");
610     }
611 }
612
613 /*
614  * return  1: guard moved,  0: guard didn't,  -1: let m_move do it,  -2: died
615  */
616 int
617 gd_move(grd)
618 register struct monst *grd;
619 {
620     int x, y, nx, ny, m, n;
621     int dx, dy, gx, gy, fci;
622     uchar typ;
623     struct fakecorridor *fcp;
624     register struct egd *egrd = EGD(grd);
625     struct rm *crm;
626     boolean goldincorridor = FALSE,
627             u_in_vault = vault_occupied(u.urooms) ? TRUE : FALSE,
628             grd_in_vault = *in_rooms(grd->mx, grd->my, VAULT) ? TRUE : FALSE;
629     boolean disappear_msg_seen = FALSE, semi_dead = (grd->mhp <= 0);
630     long umoney = money_cnt(invent);
631     register boolean u_carry_gold = ((umoney + hidden_gold()) > 0L);
632     boolean see_guard, newspot = FALSE;
633
634     if (!on_level(&(egrd->gdlevel), &u.uz))
635         return -1;
636     nx = ny = m = n = 0;
637     if (!u_in_vault && !grd_in_vault)
638         wallify_vault(grd);
639     if (!grd->mpeaceful) {
640         if (semi_dead) {
641             egrd->gddone = 1;
642             goto newpos;
643         }
644         if (!u_in_vault
645             && (grd_in_vault || (in_fcorridor(grd, grd->mx, grd->my)
646                                  && !in_fcorridor(grd, u.ux, u.uy)))) {
647             (void) rloc(grd, FALSE);
648             wallify_vault(grd);
649             (void) clear_fcorr(grd, TRUE);
650             goto letknow;
651         }
652         if (!in_fcorridor(grd, grd->mx, grd->my))
653             (void) clear_fcorr(grd, TRUE);
654         return -1;
655     }
656     if (abs(egrd->ogx - grd->mx) > 1 || abs(egrd->ogy - grd->my) > 1)
657         return -1; /* teleported guard - treat as monster */
658
659     if (egrd->witness) {
660 #if 0 /*JP*/
661         verbalize("How dare you %s that gold, scoundrel!",
662                   (egrd->witness & GD_EATGOLD) ? "consume" : "destroy");
663 #else
664         verbalize("\82æ\82­\82à\82Ü\82 \8bà\82ð%s\82à\82Ì\82¾\81C\88«\93}\82ß\81I",
665                   (egrd->witness & GD_EATGOLD) ? "\8eg\82Á\82½" : "\89ó\82µ\82½");
666 #endif
667         egrd->witness = 0;
668         grd->mpeaceful = 0;
669         return -1;
670     }
671     if (egrd->fcend == 1) {
672         if (u_in_vault && (u_carry_gold || um_dist(grd->mx, grd->my, 1))) {
673             if (egrd->warncnt == 3 && !Deaf)
674 #if 0 /*JP*/
675                 verbalize("I repeat, %sfollow me!",
676                           u_carry_gold
677                               ? (!umoney ? "drop that hidden money and "
678                                          : "drop that money and ")
679                               : "");
680 #else
681                 verbalize("\8cJ\82è\95Ô\82·\81I%s\8e\84\82É\82Â\82¢\82Ä\82±\82¢\81I",
682                           u_carry_gold
683                               ? (!umoney ? "\89B\82µ\8e\9d\82Á\82Ä\82é\8bà\82ð\92u\82¢\82Ä"
684                                          : "\8bà\82ð\92u\82¢\82Ä")
685                               : "");
686 #endif
687             if (egrd->warncnt == 7) {
688                 m = grd->mx;
689                 n = grd->my;
690                 if (!Deaf)
691 /*JP
692                     verbalize("You've been warned, knave!");
693 */
694                     verbalize("\8cx\8d\90\82Í\82µ\82½\82¼\81C\88«\93}\82ß\81I");
695                 mnexto(grd);
696                 levl[m][n].typ = egrd->fakecorr[0].ftyp;
697                 newsym(m, n);
698                 grd->mpeaceful = 0;
699                 return -1;
700             }
701             /* not fair to get mad when (s)he's fainted or paralyzed */
702             if (!is_fainted() && multi >= 0)
703                 egrd->warncnt++;
704             return 0;
705         }
706
707         if (!u_in_vault) {
708             if (u_carry_gold) { /* player teleported */
709                 m = grd->mx;
710                 n = grd->my;
711                 (void) rloc(grd, TRUE);
712                 levl[m][n].typ = egrd->fakecorr[0].ftyp;
713                 newsym(m, n);
714                 grd->mpeaceful = 0;
715             letknow:
716                 if (!cansee(grd->mx, grd->my) || !mon_visible(grd))
717 /*JP
718                     You_hear("the shrill sound of a guard's whistle.");
719 */
720                     You_hear("\94Ô\95º\82Ì\89s\82¢\93J\82Ì\89¹\82ð\95·\82¢\82½\81D");
721                 else
722 #if 0 /*JP*/
723                     You(um_dist(grd->mx, grd->my, 2)
724                             ? "see %s approaching."
725                             : "are confronted by %s.",
726                         /* "an angry guard" */
727                         x_monnam(grd, ARTICLE_A, "angry", 0, FALSE));
728 #else
729                     You(um_dist(grd->mx, grd->my, 2)
730                         ? "%s\82ª\8bß\82Ã\82¢\82Ä\82­\82é\82Ì\82ð\8c©\82½\81D"
731                         : "%s\82Æ\91Î\9b³\82µ\82½\81D",
732                         x_monnam(grd, ARTICLE_A, "\93{\82Á\82½", 0, FALSE));
733 #endif
734                 return -1;
735             } else {
736                 if (!Deaf)
737 /*JP
738                     verbalize("Well, begone.");
739 */
740                     verbalize("\97§\82¿\8b\8e\82ê\81D");
741                 wallify_vault(grd);
742                 egrd->gddone = 1;
743                 goto cleanup;
744             }
745         }
746     }
747
748     if (egrd->fcend > 1) {
749         if (egrd->fcend > 2 && in_fcorridor(grd, grd->mx, grd->my)
750             && !egrd->gddone && !in_fcorridor(grd, u.ux, u.uy)
751             && levl[egrd->fakecorr[0].fx][egrd->fakecorr[0].fy].typ
752                    == egrd->fakecorr[0].ftyp) {
753 /*JP
754             pline("%s, confused, disappears.", noit_Monnam(grd));
755 */
756             pline("%s\82Í\8d¬\97\90\82µ\81C\8fÁ\82¦\82½\81D", noit_Monnam(grd));
757             disappear_msg_seen = TRUE;
758             goto cleanup;
759         }
760         if (u_carry_gold && (in_fcorridor(grd, u.ux, u.uy)
761                              /* cover a 'blind' spot */
762                              || (egrd->fcend > 1 && u_in_vault))) {
763             if (!grd->mx) {
764                 restfakecorr(grd);
765                 return -2;
766             }
767             if (egrd->warncnt < 6) {
768                 egrd->warncnt = 6;
769                 if (!Deaf)
770 /*JP
771                     verbalize("Drop all your gold, scoundrel!");
772 */
773                     verbalize("\8bà\82ð\91S\95\94\92u\82¢\82Ä\82ä\82¯\81C\82È\82ç\82¸\82à\82Ì\81I");
774                 return 0;
775             } else {
776                 if (!Deaf)
777 /*JP
778                     verbalize("So be it, rogue!");
779 */
780                     verbalize("\93\90\90l\82ß\81I");
781                 grd->mpeaceful = 0;
782                 return -1;
783             }
784         }
785     }
786     for (fci = egrd->fcbeg; fci < egrd->fcend; fci++)
787         if (g_at(egrd->fakecorr[fci].fx, egrd->fakecorr[fci].fy)) {
788             m = egrd->fakecorr[fci].fx;
789             n = egrd->fakecorr[fci].fy;
790             goldincorridor = TRUE;
791         }
792     if (goldincorridor && !egrd->gddone) {
793         x = grd->mx;
794         y = grd->my;
795         if (m == u.ux && n == u.uy) {
796             struct obj *gold = g_at(m, n);
797             /* Grab the gold from between the hero's feet.  */
798             obj_extract_self(gold);
799             add_to_minv(grd, gold);
800             newsym(m, n);
801         } else if (m == x && n == y) {
802             mpickgold(grd); /* does a newsym */
803         } else {
804             /* just for insurance... */
805             if (MON_AT(m, n) && m != grd->mx && n != grd->my) {
806                 if (!Deaf)
807 /*JP
808                     verbalize("Out of my way, scum!");
809 */
810                     verbalize("\96Ú\82Ì\91O\82©\82ç\8fÁ\82¦\82ë\81C\83N\83\\82Á\82½\82ê\81I");
811                 (void) rloc(m_at(m, n), FALSE);
812             }
813             remove_monster(grd->mx, grd->my);
814             newsym(grd->mx, grd->my);
815             place_monster(grd, m, n);
816             mpickgold(grd); /* does a newsym */
817         }
818         if (cansee(m, n))
819 #if 0 /*JP*/
820             pline("%s%s picks up the gold.", Monnam(grd),
821                   grd->mpeaceful ? " calms down and" : "");
822 #else
823             pline("%s\82Í%s\8bà\89Ý\82ð\8fE\82Á\82½\81D", Monnam(grd),
824                   grd->mpeaceful ? "\93{\82è\82ð\90Ã\82ß" : "");
825 #endif
826         if (x != grd->mx || y != grd->my) {
827             remove_monster(grd->mx, grd->my);
828             newsym(grd->mx, grd->my);
829             place_monster(grd, x, y);
830             newsym(x, y);
831         }
832         if (!grd->mpeaceful)
833             return -1;
834         egrd->warncnt = 5;
835         return 0;
836     }
837     if (um_dist(grd->mx, grd->my, 1) || egrd->gddone) {
838         if (!egrd->gddone && !rn2(10) && !Deaf && !u.uswallow
839             && !(u.ustuck && !sticks(youmonst.data)))
840 /*JP
841             verbalize("Move along!");
842 */
843             verbalize("\97£\82ê\82é\82È\81I");
844         restfakecorr(grd);
845         return 0; /* didn't move */
846     }
847     x = grd->mx;
848     y = grd->my;
849
850     if (u_in_vault)
851         goto nextpos;
852
853     /* look around (hor & vert only) for accessible places */
854     for (nx = x - 1; nx <= x + 1; nx++)
855         for (ny = y - 1; ny <= y + 1; ny++) {
856             if ((nx == x || ny == y) && (nx != x || ny != y)
857                 && isok(nx, ny)) {
858                 typ = (crm = &levl[nx][ny])->typ;
859                 if (!IS_STWALL(typ) && !IS_POOL(typ)) {
860                     if (in_fcorridor(grd, nx, ny))
861                         goto nextnxy;
862
863                     if (*in_rooms(nx, ny, VAULT))
864                         continue;
865
866                     /* seems we found a good place to leave him alone */
867                     egrd->gddone = 1;
868                     if (ACCESSIBLE(typ))
869                         goto newpos;
870 #ifdef STUPID
871                     if (typ == SCORR)
872                         crm->typ = CORR;
873                     else
874                         crm->typ = DOOR;
875 #else
876                     crm->typ = (typ == SCORR) ? CORR : DOOR;
877 #endif
878                     if (crm->typ == DOOR)
879                         crm->doormask = D_NODOOR;
880                     goto proceed;
881                 }
882             }
883         nextnxy:
884             ;
885         }
886 nextpos:
887     nx = x;
888     ny = y;
889     gx = egrd->gdx;
890     gy = egrd->gdy;
891     dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
892     dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
893     if (abs(gx - x) >= abs(gy - y))
894         nx += dx;
895     else
896         ny += dy;
897
898     while ((typ = (crm = &levl[nx][ny])->typ) != 0) {
899         /* in view of the above we must have IS_WALL(typ) or typ == POOL */
900         /* must be a wall here */
901         if (isok(nx + nx - x, ny + ny - y) && !IS_POOL(typ)
902             && IS_ROOM(levl[nx + nx - x][ny + ny - y].typ)) {
903             crm->typ = DOOR;
904             crm->doormask = D_NODOOR;
905             goto proceed;
906         }
907         if (dy && nx != x) {
908             nx = x;
909             ny = y + dy;
910             continue;
911         }
912         if (dx && ny != y) {
913             ny = y;
914             nx = x + dx;
915             dy = 0;
916             continue;
917         }
918         /* I don't like this, but ... */
919         if (IS_ROOM(typ)) {
920             crm->typ = DOOR;
921             crm->doormask = D_NODOOR;
922             goto proceed;
923         }
924         break;
925     }
926     crm->typ = CORR;
927 proceed:
928     newspot = TRUE;
929     unblock_point(nx, ny); /* doesn't block light */
930     if (cansee(nx, ny))
931         newsym(nx, ny);
932
933     fcp = &(egrd->fakecorr[egrd->fcend]);
934     if (egrd->fcend++ == FCSIZ)
935         panic("fakecorr overflow");
936     fcp->fx = nx;
937     fcp->fy = ny;
938     fcp->ftyp = typ;
939 newpos:
940     if (egrd->gddone) {
941         /* The following is a kludge.  We need to keep    */
942         /* the guard around in order to be able to make   */
943         /* the fake corridor disappear as the player      */
944         /* moves out of it, but we also need the guard    */
945         /* out of the way.  We send the guard to never-   */
946         /* never land.  We set ogx ogy to mx my in order  */
947         /* to avoid a check at the top of this function.  */
948         /* At the end of the process, the guard is killed */
949         /* in restfakecorr().                             */
950     cleanup:
951         x = grd->mx;
952         y = grd->my;
953
954         see_guard = canspotmon(grd);
955         wallify_vault(grd);
956         remove_monster(grd->mx, grd->my);
957         newsym(grd->mx, grd->my);
958         place_monster(grd, 0, 0);
959         egrd->ogx = grd->mx;
960         egrd->ogy = grd->my;
961         restfakecorr(grd);
962         if (!semi_dead && (in_fcorridor(grd, u.ux, u.uy) || cansee(x, y))) {
963             if (!disappear_msg_seen && see_guard)
964 /*JP
965                 pline("Suddenly, %s disappears.", noit_mon_nam(grd));
966 */
967                 pline("\93Ë\91R\81C%s\82Í\8fÁ\82¦\82½\81D", noit_mon_nam(grd));
968             return 1;
969         }
970         return -2;
971     }
972     egrd->ogx = grd->mx; /* update old positions */
973     egrd->ogy = grd->my;
974     remove_monster(grd->mx, grd->my);
975     place_monster(grd, nx, ny);
976     if (newspot && g_at(nx, ny)) {
977         /* if there's gold already here (most likely from mineralize()),
978            pick it up now so that guard doesn't later think hero dropped
979            it and give an inappropriate message */
980         mpickgold(grd);
981         if (canspotmon(grd))
982 /*JP
983             pline("%s picks up some gold.", Monnam(grd));
984 */
985             pline("%s\82Í\8bà\82ð\8fE\82Á\82½\81D", Monnam(grd));
986     } else
987         newsym(grd->mx, grd->my);
988     restfakecorr(grd);
989     return 1;
990 }
991
992 /* Routine when dying or quitting with a vault guard around */
993 void
994 paygd()
995 {
996     register struct monst *grd = findgd();
997     long umoney = money_cnt(invent);
998     struct obj *coins, *nextcoins;
999     int gx, gy;
1000     char buf[BUFSZ];
1001
1002     if (!umoney || !grd)
1003         return;
1004
1005     if (u.uinvault) {
1006 #if 0 /*JP*/
1007         Your("%ld %s goes into the Magic Memory Vault.", umoney,
1008              currency(umoney));
1009 #else
1010         Your("%ld%s\82Í\96\82\96@\82Ì\8bL\94O\91q\8cÉ\82É\93ü\82Á\82½\81D", umoney,
1011              currency(umoney));
1012 #endif
1013         gx = u.ux;
1014         gy = u.uy;
1015     } else {
1016         if (grd->mpeaceful) { /* guard has no "right" to your gold */
1017             mongone(grd);
1018             return;
1019         }
1020         mnexto(grd);
1021 /*JP
1022         pline("%s remits your gold to the vault.", Monnam(grd));
1023 */
1024         pline("%s\82Í\82 \82È\82½\82Ì\8bà\89Ý\82ð\91q\8cÉ\82É\91\97\82Á\82½\81D", Monnam(grd));
1025         gx = rooms[EGD(grd)->vroom].lx + rn2(2);
1026         gy = rooms[EGD(grd)->vroom].ly + rn2(2);
1027 #if 0 /*JP*/
1028         Sprintf(buf, "To Croesus: here's the gold recovered from %s the %s.",
1029                 plname, mons[u.umonster].mname);
1030 #else
1031         Sprintf(buf, "\83N\83\8d\83C\83\\83X\82Ö: \82±\82±\82É%s\82Ì%s\82©\82ç\8eæ\82è\96ß\82µ\82½\8bà\89Ý\82ð\91\97\82é\81D",
1032                 mons[u.umonster].mname, plname);
1033 #endif
1034         make_grave(gx, gy, buf);
1035     }
1036     for (coins = invent; coins; coins = nextcoins) {
1037         nextcoins = coins->nobj;
1038         if (objects[coins->otyp].oc_class == COIN_CLASS) {
1039             freeinv(coins);
1040             place_object(coins, gx, gy);
1041             stackobj(coins);
1042         }
1043     }
1044     mongone(grd);
1045 }
1046
1047 long
1048 hidden_gold()
1049 {
1050     long value = 0L;
1051     struct obj *obj;
1052
1053     for (obj = invent; obj; obj = obj->nobj)
1054         if (Has_contents(obj))
1055             value += contained_gold(obj);
1056     /* unknown gold stuck inside statues may cause some consternation... */
1057
1058     return value;
1059 }
1060
1061 /* prevent "You hear footsteps.." when inappropriate */
1062 boolean
1063 gd_sound()
1064 {
1065     struct monst *grd = findgd();
1066
1067     if (vault_occupied(u.urooms))
1068         return FALSE;
1069     else
1070         return (boolean) (grd == (struct monst *) 0);
1071 }
1072
1073 void
1074 vault_gd_watching(activity)
1075 unsigned int activity;
1076 {
1077     struct monst *guard = findgd();
1078
1079     if (guard && guard->mcansee && m_canseeu(guard)) {
1080         if (activity == GD_EATGOLD || activity == GD_DESTROYGOLD)
1081             EGD(guard)->witness = activity;
1082     }
1083 }
1084
1085 /*vault.c*/