billr@saab.CNA.TEK.COM (Bill Randle) (07/06/89)
Submitted-by: "Philip A. Cordier" <philc@sco.COM> Posting-number: Volume 7, Issue 2 Archive-name: ularn/Part02 #! /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 2 (of 8)." # Contents: monster.c signal.c # Wrapped by billr@saab on Thu Jun 29 08:10:17 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'monster.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'monster.c'\" else echo shar: Extracting \"'monster.c'\" \(46657 characters\) sed "s/^X//" >'monster.c' <<'END_OF_FILE' X/* X * monster.c X * X * This file contains the following functions: X * ------------------------------------------------------------------------ X * X * createmonster(monstno) Function to create a monster next to the player X * int monstno; X * X * int cgood(x,y,itm,monst) Function to check location for emptiness X * int x,y,itm,monst; X * X * createitem(it,arg) Routine to place an item next to the player X * int it,arg; X * X * cast() Subroutine called by parse to cast a spell for the user X * X * speldamage(x) Function to perform spell functions cast by the player X * int x; X * X * loseint() Routine to decrement your int (intelligence) if > 3 X * X * isconfuse() Routine to check to see if player is confused X * X * nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster X * int x,monst; X * X * fullhit(xx) Function to return full damage against a monst (aka web) X * int xx; X * X * Routine to direct spell damage 1 square in 1 dir X * direct(spnum,dam,str,arg) X * int spnum,dam,arg; X * char *str; X * X * Function to perform missile attacks X * godirect(spnum,dam,str,delay,cshow) X * int spnum,dam,delay; X * char *str,cshow; X * X * Routine to put "monster" or the monster name into lastmosnt X * ifblind(x,y) X * int x,y; X * X * tdirect(spnum) Routine to teleport away a monster X * int spnum; X * X * Routine to damage all monsters 1 square from player X * omnidirect(sp,dam,str) X * int sp,dam; X * char *str; X * X * dirsub(x,y) Routine to ask for direction, then modify x,y for it X * int *x,*y; X * X * vxy(x,y) Routine to verify/fix (*x,*y) for being within bounds X * int *x,*y; X * X * dirpoly(spnum) Routine to ask for a direction and polymorph a monst X * int spnum; X * X * hitmonster(x,y) Function to hit a monster at the designated coordinates X * int x,y; X * X * hitm(x,y,amt) Function to just hit a monster at a given coordinates X * int x,y,amt; X * X * hitplayer(x,y) Function for the monster to hit the player from (x,y) X * int x,y; X * X * dropsomething(monst) Function to create an object when a monster dies X * int monst; X * X * dropgold(amount) Function to drop some gold around player X * int amount; X * X * something(level) Function to create a random item around player X * int level; X * X * newobject(lev,i) Routine to return a randomly selected new object X * int lev,*i; X * X * spattack(atckno,xx,yy) Function to process special attacks from monsters X * int atckno,xx,yy; X * X * Routine to subtract hp from user and flag bottomline display X * checkloss(x) X * int x; X * X * Routine to annihilate monsters around player, playerx,playery X * annihilate() X * X * Function to create a new sphere of annihilation X * newsphere(x,y,dir,lifetime) X * int x,y,dir,lifetime; X * X * rmsphere(x,y) Function to delete a sphere of annihilation from list X * int x,y; X * X * sphboom(x,y) Function to perform the effects of a sphere detonation X * int x,y; X * X * genmonst() Function to ask for monster and genocide from game X * X */ X#include "header.h" X Xstruct isave /* used for altar reality */ X{ X char type; /* 0=item, 1=monster */ X char id; /* item number or monster number */ X short arg; /* the type of item or hitpoints of monster */ X}; X X/* X * Function to create a monster next to the player X * createmonster(monstno) X * int monstno; X * X * Enter with the monster number (1 to MAXMONST+8) X * Returns no value. X */ Xcreatemonster(mon) Xint mon; X{ X register int x,y,k,i; X if (mon<1 || mon>MAXMONST+8) { X beep(); X lprintf("\ncan't createmonst(%d)\n",(long)mon); X nap(3000); X return; X } X while (monster[mon].genocided && mon<MAXMONST) X mon++; /* genocided? */ X for (k=rnd(8), i= -8; i<0; i++,k++)/* choose direction, then try all */ X { X if (k>8) k=1; /* wraparound the diroff arrays */ X x = playerx + diroffx[k]; X y = playery + diroffy[k]; X if (cgood(x,y,0,1)) /* if we can create here */ X { X mitem[x][y] = mon; X hitp[x][y] = monster[mon].hitpoints; X stealth[x][y]=know[x][y]=0; X switch(mon) { X case ROTHE: X case POLTERGEIST: X case VAMPIRE: X stealth[x][y]=1; X }; X return; X } X } X} X X/* X * int cgood(x,y,itm,monst) Function to check location for emptiness X * int x,y,itm,monst; X * X * Routine to return TRUE if a location does not have itm or monst there X * returns FALSE (0) otherwise X * Enter with itm or monst TRUE or FALSE if checking it X * Example: if itm==TRUE check for no item at this location X * if monst==TRUE check for no monster at this location X * This routine will return FALSE if at a wall or the dungeon exit on level 1 X */ Xcgood(x,y,itm,monst) Xregister int x,y; Xint itm,monst; X{ X if ((y>=0) && (y<=MAXY-1) X && (x>=0) && (x<=MAXX-1)) /* within bounds? */ X if (item[x][y]!=OWALL) /* can't make on walls */ X if (itm==0 || (item[x][y]==0)) /* is it free of items? */ X if (monst==0 || (mitem[x][y]==0)) /*is it free of monsters? */ X if ((level!=1) || (x!=33) || (y!=MAXY-1)) X /* not exit to level 1 */ X return(1); X return(0); X} X X/* X * createitem(it,arg) Routine to place an item next to the player X * int it,arg; X * X * Enter with the item number and its argument (iven[], ivenarg[]) X * Returns no value, thus we don't know about createitem() failures. X */ Xcreateitem(it,arg) Xint it; Xlong arg; X{ X register int x,y,k,i; X X if (it >= MAXOBJ) X return; /* no such object */ X X for (k=rnd(8), i= -8; i<0; i++,k++) { /* choose direction, try all */ X if (k>8) k=1; /* wraparound the diroff arrays */ X x = playerx + diroffx[k]; X y = playery + diroffy[k]; X if ( (it != OMAXGOLD && it != OGOLDPILE) ) { X if (cgood(x,y,1,0)) { /* if we can create here */ X item[x][y] = it; X know[x][y]=0; X iarg[x][y]=arg; X return; X } X } X else { X int i; X switch (item[x][y]) { X case OGOLDPILE : X if ( (iarg[x][y] + arg) < 32767) { X iarg[x][y] += arg; X return; X } X case ODGOLD : X if ( (10 * iarg[x][y] + arg) < 327670L) { X i = iarg[x][y] ; X iarg[x][y] = (10 * i + arg) / 10; X item[x][y] = ODGOLD; X return; X } X case OMAXGOLD : X if ( (100 * iarg[x][y] + arg) < 3276700L) { X i = (100 * iarg[x][y]) + arg; X iarg[x][y] = i / 100; X item[x][y] = OMAXGOLD; X return; X } X case OKGOLD : X if ( (1000 * iarg[x][y] + arg) < 32767000L) { X i = iarg[x][y]; X iarg[x][y] = (1000 * i + arg) / 1000; X item[x][y] = OKGOLD; X return; X } X else iarg[x][y] = 32767000L; X return; X default : X if (cgood(x,y,1,0)) { X item[x][y] = it; X know[x][y]=0; X if (it == OMAXGOLD) X iarg[x][y]= arg / 100; X else iarg[x][y]=arg; X return; X } X } /* end switch */ X } /* end else */ X } /* end for */ X} X X/* X * cast() Subroutine called by parse to cast a spell for the user X * X * No arguments and no return value. X */ Xstatic char eys[] = "\nEnter your spell: "; X Xcast() X{ X register int i,j,a,b,d; X X cursors(); X if (c[SPELLS]<=0) { X lprcat("\nYou don't have any spells!"); X return; X } X lprcat(eys); X --c[SPELLS]; X while ((a=getcharacter())=='D') { X seemagic(-1); X cursors(); X lprcat(eys); X } X if (a=='\33') goto over; /* to escape casting a spell */ X if ((b=getcharacter())=='\33') goto over; /*to escape casting a spell */ X if ((d=getcharacter())=='\33') { Xover: X lprcat(aborted); X c[SPELLS]++; X return; X } /* to escape casting a spell */ X /*seq search for his spell, hash?*/ X for (lprc('\n'),j= -1,i=0; i<SPNUM+1; i++) X if ((spelcode[i][0]==a) && (spelcode[i][1]==b) && (spelcode[i][2]==d)) X if (spelknow[i]) { X speldamage(i); X j = 1; X i=SPNUM+1; X } X X if (j == -1) lprcat(" Nothing Happened "); X bottomline(); X} X X/* X * speldamage(x) Function to perform spell functions cast by the player X * int x; X * X * Enter with the spell number, returns no value. X * Please insure that there are 2 spaces before all messages here X */ Xspeldamage(x) Xint x; X{ X register int i,j,clev; X int xl,xh,yl,yh; X register char *p,*kn,*pm; X X if (x>=SPNUM+1) return; /* no such spell */ X X if (c[TIMESTOP]) { X lprcat(" It didn't seem to work"); X return; X } /* not if time stopped */ X X if ((rnd(23)==7) || (rnd(18) > c[INTELLIGENCE])) X { X lprcat(" It didn't work!"); X return; X } X X clev = c[LEVEL]; X if (clev*3+2 < x) X { X lprcat(" Nothing happens. You seem inexperienced at this"); X return; X } X X switch(x) X { X /* ----- LEVEL 1 SPELLS ----- */ X X case 0: X if (c[PROTECTIONTIME]==0) X c[MOREDEFENSES]+=2; /* protection field +2 */ X c[PROTECTIONTIME] += 250; X return; X X case 1: X i = rnd(((clev+1)<<1)) + clev + 3; X godirect(x,i,(clev>=2)?" Your missiles hit the %s":" Your missile hit the %s",100,'+'); /* magic missile */ X return; X X case 2: X if (c[DEXCOUNT]==0) X c[DEXTERITY]+=3; /* dexterity */ X c[DEXCOUNT] += 400; X return; X X case 3: X i=rnd(3)+1; X p=" While the %s slept, you smashed it %d times"; Xws: X direct(x,fullhit(i),p,i); /* sleep */ X return; X X case 4: /* charm monster */ X X c[CHARMCOUNT] += c[CHARISMA]<<1; X return; X X /* sonic spear */ X case 5: X godirect(x,rnd(10)+15+clev," The sound damages the %s",70,'@'); X return; X X /* ----- LEVEL 2 SPELLS ----- */ X X case 6: X i=rnd(3)+2; X p=" While the %s is entangled, you hit %d times"; X goto ws; /* web */ X X case 7: X if (c[STRCOUNT]==0) c[STREXTRA]+=3;/* strength*/ X c[STRCOUNT] += 150+rnd(100); X return; X X case 8: X yl = playery-5; /* enlightenment */ X yh = playery+6; X xl = playerx-15; X xh = playerx+16; X vxy(&xl,&yl); X vxy(&xh,&yh); /* check bounds */ X for (i=yl; i<=yh; i++) /* enlightenment */ X for (j=xl; j<=xh; j++) know[j][i]=1; X draws(xl,xh+1,yl,yh+1); X return; X X case 9: X raisehp(20+(clev<<1)); X return; /* healing */ X X case 10: X c[BLINDCOUNT]=0; X return; /* cure blindness */ X X case 11: X createmonster(makemonst(level+1)+8); X return; X X case 12: X if (rnd(11)+7 <= c[WISDOM]) X direct(x,rnd(20)+20+clev," The %s believed!",0); X else X lprcat(" It didn't believe the illusions!"); X return; X X /* if he has the amulet of invisibility then add more time */ X case 13: X for (j=i=0; i<26; i++) X if (iven[i]==OAMULET) X j+= 1+ivenarg[i]; X c[INVISIBILITY] += (j<<7)+12; X return; X X /* ----- LEVEL 3 SPELLS ----- */ X X case 14: X godirect(x,rnd(25+clev)+25+clev," The fireball hits the %s",40,'*'); X return; /* fireball */ X X case 15: X godirect(x,rnd(25)+20+clev," Your cone of cold strikes the %s",60,'O'); /* cold */ X return; X X case 16: X dirpoly(x); X return; /* polymorph */ X X case 17: X c[CANCELLATION]+= 5+clev; X return; /* cancellation */ X X case 18: X c[HASTESELF]+= 7+clev; X return; /* haste self */ X X /* cloud kill */ X case 19: X omnidirect(x,30+rnd(10)," The %s gasps for air"); X return; X X /* vaporize rock */ X case 20: X xh = min(playerx+1,MAXX-2); X yh = min(playery+1,MAXY-2); X for (i=max(playerx-1,1); i<=xh; i++) X for (j=max(playery-1,1); j<=yh; j++) { X kn = &know[i][j]; X pm = &mitem[i][j]; X switch(*(p= &item[i][j])) { X case OWALL: X if (level<MAXLEVEL+MAXVLEVEL-3) X *p = *kn = 0; X break; X X case OSTATUE: X if (c[HARDGAME]>3 && rnd(60)<30) X break; X *p=OBOOK; X iarg[i][j]=level; X *kn=0; X break; X X case OTHRONE: X *pm=GNOMEKING; X *kn=0; X *p= OTHRONE2; X hitp[i][j]=monster[GNOMEKING].hitpoints; X break; X X case OALTAR: X *pm=DEMONPRINCE; X *kn=0; X hitp[i][j]=monster[DEMONPRINCE].hitpoints; X createmonster(DEMONPRINCE); X createmonster(DEMONPRINCE); X createmonster(DEMONPRINCE); X createmonster(DEMONPRINCE); X break; X }; X switch(*pm) X { /* Xorn takes damage from vpr */ X case XORN: X ifblind(i,j); X hitm(i,j,200); X break; X case TROLL: X ifblind(i,j); X hitm(i,j,200); X break; X } X } X return; X X /* ----- LEVEL 4 SPELLS ----- */ X X case 21:/* dehydration */ X X direct(x,100+clev," The %s shrivels up",0); X return; X X case 22: /* lightning */ X godirect(x,rnd(25)+20+(clev<<1)," A lightning bolt hits the %s",1,'~'); X return; X X case 23: X i=min(c[HP]-1,c[HPMAX]/2); /* drain life */ X direct(x,i+i,"",0); X c[HP] -= i; X return; X X case 24: X if (c[GLOBE]==0) c[MOREDEFENSES] += 10; X c[GLOBE] += 200; X loseint(); /* globe of invulnerability */ X return; X X case 25: X omnidirect(x,32+clev," The %s struggles for air in your flood!"); /* flood */ X return; X X /* finger of death */ X case 26: X if (rnd(151)==63) { X beep(); X lprcat("\nYour heart stopped!\n"); X nap(4000); X died(270); X return; X } X if (c[WISDOM]>rnd(10)+10) direct(x,2000," The %s's heart stopped",0); X else lprcat(" It didn't work"); X return; X X /* ----- LEVEL 5 SPELLS ----- */ X X /* scare monster */ X case 27: X c[SCAREMONST] += rnd(10)+clev; X X /* if have HANDofFEAR make last longer */ X for (j=i=0; i<26; i++) X if (iven[i]==OHANDofFEAR) { X c[SCAREMONST] *= 3; X break; X } X return; X X case 28: X c[HOLDMONST] += rnd(10)+clev; X return; /* hold monster */ X X case 29: X c[TIMESTOP] += rnd(20)+(clev<<1); X return; /* time stop */ X X case 30: X tdirect(x); X return; /* teleport away */ X X /* magic fire */ X case 31: X omnidirect(x,35+rnd(10)+clev," The %s cringes from the flame"); X return; X X /* ----- LEVEL 6 SPELLS ----- */ X X case 32: /* make wall */ X makewall(x); X return; X X /* sphere of annihilation */ X case 33: X if ((rnd(23)==5) && (wizard==0)) X { X beep(); X lprcat("\nYou have been enveloped by the zone of nothingness!\n"); X nap(4000); X died(258); X return; X } X xl=playerx; X yl=playery; X loseint(); X i=dirsub(&xl,&yl); /* get direction of sphere */ X newsphere(xl,yl,i,rnd(20)+11);/*make a sphere */ X return; X X case 34: X genmonst(); X spelknow[34]=0; /* genocide */ X loseint(); X return; X X case 35:/* summon demon */ X if (rnd(100) > 30) { X direct(x-1,150," The demon strikes at the %s",0); X return; X } X if (rnd(100) > 15) { X lprcat(" Nothing seems to have happened"); X return; X } X lprcat(" The demon turned on you and vanished!"); X beep(); X i=rnd(40)+30; X lastnum=277; X losehp(i); /* must say killed by a demon */ X X return; X X case 36:/* walk through walls */ X c[WTW] += rnd(10)+5; X return; X X case 37:/* alter reality */ X { X struct isave *save; X /* pointer to item save structure */ X int sc; X sc=0; /* # items saved */ X save = (struct isave *)malloc(sizeof(struct isave)*MAXX*MAXY*2); X for (j=0; j<MAXY; j++)/* save all items and monsters */ X for (i=0; i<MAXX; i++) X { X xl = item[i][j]; X if (xl && xl!=OWALL && xl!=OANNIHILATION) X { X save[sc].type=0; X save[sc].id=item[i][j]; X save[sc++].arg=iarg[i][j]; X } X if (mitem[i][j]) X { X save[sc].type=1; X save[sc].id=mitem[i][j]; X save[sc++].arg=hitp[i][j]; X } X item[i][j]=OWALL; X mitem[i][j]=0; X if (wizard) know[i][j]=1; X else know[i][j]=0; X } X eat(1,1); X if (level==1) item[33][MAXY-1]=0; X for (j=rnd(MAXY-2), i=1; i<MAXX-1; i++) item[i][j]=0; X while (sc>0) /* put objects back in level */ X { X --sc; X if (save[sc].type == 0) X { X int trys; X for (trys=100, i=j=1; --trys>0 && item[i][j]; i=rnd(MAXX-1), j=rnd(MAXY-1)); X if (trys) { X item[i][j]=save[sc].id; X iarg[i][j]=save[sc].arg; X } X } X else X { /* put monsters back in */ X int trys; X for (trys=100, i=j=1; --trys>0 && (item[i][j]==OWALL || mitem[i][j]); i=rnd(MAXX-1), j=rnd(MAXY-1)); X if (trys) { X mitem[i][j]=save[sc].id; X hitp[i][j]=save[sc].arg; X } X } X } X loseint(); X draws(0,MAXX,0,MAXY); X if (wizard==0) spelknow[37]=0; X free((char*)save); X positionplayer(); X return; X } X X case 38: /* permanence */ X X adjtime(-99999L); X spelknow[38]=0; /* forget */ X loseint(); X return; X X default: X lprintf(" spell %d not available!",(long)x); X beep(); X return; X }; X} X X/* X * loseint() X * Routine to subtract 1 from your int (intelligence) if > 3 X * X * No arguments and no return value X */ Xloseint() X{ X if (--c[INTELLIGENCE]<3) c[INTELLIGENCE]=3; X} X X/* X * isconfuse() Routine to check to see if player is confused X * X * This routine prints out a message saying "You can't aim your magic!" X * returns 0 if not confused, non-zero (time remaining confused) X * if confused X */ Xisconfuse() X{ X if (c[CONFUSE]) { X lprcat(" You can't aim your magic!"); X beep(); X } X return(c[CONFUSE]); X} X X/* Routine to return 1 if a spell doesn't affect a monster X * nospell(x,monst) X * int x,monst; X * X * Subroutine to return 1 if the spell can't affect the monster X * otherwise returns 0 X * Enter with the spell number in x, and the monster number in monst. X */ Xnospell(x,monst) Xint x,monst; X{ X register int tmp; X X /* bad spell or monst */ X if (x>=SPNUM || monst>MAXMONST+8 || monst<0 || x<0) return(0); X X if ((tmp=spelweird[monst-1][x])==0) X return(0); X cursors(); X lprc('\n'); X lprintf(spelmes[tmp],monster[monst].name); X return(1); X} X X/* X * Function to return full damage against a monster (aka web) X * fullhit(xx) X * int xx; X * X * Function to return hp damage to monster due to a number of full hits X * Enter with the number of full hits being done X */ Xfullhit(xx) Xint xx; X{ X register int i; X X if (xx<0 || xx>20) return(0); /* fullhits are out of range */ X if (c[LANCEDEATH]) return(10000); /* lance of death */ X Xi = xx * ((c[WCLASS]>>1)+c[STRENGTH]+c[STREXTRA]-c[HARDGAME]-12+c[MOREDAM]); X X return( (i>=1) ? i : xx ); X} X X/* X * Routine to direct spell damage 1 square in 1 dir X * direct(spnum,dam,str,arg) X * int spnum,dam,arg; X * char *str; X * X * Routine to ask for a direction to a spell and then hit the monster X * Enter with the spell number in spnum, the damage to be done in dam, X * lprintf format string in str, and lprintf's argument in arg. X * Returns no value. X */ Xdirect(spnum,dam,str,arg) Xint spnum,dam,arg; Xchar *str; X{ X int x,y; X register int m; X if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad arguments */ X if (isconfuse()) return; X dirsub(&x,&y); X m = mitem[x][y]; X if (item[x][y]==OMIRROR) { X if (spnum==3) /* sleep */ X { X lprcat("You fall asleep! "); X beep(); Xfool: X arg += 2; X while (arg-- > 0) { X parse2(); X nap(1000); X } X return; X } X else if (spnum==6) /* web */ X { X lprcat("You get stuck in your own web! "); X beep(); X goto fool; X } X else { X lastnum=278; X lprintf(str,"spell caster (thats you)",(long)arg); X beep(); X losehp(dam); X return; X } X } X if (m==0) { X lprcat(" There wasn't anything there!"); X return; X } X ifblind(x,y); X if (nospell(spnum,m)) { X lasthx=x; X lasthy=y; X return; X } X lprintf(str,lastmonst,(long)arg); X hitm(x,y,dam); X} X X/* X * Function to perform missile attacks X * godirect(spnum,dam,str,delay,cshow) X * int spnum,dam,delay; X * char *str,cshow; X * X * Function to hit in a direction from a missile weapon and have it keep X * on going in that direction until its power is exhausted X * Enter with the spell number in spnum, the power of the weapon in hp, X * lprintf format string in str, the # of milliseconds to delay between X * locations in delay, and the character to represent the weapon in cshow. X * Returns no value. X */ Xgodirect(spnum,dam,str,delay,cshow) Xint spnum,dam,delay; Xchar *str,cshow; X{ X register char *p; X register int x,y,m; X int dx,dy; X X if (spnum<0 || spnum>=SPNUM || str==0 || delay<0) return; /* bad args */ X X if (isconfuse()) return; X X dirsub(&dx,&dy); X x=dx; X y=dy; X dx = x-playerx; X dy = y-playery; X x = playerx; X y = playery; X X while (dam>0) { X x += dx; X y += dy; X if ((x > MAXX-1) || (y > MAXY-1) || (x < 0) || (y < 0)) { X dam=0; X break; /* out of bounds */ X } X if ((x==playerx) && (y==playery)) /* if energy hits player */ X { X cursors(); X lprcat("\nYou are hit my your own magic!"); X beep(); X lastnum=278; X losehp(dam); X return; X } X if (c[BLINDCOUNT]==0) /* if not blind show effect */ X { X cursor(x+1,y+1); X lprc(cshow); X nap(delay); X show1cell(x,y); X } X if ((m=mitem[x][y])) /* is there a monster there? */ X { X ifblind(x,y); X if (m == LUCIFER || (m>=DEMONLORD && rnd(100)<10) ) { X dx *= -1; X dy *= -1; X cursors(); X lprc('\n'); X lprintf("\nthe %s returns your puny missile!", monster[m].name); X } X else { X if (nospell(spnum,m)) { X lasthx=x; X lasthy=y; X return; X } X cursors(); X lprc('\n'); X lprintf(str,lastmonst); X dam -= hitm(x,y,dam); X show1cell(x,y); X nap(1000); X x -= dx; X y -= dy; X } X } X else switch (*(p= &item[x][y])) { X case OWALL: X cursors(); X lprc('\n'); X lprintf(str,"wall"); X if (dam>=50+c[HARDGAME]) /* enough damage? */ X if (level<MAXLEVEL+MAXVLEVEL-3) /* not on V3 */ X if ((x<MAXX-1) && (y<MAXY-1) && (x) && (y)) X { X lprcat(" The wall crumbles"); Xgod3: X *p=0; Xgod: X know[x][y]=0; X show1cell(x,y); X } Xgod2: X dam = 0; X break; X X case OCLOSEDDOOR: X cursors(); X lprc('\n'); X lprintf(str,"door"); X if (dam>=40) { X lprcat(" The door is blasted apart"); X goto god3; X } X goto god2; X X case OSTATUE: X cursors(); X lprc('\n'); X lprintf(str,"statue"); X if (dam>44) { X if (c[HARDGAME] > 3 && rnd(60)<30) X goto god2; X lprcat(" The statue crumbles"); X *p=OBOOK; X iarg[x][y]=level; X goto god; X } X goto god2; X X case OTHRONE: X cursors(); X lprc('\n'); X lprintf(str,"throne"); X if (dam>33) { X mitem[x][y]=GNOMEKING; X hitp[x][y]=monster[GNOMEKING].hitpoints; X *p = OTHRONE2; X goto god; X } X goto god2; X X case OMIRROR: X dx *= -1; X dy *= -1; X break; X }; X dam -= 3 + (c[HARDGAME]>>1); X } X} X X/* X * Routine to put "monster" or the monster name into lastmosnt X * ifblind(x,y) X * int x,y; X * X * Subroutine to copy the word "monster" into lastmonst if the player is X * blind. Enter with the coordinates (x,y) of the monster X * Returns no value. X */ Xifblind(x,y) Xint x,y; X{ X char *p; X vxy(&x,&y); /* verify correct x,y coordinates */ X if (c[BLINDCOUNT]) { X lastnum=279; X p="monster"; X } X else { X lastnum=mitem[x][y]; X p=monster[lastnum].name; X } X strcpy(lastmonst,p); X} X X/* X * tdirect(spnum) Routine to teleport away a monster X * int spnum; X * X * Routine to ask for a direction to a spell and then teleport away monster X * Enter with the spell number that wants to teleport away X * Returns no value. X */ Xtdirect(spnum) Xint spnum; X{ X int x,y; X register int m; X X if (spnum<0 || spnum>=SPNUM) return; /* bad args */ X if (isconfuse()) return; X dirsub(&x,&y); X if ((m=mitem[x][y])==0) X { X lprcat(" There wasn't anything there!"); X return; X } X ifblind(x,y); X if (nospell(spnum,m)) { X lasthx=x; X lasthy=y; X return; X } X fillmonst(m); X mitem[x][y]=know[x][y]=0; X} X X Xmakewall(spnum) Xint spnum; X{ X int x,y; X X if (spnum<0 || spnum>=SPNUM) return; /* bad args */ X if (isconfuse()) return; X dirsub(&x,&y); X X if ((y>=0) && (y<=MAXY-1) && (x>=0) && (x<=MAXX-1)) /* within bounds? */ X if (item[x][y]!=OWALL) { /* can't make anything on walls */ X if (item[x][y]==0){ /* is it free of items? */ X if (mitem[x][y]==0){ /*is it free of monsters? */ X if ((level!=1) || (x!=33) || (y!=MAXY-1)) { X item[x][y]=OWALL; X know[x][y]=1; X show1cell(x,y); X } X else lprcat("\nyou can't make a wall there!"); X } X else lprcat("\nthere's a monster there!"); X } X else lprcat("\nthere's something there already!"); X } X else lprcat("\nthere's a wall there already!"); X X} X X/* X * omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player X * int sp,dam; X * char *str; X * X * Routine to cast a spell and then hit the monster in all directions X * Enter with the spell number in sp, the damage done to wach square in dam, X * and the lprintf string to identify the spell in str. X * Returns no value. X */ Xomnidirect(spnum,dam,str) Xint spnum,dam; Xchar *str; X{ X register int x,y,m; X if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad args */ X for (x=playerx-1; x<playerx+2; x++) X for (y=playery-1; y<playery+2; y++) X { X if (m=mitem[x][y]) X if (nospell(spnum,m) == 0) X { X ifblind(x,y); X cursors(); X lprc('\n'); X lprintf(str,lastmonst); X hitm(x,y,dam); X nap(800); X } X else { X lasthx=x; X lasthy=y; X } X } X} X X/* X * Routine to ask for direction, then modify x,y for it X * static dirsub(x,y) X * int *x,*y; X * X * Function to ask for a direction and modify an x,y for that direction X * Enter with the origination coordinates in (x,y). X * Returns index into diroffx[] (0-8). X */ Xdirsub(x,y) Xint *x,*y; X{ X register int i; X lprcat("\nIn What Direction? "); X for (i=0; ; ) X switch(getcharacter()) X { X case 'b': X i++; X case 'n': X i++; X case 'y': X i++; X case 'u': X i++; X case 'h': X i++; X case 'k': X i++; X case 'l': X i++; X case 'j': X i++; X goto out; X }; Xout: X *x = playerx+diroffx[i]; X *y = playery+diroffy[i]; X vxy(x,y); X return(i); X} X X/* X * vxy(x,y) Routine to verify/fix coordinates for being within bounds X * int *x,*y; X * X * Function to verify x & y are within the bounds for a level X * If *x or *y is not within the absolute bounds for a level, fix them so that X * they are on the level. X * Returns TRUE if it was out of bounds, and the *x & *y in the calling X * routine are affected. X */ Xvxy(x,y) Xint *x,*y; X{ X int flag=0; X if (*x<0) { X *x=0; X flag++; X } X if (*y<0) { X *y=0; X flag++; X } X if (*x>=MAXX) { X *x=MAXX-1; X flag++; X } X if (*y>=MAXY) { X *y=MAXY-1; X flag++; X } X return(flag); X} X X/* X * dirpoly(spnum) Routine to ask for a direction and polymorph a monst X * int spnum; X * X * Subroutine to polymorph a monster and ask for the direction its in X * Enter with the spell number in spmun. X * Returns no value. X */ Xdirpoly(spnum) Xint spnum; X{ X int x,y,m; X if (spnum<0 || spnum>=SPNUM) return; /* bad args */ X if (isconfuse()) return; /* if he is confused, he can't aim his magic */ X dirsub(&x,&y); X if (mitem[x][y]==0) X { X lprcat(" There wasn't anything there!"); X return; X } X ifblind(x,y); X if (nospell(spnum,mitem[x][y])) { X lasthx=x; X lasthy=y; X return; X } X while ( monster[m = mitem[x][y] = rnd(MAXMONST+7)].genocided ); X hitp[x][y] = monster[m].hitpoints; X show1cell(x,y); /* show the new monster */ X} X X/* X * Function to hit a monster at the designated coordinates X * hitmonster(x,y) X * int x,y; X * X * This routine is used for a bash & slash type attack on a monster X * Enter with the coordinates of the monster in (x,y). X * Returns no value. X */ Xhitmonster(x,y) Xint x,y; X{ X register int tmp,monst,damag,flag; X X if (c[TIMESTOP]) return; /* not if time stopped */ X X vxy(&x,&y); /* verify coordinates are within range */ X X if ((monst = mitem[x][y]) == 0) return; X X hit3flag=1; X ifblind(x,y); X Xtmp = monster[monst].armorclass + c[LEVEL] + c[DEXTERITY] + c[WCLASS/4] -12 X - c[HARDGAME]; X X cursors(); X X /* need at least random chance to hit */ X if ((rnd(20) < tmp) || (rnd(71) < 5)) { X lprcat("\nYou hit"); X flag=1; X damag = fullhit(1); X if (damag<9999) damag=rnd(damag)+1; X } X else { X lprcat("\nYou missed"); X flag=0; X } X lprcat(" the "); X X lprcat(lastmonst); X /* lprintf(" (tmp = %d)", tmp); */ X X if (flag) /* if the monster was hit */ X if (iven[c[WIELD]] != OSWORDofSLASHING) X if ((monst==RUSTMONSTER) || (monst==DISENCHANTRESS) || (monst==CUBE)) X if (c[WIELD]>0) X if (ivenarg[c[WIELD]] > -10) { X lprintf("\nYour weapon is dulled by the %s",lastmonst); X beep(); X --ivenarg[c[WIELD]]; X } X if (flag) { X hitm(x,y,damag); X if ((monst >= DEMONLORD) && X (c[LANCEDEATH]) && X (hitp[x][y]) ) X lprintf("\nYour lance of death tickles the %s!",lastmonst); X } X/* X if (monst == VAMPIRE) X if (hitp[x][y]<25) X { mitem[x][y]=LEMMING; X know[x][y]=0; X } X*/ X X if (monst == METAMORPH) X if (hitp[x][y]<25 && hitp[x][y] > 0) X mitem[x][y]=BRONZEDRAGON+rund(9); X X if (mitem[x][y]==LEMMING) X if (rnd(100)<=40) createmonster(LEMMING); X} X X/* X * Function to just hit a monster at a given coordinates X * hitm(x,y,amt) X * int x,y,amt; X * X * Returns the number of hitpoints the monster absorbed X *This routine is used to specifically damage a monster at a location (x,y) X * Called by hitmonster(x,y) X */ Xhitm(x,y,amt) Xint x,y; Xregister amt; X{ X register int monst; X int hpoints,amt2; X X vxy(&x,&y); /* verify coordinates are within range */ X amt2 = amt; /* save initial damage so we can return it */ X monst = mitem[x][y]; X X /* if half damage curse adjust damage points */ X if (c[HALFDAM]) amt >>= 1; X if (amt<=0) amt2 = amt = 1; X X lasthx=x; X lasthy=y; X X /* make sure hitting monst breaks stealth condition */ X stealth[x][y]=1; X c[HOLDMONST]=0; /* hit a monster breaks hold monster spell */ X switch(monst) /* if a dragon and orb(s) of dragon slaying */ X { X case WHITEDRAGON: X case REDDRAGON: X case GREENDRAGON: X case BRONZEDRAGON: X case PLATINUMDRAGON: X case SILVERDRAGON: X if (c[SLAYING]) X amt *= 3; X break; X } X /* invincible monster fix is here */ X if (hitp[x][y] > monster[monst].hitpoints) X hitp[x][y] = monster[monst].hitpoints; X X if (monst >= DEMONLORD) { X if (c[LANCEDEATH]) X amt=300; X if (iven[c[WIELD]] == OSLAYER) X amt=10000; X } X X if ((hpoints = hitp[x][y]) <= amt) { X lprintf("\nThe %s died!",lastmonst); X raiseexperience((long)monster[monst].experience); X amt = monster[monst].gold; X if (amt>0) dropgold(rnd(amt)+amt); X dropsomething(monst); X disappear(x,y); X bottomline(); X hitp[x][y] = 0; X return(hpoints); X } X hitp[x][y] = hpoints-amt; X return(amt2); X} X X/* X * Function for the monster to hit the player from (x,y) X * hitplayer(x,y) X * int x,y; X * X * Function for the monster to hit the player with monster at location x,y X * Returns nothing of value. X */ Xhitplayer(x,y) Xint x,y; X{ X register int dam,tmp,mster,bias; X X vxy(&x,&y); /* verify coordinates are within range */ X X lastnum = mster = mitem[x][y]; X X if ((know[x][y]&1) == 0) { X know[x][y]=1; X show1cell(x,y); X } X X bias = (c[HARDGAME]) + 1; X hitflag = hit2flag = hit3flag = 1; X yrepcount=0; X cursors(); X ifblind(x,y); X X if (mster < DEMONLORD) X if (c[INVISIBILITY]) if (rnd(33)<20) { X lprintf("\nThe %s misses wildly",lastmonst); X return; X } X X if ( (mster < DEMONLORD) && (mster != PLATINUMDRAGON) ) X if (c[CHARMCOUNT]) X if (rnd(30)+5*monster[mster].level-c[CHARISMA]<30) { X lprintf("\nThe %s is awestruck at your magnificence!",lastmonst); X return; X } X X if (mster==LEMMING) return; X else { X dam = monster[mster].damage; X dam += rnd( (int) ((dam<1)?1:dam) ) + monster[mster].level; X } X X /* demon lords/prince/god of hellfire damage is reduced if wielding X Slayer */ X if (mster >= DEMONLORD) X if (iven[c[WIELD]]==OSLAYER) X dam=(int) (1 - (0.1 * rnd(5)) * dam); X X /* spirit naga's and poltergeist's damage is halved if scarab of X negate spirit */ X if (c[NEGATESPIRIT] || c[SPIRITPRO]) X if ((mster ==POLTERGEIST) || (mster ==SPIRITNAGA)) X dam = (int) dam/2; X X /* halved if undead and cube of undead control */ X if (c[CUBEofUNDEAD] || c[UNDEADPRO]) X if ((mster ==VAMPIRE) || (mster ==WRAITH) || (mster ==ZOMBIE)) X dam = (int) dam/2; X X tmp = 0; X if (monster[mster].attack>0) X if (((dam + bias + 8) > c[AC]) X || (rnd((int)((c[AC]>0)?c[AC]:1))==1)) { X if (spattack(monster[mster].attack,x,y)) { X flushall(); X return; X } X tmp = 1; X bias -= 2; X cursors(); X } X X if (((dam + bias) > c[AC]) || (rnd((int)((c[AC]>0)?c[AC]:1))==1)) { X lprintf("\n The %s hit you ",lastmonst); X tmp = 1; X if ((dam -= c[AC]) < 0) X dam=0; X X if (dam > 0) { X losehp(dam); X bottomhp(); X flushall(); X } X } X X if (tmp == 0) X lprintf("\n The %s missed ",lastmonst); X} X X/* X * dropsomething(monst) Function to create an object when a monster dies X * int monst; X * X * Function to create an object near the player when X * certain monsters are killed X * Enter with the monster number X * Returns nothing of value. X */ Xdropsomething(monst) Xint monst; X{ X switch(monst) { X case ORC: X case NYMPH: X case ELF: X case TROGLODYTE: X case TROLL: X case ROTHE: X case VIOLETFUNGI: X case PLATINUMDRAGON: X case GNOMEKING: X case REDDRAGON: X something(level); X return; X X case LEPRECHAUN: X if (rnd(101)>=75) creategem(); X if (rnd(5)==1) dropsomething(LEPRECHAUN); X return; X case LEMMING: /* createitem(OGOLDPILE,1); */ X return; X } X} X X/* X * dropgold(amount) Function to drop some gold around player X * int amount; X * X * Enter with the number of gold pieces to drop X * Returns nothing of value. X */ Xdropgold(amount) Xregister int amount; X{ X if (amount > 250) createitem(OMAXGOLD, amount); X else createitem(OGOLDPILE,amount); X} X X/* X * something(level) Function to create a random item around player X * int level; X * X * Function to create an item from a designed probability around player X * Enter with the cave level on which something is to be dropped X * Returns nothing of value. X */ Xsomething(lev) Xint lev; X{ X register int j; X int i; X X if (lev<0 || lev>MAXLEVEL+MAXVLEVEL) X return; /* correct level? */ X if (rnd(101)<8) X something(lev); /* possibly more than one item */ X j = newobject(lev,&i); X createitem(j,i); X} X X/* X * newobject(lev,i) Routine to return a randomly selected new object X * int lev,*i; X * X * Routine to return a randomly selected object to be created X * Returns the object number created, and sets *i for its argument X * Enter with the cave level and a pointer to the items arg X */ Xstatic char nobjtab[] = X{ X 0, OSCROLL, OSCROLL, OSCROLL, OSCROLL, OPOTION, X OPOTION, OPOTION, OPOTION, OGOLDPILE, OGOLDPILE, OGOLDPILE, OGOLDPILE, X OBOOK, OBOOK, OBOOK, OBOOK, ODAGGER, ODAGGER, ODAGGER, OLEATHER, OLEATHER, X OLEATHER, OREGENRING, OPROTRING, OENERGYRING, ODEXRING, OSTRRING, OSPEAR, X OBELT, ORING, OSTUDLEATHER, OSHIELD, OFLAIL, OCHAIN, O2SWORD, OPLATE, X OLONGSWORD }; X Xnewobject(lev,i) Xregister int lev,*i; X{ X register int tmp=32,j; X X if (level<0 || level>MAXLEVEL+MAXVLEVEL) X return(0); /* correct level? */ X X if (lev>6) tmp=37; X else if (lev>4) tmp=35; X X j = nobjtab[tmp=rnd(tmp)]; /* the object type */ X switch(tmp) { X case 1: X case 2: X case 3: X case 4: X *i=newscroll(); X break; X case 5: X case 6: X case 7: X case 8: X *i=newpotion(); X break; X case 9: X case 10: X case 11: X case 12: X *i=rnd((lev+1)*10)+lev*10+10; X break; X case 13: X case 14: X case 15: X case 16: X *i=lev; X break; X case 17: X case 18: X case 19: X if (!(*i=newdagger())) return(0); X break; X case 20: X case 21: X case 22: X if (!(*i=newleather())) return(0); X break; X case 23: X case 32: X case 35: X *i=rund(lev/3+1); X break; X case 24: X case 26: X *i=rnd(lev/4+1); X break; X case 25: X *i=rund(lev/4+1); X break; X case 27: X *i=rnd(lev/2+1); X break; X case 28: X *i=rund(lev/3+1); X if (*i==0) return(0); X break; X case 29: X case 31: X *i=rund(lev/2+1); X if (*i==0) return(0); X break; X case 30: X case 33: X *i=rund(lev/2+1); X break; X case 34: X *i=newchain(); X break; X case 36: X *i=newplate(); X break; X case 37: X *i=newsword(); X break; X } X return(j); X} X X/* X * Function to process special attacks from monsters X * spattack(atckno,xx,yy) X * int atckno,xx,yy; X * X * Enter with the special attack number, and the coordinates (xx,yy) X * of the monster that is special attacking X * Returns 1 if must do a show1cell(xx,yy) upon return, 0 otherwise X * X * atckno monster effect X * --------------------------------------------------- X * 0 none X * 1 rust monster eat armor X * 2 hell hound breathe light fire X * 3 dragon breathe fire X * 4 giant centipede weakening sing X * 5 white dragon cold breath X * 6 wraith drain level X * 7 waterlord water gusher X * 8 leprechaun steal gold X * 9 disenchantress disenchant weapon or armor X * 10 ice lizard hits with barbed tail X * 11 umber hulk confusion X * 12 spirit naga cast spells taken from special attacks X * 13 platinum dragon psionics X * 14 nymph steal objects X * 15 bugbear bite X * 16 osequip bite X * X * char rustarm[ARMORTYPES][2]; X * special array for maximum rust damage to armor from rustmonster X * format is: { armor type , minimum attribute X */ X#define ARMORTYPES 6 X Xstatic char rustarm[ARMORTYPES][2] = X{ X OSTUDLEATHER,-2,ORING,-4, OCHAIN,-5, OSPLINT,-6,OPLATE,-8,OPLATEARMOR,-9 }; X Xstatic char spsel[] = { X 1, 2, 3, 5, 6, 8, 9, 11, 13, 14 }; Xspattack(x,xx,yy) Xint x,xx,yy; X{ X register int i,j=0,k,m; X register char *p=0; X X vxy(&xx,&yy); /* verify x & y coordinates */ X X /* cancel only works 5% of time for demon prince X and god */ X if (c[CANCELLATION]) X if (mitem[xx][yy] >= DEMONPRINCE) { X if (rnd(100) >= 95) return(0); X } X else return(0); X X /* staff of power cancels demonlords/wraiths/vampires 75% of time */ X if (mitem[xx][yy] != LUCIFER) { X if ( (mitem[xx][yy] >= DEMONLORD) || X (mitem[xx][yy] == WRAITH) || X (mitem[xx][yy] == VAMPIRE) ) X for (i=0;i<26;i++) X if (iven[i]==OPSTAFF) X if (rnd(100)<75) X return(0); X } X X /* if have cube of undead control, wraiths and vampires do nothing */ X if ( (mitem[xx][yy]==WRAITH) || (mitem[xx][yy]==VAMPIRE) ) X if ( (c[CUBEofUNDEAD]) || (c[UNDEADPRO]) ) X return(0); X X switch(x) { X case 1: /* rust your armor, j=1 when rusting has occurred */ X m = k = c[WEAR]; X if ((i=c[SHIELD]) != -1) X if (--ivenarg[i] < -1) X ivenarg[i]= -1; X else j=1; X if ((j==0) && (k != -1)) { X m = iven[k]; X for (i=0; i<ARMORTYPES; i++) X if (m == rustarm[i][0]) X /* find his armor in table */ X { X if (--ivenarg[k]< rustarm[i][1]) X ivenarg[k]= rustarm[i][1]; X else j=1; X break; X } X } X if (j==0) /* if rusting did not occur */ X switch(m) { X case OLEATHER: X p = "\nThe %s hit you -- You are lucky you have leather on"; X break; X case OSSPLATE: X p = "\nThe %s hit you -- You are fortunate to have stainless steel armor!"; X break; X case OELVENCHAIN: X p = "\nThe %s hit you -- You are very lucky to have such strong elven chain!"; X break; X } X else { X beep(); X p = "\nThe %s hit you -- your armor feels weaker"; X } X break; X X case 2: X i = rnd(15)+8-c[AC]; Xspout: X p="\nThe %s breathes fire at you!"; X if (c[FIRERESISTANCE]) X p="\nThe %s's flame doesn't phase you!"; X else Xspout2: X if (p) { X lprintf(p,lastmonst); X beep(); X } X checkloss(i); X return(0); X X case 3: X i = rnd(20)+25-c[AC]; X goto spout; X X case 4: X if (c[STRENGTH]>3) { X p="\nThe %s stung you! You feel weaker"; X beep(); X if (--c[STRENGTH] < 3) X c[STRENGTH] = 3; X } X else p="\nThe %s stung you!"; X break; X X case 5: X p="\nThe %s blasts you with his cold breath"; X i = rnd(15)+18-c[AC]; X goto spout2; X X case 6: X lprintf("\nThe %s drains you of your life energy!",lastmonst); X loselevel(); X if (mitem[xx][yy]==DEMONPRINCE) losemspells(1); X if (mitem[xx][yy]==LUCIFER) { X loselevel(); X losemspells(2); X for (i=0;i<=5;i++) X if (c[i]-- < 3) c[i]=3; X } X beep(); X return(0); X X case 7: X p="\nThe %s got you with a gusher!"; X i = rnd(15)+25-c[AC]; X goto spout2; X X case 8: X if (c[NOTHEFT]) return(0); X /* he has a device of no theft */ X if (c[GOLD]) { X p="\nThe %s hit you -- Your purse feels lighter"; X if (c[GOLD]>32767) c[GOLD]>>=1; X else c[GOLD] -= rnd((int)(1+(c[GOLD]>>1))); X if (c[GOLD] < 0) c[GOLD]=0; X } X else p="\nThe %s couldn't find any gold to steal"; X lprintf(p,lastmonst); X disappear(xx,yy); X beep(); X bottomgold(); X return(1); X X case 9: X for(j=50; ; ) /* disenchant */ X { X i=rund(26); X m=iven[i]; /* randomly select item */ X if (m>0 && ivenarg[i]>0 && m!=OSCROLL && m!=OPOTION) X { X if ((ivenarg[i] -= 3)<0) ivenarg[i]=0; X lprintf("\nThe %s hits you with a spell of disenchantment! ",lastmonst); X srcount=0; X beep(); X show3(i); X bottomline(); X return(0); X } X if (--j<=0) { X p="\nThe %s nearly misses"; X break; X } X break; X } X break; X X case 10: X p="\nThe %s hit you with his barbed tail"; X i = rnd(25)-c[AC]; X goto spout2; X X case 11: X p="\nThe %s has confused you"; X beep(); X c[CONFUSE]+= 10+rnd(10); X break; X X case 12:/*performs any number of other special attacks */ X return(spattack(spsel[rund(10)],xx,yy)); X X case 13: X p="\nThe %s flattens you with his psionics!"; X i = rnd(15)+30-c[AC]; X goto spout2; X X case 14: X if (c[NOTHEFT]) return(0); X /* he has device of no theft */ X if (emptyhanded()==1) { X p="\nThe %s couldn't find anything to steal"; X break; X } X lprintf("\nThe %s picks your pocket and takes:",lastmonst); X beep(); X if (stealsomething()==0) lprcat(" nothing"); X disappear(xx,yy); X bottomline(); X return(1); X X case 15: X i= rnd(10)+ 5-c[AC]; Xspout3: X p="\nThe %s bit you!"; X goto spout2; X X case 16: X i= rnd(15)+10-c[AC]; X goto spout3; X }; X X if (p) { X lprintf(p,lastmonst); X bottomline(); X } X return(0); X} X X/* X * Routine to subtract hp from user and flag bottomline display X * checkloss(x) X * int x; X * X * Enter with the number of hit points to lose X * Note: if x > c[HP] this routine could kill the player! X */ Xcheckloss(x) Xint x; X{ X if (x>0) { X losehp(x); X bottomhp(); X } X} X X/* X * Routine to annihilate all monsters around player (playerx,playery) X * annihilate() X * X * Gives player experience, but no dropped objects X * Returns the experience gained from all monsters killed X */ Xannihilate() X{ X int i,j; X register long k; X register char *p; X X for (k=0, i=playerx-1; i<=playerx+1; i++) X for (j=playery-1; j<=playery+1; j++) X if (!vxy(&i,&j)) /* if not out of bounds */ X if (*(p= &mitem[i][j])) /* if a monster there */ X if (*p<DEMONLORD) { X k += monster[*p].experience; X *p=know[i][j]=0; X } X else { X lprintf("\nThe %s barely escapes being annihilated!",monster[*p].name); X hitp[i][j] = (hitp[i][j]>>1) + 1; X /* lose half hit points*/ X } X if (k>0) { X lprcat("\nYou hear loud screams of agony!"); X raiseexperience((long)k); X } X return(k); X} X X/* X * Function to create a new sphere of annihilation X * newsphere(x,y,dir,lifetime) X * int x,y,dir,lifetime; X * X * Enter with the coordinates of the sphere in x,y X * the direction (0-8 diroffx format) in dir, and the lifespan of the X * sphere in lifetime (in turns) X * Returns the number of spheres currently in existence X */ Xnewsphere(x,y,dir,life) Xint x,y,dir,life; X{ X int m,i; X struct sphere *sp; X X if (((sp=(struct sphere *)malloc(sizeof(struct sphere)))) == 0) X return(c[SPHCAST]); /* can't malloc, therefore failure */ X if (dir>=9) dir=0; /* no movement if direction not found */ X if (level==0) vxy(&x,&y); /* don't go out of bounds */ X else { X if (x<1) x=1; X if (x>=MAXX-1) x=MAXX-2; X if (y<1) y=1; X if (y>=MAXY-1) y=MAXY-2; X } X X for (i=0;i<26;i++) X if (iven[i]==OSPHTALISMAN) goto out; X X /* demons dispel spheres */ X if ((m=mitem[x][y]) >= DEMONLORD) { X i = hitp[x][y]; X know[x][y]=1; X show1cell(x,y); /* show the demon (ha ha) */ X cursors(); X lprintf("\nThe %s dispels the sphere!",monster[m].name); X beep(); X rmsphere(x,y); /* remove any spheres that are here */ X mitem[x][y] = m; X hitp[x][y] = i; X know[x][y]=0; X return(c[SPHCAST]); X } X X /* disenchantress cancels spheres */ X if (m==DISENCHANTRESS) { X cursors(); X lprintf("\nThe %s causes cancellation of the sphere!",monster[m].name); X beep(); X Xboom: X sphboom(x,y); /* blow up stuff around sphere */ X rmsphere(x,y); /* remove any spheres that are here */ X return(c[SPHCAST]); X } X X /* cancellation cancels spheres */ X if (c[CANCELLATION]) { X cursors(); X lprcat("\nAs the cancellation takes effect, you hear a great earth shaking blast!"); X beep(); X goto boom; X } X /* collision of sphere and player! */ X if (playerx==x && playery==y) { X cursors(); X lprcat("\nYou have been enveloped by the zone of nothingness!\n"); X beep(); X rmsphere(x,y); /* remove any spheres that are here */ X nap(4000); X died(258); X } Xout: X /* collision of spheres detonates spheres */ X if (item[x][y]==OANNIHILATION) { X cursors(); X lprcat("\nTwo spheres of annihilation collide! You hear a great earth shaking blast!"); X beep(); X rmsphere(x,y); X goto boom; X } X X item[x][y]=OANNIHILATION; X mitem[x][y]=0; X know[x][y]=1; X show1cell(x,y); /* show the new sphere */ X sp->x=x; X sp->y=y; X sp->lev=level; X sp->dir=dir; X sp->lifetime=life; X sp->p=0; X if (spheres==0) spheres=sp; /* if first node in the sphere list */ X else /* add sphere to beginning of linked list */ X { X sp->p = spheres; X spheres = sp; X } X return(++c[SPHCAST]); /* one more sphere in the world */ X} X X/* X * rmsphere(x,y) Function to delete a sphere of annihilation from list X * int x,y; X * X * Enter with the coordinates of the sphere (on current level) X * Returns the number of spheres currently in existence X */ Xrmsphere(x,y) Xint x,y; X{ X register struct sphere *sp,*sp2=0; X X for (sp=spheres; sp; sp2=sp,sp=sp->p) X if (level==sp->lev) /* is sphere on this level? */ X if ((x==sp->x) && (y==sp->y)) X /* locate sphere at this location */ X { X item[x][y]= mitem[x][y]= 0; X know[x][y]=1; X show1cell(x,y); /* show the now missing sphere */ X --c[SPHCAST]; X if (sp==spheres) { X sp2=sp; X spheres=sp->p; X free((char*)sp2); X } X else X { X sp2->p = sp->p; X free((char*)sp); X } X break; X } X return(c[SPHCAST]); /* return number of spheres in the world */ X} X X/* X * sphboom(x,y) Function to perform the effects of a sphere detonation X * int x,y; X * X * Enter with the coordinates of the blast, Returns no value X */ Xsphboom(x,y) Xint x,y; X{ X register int i,j,k; X X if (c[HOLDMONST]) c[HOLDMONST]=1; X if (c[CANCELLATION]) c[CANCELLATION]=1; X for (j=max(1,x-2); j<min(x+3,MAXX-1); j++) X for (i=max(1,y-2); i<min(y+3,MAXY-1); i++) X { X item[j][i]=mitem[j][i]=0; X show1cell(j,i); X for (k=0;k<26;k++) if (iven[k]==OSPHTALISMAN) return; X if (playerx==j && playery==i) X { X cursors(); X beep(); X lprcat("\nYou were too close to the sphere!"); X nap(3000); X died(283); /* player killed in explosion */ X } X } X} X X/* X * Function to ask for monster and genocide from game X * genmonst() X * X * This is done by setting a flag in the monster[] structure X */ Xgenmonst() X{ X register int i,j; X cursors(); X lprcat("\nGenocide what monster? "); X for (i=0; (!isalpha(i)) && (i!=' '); i=getcharacter()); X lprc(i); X for (j=0; j<MAXMONST; j++) /* search for the monster type */ X if (monstnamelist[j]==i) /* have we found it? */ X if (monster[j].genocided==0) { X monster[j].genocided=1; /* genocided from game */ X lprintf(" There will be no more %s's",monster[j].name); X /* now wipe out monsters on this level */ X newcavelevel(level); X draws(0,MAXX,0,MAXY); X bot_linex(); X return; X } X lprcat(" You sense failure!"); X} END_OF_FILE if test 46657 -ne `wc -c <'monster.c'`; then echo shar: \"'monster.c'\" unpacked with wrong size! fi # end of 'monster.c' fi if test -f 'signal.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'signal.c'\" else echo shar: Extracting \"'signal.c'\" \(4653 characters\) sed "s/^X//" >'signal.c' <<'END_OF_FILE' X/* signal.c */ X X#include "header.h" X X#define BIT(a) (1<<((a)-1)) Xextern char savefilename[],wizard,predostuff,nosignal; X Xs2choose() /* text to be displayed if ^C during intro screen */ X{ X cursor(1,24); X lprcat("Press "); X if (boldon) setbold(); X lprcat("return"); X if (boldon) resetbold(); X lprcat(" to continue: "); X lflush(); X} X Xcntlc() /* what to do for a ^C */ X{ X if (nosignal) X return; /* don't do anything if inhibited */ X signal(SIGINT,SIG_IGN); X quit(); X if (predostuff==1) X s2choose(); X else X showplayer(); X lflush(); X signal(SIGQUIT,cntlc); X signal(SIGINT,cntlc); X} X X/* X * subroutine to save the game if a hangup signal X */ Xsgam() X{ X savegame(savefilename); X wizard=1; X died(-257); /* hangup signal */ X} X X#ifdef SIGTSTP Xtstop() X{ X if (nosignal) X return; /* nothing if inhibited */ X lcreat((char*)0); X clearvt100(); X lflush(); X signal(SIGTSTP,SIG_DFL); X#ifdef SIGVTALRM X/* looks like BSD4.2 or higher - must clr mask for signal to take effect*/ X sigsetmask(sigblock(0)& ~BIT(SIGTSTP)); X#endif X kill(getpid(),SIGTSTP); X X setupvt100(); X signal(SIGTSTP,tstop); X if (predostuff==1) X s2choose(); X else X drawscreen(); X showplayer(); X lflush(); X} X#endif /* SIGTSTP */ X X/* X * subroutine to issue the needed signal traps called from main() X */ Xsigill() { sigpanic(SIGILL); } Xsigtrap() { sigpanic(SIGTRAP); } Xsigiot() { sigpanic(SIGIOT); } Xsigemt() { sigpanic(SIGEMT); } Xsigfpe() { sigpanic(SIGFPE); } Xsigbus() { sigpanic(SIGBUS); } Xsigsegv() { sigpanic(SIGSEGV); } Xsigsys() { sigpanic(SIGSYS); } Xsigpipe() { sigpanic(SIGPIPE); } Xsigterm() { sigpanic(SIGTERM); } X Xsigsetup() X{ X signal(SIGQUIT, cntlc); X signal(SIGINT, cntlc); X signal(SIGKILL, SIG_IGN); X signal(SIGHUP, sgam); X signal(SIGILL, sigill); X signal(SIGTRAP, sigtrap); X signal(SIGIOT, sigiot); X signal(SIGEMT, sigemt); X signal(SIGFPE, sigfpe); X signal(SIGBUS, sigbus); X signal(SIGSEGV, sigsegv); X signal(SIGSYS, sigsys); X signal(SIGPIPE, sigpipe); X signal(SIGTERM, sigterm); X#ifdef SIGTSTP X signal(SIGTSTP,tstop); X signal(SIGSTOP,tstop); X#endif /* SIGTSTP */ X} X X#ifdef BSD /* for BSD UNIX? */ X Xstatic char *signame[NSIG] = { X "", X "SIGHUP", /* 1 hangup */ X "SIGINT", /* 2 interrupt */ X "SIGQUIT", /* 3 quit */ X "SIGILL", /* 4 illegal instruction (not reset when caught) */ X "SIGTRAP", /* 5 trace trap (not reset when caught) */ X "SIGIOT", /* 6 IOT instruction */ X "SIGEMT", /* 7 EMT instruction */ X "SIGFPE", /* 8 floating point exception */ X "SIGKILL", /* 9 kill (cannot be caught or ignored) */ X "SIGBUS", /* 10 bus error */ X "SIGSEGV", /* 11 segmentation violation */ X "SIGSYS", /* 12 bad argument to system call */ X "SIGPIPE", /* 13 write on a pipe with no one to read it */ X "SIGALRM", /* 14 alarm clock */ X "SIGTERM", /* 15 software termination signal from kill */ X "SIGURG", /* 16 urgent condition on IO channel */ X "SIGSTOP", /* 17 sendable stop signal not from tty */ X "SIGTSTP", /* 18 stop signal from tty */ X "SIGCONT", /* 19 continue a stopped process */ X "SIGCHLD", /* 20 to parent on child stop or exit */ X "SIGTTIN", /* 21 to readers pgrp upon background tty read */ X "SIGTTOU", /* 22 like TTIN for output if (tp->t_local<OSTOP)*/ X "SIGIO", /* 23 input/output possible signal */ X "SIGXCPU", /* 24 exceeded CPU time limit */ X "SIGXFSZ", /* 25 exceeded file size limit */ X "SIGVTALRM",/* 26 virtual time alarm */ X "SIGPROF", /* 27 profiling time alarm */ X "","","","" }; X X#else /* SYSV */ Xstatic char *signame[NSIG] = { X "", X "SIGHUP", /* 1 hangup */ X "SIGINT", /* 2 interrupt */ X "SIGQUIT", /* 3 quit */ X "SIGILL", /* 4 illegal instruction (not reset when caught) */ X "SIGTRAP", /* 5 trace trap (not reset when caught) */ X "SIGIOT", /* 6 IOT instruction */ X "SIGEMT", /* 7 EMT instruction */ X "SIGFPE", /* 8 floating point exception */ X "SIGKILL", /* 9 kill (cannot be caught or ignored) */ X "SIGBUS", /* 10 bus error */ X "SIGSEGV", /* 11 segmentation violation */ X "SIGSYS", /* 12 bad argument to system call */ X "SIGPIPE", /* 13 write on a pipe with no one to read it */ X "SIGALRM", /* 14 alarm clock */ X "SIGTERM", /* 15 software termination signal from kill */ X "SIGUSR1", /* 16 user defines signal 1 */ X "SIGUSR2", /* 17 user defines signal 2 */ X "SIGCLD", /* 18 child death */ X "SIGPWR" /* 19 power fail */ X}; X#endif /* BSD */ X X/* X * routine to process a fatal error signal X */ Xsigpanic(sig) Xint sig; X{ X signal(sig,SIG_DFL); X fprintf(stderr,"\nUlarn - SHIT! Signal %d !!! [%s]\n",sig,signame[sig]); X fflush(stderr); X sleep(2); X sncbr(); X savegame(savefilename); X kill(getpid(),sig); /* this will terminate us */ X} END_OF_FILE if test 4653 -ne `wc -c <'signal.c'`; then echo shar: \"'signal.c'\" unpacked with wrong size! fi # end of 'signal.c' fi echo shar: End of archive 2 \(of 8\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 4 5 6 7 8 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 8 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0