ftp.nice.ch/pub/next/games/strategic/NetHack.s.tar.gz#/NetHackSource/src/priest.c

This is priest.c in view mode; [Download] [Up]

/*	SCCS Id: @(#)priest.c	3.0	89/06/26
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* Copyright (c) Izchak Miller, Steve Linhart, 1989. */
/* NetHack may be freely redistributed.  See license for details. */

#define MONATTK_H	/* comment line for pre-compiled headers */
/* block some unused #defines to avoid overloading some cpp's */
#include "hack.h"
#include "mfndpos.h"
#include "eshk.h"
#include "epri.h"

static boolean FDECL(histemple_at,(struct monst *,int,int));
static int FDECL(t_alignment,(struct mkroom *));
static boolean FDECL(is_shrined,(struct mkroom *));
static boolean FDECL(t_coaligned,(struct mkroom *));
struct monst *FDECL(findpriest,(struct mkroom *));
static boolean FDECL(p_inhistemple,(struct mkroom *));

#ifdef OVLB

/* used for the insides of shk_move and pri_move */
int
move_special(mtmp,monroom,appr,uondoor,avoid,omx,omy,gx,gy)
register struct monst *mtmp;
schar monroom,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 = 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) &&
		    (!needspick(mtmp->data) || m_carrying(mtmp, PICK_AXE)))
		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 (allowflags & ALLOW_DIG) if(!mdig_tunnel(mtmp)) return(-2);

	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(levl[nx][ny].typ == ROOM ||
#if defined(ALTARS) && defined(THEOLOGY)
			(mtmp->ispriest &&
			    levl[nx][ny].typ == ALTAR) ||
#endif
			(mtmp->isshk &&
			    (monroom != ESHK(mtmp)->shoproom
			    || 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 defined(ALTARS) && defined(THEOLOGY)
	if(mtmp->ispriest && avoid &&
			nix == omx && niy == omy && online(omx,omy)) {
		/* might as well move closer as long it's going to stay
		 * lined up */
		avoid = FALSE;
		goto pick_move;
	}
#endif

	if(nix != omx || niy != omy) {
		remove_monster(omx, omy);
		place_monster(mtmp, nix, niy);
		pmon(mtmp);
		if(ib) {
			if (cansee(mtmp->mx,mtmp->my))
			    pline("%s picks up %s.", Monnam(mtmp),
				distant_name(ib,doname));
			freeobj(ib);
			mpickobj(mtmp, ib);
		}
		return(1);
	}
	return(0);
}

#endif /* OVLB */

#if defined(ALTARS) && defined(THEOLOGY)

#ifdef OVL0

struct mkroom *
in_temple(x, y)
register int x, y;
{
	register int roomno = inroom(x, y);

	if (roomno < 0 || rooms[roomno].rtype != TEMPLE)
		return((struct mkroom *)0);
	return(&rooms[roomno]);
}

#endif /* OVL0 */
#ifdef OVLB

static boolean
histemple_at(priest, x, y)
register struct monst *priest;
register int x, y;
{
	return(EPRI(priest)->shroom == inroom(x, y) && 
	       EPRI(priest)->shrlevel == dlevel);
}

/*
 * pri_move: return 1: he moved  0: he 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) {
		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(temple == inroom(u.ux,u.uy)) {
			/* don't chase player outside temple */
			long saveBlind = Blinded;
			struct obj *saveUblindf = ublindf;
			Blinded = 0;
			ublindf = (struct obj *)0;
			if(priest->mcansee && !Invis && cansee(omx,omy)) {
				gx = u.ux;
				gy = u.uy;
			}
			Blinded = saveBlind;
			ublindf = saveUblindf;
			avoid = FALSE;
		}
	} else if(Invis) avoid = FALSE;
	
	return(move_special(priest,temple,TRUE,FALSE,avoid,omx,omy,gx,gy));
}

