Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

v07i002: ularn - ultra-larn, an enhancement of the larn adventure game, Part02/08

9 views
Skip to first unread message

Bill Randle

unread,
Jul 6, 1989, 9:59:40 AM7/6/89
to
Submitted-by: "Philip A. Cordier" <ph...@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&LTOSTOP)*/
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

0 new messages