Files
nethack/src/priest.c
Pasi Kallinen 411ee58593 Add more explicit helpless reasons
Instead of just "while helpless", the death reason will tell
more explicitly why the player was helpless.  For example:
"while frozen by a monster's gaze"
2015-03-29 22:12:19 +03:00

803 lines
22 KiB
C

/* NetHack 3.5 priest.c $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ */
/* NetHack 3.5 priest.c $Date: 2012/02/16 02:40:24 $ $Revision: 1.27 $ */
/* Copyright (c) Izchak Miller, Steve Linhart, 1989. */
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
#include "mfndpos.h"
/* these match the categorizations shown by enlightenment */
#define ALGN_SINNED (-4) /* worse than strayed (-1..-3) */
#define ALGN_PIOUS 14 /* better than fervent (9..13) */
STATIC_DCL boolean FDECL(histemple_at,(struct monst *,XCHAR_P,XCHAR_P));
STATIC_DCL boolean FDECL(has_shrine,(struct monst *));
void
newepri(mtmp)
struct monst *mtmp;
{
if (!mtmp->mextra) mtmp->mextra = newmextra();
if (!EPRI(mtmp)) {
EPRI(mtmp) = (struct epri *)alloc(sizeof(struct epri));
(void) memset((genericptr_t) EPRI(mtmp), 0, sizeof(struct epri));
}
}
void
free_epri(mtmp)
struct monst *mtmp;
{
if (mtmp->mextra && EPRI(mtmp)) {
free((genericptr_t) EPRI(mtmp));
EPRI(mtmp) = (struct epri *)0;
}
mtmp->ispriest = 0;
}
/*
* Move for priests and shopkeepers. Called from shk_move() and pri_move().
* Valid returns are 1: moved 0: didn't -1: let m_move do it -2: died.
*/
int
move_special(mtmp,in_his_shop,appr,uondoor,avoid,omx,omy,gx,gy)
register struct monst *mtmp;
boolean in_his_shop;
schar appr;
boolean uondoor,avoid;
register xchar omx,omy,gx,gy;
{
register xchar nx,ny,nix,niy;
register schar i;
schar chcnt,cnt;
coord poss[9];
long info[9];
long allowflags;
struct obj *ib = (struct obj *)0;
if(omx == gx && omy == gy)
return(0);
if(mtmp->mconf) {
avoid = FALSE;
appr = 0;
}
nix = omx;
niy = omy;
if (mtmp->isshk) allowflags = ALLOW_SSM;
else allowflags = ALLOW_SSM | ALLOW_SANCT;
if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK|ALLOW_WALL);
if (throws_rocks(mtmp->data)) allowflags |= ALLOW_ROCK;
if (tunnels(mtmp->data)) allowflags |= ALLOW_DIG;
if (!nohands(mtmp->data) && !verysmall(mtmp->data)) {
allowflags |= OPENDOOR;
if (m_carrying(mtmp, SKELETON_KEY)) allowflags |= BUSTDOOR;
}
if (is_giant(mtmp->data)) allowflags |= BUSTDOOR;
cnt = mfndpos(mtmp, poss, info, allowflags);
if(mtmp->isshk && avoid && uondoor) { /* perhaps we cannot avoid him */
for(i=0; i<cnt; i++)
if(!(info[i] & NOTONL)) goto pick_move;
avoid = FALSE;
}
#define GDIST(x,y) (dist2(x,y,gx,gy))
pick_move:
chcnt = 0;
for(i=0; i<cnt; i++) {
nx = poss[i].x;
ny = poss[i].y;
if (IS_ROOM(levl[nx][ny].typ) ||
(mtmp->isshk &&
(!in_his_shop || ESHK(mtmp)->following))) {
if(avoid && (info[i] & NOTONL))
continue;
if((!appr && !rn2(++chcnt)) ||
(appr && GDIST(nx,ny) < GDIST(nix,niy))) {
nix = nx;
niy = ny;
}
}
}
if(mtmp->ispriest && avoid &&
nix == omx && niy == omy && onlineu(omx,omy)) {
/* might as well move closer as long it's going to stay
* lined up */
avoid = FALSE;
goto pick_move;
}
if(nix != omx || niy != omy) {
remove_monster(omx, omy);
place_monster(mtmp, nix, niy);
newsym(nix,niy);
if (mtmp->isshk && !in_his_shop && inhishop(mtmp))
check_special_room(FALSE);
if(ib) {
if (cansee(mtmp->mx,mtmp->my))
pline("%s picks up %s.", Monnam(mtmp),
distant_name(ib,doname));
obj_extract_self(ib);
(void) mpickobj(mtmp, ib);
}
return(1);
}
return(0);
}
char
temple_occupied(array)
register char *array;
{
register char *ptr;
for (ptr = array; *ptr; ptr++)
if (rooms[*ptr - ROOMOFFSET].rtype == TEMPLE)
return(*ptr);
return('\0');
}
STATIC_OVL boolean
histemple_at(priest, x, y)
register struct monst *priest;
register xchar x, y;
{
return((boolean)((EPRI(priest)->shroom == *in_rooms(x, y, TEMPLE)) &&
on_level(&(EPRI(priest)->shrlevel), &u.uz)));
}
boolean
inhistemple(priest)
struct monst *priest;
{
/* make sure we have a priest */
if (!priest || !priest->ispriest) return FALSE;
/* priest must be on right level and in right room */
if (!histemple_at(priest, priest->mx, priest->my)) return FALSE;
/* temple room must still contain properly aligned altar */
return has_shrine(priest);
}
/*
* pri_move: return 1: moved 0: didn't -1: let m_move do it -2: died
*/
int
pri_move(priest)
register struct monst *priest;
{
register xchar gx,gy,omx,omy;
schar temple;
boolean avoid = TRUE;
omx = priest->mx;
omy = priest->my;
if(!histemple_at(priest, omx, omy)) return(-1);
temple = EPRI(priest)->shroom;
gx = EPRI(priest)->shrpos.x;
gy = EPRI(priest)->shrpos.y;
gx += rn1(3,-1); /* mill around the altar */
gy += rn1(3,-1);
if(!priest->mpeaceful ||
(Conflict && !resist(priest, RING_CLASS, 0, 0))) {
if(monnear(priest, u.ux, u.uy)) {
if(Displaced)
Your("displaced image doesn't fool %s!",
mon_nam(priest));
(void) mattacku(priest);
return(0);
} else if(index(u.urooms, temple)) {
/* chase player if inside temple & can see him */
if(priest->mcansee && m_canseeu(priest)) {
gx = u.ux;
gy = u.uy;
}
avoid = FALSE;
}
} else if(Invis) avoid = FALSE;
return(move_special(priest,FALSE,TRUE,FALSE,avoid,omx,omy,gx,gy));
}
/* exclusively for mktemple() */
void
priestini(lvl, sroom, sx, sy, sanctum)
d_level *lvl;
struct mkroom *sroom;
int sx, sy;
boolean sanctum; /* is it the seat of the high priest? */
{
struct monst *priest;
struct obj *otmp;
int cnt;
if(MON_AT(sx+1, sy))
(void) rloc(m_at(sx+1, sy), FALSE); /* insurance */
priest = makemon(&mons[sanctum ? PM_HIGH_PRIEST : PM_ALIGNED_PRIEST],
sx + 1, sy, MM_EPRI);
if (priest) {
EPRI(priest)->shroom = (schar)((sroom - rooms) + ROOMOFFSET);
EPRI(priest)->shralign = Amask2align(levl[sx][sy].altarmask);
EPRI(priest)->shrpos.x = sx;
EPRI(priest)->shrpos.y = sy;
assign_level(&(EPRI(priest)->shrlevel), lvl);
priest->mtrapseen = ~0; /* traps are known */
priest->mpeaceful = 1;
priest->ispriest = 1;
priest->isminion = 0;
priest->msleeping = 0;
set_malign(priest); /* mpeaceful may have changed */
/* now his/her goodies... */
if(sanctum && EPRI(priest)->shralign == A_NONE &&
on_level(&sanctum_level, &u.uz)) {
(void) mongets(priest, AMULET_OF_YENDOR);
}
/* 2 to 4 spellbooks */
for (cnt = rn1(3,2); cnt > 0; --cnt) {
(void) mpickobj(priest, mkobj(SPBOOK_CLASS, FALSE));
}
/* robe [via makemon()] */
if (rn2(2) && (otmp = which_armor(priest, W_ARMC)) != 0) {
if (p_coaligned(priest))
uncurse(otmp);
else
curse(otmp);
}
}
}
/* get a monster's alignment type without caller needing EPRI & EMIN */
aligntyp
mon_aligntyp(mon)
struct monst *mon;
{
aligntyp algn = mon->ispriest ? EPRI(mon)->shralign :
mon->isminion ? EMIN(mon)->min_align :
mon->data->maligntyp;
if (algn == A_NONE) return A_NONE; /* negative but differs from chaotic */
return (algn > 0) ? A_LAWFUL : (algn < 0) ? A_CHAOTIC : A_NEUTRAL;
}
/*
* Specially aligned monsters are named specially.
* - aligned priests with ispriest and high priests have shrines
* they retain ispriest and epri when polymorphed
* - aligned priests without ispriest are roamers
* they have isminion set and use emin rather than epri
* - minions do not have ispriest but have isminion and emin
* - caller needs to inhibit Hallucination if it wants to force
* the true name even when under that influence
*/
char *
priestname(mon, pname)
register struct monst *mon;
char *pname; /* caller-supplied output buffer */
{
boolean do_hallu = Hallucination,
aligned_priest = mon->data == &mons[PM_ALIGNED_PRIEST],
high_priest = mon->data == &mons[PM_HIGH_PRIEST];
char whatcode = '\0';
const char *what = do_hallu ? rndmonnam(&whatcode) : mon->data->mname;
if (!mon->ispriest && !mon->isminion) /* should never happen... */
return strcpy(pname, what); /* caller must be confused */
*pname = '\0';
if (!do_hallu || !bogon_is_pname(whatcode)) Strcat(pname, "the ");
if (mon->minvis) Strcat(pname, "invisible ");
if (mon->isminion && EMIN(mon)->renegade)
Strcat(pname, "renegade ");
if (mon->ispriest || aligned_priest) { /* high_priest implies ispriest */
if (!aligned_priest && !high_priest) {
; /* polymorphed priest; use ``what'' as is */
} else {
if (high_priest)
Strcat(pname, "high ");
if (Hallucination)
what = "poohbah";
else if (mon->female)
what = "priestess";
else
what = "priest";
}
} else {
if (mon->mtame && !strcmpi(what, "Angel"))
Strcat(pname, "guardian ");
}
Strcat(pname, what);
/* same as distant_monnam(), more or less... */
if (do_hallu || !high_priest || !Is_astralevel(&u.uz) ||
distu(mon->mx, mon->my) <= 2 || program_state.gameover) {
Strcat(pname, " of ");
Strcat(pname, halu_gname(mon_aligntyp(mon)));
}
return pname;
}
boolean
p_coaligned(priest)
struct monst *priest;
{
return((boolean)(u.ualign.type == ((int)EPRI(priest)->shralign)));
}
STATIC_OVL boolean
has_shrine(pri)
struct monst *pri;
{
struct rm *lev;
struct epri *epri_p;
if (!pri || !pri->ispriest) return FALSE;
epri_p = EPRI(pri);
lev = &levl[epri_p->shrpos.x][epri_p->shrpos.y];
if (!IS_ALTAR(lev->typ) || !(lev->altarmask & AM_SHRINE)) return FALSE;
return (boolean)(epri_p->shralign ==
(Amask2align(lev->altarmask & ~AM_SHRINE)));
}
struct monst *
findpriest(roomno)
char roomno;
{
register struct monst *mtmp;
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) continue;
if(mtmp->ispriest && (EPRI(mtmp)->shroom == roomno) &&
histemple_at(mtmp,mtmp->mx,mtmp->my))
return(mtmp);
}
return (struct monst *)0;
}
/* called from check_special_room() when the player enters the temple room */
void
intemple(roomno)
int roomno;
{
struct monst *priest, *mtmp;
struct epri *epri_p;
boolean shrined, sanctum, can_speak;
long *this_time, *other_time;
const char *msg1, *msg2;
char buf[BUFSZ];
/* don't do anything if hero is already in the room */
if (temple_occupied(u.urooms0)) return;
if ((priest = findpriest((char)roomno)) != 0) {
/* tended */
epri_p = EPRI(priest);
shrined = has_shrine(priest);
sanctum = (priest->data == &mons[PM_HIGH_PRIEST] &&
(Is_sanctum(&u.uz) || In_endgame(&u.uz)));
can_speak = (priest->mcanmove && !priest->msleeping);
if (can_speak && !Deaf && moves >= epri_p->intone_time) {
unsigned save_priest = priest->ispriest;
/* don't reveal the altar's owner upon temple entry in
the endgame; for the Sanctum, the next message names
Moloch so suppress the "of Moloch" for him here too */
if (sanctum && !Hallucination) priest->ispriest = 0;
pline("%s intones:",
canseemon(priest) ? Monnam(priest) : "A nearby voice");
priest->ispriest = save_priest;
epri_p->intone_time = moves + (long)d(10, 500); /* ~2505 */
/* make sure that we don't suppress entry message when
we've just given its "priest intones" introduction */
epri_p->enter_time = 0L;
}
msg1 = msg2 = 0;
if (sanctum && Is_sanctum(&u.uz)) {
if (priest->mpeaceful) {
/* first time inside */
msg1 = "Infidel, you have entered Moloch's Sanctum!";
msg2 = "Be gone!";
priest->mpeaceful = 0;
/* became angry voluntarily; no penalty for attacking him */
set_malign(priest);
} else {
/* repeat visit, or attacked priest before entering */
msg1 = "You desecrate this place by your presence!";
}
} else if (moves >= epri_p->enter_time) {
Sprintf(buf, "Pilgrim, you enter a %s place!",
!shrined ? "desecrated" : "sacred");
msg1 = buf;
}
if (msg1 && can_speak && !Deaf) {
verbalize1(msg1);
if (msg2) verbalize1(msg2);
epri_p->enter_time = moves + (long)d(10, 100); /* ~505 */
}
if (!sanctum) {
if (!shrined || !p_coaligned(priest) ||
u.ualign.record <= ALGN_SINNED) {
msg1 = "have a%s forbidding feeling...";
msg2 = (!shrined || !p_coaligned(priest)) ? "" : " strange";
this_time = &epri_p->hostile_time;
other_time = &epri_p->peaceful_time;
} else {
msg1 = "experience %s sense of peace.";
msg2 = (u.ualign.record >= ALGN_PIOUS) ? "a" : "an unusual";
this_time = &epri_p->peaceful_time;
other_time = &epri_p->hostile_time;
}
/* give message if we haven't seen it recently or
if alignment update has caused it to switch from
forbidding to sense-of-peace or vice versa */
if (moves >= *this_time || *other_time >= *this_time) {
You(msg1, msg2);
*this_time = moves + (long)d(10, 20); /* ~55 */
/* avoid being tricked by the RNG: switch might have just
happened and previous random threshold could be larger */
if (*this_time <= *other_time) *other_time = *this_time - 1L;
}
}
/* recognize the Valley of the Dead and Moloch's Sanctum
once hero has encountered the temple priest on those levels */
mapseen_temple(priest);
} else {
/* untended */
switch (rn2(4)) {
case 0: You("have an eerie feeling..."); break;
case 1: You_feel("like you are being watched."); break;
case 2: pline("A shiver runs down your %s.",
body_part(SPINE)); break;
default: break; /* no message; unfortunately there's no
EPRI(priest)->eerie_time available to
make sure we give one the first time */
}
if (!rn2(5) &&
(mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, NO_MM_FLAGS)) != 0) {
/* [TODO: alter this (at a minimum, by switching from
an exclamation to a simple declaration) if hero has
already killed enough ghosts.] */
if (canspotmon(mtmp))
pline("An enormous ghost appears next to you!");
else
You("sense a presence close by!");
mtmp->mpeaceful = 0;
set_malign(mtmp);
if (flags.verbose)
You("are frightened to death, and unable to move.");
nomul(-3);
multi_reason = "being terrified of a demon";
nomovemsg = "You regain your composure.";
}
}
}
/* reset the move counters used to limit temple entry feedback;
leaving the level and then returning yields a fresh start */
void
forget_temple_entry(priest)
struct monst *priest;
{
struct epri *epri_p = priest->ispriest ? EPRI(priest) : 0;
if (!epri_p) {
impossible("attempting to manipulate shrine data for non-priest?");
return;
}
epri_p->intone_time = epri_p->enter_time =
epri_p->peaceful_time = epri_p->hostile_time = 0L;
}
void
priest_talk(priest)
register struct monst *priest;
{
boolean coaligned = p_coaligned(priest);
boolean strayed = (u.ualign.record < 0);
/* KMH, conduct */
u.uconduct.gnostic++;
if(priest->mflee || (!priest->ispriest && coaligned && strayed)) {
pline("%s doesn't want anything to do with you!",
Monnam(priest));
priest->mpeaceful = 0;
return;
}
/* priests don't chat unless peaceful and in their own temple */
if(!histemple_at(priest,priest->mx,priest->my) ||
!priest->mpeaceful || !priest->mcanmove || priest->msleeping) {
static const char *cranky_msg[3] = {
"Thou wouldst have words, eh? I'll give thee a word or two!",
"Talk? Here is what I have to say!",
"Pilgrim, I would speak no longer with thee."
};
if(!priest->mcanmove || priest->msleeping) {
pline("%s breaks out of %s reverie!",
Monnam(priest), mhis(priest));
priest->mfrozen = priest->msleeping = 0;
priest->mcanmove = 1;
}
priest->mpeaceful = 0;
verbalize1(cranky_msg[rn2(3)]);
return;
}
/* you desecrated the temple and now you want to chat? */
if(priest->mpeaceful && *in_rooms(priest->mx, priest->my, TEMPLE) &&
!has_shrine(priest)) {
verbalize("Begone! Thou desecratest this holy place with thy presence.");
priest->mpeaceful = 0;
return;
}
if(!money_cnt(invent)) {
if(coaligned && !strayed) {
long pmoney = money_cnt(priest->minvent);
if (pmoney > 0L) {
/* Note: two bits is actually 25 cents. Hmm. */
pline("%s gives you %s for an ale.", Monnam(priest),
(pmoney == 1L) ? "one bit" : "two bits");
money2u(priest, pmoney > 1L ? 2 : 1);
} else
pline("%s preaches the virtues of poverty.", Monnam(priest));
exercise(A_WIS, TRUE);
} else
pline("%s is not interested.", Monnam(priest));
return;
} else {
long offer;
pline("%s asks you for a contribution for the temple.",
Monnam(priest));
if((offer = bribe(priest)) == 0) {
verbalize("Thou shalt regret thine action!");
if(coaligned) adjalign(-1);
} else if(offer < (u.ulevel * 200)) {
if(money_cnt(invent) > (offer * 2L)) verbalize("Cheapskate.");
else {
verbalize("I thank thee for thy contribution.");
/* give player some token */
exercise(A_WIS, TRUE);
}
} else if(offer < (u.ulevel * 400)) {
verbalize("Thou art indeed a pious individual.");
if(money_cnt(invent) < (offer * 2L)) {
if (coaligned && u.ualign.record <= ALGN_SINNED)
adjalign(1);
verbalize("I bestow upon thee a blessing.");
incr_itimeout(&HClairvoyant, rn1(500,500));
}
} else if(offer < (u.ulevel * 600) &&
/* u.ublessed is only active when Protection is
enabled via something other than worn gear
(theft by gremlin clears the intrinsic but not
its former magnitude, making it recoverable) */
(!(HProtection & INTRINSIC) ||
(u.ublessed < 20 &&
(u.ublessed < 9 || !rn2(u.ublessed))))) {
verbalize("Thy devotion has been rewarded.");
if (!(HProtection & INTRINSIC)) {
HProtection |= FROMOUTSIDE;
if (!u.ublessed) u.ublessed = rn1(3, 2);
} else u.ublessed++;
} else {
verbalize("Thy selfless generosity is deeply appreciated.");
if(money_cnt(invent) < (offer * 2L) && coaligned) {
if(strayed && (moves - u.ucleansed) > 5000L) {
u.ualign.record = 0; /* cleanse thee */
u.ucleansed = moves;
} else {
adjalign(2);
}
}
}
}
}
struct monst *
mk_roamer(ptr, alignment, x, y, peaceful)
register struct permonst *ptr;
aligntyp alignment;
xchar x, y;
boolean peaceful;
{
register struct monst *roamer;
register boolean coaligned = (u.ualign.type == alignment);
#if 0 /* this was due to permonst's pxlth field which is now gone */
if (ptr != &mons[PM_ALIGNED_PRIEST] && ptr != &mons[PM_ANGEL])
return((struct monst *)0);
#endif
if (MON_AT(x, y)) (void) rloc(m_at(x, y), FALSE); /* insurance */
if (!(roamer = makemon(ptr, x, y, MM_ADJACENTOK|MM_EMIN)))
return((struct monst *)0);
EMIN(roamer)->min_align = alignment;
EMIN(roamer)->renegade = (coaligned && !peaceful);
roamer->ispriest = 0;
roamer->isminion = 1;
roamer->mtrapseen = ~0; /* traps are known */
roamer->mpeaceful = peaceful;
roamer->msleeping = 0;
set_malign(roamer); /* peaceful may have changed */
/* MORE TO COME */
return(roamer);
}
void
reset_hostility(roamer)
register struct monst *roamer;
{
if (!roamer->isminion) return;
if (roamer->data != &mons[PM_ALIGNED_PRIEST] &&
roamer->data != &mons[PM_ANGEL]) return;
if (EMIN(roamer)->min_align != u.ualign.type) {
roamer->mpeaceful = roamer->mtame = 0;
set_malign(roamer);
}
newsym(roamer->mx, roamer->my);
}
boolean
in_your_sanctuary(mon, x, y)
struct monst *mon; /* if non-null, <mx,my> overrides <x,y> */
xchar x, y;
{
register char roomno;
register struct monst *priest;
if (mon) {
if (is_minion(mon->data) || is_rider(mon->data)) return FALSE;
x = mon->mx, y = mon->my;
}
if (u.ualign.record <= ALGN_SINNED) /* sinned or worse */
return FALSE;
if ((roomno = temple_occupied(u.urooms)) == 0 ||
roomno != *in_rooms(x, y, TEMPLE))
return FALSE;
if ((priest = findpriest(roomno)) == 0)
return FALSE;
return (boolean)(has_shrine(priest) &&
p_coaligned(priest) &&
priest->mpeaceful);
}
void
ghod_hitsu(priest) /* when attacking "priest" in his temple */
struct monst *priest;
{
int x, y, ax, ay, roomno = (int)temple_occupied(u.urooms);
struct mkroom *troom;
if (!roomno || !has_shrine(priest))
return;
ax = x = EPRI(priest)->shrpos.x;
ay = y = EPRI(priest)->shrpos.y;
troom = &rooms[roomno - ROOMOFFSET];
if ((u.ux == x && u.uy == y) || !linedup(u.ux, u.uy, x, y, 1)) {
if(IS_DOOR(levl[u.ux][u.uy].typ)) {
if(u.ux == troom->lx - 1) {
x = troom->hx;
y = u.uy;
} else if(u.ux == troom->hx + 1) {
x = troom->lx;
y = u.uy;
} else if(u.uy == troom->ly - 1) {
x = u.ux;
y = troom->hy;
} else if(u.uy == troom->hy + 1) {
x = u.ux;
y = troom->ly;
}
} else {
switch(rn2(4)) {
case 0: x = u.ux; y = troom->ly; break;
case 1: x = u.ux; y = troom->hy; break;
case 2: x = troom->lx; y = u.uy; break;
default: x = troom->hx; y = u.uy; break;
}
}
if (!linedup(u.ux, u.uy, x, y, 1)) return;
}
switch(rn2(3)) {
case 0:
pline("%s roars in anger: \"Thou shalt suffer!\"",
a_gname_at(ax, ay));
break;
case 1:
pline("%s voice booms: \"How darest thou harm my servant!\"",
s_suffix(a_gname_at(ax, ay)));
break;
default:
pline("%s roars: \"Thou dost profane my shrine!\"",
a_gname_at(ax, ay));
break;
}
buzz(-10-(AD_ELEC-1), 6, x, y, sgn(tbx), sgn(tby)); /* bolt of lightning */
exercise(A_WIS, FALSE);
}
void
angry_priest()
{
register struct monst *priest;
struct rm *lev;
if ((priest = findpriest(temple_occupied(u.urooms))) != 0) {
struct epri *eprip = EPRI(priest);
wakeup(priest);
/*
* If the altar has been destroyed or converted, let the
* priest run loose.
* (When it's just a conversion and there happens to be
* a fresh corpse nearby, the priest ought to have an
* opportunity to try converting it back; maybe someday...)
*/
lev = &levl[eprip->shrpos.x][eprip->shrpos.y];
if (!IS_ALTAR(lev->typ) ||
((aligntyp)Amask2align(lev->altarmask & AM_MASK) !=
eprip->shralign)) {
if (!EMIN(priest)) newemin(priest);
priest->ispriest = 0; /* now a roaming minion */
priest->isminion = 1;
EMIN(priest)->min_align = eprip->shralign;
EMIN(priest)->renegade = FALSE;
/* discard priest's memory of his former shrine;
if we ever implement the re-conversion mentioned
above, this will need to be removed */
free_epri(priest);
}
}
}
/*
* When saving bones, find priests that aren't on their shrine level,
* and remove them. This avoids big problems when restoring bones.
* [Perhaps we should convert them into roamers instead?]
*/
void
clearpriests()
{
struct monst *mtmp;
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) continue;
if (mtmp->ispriest && !on_level(&(EPRI(mtmp)->shrlevel), &u.uz))
mongone(mtmp);
}
}
/* munge priest-specific structure when restoring -dlc */
void
restpriest(mtmp, ghostly)
register struct monst *mtmp;
boolean ghostly;
{
if(u.uz.dlevel) {
if (ghostly)
assign_level(&(EPRI(mtmp)->shrlevel), &u.uz);
}
}
/*priest.c*/