1 /* SCCS Id: @(#)vault.c 3.4 2003/01/15 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 #include "hack.h"
6 #include "vault.h"
7
8 STATIC_DCL struct monst *NDECL(findgd);
9
10 #define g_monnam(mtmp) \
11 x_monnam(mtmp, ARTICLE_NONE, (char *)0, SUPPRESS_IT, FALSE)
12
13 #ifdef OVLB
14
15 STATIC_DCL boolean FDECL(clear_fcorr, (struct monst *,BOOLEAN_P));
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 STATIC_OVL boolean
clear_fcorr(grd,forceshow)22 clear_fcorr(grd, forceshow)
23 register struct monst *grd;
24 register boolean forceshow;
25 {
26 register int fcx, fcy, fcbeg;
27 register struct monst *mtmp;
28
29 if (!on_level(&(EGD(grd)->gdlevel), &u.uz)) return TRUE;
30
31 while((fcbeg = EGD(grd)->fcbeg) < EGD(grd)->fcend) {
32 fcx = EGD(grd)->fakecorr[fcbeg].fx;
33 fcy = EGD(grd)->fakecorr[fcbeg].fy;
34 if((grd->mhp <= 0 || !in_fcorridor(grd, u.ux, u.uy)) &&
35 EGD(grd)->gddone)
36 forceshow = TRUE;
37 if((u.ux == fcx && u.uy == fcy && grd->mhp > 0)
38 || (!forceshow && couldsee(fcx,fcy))
39 || (Punished && !carried(uball)
40 && uball->ox == fcx && uball->oy == fcy))
41 return FALSE;
42
43 if ((mtmp = m_at(fcx,fcy)) != 0) {
44 if(mtmp->isgd) return(FALSE);
45 else if(!in_fcorridor(grd, u.ux, u.uy)) {
46 if(mtmp->mtame) yelp(mtmp);
47 (void) rloc(mtmp, FALSE);
48 }
49 }
50 levl[fcx][fcy].typ = EGD(grd)->fakecorr[fcbeg].ftyp;
51 map_location(fcx, fcy, 1); /* bypass vision */
52 if(!ACCESSIBLE(levl[fcx][fcy].typ)) block_point(fcx,fcy);
53 EGD(grd)->fcbeg++;
54 }
55 if(grd->mhp <= 0) {
56 pline_The("corridor disappears.");
57 if(IS_ROCK(levl[u.ux][u.uy].typ)) You("are encased in rock.");
58 }
59 return(TRUE);
60 }
61
62 STATIC_OVL void
restfakecorr(grd)63 restfakecorr(grd)
64 register struct monst *grd;
65 {
66 /* it seems you left the corridor - let the guard disappear */
67 if(clear_fcorr(grd, FALSE)) mongone(grd);
68 }
69
70 boolean
grddead(grd)71 grddead(grd) /* called in mon.c */
72 register struct monst *grd;
73 {
74 register boolean dispose = clear_fcorr(grd, TRUE);
75
76 if(!dispose) {
77 /* see comment by newpos in gd_move() */
78 remove_monster(grd->mx, grd->my);
79 newsym(grd->mx, grd->my);
80 place_monster(grd, 0, 0);
81 EGD(grd)->ogx = grd->mx;
82 EGD(grd)->ogy = grd->my;
83 dispose = clear_fcorr(grd, TRUE);
84 }
85 return(dispose);
86 }
87
88 STATIC_OVL boolean
in_fcorridor(grd,x,y)89 in_fcorridor(grd, x, y)
90 register struct monst *grd;
91 int x, y;
92 {
93 register int fci;
94
95 for(fci = EGD(grd)->fcbeg; fci < EGD(grd)->fcend; fci++)
96 if(x == EGD(grd)->fakecorr[fci].fx &&
97 y == EGD(grd)->fakecorr[fci].fy)
98 return(TRUE);
99 return(FALSE);
100 }
101
102 STATIC_OVL
103 struct monst *
findgd()104 findgd()
105 {
106 register struct monst *mtmp;
107
108 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
109 if(mtmp->isgd && !DEADMONSTER(mtmp) && on_level(&(EGD(mtmp)->gdlevel), &u.uz))
110 return(mtmp);
111 return((struct monst *)0);
112 }
113
114 #endif /* OVLB */
115 #ifdef OVL0
116
117 char
vault_occupied(array)118 vault_occupied(array)
119 char *array;
120 {
121 register char *ptr;
122
123 for (ptr = array; *ptr; ptr++)
124 if (rooms[*ptr - ROOMOFFSET].rtype == VAULT)
125 return(*ptr);
126 return('\0');
127 }
128
129 void
invault()130 invault()
131 {
132 #ifdef BSD_43_BUG
133 int dummy; /* hack to avoid schain botch */
134 #endif
135 struct monst *guard;
136 int trycount, vaultroom = (int)vault_occupied(u.urooms);
137
138 if(!vaultroom) {
139 u.uinvault = 0;
140 return;
141 }
142
143 vaultroom -= ROOMOFFSET;
144
145 guard = findgd();
146 if(++u.uinvault % 30 == 0 && !guard) { /* if time ok and no guard now. */
147 char buf[BUFSZ];
148 register int x, y, dd, gx, gy;
149 int lx = 0, ly = 0;
150 #ifdef GOLDOBJ
151 long umoney;
152 #endif
153 /* first find the goal for the guard */
154 for(dd = 2; (dd < ROWNO || dd < COLNO); dd++) {
155 for(y = u.uy-dd; y <= u.uy+dd; ly = y, y++) {
156 if(y < 0 || y > ROWNO-1) continue;
157 for(x = u.ux-dd; x <= u.ux+dd; lx = x, x++) {
158 if(y != u.uy-dd && y != u.uy+dd && x != u.ux-dd)
159 x = u.ux+dd;
160 if(x < 1 || x > COLNO-1) continue;
161 if(levl[x][y].typ == CORR) {
162 if(x < u.ux) lx = x + 1;
163 else if(x > u.ux) lx = x - 1;
164 else lx = x;
165 if(y < u.uy) ly = y + 1;
166 else if(y > u.uy) ly = y - 1;
167 else ly = y;
168 if(levl[lx][ly].typ != STONE && levl[lx][ly].typ != CORR)
169 goto incr_radius;
170 goto fnd;
171 }
172 }
173 }
174 incr_radius: ;
175 }
176 impossible("Not a single corridor on this level??");
177 tele();
178 return;
179 fnd:
180 gx = x; gy = y;
181
182 /* next find a good place for a door in the wall */
183 x = u.ux; y = u.uy;
184 if(levl[x][y].typ != ROOM) { /* player dug a door and is in it */
185 if(levl[x+1][y].typ == ROOM) x = x + 1;
186 else if(levl[x][y+1].typ == ROOM) y = y + 1;
187 else if(levl[x-1][y].typ == ROOM) x = x - 1;
188 else if(levl[x][y-1].typ == ROOM) y = y - 1;
189 else if(levl[x+1][y+1].typ == ROOM) {
190 x = x + 1;
191 y = y + 1;
192 } else if (levl[x-1][y-1].typ == ROOM) {
193 x = x - 1;
194 y = y - 1;
195 } else if (levl[x+1][y-1].typ == ROOM) {
196 x = x + 1;
197 y = y - 1;
198 } else if (levl[x-1][y+1].typ == ROOM) {
199 x = x - 1;
200 y = y + 1;
201 }
202 }
203 while(levl[x][y].typ == ROOM) {
204 register int dx,dy;
205
206 dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
207 dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
208 if(abs(gx-x) >= abs(gy-y))
209 x += dx;
210 else
211 y += dy;
212 }
213 if(x == u.ux && y == u.uy) {
214 if(levl[x+1][y].typ == HWALL || levl[x+1][y].typ == DOOR)
215 x = x + 1;
216 else if(levl[x-1][y].typ == HWALL || levl[x-1][y].typ == DOOR)
217 x = x - 1;
218 else if(levl[x][y+1].typ == VWALL || levl[x][y+1].typ == DOOR)
219 y = y + 1;
220 else if(levl[x][y-1].typ == VWALL || levl[x][y-1].typ == DOOR)
221 y = y - 1;
222 else return;
223 }
224
225 /* make something interesting happen */
226 if(!(guard = makemon(&mons[PM_GUARD], x, y, NO_MM_FLAGS))) return;
227 guard->isgd = 1;
228 guard->mpeaceful = 1;
229 set_malign(guard);
230 EGD(guard)->gddone = 0;
231 EGD(guard)->ogx = x;
232 EGD(guard)->ogy = y;
233 assign_level(&(EGD(guard)->gdlevel), &u.uz);
234 EGD(guard)->vroom = vaultroom;
235 EGD(guard)->warncnt = 0;
236
237 reset_faint(); /* if fainted - wake up */
238 if (canspotmon(guard))
239 pline("Suddenly one of the Vault's %s enters!",
240 makeplural(g_monnam(guard)));
241 else
242 pline("Someone else has entered the Vault.");
243 newsym(guard->mx,guard->my);
244 if (youmonst.m_ap_type == M_AP_OBJECT || u.uundetected) {
245 if (youmonst.m_ap_type == M_AP_OBJECT &&
246 youmonst.mappearance != GOLD_PIECE)
247 verbalize("Hey! Who left that %s in here?", mimic_obj_name(&youmonst));
248 /* You're mimicking some object or you're hidden. */
249 pline("Puzzled, %s turns around and leaves.", mhe(guard));
250 mongone(guard);
251 return;
252 }
253 if (Strangled || is_silent(youmonst.data) || multi < 0) {
254 /* [we ought to record whether this this message has already
255 been given in order to vary it upon repeat visits, but
256 discarding the monster and its egd data renders that hard] */
257 verbalize("I'll be back when you're ready to speak to me!");
258 mongone(guard);
259 return;
260 }
261
262 stop_occupation(); /* if occupied, stop it *now* */
263 if (multi > 0) { nomul(0, 0); unmul((char *)0); }
264 trycount = 5;
265 do {
266 getlin("\"Hello stranger, who are you?\" -", buf);
267 (void) mungspaces(buf);
268 } while (!letter(buf[0]) && --trycount > 0);
269
270 if (u.ualign.type == A_LAWFUL &&
271 /* ignore trailing text, in case player includes character's rank */
272 strncmpi(buf, plname, (int) strlen(plname)) != 0) {
273 adjalign(-1); /* Liar! */
274 }
275
276 if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos")
277 #ifdef TOURIST
278 || !strcmpi(buf, "Creosote")
279 #endif
280 ) {
281 if (!mvitals[PM_CROESUS].died) {
282 verbalize("Oh, yes, of course. Sorry to have disturbed you.");
283 mongone(guard);
284 } else {
285 setmangry(guard);
286 verbalize("Back from the dead, are you? I'll remedy that!");
287 /* don't want guard to waste next turn wielding a weapon */
288 if (!MON_WEP(guard)) {
289 guard->weapon_check = NEED_HTH_WEAPON;
290 (void) mon_wield_item(guard);
291 }
292 }
293 return;
294 }
295 verbalize("I don't know you.");
296 #ifndef GOLDOBJ
297 if (!u.ugold && !hidden_gold())
298 verbalize("Please follow me.");
299 else {
300 if (!u.ugold)
301 verbalize("You have hidden gold.");
302 verbalize("Most likely all your gold was stolen from this vault.");
303 verbalize("Please drop that gold and follow me.");
304 }
305 #else
306 umoney = money_cnt(invent);
307 if (!umoney && !hidden_gold())
308 verbalize("Please follow me.");
309 else {
310 if (!umoney)
311 verbalize("You have hidden money.");
312 verbalize("Most likely all your money was stolen from this vault.");
313 verbalize("Please drop that money and follow me.");
314 }
315 #endif
316 EGD(guard)->gdx = gx;
317 EGD(guard)->gdy = gy;
318 EGD(guard)->fcbeg = 0;
319 EGD(guard)->fakecorr[0].fx = x;
320 EGD(guard)->fakecorr[0].fy = y;
321 if(IS_WALL(levl[x][y].typ))
322 EGD(guard)->fakecorr[0].ftyp = levl[x][y].typ;
323 else { /* the initial guard location is a dug door */
324 int vlt = EGD(guard)->vroom;
325 xchar lowx = rooms[vlt].lx, hix = rooms[vlt].hx;
326 xchar lowy = rooms[vlt].ly, hiy = rooms[vlt].hy;
327
328 if(x == lowx-1 && y == lowy-1)
329 EGD(guard)->fakecorr[0].ftyp = TLCORNER;
330 else if(x == hix+1 && y == lowy-1)
331 EGD(guard)->fakecorr[0].ftyp = TRCORNER;
332 else if(x == lowx-1 && y == hiy+1)
333 EGD(guard)->fakecorr[0].ftyp = BLCORNER;
334 else if(x == hix+1 && y == hiy+1)
335 EGD(guard)->fakecorr[0].ftyp = BRCORNER;
336 else if(y == lowy-1 || y == hiy+1)
337 EGD(guard)->fakecorr[0].ftyp = HWALL;
338 else if(x == lowx-1 || x == hix+1)
339 EGD(guard)->fakecorr[0].ftyp = VWALL;
340 }
341 levl[x][y].typ = DOOR;
342 levl[x][y].doormask = D_NODOOR;
343 unblock_point(x, y); /* doesn't block light */
344 EGD(guard)->fcend = 1;
345 EGD(guard)->warncnt = 1;
346 }
347 }
348
349 #endif /* OVL0 */
350 #ifdef OVLB
351
352 STATIC_OVL void
move_gold(gold,vroom)353 move_gold(gold, vroom)
354 struct obj *gold;
355 int vroom;
356 {
357 xchar nx, ny;
358
359 remove_object(gold);
360 newsym(gold->ox, gold->oy);
361 nx = rooms[vroom].lx + rn2(2);
362 ny = rooms[vroom].ly + rn2(2);
363 place_object(gold, nx, ny);
364 stackobj(gold);
365 newsym(nx,ny);
366 }
367
368 STATIC_OVL void
wallify_vault(grd)369 wallify_vault(grd)
370 struct monst *grd;
371 {
372 int x, y, typ;
373 int vlt = EGD(grd)->vroom;
374 char tmp_viz;
375 xchar lox = rooms[vlt].lx - 1, hix = rooms[vlt].hx + 1,
376 loy = rooms[vlt].ly - 1, hiy = rooms[vlt].hy + 1;
377 struct monst *mon;
378 struct obj *gold;
379 struct trap *trap;
380 boolean fixed = FALSE;
381 boolean movedgold = FALSE;
382
383 for (x = lox; x <= hix; x++)
384 for (y = loy; y <= hiy; y++) {
385 /* if not on the room boundary, skip ahead */
386 if (x != lox && x != hix && y != loy && y != hiy) continue;
387
388 if (!IS_WALL(levl[x][y].typ) && !in_fcorridor(grd, x, y)) {
389 if ((mon = m_at(x, y)) != 0 && mon != grd) {
390 if (mon->mtame) yelp(mon);
391 (void) rloc(mon, FALSE);
392 }
393 if ((gold = g_at(x, y)) != 0) {
394 move_gold(gold, EGD(grd)->vroom);
395 movedgold = TRUE;
396 }
397 if ((trap = t_at(x, y)) != 0)
398 deltrap(trap);
399 if (x == lox)
400 typ = (y == loy) ? TLCORNER :
401 (y == hiy) ? BLCORNER : VWALL;
402 else if (x == hix)
403 typ = (y == loy) ? TRCORNER :
404 (y == hiy) ? BRCORNER : VWALL;
405 else /* not left or right side, must be top or bottom */
406 typ = HWALL;
407 levl[x][y].typ = typ;
408 levl[x][y].doormask = 0;
409 /*
410 * hack: player knows walls are restored because of the
411 * message, below, so show this on the screen.
412 */
413 tmp_viz = viz_array[y][x];
414 viz_array[y][x] = IN_SIGHT|COULD_SEE;
415 newsym(x,y);
416 viz_array[y][x] = tmp_viz;
417 block_point(x,y);
418 fixed = TRUE;
419 }
420 }
421
422 if(movedgold || fixed) {
423 if(in_fcorridor(grd, grd->mx, grd->my) || cansee(grd->mx, grd->my))
424 pline_The("%s whispers an incantation.", g_monnam(grd));
425 else You_hear("a distant chant.");
426 if(movedgold)
427 pline("A mysterious force moves the gold into the vault.");
428 if(fixed)
429 pline_The("damaged vault's walls are magically restored!");
430 }
431 }
432
433 /*
434 * return 1: guard moved, 0: guard didn't, -1: let m_move do it, -2: died
435 */
436 int
gd_move(grd)437 gd_move(grd)
438 register struct monst *grd;
439 {
440 int x, y, nx, ny, m, n;
441 int dx, dy, gx, gy, fci;
442 uchar typ;
443 struct fakecorridor *fcp;
444 register struct egd *egrd = EGD(grd);
445 register struct rm *crm;
446 register boolean goldincorridor = FALSE,
447 u_in_vault = vault_occupied(u.urooms)? TRUE : FALSE,
448 grd_in_vault = *in_rooms(grd->mx, grd->my, VAULT)?
449 TRUE : FALSE;
450 boolean disappear_msg_seen = FALSE, semi_dead = (grd->mhp <= 0);
451 #ifndef GOLDOBJ
452 register boolean u_carry_gold = ((u.ugold + hidden_gold()) > 0L);
453 #else
454 long umoney = money_cnt(invent);
455 register boolean u_carry_gold = ((umoney + hidden_gold()) > 0L);
456 #endif
457 boolean see_guard;
458
459 if(!on_level(&(egrd->gdlevel), &u.uz)) return(-1);
460 nx = ny = m = n = 0;
461 if(!u_in_vault && !grd_in_vault)
462 wallify_vault(grd);
463 if(!grd->mpeaceful) {
464 if(semi_dead) {
465 egrd->gddone =1;
466 goto newpos;
467 }
468 if(!u_in_vault &&
469 (grd_in_vault ||
470 (in_fcorridor(grd, grd->mx, grd->my) &&
471 !in_fcorridor(grd, u.ux, u.uy)))) {
472 (void) rloc(grd, FALSE);
473 wallify_vault(grd);
474 (void) clear_fcorr(grd, TRUE);
475 goto letknow;
476 }
477 if(!in_fcorridor(grd, grd->mx, grd->my))
478 (void) clear_fcorr(grd, TRUE);
479 return(-1);
480 }
481 if(abs(egrd->ogx - grd->mx) > 1 ||
482 abs(egrd->ogy - grd->my) > 1)
483 return(-1); /* teleported guard - treat as monster */
484 if(egrd->fcend == 1) {
485 if(u_in_vault &&
486 (u_carry_gold || um_dist(grd->mx, grd->my, 1))) {
487 if(egrd->warncnt == 3)
488 verbalize("I repeat, %sfollow me!",
489 u_carry_gold ? (
490 #ifndef GOLDOBJ
491 !u.ugold ?
492 "drop that hidden gold and " :
493 "drop that gold and ") : "");
494 #else
495 !umoney ?
496 "drop that hidden money and " :
497 "drop that money and ") : "");
498 #endif
499 if(egrd->warncnt == 7) {
500 m = grd->mx;
501 n = grd->my;
502 verbalize("You've been warned, knave!");
503 mnexto(grd);
504 levl[m][n].typ = egrd->fakecorr[0].ftyp;
505 newsym(m,n);
506 grd->mpeaceful = 0;
507 return(-1);
508 }
509 /* not fair to get mad when (s)he's fainted or paralyzed */
510 if(!is_fainted() && multi >= 0) egrd->warncnt++;
511 return(0);
512 }
513
514 if (!u_in_vault) {
515 if (u_carry_gold) { /* player teleported */
516 m = grd->mx;
517 n = grd->my;
518 (void) rloc(grd, FALSE);
519 levl[m][n].typ = egrd->fakecorr[0].ftyp;
520 newsym(m,n);
521 grd->mpeaceful = 0;
522 letknow:
523 if (!cansee(grd->mx, grd->my) || !mon_visible(grd))
524 You_hear("the shrill sound of a guard's whistle.");
525 else
526 You(um_dist(grd->mx, grd->my, 2) ?
527 "see an angry %s approaching." :
528 "are confronted by an angry %s.",
529 g_monnam(grd));
530 return(-1);
531 } else {
532 verbalize("Well, begone.");
533 wallify_vault(grd);
534 egrd->gddone = 1;
535 goto cleanup;
536 }
537 }
538 }
539
540 if(egrd->fcend > 1) {
541 if(egrd->fcend > 2 && in_fcorridor(grd, grd->mx, grd->my) &&
542 !egrd->gddone && !in_fcorridor(grd, u.ux, u.uy) &&
543 levl[egrd->fakecorr[0].fx][egrd->fakecorr[0].fy].typ
544 == egrd->fakecorr[0].ftyp) {
545 pline_The("%s, confused, disappears.", g_monnam(grd));
546 disappear_msg_seen = TRUE;
547 goto cleanup;
548 }
549 if(u_carry_gold &&
550 (in_fcorridor(grd, u.ux, u.uy) ||
551 /* cover a 'blind' spot */
552 (egrd->fcend > 1 && u_in_vault))) {
553 if(!grd->mx) {
554 restfakecorr(grd);
555 return(-2);
556 }
557 if(egrd->warncnt < 6) {
558 egrd->warncnt = 6;
559 verbalize("Drop all your gold, scoundrel!");
560 return(0);
561 } else {
562 verbalize("So be it, rogue!");
563 grd->mpeaceful = 0;
564 return(-1);
565 }
566 }
567 }
568 for(fci = egrd->fcbeg; fci < egrd->fcend; fci++)
569 if(g_at(egrd->fakecorr[fci].fx, egrd->fakecorr[fci].fy)){
570 m = egrd->fakecorr[fci].fx;
571 n = egrd->fakecorr[fci].fy;
572 goldincorridor = TRUE;
573 }
574 if(goldincorridor && !egrd->gddone) {
575 x = grd->mx;
576 y = grd->my;
577 if (m == u.ux && n == u.uy) {
578 struct obj *gold = g_at(m,n);
579 /* Grab the gold from between the hero's feet. */
580 #ifndef GOLDOBJ
581 grd->mgold += gold->quan;
582 delobj(gold);
583 #else
584 obj_extract_self(gold);
585 add_to_minv(grd, gold);
586 #endif
587 newsym(m,n);
588 } else if (m == x && n == y) {
589 mpickgold(grd); /* does a newsym */
590 } else {
591 /* just for insurance... */
592 if (MON_AT(m, n) && m != grd->mx && n != grd->my) {
593 verbalize("Out of my way, scum!");
594 (void) rloc(m_at(m, n), FALSE);
595 }
596 remove_monster(grd->mx, grd->my);
597 newsym(grd->mx, grd->my);
598 place_monster(grd, m, n);
599 mpickgold(grd); /* does a newsym */
600 }
601 if(cansee(m,n))
602 pline("%s%s picks up the gold.", Monnam(grd),
603 grd->mpeaceful ? " calms down and" : "");
604 if(x != grd->mx || y != grd->my) {
605 remove_monster(grd->mx, grd->my);
606 newsym(grd->mx, grd->my);
607 place_monster(grd, x, y);
608 newsym(x, y);
609 }
610 if(!grd->mpeaceful) return(-1);
611 else {
612 egrd->warncnt = 5;
613 return(0);
614 }
615 }
616 if(um_dist(grd->mx, grd->my, 1) || egrd->gddone) {
617 if(!egrd->gddone && !rn2(10)) verbalize("Move along!");
618 restfakecorr(grd);
619 return(0); /* didn't move */
620 }
621 x = grd->mx;
622 y = grd->my;
623
624 if(u_in_vault) goto nextpos;
625
626 /* look around (hor & vert only) for accessible places */
627 for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) {
628 if((nx == x || ny == y) && (nx != x || ny != y) && isok(nx, ny)) {
629
630 typ = (crm = &levl[nx][ny])->typ;
631 if(!IS_STWALL(typ) && !IS_POOL(typ)) {
632
633 if(in_fcorridor(grd, nx, ny))
634 goto nextnxy;
635
636 if(*in_rooms(nx,ny,VAULT))
637 continue;
638
639 /* seems we found a good place to leave him alone */
640 egrd->gddone = 1;
641 if(ACCESSIBLE(typ)) goto newpos;
642 #ifdef STUPID
643 if (typ == SCORR)
644 crm->typ = CORR;
645 else
646 crm->typ = DOOR;
647 #else
648 crm->typ = (typ == SCORR) ? CORR : DOOR;
649 #endif
650 if(crm->typ == DOOR) crm->doormask = D_NODOOR;
651 goto proceed;
652 }
653 }
654 nextnxy: ;
655 }
656 nextpos:
657 nx = x;
658 ny = y;
659 gx = egrd->gdx;
660 gy = egrd->gdy;
661 dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
662 dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
663 if(abs(gx-x) >= abs(gy-y)) nx += dx; else ny += dy;
664
665 while((typ = (crm = &levl[nx][ny])->typ) != 0) {
666 /* in view of the above we must have IS_WALL(typ) or typ == POOL */
667 /* must be a wall here */
668 if(isok(nx+nx-x,ny+ny-y) && !IS_POOL(typ) &&
669 IS_ROOM(levl[nx+nx-x][ny+ny-y].typ)){
670 crm->typ = DOOR;
671 crm->doormask = D_NODOOR;
672 goto proceed;
673 }
674 if(dy && nx != x) {
675 nx = x; ny = y+dy;
676 continue;
677 }
678 if(dx && ny != y) {
679 ny = y; nx = x+dx; dy = 0;
680 continue;
681 }
682 /* I don't like this, but ... */
683 if(IS_ROOM(typ)) {
684 crm->typ = DOOR;
685 crm->doormask = D_NODOOR;
686 goto proceed;
687 }
688 break;
689 }
690 crm->typ = CORR;
691 proceed:
692 unblock_point(nx, ny); /* doesn't block light */
693 if (cansee(nx,ny))
694 newsym(nx,ny);
695
696 fcp = &(egrd->fakecorr[egrd->fcend]);
697 if(egrd->fcend++ == FCSIZ) panic("fakecorr overflow");
698 fcp->fx = nx;
699 fcp->fy = ny;
700 fcp->ftyp = typ;
701 newpos:
702 if(egrd->gddone) {
703 /* The following is a kludge. We need to keep */
704 /* the guard around in order to be able to make */
705 /* the fake corridor disappear as the player */
706 /* moves out of it, but we also need the guard */
707 /* out of the way. We send the guard to never- */
708 /* never land. We set ogx ogy to mx my in order */
709 /* to avoid a check at the top of this function. */
710 /* At the end of the process, the guard is killed */
711 /* in restfakecorr(). */
712 cleanup:
713 x = grd->mx; y = grd->my;
714
715 see_guard = canspotmon(grd);
716 wallify_vault(grd);
717 remove_monster(grd->mx, grd->my);
718 newsym(grd->mx,grd->my);
719 place_monster(grd, 0, 0);
720 egrd->ogx = grd->mx;
721 egrd->ogy = grd->my;
722 restfakecorr(grd);
723 if(!semi_dead && (in_fcorridor(grd, u.ux, u.uy) ||
724 cansee(x, y))) {
725 if (!disappear_msg_seen && see_guard)
726 pline("Suddenly, the %s disappears.", g_monnam(grd));
727 return(1);
728 }
729 return(-2);
730 }
731 egrd->ogx = grd->mx; /* update old positions */
732 egrd->ogy = grd->my;
733 remove_monster(grd->mx, grd->my);
734 place_monster(grd, nx, ny);
735 newsym(grd->mx,grd->my);
736 restfakecorr(grd);
737 return(1);
738 }
739
740 /* Routine when dying or quitting with a vault guard around */
741 void
paygd()742 paygd()
743 {
744 register struct monst *grd = findgd();
745 #ifndef GOLDOBJ
746 struct obj *gold;
747 #else
748 long umoney = money_cnt(invent);
749 struct obj *coins, *nextcoins;
750 #endif
751 int gx,gy;
752 char buf[BUFSZ];
753
754 #ifndef GOLDOBJ
755 if (!u.ugold || !grd) return;
756 #else
757 if (!umoney || !grd) return;
758 #endif
759
760 if (u.uinvault) {
761 Your("%ld %s goes into the Magic Memory Vault.",
762 #ifndef GOLDOBJ
763 u.ugold,
764 currency(u.ugold));
765 #else
766 umoney,
767 currency(umoney));
768 #endif
769 gx = u.ux;
770 gy = u.uy;
771 } else {
772 if(grd->mpeaceful) { /* guard has no "right" to your gold */
773 mongone(grd);
774 return;
775 }
776 mnexto(grd);
777 pline("%s remits your gold to the vault.", Monnam(grd));
778 gx = rooms[EGD(grd)->vroom].lx + rn2(2);
779 gy = rooms[EGD(grd)->vroom].ly + rn2(2);
780 Sprintf(buf,
781 "To Croesus: here's the gold recovered from %s the %s.",
782 plname, mons[u.umonster].mname);
783 make_grave(gx, gy, buf);
784 }
785 #ifndef GOLDOBJ
786 place_object(gold = mkgoldobj(u.ugold), gx, gy);
787 stackobj(gold);
788 #else
789 for (coins = invent; coins; coins = nextcoins) {
790 nextcoins = coins->nobj;
791 if (objects[coins->otyp].oc_class == COIN_CLASS) {
792 freeinv(coins);
793 place_object(coins, gx, gy);
794 stackobj(coins);
795 }
796 }
797 #endif
798 mongone(grd);
799 }
800
801 long
hidden_gold()802 hidden_gold()
803 {
804 register long value = 0L;
805 register struct obj *obj;
806
807 for (obj = invent; obj; obj = obj->nobj)
808 if (Has_contents(obj))
809 value += contained_gold(obj);
810 /* unknown gold stuck inside statues may cause some consternation... */
811
812 return(value);
813 }
814
815 boolean
gd_sound()816 gd_sound() /* prevent "You hear footsteps.." when inappropriate */
817 {
818 register struct monst *grd = findgd();
819
820 if (vault_occupied(u.urooms)) return(FALSE);
821 else return((boolean)(grd == (struct monst *)0));
822 }
823
824 #endif /* OVLB */
825
826 /*vault.c*/
827