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