NetHack->aNetHack
[aNetHack.git] / src / vault.c
blobf076986f5b837340db078f79835956290545578e
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 /* NetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
7 STATIC_DCL struct monst *NDECL(findgd);
9 STATIC_DCL boolean FDECL(clear_fcorr, (struct monst *, BOOLEAN_P));
10 STATIC_DCL void FDECL(blackout, (int, int));
11 STATIC_DCL void FDECL(restfakecorr, (struct monst *));
12 STATIC_DCL boolean FDECL(in_fcorridor, (struct monst *, int, int));
13 STATIC_DCL void FDECL(move_gold, (struct obj *, int));
14 STATIC_DCL void FDECL(wallify_vault, (struct monst *));
16 void
17 newegd(mtmp)
18 struct monst *mtmp;
20 if (!mtmp->mextra)
21 mtmp->mextra = newmextra();
22 if (!EGD(mtmp)) {
23 EGD(mtmp) = (struct egd *) alloc(sizeof(struct egd));
24 (void) memset((genericptr_t) EGD(mtmp), 0, sizeof(struct egd));
28 void
29 free_egd(mtmp)
30 struct monst *mtmp;
32 if (mtmp->mextra && EGD(mtmp)) {
33 free((genericptr_t) EGD(mtmp));
34 EGD(mtmp) = (struct egd *) 0;
36 mtmp->isgd = 0;
39 STATIC_OVL boolean
40 clear_fcorr(grd, forceshow)
41 struct monst *grd;
42 boolean forceshow;
44 register int fcx, fcy, fcbeg;
45 struct monst *mtmp;
46 boolean sawcorridor = FALSE;
47 struct egd *egrd = EGD(grd);
48 struct trap *trap;
49 struct rm *lev;
51 if (!on_level(&egrd->gdlevel, &u.uz))
52 return TRUE;
54 while ((fcbeg = egrd->fcbeg) < egrd->fcend) {
55 fcx = egrd->fakecorr[fcbeg].fx;
56 fcy = egrd->fakecorr[fcbeg].fy;
57 if ((grd->mhp <= 0 || !in_fcorridor(grd, u.ux, u.uy)) && egrd->gddone)
58 forceshow = TRUE;
59 if ((u.ux == fcx && u.uy == fcy && grd->mhp > 0)
60 || (!forceshow && couldsee(fcx, fcy))
61 || (Punished && !carried(uball) && uball->ox == fcx
62 && uball->oy == fcy))
63 return FALSE;
65 if ((mtmp = m_at(fcx, fcy)) != 0) {
66 if (mtmp->isgd) {
67 return FALSE;
68 } else if (!in_fcorridor(grd, u.ux, u.uy)) {
69 if (mtmp->mtame)
70 yelp(mtmp);
71 (void) rloc(mtmp, FALSE);
74 lev = &levl[fcx][fcy];
75 if (lev->typ == CORR && cansee(fcx, fcy))
76 sawcorridor = TRUE;
77 lev->typ = egrd->fakecorr[fcbeg].ftyp;
78 if (IS_STWALL(lev->typ)) {
79 /* destroy any trap here (pit dug by you, hole dug via
80 wand while levitating or by monster, bear trap or land
81 mine via object, spun web) when spot reverts to stone */
82 if ((trap = t_at(fcx, fcy)) != 0)
83 deltrap(trap);
84 /* undo scroll/wand/spell of light affecting this spot */
85 if (lev->typ == STONE)
86 blackout(fcx, fcy);
88 map_location(fcx, fcy, 1); /* bypass vision */
89 if (!ACCESSIBLE(lev->typ))
90 block_point(fcx, fcy);
91 vision_full_recalc = 1;
92 egrd->fcbeg++;
94 if (sawcorridor)
95 pline_The("corridor disappears.");
96 if (IS_ROCK(levl[u.ux][u.uy].typ))
97 You("are encased in rock.");
98 return TRUE;
101 /* as a temporary corridor is removed, set stone locations and adjacent
102 spots to unlit; if player used scroll/wand/spell of light while inside
103 the corridor, we don't want the light to reappear if/when a new tunnel
104 goes through the same area */
105 STATIC_OVL void
106 blackout(x, y)
107 int x, y;
109 struct rm *lev;
110 int i, j;
112 for (i = x - 1; i <= x + 1; ++i)
113 for (j = y - 1; j <= y + 1; ++j) {
114 if (!isok(i, j))
115 continue;
116 lev = &levl[i][j];
117 /* [possible bug: when (i != x || j != y), perhaps we ought
118 to check whether the spot on the far side is lit instead
119 of doing a blanket blackout of adjacent locations] */
120 if (lev->typ == STONE)
121 lev->lit = lev->waslit = 0;
122 /* mark <i,j> as not having been seen from <x,y> */
123 unset_seenv(lev, x, y, i, j);
127 STATIC_OVL void
128 restfakecorr(grd)
129 struct monst *grd;
131 /* it seems you left the corridor - let the guard disappear */
132 if (clear_fcorr(grd, FALSE)) {
133 grd->isgd = 0; /* dmonsfree() should delete this mon */
134 mongone(grd);
138 /* called in mon.c */
139 boolean
140 grddead(grd)
141 struct monst *grd;
143 boolean dispose = clear_fcorr(grd, TRUE);
145 if (!dispose) {
146 /* destroy guard's gold; drop any other inventory */
147 relobj(grd, 0, FALSE);
148 /* guard is dead; monster traversal loops should skip it */
149 grd->mhp = 0;
150 if (grd == context.polearm.hitmon)
151 context.polearm.hitmon = 0;
152 /* see comment by newpos in gd_move() */
153 remove_monster(grd->mx, grd->my);
154 newsym(grd->mx, grd->my);
155 place_monster(grd, 0, 0);
156 EGD(grd)->ogx = grd->mx;
157 EGD(grd)->ogy = grd->my;
158 dispose = clear_fcorr(grd, TRUE);
160 if (dispose)
161 grd->isgd = 0; /* for dmonsfree() */
162 return dispose;
165 STATIC_OVL boolean
166 in_fcorridor(grd, x, y)
167 struct monst *grd;
168 int x, y;
170 register int fci;
171 struct egd *egrd = EGD(grd);
173 for (fci = egrd->fcbeg; fci < egrd->fcend; fci++)
174 if (x == egrd->fakecorr[fci].fx && y == egrd->fakecorr[fci].fy)
175 return TRUE;
176 return FALSE;
179 STATIC_OVL
180 struct monst *
181 findgd()
183 register struct monst *mtmp;
185 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
186 if (DEADMONSTER(mtmp))
187 continue;
188 if (mtmp->isgd && on_level(&(EGD(mtmp)->gdlevel), &u.uz))
189 return mtmp;
191 return (struct monst *) 0;
194 char
195 vault_occupied(array)
196 char *array;
198 register char *ptr;
200 for (ptr = array; *ptr; ptr++)
201 if (rooms[*ptr - ROOMOFFSET].rtype == VAULT)
202 return *ptr;
203 return '\0';
206 void
207 invault()
209 #ifdef BSD_43_BUG
210 int dummy; /* hack to avoid schain botch */
211 #endif
212 struct monst *guard;
213 boolean gsensed;
214 int trycount, vaultroom = (int) vault_occupied(u.urooms);
216 if (!vaultroom) {
217 u.uinvault = 0;
218 return;
221 vaultroom -= ROOMOFFSET;
223 guard = findgd();
224 if (++u.uinvault % 30 == 0 && !guard) { /* if time ok and no guard now. */
225 char buf[BUFSZ];
226 register int x, y, dd, gx, gy;
227 int lx = 0, ly = 0;
228 long umoney;
230 /* first find the goal for the guard */
231 for (dd = 2; (dd < ROWNO || dd < COLNO); dd++) {
232 for (y = u.uy - dd; y <= u.uy + dd; ly = y, y++) {
233 if (y < 0 || y > ROWNO - 1)
234 continue;
235 for (x = u.ux - dd; x <= u.ux + dd; lx = x, x++) {
236 if (y != u.uy - dd && y != u.uy + dd && x != u.ux - dd)
237 x = u.ux + dd;
238 if (x < 1 || x > COLNO - 1)
239 continue;
240 if (levl[x][y].typ == CORR) {
241 if (x < u.ux)
242 lx = x + 1;
243 else if (x > u.ux)
244 lx = x - 1;
245 else
246 lx = x;
247 if (y < u.uy)
248 ly = y + 1;
249 else if (y > u.uy)
250 ly = y - 1;
251 else
252 ly = y;
253 if (levl[lx][ly].typ != STONE
254 && levl[lx][ly].typ != CORR)
255 goto incr_radius;
256 goto fnd;
260 incr_radius:
263 impossible("Not a single corridor on this level??");
264 tele();
265 return;
266 fnd:
267 gx = x;
268 gy = y;
270 /* next find a good place for a door in the wall */
271 x = u.ux;
272 y = u.uy;
273 if (levl[x][y].typ != ROOM) { /* player dug a door and is in it */
274 if (levl[x + 1][y].typ == ROOM)
275 x = x + 1;
276 else if (levl[x][y + 1].typ == ROOM)
277 y = y + 1;
278 else if (levl[x - 1][y].typ == ROOM)
279 x = x - 1;
280 else if (levl[x][y - 1].typ == ROOM)
281 y = y - 1;
282 else if (levl[x + 1][y + 1].typ == ROOM) {
283 x = x + 1;
284 y = y + 1;
285 } else if (levl[x - 1][y - 1].typ == ROOM) {
286 x = x - 1;
287 y = y - 1;
288 } else if (levl[x + 1][y - 1].typ == ROOM) {
289 x = x + 1;
290 y = y - 1;
291 } else if (levl[x - 1][y + 1].typ == ROOM) {
292 x = x - 1;
293 y = y + 1;
296 while (levl[x][y].typ == ROOM) {
297 register int dx, dy;
299 dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
300 dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
301 if (abs(gx - x) >= abs(gy - y))
302 x += dx;
303 else
304 y += dy;
306 if (x == u.ux && y == u.uy) {
307 if (levl[x + 1][y].typ == HWALL || levl[x + 1][y].typ == DOOR)
308 x = x + 1;
309 else if (levl[x - 1][y].typ == HWALL
310 || levl[x - 1][y].typ == DOOR)
311 x = x - 1;
312 else if (levl[x][y + 1].typ == VWALL
313 || levl[x][y + 1].typ == DOOR)
314 y = y + 1;
315 else if (levl[x][y - 1].typ == VWALL
316 || levl[x][y - 1].typ == DOOR)
317 y = y - 1;
318 else
319 return;
322 /* make something interesting happen */
323 if (!(guard = makemon(&mons[PM_GUARD], x, y, MM_EGD)))
324 return;
325 guard->isgd = 1;
326 guard->mpeaceful = 1;
327 set_malign(guard);
328 EGD(guard)->gddone = 0;
329 EGD(guard)->ogx = x;
330 EGD(guard)->ogy = y;
331 assign_level(&(EGD(guard)->gdlevel), &u.uz);
332 EGD(guard)->vroom = vaultroom;
333 EGD(guard)->warncnt = 0;
335 reset_faint(); /* if fainted - wake up */
336 gsensed = !canspotmon(guard);
337 if (!gsensed)
338 pline("Suddenly one of the Vault's %s enters!",
339 makeplural(guard->data->mname));
340 else
341 pline("Someone else has entered the Vault.");
342 newsym(guard->mx, guard->my);
343 if (u.uswallow) {
344 /* can't interrogate hero, don't interrogate engulfer */
345 if (!Deaf) verbalize("What's going on here?");
346 if (gsensed)
347 pline_The("other presence vanishes.");
348 mongone(guard);
349 return;
351 if (youmonst.m_ap_type == M_AP_OBJECT || u.uundetected) {
352 if (youmonst.m_ap_type == M_AP_OBJECT
353 && youmonst.mappearance != GOLD_PIECE)
354 if (!Deaf) verbalize("Hey! Who left that %s in here?",
355 mimic_obj_name(&youmonst));
356 /* You're mimicking some object or you're hidden. */
357 pline("Puzzled, %s turns around and leaves.", mhe(guard));
358 mongone(guard);
359 return;
361 if (Strangled || is_silent(youmonst.data) || multi < 0) {
362 /* [we ought to record whether this this message has already
363 been given in order to vary it upon repeat visits, but
364 discarding the monster and its egd data renders that hard] */
365 if (Deaf)
366 pline("%s huffs and turns to leave.", noit_Monnam(guard));
367 else
368 verbalize("I'll be back when you're ready to speak to me!");
369 mongone(guard);
370 return;
373 stop_occupation(); /* if occupied, stop it *now* */
374 if (multi > 0) {
375 nomul(0);
376 unmul((char *) 0);
378 trycount = 5;
379 do {
380 getlin(Deaf ? "You are required to supply your name. -"
381 : "\"Hello stranger, who are you?\" -", buf);
382 (void) mungspaces(buf);
383 } while (!buf[0] && --trycount > 0);
385 if (u.ualign.type == A_LAWFUL
386 /* ignore trailing text, in case player includes rank */
387 && strncmpi(buf, plname, (int) strlen(plname)) != 0) {
388 adjalign(-1); /* Liar! */
391 if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos")
392 || !strcmpi(buf, "Creosote")) {
393 if (!mvitals[PM_CROESUS].died) {
394 if (Deaf) {
395 if (!Blind)
396 pline("%s waves goodbye.", noit_Monnam(guard));
397 } else {
398 verbalize(
399 "Oh, yes, of course. Sorry to have disturbed you.");
401 mongone(guard);
402 } else {
403 setmangry(guard, FALSE);
404 if (Deaf) {
405 if (!Blind)
406 pline("%s mouths something and looks very angry!",
407 noit_Monnam(guard));
408 } else {
409 verbalize(
410 "Back from the dead, are you? I'll remedy that!");
412 /* don't want guard to waste next turn wielding a weapon */
413 if (!MON_WEP(guard)) {
414 guard->weapon_check = NEED_HTH_WEAPON;
415 (void) mon_wield_item(guard);
418 return;
420 if (Deaf)
421 pline("%s doesn't %srecognize you.", noit_Monnam(guard),
422 (Blind) ? "" : "appear to ");
423 else
424 verbalize("I don't know you.");
425 umoney = money_cnt(invent);
426 if (!umoney && !hidden_gold()) {
427 if (Deaf)
428 pline("%s stomps%s.", noit_Monnam(guard),
429 (Blind) ? "" : " and beckons");
430 else
431 verbalize("Please follow me.");
432 } else {
433 if (!umoney) {
434 if (Deaf) {
435 if (!Blind)
436 pline("%s glares at you%s.", noit_Monnam(guard),
437 invent ? "r stuff" : "");
438 } else {
439 verbalize("You have hidden gold.");
442 if (Deaf) {
443 if (!Blind)
444 pline(
445 "%s holds out %s palm and beckons with %s other hand.",
446 noit_Monnam(guard), mhis(guard), mhis(guard));
447 } else {
448 verbalize(
449 "Most likely all your gold was stolen from this vault.");
450 verbalize("Please drop that gold and follow me.");
453 EGD(guard)->gdx = gx;
454 EGD(guard)->gdy = gy;
455 EGD(guard)->fcbeg = 0;
456 EGD(guard)->fakecorr[0].fx = x;
457 EGD(guard)->fakecorr[0].fy = y;
458 if (IS_WALL(levl[x][y].typ))
459 EGD(guard)->fakecorr[0].ftyp = levl[x][y].typ;
460 else { /* the initial guard location is a dug door */
461 int vlt = EGD(guard)->vroom;
462 xchar lowx = rooms[vlt].lx, hix = rooms[vlt].hx;
463 xchar lowy = rooms[vlt].ly, hiy = rooms[vlt].hy;
465 if (x == lowx - 1 && y == lowy - 1)
466 EGD(guard)->fakecorr[0].ftyp = TLCORNER;
467 else if (x == hix + 1 && y == lowy - 1)
468 EGD(guard)->fakecorr[0].ftyp = TRCORNER;
469 else if (x == lowx - 1 && y == hiy + 1)
470 EGD(guard)->fakecorr[0].ftyp = BLCORNER;
471 else if (x == hix + 1 && y == hiy + 1)
472 EGD(guard)->fakecorr[0].ftyp = BRCORNER;
473 else if (y == lowy - 1 || y == hiy + 1)
474 EGD(guard)->fakecorr[0].ftyp = HWALL;
475 else if (x == lowx - 1 || x == hix + 1)
476 EGD(guard)->fakecorr[0].ftyp = VWALL;
478 levl[x][y].typ = DOOR;
479 levl[x][y].doormask = D_NODOOR;
480 unblock_point(x, y); /* doesn't block light */
481 EGD(guard)->fcend = 1;
482 EGD(guard)->warncnt = 1;
486 STATIC_OVL void
487 move_gold(gold, vroom)
488 struct obj *gold;
489 int vroom;
491 xchar nx, ny;
493 remove_object(gold);
494 newsym(gold->ox, gold->oy);
495 nx = rooms[vroom].lx + rn2(2);
496 ny = rooms[vroom].ly + rn2(2);
497 place_object(gold, nx, ny);
498 stackobj(gold);
499 newsym(nx, ny);
502 STATIC_OVL void
503 wallify_vault(grd)
504 struct monst *grd;
506 int x, y, typ;
507 int vlt = EGD(grd)->vroom;
508 char tmp_viz;
509 xchar lox = rooms[vlt].lx - 1, hix = rooms[vlt].hx + 1,
510 loy = rooms[vlt].ly - 1, hiy = rooms[vlt].hy + 1;
511 struct monst *mon;
512 struct obj *gold;
513 struct trap *trap;
514 boolean fixed = FALSE;
515 boolean movedgold = FALSE;
517 for (x = lox; x <= hix; x++)
518 for (y = loy; y <= hiy; y++) {
519 /* if not on the room boundary, skip ahead */
520 if (x != lox && x != hix && y != loy && y != hiy)
521 continue;
523 if (!IS_WALL(levl[x][y].typ) && !in_fcorridor(grd, x, y)) {
524 if ((mon = m_at(x, y)) != 0 && mon != grd) {
525 if (mon->mtame)
526 yelp(mon);
527 (void) rloc(mon, FALSE);
529 if ((gold = g_at(x, y)) != 0) {
530 move_gold(gold, EGD(grd)->vroom);
531 movedgold = TRUE;
533 if ((trap = t_at(x, y)) != 0)
534 deltrap(trap);
535 if (x == lox)
536 typ =
537 (y == loy) ? TLCORNER : (y == hiy) ? BLCORNER : VWALL;
538 else if (x == hix)
539 typ =
540 (y == loy) ? TRCORNER : (y == hiy) ? BRCORNER : VWALL;
541 else /* not left or right side, must be top or bottom */
542 typ = HWALL;
543 levl[x][y].typ = typ;
544 levl[x][y].doormask = 0;
546 * hack: player knows walls are restored because of the
547 * message, below, so show this on the screen.
549 tmp_viz = viz_array[y][x];
550 viz_array[y][x] = IN_SIGHT | COULD_SEE;
551 newsym(x, y);
552 viz_array[y][x] = tmp_viz;
553 block_point(x, y);
554 fixed = TRUE;
558 if (movedgold || fixed) {
559 if (in_fcorridor(grd, grd->mx, grd->my) || cansee(grd->mx, grd->my))
560 pline("%s whispers an incantation.", noit_Monnam(grd));
561 else
562 You_hear("a distant chant.");
563 if (movedgold)
564 pline("A mysterious force moves the gold into the vault.");
565 if (fixed)
566 pline_The("damaged vault's walls are magically restored!");
571 * return 1: guard moved, 0: guard didn't, -1: let m_move do it, -2: died
574 gd_move(grd)
575 register struct monst *grd;
577 int x, y, nx, ny, m, n;
578 int dx, dy, gx, gy, fci;
579 uchar typ;
580 struct fakecorridor *fcp;
581 register struct egd *egrd = EGD(grd);
582 struct rm *crm;
583 boolean goldincorridor = FALSE,
584 u_in_vault = vault_occupied(u.urooms) ? TRUE : FALSE,
585 grd_in_vault = *in_rooms(grd->mx, grd->my, VAULT) ? TRUE : FALSE;
586 boolean disappear_msg_seen = FALSE, semi_dead = (grd->mhp <= 0);
587 long umoney = money_cnt(invent);
588 register boolean u_carry_gold = ((umoney + hidden_gold()) > 0L);
589 boolean see_guard, newspot = FALSE;
591 if (!on_level(&(egrd->gdlevel), &u.uz))
592 return -1;
593 nx = ny = m = n = 0;
594 if (!u_in_vault && !grd_in_vault)
595 wallify_vault(grd);
596 if (!grd->mpeaceful) {
597 if (semi_dead) {
598 egrd->gddone = 1;
599 goto newpos;
601 if (!u_in_vault
602 && (grd_in_vault || (in_fcorridor(grd, grd->mx, grd->my)
603 && !in_fcorridor(grd, u.ux, u.uy)))) {
604 (void) rloc(grd, FALSE);
605 wallify_vault(grd);
606 (void) clear_fcorr(grd, TRUE);
607 goto letknow;
609 if (!in_fcorridor(grd, grd->mx, grd->my))
610 (void) clear_fcorr(grd, TRUE);
611 return -1;
613 if (abs(egrd->ogx - grd->mx) > 1 || abs(egrd->ogy - grd->my) > 1)
614 return -1; /* teleported guard - treat as monster */
616 if (egrd->witness) {
617 if (!Deaf)
618 verbalize("How dare you %s that gold, scoundrel!",
619 (egrd->witness & GD_EATGOLD) ? "consume" : "destroy");
620 egrd->witness = 0;
621 grd->mpeaceful = 0;
622 return -1;
624 if (egrd->fcend == 1) {
625 if (u_in_vault && (u_carry_gold || um_dist(grd->mx, grd->my, 1))) {
626 if (egrd->warncnt == 3 && !Deaf)
627 verbalize("I repeat, %sfollow me!",
628 u_carry_gold
629 ? (!umoney ? "drop that hidden money and "
630 : "drop that money and ")
631 : "");
632 if (egrd->warncnt == 7) {
633 m = grd->mx;
634 n = grd->my;
635 if (!Deaf)
636 verbalize("You've been warned, knave!");
637 mnexto(grd);
638 levl[m][n].typ = egrd->fakecorr[0].ftyp;
639 newsym(m, n);
640 grd->mpeaceful = 0;
641 return -1;
643 /* not fair to get mad when (s)he's fainted or paralyzed */
644 if (!is_fainted() && multi >= 0)
645 egrd->warncnt++;
646 return 0;
649 if (!u_in_vault) {
650 if (u_carry_gold) { /* player teleported */
651 m = grd->mx;
652 n = grd->my;
653 (void) rloc(grd, TRUE);
654 levl[m][n].typ = egrd->fakecorr[0].ftyp;
655 newsym(m, n);
656 grd->mpeaceful = 0;
657 letknow:
658 if (!cansee(grd->mx, grd->my) || !mon_visible(grd))
659 You_hear("the shrill sound of a guard's whistle.");
660 else
661 You(um_dist(grd->mx, grd->my, 2)
662 ? "see %s approaching."
663 : "are confronted by %s.",
664 /* "an angry guard" */
665 x_monnam(grd, ARTICLE_A, "angry", 0, FALSE));
666 return -1;
667 } else {
668 if (!Deaf)
669 verbalize("Well, begone.");
670 wallify_vault(grd);
671 egrd->gddone = 1;
672 goto cleanup;
677 if (egrd->fcend > 1) {
678 if (egrd->fcend > 2 && in_fcorridor(grd, grd->mx, grd->my)
679 && !egrd->gddone && !in_fcorridor(grd, u.ux, u.uy)
680 && levl[egrd->fakecorr[0].fx][egrd->fakecorr[0].fy].typ
681 == egrd->fakecorr[0].ftyp) {
682 pline("%s, confused, disappears.", noit_Monnam(grd));
683 disappear_msg_seen = TRUE;
684 goto cleanup;
686 if (u_carry_gold && (in_fcorridor(grd, u.ux, u.uy)
687 /* cover a 'blind' spot */
688 || (egrd->fcend > 1 && u_in_vault))) {
689 if (!grd->mx) {
690 restfakecorr(grd);
691 return -2;
693 if (egrd->warncnt < 6) {
694 egrd->warncnt = 6;
695 if (Deaf) {
696 if (!Blind)
697 pline("%s holds out %s palm demandingly!",
698 noit_Monnam(grd), mhis(grd));
699 } else {
700 verbalize("Drop all your gold, scoundrel!");
702 return 0;
703 } else {
704 if (Deaf) {
705 if (!Blind)
706 pline("%s rubs %s hands with enraged delight!",
707 noit_Monnam(grd), mhis(grd));
708 } else {
709 verbalize("So be it, rogue!");
711 grd->mpeaceful = 0;
712 return -1;
716 for (fci = egrd->fcbeg; fci < egrd->fcend; fci++)
717 if (g_at(egrd->fakecorr[fci].fx, egrd->fakecorr[fci].fy)) {
718 m = egrd->fakecorr[fci].fx;
719 n = egrd->fakecorr[fci].fy;
720 goldincorridor = TRUE;
722 if (goldincorridor && !egrd->gddone) {
723 x = grd->mx;
724 y = grd->my;
725 if (m == u.ux && n == u.uy) {
726 struct obj *gold = g_at(m, n);
727 /* Grab the gold from between the hero's feet. */
728 obj_extract_self(gold);
729 add_to_minv(grd, gold);
730 newsym(m, n);
731 } else if (m == x && n == y) {
732 mpickgold(grd); /* does a newsym */
733 } else {
734 /* just for insurance... */
735 if (MON_AT(m, n) && m != grd->mx && n != grd->my) {
736 if (!Deaf)
737 verbalize("Out of my way, scum!");
738 (void) rloc(m_at(m, n), FALSE);
740 remove_monster(grd->mx, grd->my);
741 newsym(grd->mx, grd->my);
742 place_monster(grd, m, n);
743 mpickgold(grd); /* does a newsym */
745 if (cansee(m, n))
746 pline("%s%s picks up the gold.", Monnam(grd),
747 grd->mpeaceful ? " calms down and" : "");
748 if (x != grd->mx || y != grd->my) {
749 remove_monster(grd->mx, grd->my);
750 newsym(grd->mx, grd->my);
751 place_monster(grd, x, y);
752 newsym(x, y);
754 if (!grd->mpeaceful)
755 return -1;
756 egrd->warncnt = 5;
757 return 0;
759 if (um_dist(grd->mx, grd->my, 1) || egrd->gddone) {
760 if (!egrd->gddone && !rn2(10) && !Deaf && !u.uswallow
761 && !(u.ustuck && !sticks(youmonst.data)))
762 verbalize("Move along!");
763 restfakecorr(grd);
764 return 0; /* didn't move */
766 x = grd->mx;
767 y = grd->my;
769 if (u_in_vault)
770 goto nextpos;
772 /* look around (hor & vert only) for accessible places */
773 for (nx = x - 1; nx <= x + 1; nx++)
774 for (ny = y - 1; ny <= y + 1; ny++) {
775 if ((nx == x || ny == y) && (nx != x || ny != y)
776 && isok(nx, ny)) {
777 typ = (crm = &levl[nx][ny])->typ;
778 if (!IS_STWALL(typ) && !IS_POOL(typ)) {
779 if (in_fcorridor(grd, nx, ny))
780 goto nextnxy;
782 if (*in_rooms(nx, ny, VAULT))
783 continue;
785 /* seems we found a good place to leave him alone */
786 egrd->gddone = 1;
787 if (ACCESSIBLE(typ))
788 goto newpos;
789 #ifdef STUPID
790 if (typ == SCORR)
791 crm->typ = CORR;
792 else
793 crm->typ = DOOR;
794 #else
795 crm->typ = (typ == SCORR) ? CORR : DOOR;
796 #endif
797 if (crm->typ == DOOR)
798 crm->doormask = D_NODOOR;
799 goto proceed;
802 nextnxy:
805 nextpos:
806 nx = x;
807 ny = y;
808 gx = egrd->gdx;
809 gy = egrd->gdy;
810 dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
811 dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
812 if (abs(gx - x) >= abs(gy - y))
813 nx += dx;
814 else
815 ny += dy;
817 while ((typ = (crm = &levl[nx][ny])->typ) != STONE) {
818 /* in view of the above we must have IS_WALL(typ) or typ == POOL */
819 /* must be a wall here */
820 if (isok(nx + nx - x, ny + ny - y) && !IS_POOL(typ)
821 && IS_ROOM(levl[nx + nx - x][ny + ny - y].typ)) {
822 crm->typ = DOOR;
823 crm->doormask = D_NODOOR;
824 goto proceed;
826 if (dy && nx != x) {
827 nx = x;
828 ny = y + dy;
829 continue;
831 if (dx && ny != y) {
832 ny = y;
833 nx = x + dx;
834 dy = 0;
835 continue;
837 /* I don't like this, but ... */
838 if (IS_ROOM(typ)) {
839 crm->typ = DOOR;
840 crm->doormask = D_NODOOR;
841 goto proceed;
843 break;
845 crm->typ = CORR;
846 proceed:
847 newspot = TRUE;
848 unblock_point(nx, ny); /* doesn't block light */
849 if (cansee(nx, ny))
850 newsym(nx, ny);
852 fcp = &(egrd->fakecorr[egrd->fcend]);
853 if (egrd->fcend++ == FCSIZ)
854 panic("fakecorr overflow");
855 fcp->fx = nx;
856 fcp->fy = ny;
857 fcp->ftyp = typ;
858 newpos:
859 if (egrd->gddone) {
860 /* The following is a kludge. We need to keep */
861 /* the guard around in order to be able to make */
862 /* the fake corridor disappear as the player */
863 /* moves out of it, but we also need the guard */
864 /* out of the way. We send the guard to never- */
865 /* never land. We set ogx ogy to mx my in order */
866 /* to avoid a check at the top of this function. */
867 /* At the end of the process, the guard is killed */
868 /* in restfakecorr(). */
869 cleanup:
870 x = grd->mx;
871 y = grd->my;
873 see_guard = canspotmon(grd);
874 wallify_vault(grd);
875 remove_monster(grd->mx, grd->my);
876 newsym(grd->mx, grd->my);
877 place_monster(grd, 0, 0);
878 egrd->ogx = grd->mx;
879 egrd->ogy = grd->my;
880 restfakecorr(grd);
881 if (!semi_dead && (in_fcorridor(grd, u.ux, u.uy) || cansee(x, y))) {
882 if (!disappear_msg_seen && see_guard)
883 pline("Suddenly, %s disappears.", noit_mon_nam(grd));
884 return 1;
886 return -2;
888 egrd->ogx = grd->mx; /* update old positions */
889 egrd->ogy = grd->my;
890 remove_monster(grd->mx, grd->my);
891 place_monster(grd, nx, ny);
892 if (newspot && g_at(nx, ny)) {
893 /* if there's gold already here (most likely from mineralize()),
894 pick it up now so that guard doesn't later think hero dropped
895 it and give an inappropriate message */
896 mpickgold(grd);
897 if (canspotmon(grd))
898 pline("%s picks up some gold.", Monnam(grd));
899 } else
900 newsym(grd->mx, grd->my);
901 restfakecorr(grd);
902 return 1;
905 /* Routine when dying or quitting with a vault guard around */
906 void
907 paygd()
909 register struct monst *grd = findgd();
910 long umoney = money_cnt(invent);
911 struct obj *coins, *nextcoins;
912 int gx, gy;
913 char buf[BUFSZ];
915 if (!umoney || !grd)
916 return;
918 if (u.uinvault) {
919 Your("%ld %s goes into the Magic Memory Vault.", umoney,
920 currency(umoney));
921 gx = u.ux;
922 gy = u.uy;
923 } else {
924 if (grd->mpeaceful) { /* guard has no "right" to your gold */
925 mongone(grd);
926 return;
928 mnexto(grd);
929 pline("%s remits your gold to the vault.", Monnam(grd));
930 gx = rooms[EGD(grd)->vroom].lx + rn2(2);
931 gy = rooms[EGD(grd)->vroom].ly + rn2(2);
932 Sprintf(buf, "To Croesus: here's the gold recovered from %s the %s.",
933 plname, mons[u.umonster].mname);
934 make_grave(gx, gy, buf);
936 for (coins = invent; coins; coins = nextcoins) {
937 nextcoins = coins->nobj;
938 if (objects[coins->otyp].oc_class == COIN_CLASS) {
939 freeinv(coins);
940 place_object(coins, gx, gy);
941 stackobj(coins);
944 mongone(grd);
947 long
948 hidden_gold()
950 long value = 0L;
951 struct obj *obj;
953 for (obj = invent; obj; obj = obj->nobj)
954 if (Has_contents(obj))
955 value += contained_gold(obj);
956 /* unknown gold stuck inside statues may cause some consternation... */
958 return value;
961 /* prevent "You hear footsteps.." when inappropriate */
962 boolean
963 gd_sound()
965 struct monst *grd = findgd();
967 if (vault_occupied(u.urooms))
968 return FALSE;
969 else
970 return (boolean) (grd == (struct monst *) 0);
973 void
974 vault_gd_watching(activity)
975 unsigned int activity;
977 struct monst *guard = findgd();
979 if (guard && guard->mcansee && m_canseeu(guard)) {
980 if (activity == GD_EATGOLD || activity == GD_DESTROYGOLD)
981 EGD(guard)->witness = activity;
985 /*vault.c*/