OSDN Git Service

patch src/
[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             verbalize("What's going on here?");
364             if (gsensed)
365                 pline_The("other presence vanishes.");
366             mongone(guard);
367             return;
368         }
369         if (youmonst.m_ap_type == M_AP_OBJECT || u.uundetected) {
370             if (youmonst.m_ap_type == M_AP_OBJECT
371                 && youmonst.mappearance != GOLD_PIECE)
372 /*JP
373                 verbalize("Hey! Who left that %s in here?",
374 */
375                 verbalize("\82¨\82¢\81I\82¾\82ê\82ª\82±\82Ì%s\82ð\82±\82±\82É\92u\82¢\82Ä\8ds\82Á\82½\82ñ\82¾\81H",
376                           mimic_obj_name(&youmonst));
377             /* You're mimicking some object or you're hidden. */
378 /*JP
379             pline("Puzzled, %s turns around and leaves.", mhe(guard));
380 */
381             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));
382             mongone(guard);
383             return;
384         }
385         if (Strangled || is_silent(youmonst.data) || multi < 0) {
386             /* [we ought to record whether this this message has already
387                been given in order to vary it upon repeat visits, but
388                discarding the monster and its egd data renders that hard] */
389 /*JP
390             verbalize("I'll be back when you're ready to speak to me!");
391 */
392             verbalize("\98b\82¹\82é\82æ\82¤\82É\82È\82Á\82½\82ç\96ß\82Á\82Ä\82«\82Ä\82â\82é\81I");
393             mongone(guard);
394             return;
395         }
396
397         stop_occupation(); /* if occupied, stop it *now* */
398         if (multi > 0) {
399             nomul(0);
400             unmul((char *) 0);
401         }
402         trycount = 5;
403         do {
404 /*JP
405             getlin("\"Hello stranger, who are you?\" -", buf);
406 */
407             getlin("\81u\8c©\82È\82¢\8aç\82¾\82È\81C\82¨\82Ü\82¦\82Í\92N\82¾\81H\81v-", buf);
408             (void) mungspaces(buf);
409 #if 0 /*JP*/
410         } while (!letter(buf[0]) && --trycount > 0);
411 #else
412         } while (!letter(buf[0]) && !is_kanji(buf[0]) && --trycount > 0);
413 #endif
414
415         if (u.ualign.type == A_LAWFUL
416             /* ignore trailing text, in case player includes rank */
417             && strncmpi(buf, plname, (int) strlen(plname)) != 0) {
418             adjalign(-1); /* Liar! */
419         }
420
421 #if 0 /*JP*/
422         if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos")
423             || !strcmpi(buf, "Creosote")) {
424 #else
425     if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos")
426         || !strcmpi(buf, "Creosote")
427         || !strcmp(buf, "\83N\83\8d\83C\83\\83X") || !strcmp(buf, "\83N\83\8c\83I\83\\81[\83g")) {
428 #endif
429             if (!mvitals[PM_CROESUS].died) {
430                 verbalize(
431 /*JP
432                     "Oh, yes, of course.  Sorry to have disturbed you.");
433 */
434                     "\82¢\82â\81C\82±\82è\82á\81C\82¦\81[\82Æ\81C\82¨\91\9b\82ª\82¹\82µ\82Ü\82µ\82½\81D");
435                 mongone(guard);
436             } else {
437                 setmangry(guard);
438 /*JP
439                 verbalize("Back from the dead, are you?  I'll remedy that!");
440 */
441                 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");
442                 /* don't want guard to waste next turn wielding a weapon */
443                 if (!MON_WEP(guard)) {
444                     guard->weapon_check = NEED_HTH_WEAPON;
445                     (void) mon_wield_item(guard);
446                 }
447             }
448             return;
449         }
450 /*JP
451         verbalize("I don't know you.");
452 */
453         verbalize("\92m\82ç\82ñ\82È\81D");
454         umoney = money_cnt(invent);
455         if (Deaf) {
456             ;
457         } else if (!umoney && !hidden_gold()) {
458 /*JP
459             verbalize("Please follow me.");
460 */
461             verbalize("\8e\84\82Ì\8cã\82É\82Â\82¢\82Ä\82«\82È\82³\82¢\81D");
462         } else {
463             if (!umoney)
464 /*JP
465                 verbalize("You have hidden gold.");
466 */
467                 verbalize("\82Ü\82¾\8bà\89Ý\82ð\89B\82µ\82Ä\82é\82È\81D");
468             verbalize(
469 /*JP
470                 "Most likely all your gold was stolen from this vault.");
471 */
472                 "\91q\8cÉ\82©\82ç\93\90\82ñ\82¾\8bà\89Ý\82ª\82 \82é\82¾\82ë\82¤\81D");
473 /*JP
474             verbalize("Please drop that gold and follow me.");
475 */
476             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");
477         }
478         EGD(guard)->gdx = gx;
479         EGD(guard)->gdy = gy;
480         EGD(guard)->fcbeg = 0;
481         EGD(guard)->fakecorr[0].fx = x;
482         EGD(guard)->fakecorr[0].fy = y;
483         if (IS_WALL(levl[x][y].typ))
484             EGD(guard)->fakecorr[0].ftyp = levl[x][y].typ;
485         else { /* the initial guard location is a dug door */
486             int vlt = EGD(guard)->vroom;
487             xchar lowx = rooms[vlt].lx, hix = rooms[vlt].hx;
488             xchar lowy = rooms[vlt].ly, hiy = rooms[vlt].hy;
489
490             if (x == lowx - 1 && y == lowy - 1)
491                 EGD(guard)->fakecorr[0].ftyp = TLCORNER;
492             else if (x == hix + 1 && y == lowy - 1)
493                 EGD(guard)->fakecorr[0].ftyp = TRCORNER;
494             else if (x == lowx - 1 && y == hiy + 1)
495                 EGD(guard)->fakecorr[0].ftyp = BLCORNER;
496             else if (x == hix + 1 && y == hiy + 1)
497                 EGD(guard)->fakecorr[0].ftyp = BRCORNER;
498             else if (y == lowy - 1 || y == hiy + 1)
499                 EGD(guard)->fakecorr[0].ftyp = HWALL;
500             else if (x == lowx - 1 || x == hix + 1)
501                 EGD(guard)->fakecorr[0].ftyp = VWALL;
502         }
503         levl[x][y].typ = DOOR;
504         levl[x][y].doormask = D_NODOOR;
505         unblock_point(x, y); /* doesn't block light */
506         EGD(guard)->fcend = 1;
507         EGD(guard)->warncnt = 1;
508     }
509 }
510
511 STATIC_OVL void
512 move_gold(gold, vroom)
513 struct obj *gold;
514 int vroom;
515 {
516     xchar nx, ny;
517
518     remove_object(gold);
519     newsym(gold->ox, gold->oy);
520     nx = rooms[vroom].lx + rn2(2);
521     ny = rooms[vroom].ly + rn2(2);
522     place_object(gold, nx, ny);
523     stackobj(gold);
524     newsym(nx, ny);
525 }
526
527 STATIC_OVL void
528 wallify_vault(grd)
529 struct monst *grd;
530 {
531     int x, y, typ;
532     int vlt = EGD(grd)->vroom;
533     char tmp_viz;
534     xchar lox = rooms[vlt].lx - 1, hix = rooms[vlt].hx + 1,
535           loy = rooms[vlt].ly - 1, hiy = rooms[vlt].hy + 1;
536     struct monst *mon;
537     struct obj *gold;
538     struct trap *trap;
539     boolean fixed = FALSE;
540     boolean movedgold = FALSE;
541
542     for (x = lox; x <= hix; x++)
543         for (y = loy; y <= hiy; y++) {
544             /* if not on the room boundary, skip ahead */
545             if (x != lox && x != hix && y != loy && y != hiy)
546                 continue;
547
548             if (!IS_WALL(levl[x][y].typ) && !in_fcorridor(grd, x, y)) {
549                 if ((mon = m_at(x, y)) != 0 && mon != grd) {
550                     if (mon->mtame)
551                         yelp(mon);
552                     (void) rloc(mon, FALSE);
553                 }
554                 if ((gold = g_at(x, y)) != 0) {
555                     move_gold(gold, EGD(grd)->vroom);
556                     movedgold = TRUE;
557                 }
558                 if ((trap = t_at(x, y)) != 0)
559                     deltrap(trap);
560                 if (x == lox)
561                     typ =
562                         (y == loy) ? TLCORNER : (y == hiy) ? BLCORNER : VWALL;
563                 else if (x == hix)
564                     typ =
565                         (y == loy) ? TRCORNER : (y == hiy) ? BRCORNER : VWALL;
566                 else /* not left or right side, must be top or bottom */
567                     typ = HWALL;
568                 levl[x][y].typ = typ;
569                 levl[x][y].doormask = 0;
570                 /*
571                  * hack: player knows walls are restored because of the
572                  * message, below, so show this on the screen.
573                  */
574                 tmp_viz = viz_array[y][x];
575                 viz_array[y][x] = IN_SIGHT | COULD_SEE;
576                 newsym(x, y);
577                 viz_array[y][x] = tmp_viz;
578                 block_point(x, y);
579                 fixed = TRUE;
580             }
581         }
582
583     if (movedgold || fixed) {
584         if (in_fcorridor(grd, grd->mx, grd->my) || cansee(grd->mx, grd->my))
585 /*JP
586             pline("%s whispers an incantation.", noit_Monnam(grd));
587 */
588             pline("%s\82Í\8eô\95\82ð\82³\82³\82â\82¢\82½\81D", noit_Monnam(grd));
589         else
590 /*JP
591             You_hear("a distant chant.");
592 */
593             You_hear("\89\93\95û\82Å\82Ì\8eô\95\82ð\95·\82¢\82½\81D");
594         if (movedgold)
595 /*JP
596             pline("A mysterious force moves the gold into the vault.");
597 */
598             pline("\95s\8ev\8bc\82È\97Í\82ª\8bà\89Ý\82ð\91q\8cÉ\82Ö\89^\82ñ\82¾\81D");
599         if (fixed)
600 /*JP
601             pline_The("damaged vault's walls are magically restored!");
602 */
603             pline("\8f\9d\82Â\82¢\82½\91q\8cÉ\82Ì\95Ç\82Í\96\82\96@\82Å\95\9c\8c³\82³\82ê\82½\81I");
604     }
605 }
606
607 /*
608  * return  1: guard moved,  0: guard didn't,  -1: let m_move do it,  -2: died
609  */
610 int
611 gd_move(grd)
612 register struct monst *grd;
613 {
614     int x, y, nx, ny, m, n;
615     int dx, dy, gx, gy, fci;
616     uchar typ;
617     struct fakecorridor *fcp;
618     register struct egd *egrd = EGD(grd);
619     struct rm *crm;
620     boolean goldincorridor = FALSE,
621             u_in_vault = vault_occupied(u.urooms) ? TRUE : FALSE,
622             grd_in_vault = *in_rooms(grd->mx, grd->my, VAULT) ? TRUE : FALSE;
623     boolean disappear_msg_seen = FALSE, semi_dead = (grd->mhp <= 0);
624     long umoney = money_cnt(invent);
625     register boolean u_carry_gold = ((umoney + hidden_gold()) > 0L);
626     boolean see_guard, newspot = FALSE;
627
628     if (!on_level(&(egrd->gdlevel), &u.uz))
629         return -1;
630     nx = ny = m = n = 0;
631     if (!u_in_vault && !grd_in_vault)
632         wallify_vault(grd);
633     if (!grd->mpeaceful) {
634         if (semi_dead) {
635             egrd->gddone = 1;
636             goto newpos;
637         }
638         if (!u_in_vault
639             && (grd_in_vault || (in_fcorridor(grd, grd->mx, grd->my)
640                                  && !in_fcorridor(grd, u.ux, u.uy)))) {
641             (void) rloc(grd, FALSE);
642             wallify_vault(grd);
643             (void) clear_fcorr(grd, TRUE);
644             goto letknow;
645         }
646         if (!in_fcorridor(grd, grd->mx, grd->my))
647             (void) clear_fcorr(grd, TRUE);
648         return -1;
649     }
650     if (abs(egrd->ogx - grd->mx) > 1 || abs(egrd->ogy - grd->my) > 1)
651         return -1; /* teleported guard - treat as monster */
652
653     if (egrd->witness) {
654         verbalize("How dare you %s that gold, scoundrel!",
655                   (egrd->witness & GD_EATGOLD) ? "consume" : "destroy");
656         egrd->witness = 0;
657         grd->mpeaceful = 0;
658         return -1;
659     }
660     if (egrd->fcend == 1) {
661         if (u_in_vault && (u_carry_gold || um_dist(grd->mx, grd->my, 1))) {
662             if (egrd->warncnt == 3 && !Deaf)
663 #if 0 /*JP*/
664                 verbalize("I repeat, %sfollow me!",
665                           u_carry_gold
666                               ? (!umoney ? "drop that hidden money and "
667                                          : "drop that money and ")
668                               : "");
669 #else
670                 verbalize("\8cJ\82è\95Ô\82·\81I%s\8e\84\82É\82Â\82¢\82Ä\82±\82¢\81I",
671                           u_carry_gold
672                               ? (!umoney ? "\89B\82µ\8e\9d\82Á\82Ä\82é\8bà\82ð\92u\82¢\82Ä"
673                                          : "\8bà\82ð\92u\82¢\82Ä")
674                               : "");
675 #endif
676             if (egrd->warncnt == 7) {
677                 m = grd->mx;
678                 n = grd->my;
679                 if (!Deaf)
680 /*JP
681                     verbalize("You've been warned, knave!");
682 */
683                     verbalize("\8cx\8d\90\82Í\82µ\82½\82¼\81C\88«\93}\82ß\81I");
684                 mnexto(grd);
685                 levl[m][n].typ = egrd->fakecorr[0].ftyp;
686                 newsym(m, n);
687                 grd->mpeaceful = 0;
688                 return -1;
689             }
690             /* not fair to get mad when (s)he's fainted or paralyzed */
691             if (!is_fainted() && multi >= 0)
692                 egrd->warncnt++;
693             return 0;
694         }
695
696         if (!u_in_vault) {
697             if (u_carry_gold) { /* player teleported */
698                 m = grd->mx;
699                 n = grd->my;
700                 (void) rloc(grd, TRUE);
701                 levl[m][n].typ = egrd->fakecorr[0].ftyp;
702                 newsym(m, n);
703                 grd->mpeaceful = 0;
704             letknow:
705                 if (!cansee(grd->mx, grd->my) || !mon_visible(grd))
706 /*JP
707                     You_hear("the shrill sound of a guard's whistle.");
708 */
709                     You_hear("\94Ô\95º\82Ì\89s\82¢\93J\82Ì\89¹\82ð\95·\82¢\82½\81D");
710                 else
711 #if 0 /*JP*/
712                     You(um_dist(grd->mx, grd->my, 2)
713                             ? "see %s approaching."
714                             : "are confronted by %s.",
715                         /* "an angry guard" */
716                         x_monnam(grd, ARTICLE_A, "angry", 0, FALSE));
717 #else
718                     You(um_dist(grd->mx, grd->my, 2)
719                         ? "%s\82ª\8bß\82Ã\82¢\82Ä\82­\82é\82Ì\82ð\8c©\82½\81D"
720                         : "%s\82Æ\91Î\9b³\82µ\82½\81D",
721                         x_monnam(grd, ARTICLE_A, "\93{\82Á\82½", 0, FALSE));
722 #endif
723                 return -1;
724             } else {
725                 if (!Deaf)
726 /*JP
727                     verbalize("Well, begone.");
728 */
729                     verbalize("\97§\82¿\8b\8e\82ê\81D");
730                 wallify_vault(grd);
731                 egrd->gddone = 1;
732                 goto cleanup;
733             }
734         }
735     }
736
737     if (egrd->fcend > 1) {
738         if (egrd->fcend > 2 && in_fcorridor(grd, grd->mx, grd->my)
739             && !egrd->gddone && !in_fcorridor(grd, u.ux, u.uy)
740             && levl[egrd->fakecorr[0].fx][egrd->fakecorr[0].fy].typ
741                    == egrd->fakecorr[0].ftyp) {
742 /*JP
743             pline("%s, confused, disappears.", noit_Monnam(grd));
744 */
745             pline("%s\82Í\8d¬\97\90\82µ\81C\8fÁ\82¦\82½\81D", noit_Monnam(grd));
746             disappear_msg_seen = TRUE;
747             goto cleanup;
748         }
749         if (u_carry_gold && (in_fcorridor(grd, u.ux, u.uy)
750                              /* cover a 'blind' spot */
751                              || (egrd->fcend > 1 && u_in_vault))) {
752             if (!grd->mx) {
753                 restfakecorr(grd);
754                 return -2;
755             }
756             if (egrd->warncnt < 6) {
757                 egrd->warncnt = 6;
758                 if (!Deaf)
759 /*JP
760                     verbalize("Drop all your gold, scoundrel!");
761 */
762                     verbalize("\8bà\82ð\91S\95\94\92u\82¢\82Ä\82ä\82¯\81C\82È\82ç\82¸\82à\82Ì\81I");
763                 return 0;
764             } else {
765                 if (!Deaf)
766 /*JP
767                     verbalize("So be it, rogue!");
768 */
769                     verbalize("\93\90\90l\82ß\81I");
770                 grd->mpeaceful = 0;
771                 return -1;
772             }
773         }
774     }
775     for (fci = egrd->fcbeg; fci < egrd->fcend; fci++)
776         if (g_at(egrd->fakecorr[fci].fx, egrd->fakecorr[fci].fy)) {
777             m = egrd->fakecorr[fci].fx;
778             n = egrd->fakecorr[fci].fy;
779             goldincorridor = TRUE;
780         }
781     if (goldincorridor && !egrd->gddone) {
782         x = grd->mx;
783         y = grd->my;
784         if (m == u.ux && n == u.uy) {
785             struct obj *gold = g_at(m, n);
786             /* Grab the gold from between the hero's feet.  */
787             obj_extract_self(gold);
788             add_to_minv(grd, gold);
789             newsym(m, n);
790         } else if (m == x && n == y) {
791             mpickgold(grd); /* does a newsym */
792         } else {
793             /* just for insurance... */
794             if (MON_AT(m, n) && m != grd->mx && n != grd->my) {
795                 if (!Deaf)
796 /*JP
797                     verbalize("Out of my way, scum!");
798 */
799                     verbalize("\96Ú\82Ì\91O\82©\82ç\8fÁ\82¦\82ë\81C\83N\83\\82Á\82½\82ê\81I");
800                 (void) rloc(m_at(m, n), FALSE);
801             }
802             remove_monster(grd->mx, grd->my);
803             newsym(grd->mx, grd->my);
804             place_monster(grd, m, n);
805             mpickgold(grd); /* does a newsym */
806         }
807         if (cansee(m, n))
808 #if 0 /*JP*/
809             pline("%s%s picks up the gold.", Monnam(grd),
810                   grd->mpeaceful ? " calms down and" : "");
811 #else
812             pline("%s\82Í%s\8bà\89Ý\82ð\8fE\82Á\82½\81D", Monnam(grd),
813                   grd->mpeaceful ? "\93{\82è\82ð\90Ã\82ß" : "");
814 #endif
815         if (x != grd->mx || y != grd->my) {
816             remove_monster(grd->mx, grd->my);
817             newsym(grd->mx, grd->my);
818             place_monster(grd, x, y);
819             newsym(x, y);
820         }
821         if (!grd->mpeaceful)
822             return -1;
823         egrd->warncnt = 5;
824         return 0;
825     }
826     if (um_dist(grd->mx, grd->my, 1) || egrd->gddone) {
827         if (!egrd->gddone && !rn2(10) && !Deaf && !u.uswallow
828             && !(u.ustuck && !sticks(youmonst.data)))
829 /*JP
830             verbalize("Move along!");
831 */
832             verbalize("\97£\82ê\82é\82È\81I");
833         restfakecorr(grd);
834         return 0; /* didn't move */
835     }
836     x = grd->mx;
837     y = grd->my;
838
839     if (u_in_vault)
840         goto nextpos;
841
842     /* look around (hor & vert only) for accessible places */
843     for (nx = x - 1; nx <= x + 1; nx++)
844         for (ny = y - 1; ny <= y + 1; ny++) {
845             if ((nx == x || ny == y) && (nx != x || ny != y)
846                 && isok(nx, ny)) {
847                 typ = (crm = &levl[nx][ny])->typ;
848                 if (!IS_STWALL(typ) && !IS_POOL(typ)) {
849                     if (in_fcorridor(grd, nx, ny))
850                         goto nextnxy;
851
852                     if (*in_rooms(nx, ny, VAULT))
853                         continue;
854
855                     /* seems we found a good place to leave him alone */
856                     egrd->gddone = 1;
857                     if (ACCESSIBLE(typ))
858                         goto newpos;
859 #ifdef STUPID
860                     if (typ == SCORR)
861                         crm->typ = CORR;
862                     else
863                         crm->typ = DOOR;
864 #else
865                     crm->typ = (typ == SCORR) ? CORR : DOOR;
866 #endif
867                     if (crm->typ == DOOR)
868                         crm->doormask = D_NODOOR;
869                     goto proceed;
870                 }
871             }
872         nextnxy:
873             ;
874         }
875 nextpos:
876     nx = x;
877     ny = y;
878     gx = egrd->gdx;
879     gy = egrd->gdy;
880     dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
881     dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
882     if (abs(gx - x) >= abs(gy - y))
883         nx += dx;
884     else
885         ny += dy;
886
887     while ((typ = (crm = &levl[nx][ny])->typ) != 0) {
888         /* in view of the above we must have IS_WALL(typ) or typ == POOL */
889         /* must be a wall here */
890         if (isok(nx + nx - x, ny + ny - y) && !IS_POOL(typ)
891             && IS_ROOM(levl[nx + nx - x][ny + ny - y].typ)) {
892             crm->typ = DOOR;
893             crm->doormask = D_NODOOR;
894             goto proceed;
895         }
896         if (dy && nx != x) {
897             nx = x;
898             ny = y + dy;
899             continue;
900         }
901         if (dx && ny != y) {
902             ny = y;
903             nx = x + dx;
904             dy = 0;
905             continue;
906         }
907         /* I don't like this, but ... */
908         if (IS_ROOM(typ)) {
909             crm->typ = DOOR;
910             crm->doormask = D_NODOOR;
911             goto proceed;
912         }
913         break;
914     }
915     crm->typ = CORR;
916 proceed:
917     newspot = TRUE;
918     unblock_point(nx, ny); /* doesn't block light */
919     if (cansee(nx, ny))
920         newsym(nx, ny);
921
922     fcp = &(egrd->fakecorr[egrd->fcend]);
923     if (egrd->fcend++ == FCSIZ)
924         panic("fakecorr overflow");
925     fcp->fx = nx;
926     fcp->fy = ny;
927     fcp->ftyp = typ;
928 newpos:
929     if (egrd->gddone) {
930         /* The following is a kludge.  We need to keep    */
931         /* the guard around in order to be able to make   */
932         /* the fake corridor disappear as the player      */
933         /* moves out of it, but we also need the guard    */
934         /* out of the way.  We send the guard to never-   */
935         /* never land.  We set ogx ogy to mx my in order  */
936         /* to avoid a check at the top of this function.  */
937         /* At the end of the process, the guard is killed */
938         /* in restfakecorr().                             */
939     cleanup:
940         x = grd->mx;
941         y = grd->my;
942
943         see_guard = canspotmon(grd);
944         wallify_vault(grd);
945         remove_monster(grd->mx, grd->my);
946         newsym(grd->mx, grd->my);
947         place_monster(grd, 0, 0);
948         egrd->ogx = grd->mx;
949         egrd->ogy = grd->my;
950         restfakecorr(grd);
951         if (!semi_dead && (in_fcorridor(grd, u.ux, u.uy) || cansee(x, y))) {
952             if (!disappear_msg_seen && see_guard)
953 /*JP
954                 pline("Suddenly, %s disappears.", noit_mon_nam(grd));
955 */
956                 pline("\93Ë\91R\81C%s\82Í\8fÁ\82¦\82½\81D", noit_mon_nam(grd));
957             return 1;
958         }
959         return -2;
960     }
961     egrd->ogx = grd->mx; /* update old positions */
962     egrd->ogy = grd->my;
963     remove_monster(grd->mx, grd->my);
964     place_monster(grd, nx, ny);
965     if (newspot && g_at(nx, ny)) {
966         /* if there's gold already here (most likely from mineralize()),
967            pick it up now so that guard doesn't later think hero dropped
968            it and give an inappropriate message */
969         mpickgold(grd);
970         if (canspotmon(grd))
971             pline("%s picks up some gold.", Monnam(grd));
972     } else
973         newsym(grd->mx, grd->my);
974     restfakecorr(grd);
975     return 1;
976 }
977
978 /* Routine when dying or quitting with a vault guard around */
979 void
980 paygd()
981 {
982     register struct monst *grd = findgd();
983     long umoney = money_cnt(invent);
984     struct obj *coins, *nextcoins;
985     int gx, gy;
986     char buf[BUFSZ];
987
988     if (!umoney || !grd)
989         return;
990
991     if (u.uinvault) {
992 #if 0 /*JP*/
993         Your("%ld %s goes into the Magic Memory Vault.", umoney,
994              currency(umoney));
995 #else
996         Your("%ld%s\82Í\96\82\96@\82Ì\8bL\94O\91q\8cÉ\82É\93ü\82Á\82½\81D", umoney,
997              currency(umoney));
998 #endif
999         gx = u.ux;
1000         gy = u.uy;
1001     } else {
1002         if (grd->mpeaceful) { /* guard has no "right" to your gold */
1003             mongone(grd);
1004             return;
1005         }
1006         mnexto(grd);
1007 /*JP
1008         pline("%s remits your gold to the vault.", Monnam(grd));
1009 */
1010         pline("%s\82Í\82 \82È\82½\82Ì\8bà\89Ý\82ð\91q\8cÉ\82É\91\97\82Á\82½\81D", Monnam(grd));
1011         gx = rooms[EGD(grd)->vroom].lx + rn2(2);
1012         gy = rooms[EGD(grd)->vroom].ly + rn2(2);
1013 #if 0 /*JP*/
1014         Sprintf(buf, "To Croesus: here's the gold recovered from %s the %s.",
1015                 plname, mons[u.umonster].mname);
1016 #else
1017         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",
1018                 mons[u.umonster].mname, plname);
1019 #endif
1020         make_grave(gx, gy, buf);
1021     }
1022     for (coins = invent; coins; coins = nextcoins) {
1023         nextcoins = coins->nobj;
1024         if (objects[coins->otyp].oc_class == COIN_CLASS) {
1025             freeinv(coins);
1026             place_object(coins, gx, gy);
1027             stackobj(coins);
1028         }
1029     }
1030     mongone(grd);
1031 }
1032
1033 long
1034 hidden_gold()
1035 {
1036     long value = 0L;
1037     struct obj *obj;
1038
1039     for (obj = invent; obj; obj = obj->nobj)
1040         if (Has_contents(obj))
1041             value += contained_gold(obj);
1042     /* unknown gold stuck inside statues may cause some consternation... */
1043
1044     return value;
1045 }
1046
1047 /* prevent "You hear footsteps.." when inappropriate */
1048 boolean
1049 gd_sound()
1050 {
1051     struct monst *grd = findgd();
1052
1053     if (vault_occupied(u.urooms))
1054         return FALSE;
1055     else
1056         return (boolean) (grd == (struct monst *) 0);
1057 }
1058
1059 void
1060 vault_gd_watching(activity)
1061 unsigned int activity;
1062 {
1063     struct monst *guard = findgd();
1064
1065     if (guard && guard->mcansee && m_canseeu(guard)) {
1066         if (activity == GD_EATGOLD || activity == GD_DESTROYGOLD)
1067             EGD(guard)->witness = activity;
1068     }
1069 }
1070
1071 /*vault.c*/