OSDN Git Service

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