/* exclusively for mktemple() */
void
priestini(lvl, sx, sy, align)
register int lvl, sx, sy, align;
{
	register struct monst *priest;
	register struct obj *otmp = (struct obj *)0;
#ifdef SPELLS
	register int cnt;
#endif
	if(MON_AT(sx+1, sy)) rloc(m_at(sx+1, sy)); /* insurance */

	if(priest = makemon(&mons[!rn2(2) ? PM_TEMPLE_PRIEST : 
			PM_TEMPLE_PRIESTESS], sx+1, sy)) {
		EPRI(priest)->shroom = inroom(sx, sy);
		EPRI(priest)->shralign = align;
		EPRI(priest)->shrpos.x = sx;
		EPRI(priest)->shrpos.y = sy;
		EPRI(priest)->shrlevel = lvl;
		EPRI(priest)->ismale = 
				(priest->data == &mons[PM_TEMPLE_PRIEST]);
		Strcpy(EPRI(priest)->deitynam, a_gname_at(sx, sy));
		priest->mtrapseen = ~0;	/* traps are known */
		priest->mpeaceful = 1;
		priest->ispriest = 1;
		priest->msleep = 0;

		/* now his/her goodies... */
		(void) mongets(priest, CHAIN_MAIL);
		(void) mongets(priest, SMALL_SHIELD);

		/* Do NOT put the rest in m_initinv.    */
		/* Priests created elsewhere than in a  */
		/* temple should not carry these items, */
		/* except for the mace.			*/
#ifdef SPELLS
		cnt = rn1(2,3);
		while(cnt) {
		    otmp = mkobj(SPBOOK_SYM, FALSE);
		    if(otmp) mpickobj(priest, otmp);
		    cnt--;
		}
#endif
		if(p_coaligned(priest)) {
		    (void) mongets(priest, rn2(2) ? CLOAK_OF_PROTECTION
						  : CLOAK_OF_MAGIC_RESISTANCE);
#ifdef NAMED_ITEMS
		    otmp = mk_aligned_artifact((unsigned)EPRI(priest)->shralign + 1);
		    if(otmp) {
			otmp->spe = rnd(4);
			mpickobj(priest, otmp);
		    }
#endif
		} else {
		    if(!rn2(5)) 
			otmp = mksobj(CLOAK_OF_MAGIC_RESISTANCE, FALSE); 
		    else otmp = mksobj(CLOAK_OF_PROTECTION, FALSE); 
		    if(otmp) {
			if(!rn2(2)) curse(otmp);
			mpickobj(priest, otmp);
		    }
		    otmp = mksobj(MACE, FALSE);
		    if(otmp) {
			otmp->spe = rnd(3);
			if(!rn2(2)) curse(otmp);
			mpickobj(priest, otmp);
		    }
		}
	}
}

char *
priestname(priest)
register struct monst *priest;
{
	static char pname[PL_NSIZ];

	Strcpy(pname, "the ");
	if(priest->minvis) Strcat(pname, "invisible ");
	if(priest->data != &mons[PM_TEMPLE_PRIEST] &&
			priest->data != &mons[PM_TEMPLE_PRIESTESS]) {
		Strcat(pname, priest->data->mname);
		Strcat(pname, " ");
	}
	if(EPRI(priest)->ismale)
		Strcat(pname, "priest of ");
	else 	Strcat(pname, "priestess of ");
	Strcat(pname, EPRI(priest)->deitynam);
	return(pname);
}

boolean
p_coaligned(priest)
struct monst *priest;
{
	return(!strcmp(u_gname(), EPRI(priest)->deitynam));
}

static int
t_alignment(troom)
struct mkroom *troom;
{
	int x, y;

	shrine_pos(&x,&y,troom);

	if(IS_ALTAR(levl[x][y].typ) && (levl[x][y].altarmask & A_SHRINE) != 0)
		return(levl[x][y].altarmask & ~A_SHRINE); 
	return(-2); /* arbitrary non-alignment type value */
}

static boolean
is_shrined(troom)
struct mkroom *troom;
{
	int x, y;

	shrine_pos(&x,&y,troom);

