[comp.sources.games] v10i077: nethack3p9 - display oriented dungeons & dragons

billr@saab.CNA.TEK.COM (Bill Randle) (07/12/90)

Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 10, Issue 77
Archive-name: nethack3p9/Part32
Supersedes: NetHack3: Volume 7, Issue 56-93



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 32 (of 56)."
# Contents:  src/mklev.c src/monmove.c src/rip.c
# Wrapped by billr@saab on Wed Jul 11 17:11:39 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/mklev.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/mklev.c'\"
else
echo shar: Extracting \"'src/mklev.c'\" \(28964 characters\)
sed "s/^X//" >'src/mklev.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)mklev.c	3.0	89/12/06
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include "hack.h"
X
X/* for UNIX, Rand #def'd to (long)lrand48() or (long)random() */
X/* croom->lx etc are schar (width <= int), so % arith ensures that */
X/* conversion of result to int is reasonable */
X
X#ifdef SINKS
Xstatic void FDECL(mksink,(struct mkroom *));
X#endif
X#ifdef ALTARS
Xstatic void FDECL(mkaltar,(struct mkroom *));
X#endif
Xstatic boolean FDECL(occupied,(XCHAR_P,XCHAR_P));
Xstatic void NDECL(makevtele);
Xstatic void NDECL(init_levels);
Xstatic void NDECL(makelevel);
Xstatic boolean FDECL(bydoor,(XCHAR_P,XCHAR_P));
Xstatic boolean FDECL(place_niche,(struct mkroom *,int*,int*,int*));
Xstatic void FDECL(makeniche,(int));
Xstatic void NDECL(make_niches);
Xstatic void NDECL(makebigroom);
Xstatic void FDECL(addrsx,(int,int,int,int,BOOLEAN_P));
Xstatic void FDECL(addrs,(int,int,int,int));
XSTATIC_PTR int FDECL(comp,(genericptr_t,genericptr_t));
Xstatic void FDECL(dosdoor,(int,int,struct mkroom *,int));
Xstatic void NDECL(makecorridors);
Xstatic void FDECL(join,(int,int));
Xstatic int NDECL(makerooms);
Xstatic int FDECL(maker,(SCHAR_P,SCHAR_P,SCHAR_P,SCHAR_P,BOOLEAN_P));
Xstatic void FDECL(finddpos,(coord *,XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P));
X
Xint
Xsomex(croom)
Xregister struct mkroom *croom;
X{
X	return rn2(croom->hx-croom->lx+1) + croom->lx;
X}
X
Xint
Xsomey(croom)
Xregister struct mkroom *croom;
X{
X	return rn2(croom->hy-croom->ly+1) + croom->ly;
X}
X
X#define	XLIM	4	/* define minimum required space around a room */
X#define	YLIM	3
Xboolean secret;		/* TRUE while making a vault: increase [XY]LIM */
Xstruct rm zerorm;
Xschar nxcor;
Xboolean goldseen;
X
X/* Definitions used by makerooms() and addrs() */
X#define	MAXRS	50	/* max lth of temp rectangle table - arbitrary */
Xstruct rectangle {
X	xchar rlx,rly,rhx,rhy;
X} rs[MAXRS+1];
Xint rscnt,rsmax;	/* 0..rscnt-1: currently under consideration */
X			/* rscnt..rsmax: discarded */
X
Xstatic void
Xaddrsx(lx,ly,hx,hy,discarded)
Xregister int lx,ly,hx,hy;
Xboolean discarded;		/* piece of a discarded area */
X{
X	register struct rectangle *rsp;
X
X	/* check inclusions */
X	for(rsp = rs; rsp < &rs[rsmax]; rsp++) {
X		if(lx >= rsp->rlx && hx <= rsp->rhx &&
X		   ly >= rsp->rly && hy <= rsp->rhy)
X			return;
X	}
X
X	/* make a new entry */
X	if(rsmax >= MAXRS) {
X#ifdef WIZARD
X		if(wizard) pline("MAXRS may be too small.");
X#endif
X		return;
X	}
X	rsmax++;
X	if(!discarded) {
X		*rsp = rs[rscnt];
X		rsp = &rs[rscnt];
X		rscnt++;
X	}
X	rsp->rlx = lx;
X	rsp->rly = ly;
X	rsp->rhx = hx;
X	rsp->rhy = hy;
X}
X
Xstatic void
Xaddrs(lowx,lowy,hix,hiy)
Xregister int lowx,lowy,hix,hiy;
X{
X	register struct rectangle *rsp;
X	register int lx,ly,hx,hy,xlim,ylim;
X	boolean discarded;
X
X	xlim = XLIM + secret;
X	ylim = YLIM + secret;
X
X	/* walk down since rscnt and rsmax change */
X	for(rsp = &rs[rsmax-1]; rsp >= rs; rsp--) {
X
X		if((lx = rsp->rlx) > hix || (ly = rsp->rly) > hiy ||
X		   (hx = rsp->rhx) < lowx || (hy = rsp->rhy) < lowy)
X			continue;
X		if((discarded = (rsp >= &rs[rscnt]))) {
X			*rsp = rs[--rsmax];
X		} else {
X			rsmax--;
X			rscnt--;
X			*rsp = rs[rscnt];
X			if(rscnt != rsmax)
X				rs[rscnt] = rs[rsmax];
X		}
X		if(lowy - ly > 2*ylim + 4)
X			addrsx(lx,ly,hx,lowy-2,discarded);
X		if(lowx - lx > 2*xlim + 4)
X			addrsx(lx,ly,lowx-2,hy,discarded);
X		if(hy - hiy > 2*ylim + 4)
X			addrsx(lx,hiy+2,hx,hy,discarded);
X		if(hx - hix > 2*xlim + 4)
X			addrsx(hix+2,ly,hx,hy,discarded);
X	}
X}
X
X/* Args must be genericptr_t so that qsort will always be happy. */
X
XSTATIC_PTR int
Xcomp(vx,vy)
Xgenericptr_t vx;
Xgenericptr_t vy;
X{
X#ifdef LINT
X/* lint complains about possible pointer alignment problems, but we know
X   that vx and vy are always properly aligned. Hence, the following
X   bogus definition:
X*/
X	return (vx == vy) ? 0 : -1;
X#else
X	register struct mkroom *x, *y;
X
X	x = (struct mkroom *)vx;
X	y = (struct mkroom *)vy;
X	if(x->lx < y->lx) return(-1);
X	return(x->lx > y->lx);
X#endif /* LINT */
X}
X
Xstatic void
Xfinddpos(cc, xl,yl,xh,yh)
Xcoord	*cc;
Xxchar	xl,yl,xh,yh;
X{
X	register xchar x, y;
X
X	x = (xl == xh) ? xl : (xl + rn2(xh-xl+1));
X	y = (yl == yh) ? yl : (yl + rn2(yh-yl+1));
X	if(okdoor(x, y))
X		goto gotit;
X
X	for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
X		if(okdoor(x, y))
X			goto gotit;
X
X	for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
X		if(IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR)
X			goto gotit;
X	/* cannot find something reasonable -- strange */
X	x = xl;
X	y = yh;
Xgotit:
X	cc->x = x;
X	cc->y = y;
X	return;
X}
X
X/* Only called from makerooms() and makebigroom() */
Xstatic int
Xmaker(lowx,ddx,lowy,ddy,lit)
Xschar lowx,ddx,lowy,ddy;
Xboolean lit;
X{
X	register struct mkroom *croom;
X	register int x, y, hix = lowx+ddx, hiy = lowy+ddy;
X	register int xlim = XLIM + secret, ylim = YLIM + secret;
X
X	if(nroom >= MAXNROFROOMS) return(0);
X	if(lowx < XLIM) lowx = XLIM;
X	if(lowy < YLIM) lowy = YLIM;
X	if(hix > COLNO-XLIM-1) hix = COLNO-XLIM-1;
X	if(hiy > ROWNO-YLIM-1) hiy = ROWNO-YLIM-1;
Xchk:
X	if(hix <= lowx || hiy <= lowy) return(0);
X
X	/* check area around room (and make room smaller if necessary) */
X	for(x = lowx - xlim; x <= hix + xlim; x++) {
X		for(y = lowy - ylim; y <= hiy + ylim; y++) {
X			if(isok(x,y) && levl[x][y].typ) {
X#ifdef WIZARD
X			    if(wizard && !secret)
X				pline("Strange area [%d,%d] in maker().",x,y);
X#endif
X			    if(!rn2(3)) return(0);
X			    if(x < lowx)
X				    lowx = x+xlim+1;
X			    else
X				    hix = x-xlim-1;
X			    if(y < lowy)
X				    lowy = y+ylim+1;
X			    else
X				    hiy = y-ylim-1;
X			    goto chk;
X			}
X		}
X	}
X
X	croom = &rooms[nroom];
X
X	/* on low levels the room is lit (usually) */
X	/* secret vaults are always lit */
X	/* some other rooms may require lighting */
X	if((rnd(dlevel) < 10 && rn2(77)) || secret || lit) {
X		for(x = lowx-1; x <= hix+1; x++)
X			for(y = lowy-1; y <= hiy+1; y++)
X				levl[x][y].lit = 1;
X		croom->rlit = 1;
X	} else
X		croom->rlit = 0;
X	croom->lx = lowx;
X	croom->hx = hix;
X	croom->ly = lowy;
X	croom->hy = hiy;
X	croom->rtype = OROOM;
X	croom->doorct = 0;
X	/* if we're not making a vault, doorindex will still be 0
X	 * if we are, we'll have problems adding niches to the previous room
X	 * unless fdoor is at least doorindex
X	 */
X	croom->fdoor = doorindex;
X
X	for(x = lowx-1; x <= hix+1; x++)
X	    for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
X		levl[x][y].typ = HWALL;
X		levl[x][y].scrsym = HWALL_SYM;
X	    }
X	for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
X	    for(y = lowy; y <= hiy; y++) {
X		levl[x][y].typ = VWALL;
X		levl[x][y].scrsym = VWALL_SYM;
X	    }
X	for(x = lowx; x <= hix; x++)
X	    for(y = lowy; y <= hiy; y++) {
X		levl[x][y].typ = ROOM;
X		levl[x][y].scrsym = ROOM_SYM;
X	    }
X	levl[lowx-1][lowy-1].typ = TLCORNER;
X	levl[hix+1][lowy-1].typ = TRCORNER;
X	levl[lowx-1][hiy+1].typ = BLCORNER;
X	levl[hix+1][hiy+1].typ = BRCORNER;
X	levl[lowx-1][lowy-1].scrsym = TLCORN_SYM;
X	levl[hix+1][lowy-1].scrsym = TRCORN_SYM;
X	levl[lowx-1][hiy+1].scrsym = BLCORN_SYM;
X	levl[hix+1][hiy+1].scrsym = BRCORN_SYM;
X
X	smeq[nroom] = nroom;
X	croom++;
X	croom->hx = -1;
X	nroom++;
X	return(1);
X}
X
Xstatic int
Xmakerooms() {
Xregister struct rectangle *rsp;
Xregister int lx, ly, hx, hy, lowx, lowy, hix, hiy, dx, dy;
Xint tryct = 0, xlim, ylim;
X
X	/* init */
X	xlim = XLIM + secret;
X	ylim = YLIM + secret;
X	if(nroom == 0) {
X		rsp = rs;
X		rsp->rlx = rsp->rly = 0;
X		rsp->rhx = COLNO-1;
X		rsp->rhy = ROWNO-1;
X		rsmax = 1;
X	}
X	rscnt = rsmax;
X
X	/* make rooms until satisfied */
X	while(rscnt > 0 && nroom < MAXNROFROOMS-1) {
X		if(!secret && nroom > (MAXNROFROOMS/4) &&
X		   !rn2((MAXNROFROOMS-nroom)*(MAXNROFROOMS-nroom)))
X			return 0;
X
X		/* pick a rectangle */
X		rsp = &rs[rn2(rscnt)];
X		hx = rsp->rhx;
X		hy = rsp->rhy;
X		lx = rsp->rlx;
X		ly = rsp->rly;
X
X		/* find size of room */
X		if(secret)
X			dx = dy = 1;
X		else {
X			dx = 2 + rn2((hx-lx-8 > 20) ? 12 : 8);
X			dy = 2 + rn2(4);
X			if(dx*dy > 50)
X				dy = 50/dx;
X		}
X
X		/* look whether our room will fit */
X		if(hx-lx < dx + (dx>>1) + 2*xlim ||
X		   hy-ly < dy + dy/3 + 2*ylim) {
X					/* no, too small */
X					/* maybe we throw this area out */
X			if(secret || !rn2(MAXNROFROOMS+1-nroom-tryct)) {
X				rscnt--;
X				rs[rsmax] = *rsp;
X				*rsp = rs[rscnt];
X				rs[rscnt] = rs[rsmax];
X				tryct = 0;
X			} else
X				tryct++;
X			continue;
X		}
X
X		lowx = lx + xlim + rn2(hx - lx - dx - 2*xlim + 1);
X		lowy = ly + ylim + rn2(hy - ly - dy - 2*ylim + 1);
X		hix = lowx + dx;
X		hiy = lowy + dy;
X
X		if(maker(lowx, dx, lowy, dy, FALSE)) {
X			if(secret) return(1);
X			addrs(lowx-1, lowy-1, hix+1, hiy+1);
X			tryct = 0;
X		} else
X			if(tryct++ > 100)
X				break;
X	}
X	return(0);	/* failed to make vault - very strange */
X}
X
Xstatic void
Xjoin(a,b)
Xregister int a, b;
X{
X	coord cc,tt;
X	register int tx, ty, xx, yy;
X	register struct rm *crm;
X	register struct mkroom *croom, *troom;
X	register int dx, dy, dix, diy, cct;
X
X	croom = &rooms[a];
X	troom = &rooms[b];
X
X	/* find positions cc and tt for doors in croom and troom
X	   and direction for a corridor between them */
X
X	if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return;
X	if(troom->lx > croom->hx) {
X		dx = 1;
X		dy = 0;
X		xx = croom->hx+1;
X		tx = troom->lx-1;
X		finddpos(&cc, xx, croom->ly, xx, croom->hy);
X		finddpos(&tt, tx, troom->ly, tx, troom->hy);
X	} else if(troom->hy < croom->ly) {
X		dy = -1;
X		dx = 0;
X		yy = croom->ly-1;
X		finddpos(&cc, croom->lx, yy, croom->hx, yy);
X		ty = troom->hy+1;
X		finddpos(&tt, troom->lx, ty, troom->hx, ty);
X	} else if(troom->hx < croom->lx) {
X		dx = -1;
X		dy = 0;
X		xx = croom->lx-1;
X		tx = troom->hx+1;
X		finddpos(&cc, xx, croom->ly, xx, croom->hy);
X		finddpos(&tt, tx, troom->ly, tx, troom->hy);
X	} else {
X		dy = 1;
X		dx = 0;
X		yy = croom->hy+1;
X		ty = troom->ly-1;
X		finddpos(&cc, croom->lx, yy, croom->hx, yy);
X		finddpos(&tt, troom->lx, ty, troom->hx, ty);
X	}
X	xx = cc.x;
X	yy = cc.y;
X	tx = tt.x - dx;
X	ty = tt.y - dy;
X	if(nxcor && levl[xx+dx][yy+dy].typ)
X		return;
X	dodoor(xx,yy,croom);
X
X	cct = 0;
X	while(xx != tx || yy != ty) {
X	    xx += dx;
X	    yy += dy;
X
X	    /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
X	    if(cct++ > 500 || (nxcor && !rn2(35)))
X		return;
X
X	    if(xx == COLNO-1 || xx == 0 || yy == 0 || yy == ROWNO-1)
X		return;		/* impossible */
X
X	    crm = &levl[xx][yy];
X	    if(!(crm->typ)) {
X		if(rn2(100)) {
X			crm->typ = CORR;
X			crm->scrsym = CORR_SYM;
X			if(nxcor && !rn2(50))
X				(void) mksobj_at(BOULDER, xx, yy);
X		} else {
X			crm->typ = SCORR;
X			crm->scrsym = ' ';	/* _not_ STONE_SYM */
X		}
X	    } else
X	    if(crm->typ != CORR && crm->typ != SCORR) {
X		/* strange ... */
X		return;
X	    }
X
X	    /* find next corridor position */
X	    dix = abs(xx-tx);
X	    diy = abs(yy-ty);
X
X	    /* do we have to change direction ? */
X	    if(dy && dix > diy) {
X		register int ddx = (xx > tx) ? -1 : 1;
X
X		crm = &levl[xx+ddx][yy];
X		if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) {
X		    dx = ddx;
X		    dy = 0;
X		    continue;
X		}
X	    } else if(dx && diy > dix) {
X		register int ddy = (yy > ty) ? -1 : 1;
X
X		crm = &levl[xx][yy+ddy];
X		if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) {
X		    dy = ddy;
X		    dx = 0;
X		    continue;
X		}
X	    }
X
X	    /* continue straight on? */
X	    crm = &levl[xx+dx][yy+dy];
X	    if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
X		continue;
X
X	    /* no, what must we do now?? */
X	    if(dx) {
X		dx = 0;
X		dy = (ty < yy) ? -1 : 1;
X		crm = &levl[xx+dx][yy+dy];
X		if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
X		    continue;
X		dy = -dy;
X		continue;
X	    } else {
X		dy = 0;
X		dx = (tx < xx) ? -1 : 1;
X		crm = &levl[xx+dx][yy+dy];
X		if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
X		    continue;
X		dx = -dx;
X		continue;
X	    }
X	}
X
X	/* we succeeded in digging the corridor */
X	dodoor(tt.x, tt.y, troom);
X
X	if(smeq[a] < smeq[b])
X		smeq[b] = smeq[a];
X	else
X		smeq[a] = smeq[b];
X}
X
Xstatic void
Xmakecorridors() {
X	register int a, b;
X
X	nxcor = 0;
X	for(a = 0; a < nroom-1; a++)
X		join(a, a+1);
X	for(a = 0; a < nroom-2; a++)
X	    if(smeq[a] != smeq[a+2])
X		join(a, a+2);
X	for(a = 0; a < nroom; a++)
X	    for(b = 0; b < nroom; b++)
X		if(smeq[a] != smeq[b])
X		    join(a, b);
X	if(nroom > 2)
X	    for(nxcor = rn2(nroom) + 4; nxcor; nxcor--) {
X		a = rn2(nroom);
X		b = rn2(nroom-2);
X		if(b >= a) b += 2;
X		join(a, b);
X	    }
X}
X
Xstatic void
Xdosdoor(x,y,aroom,type)
Xregister int x, y;
Xregister struct mkroom *aroom;
Xregister int type;
X{
X	register struct mkroom *broom;
X	register int tmp;
X	boolean shdoor = in_shop(x, y);
X
X	if(!IS_WALL(levl[x][y].typ)) /* avoid SDOORs with DOOR_SYM as scrsym */
X		type = DOOR;
X	levl[x][y].typ = type;
X	if(type == DOOR) {
X	    if(!rn2(3)) {      /* is it a locked door, closed, or a doorway? */
X		if(!rn2(5))
X		    levl[x][y].doormask = D_ISOPEN;
X		else if(!rn2(6))
X		    levl[x][y].doormask = D_LOCKED;
X		else
X		    levl[x][y].doormask = D_CLOSED;
X
X		if (levl[x][y].doormask != D_ISOPEN && !shdoor && !rn2(25))
X		    levl[x][y].doormask |= D_TRAPPED;
X	    } else
X#ifdef STUPID
X		if (shdoor)
X			levl[x][y].doormask = D_ISOPEN;
X		else
X			levl[x][y].doormask = D_NODOOR;
X#else
X		levl[x][y].doormask = (shdoor ? D_ISOPEN : D_NODOOR);
X#endif
X	    levl[x][y].scrsym = news0(x,y);
X	} else { /* SDOOR */
X		if(shdoor || !rn2(5))	levl[x][y].doormask = D_LOCKED;
X		else			levl[x][y].doormask = D_CLOSED;
X
X		if(!shdoor && !rn2(20)) levl[x][y].doormask |= D_TRAPPED;
X	}
X	aroom->doorct++;
X	broom = aroom+1;
X	if(broom->hx < 0) tmp = doorindex; else
X	for(tmp = doorindex; tmp > broom->fdoor; tmp--)
X		doors[tmp] = doors[tmp-1];
X	doorindex++;
X	doors[tmp].x = x;
X	doors[tmp].y = y;
X	for( ; broom->hx >= 0; broom++) broom->fdoor++;
X}
X
Xstatic boolean
Xplace_niche(aroom,dy,xx,yy)
Xregister struct mkroom *aroom;
Xint *dy, *xx, *yy;
X{
X	coord dd;
X
X	if(rn2(2)) {
X	    *dy = 1;
X	    finddpos(&dd, aroom->lx, aroom->hy+1, aroom->hx, aroom->hy+1);
X	} else {
X	    *dy = -1;
X	    finddpos(&dd, aroom->lx, aroom->ly-1, aroom->hx, aroom->ly-1);
X	}
X	*xx = dd.x;
X	*yy = dd.y;
X	return(levl[*xx][(*yy)+(*dy)].typ == STONE);
X}
X
X#ifdef ORACLE
Xboolean
Xplace_oracle(aroom,dy,xx,yy)
Xregister struct mkroom *aroom;
Xint *dy, *xx, *yy;
X{
X	if(!place_niche(aroom,dy,xx,yy)) return FALSE;
X
X	dosdoor(*xx,*yy,aroom,DOOR);
X	levl[*xx][*yy].doormask = D_NODOOR;
X	return TRUE;
X}
X#endif
X
X/* there should be one of these per trap */
Xconst char *engravings[] = {	"", "", "", "", "", "",
X				"?la? ?as ?er?", "ad ae?ar um",
X				"", "", "", "" ,""
X				, "", "ad ae?ar um"
X#ifdef SPELLS
X				,""
X#endif
X				,""
X#ifdef POLYSELF
X				,""
X#endif
X				,""
X				};
X
Xstatic void
Xmakeniche(trap_type)
Xint trap_type;
X{
X	register struct mkroom *aroom;
X	register struct rm *rm;
X	register int vct = 8;
X	int dy, xx, yy;
X	register struct trap *ttmp;
X
X	if(doorindex < DOORMAX)
X	  while(vct--) {
X	    aroom = &rooms[rn2(nroom)];
X	    if(aroom->rtype != OROOM) continue;	/* not an ordinary room */
X	    if(aroom->doorct == 1 && rn2(5)) continue;
X	    if(!place_niche(aroom,&dy,&xx,&yy)) continue;
X
X	    rm = &levl[xx][yy+dy];
X	    if(trap_type || !rn2(4)) {
X
X		rm->typ = SCORR;
X		rm->scrsym = ' ';		/* _not_ STONE_SYM */
X		if(trap_type) {
X		    ttmp = maketrap(xx, yy+dy, trap_type);
X		    ttmp->once = 1;
X		    if (strlen(engravings[trap_type]) > 0)
X			make_engr_at(xx, yy-dy, engravings[trap_type]);
X		}
X		dosdoor(xx, yy, aroom, SDOOR);
X	    } else {
X		rm->typ = CORR;
X		rm->scrsym = CORR_SYM;
X		if(rn2(7))
X		    dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR);
X		else {
X		    (void) mksobj_at(SCR_TELEPORTATION, xx, yy+dy);
X		    if(!rn2(3)) (void) mkobj_at(0, xx, yy+dy, TRUE);
X		}
X	    }
X	    return;
X	}
X}
X
Xstatic void
Xmake_niches()
X{
X	register int ct = rnd((nroom>>1) + 1);
X	boolean	ltptr = TRUE,
X		vamp = TRUE;
X
X	while(ct--) {
X
X		if(dlevel > 15 && !rn2(6) && ltptr) {
X
X			ltptr = FALSE;
X			makeniche(LEVEL_TELEP);
X		} else if (dlevel > 5 && dlevel < 25
X			   && !rn2(6) && vamp) {
X
X			vamp = FALSE;
X			makeniche(TRAPDOOR);
X		} else	makeniche(NO_TRAP);
X	}
X}
X
Xstatic void
Xmakebigroom()
X{
X	register int x,y,n;
X	register struct mkroom *croom;
X	register struct monst *tmonst;
X
X	/* make biggest possible room; make sure it's lit */
X	(void) maker(XLIM, COLNO - 2*XLIM - 1, YLIM, ROWNO - 2*YLIM - 1, TRUE);
X	croom = &rooms[0];
X
X	/* add extra monsters and goodies */
X	n = 10 + rn2(15);
X	while (n--) {
X		x = somex(croom);
X		y = somey(croom);
X		tmonst = makemon((struct permonst *) 0,x,y);
X		if (tmonst && tmonst->data==&mons[PM_GIANT_SPIDER])
X			(void) maketrap(x,y,WEB);
X		if (tmonst && rn2(2))
X			tmonst->msleep = 1;
X	}
X	n = 6 + rn2(10);
X	while (n--)
X		(void) mkobj_at(0,somex(croom),somey(croom),TRUE);
X}
X
Xstatic void
Xmakevtele()
X{
X	makeniche(TELEP_TRAP);
X}
X
X#define rntwixt(L1,L2)	rn1((L2)-(L1),L1)
X
Xstatic void
Xinit_levels()
X{
X#if defined(STRONGHOLD) && defined(MUSIC)
X	register int x;
X#endif
X
X#ifdef LINT	/* handle constant in conditional context */
X	medusa_level = 0;
X#else
X	medusa_level = rn1(3, HELLLEVEL - 5);
X#endif /* LINT */
X#ifdef STRONGHOLD
X	stronghold_level = rn1(5, medusa_level)+1;
X# ifdef MUSIC
X	for (x=0; x<5; x++)
X		tune[x] = 'A' + rn2(7);
X	tune[5] = 0;
X# endif
X	/* The tower will be on 3 levels */
X	tower_level = rntwixt(stronghold_level, MAXLEVEL-2)+1;
X	/* We don't want the wizard in Vlad's tower */
X	do
X		wiz_level = rntwixt(stronghold_level, MAXLEVEL)+1;
X	while (wiz_level >= tower_level && wiz_level <= tower_level + 2);
X#else
X	wiz_level	 = rntwixt(medusa_level, MAXLEVEL)+1;
X#endif /* STRONGHOLD /**/
X#ifdef WIZARD
X	if (!rn2(15) || wizard)
X#else
X	if (!rn2(15))
X#endif
X		/* between the middle of the dungeon and the medusa level */
X		bigroom_level = rntwixt(HELLLEVEL>>1, medusa_level);
X#ifdef REINCARNATION
X# ifdef WIZARD
X	if (!rn2(3) || wizard)
X# else
X	if (!rn2(3))
X# endif
X		rogue_level = rn1(5,10);
X#endif
X#ifdef ORACLE
X	oracle_level = rn1(4,5);
X#endif
X}
X
X#undef rntwixt
X
Xstatic void
Xmakelevel() {
X	register struct mkroom *croom, *troom;
X	register unsigned int tryct;
X	register int x,y;
X	struct monst *tmonst;	/* always put a web with a spider */
X
X	nroom = 0;
X	doorindex = 0;
X	rooms[0].hx = -1;	/* in case we are in a maze */
X
X	for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++) {
X		levl[x][y] = zerorm;
X		level.objects[x][y] = (struct obj *)0;
X		level.monsters[x][y] = (struct monst *)0;
X	}
X
X	oinit();	/* assign level dependent obj probabilities */
X	fountsound = 0;
X	sinksound = 0;
X
X	if (wiz_level == 0)
X		init_levels();
X	if (
X#ifndef STRONGHOLD
X	    Inhell
X#else
X	    dlevel >= stronghold_level || dlevel < 0
X#endif
X	    || (dlevel > medusa_level && rn2(5))
X	   ) {
X	    makemaz();
X	    return;
X	}
X
X	/* construct the rooms */
X	nroom = 0;
X	secret = FALSE;
X
X#ifdef REINCARNATION
X	if (dlevel == rogue_level) {
X	    makeroguerooms();
X	    makerogueghost();
X	} else
X#endif
X	if (dlevel == bigroom_level)
X	    makebigroom();
X	else
X	    (void) makerooms();
X
X	/* construct stairs (up and down in different rooms if possible) */
X	croom = &rooms[rn2(nroom)];
X	xdnstair = somex(croom);
X	ydnstair = somey(croom);
X	levl[xdnstair][ydnstair].scrsym = DN_SYM;
X	levl[xdnstair][ydnstair].typ = STAIRS;
X#ifdef MEDUSA
X	if (dlevel == medusa_level) {
X		struct monst *mtmp;
X		struct obj *otmp;
X
X		if (mtmp = makemon(&mons[PM_MEDUSA], xdnstair, ydnstair))
X			mtmp->msleep = 1;
X		for (tryct = rn1(1,3); tryct; tryct--) {
X			x = somex(croom); y = somey(croom);
X			if (goodpos(x,y,(struct permonst *)0)) {
X				otmp = mk_tt_object(STATUE, x, y);
X				while(otmp &&
X				      resists_ston(&mons[otmp->corpsenm])) {
X					otmp->corpsenm = rndmonnum();
X					otmp->owt = weight(otmp);
X				}
X			}
X		}
X	}
X#endif
X	if(nroom > 1) {
X		troom = croom;
X		croom = &rooms[rn2(nroom-1)];
X		if(croom >= troom) croom++;
X	}
X	do {
X	    xupstair = somex(croom);
X	    yupstair = somey(croom);
X	} while(occupied(xupstair, yupstair));
X	levl[xupstair][yupstair].scrsym = UP_SYM;
X	levl[xupstair][yupstair].typ = STAIRS;
X#ifdef STRONGHOLD
X	xdnladder = ydnladder = xupladder = yupladder = 0;
X#endif
X	is_maze_lev = FALSE;
X
X#if defined(SYSV) || defined(DGUX)
X	qsort((genericptr_t) rooms, (unsigned)nroom, sizeof(struct mkroom), comp);
X#else
X	qsort((genericptr_t) rooms, nroom, sizeof(struct mkroom), comp);
X#endif
X#ifdef REINCARNATION
X	if (dlevel == rogue_level) {
X	   You("feel as though you were here in a previous lifetime.");
X	   goto skip0;
X	}
X#endif
X	makecorridors();
X	make_niches();
X
X	/* make a secret treasure vault, not connected to the rest */
X	if(nroom <= (MAXNROFROOMS/2)) if(rn2(3)) {
X
X		troom = &rooms[nroom];
X		secret = TRUE;
X		if(makerooms()) {
X			troom->rtype = VAULT;		/* treasure vault */
X			for(x = troom->lx; x <= troom->hx; x++)
X			for(y = troom->ly; y <= troom->hy; y++)
X				mkgold((long)(rnd(dlevel*100) + 50), x, y);
X			if(!rn2(3))
X				makevtele();
X		}
X	}
X
X#ifdef WIZARD
X	if(wizard && getenv("SHOPTYPE")) mkroom(SHOPBASE); else
X#endif
X#ifdef ORACLE
X	if(dlevel == oracle_level) mkroom(DELPHI);
X	/*  It is possible that we find no good place to set up Delphi.
X	 *  It is also possible to get more than one Delphi using bones levels.
X	 *  The first is not a problem; the second is a minor nuisance.
X	 */
X	else
X#endif
X	if(dlevel > 1 && dlevel < medusa_level && rn2(dlevel) < 3) mkroom(SHOPBASE);
X	else
X#ifdef THRONES
X	if(dlevel > 4 && !rn2(6)) mkroom(COURT);
X	else
X#endif
X	if(dlevel > 6 && !rn2(7)) mkroom(ZOO);
X	else
X#ifdef ALTARS
X	if(dlevel > 8 && !rn2(5)) mkroom(TEMPLE);
X	else
X#endif
X	if(dlevel > 9 && !rn2(5) && !(mons[PM_KILLER_BEE].geno & G_GENOD))
X		mkroom(BEEHIVE);
X	else
X	if(dlevel > 11 && !rn2(6)) mkroom(MORGUE);
X	else
X#ifdef ARMY
X	if(dlevel > 14 && !rn2(4) && !(mons[PM_SOLDIER].geno & G_GENOD))
X		mkroom(BARRACKS);
X	else
X#endif
X	if(dlevel > 18 && !rn2(6)) mkroom(SWAMP);
X
X#ifdef REINCARNATION
Xskip0:
X#endif
X	/* for each room: put things inside */
X	for(croom = rooms; croom->hx > 0; croom++) {
X		register boolean boxinlev = FALSE;
X
X		if(croom->rtype != OROOM) continue;
X
X		/* put a sleeping monster inside */
X		/* Note: monster may be on the stairs. This cannot be
X		   avoided: maybe the player fell through a trap door
X		   while a monster was on the stairs. Conclusion:
X		   we have to check for monsters on the stairs anyway. */
X
X		if(u.uhave_amulet || !rn2(3)) {
X		    x = somex(croom); y = somey(croom);
X		    tmonst = makemon((struct permonst *) 0, x,y);
X		    if (tmonst && tmonst->data == &mons[PM_GIANT_SPIDER])
X			(void) maketrap (x,y,WEB);
X		}
X		/* put traps and mimics inside */
X		goldseen = FALSE;
X		while(!rn2(8-(dlevel/6))) mktrap(0,0,croom);
X		if(!goldseen && !rn2(3)) mkgold(0L, somex(croom), somey(croom));
X#ifdef REINCARNATION
X		if (dlevel == rogue_level) goto skip_nonrogue;
X#endif
X#ifdef FOUNTAINS
X		if(!rn2(10)) mkfount(0,croom);
X#endif
X#ifdef SINKS
X		if(!rn2(60)) mksink(croom);
X#endif
X#ifdef ALTARS
X		if(!rn2(60)) mkaltar(croom);
X#endif
X		/* put statues inside */
X#ifdef MEDUSA
X		if(!rn2(dlevel == medusa_level ? 1 : 20)) {
X			struct obj *otmp;
X
X			if (!rn2(dlevel == medusa_level ? 2 : 50))
X				otmp = mk_tt_object(STATUE,
X						somex(croom), somey(croom));
X			else {
X				otmp = mkcorpstat(STATUE, (struct permonst *)0,
X						somex(croom), somey(croom));
X			}
X			if (dlevel == medusa_level && otmp) {
X				/* Medusa statues don't contain books */
X				otmp->spe = 0;
X				while(resists_ston(&mons[otmp->corpsenm])) {
X					otmp->corpsenm = rndmonnum();
X					otmp->owt = weight(otmp);
X				}
X			}
X		}
X#else
X		if(!rn2(20))
X				(void) mkcorpstat(STATUE, (struct permonst *)0,
X						somex(croom), somey(croom));
X#endif
X
X		/* put box/chest inside */
X		if(!rn2(20) && !boxinlev) {
X
X		    boxinlev = TRUE;
X		    (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
X				     somex(croom), somey(croom));
X		}
X
X#ifdef REINCARNATION
X	skip_nonrogue:
X#endif
X		if(!rn2(3)) {
X			(void) mkobj_at(0, somex(croom), somey(croom), TRUE);
X			tryct = 0;
X			while(!rn2(5)) {
X				if(++tryct > 100){
X					Printf("tryct overflow4\n");
X					break;
X				}
X				(void) mkobj_at(0, somex(croom), somey(croom),
X									TRUE);
X			}
X		}
X	}
X}
X
Xvoid
Xmklev()
X{
X	if(getbones()) return;
X
X	in_mklev = TRUE;
X	makelevel();
X	bound_digging();
X	in_mklev = FALSE;
X}
X
Xstatic boolean
Xbydoor(x, y)
Xregister xchar x, y;
X{
X	register boolean tmp1, tmp2;
X
X	/* break up large expression to help some compilers */
X	tmp1 = (IS_DOOR(levl[x+1][y].typ) || levl[x+1][y].typ == SDOOR ||
X		IS_DOOR(levl[x-1][y].typ) || levl[x-1][y].typ == SDOOR);
X	tmp2 = (IS_DOOR(levl[x][y+1].typ) || levl[x][y+1].typ == SDOOR ||
X		IS_DOOR(levl[x][y-1].typ) || levl[x][y-1].typ == SDOOR);
X	return(tmp1 || tmp2);
X}
X
X/* see whether it is allowable to create a door at [x,y] */
Xint
Xokdoor(x,y)
Xregister xchar x, y;
X{
X	register boolean near_door = bydoor(x, y);
X
X	return((levl[x][y].typ == HWALL || levl[x][y].typ == VWALL) &&
X	   		doorindex < DOORMAX && !near_door);
X}
X
Xvoid
Xdodoor(x,y,aroom)
Xregister int x, y;
Xregister struct mkroom *aroom;
X{
X	if(doorindex >= DOORMAX) {
X		impossible("DOORMAX exceeded?");
X		return;
X	}
X	if(!okdoor(x,y) && nxcor)
X		return;
X	dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR);
X}
X
Xstatic boolean
Xoccupied(x, y)
Xregister xchar x, y;
X{
X	return(t_at(x, y) || levl[x][y].typ == STAIRS
X#ifdef FOUNTAINS
X		|| IS_FOUNTAIN(levl[x][y].typ)
X#endif
X#ifdef THRONES
X		|| IS_THRONE(levl[x][y].typ)
X#endif
X#ifdef SINKS
X		|| IS_SINK(levl[x][y].typ)
X#endif
X#ifdef ALTARS
X		|| levl[x][y].typ == ALTAR
X#endif
X		|| is_pool(x,y)
X		);
X}
X
X/* make a trap somewhere (in croom if mazeflag = 0) */
Xvoid
Xmktrap(num, mazeflag, croom)
Xregister int num, mazeflag;
Xregister struct mkroom *croom;
X{
X	register struct trap *ttmp;
X	register int kind,nomonst,nomimic,nospider,
X#ifdef POLYSELF
X		    nopoly,
X#endif
X		    nospikes, nolevltp,
X		    nolandmine,
X		    tryct = 0;
X
X	xchar mx,my;
X
X#ifdef __GNULINT__
X	kind = nomimic = 0;
X#endif
X	if(!num || num >= TRAPNUM) {
X		nomonst = (dlevel < 4) ? 1 : 0;
X		nolevltp = (dlevel < 5) ? 1 : 0;
X		nospikes = (dlevel < 6) ? 1 : 0;
X		nospider = (dlevel < 7) ? 1 : 0;
X#ifdef POLYSELF
X		nopoly = (dlevel < 6) ? 1 : 0;
X#endif
X		nolandmine = (dlevel < 5) ? 1 : 0;
X		nomimic = (dlevel < 9 || goldseen ) ? 1 : 0;
X		if((mons[PM_SMALL_MIMIC].geno & G_GENOD) &&
X		   (mons[PM_LARGE_MIMIC].geno & G_GENOD) &&
X		   (mons[PM_GIANT_MIMIC].geno & G_GENOD))
X			nomimic = 1;
X		if(mons[PM_GIANT_SPIDER].geno & G_GENOD)
X			nospider = 1;
X
X		do {
X#ifdef REINCARNATION
X		    if (dlevel==rogue_level) {
X			switch(rn2(7)) {
X			     case 0: kind = BEAR_TRAP; break;
X			     case 1: kind = ARROW_TRAP; break;
X			     case 2: kind = DART_TRAP; break;
X			     case 3: kind = TRAPDOOR; break;
X			     case 4: kind = PIT; break;
X			     case 5: kind = SLP_GAS_TRAP; break;
X			     case 6: kind = RUST_TRAP; break;
X			}
X		    } else
X#endif
X			    kind = rnd(TRAPNUM-1);
X		    if((kind == MONST_TRAP && (nomonst && nomimic))
X			|| ((kind == WEB) && nospider)
X			|| (kind == SPIKED_PIT && nospikes)
X			|| (kind == LEVEL_TELEP && nolevltp)
X#ifdef POLYSELF
X			|| (kind == POLY_TRAP && nopoly)
X#endif
X			|| (kind == LANDMINE && nolandmine)
X			)  kind = NO_TRAP;
X		} while(kind == NO_TRAP);
X	} else kind = num;
X
X	if(kind == MONST_TRAP && !nomimic && !rn2(4) && !mazeflag) {
X		register struct monst *mtmp;
X
X		do {
X			if(++tryct > 200) return;
X			/* note: fakedoor maybe on actual door */
X			if(rn2(2)){
X			    if(rn2(2))	mx = croom->hx+1;
X			    else	mx = croom->lx-1;
X			    my = somey(croom);
X			} else {
X			    if(rn2(2))	my = croom->hy+1;
X			    else	my = croom->ly-1;
X			    mx = somex(croom);
X			}
X		} while
X			(MON_AT(mx, my));
X
X		if((mtmp = makemon(mkclass(S_MIMIC), mx, my))) {
X		    mtmp->mimic = 1;
X		    mtmp->m_ap_type = M_AP_FURNITURE;
X		    mtmp->mappearance = S_cdoor;
X		}
X		return;
X	}
X
X	do {
X		if(++tryct > 200)
X			return;
X		if(mazeflag){
X			coord mm;
X			mazexy(&mm);
X			mx = mm.x;
X			my = mm.y;
X		} else {
X			mx = somex(croom);
X			my = somey(croom);
X		}
X	} while(occupied(mx, my));
X
X	ttmp = maketrap(mx, my, kind);
X	if (kind == WEB) (void) makemon(&mons[PM_GIANT_SPIDER], mx, my);
X	if(mazeflag && !rn2(10) && ttmp->ttyp < MONST_TRAP)
X		ttmp->tseen = 1;
X}
X
X#ifdef FOUNTAINS
Xvoid
Xmkfount(mazeflag,croom)
Xregister struct mkroom *croom;
Xregister int mazeflag;
X{
X	register xchar mx,my;
X	register int tryct = 0;
X
X	do {
X	    if(++tryct > 200) return;
X	    if(mazeflag) {
X		 coord mm;
X		 mazexy(&mm);
X		 mx = mm.x;
X		 my = mm.y;
X	    } else {
X		 mx = somex(croom);
X		 my = somey(croom);
X	    }
X	} while(occupied(mx, my) || bydoor(mx, my));
X
X	/* Put a fountain at mx, my */
X	levl[mx][my].typ = FOUNTAIN;
X	levl[mx][my].scrsym = FOUNTAIN_SYM;
X
X	fountsound++;
X}
X#endif /* FOUNTAINS /**/
X
X#ifdef SINKS
Xstatic void
Xmksink(croom)
Xregister struct mkroom *croom;
X{
X	register xchar mx,my;
X	register int tryct = 0;
X
X	do {
X	    if(++tryct > 200) return;
X	    mx = somex(croom);
X	    my = somey(croom);
X	} while(occupied(mx, my) || bydoor(mx, my));
X
X	/* Put a sink at mx, my */
X	levl[mx][my].typ = SINK;
X	levl[mx][my].scrsym = SINK_SYM;
X
X	sinksound++;
X}
X#endif /* SINKS /**/
X
X
X#ifdef ALTARS
Xstatic void
Xmkaltar(croom)
Xregister struct mkroom *croom;
X{
X	register xchar mx,my;
X	register int tryct = 0;
X
X	if(croom->rtype != OROOM) return;
X
X	do {
X	    if(++tryct > 200) return;
X	    mx = somex(croom);
X	    my = somey(croom);
X	} while(occupied(mx, my) || bydoor(mx, my));
X
X	/* Put an altar at mx, my */
X	levl[mx][my].typ = ALTAR;
X	levl[mx][my].scrsym = ALTAR_SYM;
X	/* 0 - A_CHAOS, 1 - A_NEUTRAL, 2 - A_LAW */
X	levl[mx][my].altarmask = rn2((int)A_LAW+1);
X}
X#endif /* ALTARS /**/
END_OF_FILE
if test 28964 -ne `wc -c <'src/mklev.c'`; then
    echo shar: \"'src/mklev.c'\" unpacked with wrong size!
