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