1 | /* SCCS Id: @(#)priest.c 3.3 2000/02/19 */
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 | #ifdef OVLB
12 |
13 | STATIC_DCL boolean FDECL(histemple_at,(struct monst *,XCHAR_P,XCHAR_P));
14 | STATIC_DCL boolean FDECL(has_shrine,(struct monst *));
15 |
16 | /*
17 | * Move for priests and shopkeepers. Called from shk_move() and pri_move().
18 | * Valid returns are 1: moved 0: didn't -1: let m_move do it -2: died.
19 | */
20 | int
21 | move_special(mtmp,in_his_shop,appr,uondoor,avoid,omx,omy,gx,gy)
22 | register struct monst *mtmp;
23 | boolean in_his_shop;
24 | schar appr;
25 | boolean uondoor,avoid;
26 | register xchar omx,omy,gx,gy;
27 | {
28 | register xchar nx,ny,nix,niy;
29 | register schar i;
30 | schar chcnt,cnt;
31 | coord poss[9];
32 | long info[9];
33 | long allowflags;
34 | struct obj *ib = (struct obj *)0;
35 |
36 | if(omx == gx && omy == gy)
37 | return(0);
38 | if(mtmp->mconf) {
39 | avoid = FALSE;
40 | appr = 0;
41 | }
42 |
43 | nix = omx;
44 | niy = omy;
45 | if (mtmp->isshk) allowflags = ALLOW_SSM;
46 | else allowflags = ALLOW_SSM | ALLOW_SANCT;
47 | if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK|ALLOW_WALL);
48 | if (throws_rocks(mtmp->data)) allowflags |= ALLOW_ROCK;
49 | if (tunnels(mtmp->data) &&
50 | (!needspick(mtmp->data) || m_carrying(mtmp, PICK_AXE) ||
51 | m_carrying(mtmp, DWARVISH_MATTOCK)))
52 | 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
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
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
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
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 | register struct monst *priest;
194 | register struct obj *otmp;
195 | register int cnt;
196 |
197 | if(MON_AT(sx+1, sy))
198 | rloc(m_at(sx+1, sy)); /* 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 | /* Do NOT put the rest in m_initinv. */
220 | /* Priests created elsewhere than in a */
221 | /* temple should not carry these items, */
222 | cnt = rn1(2,3);
223 | while(cnt) {
224 | otmp = mkobj(SPBOOK_CLASS, FALSE);
225 | if(otmp) (void) mpickobj(priest, otmp);
226 | cnt--;
227 | }
228 | if(p_coaligned(priest))
229 | (void) mongets(priest, ROBE);
230 | else {
231 | otmp = mksobj(ROBE, TRUE, FALSE);
232 | if(otmp) {
233 | if(!rn2(2)) curse(otmp);
234 | (void) mpickobj(priest, otmp);
235 | }
236 | }
237 | m_dowear(priest, TRUE);
238 | }
239 | }
240 |
241 | /*
242 | * Specially aligned monsters are named specially.
243 | * - aligned priests with ispriest and high priests have shrines
244 | * they retain ispriest and epri when polymorphed
245 | * - aligned priests without ispriest and Angels are roamers
246 | * they retain isminion and access epri as emin when polymorphed
247 | * (coaligned Angels are also created as minions, but they
248 | * use the same naming convention)
249 | * - minions do not have ispriest but have isminion and emin
250 | * - caller needs to inhibit Hallucination if it wants to force
251 | * the true name even when under that influence
252 | */
253 | char *
254 | priestname(mon, pname)
255 | register struct monst *mon;
256 | char *pname; /* caller-supplied output buffer */
257 | {
258 | const char *what = Hallucination ? rndmonnam() : mon->data->mname;
259 |
260 | Strcpy(pname, "the ");
261 | if (mon->minvis) Strcat(pname, "invisible ");
262 | if (mon->ispriest || mon->data == &mons[PM_ALIGNED_PRIEST] ||
263 | mon->data == &mons[PM_ANGEL]) {
264 | /* use epri */
265 | if (mon->mtame && mon->data == &mons[PM_ANGEL])
266 | Strcat(pname, "guardian ");
267 | if (mon->data != &mons[PM_ALIGNED_PRIEST] &&
268 | mon->data != &mons[PM_HIGH_PRIEST]) {
269 | Strcat(pname, what);
270 | Strcat(pname, " ");
271 | }
272 | if (mon->data != &mons[PM_ANGEL]) {
273 | if (!mon->ispriest && EPRI(mon)->renegade)
274 | Strcat(pname, "renegade ");
275 | if (mon->data == &mons[PM_HIGH_PRIEST])
276 | Strcat(pname, "high ");
277 | if (Hallucination)
278 | Strcat(pname, "poohbah ");
279 | else if (mon->female)
280 | Strcat(pname, "priestess ");
281 | else
282 | Strcat(pname, "priest ");
283 | }
284 | Strcat(pname, "of ");
285 | Strcat(pname, halu_gname((int)EPRI(mon)->shralign));
286 | return(pname);
287 | }
288 | /* use emin instead of epri */
289 | Strcat(pname, what);
290 | Strcat(pname, " of ");
291 | Strcat(pname, halu_gname(EMIN(mon)->min_align));
292 | return(pname);
293 | }
294 |
295 | boolean
296 | p_coaligned(priest)
297 | struct monst *priest;
298 | {
299 | return((boolean)(u.ualign.type == ((int)EPRI(priest)->shralign)));
300 | }
301 |
302 | STATIC_OVL boolean
303 | has_shrine(pri)
304 | struct monst *pri;
305 | {
306 | struct rm *lev;
307 |
308 | if(!pri)
309 | return(FALSE);
310 | lev = &levl[EPRI(pri)->shrpos.x][EPRI(pri)->shrpos.y];
311 | if (!IS_ALTAR(lev->typ) || !(lev->altarmask & AM_SHRINE))
312 | return(FALSE);
313 | return((boolean)(EPRI(pri)->shralign == Amask2align(lev->altarmask & ~AM_SHRINE)));
314 | }
315 |
316 | struct monst *
317 | findpriest(roomno)
318 | char roomno;
319 | {
320 | register struct monst *mtmp;
321 |
322 | for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
323 | if (DEADMONSTER(mtmp)) continue;
324 | if(mtmp->ispriest && (EPRI(mtmp)->shroom == roomno) &&
325 | histemple_at(mtmp,mtmp->mx,mtmp->my))
326 | return(mtmp);
327 | }
328 | return (struct monst *)0;
329 | }
330 |
331 | /* called from check_special_room() when the player enters the temple room */
332 | void
333 | intemple(roomno)
334 | register int roomno;
335 | {
336 | register struct monst *priest = findpriest((char)roomno);
337 | boolean tended = (priest != (struct monst *)0);
338 | boolean shrined, sanctum, can_speak;
339 | const char *msg1, *msg2;
340 | char buf[BUFSZ];
341 |
342 | if(!temple_occupied(u.urooms0)) {
343 | if(tended) {
344 | shrined = has_shrine(priest);
345 | sanctum = (priest->data == &mons[PM_HIGH_PRIEST] &&
346 | (Is_sanctum(&u.uz) || In_endgame(&u.uz)));
347 | can_speak = (priest->mcanmove && !priest->msleeping);
348 | if (can_speak)
349 | pline("%s intones:",
350 | (!Blind ? Monnam(priest) : "A nearby voice"));
351 | msg2 = 0;
352 | if(sanctum && Is_sanctum(&u.uz)) {
353 | if(priest->mpeaceful) {
354 | msg1 = "Infidel, you entered Moloch's Sanctum!";
355 | msg2 = "Be gone!";
356 | priest->mpeaceful = 0;
357 | set_malign(priest);
358 | } else
359 | msg1 = "You desecrate this place by your presence!";
360 | } else {
361 | Sprintf(buf, "Pilgrim, you enter a %s place!",
362 | !shrined ? "desecrated" : "sacred");
363 | msg1 = buf;
364 | }
365 | if (can_speak) {
366 | verbalize(msg1);
367 | if (msg2) verbalize(msg2);
368 | }
369 | if(!sanctum) {
370 | /* !tended -> !shrined */
371 | if(!shrined || !p_coaligned(priest) ||
372 | u.ualign.record < -5)
373 | You("have a%s forbidding feeling...",
374 | (!shrined) ? "" : " strange");
375 | else You("experience a strange sense of peace.");
376 | }
377 | } else {
378 | switch(rn2(3)) {
379 | case 0: You("have an eerie feeling..."); break;
380 | case 1: You_feel("like you are being watched."); break;
381 | default: pline("A shiver runs down your %s.",
382 | body_part(SPINE)); break;
383 | }
384 | if(!rn2(5)) {
385 | struct monst *mtmp;
386 |
387 | if(!(mtmp = makemon(&mons[PM_GHOST],u.ux,u.uy,NO_MM_FLAGS)))
388 | return;
389 | pline("An enormous ghost appears next to you!");
390 | mtmp->mpeaceful = 0;
391 | set_malign(mtmp);
392 | if(flags.verbose)
393 | You("are frightened to death, and unable to move.");
394 | nomul(-3);
395 | nomovemsg = "You regain your composure.";
396 | }
397 | }
398 | }
399 | }
400 |
401 | void
402 | priest_talk(priest)
403 | register struct monst *priest;
404 | {
405 | boolean coaligned = p_coaligned(priest);
406 | boolean strayed = (u.ualign.record < 0);
407 |
408 |
409 | /* KMH, conduct */
410 | u.uconduct.gnostic++;
411 |
412 | if(priest->mflee || (!priest->ispriest && coaligned && strayed)) {
413 | pline("%s doesn't want anything to do with you!",
414 | Monnam(priest));
415 | priest->mpeaceful = 0;
416 | return;
417 | }
418 |
419 | /* priests don't chat unless peaceful and in their own temple */
420 | if(!histemple_at(priest,priest->mx,priest->my) ||
421 | !priest->mpeaceful || !priest->mcanmove || priest->msleeping) {
422 | static const char *cranky_msg[3] = {
423 | "Thou wouldst have words, eh? I'll give thee a word or two!",
424 | "Talk? Here is what I have to say!",
425 | "Pilgrim, I would speak no longer with thee."
426 | };
427 |
428 | if(!priest->mcanmove || priest->msleeping) {
429 | pline("%s breaks out of %s reverie!",
430 | Monnam(priest), his[pronoun_gender(priest)]);
431 | priest->mfrozen = priest->msleeping = 0;
432 | priest->mcanmove = 1;
433 | }
434 | priest->mpeaceful = 0;
435 | verbalize(cranky_msg[rn2(3)]);
436 | return;
437 | }
438 |
439 | /* you desecrated the temple and now you want to chat? */
440 | if(priest->mpeaceful && *in_rooms(priest->mx, priest->my, TEMPLE) &&
441 | !has_shrine(priest)) {
442 | verbalize("Begone! Thou desecratest this holy place with thy presence.");
443 | priest->mpeaceful = 0;
444 | return;
445 | }
446 |
447 | if(!u.ugold) {
448 | if(coaligned && !strayed) {
449 | if (priest->mgold > 0L) {
450 | /* Note: two bits is actually 25 cents. Hmm. */
451 | pline("%s gives you %s for an ale.", Monnam(priest),
452 | (priest->mgold == 1L) ? "one bit" : "two bits");
453 | if (priest->mgold > 1L)
454 | u.ugold = 2L;
455 | else
456 | u.ugold = 1L;
457 | priest->mgold -= u.ugold;
458 | flags.botl = 1;
459 | } else
460 | pline("%s preaches the virtues of poverty.", Monnam(priest));
461 | exercise(A_WIS, TRUE);
462 | } else
463 | pline("%s is not interested.", Monnam(priest));
464 | return;
465 | } else {
466 | long offer;
467 |
468 | pline("%s asks you for a contribution for the temple.",
469 | Monnam(priest));
470 | if((offer = bribe(priest)) == 0) {
471 | verbalize("Thou shalt regret thine action!");
472 | if(coaligned) adjalign(-1);
473 | } else if(offer < (u.ulevel * 200)) {
474 | if(u.ugold > (offer * 2L)) verbalize("Cheapskate.");
475 | else {
476 | verbalize("I thank thee for thy contribution.");
477 | /* give player some token */
478 | exercise(A_WIS, TRUE);
479 | }
480 | } else if(offer < (u.ulevel * 400)) {
481 | verbalize("Thou art indeed a pious individual.");
482 | if(u.ugold < (offer * 2L)) {
483 | if(coaligned && u.ualign.record < -5) adjalign(1);
484 | verbalize("I bestow upon thee a blessing.");
485 | incr_itimeout(&HClairvoyant, rn1(500,500));
486 | }
487 | } else if(offer < (u.ulevel * 600) &&
488 | u.ublessed < 20 &&
489 | (u.ublessed < 9 || !rn2(u.ublessed))) {
490 | verbalize("Thy devotion has been rewarded.");
491 | if (!(HProtection & INTRINSIC)) {
492 | HProtection |= FROMOUTSIDE;
493 | if (!u.ublessed) u.ublessed = rn1(3, 2);
494 | } else u.ublessed++;
495 | } else {
496 | verbalize("Thy selfless generosity is deeply appreciated.");
497 | if(u.ugold < (offer * 2L) && coaligned) {
498 | if(strayed && (moves - u.ucleansed) > 5000L) {
499 | u.ualign.record = 0; /* cleanse thee */
500 | u.ucleansed = moves;
501 | } else {
502 | adjalign(2);
503 | }
504 | }
505 | }
506 | }
507 | }
508 |
509 | struct monst *
510 | mk_roamer(ptr, alignment, x, y, peaceful)
511 | register struct permonst *ptr;
512 | aligntyp alignment;
513 | xchar x, y;
514 | boolean peaceful;
515 | {
516 | register struct monst *roamer;
517 | register boolean coaligned = (u.ualign.type == alignment);
518 |
519 | if (ptr != &mons[PM_ALIGNED_PRIEST] && ptr != &mons[PM_ANGEL])
520 | return((struct monst *)0);
521 |
522 | if (MON_AT(x, y)) rloc(m_at(x, y)); /* insurance */
523 |
524 | if (!(roamer = makemon(ptr, x, y, NO_MM_FLAGS)))
525 | return((struct monst *)0);
526 |
527 | EPRI(roamer)->shralign = alignment;
528 | if (coaligned && !peaceful)
529 | EPRI(roamer)->renegade = TRUE;
530 | /* roamer->ispriest == FALSE naturally */
531 | roamer->isminion = TRUE; /* borrowing this bit */
532 | roamer->mtrapseen = ~0; /* traps are known */
533 | roamer->mpeaceful = peaceful;
534 | roamer->msleeping = 0;
535 | set_malign(roamer); /* peaceful may have changed */
536 |
537 | /* MORE TO COME */
538 | return(roamer);
539 | }
540 |
541 | void
542 | reset_hostility(roamer)
543 | register struct monst *roamer;
544 | {
545 | if(!(roamer->isminion && (roamer->data == &mons[PM_ALIGNED_PRIEST] ||
546 | roamer->data == &mons[PM_ANGEL])))
547 | return;
548 |
549 | if(EPRI(roamer)->shralign != u.ualign.type) {
550 | roamer->mpeaceful = roamer->mtame = 0;
551 | set_malign(roamer);
552 | }
553 | newsym(roamer->mx, roamer->my);
554 | }
555 |
556 | boolean
557 | in_your_sanctuary(mon, x, y)
558 | struct monst *mon; /* if non-null, <mx,my> overrides <x,y> */
559 | xchar x, y;
560 | {
561 | register char roomno;
562 | register struct monst *priest;
563 |
564 | if (mon) {
565 | if (is_minion(mon->data) || is_rider(mon->data)) return FALSE;
566 | x = mon->mx, y = mon->my;
567 | }
568 | if (u.ualign.record < -3) /* sinned or worse */
569 | return FALSE;
570 | if ((roomno = temple_occupied(u.urooms)) == 0 ||
571 | roomno != *in_rooms(x, y, TEMPLE))
572 | return FALSE;
573 | if ((priest = findpriest(roomno)) == 0)
574 | return FALSE;
575 | return (boolean)(has_shrine(priest) &&
576 | p_coaligned(priest) &&
577 | priest->mpeaceful);
578 | }
579 |
580 | void
581 | ghod_hitsu(priest) /* when attacking "priest" in his temple */
582 | struct monst *priest;
583 | {
584 | int x, y, ax, ay, roomno = (int)temple_occupied(u.urooms);
585 | struct mkroom *troom;
586 |
587 | if (!roomno || !has_shrine(priest))
588 | return;
589 |
590 | ax = x = EPRI(priest)->shrpos.x;
591 | ay = y = EPRI(priest)->shrpos.y;
592 | troom = &rooms[roomno - ROOMOFFSET];
593 |
594 | if((u.ux == x && u.uy == y) || !linedup(u.ux, u.uy, x, y)) {
595 | if(IS_DOOR(levl[u.ux][u.uy].typ)) {
596 |
597 | if(u.ux == troom->lx - 1) {
598 | x = troom->hx;
599 | y = u.uy;
600 | } else if(u.ux == troom->hx + 1) {
601 | x = troom->lx;
602 | y = u.uy;
603 | } else if(u.uy == troom->ly - 1) {
604 | x = u.ux;
605 | y = troom->hy;
606 | } else if(u.uy == troom->hy + 1) {
607 | x = u.ux;
608 | y = troom->ly;
609 | }
610 | } else {
611 | switch(rn2(4)) {
612 | case 0: x = u.ux; y = troom->ly; break;
613 | case 1: x = u.ux; y = troom->hy; break;
614 | case 2: x = troom->lx; y = u.uy; break;
615 | default: x = troom->hx; y = u.uy; break;
616 | }
617 | }
618 | if(!linedup(u.ux, u.uy, x, y)) return;
619 | }
620 |
621 | switch(rn2(3)) {
622 | case 0:
623 | pline("%s roars in anger: \"Thou shalt suffer!\"",
624 | a_gname_at(ax, ay));
625 | break;
626 | case 1:
627 | pline("%s voice booms: \"How darest thou harm my servant!\"",
628 | s_suffix(a_gname_at(ax, ay)));
629 | break;
630 | default:
631 | pline("%s roars: \"Thou dost profane my shrine!\"",
632 | a_gname_at(ax, ay));
633 | break;
634 | }
635 |
636 | buzz(-10-(AD_ELEC-1), 6, x, y, sgn(tbx), sgn(tby)); /* bolt of lightning */
637 | exercise(A_WIS, FALSE);
638 | }
639 |
640 | void
641 | angry_priest()
642 | {
643 | register struct monst *priest;
644 | struct rm *lev;
645 |
646 | if ((priest = findpriest(temple_occupied(u.urooms))) != 0) {
647 | wakeup(priest);
648 | /*
649 | * If the altar has been destroyed or converted, let the
650 | * priest run loose.
651 | * (When it's just a conversion and there happens to be
652 | * a fresh corpse nearby, the priest ought to have an
653 | * opportunity to try converting it back; maybe someday...)
654 | */
655 | lev = &levl[EPRI(priest)->shrpos.x][EPRI(priest)->shrpos.y];
656 | if (!IS_ALTAR(lev->typ) ||
657 | ((aligntyp)Amask2align(lev->altarmask & AM_MASK) !=
658 | EPRI(priest)->shralign)) {
659 | priest->ispriest = 0; /* now a roamer */
660 | priest->isminion = 1; /* but still aligned */
661 | /* this overloads the `shroom' field, which is now clobbered */
662 | EPRI(priest)->renegade = 0;
663 | }
664 | }
665 | }
666 |
667 | /*
668 | * When saving bones, find priests that aren't on their shrine level,
669 | * and remove them. This avoids big problems when restoring bones.
670 | */
671 | void
672 | clearpriests()
673 | {
674 | register struct monst *mtmp, *mtmp2;
675 |
676 | for(mtmp = fmon; mtmp; mtmp = mtmp2) {
677 | mtmp2 = mtmp->nmon;
678 | if (!DEADMONSTER(mtmp) && mtmp->ispriest && !on_level(&(EPRI(mtmp)->shrlevel), &u.uz))
679 | mongone(mtmp);
680 | }
681 | }
682 |
683 | /* munge priest-specific structure when restoring -dlc */
684 | void
685 | restpriest(mtmp, ghostly)
686 | register struct monst *mtmp;
687 | boolean ghostly;
688 | {
689 | if(u.uz.dlevel) {
690 | if (ghostly)
691 | assign_level(&(EPRI(mtmp)->shrlevel), &u.uz);
692 | }
693 | }
694 |
695 | #endif /* OVLB */
696 |
697 | /*priest.c*/