fi
# end of 'src/mklev.c'
fi
if test -f 'src/monmove.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/monmove.c'\"
else
echo shar: Extracting \"'src/monmove.c'\" \(24074 characters\)
sed "s/^X//" >'src/monmove.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)monmove.c	3.0	89/11/21
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#ifndef LINT	/* comment line for pre-compiled headers */
X# ifndef __STDC__	/* comment line for pre-compiled headers */
X#define TRAP_H	/* comment line for pre-compiled headers */
X/* block some unused #defines to avoid overloading some cpp's */
X# endif	/* comment line for pre-compiled headers */
X#endif	/* comment line for pre-compiled headers */
X
X#include "hack.h"
X#include "mfndpos.h"
X#ifdef NAMED_ITEMS
X#  include "artifact.h"
X#endif
X
X#ifdef OVL1
Xstatic void FDECL(distfleeck,(struct monst *,int *,int *,int *));
X#endif /* OVL1 */
X
X#ifdef OVL0
X# ifdef POLYSELF
Xstatic boolean FDECL(itsstuck,(struct monst *));
X# endif
X#endif /* OVL0 */
X
X#ifdef OVLB
X
Xboolean /* TRUE : mtmp died */
Xmb_trapped(mtmp)
Xregister struct monst *mtmp;
X{
X	if (flags.verbose) {
X	    if (cansee(mtmp->mx, mtmp->my))
X	       pline("KABOOM!!  You see a door explode.");
X	    else if (flags.soundok)
X               You("hear a distant explosion.");
X	}
X	mtmp->mstun = 1;
X	mtmp->mhp -= rnd(15);
X	if(mtmp->mhp <= 0) {
X		mondied(mtmp);
X		return(TRUE);
X	}
X	return(FALSE);
X}
X
Xboolean  
Xmdig_tunnel(mtmp)  /* FALSE: monster died */
Xregister struct monst *mtmp;
X{
X	register struct rm *here;
X	register int pile = rnd(12);
X	boolean canseeit = cansee(mtmp->mx, mtmp->my);
X	here = &levl[mtmp->mx][mtmp->my];
X
X	if (here->typ == SDOOR)
X		here->typ = DOOR;
X	if(IS_ROCK(here->typ)) {
X	    /* Just ate something. */
X	    if(IS_WALL(here->typ)) {
X		if (!(here->diggable & W_NONDIGGABLE)) {
X			if(flags.soundok && flags.verbose && !rn2(5))
X		       		You("hear the sound of crashing rock.");
X			if(!is_maze_lev) {
X		  		here->typ = DOOR;
X		  		here->doormask = D_NODOOR;
X			}
X			else
X		  		here->typ = ROOM;
X		}
X	    } else	
X	    	here->typ = CORR;
X	    mnewsym(mtmp->mx, mtmp->my);
X	} else 		/* Eats away door if present & closed or locked */
X		if(closed_door(mtmp->mx, mtmp->my)) {
X			if(here->doormask & D_TRAPPED) {
X		    		here->doormask = D_NODOOR;
X		    		if(mb_trapped(mtmp)) return(FALSE);
X			} else {
X		    		if(!rn2(3) && flags.verbose)
X				    /* not too often.. */
X		        		You("feel an unexpected draft of air.");
X		    		here->doormask = D_BROKEN;
X			}
X		    	mnewsym(mtmp->mx, mtmp->my);
X	    	} else 
X		    /* it doesn't leave rocks if it didn't dig */
X			return TRUE; 
X
X	/* Left behind a pile? */
X	if(pile < 5) {
X	    if(pile == 1)
X		(void) mksobj_at(BOULDER, mtmp->mx, mtmp->my);
X	    else
X		(void) mksobj_at(ROCK, mtmp->mx, mtmp->my);
X	}
X	here->seen = TRUE; /* required for newsym and mnewsym to work */
X	if(canseeit && mtmp->minvis && !See_invisible)
X	    newsym(mtmp->mx,mtmp->my);
X	else
X	    mnewsym(mtmp->mx,mtmp->my);
X	if (!canseeit)
X		here->seen = FALSE;
X	return(TRUE);
X}
X
X#endif /* OVLB */
X#ifdef OVL1
X
Xint
Xdochugw(mtmp)
X	register struct monst *mtmp;
X{
X	register int x = mtmp->mx;
X	register int y = mtmp->my;
X	register int rd = dochug(mtmp);
X	register int dd;
X
X	if(!rd && !mtmp->mpeaceful &&
X			(dd = dist(mtmp->mx,mtmp->my)) < dist(x,y) &&
X			dd < 100 && !canseemon(mtmp)) {
X#ifdef NAMED_ITEMS
X	    /* Note: this assumes we only want to warn against the monster which
X	     * the weapon does extra damage to, as there is no "monster which
X	     * the weapon warns against" field.
X	     */
X		if(spec_ability(uwep,SPFX_WARN) && spec_dbon(uwep,mtmp->data,1))
X			warnlevel = 100;
X		else
X#endif
X		if (Warning && mtmp->m_lev > warnlevel)
X			warnlevel = mtmp->m_lev;
X	}
X	return(rd);
X}
X
X#endif /* OVL1 */
X#ifdef OVL2
X
Xboolean
Xonscary(x, y, mtmp)
Xint x, y;
Xstruct monst *mtmp;
X{
X	/* Note: minotaurs must be immune to scare monster to avoid abuse
X	 * from creating them and taking their wands, then polymorphing 60
X	 * or so wands to get wishing...
X	 */
X	if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee ||
X			mtmp->data->mlet == S_HUMAN || mtmp->mpeaceful ||
X			mtmp->data == &mons[PM_MINOTAUR])
X		return(FALSE);
X	return(
X#ifdef ELBERETH
X		   sengr_at("Elbereth", x, y) ||
X#endif
X		    sobj_at(SCR_SCARE_MONSTER, x, y) != (struct obj *)0);
X}
X
X#endif /* OVL2 */
X#ifdef OVL1
X
Xstatic void
Xdistfleeck(mtmp,inrange,nearby,scared)
Xregister struct monst *mtmp;
Xint *inrange, *nearby, *scared;
X{
X	int seescaryx, seescaryy;
X
X	*inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=
X							(BOLT_LIM * BOLT_LIM));
X	*nearby = monnear(mtmp, mtmp->mux, mtmp->muy);
X
X	/* Note: if your image is displaced, the monster sees the Elbereth
X	 * at your displaced position, thus never attacking your displaced
X	 * position, but possibly attacking you by accident.  If you are
X	 * invisible, it sees the Elbereth at your real position, thus never
X	 * running into you by accident but possibly attacking the spot
X	 * where it guesses you are.
X	 */
X	if (Invis && !perceives(mtmp->data)) {
X		seescaryx = mtmp->mux;
X		seescaryy = mtmp->muy;
X	} else {
X		seescaryx = u.ux;
X		seescaryy = u.uy;
X	}
X	*scared = (*nearby && onscary(seescaryx, seescaryy, mtmp));
X
X	if(*scared && !mtmp->mflee) {
X#ifdef POLYSELF
X		if (!sticks(uasmon))
X#endif
X			unstuck(mtmp);	/* monster lets go when fleeing */
X		mtmp->mflee = 1;
X#ifdef STUPID
X		if (rn2(7))
X		    mtmp->mfleetim = rnd(10);
X		else
X		    mtmp->mfleetim = rnd(100);
X#else
X		mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100));
X#endif
X	}
X
X}
X
X/* returns 1 if monster died moving, 0 otherwise */
Xint
Xdochug(mtmp)
Xregister struct monst *mtmp;
X{
X	register struct permonst *mdat = mtmp->data;
X	register int tmp=0;
X	int inrange, nearby, scared;
X
X/*	Pre-movement adjustments	*/
X
X	if(mtmp->cham && !rn2(6))	/* polymorph chameleons */
X	    (void) newcham(mtmp, (struct permonst *)0);
X
X	/* regenerate monsters */
X	if((!(moves%20) || regenerates(mdat)) && mtmp->mhp < mtmp->mhpmax)
X		mtmp->mhp++;
X	if(mtmp->mspec_used) mtmp->mspec_used--;
X
X	/* polymorph lycanthropes */
X	were_change(mtmp);
X
X	if(!mtmp->mcanmove) {
X		if (Hallucination) pmon(mtmp);
X		return(0);	/* frozen monsters don't do anything */
X	}
X
X	if(mtmp->msleep)	/* there is a chance we will wake it */
X		if(!disturb(mtmp)) return(0);
X
X	/* not frozen or sleeping: wipe out texts written in the dust */
X	wipe_engr_at(mtmp->mx, mtmp->my, 1);
X
X	/* confused monsters get unconfused with small probability */
X	if(mtmp->mconf && !rn2(50)) mtmp->mconf = 0;
X
X	/* stunned monsters get un-stunned with larger probability */
X	if(mtmp->mstun && !rn2(10)) mtmp->mstun = 0;
X
X	/* some monsters teleport */
X	if(mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz) {
X		rloc(mtmp);
X		return(0);
X	}
X	if(mdat->mmove < rnd(6)) return(0);
X
X	/* fleeing monsters might regain courage */
X	if(mtmp->mflee && !mtmp->mfleetim
X	   && mtmp->mhp == mtmp->mhpmax && !rn2(25)) mtmp->mflee = 0;
X
X	set_apparxy(mtmp);
X	/* Must be done after you move and before the monster does.  The
X	 * set_apparxy() call in m_move() doesn't suffice since the variables
X	 * inrange, etc... all depend on stuff set by set_apparxy().
X	 */
X
X	/* The Wizard's prime directive */
X	/* may teleport, so do it before inrange is set */
X	if(mtmp->iswiz)
X		(void) wiz_get_amulet(mtmp);
X
X	/* check distance and scariness of attacks */
X	distfleeck(mtmp,&inrange,&nearby,&scared);
X
X#ifdef INFERNO		/* Demonic Blackmail! */
X	if(nearby && mdat->msound == MS_BRIBE &&
X	   mtmp->mpeaceful && !mtmp->mtame) {
X		if (mtmp->mux != u.ux || mtmp->muy != u.uy) {
X			pline("%s whispers something to thin air.",
X			    cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "It");
X# ifdef POLYSELF
X			if (is_demon(uasmon)) rloc(mtmp);
X			  /* "Good hunting, brother" */
X			else {
X# endif
X			    mtmp->minvis = 0;
X			    /* Why?  For the same reason in real demon talk */
X			    pline("%s gets angry.", Xmonnam(mtmp));
X			    mtmp->mpeaceful = 0;
X			    /* since no way is an image going to pay it off */
X# ifdef POLYSELF
X			}
X# endif
X		} else if(demon_talk(mtmp)) return(1);	/* you paid it off */
X	}
X#endif
X
X/*	Now the actual movement phase	*/
X
X	if(!nearby || mtmp->mflee || scared ||
X	   mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) ||
X	   (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) ||
X	   (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) ||
X	   (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) {
X
X		tmp = m_move(mtmp, 0);
X		distfleeck(mtmp,&inrange,&nearby,&scared);	/* recalc */
X
X		switch (tmp) {
X
X		    case 0:	/* no movement, but it can still attack you */
X		    case 3:	/* absolutely no movement */
X				/* for pets, case 0 and 3 are equivalent */
X 			/* During hallucination, monster appearance should
X 			 * still change - even if it doesn't move.
X  			 */
X 			if(Hallucination) pmon(mtmp);
X 			break;
X 		    case 1:	/* monster moved */
X			/* Maybe it stepped on a trap and fell asleep... */
X			if(mtmp->msleep || !mtmp->mcanmove) return(0);
X 			if(!nearby && ranged_attk(mdat)) break;
X 			else if(mdat->mmove <= 12) return(0);
X 			break;
X 		    case 2:	/* monster died */
X 			return(1);
X 		}
X	}
X
X/*	Now, attack the player if possible - one attack set per monst	*/
X
X	if(inrange && !noattacks(mdat) &&
X	   !mtmp->mpeaceful && !mtmp->mtame && u.uhp > 0 && !scared && tmp != 3)
X	    if(mattacku(mtmp)) return(1); /* monster died (e.g. exploded) */
X
X#ifdef WORM
X	if(mtmp->wormno && !mtmp->mtame) wormhit(mtmp);
X#endif
X
X	/* extra emotional attack for vile monsters */
X	if(inrange && mtmp->data->msound == MS_CUSS &&
X	   !mtmp->minvis && !mtmp->mpeaceful && !rn2(5))
X	    cuss(mtmp);
X
X	/* extra movement for fast monsters */
X	if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp, 1);
X	return(tmp == 2);
X}
X
Xstatic const char NEARDATA practical[] = { WEAPON_SYM, GEM_SYM, FOOD_SYM, 0 };
Xstatic const char NEARDATA magical[] = {
X	AMULET_SYM, POTION_SYM, SCROLL_SYM, WAND_SYM, RING_SYM,
X#ifdef SPELLS
X	SPBOOK_SYM,
X#endif
X	0 };
Xstatic const char NEARDATA indigestion[] = { BALL_SYM, ROCK_SYM, 0 };
X
X#endif /* OVL1 */
X#ifdef OVL0
X
X#ifdef POLYSELF
Xstatic boolean
Xitsstuck(mtmp)
Xregister struct monst *mtmp;
X{
X	if (sticks(uasmon) && mtmp==u.ustuck && !u.uswallow) {
X		kludge("%s cannot escape from you!", Monnam(mtmp));
X		return(TRUE);
X	}
X	return(FALSE);
X}
X#endif
X
Xint
Xm_move(mtmp, after)
Xregister struct monst *mtmp;
Xregister int after;
X{
X	register struct monst *mtmp2;
X	register int nx,ny,omx,omy,appr,nearer,cnt,i,j;
X	xchar gx,gy,nix,niy,chcnt;
X	schar chi;
X	boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0;
X	boolean likerock=0, can_tunnel=0;
X	boolean can_open=0, can_unlock=0, doorbuster=0;
X	struct permonst *ptr = mtmp->data;
X	schar mmoved = 0;	/* not strictly nec.: chi >= 0 will do */
X	coord poss[9];
X	long info[9];
X	long flag;
X
X	if(mtmp->mtrapped) {
X	    i = mintrap(mtmp);
X	    if(i == 2) return(2);	/* it died */
X	    if(i == 1) return(0);	/* still in trap, so didn't move */
X	}
X	if(mtmp->mhide &&
X	   (OBJ_AT(mtmp->mx, mtmp->my) || levl[mtmp->mx][mtmp->my].gmask) &&
X	   rn2(10))
X	    return(0);		/* do not leave hiding place */
X	if(mtmp->meating) {
X	    mtmp->meating--;
X	    return(3);			/* still eating */
X	}
X
X	set_apparxy(mtmp);
X	/* where does mtmp think you are? */
X	/* Not necessary if m_move called from this file, but necessary in
X	 * other calls of m_move (ex. leprechauns dodging)
X	 */
X	can_tunnel = tunnels(ptr) &&
X#ifdef REINCARNATION
X		     dlevel != rogue_level &&
X#endif
X		     (!needspick(ptr) || m_carrying(mtmp, PICK_AXE));
X	can_open = !(nohands(ptr) || verysmall(ptr));
X	can_unlock = ((can_open && m_carrying(mtmp, SKELETON_KEY)) || mtmp->iswiz);
X	doorbuster = is_giant(ptr);
X#ifdef WORM
X	if(mtmp->wormno) goto not_special;
X#endif
X	/* my dog gets special treatment */
X	if(mtmp->mtame) {
X	    mmoved = dog_move(mtmp, after);
X	    goto postmov;
X	}
X
X	/* likewise for shopkeeper */
X	if(mtmp->isshk) {
X	    mmoved = shk_move(mtmp);
X	    if(mmoved == -2) return(2);
X	    if(mmoved >= 0) goto postmov;
X	    mmoved = 0;		/* follow player outside shop */
X	}
X
X	/* and for the guard */
X	if(mtmp->isgd) {
X	    mmoved = gd_move(mtmp);
X	    if(mmoved == -2) return(2);
X	    if(mmoved >= 0) goto postmov;
X	    mmoved = 0;
X	}
X
X	/* and the wiz already got special treatment */
X	if(mtmp->iswiz) {
X	    mmoved = 0;
X	    goto postmov;
X	}
X#if defined(ALTARS) && defined(THEOLOGY)
X	/* and for the priest */
X	if(mtmp->ispriest) {
X	    mmoved = pri_move(mtmp);
X	    if(mmoved == -2) return(2);
X	    if(mmoved >= 0) goto postmov;
X	    mmoved = 0;
X	}
X#endif
X#ifdef MAIL
X	if(ptr == &mons[PM_MAIL_DAEMON]) {
X	    if(flags.soundok && canseemon(mtmp))
X		verbalize("I'm late!");
X	    mongone(mtmp);
X	    return(2);	    
X	}
X#endif
X	/* teleport if that lies in our nature */
X	if(ptr == &mons[PM_TENGU] && !rn2(5)) {
X	    if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2))
X		rloc(mtmp);
X	    else
X		mnexto(mtmp);
X	    mmoved = 1;
X	    goto postmov;
X	}
X#ifdef WORM
Xnot_special:
X#endif
X	if(!mtmp->mflee && u.uswallow && u.ustuck != mtmp) return(1);
X	appr = 1;
X	if(mtmp->mflee) appr = -1;
X	if(mtmp->mconf || (Invis && !perceives(ptr)) ||  !mtmp->mcansee ||
X#ifdef POLYSELF
X	   (u.usym == S_MIMIC_DEF) || u.uundetected ||
X#endif
X	   (mtmp->mpeaceful && !mtmp->isshk) ||	/* allow shks to follow */
X	   ((ptr->mlet == S_STALKER || ptr->mlet == S_BAT ||
X	     ptr->mlet == S_YLIGHT) && !rn2(3)))
X	    appr = 0;
X	omx = mtmp->mx;
X	omy = mtmp->my;
X	gx = mtmp->mux;
X	gy = mtmp->muy;
X	if(ptr == &mons[PM_LEPRECHAUN] && appr == 1 && mtmp->mgold > u.ugold)
X	    appr = -1;
X
X	if(can_track(ptr)) {
X	    register coord *cp;
X	    schar mroom;
X
X	    mroom = inroom(omx,omy);
X	    if(mroom < 0 || mroom != inroom(u.ux,u.uy)){
X		cp = gettrack(omx,omy);
X		if(cp){
X		    gx = cp->x;
X		    gy = cp->y;
X		}
X	    }
X	}
X
X#ifdef REINCARNATION
X	if (dlevel != rogue_level)
X#endif
X	{
X		register int pctload = (curr_mon_load(mtmp) * 100) /
X			max_mon_load(mtmp);
X
X		/* look for gold or jewels nearby */
X		likegold = (likes_gold(ptr) && pctload < 95);
X		likegems = (likes_gems(ptr) && pctload < 85);
X		likeobjs = (likes_objs(ptr) && pctload < 75);
X		likemagic = (likes_magic(ptr) && pctload < 85);
X		likerock = (throws_rocks(ptr) && pctload < 50);
X		conceals = hides_under(ptr);
X	}
X
X#define SQSRCHRADIUS	5
X#define	SRCHRADIUS	(SQSRCHRADIUS*SQSRCHRADIUS)
X
X      { xchar mind = SRCHRADIUS;		/* not too far away */
X	register int dd;
X
X	/* cut down the search radius if it thinks character is closer. */
X	if(dist2(mtmp->mux, mtmp->muy, omx, omy) < SRCHRADIUS &&
X	    !mtmp->mtame && !mtmp->mpeaceful)	 mind /= 2;
X
X	if(likegold){
X	    register struct gold *gold;
X
X	    for(gold = fgold; gold; gold = gold->ngold)
X		if((dd = dist2(omx,omy,gold->gx,gold->gy)) < mind){
X		    mind = dd;
X		    gx = gold->gx;
X		    gy = gold->gy;
X		}
X	}
X	if((likegems || likeobjs || likemagic || likerock || conceals)
X	      && (!in_shop(omx, omy) || (!rn2(25) && !mtmp->isshk))) {
X	    register struct obj *otmp;
X	    register int xx, yy;
X
X	    for(xx = omx-SQSRCHRADIUS; xx <= omx+SQSRCHRADIUS; xx++) {
X		for(yy = omy-SQSRCHRADIUS; yy <= omy+SQSRCHRADIUS; yy++) {
X		    if(!isok(xx, yy)) continue;
X		    if((dd = dist2(omx,omy,xx, yy)) >= mind) continue;
X		    for(otmp = level.objects[xx][yy]; otmp; otmp = otmp->nexthere)
X		      if((likeobjs && index(practical, otmp->olet)) ||
X			 (likemagic && index(magical, otmp->olet)) ||
X			 (likerock && otmp->otyp == BOULDER) ||
X			 (likegems && otmp->olet == GEM_SYM &&
X			  otmp->otyp < LAST_GEM + 6) ||
X			 (conceals && !cansee(otmp->ox,otmp->oy)) ||
X			 (ptr == &mons[PM_GELATINOUS_CUBE] &&
X			  !index(indigestion, otmp->olet))
X			 ) {
X			  if(can_carry(mtmp,otmp))
X			    if(ptr->mlet != S_UNICORN ||
X			       objects[otmp->otyp].g_val != 0){
X				mind = dd;
X				gx = otmp->ox;
X				gy = otmp->oy;
X				break;
X			    }
X		      }
X		}
X	    }
X	}
X	if(mind < SRCHRADIUS && appr == -1) {
X	    if(dist2(omx,omy,mtmp->mux,mtmp->muy) < 10) {
X		gx = mtmp->mux;
X		gy = mtmp->muy;
X	    } else
X		appr = 1;
X	}
X      }
X	nix = omx;
X	niy = omy;
X	flag = ALLOW_TRAPS;
X	if (mtmp->mpeaceful) flag |= (ALLOW_SANCT | ALLOW_SSM);
X	else flag |= ALLOW_U;
X	if (ptr->mlet == S_UNICORN) flag |= NOTONL;
X	if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK);
X	if (can_tunnel) flag |= ALLOW_DIG;
X	if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM;
X	if (is_undead(ptr)) flag |= NOGARLIC;
X	if (throws_rocks(ptr)) flag |= ALLOW_ROCK;
X	if (can_open) flag |= OPENDOOR;
X	if (can_unlock) flag |= UNLOCKDOOR;
X	if (doorbuster) flag |= BUSTDOOR;
X	cnt = mfndpos(mtmp, poss, info, flag);
X	chcnt = 0;
X	chi = -1;
X
X	for(i=0; i < cnt; i++) {
X	    nx = poss[i].x;
X	    ny = poss[i].y;
X
X	    if (appr != 0) for(j=0; j < MTSZ && j < cnt-1; j++)
X		if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
X		    if(rn2(4*(cnt-j))) goto nxti;
X
X	    nearer = (dist2(nx,ny,gx,gy) < dist2(nix,niy,gx,gy));
X
X	    if((appr == 1 && nearer) || (appr == -1 && !nearer) ||
X		   	(!appr && !rn2(++chcnt)) || !mmoved) {
X		nix = nx;
X		niy = ny;
X		chi = i;
X		mmoved = 1;
X	    }
X	nxti:	;
X	}
X
X	if(mmoved) {
X#ifdef POLYSELF
X	    if (mmoved==1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp))
X		return(3);
X#endif
X	    if((info[chi] & ALLOW_U) || (nix == u.ux && niy == u.uy)) {
X		mtmp->mux = u.ux;
X		mtmp->muy = u.uy;
X		return(0);
X	    }
X	    /* The monster may attack another based on 1 of 2 conditions:
X	     * 1 - He may be under the "conflict" influence.
X	     * 2 - He may mistake the monster for your (displaced) image.
X	     * Pets get taken care of above and shouldn't reach this code.
X	     */
X	    if((info[chi] & ALLOW_M) ||
X		   (nix == mtmp->mux && niy == mtmp->muy)) {
X		int stat;
X		mtmp2 = m_at(nix,niy);
X		if((stat = mattackm(mtmp, mtmp2)) == 1 && rn2(4) &&
X			mtmp2->mlstmv != moves && mattackm(mtmp2, mtmp) == 2)
X		    return(2);
X		if(stat == -1) return(2);
X		return(3);
X	    }
X#ifdef WORM
X	    /* The square now has a worm segment and must keep its MON_AT() state */
X	    if (!mtmp->wormno)
X#endif
X		    remove_monster(omx, omy);
X	    place_monster(mtmp, nix, niy);
X	    for(j = MTSZ-1; j > 0; j--)
X		mtmp->mtrack[j] = mtmp->mtrack[j-1];
X	    mtmp->mtrack[0].x = omx;
X	    mtmp->mtrack[0].y = omy;
X#ifdef WORM
X	    if(mtmp->wormno) worm_move(mtmp);
X#endif
X	} else {
X	    if(ptr->mlet == S_UNICORN && rn2(2)) {
X		rloc(mtmp);
X		return(1);
X	    }
X#ifdef WORM
X	    if(mtmp->wormno) worm_nomove(mtmp);
X#endif
X	}
Xpostmov:
X	if(mmoved == 1) {
X	    boolean canseeit = cansee(mtmp->mx, mtmp->my);
X	    boolean abstain = (mtmp->mpeaceful && !mtmp->mtame);
X
X	    if(mintrap(mtmp) == 2) return(2);	/* he died */
X
X	    /* open a door, or crash through it, if you can */
X	    if(IS_DOOR(levl[mtmp->mx][mtmp->my].typ)
X		    && !passes_walls(ptr) /* doesn't need to open doors */
X		    && !can_tunnel /* taken care of below */
X		  ) {
X		struct rm *here = &levl[mtmp->mx][mtmp->my];
X		boolean btrapped = (here->doormask & D_TRAPPED);
X
X		if(here->doormask & (D_LOCKED|D_CLOSED) && amorphous(ptr)) {
X		    if (flags.verbose && canseeit)
X			pline("%s %ss under the door.", Monnam(mtmp),
X			      ptr == &mons[PM_FOG_CLOUD] ? "flow" : "ooze");
X		} else if(here->doormask & D_LOCKED && can_unlock) {
X		    if(btrapped) {
X			here->doormask = D_NODOOR;
X			mnewsym(mtmp->mx, mtmp->my);
X			if (canseeit) prl(mtmp->mx,mtmp->my);
X			if(mb_trapped(mtmp)) return(2);
X		    } else {
X			if (flags.verbose) {
X			    if (canseeit)
X			      You("see a door being unlocked and opened.");
X			    else if (flags.soundok)
X			       You("hear a door being unlocked and opened.");
X		        }
X		        here->doormask = D_ISOPEN;
X			mnewsym(mtmp->mx, mtmp->my);
X			if (canseeit) prl(mtmp->mx,mtmp->my);
X		    }
X		} else if (here->doormask == D_CLOSED && can_open) {
X		    if(btrapped) {
X			here->doormask = D_NODOOR;
X			mnewsym(mtmp->mx, mtmp->my);
X			if (canseeit) prl(mtmp->mx,mtmp->my);
X			if(mb_trapped(mtmp)) return(2);
X		    } else {
X		        if (flags.verbose) {
X			    if (canseeit)
X			         You("see a door being opened.");
X			    else if (flags.soundok)
X			         You("hear the sound of a door opening.");
X		        }
X		        here->doormask = D_ISOPEN;
X			mnewsym(mtmp->mx, mtmp->my);
X			if (canseeit) prl(mtmp->mx,mtmp->my);
X		    }
X		} else if (here->doormask & (D_LOCKED|D_CLOSED)) {
X		       /* mfndpos guarantees this must be a doorbuster */
X		    if(btrapped) {
X			here->doormask = D_NODOOR;
X			mnewsym(mtmp->mx, mtmp->my);
X			if (canseeit) prl(mtmp->mx,mtmp->my);
X			if(mb_trapped(mtmp)) return(2);
X		    } else {
X		        if (flags.verbose) {
X			    if (canseeit)
X			        You("see a door crash open.");
X			    else if (flags.soundok)
X			        You("hear the sound of a door crashing open.");
X		        }
X		        if (here->doormask & D_LOCKED && !rn2(2))
X			        here->doormask = D_NODOOR;
X		        else here->doormask = D_BROKEN;
X			mnewsym(mtmp->mx, mtmp->my);
X			if (canseeit) prl(mtmp->mx,mtmp->my);
X		    }
X		}
X	      }
X	    /* Maybe a rock mole just ate something? */
X	    if(can_tunnel) if(!mdig_tunnel(mtmp)) return(2); /* died? */
X
X	    if(levl[mtmp->mx][mtmp->my].gmask == TRUE) {
X		/* Maybe a rock mole just ate some gold */
X		if(metallivorous(ptr)) meatgold(mtmp);
X		if(likegold && (!abstain || !rn2(10))) mpickgold(mtmp);
X	    }
X	    if(OBJ_AT(mtmp->mx, mtmp->my)) {
X		/* Maybe a rock mole just ate some metal object */
X		if(metallivorous(ptr)) meatgold(mtmp);
X		/* Maybe a cube ate just about anything */
X		if(ptr == &mons[PM_GELATINOUS_CUBE]) meatobj(mtmp);
X
X		if ((!abstain || !rn2(10)) 
X			&& (!in_shop(mtmp->mx, mtmp->my) || !rn2(25))) {
X		    if(likeobjs) mpickstuff(mtmp, practical);
X		    if(likemagic) mpickstuff(mtmp, magical);
X		    if(likerock || likegems) mpickgems(mtmp);
X		}
X	    }
X	    if(mtmp->mhide) mtmp->mundetected = (OBJ_AT(mtmp->mx, mtmp->my)
X					|| levl[mtmp->mx][mtmp->my].gmask);
X
X	    /* set also in domove(), hack.c */
X	    if(u.uswallow && mtmp == u.ustuck) {
X		u.ux = mtmp->mx;
X		u.uy = mtmp->my;
X	        if(mtmp->mx != mtmp->mdx || mtmp->my != mtmp->mdy) {
X		    swallowed(0);
X		    newsym(mtmp->mdx,mtmp->mdy);
X		    mtmp->mdx = mtmp->mx;
X		    mtmp->mdy = mtmp->my;
X		}
X	    }
X	    pmon(mtmp);
X	}
X	return(mmoved);
X}
X
X#endif /* OVL0 */
X#ifdef OVL2
X
Xboolean
Xclosed_door(x, y)
Xregister int x, y;
X{
X	return(IS_DOOR(levl[x][y].typ) &&
X			(levl[x][y].doormask & (D_LOCKED | D_CLOSED)));
X}
X
Xboolean
Xaccessible(x, y)
Xregister int x, y;
X{
X	return(ACCESSIBLE(levl[x][y].typ) && !closed_door(x, y));
X}
X
X#endif /* OVL2 */
X#ifdef OVL1
X
Xvoid
Xset_apparxy(mtmp)		/* where does mtmp think you are standing? */
X	register struct monst *mtmp;
X{
X#define notseen (Invis && !perceives(mtmp->data))
X/*	add cases as required.  eg. Displacement ... */
X	register int disp = (notseen ? 1 : Displaced ? 2 : 0);
X
X/* 	without something like the following, invis. and displ. are too */
X/*	powerful. */
X	register boolean gotu =
X		(notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE);
X
X/*	Monsters which know where you are don't suddenly forget, if you
X	didn't move away. */
X	if (mtmp->mux==u.ux && mtmp->muy==u.uy) gotu = 1;
X
X/* 	your dog follows your smell */
X	if(!disp || mtmp->mtame || gotu ||
X/*	If invisible but not displaced, staying around gets you 'discovered' */
X	    (!Displaced && u.dx == 0 && u.dy == 0)) {
X		mtmp->mux = u.ux;
X		mtmp->muy = u.uy;
X	}
X	else do {
X		mtmp->mux = u.ux - disp + rn2(2*disp+1);
X		mtmp->muy = u.uy - disp + rn2(2*disp+1);
X	} while((mtmp->mux != u.ux || mtmp->muy != u.uy) &&
X	        ( (!passes_walls(mtmp->data) &&
X		      (!ACCESSIBLE(levl[mtmp->mux][mtmp->muy].typ) ||
X		       (closed_door(mtmp->mux, mtmp->muy) &&
X			!amorphous(mtmp->data)
X		       )
X		      )
X		  ) ||
X		  (disp==1 && mtmp->mux == mtmp->mx && mtmp->muy == mtmp->my)
X	        )
X	       );
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
X#ifdef STUPID_CPP	/* otherwise these functions are macros in rm.h */
X/*
X * Functions for encapsulation of level.monsters references.
X */
Xboolean
XMON_AT(x, y)
Xint x, y;
X{
X    return(level.monsters[x][y] != (struct monst *)0);
X}
X
Xvoid place_monster(mtmp, x, y)
Xregister struct monst *mtmp;
Xint x, y;
X{
X    level.monsters[x][y] = mtmp;
X    mtmp->mx = x;
X    mtmp->my = y;
X}
X
Xvoid place_worm_seg(mtmp, x, y)
Xregister struct monst *mtmp;
Xint x, y;
X{
X    level.monsters[x][y] = mtmp;
X}
X
Xvoid remove_monster(x, y)
Xint x, y;
X{
X    level.monsters[x][y] = (struct monst *)0;
X}
X
Xstruct monst *m_at(x, y)
Xint x, y;
X{
X    return(level.monsters[x][y]);
X}
X#endif	/* STUPID_CPP */
X
X#endif /* OVLB */
END_OF_FILE
if test 24074 -ne `wc -c <'src/monmove.c'`; then
    echo shar: \"'src/monmove.c'\" unpacked with wrong size!
fi
# end of 'src/monmove.c'
fi
if test -f 'src/rip.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/rip.c'\"
else
echo shar: Extracting \"'src/rip.c'\" \(2319 characters\)
sed "s/^X//" >'src/rip.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)rip.c	3.0	88/04/27
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include "hack.h"
X
Xstatic void FDECL(center,(int,char *));
X
Xstatic const char *rip_txt[] = {
X"                       ----------",
X"                      /          \\",
X"                     /    REST    \\",
X"                    /      IN      \\",
X"                   /     PEACE      \\",
X"                  /                  \\",
X"                  |                  |",
X"                  |                  |",
X"                  |                  |",
X"                  |                  |",
X"                  |                  |",
X"                  |       1001       |",
X"                 *|     *  *  *      | *",
X"        _________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______\n",
X0
X};
X
Xchar **rip;
X
Xstatic void
Xcenter(line, text)
Xint line;
Xchar *text;
X{
X	register char *ip,*op;
X	ip = text;
X	op = &rip[line][28 - ((strlen(text)+1)>>1)];
X	while(*ip) *op++ = *ip++;
X}
X
Xvoid
Xoutrip(){
X	register char **dp;
X	register char *dpx;
X	char buf[BUFSZ];
X	register int x, y;
X	int killed_by_line = 0;
X
X	rip = dp = (char **) alloc(sizeof(rip_txt));
X	if (!dp) return;
X	for (x = 0; rip_txt[x]; x++) {
X		dp[x] = (char *) alloc((unsigned int)(strlen(rip_txt[x]) + 1));
X		if (!dp[x]) return;
X		Strcpy(dp[x], rip_txt[x]);
X	}
X	dp[x] = (char *)0;
X
X	cls();
X	Sprintf(buf, "%s", plname);
X	buf[16] = 0;
X	center(6, buf);
X	Sprintf(buf, "%ld Au", u.ugold);
X	center(7, buf);
X	if (killer_format != NO_KILLER_PREFIX) {
X		killed_by_line = 1;
X		Strcpy(buf, "killed by");
X		if (killer_format == KILLED_BY_AN)
X			Strcat(buf, index(vowels, *killer) ? " an" : " a");
X		center(8, buf);
X	}
X	Strcpy(buf, killer);
X	if(strlen(buf) > 16) {
X	    register int i,i0,i1;
X		i0 = i1 = 0;
X		for(i = 0; i <= 16; i++)
X			if(buf[i] == ' ') i0 = i, i1 = i+1;
X		if(!i0) i0 = i1 = 16;
X		buf[i1 + 16] = 0;
X		center(9 + killed_by_line, buf+i1);
X		buf[i0] = 0;
X	}
X	center(8 + killed_by_line, buf);
X	Sprintf(buf, "%4d", getyear());
X	center(11, buf);
X	for(y=8; *dp; y++,dp++){
X		x = 0;
X		dpx = *dp;
X		while(dpx[x]) {
X			while(dpx[x] == ' ') x++;
X			curs(x,y);
X			while(dpx[x] && dpx[x] != ' '){
X				if(done_stopprint)
X					return;
X				curx++;
X				(void) putchar(dpx[x++]);
X			}
X		}
X	}
X	getret();
X}
X
END_OF_FILE
if test 2319 -ne `wc -c <'src/rip.c'`; then
    echo shar: \"'src/rip.c'\" unpacked with wrong size!
fi
# end of 'src/rip.c'
fi
echo shar: End of archive 32 \(of 56\).
cp /dev/null ark32isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 56 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0