OSDN Git Service

Initial Import
[nethackexpress/trunk.git] / src / priest.c
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
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
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         struct monst *priest;
194         struct obj *otmp;
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                 /* robe [via makemon()] */
224                 if (rn2(2) && (otmp = which_armor(priest, W_ARMC)) != 0) {
225                     if (p_coaligned(priest))
226                         uncurse(otmp);
227                     else
228                         curse(otmp);
229                 }
230         }
231 }
232
233 /*
234  * Specially aligned monsters are named specially.
235  *      - aligned priests with ispriest and high priests have shrines
236  *              they retain ispriest and epri when polymorphed
237  *      - aligned priests without ispriest and Angels are roamers
238  *              they retain isminion and access epri as emin when polymorphed
239  *              (coaligned Angels are also created as minions, but they
240  *              use the same naming convention)
241  *      - minions do not have ispriest but have isminion and emin
242  *      - caller needs to inhibit Hallucination if it wants to force
243  *              the true name even when under that influence
244  */
245 char *
246 priestname(mon, pname)
247 register struct monst *mon;
248 char *pname;            /* caller-supplied output buffer */
249 {
250         const char *what = Hallucination ? rndmonnam() : mon->data->mname;
251
252         Strcpy(pname, "the ");
253         if (mon->minvis) Strcat(pname, "invisible ");
254         if (mon->ispriest || mon->data == &mons[PM_ALIGNED_PRIEST] ||
255                                         mon->data == &mons[PM_ANGEL]) {
256                 /* use epri */
257                 if (mon->mtame && mon->data == &mons[PM_ANGEL])
258                         Strcat(pname, "guardian ");
259                 if (mon->data != &mons[PM_ALIGNED_PRIEST] &&
260                                 mon->data != &mons[PM_HIGH_PRIEST]) {
261                         Strcat(pname, what);
262                         Strcat(pname, " ");
263                 }
264                 if (mon->data != &mons[PM_ANGEL]) {
265                         if (!mon->ispriest && EPRI(mon)->renegade)
266                                 Strcat(pname, "renegade ");
267                         if (mon->data == &mons[PM_HIGH_PRIEST])
268                                 Strcat(pname, "high ");
269                         if (Hallucination)
270                                 Strcat(pname, "poohbah ");
271                         else if (mon->female)
272                                 Strcat(pname, "priestess ");
273                         else
274                                 Strcat(pname, "priest ");
275                 }
276                 Strcat(pname, "of ");
277                 Strcat(pname, halu_gname((int)EPRI(mon)->shralign));
278                 return(pname);
279         }
280         /* use emin instead of epri */
281         Strcat(pname, what);
282         Strcat(pname, " of ");
283         Strcat(pname, halu_gname(EMIN(mon)->min_align));
284         return(pname);
285 }
286
287 boolean
288 p_coaligned(priest)
289 struct monst *priest;
290 {
291         return((boolean)(u.ualign.type == ((int)EPRI(priest)->shralign)));
292 }
293
294 STATIC_OVL boolean
295 has_shrine(pri)
296 struct monst *pri;
297 {
298         struct rm *lev;
299
300         if(!pri)
301                 return(FALSE);
302         lev = &levl[EPRI(pri)->shrpos.x][EPRI(pri)->shrpos.y];
303         if (!IS_ALTAR(lev->typ) || !(lev->altarmask & AM_SHRINE))
304                 return(FALSE);
305         return((boolean)(EPRI(pri)->shralign == Amask2align(lev->altarmask & ~AM_SHRINE)));
306 }
307
308 struct monst *
309 findpriest(roomno)
310 char roomno;
311 {
312         register struct monst *mtmp;
313
314         for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
315             if (DEADMONSTER(mtmp)) continue;
316             if(mtmp->ispriest && (EPRI(mtmp)->shroom == roomno) &&
317                histemple_at(mtmp,mtmp->mx,mtmp->my))
318                 return(mtmp);
319         }
320         return (struct monst *)0;
321 }
322
323 /* called from check_special_room() when the player enters the temple room */
324 void
325 intemple(roomno)
326 register int roomno;
327 {
328         register struct monst *priest = findpriest((char)roomno);
329         boolean tended = (priest != (struct monst *)0);
330         boolean shrined, sanctum, can_speak;
331         const char *msg1, *msg2;
332         char buf[BUFSZ];
333
334         if(!temple_occupied(u.urooms0)) {
335             if(tended) {
336                 shrined = has_shrine(priest);
337                 sanctum = (priest->data == &mons[PM_HIGH_PRIEST] &&
338                            (Is_sanctum(&u.uz) || In_endgame(&u.uz)));
339                 can_speak = (priest->mcanmove && !priest->msleeping &&
340                              flags.soundok);
341                 if (can_speak) {
342                     unsigned save_priest = priest->ispriest;
343                     /* don't reveal the altar's owner upon temple entry in
344                        the endgame; for the Sanctum, the next message names
345                        Moloch so suppress the "of Moloch" for him here too */
346                     if (sanctum && !Hallucination) priest->ispriest = 0;
347                     pline("%s intones:",
348                         canseemon(priest) ? Monnam(priest) : "A nearby voice");
349                     priest->ispriest = save_priest;
350                 }
351                 msg2 = 0;
352                 if(sanctum && Is_sanctum(&u.uz)) {
353                     if(priest->mpeaceful) {
354                         msg1 = "Infidel, you have 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 <= ALGN_SINNED)
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                     if (!Blind || sensemon(mtmp))
390                         pline("An enormous ghost appears next to you!");
391                     else You("sense a presence close by!");
392                     mtmp->mpeaceful = 0;
393                     set_malign(mtmp);
394                     if(flags.verbose)
395                         You("are frightened to death, and unable to move.");
396                     nomul(-3);
397                     nomovemsg = "You regain your composure.";
398                }
399            }
400        }
401 }
402
403 void
404 priest_talk(priest)
405 register struct monst *priest;
406 {
407         boolean coaligned = p_coaligned(priest);
408         boolean strayed = (u.ualign.record < 0);
409
410         /* KMH, conduct */
411         u.uconduct.gnostic++;
412
413         if(priest->mflee || (!priest->ispriest && coaligned && strayed)) {
414             pline("%s doesn't want anything to do with you!",
415                                 Monnam(priest));
416             priest->mpeaceful = 0;
417             return;
418         }
419
420         /* priests don't chat unless peaceful and in their own temple */
421         if(!histemple_at(priest,priest->mx,priest->my) ||
422                  !priest->mpeaceful || !priest->mcanmove || priest->msleeping) {
423             static const char *cranky_msg[3] = {
424                 "Thou wouldst have words, eh?  I'll give thee a word or two!",
425                 "Talk?  Here is what I have to say!",
426                 "Pilgrim, I would speak no longer with thee."
427             };
428
429             if(!priest->mcanmove || priest->msleeping) {
430                 pline("%s breaks out of %s reverie!",
431                       Monnam(priest), mhis(priest));
432                 priest->mfrozen = priest->msleeping = 0;
433                 priest->mcanmove = 1;
434             }
435             priest->mpeaceful = 0;
436             verbalize(cranky_msg[rn2(3)]);
437             return;
438         }
439
440         /* you desecrated the temple and now you want to chat? */
441         if(priest->mpeaceful && *in_rooms(priest->mx, priest->my, TEMPLE) &&
442                   !has_shrine(priest)) {
443             verbalize("Begone!  Thou desecratest this holy place with thy presence.");
444             priest->mpeaceful = 0;
445             return;
446         }
447 #ifndef GOLDOBJ
448         if(!u.ugold) {
449             if(coaligned && !strayed) {
450                 if (priest->mgold > 0L) {
451                     /* Note: two bits is actually 25 cents.  Hmm. */
452                     pline("%s gives you %s for an ale.", Monnam(priest),
453                         (priest->mgold == 1L) ? "one bit" : "two bits");
454                     if (priest->mgold > 1L)
455                         u.ugold = 2L;
456                     else
457                         u.ugold = 1L;
458                     priest->mgold -= u.ugold;
459                     flags.botl = 1;
460 #else
461         if(!money_cnt(invent)) {
462             if(coaligned && !strayed) {
463                 long pmoney = money_cnt(priest->minvent);
464                 if (pmoney > 0L) {
465                     /* Note: two bits is actually 25 cents.  Hmm. */
466                     pline("%s gives you %s for an ale.", Monnam(priest),
467                         (pmoney == 1L) ? "one bit" : "two bits");
468                      money2u(priest, pmoney > 1L ? 2 : 1);
469 #endif
470                 } else
471                     pline("%s preaches the virtues of poverty.", Monnam(priest));
472                 exercise(A_WIS, TRUE);
473             } else
474                 pline("%s is not interested.", Monnam(priest));
475             return;
476         } else {
477             long offer;
478
479             pline("%s asks you for a contribution for the temple.",
480                         Monnam(priest));
481             if((offer = bribe(priest)) == 0) {
482                 verbalize("Thou shalt regret thine action!");
483                 if(coaligned) adjalign(-1);
484             } else if(offer < (u.ulevel * 200)) {
485 #ifndef GOLDOBJ
486                 if(u.ugold > (offer * 2L)) verbalize("Cheapskate.");
487 #else
488                 if(money_cnt(invent) > (offer * 2L)) verbalize("Cheapskate.");
489 #endif
490                 else {
491                     verbalize("I thank thee for thy contribution.");
492                     /*  give player some token  */
493                     exercise(A_WIS, TRUE);
494                 }
495             } else if(offer < (u.ulevel * 400)) {
496                 verbalize("Thou art indeed a pious individual.");
497 #ifndef GOLDOBJ
498                 if(u.ugold < (offer * 2L)) {
499 #else
500                 if(money_cnt(invent) < (offer * 2L)) {
501 #endif
502                     if (coaligned && u.ualign.record <= ALGN_SINNED)
503                         adjalign(1);
504                     verbalize("I bestow upon thee a blessing.");
505                     incr_itimeout(&HClairvoyant, rn1(500,500));
506                 }
507             } else if(offer < (u.ulevel * 600) &&
508                       u.ublessed < 20 &&
509                       (u.ublessed < 9 || !rn2(u.ublessed))) {
510                 verbalize("Thy devotion has been rewarded.");
511                 if (!(HProtection & INTRINSIC))  {
512                         HProtection |= FROMOUTSIDE;
513                         if (!u.ublessed)  u.ublessed = rn1(3, 2);
514                 } else u.ublessed++;
515             } else {
516                 verbalize("Thy selfless generosity is deeply appreciated.");
517 #ifndef GOLDOBJ
518                 if(u.ugold < (offer * 2L) && coaligned) {
519 #else
520                 if(money_cnt(invent) < (offer * 2L) && coaligned) {
521 #endif
522                     if(strayed && (moves - u.ucleansed) > 5000L) {
523                         u.ualign.record = 0; /* cleanse thee */
524                         u.ucleansed = moves;
525                     } else {
526                         adjalign(2);
527                     }
528                 }
529             }
530         }
531 }
532
533 struct monst *
534 mk_roamer(ptr, alignment, x, y, peaceful)
535 register struct permonst *ptr;
536 aligntyp alignment;
537 xchar x, y;
538 boolean peaceful;
539 {
540         register struct monst *roamer;
541         register boolean coaligned = (u.ualign.type == alignment);
542
543         if (ptr != &mons[PM_ALIGNED_PRIEST] && ptr != &mons[PM_ANGEL])
544                 return((struct monst *)0);
545         
546         if (MON_AT(x, y)) (void) rloc(m_at(x, y), FALSE);       /* insurance */
547
548         if (!(roamer = makemon(ptr, x, y, NO_MM_FLAGS)))
549                 return((struct monst *)0);
550
551         EPRI(roamer)->shralign = alignment;
552         if (coaligned && !peaceful)
553                 EPRI(roamer)->renegade = TRUE;
554         /* roamer->ispriest == FALSE naturally */
555         roamer->isminion = TRUE;        /* borrowing this bit */
556         roamer->mtrapseen = ~0;         /* traps are known */
557         roamer->mpeaceful = peaceful;
558         roamer->msleeping = 0;
559         set_malign(roamer); /* peaceful may have changed */
560
561         /* MORE TO COME */
562         return(roamer);
563 }
564
565 void
566 reset_hostility(roamer)
567 register struct monst *roamer;
568 {
569         if(!(roamer->isminion && (roamer->data == &mons[PM_ALIGNED_PRIEST] ||
570                                   roamer->data == &mons[PM_ANGEL])))
571                 return;
572
573         if(EPRI(roamer)->shralign != u.ualign.type) {
574             roamer->mpeaceful = roamer->mtame = 0;
575             set_malign(roamer);
576         }
577         newsym(roamer->mx, roamer->my);
578 }
579
580 boolean
581 in_your_sanctuary(mon, x, y)
582 struct monst *mon;      /* if non-null, <mx,my> overrides <x,y> */
583 xchar x, y;
584 {
585         register char roomno;
586         register struct monst *priest;
587
588         if (mon) {
589             if (is_minion(mon->data) || is_rider(mon->data)) return FALSE;
590             x = mon->mx, y = mon->my;
591         }
592         if (u.ualign.record <= ALGN_SINNED)     /* sinned or worse */
593             return FALSE;
594         if ((roomno = temple_occupied(u.urooms)) == 0 ||
595                 roomno != *in_rooms(x, y, TEMPLE))
596             return FALSE;
597         if ((priest = findpriest(roomno)) == 0)
598             return FALSE;
599         return (boolean)(has_shrine(priest) &&
600                          p_coaligned(priest) &&
601                          priest->mpeaceful);
602 }
603
604 void
605 ghod_hitsu(priest)      /* when attacking "priest" in his temple */
606 struct monst *priest;
607 {
608         int x, y, ax, ay, roomno = (int)temple_occupied(u.urooms);
609         struct mkroom *troom;
610
611         if (!roomno || !has_shrine(priest))
612                 return;
613
614         ax = x = EPRI(priest)->shrpos.x;
615         ay = y = EPRI(priest)->shrpos.y;
616         troom = &rooms[roomno - ROOMOFFSET];
617
618         if((u.ux == x && u.uy == y) || !linedup(u.ux, u.uy, x, y)) {
619             if(IS_DOOR(levl[u.ux][u.uy].typ)) {
620
621                 if(u.ux == troom->lx - 1) {
622                     x = troom->hx;
623                     y = u.uy;
624                 } else if(u.ux == troom->hx + 1) {
625                     x = troom->lx;
626                     y = u.uy;
627                 } else if(u.uy == troom->ly - 1) {
628                     x = u.ux;
629                     y = troom->hy;
630                 } else if(u.uy == troom->hy + 1) {
631                     x = u.ux;
632                     y = troom->ly;
633                 }
634             } else {
635                 switch(rn2(4)) {
636                 case 0:  x = u.ux; y = troom->ly; break;
637                 case 1:  x = u.ux; y = troom->hy; break;
638                 case 2:  x = troom->lx; y = u.uy; break;
639                 default: x = troom->hx; y = u.uy; break;
640                 }
641             }
642             if(!linedup(u.ux, u.uy, x, y)) return;
643         }
644
645         switch(rn2(3)) {
646         case 0:
647             pline("%s roars in anger:  \"Thou shalt suffer!\"",
648                         a_gname_at(ax, ay));
649             break;
650         case 1:
651             pline("%s voice booms:  \"How darest thou harm my servant!\"",
652                         s_suffix(a_gname_at(ax, ay)));
653             break;
654         default:
655             pline("%s roars:  \"Thou dost profane my shrine!\"",
656                         a_gname_at(ax, ay));
657             break;
658         }
659
660         buzz(-10-(AD_ELEC-1), 6, x, y, sgn(tbx), sgn(tby)); /* bolt of lightning */
661         exercise(A_WIS, FALSE);
662 }
663
664 void
665 angry_priest()
666 {
667         register struct monst *priest;
668         struct rm *lev;
669
670         if ((priest = findpriest(temple_occupied(u.urooms))) != 0) {
671             wakeup(priest);
672             /*
673              * If the altar has been destroyed or converted, let the
674              * priest run loose.
675              * (When it's just a conversion and there happens to be
676              *  a fresh corpse nearby, the priest ought to have an
677              *  opportunity to try converting it back; maybe someday...)
678              */
679             lev = &levl[EPRI(priest)->shrpos.x][EPRI(priest)->shrpos.y];
680             if (!IS_ALTAR(lev->typ) ||
681                 ((aligntyp)Amask2align(lev->altarmask & AM_MASK) !=
682                         EPRI(priest)->shralign)) {
683                 priest->ispriest = 0;           /* now a roamer */
684                 priest->isminion = 1;           /* but still aligned */
685                 /* this overloads the `shroom' field, which is now clobbered */
686                 EPRI(priest)->renegade = 0;
687             }
688         }
689 }
690
691 /*
692  * When saving bones, find priests that aren't on their shrine level,
693  * and remove them.   This avoids big problems when restoring bones.
694  */
695 void
696 clearpriests()
697 {
698     register struct monst *mtmp, *mtmp2;
699
700     for(mtmp = fmon; mtmp; mtmp = mtmp2) {
701         mtmp2 = mtmp->nmon;
702         if (!DEADMONSTER(mtmp) && mtmp->ispriest && !on_level(&(EPRI(mtmp)->shrlevel), &u.uz))
703             mongone(mtmp);
704     }
705 }
706
707 /* munge priest-specific structure when restoring -dlc */
708 void
709 restpriest(mtmp, ghostly)
710 register struct monst *mtmp;
711 boolean ghostly;
712 {
713     if(u.uz.dlevel) {
714         if (ghostly)
715             assign_level(&(EPRI(mtmp)->shrlevel), &u.uz);
716     }
717 }
718
719 #endif /* OVLB */
720
721 /*priest.c*/