	if(IS_ALTAR(levl[x][y].typ) && (levl[x][y].altarmask & A_SHRINE) != 0)
		return(TRUE);
	return(FALSE);
}

static boolean
t_coaligned(troom)
struct mkroom *troom;
{
	return(t_alignment(troom) == u.ualigntyp + 1);
}

struct monst *
findpriest(troom)
struct mkroom *troom;
{
	register struct monst *mtmp;
	extern struct monst *fdmon; /* from mon.c */

	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
	    if(mtmp->ispriest && histemple_at(mtmp,mtmp->mx,mtmp->my)
			&& &rooms[EPRI(mtmp)->shroom] == troom)
		return(mtmp);
	for(mtmp = fdmon; mtmp; mtmp = mtmp->nmon)
	    if(mtmp->ispriest && histemple_at(mtmp,mtmp->mx,mtmp->my)
			&& &rooms[EPRI(mtmp)->shroom] == troom)
		return(mtmp);
	return (struct monst *)0;
}

static boolean
p_inhistemple(troom)
struct mkroom *troom;
{
	register struct monst *priest;

	priest = findpriest(troom);
	if(priest) return(TRUE);
	return(FALSE);
}

void
intemple() {
	register struct mkroom *troom;

	if(troom = in_temple(u.ux, u.uy)) {
	    boolean shrined = is_shrined(troom);
	    boolean tended = p_inhistemple(troom);

	    if(!in_temple(u.ux0, u.uy0)) {
		pline("Pilgrim, you enter a%s place!",
			(!(shrined || tended) ? " desecrated and deserted" :
			 !shrined ? " desecrated" :
			 !tended ? "n untended sacred" :
			  " sacred"));
		if(!t_coaligned(troom) || u.ualign < -5 || !shrined || !tended)
		    You("have a%s forbidding feeling...",
				(!shrined || !tended) ? "" :
				 " strange");
		else You("experience a strange sense of peace.");
	    } else if(!(shrined || tended) && !rn2(5)) {
		switch(rn2(3)) {
		    case 0: You("have an eerie feeling..."); break;
		    case 1: You("feel like you are being watched."); break;
		    default: pline("A shiver runs down your spine."); break;
		}
		if(!rn2(5)) {
		    struct monst *mtmp;

		    if(!(mtmp = makemon(&mons[PM_GHOST],u.ux,u.uy))) return;
		    pline("An enormous ghost appears next to you!");
		    mtmp->mpeaceful = 0;
		    if(flags.verbose)
		        You("are frightened to death, and unable to move.");
		    nomul(-3);
		    nomovemsg = "You regain your composure.";
		}
	    }
	}
}

