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