[comp.sources.games] v03i007: NetHack2.2 - display oriented dungeons and dragons, Part07/20

games-request@tekred.TEK.COM (12/02/87)

Submitted by: mike@genat.UUCP (Mike Stephenson)
Comp.sources.games: Volume 3, Issue 7
Archive-name: nethack2.2/Part07



#! /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 7 (of 20)."
# Contents:  mklev.c mon.c topten.c
# Wrapped by billr@tekred on Tue Dec  1 16:24:55 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f mklev.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"mklev.c\"
else
echo shar: Extracting \"mklev.c\" \(20060 characters\)
sed "s/^X//" >mklev.c <<'END_OF_mklev.c'
X/*	SCCS Id: @(#)mklev.c	2.1	87/09/23
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X
X#include "hack.h"
X
Xextern char *getlogin(), *getenv();
Xextern struct monst *makemon();
Xextern struct obj *mkobj_at();
Xextern struct trap *maketrap();
X
X#ifdef RPH
Xextern struct permonst pm_medusa;
X#endif
X
X#define somex() ((rand()%(croom->hx-croom->lx+1))+croom->lx)
X#define somey() ((rand()%(croom->hy-croom->ly+1))+croom->ly)
X
X#include "mkroom.h"
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 */
Xextern struct mkroom rooms[MAXNROFROOMS+1];
Xint smeq[MAXNROFROOMS+1];
Xextern coord doors[DOORMAX];
Xint doorindex;
Xstruct rm zerorm;
Xint comp();
Xschar nxcor;
Xboolean goldseen;
Xint nroom;
Xextern xchar xdnstair,xupstair,ydnstair,yupstair;
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
Xmakelevel()
X{
X	register struct mkroom *croom, *troom;
X	register unsigned tryct;
X#ifndef REGBUG
X	register
X#endif
X		 int x,y;
X#ifdef SPIDERS			/* always put a web with a spider */
X	struct monst *tmonst;
X#endif
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
X	oinit();	/* assign level dependent obj probabilities */
X#ifdef RPH
X	if (u.wiz_level == 0) {
X	    u.medusa_level = rn1(3,25);
X	    u.wiz_level    = d(3,10) + u.medusa_level;
X# ifdef WIZARD
X	    if (wizard && dlevel == 1)
X	        pline ("The wiz is at %d, and the medusa at %d",
X			u.wiz_level, u.medusa_level);
X# endif
X	}
X	if (dlevel > u.medusa_level) {
X	    makemaz();
X	    return;
X	}
X#else
X	if(dlevel >= rn1(3, 26)) {	/* there might be several mazes */
X		makemaz();
X		return;
X	}
X#endif
X	/* construct the rooms */
X	nroom = 0;
X	secret = FALSE;
X	(void) makerooms();
X
X	/* construct stairs (up and down in different rooms if possible) */
X	croom = &rooms[rn2(nroom)];
X	xdnstair = somex();
X	ydnstair = somey();
X	levl[xdnstair][ydnstair].scrsym = DN_SYM;
X	levl[xdnstair][ydnstair].typ = STAIRS;
X#ifdef RPH
X	{ struct monst *mtmp;
X	if (dlevel == u.medusa_level) 
X	    if (mtmp = makemon(PM_MEDUSA, xdnstair, ydnstair))
X	        mtmp->msleep = 1;
X	}
X#endif
X	if(nroom > 1) {
X		troom = croom;
X		croom = &rooms[rn2(nroom-1)];
X		if(croom >= troom) croom++;
X	}
X	xupstair = somex();	/* %% < and > might be in the same place */
X	yupstair = somey();
X	levl[xupstair][yupstair].scrsym = UP_SYM;
X	levl[xupstair][yupstair].typ = STAIRS;
X
X	/* for each room: put things inside */
X	for(croom = rooms; croom->hx > 0; croom++) {
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 trapdoor
X		   while a monster was on the stairs. Conclusion:
X		   we have to check for monsters on the stairs anyway. */
X#ifdef BVH
X		if(has_amulet() || !rn2(3))
X#else
X		if (!rn2(3))
X#endif
X#ifndef SPIDERS
X		    (void)makemon((struct permonst *) 0, somex(), somey());
X#else
X		{
X		    x = somex(); y = somey();
X		    tmonst=makemon((struct permonst *) 0, x,y);
X		    if (tmonst && tmonst->data->mlet == 's')
X		        (void) maketrap (x,y,WEB);
X		}
X#endif
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(),somey());
X#ifdef FOUNTAINS
X		if(!rn2(10)) mkfount(0,croom);
X#endif
X		if(!rn2(3)) {
X			(void) mkobj_at(0, somex(), somey());
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(), somey());
X			}
X		}
X	}
X
X	qsort((char *) rooms, nroom, sizeof(struct mkroom), comp);
X	makecorridors();
X	make_niches();
X
X	/* make a secret treasure vault, not connected to the rest */
X	if(nroom <= (2*MAXNROFROOMS/3)) if(rn2(3)) {
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")) mkshop(); else
X#endif
X	if(dlevel > 1 && dlevel < 20 && rn2(dlevel) < 3) mkshop();
X	else
X#ifdef NEWCLASS
X	if(dlevel > 4 && !rn2(6)) mkzoo(COURT);
X#endif
X	if(dlevel > 6 && !rn2(7)) mkzoo(ZOO);
X	else
X	if(dlevel > 9 && !rn2(5)) mkzoo(BEEHIVE);
X	else
X	if(dlevel > 11 && !rn2(6)) mkzoo(MORGUE);
X	else
X	if(dlevel > 18 && !rn2(6)) mkswamp();
X}
X
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/3) &&
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/2 + 2*xlim || 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)) {
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
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
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
Xcomp(x,y)
Xregister struct mkroom *x,*y;
X{
X	if(x->lx < y->lx) return(-1);
X	return(x->lx > y->lx);
X}
X
Xfinddpos(cc, xl,yl,xh,yh)
Xcoord	*cc;
Xint	xl,yl,xh,yh;
X{
X	register 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(levl[x][y].typ == DOOR || 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(0);
X}
X
X/* see whether it is allowable to create a door at [x,y] */
Xokdoor(x,y)
Xregister x,y;
X{
X	if(levl[x-1][y].typ == DOOR || levl[x+1][y].typ == DOOR ||
X	   levl[x][y+1].typ == DOOR || levl[x][y-1].typ == DOOR ||
X	   levl[x-1][y].typ == SDOOR || levl[x+1][y].typ == SDOOR ||
X	   levl[x][y-1].typ == SDOOR || levl[x][y+1].typ == SDOOR ||
X	   (levl[x][y].typ != HWALL && levl[x][y].typ != VWALL) ||
X	   doorindex >= DOORMAX)
X		return(0);
X	return(1);
X}
X
Xdodoor(x,y,aroom)
Xregister 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
Xdosdoor(x,y,aroom,type)
Xregister x,y;
Xregister struct mkroom *aroom;
Xregister type;
X{
X	register struct mkroom *broom;
X	register tmp;
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		levl[x][y].scrsym = DOOR_SYM;
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
X/* Only called from makerooms() */
Xmaker(lowx,ddx,lowy,ddy)
Xschar lowx,ddx,lowy,ddy;
X{
X	register struct mkroom *croom;
X	register x, y, hix = lowx+ddx, hiy = lowy+ddy;
X	register 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(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	if((rnd(dlevel) < 10 && rn2(77)) || (ddx == 1 && ddy == 1)) {
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 = croom->fdoor = 0;
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].scrsym = HWALL_SYM;
X		levl[x][y].typ = HWALL;
X	}
X	for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
X	    for(y = lowy; y <= hiy; y++) {
X		levl[x][y].scrsym = VWALL_SYM;
X		levl[x][y].typ = VWALL;
X	}
X	for(x = lowx; x <= hix; x++)
X	    for(y = lowy; y <= hiy; y++) {
X		levl[x][y].scrsym = ROOM_SYM;
X		levl[x][y].typ = ROOM;
X	}
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
Xmakecorridors() {
X	register 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
Xjoin(a,b)
Xregister a,b;
X{
X	coord cc,tt;
X	register tx, ty, xx, yy;
X	register struct rm *crm;
X	register struct mkroom *croom, *troom;
X	register 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) mkobj_at(ROCK_SYM, xx, yy);
X		} else {
X			crm->typ = SCORR;
X			crm->scrsym = 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 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 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
Xmake_niches()
X{
X	register int ct = rnd(nroom/2 + 1);
X#ifdef NEWCLASS
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#else
X	while(ct--) makeniche(NO_TRAP);
X#endif
X}
X
Xmakevtele()
X{
X	makeniche(TELEP_TRAP);
X}
X
X/* there should be one of these per trap */
Xchar    *engravings[] = {       "", "", "", "", "",
X				"ad ae?ar um", "?la? ?as ?er?",
X				"", "", ""
X#ifdef NEWTRAPS
X				,"", ""
X#endif
X#ifdef SPIDERS
X				,""
X#endif
X#ifdef NEWCLASS
X				, "", "ad ae?ar um"
X#endif
X#ifdef SPELLS
X				,""
X#endif
X				};
X
Xmakeniche(trap_type)
Xint trap_type;
X{
X	register struct mkroom *aroom;
X	register struct rm *rm;
X	register int vct = 8;
X	coord dd;
X	register dy,xx,yy;
X	register struct trap *ttmp;
X
X	if(doorindex < DOORMAX)
X	  while(vct--) {
X	    aroom = &rooms[rn2(nroom-1)];
X	    if(aroom->rtype != OROOM) continue;	/* not an ordinary room */
X	    if(aroom->doorct == 1 && rn2(5)) continue;
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	    if((rm = &levl[xx][yy+dy])->typ) continue;
X	    if(trap_type || !rn2(4)) {
X
X		rm->typ = SCORR;
X		rm->scrsym = 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		    mksobj_at(SCR_TELEPORTATION, xx, yy+dy);
X		    if(!rn2(3)) (void) mkobj_at(0, xx, yy+dy);
X		}
X	    }
X	    return;
X	}
X}
X
X/* make a trap somewhere (in croom if mazeflag = 0) */
Xmktrap(num, mazeflag, croom)
X#ifndef REGBUG
Xregister
X#endif
X	 int num, mazeflag;
X#ifndef REGBUG
Xregister
X#endif
X	 struct mkroom *croom;
X{
X#ifndef REGBUG
X	register
X#endif
X		 struct trap *ttmp;
X#ifndef REGBUG
X	register
X#endif
X		int kind,nopierc,nomimic,fakedoor,fakegold,
X#ifdef SPIDERS
X		    nospider,
X#endif
X#ifdef NEWCLASS
X		    nospikes, nolevltp,
X#endif
X		    tryct = 0;
X
X	xchar mx,my;
X	extern char fut_geno[];
X
X	if(!num || num >= TRAPNUM) {
X		nopierc = (dlevel < 4) ? 1 : 0;
X#ifdef NEWCLASS
X		nolevltp = (dlevel < 5) ? 1 : 0;
X		nospikes = (dlevel < 6) ? 1 : 0;
X#endif
X#ifdef SPIDERS
X		nospider = (dlevel < 7) ? 1 : 0;
X#endif
X		nomimic = (dlevel < 9 || goldseen ) ? 1 : 0;
X		if(index(fut_geno, 'M')) nomimic = 1;
X
X		do {
X		    kind = rnd(TRAPNUM-1);
X			if((kind == PIERC && nopierc) ||
X			   (kind == MIMIC && nomimic)
X#ifdef SPIDERS
X			   || ((kind == WEB) && nospider)
X#endif
X#ifdef NEWCLASS
X			   || (kind == SPIKED_PIT && nospikes)
X			   || (kind == LEVEL_TELEP && nolevltp)
X#endif
X			   )  kind = NO_TRAP;
X		} while(kind == NO_TRAP);
X	} else kind = num;
X
X	if(kind == MIMIC) {
X		register struct monst *mtmp;
X
X		fakedoor = (!rn2(3) && !mazeflag);
X		fakegold = (!fakedoor && !rn2(2));
X		if(fakegold) goldseen = TRUE;
X		do {
X			if(++tryct > 200) return;
X			if(fakedoor) {
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();
X				} else {
X				    if(rn2(2))	my = croom->hy+1;
X				    else	my = croom->ly-1;
X				    mx = somex();
X				}
X			} else if(mazeflag) {
X				coord mm;
X				mazexy(&mm);
X				mx = mm.x;
X				my = mm.y;
X			} else {
X				mx = somex();
X				my = somey();
X			}
X		} while(m_at(mx,my) || levl[mx][my].typ == STAIRS);
X		if(mtmp = makemon(PM_MIMIC,mx,my)) {
X		    mtmp->mimic = 1;
X		    mtmp->mappearance =
X			fakegold ? '$' : fakedoor ? DOOR_SYM :
X			(mazeflag && rn2(2)) ? AMULET_SYM :
X#ifdef SPELLS
X			"=/)%?![<>+" [ rn2(10) ];
X#else
X			"=/)%?![<>" [ rn2(9) ];
X#endif
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();
X			my = somey();
X		}
X	} while(t_at(mx, my) || levl[mx][my].typ == STAIRS);
X	ttmp = maketrap(mx, my, kind);
X#ifdef SPIDERS
X	if (kind == WEB) mkmon_at ('s', mx, my);
X#endif
X	if(mazeflag && !rn2(10) && ttmp->ttyp < PIERC)
X		ttmp->tseen = 1;
X}
X
X#ifdef FOUNTAINS
Xmkfount(mazeflag,croom)
Xregister struct mkroom *croom;
Xregister mazeflag;
X{
X      register xchar mx,my;
X      register int tryct = 0;
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();
X		      my = somey();
X	      }
X      } while(t_at(mx, my) || levl[mx][my].typ == STAIRS
X#ifdef NEWCLASS
X	      || IS_THRONE(levl[mx][my].typ)
X#endif
X	     );
X
X       /* Put a fountain at mx, my */
X
X       levl[mx][my].typ = FOUNTAIN;
X       levl[mx][my].scrsym = FOUNTAIN_SYM;
X
X}
X#endif /* FOUNTAINS /**/
X
END_OF_mklev.c
if test 20060 -ne `wc -c <mklev.c`; then
    echo shar: \"mklev.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f mon.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"mon.c\"
else
echo shar: Extracting \"mon.c\" \(19391 characters\)
sed "s/^X//" >mon.c <<'END_OF_mon.c'
X/*	SCCS Id: @(#)mon.c	2.1	87/10/17
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X
X#include "hack.h"
X#include "mfndpos.h"
Xextern struct monst *mkmon_at();
Xextern struct trap *maketrap();
Xextern struct obj *mkobj_at(), *mksobj_at();
Xextern char *hcolor();
X#ifdef KAA
Xextern boolean	stoned;
Xextern char mlarge[];
X#endif
X#ifdef RPH
Xextern struct obj *mk_named_obj_at();
X#endif
X
Xint warnlevel;		/* used by movemon and dochugw */
Xlong lastwarntime;
Xint lastwarnlev;
Xchar	*warnings[] = {	"white", "pink", "red", "ruby", "purple", "black"  };
X
Xmovemon()
X{
X	register struct monst *mtmp;
X	register int fr;
X
X	warnlevel = 0;
X
X	while(1) {
X		/* find a monster that we haven't treated yet */
X		/* note that mtmp or mtmp->nmon might get killed
X		   while mtmp moves, so we cannot just walk down the
X		   chain (even new monsters might get created!) */
X		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X			if(mtmp->mlstmv < moves) goto next_mon;
X		/* treated all monsters */
X		break;
X
X	next_mon:
X		mtmp->mlstmv = moves;
X
X		/* most monsters drown in pools */
X		{ boolean inpool, iseel;
X
X		  inpool = (levl[mtmp->mx][mtmp->my].typ == POOL);
X		  iseel = (mtmp->data->mlet == ';');
X		  if(inpool && !iseel) {
X			if(cansee(mtmp->mx,mtmp->my))
X			    pline("%s drowns.", Monnam(mtmp));
X			mondead(mtmp);
X			continue;
X		  }
X		/* but eels have a difficult time outside */
X		  if(iseel && !inpool) {
X			if(mtmp->mhp > 1) mtmp->mhp--;
X			mtmp->mflee = 1;
X			mtmp->mfleetim += 2;
X		  }
X		}
X		if(mtmp->mblinded && !--mtmp->mblinded)
X			mtmp->mcansee = 1;
X		if(mtmp->mfleetim && !--mtmp->mfleetim)
X			mtmp->mflee = 0;
X#ifdef HARD
X		/* unwatched mimics and piercers may hide again  [MRS] */
X		if(restrap(mtmp))	continue;
X#endif
X		if(mtmp->mimic) continue;
X		if(mtmp->mspeed != MSLOW || !(moves%2)){
X			/* continue if the monster died fighting */
X			fr = -1;
X			if(Conflict && cansee(mtmp->mx,mtmp->my)
X				&& (fr = fightm(mtmp)) == 2)
X				continue;
X			if(fr<0 && dochugw(mtmp))
X				continue;
X		}
X		if(mtmp->mspeed == MFAST && dochugw(mtmp))
X			continue;
X	}
X
X	warnlevel -= u.ulevel;
X	if(warnlevel >= SIZE(warnings))
X		warnlevel = SIZE(warnings)-1;
X	if(warnlevel >= 0)
X	if(warnlevel > lastwarnlev || moves > lastwarntime + 5){
X	    register char *rr;
X	    switch((int) (Warning & (LEFT_RING | RIGHT_RING))){
X	    case LEFT_RING:
X		rr = "Your left ring glows";
X		break;
X	    case RIGHT_RING:
X		rr = "Your right ring glows";
X		break;
X	    case LEFT_RING | RIGHT_RING:
X		rr = "Both your rings glow";
X		break;
X	    default:
X		rr = "Your fingertips glow";
X		break;
X	    }
X	    pline("%s %s!", rr, Hallucination ? hcolor() : warnings[warnlevel]);
X	    lastwarntime = moves;
X	    lastwarnlev = warnlevel;
X	}
X
X	dmonsfree();	/* remove all dead monsters */
X}
X
Xjustswld(mtmp,name)
Xregister struct monst *mtmp;
Xchar *name;
X{
X
X	mtmp->mx = u.ux;
X	mtmp->my = u.uy;
X	u.ustuck = mtmp;
X	pmon(mtmp);
X	kludge("%s swallows you!",name);
X	more();
X	seeoff(1);
X	u.uswallow = 1;
X	u.uswldtim = 0;
X	swallowed();
X}
X
Xyouswld(mtmp,dam,die,name)
Xregister struct monst *mtmp;
Xregister dam,die;
Xchar *name;
X{
X	if(mtmp != u.ustuck) return;
X	kludge("%s digests you!",name);
X	u.uhp -= dam;
X	if(u.uswldtim++ >= die){	/* a3 */
X		pline("It totally digests you!");
X		u.uhp = -1;
X	}
X	if(u.uhp < 1) done_in_by(mtmp);
X	/* flags.botlx = 1;		/* should we show status line ? */
X}
X
X#ifdef ROCKMOLE
Xmeatgold(mtmp) register struct monst *mtmp; {
Xregister struct gold *gold;
Xregister int pile;
Xregister struct obj *otmp;
X#ifdef KJSMODS
X	if(dlevel < 4) return;
X#endif
X	/* Eats gold if it is there */
X	while(gold = g_at(mtmp->mx, mtmp->my)){
X		freegold(gold);
X		/* Left behind a pile? */
X		pile = rnd(25);
X		if(pile < 3) mksobj_at(ROCK, mtmp->mx, mtmp->my);
X		newsym(mtmp->mx, mtmp->my);
X	}
X	/* Eats armor if it is there */
X	otmp = o_at(mtmp->mx,mtmp->my);
X	if((otmp) && (otmp->otyp >= PLATE_MAIL) && (otmp->otyp <= RING_MAIL)){
X		freeobj(otmp);
X		/* Left behind a pile? */
X		pile = rnd(25);
X		if(pile < 3)  mksobj_at(ROCK, mtmp->mx, mtmp->my);
X		newsym(mtmp->mx, mtmp->my);
X	}
X}
X#endif /* ROCKMOLE /**/
X
Xmpickgold(mtmp) register struct monst *mtmp; {
Xregister struct gold *gold;
X	while(gold = g_at(mtmp->mx, mtmp->my)){
X		mtmp->mgold += gold->amount;
X		freegold(gold);
X		if(levl[mtmp->mx][mtmp->my].scrsym == GOLD_SYM)
X			newsym(mtmp->mx, mtmp->my);
X	}
X}
X
X/* Now includes giants which pick up enormous rocks.  KAA */
Xmpickgems(mtmp) register struct monst *mtmp; {
Xregister struct obj *otmp;
X	for(otmp = fobj; otmp; otmp = otmp->nobj)
X	  if(otmp->olet ==
X#ifdef KAA
X			   (mtmp->data->mlet=='9' ? ROCK_SYM : GEM_SYM))
X#else
X			   GEM_SYM)
X#endif
X	    if(otmp->ox == mtmp->mx && otmp->oy == mtmp->my)
X	      if(mtmp->data->mlet != 'u' || objects[otmp->otyp].g_val != 0){
X		freeobj(otmp);
X		mpickobj(mtmp, otmp);
X#ifndef KAA
X		if(levl[mtmp->mx][mtmp->my].scrsym == GEM_SYM)
X#endif
X			newsym(mtmp->mx, mtmp->my);	/* %% */
X		return;	/* pick only one object */
X	      }
X}
X
X/* return number of acceptable neighbour positions */
Xmfndpos(mon,poss,info,flag)
Xregister struct monst *mon;
Xcoord poss[9];
Xlong info[9], flag;
X{
X	register int x,y,nx,ny,cnt = 0,ntyp;
X	register struct monst *mtmp;
X	int nowtyp;
X	boolean pool;
X
X	x = mon->mx;
X	y = mon->my;
X	nowtyp = levl[x][y].typ;
X
X	pool = (mon->data->mlet == ';');
Xnexttry:	/* eels prefer the water, but if there is no water nearby,
X		   they will crawl over land */
X	if(mon->mconf) {
X		flag |= ALLOW_ALL;
X		flag &= ~NOTONL;
X	}
X	for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++)
X	if(nx != x || ny != y) if(isok(nx,ny))
X#ifdef ROCKMOLE
X	if(!IS_ROCK(ntyp = levl[nx][ny].typ) || (flag & ALLOW_WALL))
X#else
X	if(!IS_ROCK(ntyp = levl[nx][ny].typ))
X#endif
X	if(!(nx != x && ny != y && (nowtyp == DOOR || ntyp == DOOR)))
X	if((ntyp == POOL) == pool) {
X		info[cnt] = 0;
X		if(nx == u.ux && ny == u.uy){
X			if(!(flag & ALLOW_U)) continue;
X			info[cnt] = ALLOW_U;
X		} else if(mtmp = m_at(nx,ny)){
X			if(!(flag & ALLOW_M)) continue;
X			info[cnt] = ALLOW_M;
X			if(mtmp->mtame){
X				if(!(flag & ALLOW_TM)) continue;
X				info[cnt] |= ALLOW_TM;
X			}
X		}
X		if(sobj_at(CLOVE_OF_GARLIC, nx, ny)) {
X			if(flag & NOGARLIC) continue;
X			info[cnt] |= NOGARLIC;
X		}
X		if(sobj_at(SCR_SCARE_MONSTER, nx, ny) ||
X		   (!mon->mpeaceful && sengr_at("Elbereth", nx, ny))) {
X			if(!(flag & ALLOW_SSM)) continue;
X			info[cnt] |= ALLOW_SSM;
X		}
X		if(sobj_at(ENORMOUS_ROCK, nx, ny)) {
X			if(!(flag & ALLOW_ROCK)) continue;
X			info[cnt] |= ALLOW_ROCK;
X		}
X		if(!Invis && online(nx,ny)){
X			if(flag & NOTONL) continue;
X			info[cnt] |= NOTONL;
X		}
X		/* we cannot avoid traps of an unknown kind */
X		{ register struct trap *ttmp = t_at(nx, ny);
X		  register long tt;
X			if(ttmp) {
X				tt = 1L << ttmp->ttyp;
X				/* below if added by GAN 02/06/87 to avoid
X				 * traps out of range
X				 */
X				if(!(tt & ALLOW_TRAPS))  {
X					impossible("A monster looked at a very strange trap");
X					continue;
X				}
X				if(mon->mtrapseen & tt){
X					if(!(flag & tt)) continue;
X					info[cnt] |= tt;
X				}
X			}
X		}
X		poss[cnt].x = nx;
X		poss[cnt].y = ny;
X		cnt++;
X	}
X	if(!cnt && pool && nowtyp != POOL) {
X		pool = FALSE;
X		goto nexttry;
X	}
X	return(cnt);
X}
X
Xdist(x,y) int x,y; {
X	return((x-u.ux)*(x-u.ux) + (y-u.uy)*(y-u.uy));
X}
X
Xpoisoned(string, pname)
Xregister char *string, *pname;
X{
X	register i, plural;
X
X	plural = (string[strlen(string) - 1] == 's')? 1 : 0;
X	if(Blind) {
X		if (plural)	pline("They were poisoned.");
X		else		pline("It was poisoned.");
X	} else	{
X		if (plural)	pline("The %s were poisoned!", string);
X		else		pline("The %s was poisoned!", string);
X	}
X
X	if(Poison_resistance) {
X		pline("The poison doesn't seem to affect you.");
X		return;
X	}
X	i = rn2(10);
X	if(i == 0) {
X		u.uhp = -1;
X		pline("I am afraid the poison was deadly ...");
X	} else if(i <= 5) {
X		losestr(rn1(3,3));
X	} else {
X		losehp(rn1(10,6), pname);
X	}
X	if(u.uhp < 1) {
X		killer = pname;
X		done("died");
X	}
X}
X
Xmondead(mtmp)
Xregister struct monst *mtmp;
X{
X	relobj(mtmp,1);
X	unpmon(mtmp);
X	relmon(mtmp);
X	unstuck(mtmp);
X#ifdef KOPS
X       if(mtmp->data->mlet == 'K' &&
X          !strcmp(mtmp->data->mname,"Keystone Kop")) {
X	   /* When a Kop dies, he probably comes back. */
X	   switch(rnd(3)) {
X
X		case 1:	     /* returns near the stairs */
X			mkmon_at('K',xdnstair,ydnstair);
X			break;
X		case 2:	     /* randomly */
X			mkmon_at('K',0,0);
X			break;
X		default:
X			break;
X	   }
X	  }
X#endif
X	if(mtmp->isshk) shkdead(mtmp);
X	if(mtmp->isgd) gddead();
X#ifndef NOWORM
X	if(mtmp->wormno) wormdead(mtmp);
X#endif
X#ifdef HARD
X	if(mtmp->data->mlet == '1') wizdead(mtmp);
X#endif
X	monfree(mtmp);
X}
X
X/* called when monster is moved to larger structure */
Xreplmon(mtmp,mtmp2)
Xregister struct monst *mtmp, *mtmp2;
X{
X	relmon(mtmp);
X	monfree(mtmp);
X	mtmp2->nmon = fmon;
X	fmon = mtmp2;
X	if(u.ustuck == mtmp) u.ustuck = mtmp2;
X	if(mtmp2->isshk) replshk(mtmp,mtmp2);
X	if(mtmp2->isgd) replgd(mtmp,mtmp2);
X}
X
Xrelmon(mon)
Xregister struct monst *mon;
X{
X	register struct monst *mtmp;
X
X	if (fmon == 0)  panic ("relmon: no fmon available.");
X
X	if(mon == fmon) fmon = fmon->nmon;
X	else {
X		for(mtmp = fmon; mtmp->nmon != mon; mtmp = mtmp->nmon) ;
X		mtmp->nmon = mon->nmon;
X	}
X}
X
X/* we do not free monsters immediately, in order to have their name
X   available shortly after their demise */
Xstruct monst *fdmon;	/* chain of dead monsters, need not to be saved */
X
Xmonfree(mtmp) register struct monst *mtmp; {
X	mtmp->nmon = fdmon;
X	fdmon = mtmp;
X}
X
Xdmonsfree(){
Xregister struct monst *mtmp;
X	while(mtmp = fdmon){
X		fdmon = mtmp->nmon;
X		free((char *) mtmp);
X	}
X}
X
Xunstuck(mtmp)
Xregister struct monst *mtmp;
X{
X	if(u.ustuck == mtmp) {
X		if(u.uswallow){
X			u.ux = mtmp->mx;
X			u.uy = mtmp->my;
X			u.uswallow = 0;
X			setsee();
X			docrt();
X		}
X		u.ustuck = 0;
X	}
X}
X
Xkilled(mtmp)
Xregister struct monst *mtmp;
X{
X	xkilled(mtmp, 1);
X}
X
Xxkilled(mtmp, dest)
Xregister struct monst *mtmp;
Xint	dest;
X/* Dest=1, normal; dest=0, don't print message; dest=2, don't drop corpse
X   either; dest=3, message but no corpse */
X{
X#ifdef LINT
X#define	NEW_SCORING
X#endif
X	register int tmp,tmp2,nk,x,y;
X	register struct permonst *mdat = mtmp->data;
X	extern long newuexp();
X#ifdef RPH
X	int old_nlth;
X	char old_name[BUFSZ];
X#endif
X
X	if(mtmp->cham) mdat = PM_CHAMELEON;
X	if (dest & 1) {
X	    if(Blind) pline("You destroy it!");
X	    else {
X		pline("You destroy %s!",
X			mtmp->mtame ? amonnam(mtmp, "poor") : monnam(mtmp));
X	    }
X	}
X	if(u.umconf) {
X		if(!Blind)
X		{
X			pline("Your hands stop glowing %s.",
X			Hallucination ? hcolor() : "blue");
X		}
X		u.umconf = 0;
X	}
X
X	/* count killed monsters */
X#define	MAXMONNO	100
X	nk = 1;		      /* in case we cannot find it in mons */
X	tmp = mdat - mons;    /* index in mons array (if not 'd', '@', ...) */
X	if(tmp >= 0 && tmp < CMNUM+2) {
X	    extern char fut_geno[];
X	    u.nr_killed[tmp]++;
X	    if((nk = u.nr_killed[tmp]) > MAXMONNO &&
X#ifdef HARD
X# ifdef KOPS
X		!index("KkO&", mdat->mlet) &&
X# else
X		!index("kO&", mdat->mlet) &&
X# endif
X#endif
X		!index(fut_geno, mdat->mlet))
X		    charcat(fut_geno,  mdat->mlet);
X	}
X
X	/* punish bad behaviour */
X	if(mdat->mlet == '@') {
X		HTelepat = 0;
X		u.uluck -= 2;
X	}
X	if(mtmp->mpeaceful || mtmp->mtame) u.uluck--;
X	if(mdat->mlet == 'u') u.uluck -= 5;
X	if((int)u.uluck < LUCKMIN) u.uluck = LUCKMIN;
X
X	/* give experience points */
X	tmp = 1 + mdat->mlevel * mdat->mlevel;
X	if(mdat->ac < 3) tmp += 2*(7 - mdat->ac);
X	if(index(
X#ifdef RPH
X# ifdef KAA
X		 "AcsSDXaeRTVWU&In:P89",
X# else
X		 "AcsSDXaeRTVWU&In:P8",
X# endif
X#else
X# ifdef KAA
X		 "AcsSDXaeRTVWU&In:P9",
X# else
X		 "AcsSDXaeRTVWU&In:P",
X# endif
X#endif
X					 mdat->mlet)) tmp += 2*mdat->mlevel;
X
X	if(index("DeV&P",mdat->mlet)) tmp += (7*mdat->mlevel);
X	if(mdat->mlevel > 6) tmp += 50;
X	if(mdat->mlet == ';') tmp += 1000;
X
X#ifdef NEW_SCORING
X	/* ------- recent addition: make nr of points decrease
X		   when this is not the first of this kind */
X	{ int ul = u.ulevel;
X	  int ml = mdat->mlevel;
X
X	if(ul < 14)    /* points are given based on present and future level */
X	    for(tmp2 = 0; !tmp2 || ul + tmp2 <= ml; tmp2++)
X		if(u.uexp + 1 + (tmp + ((tmp2 <= 0) ? 0 : 4<<(tmp2-1)))/nk
X		    >= 10*pow((unsigned)(ul-1)))
X			if(++ul == 14) break;
X
X	tmp2 = ml - ul -1;
X	tmp = (tmp + ((tmp2 < 0) ? 0 : 4<<tmp2))/nk;
X	if(!tmp) tmp = 1;
X	}
X	/* note: ul is not necessarily the future value of u.ulevel */
X	/* ------- end of recent valuation change ------- */
X#endif /* NEW_SCORING /**/
X
X	more_experienced(tmp,0);
X	flags.botl = 1;
X	while(u.ulevel < 14 && u.uexp >= newuexp()){
X#ifdef RPH
X		/* make experience gaining simiar to d&d, whereby you */
X		/* can at most go up by one level at a time, extra expr */
X		/* possibly helping you along. Afterall, how much real */
X		/* experience does one get shooting a wand of death at */
X		/* a dragon created w/ a poymorph?? */
X		u.ulevel++;
X		if (u.uexp >= newuexp())
X		    u.uexp = newuexp() - 1;
X		pline("Welcome to experience level %u.", u.ulevel);
X#else
X		pline("Welcome to experience level %u.", ++u.ulevel);
X#endif
X		tmp = rnd(10);
X		if(tmp < 3) tmp = rnd(10);
X		u.uhpmax += tmp;
X		u.uhp += tmp;
X#ifdef SPELLS
X		tmp = rnd(u.ulevel/2+1) + 1;	/* M. Stephenson */
X		u.uenmax += tmp;
X		u.uen += tmp;
X#endif
X		flags.botl = 1;
X	}
X
X	/* dispose of monster and make cadaver */
X	x = mtmp->mx;	y = mtmp->my;
X#ifdef RPH
X	old_nlth = mtmp->mnamelth;
X	if (old_nlth > 0)  (void) strcpy (old_name, NAME(mtmp));
X#endif	    
X	mondead(mtmp);
X	tmp = mdat->mlet;
X	if(tmp == 'm') { /* he killed a minotaur, give him a wand of digging */
X			/* note: the dead minotaur will be on top of it! */
X		mksobj_at(WAN_DIGGING, x, y);
X		/* if(cansee(x,y)) atl(x,y,fobj->olet); */
X		stackobj(fobj);
X	} else
X#ifndef NOWORM
X	if(tmp == 'w') {
X		mksobj_at(WORM_TOOTH, x, y);
X		stackobj(fobj);
X	} else
X#endif
X#ifdef KJSMODS
X	if(tmp == 'N') { 
X		mksobj_at(POT_OBJECT_DETECTION, x, y);
X		stackobj(fobj);
X	} else
X#endif
X#ifdef KAA
X	if(tmp == '&') (void) mkobj_at(0, x, y);
X	else
X	if(stoned == FALSE && (!letter(tmp) || (!index("9&1", tmp) && !rn2(3)))) tmp = 0;
X	    if(dest & 2) {
X		newsym(x,y);
X		return;
X	    }
X#else
X	if(!letter(tmp) || (!index("mw", tmp) && !rn2(3))) tmp = 0;
X#endif
X	tmp2 = rn2(5);
X#ifdef KJSMODS
X	/* if a kobold or a giant rat does not become treasure, do
X	 *  not make a corpse. */
X# ifdef KOPS
X	if(mdat->mlet == 'K'
X	   && !strcmp(mdat->mname,"kobold") && tmp) tmp2 = 0;
X# endif
X# ifdef ROCKMOLE
X	if((mdat->mlet == 'r' && dlevel < 4) && tmp) tmp2 = 0;
X# endif
X#endif
X	if(!ACCESSIBLE(levl[x][y].typ)) {
X	    /* might be mimic in wall or dead eel*/
X 	    newsym(x,y);
X	} else if(x != u.ux || y != u.uy) {
X		/* might be here after swallowed */
X#ifdef KAA
X		if(stoned) {
X			register int typetmp;
X			if(index(mlarge, tmp))	typetmp = ENORMOUS_ROCK;
X			else			typetmp = ROCK;
X			mksobj_at(typetmp, x, y);
X			if(cansee(x,y))
X			    atl(x, y, Hallucination ? rndobjsym() :
X				      objects[typetmp].oc_olet);
X		} else
X#endif
X		if(index("NTVm&w",mdat->mlet) || tmp2) {
X#ifndef RPH
X			register struct obj *obj2 = mkobj_at(tmp,x,y);
X#else
X			register struct obj *obj2;
X			if (letter(tmp))
X			    obj2 = mk_named_obj_at(tmp, x, y,
X						   old_name, old_nlth);
X# ifdef KOPS
X			else if (mdat->mlet == 'K')
X			    obj2 = mksobj_at((rn2(4) ? CLUB : WHISTLE), x, y);
X# endif
X			else
X			    obj2 = mkobj_at(tmp,x,y);
X#endif   /* RPH /**/
X			if(cansee(x,y))
X			    atl(x, y, Hallucination ? rndobjsym() : obj2->olet);
X			stackobj(obj2);
X		}
X	}
X}
X
Xkludge(str,arg)
Xregister char *str,*arg;
X{
X	if(Blind) {
X		if(*str == '%') pline(str,"It");
X		else pline(str,"it");
X	} else pline(str,arg);
X}
X
Xrescham()	/* force all chameleons to become normal */
X{
X	register struct monst *mtmp;
X
X	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X		if(mtmp->cham) {
X			mtmp->cham = 0;
X			(void) newcham(mtmp, PM_CHAMELEON);
X		}
X}
X
X#ifdef DGKMOD
X/* Let the chameleons change again -dgk */
Xrestartcham()
X{
X	register struct monst *mtmp;
X
X	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X		if (mtmp->data->mlet == ':') 
X			mtmp->cham = 1;
X}
X#endif
X
Xnewcham(mtmp,mdat)	/* make a chameleon look like a new monster */
X			/* returns 1 if the monster actually changed */
Xregister struct monst *mtmp;
Xregister struct permonst *mdat;
X{
X	register mhp, hpn, hpd;
X
X	if(mdat == mtmp->data) return(0);	/* still the same monster */
X#ifndef NOWORM
X	if(mtmp->wormno) wormdead(mtmp);	/* throw tail away */
X#endif
X	hpn = mtmp->mhp;
X	hpd = (mtmp->data->mlevel)*8;	if(!hpd) hpd = 4;
X	mhp = (mdat->mlevel)*8;		if(!mhp) mhp = 4;
X
X	/* new hp: same fraction of max as before */
X	mtmp->mhp = (hpn*mhp)/hpd;
X	if (mhp > hpd && mtmp->mhp < hpn) mtmp->mhp = 127;
X/* Not totally foolproof.  A 2HD monster with 80 HP that changes into a 6HD
X   monster that really should have 240 and actually should have 127, the
X   maximum possible, will wind up having 113.  */
X	if (!mtmp->mhp) mtmp->mhp = 1;
X/* Unlikely but not impossible; a 1HD creature with 1HP that changes into a
X   0HD creature will require this statement */
X	mtmp->data = mdat;
X/* and the same for maximum hit points */
X	hpn = mtmp->mhpmax;
X	mtmp->mhpmax = (hpn*mhp)/hpd;
X	if (mhp > hpd && mtmp->mhpmax < hpn) mtmp->mhp = 127;
X	if (!mtmp->mhp) mtmp->mhp = 1;
X
X	mtmp->minvis = (mdat->mlet == 'I') ? 1 : 0;
X	/* only snakes and scorpions can hide under things -dgk */
X	/* also generated by GAN */
X	mtmp->mhide = (mdat->mlet == 'S' || mdat->mlet == 's') ? 1 : 0;
X	if (!mtmp->mhide) mtmp->mundetected = 0;
X#ifndef NOWORM
X	if(mdat->mlet == 'w' && getwn(mtmp)) initworm(mtmp);
X			/* perhaps we should clear mtmp->mtame here? */
X#endif
X	unpmon(mtmp);	/* necessary for 'I' and to force pmon */
X	pmon(mtmp);
X	return(1);
X}
X
Xmnexto(mtmp)	/* Make monster mtmp next to you (if possible) */
Xstruct monst *mtmp;
X{
X	coord mm;
X	enexto(&mm, u.ux, u.uy);
X	mtmp->mx = mm.x;
X	mtmp->my = mm.y;
X	pmon(mtmp);
X}
X
Xishuman(mtmp) register struct monst *mtmp; {
X	return(mtmp->data->mlet == '@');
X}
X
Xsetmangry(mtmp) register struct monst *mtmp; {
X	if(!mtmp->mpeaceful) return;
X	if(mtmp->mtame) return;
X	mtmp->mpeaceful = 0;
X	if(ishuman(mtmp)) pline("%s gets angry!", Monnam(mtmp));
X}
X
X/* not one hundred procent correct: now a snake may hide under an
X   invisible object */
Xcanseemon(mtmp)
Xregister struct monst *mtmp;
X{
X	return((!mtmp->minvis || See_invisible)
X		&& (!mtmp->mhide || !o_at(mtmp->mx,mtmp->my))
X		&& cansee(mtmp->mx, mtmp->my));
X}
X
Xdisturb(mtmp)		/* awaken monsters while in the same room.
X			 * return a 1 if they have been woken.
X			 */
Xregister struct monst *mtmp;
X{
X	/* wake up, or get out of here. */
X	/* ettins are hard to surprise */
X	/* Nymphs and Leprechauns do not easily wake up */
X	if(cansee(mtmp->mx,mtmp->my) &&
X		(!Stealth || (mtmp->data->mlet == 'e' && rn2(10))) &&
X		(!index("NL",mtmp->data->mlet) || !rn2(50)) &&
X#ifdef RPH
X		(Aggravate_monster || index("8d1", mtmp->data->mlet)
X#else
X		(Aggravate_monster || index("d1", mtmp->data->mlet)
X#endif
X			|| (!rn2(7) && !mtmp->mimic))) {
X		mtmp->msleep = 0;
X		return(1);
X	}
X	if(Hallucination) pmon(mtmp);
X	return(0);
X}
X
X#ifdef HARD
Xrestrap(mtmp)		/* unwatched mimics and piercers may hide again,
X			 * if so, a 1 is returned.
X			 */
Xregister struct monst *mtmp;
X{
X	if(mtmp->data->mlet == 'M' && !mtmp->mimic && !mtmp->cham
X	   && !mtmp->mcan && !cansee(mtmp->mx, mtmp->my)
X	   && !rn2(3)) {
X		mtmp->mimic = 1;
X		mtmp->mappearance = (levl[mtmp->mx][mtmp->my].typ == DOOR) ? DOOR_SYM : GOLD_SYM;
X		return(1);
X	   }
X
X	if(mtmp->data->mlet == 'p' && !mtmp->cham
X	   && !mtmp->mcan && !cansee(mtmp->mx, mtmp->my)
X	   && !rn2(3))  {
X
X		if(levl[mtmp->mx][mtmp->my].typ == ROOM)  {
X
X			maketrap(mtmp->mx, mtmp->my, PIERC);
X			mondead(mtmp);
X			return(1);
X		}
X	   }
X	return(0);
X}
X#endif
END_OF_mon.c
if test 19391 -ne `wc -c <mon.c`; then
    echo shar: \"mon.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f topten.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"topten.c\"
else
echo shar: Extracting \"topten.c\" \(11629 characters\)
sed "s/^X//" >topten.c <<'END_OF_topten.c'
X/*	SCCS Id: @(#)topten.c	2.1	87/09/28
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X
X#include <stdio.h>
X#include "hack.h"
X#ifdef GENIX
X#define	void	int	/* jhn - mod to prevent compiler from bombing */
X#endif
X
X#define	Sprintf	(void) sprintf
Xextern char plname[], pl_character[];
Xextern char *itoa(), *ordin(), *eos();
Xextern int done_hup, done_stopprint;
X
X#define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry))
X#define	NAMSZ	10
X#define	DTHSZ	60
X#define	PERSMAX	 3		/* entries per name/uid per char. allowed */
X#define	POINTSMIN	1	/* must be > 0 */
X#define	ENTRYMAX	100	/* must be >= 10 */
X#ifndef MSDOS
X#define	PERS_IS_UID		/* delete for PERSMAX per name; now per uid */
X#endif
Xstruct toptenentry {
X	struct toptenentry *tt_next;
X	long int points;
X	int level,maxlvl,hp,maxhp;
X	int uid;
X	char plchar;
X	char sex;
X	char name[NAMSZ+1];
X	char death[DTHSZ+1];
X	char date[7];		/* yymmdd */
X} *tt_head;
X
Xtopten(){
X	int uid = getuid();
X	int rank, rank0 = -1, rank1 = 0;
X	int occ_cnt = PERSMAX;
X	register struct toptenentry *t0, *t1, *tprev;
X	char *recfile = RECORD;
X#ifdef UNIX
X	char *reclock = "record_lock";
X#endif
X	int sleepct = 300;
X	FILE *rfile;
X	register flg = 0;
X	extern char *getdate();
X#ifndef DGK
X#define	HUP	if(!done_hup)
X#else
X#define HUP
X#endif
X#ifdef UNIX
X	while(link(recfile, reclock) == -1) {
X		HUP perror(reclock);
X		if(!sleepct--) {
X			HUP puts("I give up. Sorry.");
X			HUP puts("Perhaps there is an old record_lock around?");
X			return;
X		}
X		HUP printf("Waiting for access to record file. (%d)\n",
X			sleepct);
X		HUP (void) fflush(stdout);
X		sleep(1);
X	}
X#endif
X	if(!(rfile = fopen(recfile,"r"))){
X		HUP puts("Cannot open record file!");
X		goto unlock;
X	}
X	HUP (void) putchar('\n');
X
X	/* create a new 'topten' entry */
X	t0 = newttentry();
X	t0->level = dlevel;
X	t0->maxlvl = maxdlevel;
X	t0->hp = u.uhp;
X	t0->maxhp = u.uhpmax;
X	t0->points = u.urexp;
X	t0->plchar = pl_character[0];
X	t0->sex = (flags.female ? 'F' : 'M');
X	t0->uid = uid;
X	(void) strncpy(t0->name, plname, NAMSZ);
X	(t0->name)[NAMSZ] = 0;
X	(void) strncpy(t0->death, killer, DTHSZ);
X	(t0->death)[DTHSZ] = 0;
X	(void) strcpy(t0->date, getdate());
X
X	/* assure minimum number of points */
X	if(t0->points < POINTSMIN)
X		t0->points = 0;
X
X	t1 = tt_head = newttentry();
X	tprev = 0;
X	/* rank0: -1 undefined, 0 not_on_list, n n_th on list */
X	for(rank = 1; ; ) {
X	  if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
X		t1->date, &t1->uid,
X		&t1->level, &t1->maxlvl,
X		&t1->hp, &t1->maxhp, &t1->points,
X		&t1->plchar, &t1->sex, t1->name, t1->death) != 11
X	  || t1->points < POINTSMIN)
X			t1->points = 0;
X	  if(rank0 < 0 && t1->points < t0->points) {
X		rank0 = rank++;
X		if(tprev == 0)
X			tt_head = t0;
X		else
X			tprev->tt_next = t0;
X		t0->tt_next = t1;
X		occ_cnt--;
X		flg++;		/* ask for a rewrite */
X	  } else
X		tprev = t1;
X	  if(t1->points == 0) break;
X	  if(
X#ifdef PERS_IS_UID
X	     t1->uid == t0->uid &&
X#else
X	     strncmp(t1->name, t0->name, NAMSZ) == 0 &&
X#endif
X	     t1->plchar == t0->plchar && --occ_cnt <= 0){
X		if(rank0 < 0){
X			rank0 = 0;
X			rank1 = rank;
X	HUP printf("You didn't beat your previous score of %ld points.\n\n",
X				t1->points);
X		}
X		if(occ_cnt < 0){
X			flg++;
X			continue;
X		}
X	  }
X	  if(rank <= ENTRYMAX){
X		t1 = t1->tt_next = newttentry();
X		rank++;
X	  }
X	  if(rank > ENTRYMAX){
X		t1->points = 0;
X		break;
X	  }
X	}
X	if(flg) {	/* rewrite record file */
X		(void) fclose(rfile);
X		if(!(rfile = fopen(recfile,"w"))){
X			HUP puts("Cannot write record file\n");
X			goto unlock;
X		}
X
X		if(!done_stopprint) if(rank0 > 0){
X		    if(rank0 <= 10)
X			puts("You made the top ten list!\n");
X		    else
X		printf("You reached the %d%s place on the top %d list.\n\n",
X			rank0, ordin(rank0), ENTRYMAX);
X		}
X	}
X	if(rank0 == 0) rank0 = rank1;
X	if(rank0 <= 0) rank0 = rank;
X	if(!done_stopprint) outheader();
X	t1 = tt_head;
X	for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
X	  if(flg) fprintf(rfile,"%6s %d %d %d %d %d %ld %c%c %s,%s\n",
X	    t1->date, t1->uid,
X	    t1->level, t1->maxlvl,
X	    t1->hp, t1->maxhp, t1->points,
X	    t1->plchar, t1->sex, t1->name, t1->death);
X	  if(done_stopprint) continue;
X	  if(rank > flags.end_top &&
X	    (rank < rank0-flags.end_around || rank > rank0+flags.end_around)
X	    && (!flags.end_own ||
X#ifdef PERS_IS_UID
X				  t1->uid != t0->uid
X#else
X				  strncmp(t1->name, t0->name, NAMSZ)
X#endif
X		)) continue;
X	  if(rank == rank0-flags.end_around &&
X	     rank0 > flags.end_top+flags.end_around+1 &&
X	     !flags.end_own)
X		(void) putchar('\n');
X	  if(rank != rank0)
X		(void) outentry(rank, t1, 0);
X	  else if(!rank1)
X		(void) outentry(rank, t1, 1);
X	  else {
X		int t0lth = outentry(0, t0, -1);
X		int t1lth = outentry(rank, t1, t0lth);
X		if(t1lth > t0lth) t0lth = t1lth;
X		(void) outentry(0, t0, t0lth);
X	  }
X	}
X	if(rank0 >= rank) if(!done_stopprint)
X		(void) outentry(0, t0, 1);
X	(void) fclose(rfile);
Xunlock:	;
X#ifdef UNIX
X	(void) unlink(reclock);
X#endif
X}
X
Xoutheader() {
Xchar linebuf[BUFSZ];
Xregister char *bp;
X#ifdef KJSMODS
X	(void) strcpy(linebuf, " No  Points    Name");
X#else
X	(void) strcpy(linebuf, "Number Points  Name");
X#endif
X	bp = eos(linebuf);
X	while(bp < linebuf + COLNO - 9) *bp++ = ' ';
X	(void) strcpy(bp, "Hp [max]");
X	puts(linebuf);
X}
X
X/* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */
Xint
Xoutentry(rank,t1,so) register struct toptenentry *t1; {
Xboolean quit = FALSE, killed = FALSE, starv = FALSE;
Xchar linebuf[BUFSZ];
X	linebuf[0] = 0;
X	if(rank) Sprintf(eos(linebuf), "%3d", rank);
X		else Sprintf(eos(linebuf), "   ");
X#ifdef KJSMODS
X	Sprintf(eos(linebuf), " %7ld %10s", t1->points, t1->name);
X#else
X# ifdef DGKMOD
X	Sprintf(eos(linebuf), " %6ld %10s", t1->points, t1->name);
X# else
X	Sprintf(eos(linebuf), " %6ld %8s", t1->points, t1->name);
X# endif
X#endif
X	if(t1->plchar == 'X') Sprintf(eos(linebuf), " ");
X	else Sprintf(eos(linebuf), "-%c ", t1->plchar);
X	if(!strncmp("escaped", t1->death, 7)) {
X	  if(!strcmp(" (with amulet)", t1->death+7))
X	    Sprintf(eos(linebuf), "escaped the dungeon with amulet");
X	  else
X	    Sprintf(eos(linebuf), "escaped the dungeon [max level %d]",
X	      t1->maxlvl);
X	} else {
X	  if(!strncmp(t1->death,"quit",4)) {
X	    quit = TRUE;
X#ifndef KJSMODS
X	    if(t1->maxhp < 3*t1->hp && t1->maxlvl < 4)
X		Sprintf(eos(linebuf), "cravenly gave up");
X	    else
X#endif
X		Sprintf(eos(linebuf), "quit");
X	  }
X	  else if(!strcmp(t1->death,"choked"))
X	    Sprintf(eos(linebuf), "choked on %s food",
X		(t1->sex == 'F') ? "her" : "his");
X	  else if(!strncmp(t1->death,"starv",5))
X	    Sprintf(eos(linebuf), "starved to death"), starv = TRUE;
X	  else Sprintf(eos(linebuf), "was killed"), killed = TRUE;
X	  Sprintf(eos(linebuf), " on%s level %d",
X	    (killed || starv) ? "" : " dungeon", t1->level);
X	  if(t1->maxlvl != t1->level)
X	    Sprintf(eos(linebuf), " [max %d]", t1->maxlvl);
X	  if(quit && t1->death[4]) Sprintf(eos(linebuf), t1->death + 4);
X	}
X	if(killed) Sprintf(eos(linebuf), " by %s%s",
X	  (!strncmp(t1->death, "trick", 5) || !strncmp(t1->death, "the ", 4))
X		? "" :
X	  index(vowels,*t1->death) ? "an " : "a ",
X	  t1->death);
X	Sprintf(eos(linebuf), ".");
X	if(t1->maxhp) {
X	  register char *bp = eos(linebuf);
X	  char hpbuf[10];
X	  int hppos;
X#ifdef KJSMODS
X	  int lngr = strlen(linebuf);
X#endif
X	  Sprintf(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-");
X	  hppos = COLNO - 7 - strlen(hpbuf);
X#ifdef KJSMODS
X	  if (lngr >= hppos) hppos = (2*COLNO) - 7 - strlen(hpbuf);
X#endif
X	  if(bp <= linebuf + hppos) {
X	    /* pad any necessary blanks to the hit point entry */
X	    while(bp < linebuf + hppos) *bp++ = ' ';
X	    (void) strcpy(bp, hpbuf);
X	    Sprintf(eos(bp), " [%d]", t1->maxhp);
X	  }
X	}
X	if(so == 0) puts(linebuf);
X	else if(so > 0) {
X	  register char *bp = eos(linebuf);
X	  if(so >= COLNO) so = COLNO-1;
X	  while(bp < linebuf + so) *bp++ = ' ';
X	  *bp = 0;
X	  standoutbeg();
X	  fputs(linebuf,stdout);
X	  standoutend();
X	  (void) putchar('\n');
X	}
X	return(strlen(linebuf));
X}
X
Xchar *
Xitoa(a) int a; {
Xstatic char buf[12];
X	Sprintf(buf,"%d",a);
X	return(buf);
X}
X
Xchar *
Xordin(n) int n; {
Xregister int d = n%10;
X	return((d==0 || d>3 || n/10==1) ? "th" : (d==1) ? "st" :
X		(d==2) ? "nd" : "rd");
X}
X
Xchar *
Xeos(s)
Xregister char *s;
X{
X	while(*s) s++;
X	return(s);
X}
X
X/*
X * Called with args from main if argc >= 0. In this case, list scores as
X * requested. Otherwise, find scores for the current player (and list them
X * if argc == -1).
X */
Xprscore(argc,argv) int argc; char **argv; {
X	extern char *hname;
X	char **players;
X	int playerct;
X	int rank;
X	register struct toptenentry *t1, *t2;
X	char *recfile = RECORD;
X	FILE *rfile;
X	register flg = 0;
X	register int i;
X#ifdef nonsense
X	long total_score = 0L;
X	char totchars[10];
X	int totcharct = 0;
X#endif
X	int outflg = (argc >= -1);
X#ifdef PERS_IS_UID
X	int uid = -1;
X#else
X	char *player0;
X#endif
X
X	if(!(rfile = fopen(recfile,"r"))){
X		puts("Cannot open record file!");
X		return;
X	}
X
X	if(argc > 1 && !strncmp(argv[1], "-s", 2)){
X		if(!argv[1][2]){
X			argc--;
X			argv++;
X		} else if(!argv[1][3] && index("CFKSTWX", argv[1][2])) {
X			argv[1]++;
X			argv[1][0] = '-';
X		} else	argv[1] += 2;
X	}
X	if(argc <= 1){
X#ifdef PERS_IS_UID
X		uid = getuid();
X		playerct = 0;
X#else
X		player0 = plname;
X		if(!*player0)
X			player0 = "hackplayer";
X		playerct = 1;
X		players = &player0;
X#endif
X	} else {
X		playerct = --argc;
X		players = ++argv;
X	}
X	if(outflg) putchar('\n');
X
X	t1 = tt_head = newttentry();
X	for(rank = 1; ; rank++) {
X	  if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
X		t1->date, &t1->uid,
X		&t1->level, &t1->maxlvl,
X		&t1->hp, &t1->maxhp, &t1->points,
X		&t1->plchar, &t1->sex, t1->name, t1->death) != 11)
X			t1->points = 0;
X	  if(t1->points == 0) break;
X#ifdef PERS_IS_UID
X	  if(!playerct && t1->uid == uid)
X		flg++;
X	  else
X#endif
X	  for(i = 0; i < playerct; i++){
X		if(strcmp(players[i], "all") == 0 ||
X		   strncmp(t1->name, players[i], NAMSZ) == 0 ||
X		  (players[i][0] == '-' &&
X		   players[i][1] == t1->plchar &&
X		   players[i][2] == 0) ||
X		  (digit(players[i][0]) && rank <= atoi(players[i])))
X			flg++;
X	  }
X	  t1 = t1->tt_next = newttentry();
X	}
X	(void) fclose(rfile);
X	if(!flg) {
X	    if(outflg) {
X		printf("Cannot find any entries for ");
X		if(playerct < 1) printf("you.\n");
X		else {
X		  if(playerct > 1) printf("any of ");
X		  for(i=0; i<playerct; i++)
X			printf("%s%s", players[i], (i<playerct-1)?", ":".\n");
X		  printf("Call is: %s -s [playernames]\n", hname);
X		}
X	    }
X	    return;
X	}
X
X	if(outflg) outheader();
X	t1 = tt_head;
X	for(rank = 1; t1->points != 0; rank++, t1 = t2) {
X		t2 = t1->tt_next;
X#ifdef PERS_IS_UID
X		if(!playerct && t1->uid == uid)
X			goto outwithit;
X		else
X#endif
X		for(i = 0; i < playerct; i++){
X			if(strcmp(players[i], "all") == 0 ||
X			   strncmp(t1->name, players[i], NAMSZ) == 0 ||
X			  (players[i][0] == '-' &&
X			   players[i][1] == t1->plchar &&
X			   players[i][2] == 0) ||
X			  (digit(players[i][0]) && rank <= atoi(players[i]))){
X			outwithit:
X				if(outflg)
X				    (void) outentry(rank, t1, 0);
X#ifdef nonsense
X				total_score += t1->points;
X				if(totcharct < sizeof(totchars)-1)
X				    totchars[totcharct++] = t1->plchar;
X#endif
X				break;
X			}
X		}
X		free((char *) t1);
X	}
X#ifdef nonsense
X	totchars[totcharct] = 0;
X
X	/* We would like to determine whether he is experienced. However,
X	   the information collected here only tells about the scores/roles
X	   that got into the topten (top 100?). We should maintain a
X	   .hacklog or something in his home directory. */
X	flags.beginner = (total_score < 6000);
X	for(i=0; i<6; i++)
X	    if(!index(totchars, "CFKSTWX"[i])) {
X		flags.beginner = 1;
X		if(!pl_character[0]) pl_character[0] = "CFKSTWX"[i];
X		break;
X	}
X#endif /* nonsense /**/
X}
END_OF_topten.c
if test 11629 -ne `wc -c <topten.c`; then
    echo shar: \"topten.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 7 \(of 20\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 20 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