1 /*	SCCS Id: @(#)priest.c	3.4	2002/11/06	*/
2 /* Copyright (c) Izchak Miller, Steve Linhart, 1989.		  */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include "hack.h"
6 #include "mfndpos.h"
7 #include "eshk.h"
8 #include "epri.h"
9 #include "emin.h"
10 
11 /* this matches the categorizations shown by enlightenment */
12 #define ALGN_SINNED	(-4)	/* worse than strayed */
13 
14 STATIC_DCL boolean FDECL(histemple_at,(struct monst *,XCHAR_P,XCHAR_P));
15 STATIC_DCL boolean FDECL(has_shrine,(struct monst *));
16 
17 /*
18  * Move for priests and shopkeepers.  Called from shk_move() and pri_move().
19  * Valid returns are  1: moved  0: didn't  -1: let m_move do it  -2: died.
20  */
21 int
move_special(mtmp,in_his_shop,appr,uondoor,avoid,omx,omy,gx,gy)22 move_special(mtmp,in_his_shop,appr,uondoor,avoid,omx,omy,gx,gy)
23 register struct monst *mtmp;
24 boolean in_his_shop;
25 schar appr;
26 boolean uondoor,avoid;
27 register xchar omx,omy,gx,gy;
28 {
29 	register xchar nx,ny,nix,niy;
30 	register schar i;
31 	schar chcnt,cnt;
32 	coord poss[9];
33 	long info[9];
34 	long allowflags;
35 	struct obj *ib = (struct obj *)0;
36 
37 	if(omx == gx && omy == gy)
38 		return(0);
39 	if(mtmp->mconf) {
40 		avoid = FALSE;
41 		appr = 0;
42 	}
43 
44 	nix = omx;
45 	niy = omy;
46 	if (mtmp->isshk) allowflags = ALLOW_SSM;
47 	else allowflags = ALLOW_SSM | ALLOW_SANCT;
48 	if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK|ALLOW_WALL);
49 	if (throws_rocks(mtmp->data) || is_rockbreaker(mtmp->data)) allowflags |= ALLOW_ROCK;
50 	if (tunnels(mtmp->data)) allowflags |= ALLOW_DIG;
51 	if (!nohands(mtmp->data) && !verysmall(mtmp->data)) {
52 		allowflags |= OPENDOOR;
53 		if (m_carrying(mtmp, SKELETON_KEY)) allowflags |= BUSTDOOR;
54 	}
55 	if (is_giant(mtmp->data)) allowflags |= BUSTDOOR;
56 	cnt = mfndpos(mtmp, poss, info, allowflags);
57 
58 	if(mtmp->isshk && avoid && uondoor) { /* perhaps we cannot avoid him */
59 		for(i=0; i<cnt; i++)
60 		    if(!(info[i] & NOTONL)) goto pick_move;
61 		avoid = FALSE;
62 	}
63 
64 #define GDIST(x,y)	(dist2(x,y,gx,gy))
65 pick_move:
66 	chcnt = 0;
67 	for(i=0; i<cnt; i++) {
68 		nx = poss[i].x;
69 		ny = poss[i].y;
70 		if(levl[nx][ny].typ == ROOM ||
71 			(mtmp->ispriest &&
72 			    levl[nx][ny].typ == ALTAR) ||
73 			(mtmp->isshk &&
74 			    (!in_his_shop || ESHK(mtmp)->following))) {
75 		    if(avoid && (info[i] & NOTONL))
76 			continue;
77 		    if((!appr && !rn2(++chcnt)) ||
78 			(appr && GDIST(nx,ny) < GDIST(nix,niy))) {
79 			    nix = nx;
80 			    niy = ny;
81 		    }
82 		}
83 	}
84 	if(mtmp->ispriest && avoid &&
85 			nix == omx && niy == omy && onlineu(omx,omy)) {
86 		/* might as well move closer as long it's going to stay
87 		 * lined up */
88 		avoid = FALSE;
89 		goto pick_move;
90 	}
91 
92 	if(nix != omx || niy != omy) {
93 		remove_monster(omx, omy);
94 		newsym(omx,omy);
95 		place_monster(mtmp, nix, niy);
96 		newsym(nix,niy);
97 		if (mtmp->isshk && !in_his_shop && inhishop(mtmp))
98 		    check_special_room(FALSE);
99 		if ((ib = sobj_at(BOULDER, nix, niy))) {
100 			mpickup_obj(mtmp, ib);
101 		}
102 		newsym(nix,niy);
103 		return(1);
104 	}
105 	return(0);
106 }
107 
108 char
temple_occupied(array)109 temple_occupied(array)
110 register char *array;
111 {
112 	register char *ptr;
113 
114 	for (ptr = array; *ptr; ptr++)
115 		if (rooms[*ptr - ROOMOFFSET].rtype == TEMPLE)
116 			return(*ptr);
117 	return('\0');
118 }
119 
120 STATIC_OVL boolean
histemple_at(priest,x,y)121 histemple_at(priest, x, y)
122 register struct monst *priest;
123 register xchar x, y;
124 {
125 	return((boolean)((EPRI(priest)->shroom == *in_rooms(x, y, TEMPLE)) &&
126 	       on_level(&(EPRI(priest)->shrlevel), &u.uz)));
127 }
128 
129 /*
130  * pri_move: return 1: moved  0: didn't  -1: let m_move do it  -2: died
131  */
132 int
pri_move(priest)133 pri_move(priest)
134 register struct monst *priest;
135 {
136 	register xchar gx,gy,omx,omy;
137 	schar temple;
138 	boolean avoid = TRUE;
139 
140 	omx = priest->mx;
141 	omy = priest->my;
142 
143 	if(!histemple_at(priest, omx, omy)) return(-1);
144 
145 	temple = EPRI(priest)->shroom;
146 
147 	gx = EPRI(priest)->shrpos.x;
148 	gy = EPRI(priest)->shrpos.y;
149 
150 	gx += rn1(3,-1);	/* mill around the altar */
151 	gy += rn1(3,-1);
152 
153 	if(!priest->mpeaceful ||
154 	   (Conflict && !resist(priest, RING_CLASS, 0, 0))) {
155 		if(monnear(priest, u.ux, u.uy)) {
156 			if(Displaced)
157 				Your("displaced image doesn't fool %s!",
158 					mon_nam(priest));
159 			(void) mattacku(priest);
160 			return(0);
161 		} else if(index(u.urooms, temple)) {
162 			/* chase player if inside temple & can see him */
163 			if(priest->mcansee && m_canseeu(priest)) {
164 				gx = u.ux;
165 				gy = u.uy;
166 			}
167 			avoid = FALSE;
168 		}
169 	} else if(Invis) avoid = FALSE;
170 
171 	return(move_special(priest,FALSE,TRUE,FALSE,avoid,omx,omy,gx,gy));
172 }
173 
174 /* exclusively for mktemple() */
175 void
priestini(lvl,sroom,sx,sy,sanctum)176 priestini(lvl, sroom, sx, sy, sanctum)
177 d_level	*lvl;
178 struct mkroom *sroom;
179 int sx, sy;
180 boolean sanctum;   /* is it the seat of the high priest? */
181 {
182 	struct monst *priest;
183 	struct obj *otmp = NULL;
184 	int cnt;
185 
186 	if(MON_AT(sx+1, sy))
187 		(void) rloc(m_at(sx+1, sy), FALSE); /* insurance */
188 
189 	priest = makemon(&mons[sanctum ? PM_HIGH_PRIEST : PM_ALIGNED_PRIEST],
190 			 sx + 1, sy, NO_MM_FLAGS);
191 	if (priest) {
192 		EPRI(priest)->shroom = (sroom - rooms) + ROOMOFFSET;
193 		EPRI(priest)->shralign = Amask2align(levl[sx][sy].altarmask);
194 		EPRI(priest)->shrpos.x = sx;
195 		EPRI(priest)->shrpos.y = sy;
196 		assign_level(&(EPRI(priest)->shrlevel), lvl);
197 		priest->mtrapseen = ~0;	/* traps are known */
198 		priest->mpeaceful = 1;
199 		priest->ispriest = 1;
200 		priest->msleeping = 0;
201 		set_malign(priest); /* mpeaceful may have changed */
202 
203 		/* Cthulhu is Molochs new high priest */
204 		/* if(sanctum && EPRI(priest)->shralign == A_NONE &&
205 		     on_level(&sanctum_level, &u.uz)) {
206 			(void) mongets(priest, AMULET_OF_YENDOR);
207 		} */
208 		/* 2 to 4 spellbooks */
209 		for (cnt = rn1(3,2); cnt > 0; --cnt) {
210 		    (void) mpickobj(priest, mkobj(SPBOOK_CLASS, FALSE));
211 		}
212 		/* robe [via makemon()] */
213 		if (rn2(2) && (otmp = which_armor(priest, W_ARMC)) != 0) {
214 		    if (p_coaligned(priest))
215 			uncurse(otmp);
216 		    else
217 			curse(otmp);
218 		}
219 	}
220 }
221 
222 /*
223  * Specially aligned monsters are named specially.
224  *	- aligned priests with ispriest and high priests have shrines
225  *		they retain ispriest and epri when polymorphed
226  *	- aligned priests without ispriest and Angels are roamers
227  *		they retain isminion and access epri as emin when polymorphed
228  *		(coaligned Angels are also created as minions, but they
229  *		use the same naming convention)
230  *	- minions do not have ispriest but have isminion and emin
231  *	- caller needs to inhibit Hallucination if it wants to force
232  *		the true name even when under that influence
233  */
234 char *
priestname(mon,pname)235 priestname(mon, pname)
236 register struct monst *mon;
237 char *pname;		/* caller-supplied output buffer */
238 {
239 	const char *what = Hallucination ? rndmonnam() : mon->data->mname;
240 
241 	Strcpy(pname, "the ");
242 	if (mon->minvis) Strcat(pname, "invisible ");
243 	if (mon->ispriest || mon->data == &mons[PM_ALIGNED_PRIEST] ||
244 					mon->data == &mons[PM_ANGEL]) {
245 		/* use epri */
246 		if (mon->mtame && mon->data == &mons[PM_ANGEL])
247 			Strcat(pname, "guardian ");
248 		if (mon->data != &mons[PM_ALIGNED_PRIEST] &&
249 				mon->data != &mons[PM_HIGH_PRIEST]) {
250 			Strcat(pname, what);
251 			Strcat(pname, " ");
252 		}
253 		if (mon->data != &mons[PM_ANGEL]) {
254 			if (!mon->ispriest && EPRI(mon)->renegade)
255 				Strcat(pname, "renegade ");
256 			if (mon->data == &mons[PM_HIGH_PRIEST])
257 				Strcat(pname, "high ");
258 			if (Hallucination)
259 				Strcat(pname, "poohbah ");
260 			else if (mon->female)
261 				Strcat(pname, "priestess ");
262 			else
263 				Strcat(pname, "priest ");
264 		}
265 		Strcat(pname, "of ");
266 		/* Astral Call bugfix */
267 		if (mon->data == &mons[PM_HIGH_PRIEST] && !Hallucination &&
268 		            Is_astralevel(&u.uz) && distu(mon->mx, mon->my) > 2) {
269 			Strcat(pname, rnd_gname(str2role((char*)urole.name.m)));
270 			Strcat(pname, "?");
271 		} else {
272 		Strcat(pname, halu_gname((int)EPRI(mon)->shralign));
273 		}
274 		return(pname);
275 	}
276 	/* use emin instead of epri */
277 	Strcat(pname, what);
278 	Strcat(pname, " of ");
279 	Strcat(pname, halu_gname(EMIN(mon)->min_align));
280 	return(pname);
281 }
282 
283 boolean
p_coaligned(priest)284 p_coaligned(priest)
285 struct monst *priest;
286 {
287 	return((boolean)(u.ualign.type == ((int)EPRI(priest)->shralign)));
288 }
289 
290 STATIC_OVL boolean
has_shrine(pri)291 has_shrine(pri)
292 struct monst *pri;
293 {
294 	struct rm *lev;
295 
296 	if(!pri)
297 		return(FALSE);
298 	lev = &levl[EPRI(pri)->shrpos.x][EPRI(pri)->shrpos.y];
299 	if (!IS_ALTAR(lev->typ) || !(lev->altarmask & AM_SHRINE))
300 		return(FALSE);
301 	return((boolean)(EPRI(pri)->shralign == Amask2align(lev->altarmask & ~AM_SHRINE)));
302 }
303 
304 struct monst *
findpriest(roomno)305 findpriest(roomno)
306 char roomno;
307 {
308 	register struct monst *mtmp;
309 
310 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
311 	    if (DEADMONSTER(mtmp)) continue;
312 	    if(mtmp->ispriest && (EPRI(mtmp)->shroom == roomno) &&
313 	       histemple_at(mtmp,mtmp->mx,mtmp->my))
314 		return(mtmp);
315 	}
316 	return (struct monst *)0;
317 }
318 
319 /* called from check_special_room() when the player enters the temple room */
320 void
intemple(roomno)321 intemple(roomno)
322 register int roomno;
323 {
324 	register struct monst *priest = findpriest((char)roomno);
325 	boolean tended = (priest != (struct monst *)0);
326 	boolean shrined, sanctum, can_speak;
327 	const char *msg1, *msg2;
328 	char buf[BUFSZ];
329 
330 	if(!temple_occupied(u.urooms0)) {
331 	    if(tended) {
332 		shrined = has_shrine(priest);
333 		sanctum = (Is_sanctum(&u.uz) || In_endgame(&u.uz));
334 		can_speak = (priest->mcanmove && !priest->msleeping &&
335 			     flags.soundok);
336 		if (can_speak) {
337 		    unsigned save_priest = priest->ispriest;
338 		    /* don't reveal the altar's owner upon temple entry in
339 		       the endgame; for the Sanctum, the next message names
340 		       Moloch so suppress the "of Moloch" for him here too */
341 		    if (sanctum && !Hallucination) priest->ispriest = 0;
342 		    pline("%s intones:",
343 			canseemon(priest) ? Monnam(priest) : "A nearby voice");
344 		    priest->ispriest = save_priest;
345 		}
346 		msg2 = 0;
347 		if(sanctum && Is_sanctum(&u.uz)) {
348 		    if(priest->mpeaceful) {
349 			msg1 = "Infidel, you have entered Moloch's Sanctum!";
350 			msg2 = "Be gone!";
351 			priest->mpeaceful = 0;
352 			set_malign(priest);
353 		    } else
354 			msg1 = "You desecrate this place by your presence!";
355 		} else {
356 		    Sprintf(buf, "Pilgrim, you enter a %s place!",
357 			    !shrined ? "desecrated" : "sacred");
358 		    msg1 = buf;
359 		}
360 		if (can_speak) {
361 		    verbalize("%s", msg1);
362 		    if (msg2) verbalize("%s", msg2);
363 		}
364 		if(!sanctum) {
365 		    /* !tended -> !shrined */
366 		    if (!shrined || !p_coaligned(priest) ||
367 			    u.ualign.record <= ALGN_SINNED)
368 			You("have a%s forbidding feeling...",
369 				(!shrined) ? "" : " strange");
370 		    else You("experience a strange sense of peace.");
371 		}
372 	    } else {
373 		switch(rn2(3)) {
374 		  case 0: You("have an eerie feeling..."); break;
375 		  case 1: You_feel("like you are being watched."); break;
376 		  default: pline("A shiver runs down your %s.",
377 			body_part(SPINE)); break;
378 		}
379 		if(!rn2(5)) {
380 		    struct monst *mtmp;
381 
382 		    if(!(mtmp = makemon(&mons[PM_GHOST],u.ux,u.uy,NO_MM_FLAGS)))
383 			return;
384 		    if (!Blind || sensemon(mtmp))
385 			pline("An enormous ghost appears next to you!");
386 		    else You("sense a presence close by!");
387 		    mtmp->mpeaceful = 0;
388 		    set_malign(mtmp);
389 		    if(flags.verbose)
390 			You("are frightened to death, and unable to move.");
391 		    nomul(-3, "frightened to death");
392 		    nomovemsg = "You regain your composure.";
393 	       }
394 	   }
395        }
396 }
397 
398 void
priest_talk(priest)399 priest_talk(priest)
400 register struct monst *priest;
401 {
402 	boolean coaligned = p_coaligned(priest);
403 	boolean strayed = (u.ualign.record < 0);
404 
405 	/* KMH, conduct */
406 	u.uconduct.gnostic++;
407 
408 	if(priest->mflee || (!priest->ispriest && coaligned && strayed)) {
409 	    pline("%s doesn't want anything to do with you!",
410 				Monnam(priest));
411 	    priest->mpeaceful = 0;
412 	    return;
413 	}
414 
415 	/* priests don't chat unless peaceful and in their own temple */
416 	if(!histemple_at(priest,priest->mx,priest->my) ||
417 		 !priest->mpeaceful || !priest->mcanmove || priest->msleeping) {
418 	    static const char *cranky_msg[3] = {
419 		"Thou wouldst have words, eh?  I'll give thee a word or two!",
420 		"Talk?  Here is what I have to say!",
421 		"Pilgrim, I would speak no longer with thee."
422 	    };
423 
424 	    if(!priest->mcanmove || priest->msleeping) {
425 		pline("%s breaks out of %s reverie!",
426 		      Monnam(priest), mhis(priest));
427 		priest->mfrozen = priest->msleeping = 0;
428 		priest->mcanmove = 1;
429 	    }
430 	    priest->mpeaceful = 0;
431 	    verbalize("%s", cranky_msg[rn2(3)]);
432 	    return;
433 	}
434 
435 	/* you desecrated the temple and now you want to chat? */
436 	if(priest->mpeaceful && *in_rooms(priest->mx, priest->my, TEMPLE) &&
437 		  !has_shrine(priest)) {
438 	    verbalize("Begone!  Thou desecratest this holy place with thy presence.");
439 	    priest->mpeaceful = 0;
440 	    return;
441 	}
442 #ifndef GOLDOBJ
443 	if(!u.ugold) {
444 	    if(coaligned && !strayed) {
445 		if (priest->mgold > 0L) {
446 		    /* Note: two bits is actually 25 cents.  Hmm. */
447 		    pline("%s gives you %s for an ale.", Monnam(priest),
448 			(priest->mgold == 1L) ? "one bit" : "two bits");
449 		    if (priest->mgold > 1L)
450 			u.ugold = 2L;
451 		    else
452 			u.ugold = 1L;
453 		    priest->mgold -= u.ugold;
454 		    flags.botl = 1;
455 #else
456 	if(!money_cnt(invent)) {
457 	    if(coaligned && !strayed) {
458                 long pmoney = money_cnt(priest->minvent);
459 		if (pmoney > 0L) {
460 		    /* Note: two bits is actually 25 cents.  Hmm. */
461 		    pline("%s gives you %s for an ale.", Monnam(priest),
462 			(pmoney == 1L) ? "one bit" : "two bits");
463 		     money2u(priest, pmoney > 1L ? 2 : 1);
464 #endif
465 		} else
466 		    pline("%s preaches the virtues of poverty.", Monnam(priest));
467 		exercise(A_WIS, TRUE);
468 	    } else
469 		pline("%s is not interested.", Monnam(priest));
470 	    return;
471 	} else {
472 	    long offer;
473 
474 	    pline("%s asks you for a contribution for the temple.",
475 			Monnam(priest));
476 	    if((offer = bribe(priest)) == 0) {
477 		verbalize("Thou shalt regret thine action!");
478 		if(coaligned) adjalign(-1);
479 	    } else if(offer < (u.ulevel * 200)) {
480 #ifndef GOLDOBJ
481 		if(u.ugold > (offer * 2L)) verbalize("Cheapskate.");
482 #else
483 		if(money_cnt(invent) > (offer * 2L)) verbalize("Cheapskate.");
484 #endif
485 		else {
486 		    verbalize("I thank thee for thy contribution.");
487 		    /*  give player some token  */
488 		    exercise(A_WIS, TRUE);
489 		}
490 	    } else if(offer < (u.ulevel * 400)) {
491 		verbalize("Thou art indeed a pious individual.");
492 #ifndef GOLDOBJ
493 		if(u.ugold < (offer * 2L)) {
494 #else
495 		if(money_cnt(invent) < (offer * 2L)) {
496 #endif
497 		    if (coaligned && u.ualign.record <= ALGN_SINNED)
498 			adjalign(1);
499 		    verbalize("I bestow upon thee a blessing.");
500 		    incr_itimeout(&HClairvoyant, rn1(500,500));
501 		}
502 	    } else if(offer < (u.ulevel * 600) &&
503 		      u.ublessed < 20 &&
504 		      (u.ublessed < 9 || !rn2(u.ublessed))) {
505 		verbalize("Thy devotion has been rewarded.");
506 		if (!(HProtection & INTRINSIC))  {
507 			HProtection |= FROMOUTSIDE;
508 			if (!u.ublessed)  u.ublessed = rn1(3, 2);
509 		} else u.ublessed++;
510 	    } else {
511 		verbalize("Thy selfless generosity is deeply appreciated.");
512 #ifndef GOLDOBJ
513 		if(u.ugold < (offer * 2L) && coaligned) {
514 #else
515 		if(money_cnt(invent) < (offer * 2L) && coaligned) {
516 #endif
517 		    if(strayed && (moves - u.ucleansed) > 5000L) {
518 			u.ualign.record = 0; /* cleanse thee */
519 			u.ucleansed = moves;
520 		    } else {
521 			adjalign(2);
522 		    }
523 		}
524 	    }
525 	}
526 }
527 
528 struct monst *
mk_roamer(ptr,alignment,x,y,peaceful)529 mk_roamer(ptr, alignment, x, y, peaceful)
530 register struct permonst *ptr;
531 aligntyp alignment;
532 xchar x, y;
533 boolean peaceful;
534 {
535 	register struct monst *roamer;
536 	register boolean coaligned = (u.ualign.type == alignment);
537 
538 	if (ptr != &mons[PM_ALIGNED_PRIEST] && ptr != &mons[PM_ANGEL])
539 		return((struct monst *)0);
540 
541 	if (MON_AT(x, y)) (void) rloc(m_at(x, y), FALSE);	/* insurance */
542 
543 	if (!(roamer = makemon(ptr, x, y, NO_MM_FLAGS)))
544 		return((struct monst *)0);
545 
546 	EPRI(roamer)->shralign = alignment;
547 	if (coaligned && !peaceful)
548 		EPRI(roamer)->renegade = TRUE;
549 	/* roamer->ispriest == FALSE naturally */
550 	roamer->isminion = TRUE;	/* borrowing this bit */
551 	roamer->mtrapseen = ~0;		/* traps are known */
552 	roamer->mpeaceful = peaceful;
553 	roamer->msleeping = 0;
554 	set_malign(roamer); /* peaceful may have changed */
555 
556 	/* MORE TO COME */
557 	return(roamer);
558 }
559 
560 void
reset_hostility(roamer)561 reset_hostility(roamer)
562 register struct monst *roamer;
563 {
564 	if(!(roamer->isminion && (roamer->data == &mons[PM_ALIGNED_PRIEST] ||
565 				  roamer->data == &mons[PM_ANGEL])))
566 	        return;
567 
568 	if(EPRI(roamer)->shralign != u.ualign.type) {
569 	    roamer->mpeaceful = roamer->mtame = 0;
570 	    set_malign(roamer);
571 	}
572 	newsym(roamer->mx, roamer->my);
573 }
574 
575 boolean
in_your_sanctuary(mon,x,y)576 in_your_sanctuary(mon, x, y)
577 struct monst *mon;	/* if non-null, <mx,my> overrides <x,y> */
578 xchar x, y;
579 {
580 	register char roomno;
581 	register struct monst *priest;
582 
583 	if (mon) {
584 	    if (is_minion(mon->data) || is_rider(mon->data)) return FALSE;
585 	    x = mon->mx, y = mon->my;
586 	}
587 	if (u.ualign.record <= ALGN_SINNED)	/* sinned or worse */
588 	    return FALSE;
589 	if ((roomno = temple_occupied(u.urooms)) == 0 ||
590 		roomno != *in_rooms(x, y, TEMPLE))
591 	    return FALSE;
592 	if ((priest = findpriest(roomno)) == 0)
593 	    return FALSE;
594 	return (boolean)(has_shrine(priest) &&
595 			 p_coaligned(priest) &&
596 			 priest->mpeaceful);
597 }
598 
599 void
ghod_hitsu(priest)600 ghod_hitsu(priest)	/* when attacking "priest" in his temple */
601 struct monst *priest;
602 {
603 	int x, y, ax, ay, roomno = (int)temple_occupied(u.urooms);
604 	struct mkroom *troom;
605 
606 	if (!roomno || !has_shrine(priest))
607 		return;
608 
609 	ax = x = EPRI(priest)->shrpos.x;
610 	ay = y = EPRI(priest)->shrpos.y;
611 	troom = &rooms[roomno - ROOMOFFSET];
612 
613 	if((u.ux == x && u.uy == y) || !linedup(u.ux, u.uy, x, y)) {
614 	    if(IS_DOOR(levl[u.ux][u.uy].typ)) {
615 
616 		if(u.ux == troom->lx - 1) {
617 		    x = troom->hx;
618 		    y = u.uy;
619 		} else if(u.ux == troom->hx + 1) {
620 		    x = troom->lx;
621 		    y = u.uy;
622 		} else if(u.uy == troom->ly - 1) {
623 		    x = u.ux;
624 		    y = troom->hy;
625 		} else if(u.uy == troom->hy + 1) {
626 		    x = u.ux;
627 		    y = troom->ly;
628 		}
629 	    } else {
630 		switch(rn2(4)) {
631 		case 0:  x = u.ux; y = troom->ly; break;
632 		case 1:  x = u.ux; y = troom->hy; break;
633 		case 2:  x = troom->lx; y = u.uy; break;
634 		default: x = troom->hx; y = u.uy; break;
635 		}
636 	    }
637 	    if(!linedup(u.ux, u.uy, x, y)) return;
638 	}
639 
640 	switch(rn2(3)) {
641 	case 0:
642 	    pline("%s roars in anger:  \"Thou shalt suffer!\"",
643 			a_gname_at(ax, ay));
644 	    break;
645 	case 1:
646 	    pline("%s voice booms:  \"How darest thou harm my servant!\"",
647 			s_suffix(a_gname_at(ax, ay)));
648 	    break;
649 	default:
650 	    pline("%s roars:  \"Thou dost profane my shrine!\"",
651 			a_gname_at(ax, ay));
652 	    break;
653 	}
654 
655 	buzz(-10-(AD_ELEC-1), 6, x, y, sgn(tbx), sgn(tby)); /* bolt of lightning */
656 	exercise(A_WIS, FALSE);
657 }
658 
659 void
angry_priest()660 angry_priest()
661 {
662 	register struct monst *priest;
663 	struct rm *lev;
664 
665 	if ((priest = findpriest(temple_occupied(u.urooms))) != 0) {
666 	    wakeup(priest);
667 	    /*
668 	     * If the altar has been destroyed or converted, let the
669 	     * priest run loose.
670 	     * (When it's just a conversion and there happens to be
671 	     *	a fresh corpse nearby, the priest ought to have an
672 	     *	opportunity to try converting it back; maybe someday...)
673 	     */
674 	    lev = &levl[EPRI(priest)->shrpos.x][EPRI(priest)->shrpos.y];
675 	    if (!IS_ALTAR(lev->typ) ||
676 		((aligntyp)Amask2align(lev->altarmask & AM_MASK) !=
677 			EPRI(priest)->shralign)) {
678 		priest->ispriest = 0;		/* now a roamer */
679 		priest->isminion = 1;		/* but still aligned */
680 		/* this overloads the `shroom' field, which is now clobbered */
681 		EPRI(priest)->renegade = 0;
682 	    }
683 	}
684 }
685 
686 /*
687  * When saving bones, find priests that aren't on their shrine level,
688  * and remove them.   This avoids big problems when restoring bones.
689  */
690 void
clearpriests()691 clearpriests()
692 {
693     register struct monst *mtmp, *mtmp2;
694 
695     for(mtmp = fmon; mtmp; mtmp = mtmp2) {
696 	mtmp2 = mtmp->nmon;
697 	if (!DEADMONSTER(mtmp) && mtmp->ispriest && !on_level(&(EPRI(mtmp)->shrlevel), &u.uz))
698 	    mongone(mtmp);
699     }
700 }
701 
702 /* munge priest-specific structure when restoring -dlc */
703 void
restpriest(mtmp,ghostly)704 restpriest(mtmp, ghostly)
705 register struct monst *mtmp;
706 boolean ghostly;
707 {
708     if(u.uz.dlevel) {
709 	if (ghostly)
710 	    assign_level(&(EPRI(mtmp)->shrlevel), &u.uz);
711     }
712 }
713 
714 /*priest.c*/
715