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