void
priest_talk(priest)
register struct monst *priest;
{
	boolean coaligned = p_coaligned(priest);
	boolean strayed = (u.ualign < 0);
 
	if(priest->mflee) {
	    kludge("%s doesn't want anything to do with you!", 
				Monnam(priest));
	    priest->mtame = priest->mpeaceful = 0;
	    return;
	}

	/* priests don't chat unless peaceful and in their own temple */
	if(!histemple_at(priest,priest->mx,priest->my) || priest->mtame ||
		 !priest->mpeaceful || !priest->mcanmove || priest->msleep) {
            if(!priest->mcanmove || priest->msleep) {
	        kludge("%s breaks out of his reverie!", Monnam(priest));
                priest->mfrozen = priest->msleep = 0;
		priest->mcanmove = 1;
	    }
	    /* The following is now impossible according to monst.c, */
	    /* but it should stay just in case we change the latter. */
	    if(priest->mtame)
		kludge("%s breaks out of your taming spell!", Monnam(priest));
	    priest->mtame = priest->mpeaceful = 0;
	    switch(rn2(3)) {
	        case 0: 
		   verbalize("Thou wouldst have words, eh?  I'll give thee a word or two!"); 
		   break;
	        case 1: 
		   verbalize("Talk?  Here is what I have to say!"); 
		   break;
	        default: 
		   verbalize("Pilgrim, I have lost mine desire to talk.");
		   break;
	    }
	    return;
	}

	/* he desecrated the temple and now he wants to chat? */
	if(!is_shrined(&rooms[inroom(priest->mx, priest->my)])
		&& priest->mpeaceful) {
	    verbalize("Begone!  Thou desecratest this holy place with thy presence.");
	    priest->mpeaceful = 0;
	    return;
	} 

	if(!u.ugold) {
	    if(coaligned && !strayed) {
	        kludge("%s gives you two bits for an ale.", Monnam(priest));
	        u.ugold = 2L;
		if (priest->mgold) priest->mgold -= 2L;
	    } else
		kludge("%s is not interested.", Monnam(priest));
	    return;
	} else {
	    long offer;

	    kludge("%s asks you for a contribution for the temple.",
			Monnam(priest));
	    if((offer = bribe(priest)) == 0) {
		verbalize("Thou shalt regret thine action!");
		if(coaligned) u.ualign--;
	    } else if(offer < (u.ulevel * 200)) {
		if(u.ugold > (offer * 2L)) verbalize("Cheapskate.");
		else {
		    verbalize("I thank thee for thy contribution.");
		    /*  give player some token  */
		}
	    } else if(offer < (u.ulevel * 400)) {
		verbalize("Thou art indeed a pious individual.");
		if(u.ugold < (offer * 2L)) { 
		    if(coaligned && u.ualign < -5) u.ualign++;
		    verbalize("I bestow upon thee a blessing.");
		    Clairvoyant += rn1(500,500);
		}
	    } else if(offer < (u.ulevel * 600)) {
		verbalize("Thy devotion has been rewarded.");
		if (!(Protection & INTRINSIC))  {
			Protection |= INTRINSIC;
			if (!u.ublessed)  u.ublessed = rnd(3) + 1;
		} else u.ublessed++;
	    } else {
		verbalize("Thy selfless generosity is deeply appreciated.");
		if(u.ugold < (offer * 2L) && coaligned) {
		    if(strayed && (moves - u.ucleansed) > 5000L) { 
			u.ualign = 0; /* cleanse him */
			u.ucleansed = moves;
		    } else { 
		        u.ualign += 2;
		    }
		}
	    }
	}
}

boolean
u_in_sanctuary(troom) 
register struct mkroom *troom;
{
	register struct mkroom *troom2;

	troom2 = in_temple(u.ux, u.uy);

	return(troom && troom2 && troom == troom2 && is_shrined(troom2) && 
			t_coaligned(troom2) && u.ualign > -5);
}

void
ghod_hitsu() 	/* when attacking a priest in his temple */
{
	int x, y, ax, ay;
	struct monst *priest;
	struct mkroom *troom = in_temple(u.ux, u.uy);

	if(!troom || !is_shrined(troom)) return;

	/* shrine converted by human sacrifice */
	if((priest = findpriest(troom)) && 
	    strcmp(EPRI(priest)->deitynam,
		a_gname_at(EPRI(priest)->shrpos.x, EPRI(priest)->shrpos.y))) 
		    return;

	shrine_pos(&x,&y,troom);
	ax = x;
	ay = y;

	if((u.ux == x && u.uy == y) || !linedup(u.ux, u.uy, x, y)) {
	    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)) return;
	}

	switch(rn2(3)) {
	case 0: 
	    pline("%s roars in anger:  \"Thou shalt suffer!\"", 
			a_gname_at(ax, ay));
	    break;
	case 1: 
	    pline("%s's voice booms:  \"How darest thou harm my servant!\"",
			a_gname_at(ax, ay));
	    break;
	default: 
	    pline("%s roars:  \"Thou dost profane my shrine!\"",
			a_gname_at(ax, ay));
	    break;
	}

	buzz(-15, 6, x, y, sgn(tbx), sgn(tby)); /* -15: bolt of lightning */
}

void
angry_priest()
{
	register struct monst *priest;

	if(!(priest = findpriest(in_temple(u.ux, u.uy)))) return;
	wakeup(priest);
}

#endif /* OVLB */
#endif /* ALTARS && THEOLOGY */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.