Home | History | Annotate | Line # | Download | only in larn
monster.c revision 1.1
      1  1.1  cgd /*
      2  1.1  cgd  *	monster.c		Larn is copyrighted 1986 by Noah Morgan.
      3  1.1  cgd  *
      4  1.1  cgd  *	This file contains the following functions:
      5  1.1  cgd  *	----------------------------------------------------------------------------
      6  1.1  cgd  *
      7  1.1  cgd  *	createmonster(monstno) 		Function to create a monster next to the player
      8  1.1  cgd  *		int monstno;
      9  1.1  cgd  *
     10  1.1  cgd  *	int cgood(x,y,itm,monst)	Function to check location for emptiness
     11  1.1  cgd  *		int x,y,itm,monst;
     12  1.1  cgd  *
     13  1.1  cgd  *	createitem(it,arg) 			Routine to place an item next to the player
     14  1.1  cgd  *		int it,arg;
     15  1.1  cgd  *
     16  1.1  cgd  *	cast() 				Subroutine called by parse to cast a spell for the user
     17  1.1  cgd  *
     18  1.1  cgd  *	speldamage(x) 		Function to perform spell functions cast by the player
     19  1.1  cgd  *		int x;
     20  1.1  cgd  *
     21  1.1  cgd  *	loseint()			Routine to decrement your int (intelligence) if > 3
     22  1.1  cgd  *
     23  1.1  cgd  *	isconfuse() 		Routine to check to see if player is confused
     24  1.1  cgd  *
     25  1.1  cgd  *	nospell(x,monst)	Routine to return 1 if a spell doesn't affect a monster
     26  1.1  cgd  *		int x,monst;
     27  1.1  cgd  *
     28  1.1  cgd  *	fullhit(xx)			Function to return full damage against a monst (aka web)
     29  1.1  cgd  *		int xx;
     30  1.1  cgd  *
     31  1.1  cgd  *	direct(spnum,dam,str,arg)	Routine to direct spell damage 1 square in 1 dir
     32  1.1  cgd  *		int spnum,dam,arg;
     33  1.1  cgd  *		char *str;
     34  1.1  cgd  *
     35  1.1  cgd  *	godirect(spnum,dam,str,delay,cshow)		Function to perform missile attacks
     36  1.1  cgd  *		int spnum,dam,delay;
     37  1.1  cgd  *		char *str,cshow;
     38  1.1  cgd  *
     39  1.1  cgd  *	ifblind(x,y)	Routine to put "monster" or the monster name into lastmosnt
     40  1.1  cgd  *		int x,y;
     41  1.1  cgd  *
     42  1.1  cgd  *	tdirect(spnum)			Routine to teleport away a monster
     43  1.1  cgd  *		int spnum;
     44  1.1  cgd  *
     45  1.1  cgd  *	omnidirect(sp,dam,str)  Routine to damage all monsters 1 square from player
     46  1.1  cgd  *		int sp,dam;
     47  1.1  cgd  *		char *str;
     48  1.1  cgd  *
     49  1.1  cgd  *	dirsub(x,y)			Routine to ask for direction, then modify x,y for it
     50  1.1  cgd  *		int *x,*y;
     51  1.1  cgd  *
     52  1.1  cgd  *	vxy(x,y)		  	Routine to verify/fix (*x,*y) for being within bounds
     53  1.1  cgd  *		int *x,*y;
     54  1.1  cgd  *
     55  1.1  cgd  *	dirpoly(spnum)		Routine to ask for a direction and polymorph a monst
     56  1.1  cgd  *		int spnum;
     57  1.1  cgd  *
     58  1.1  cgd  *	hitmonster(x,y) 	Function to hit a monster at the designated coordinates
     59  1.1  cgd  *		int x,y;
     60  1.1  cgd  *
     61  1.1  cgd  *	hitm(x,y,amt)		Function to just hit a monster at a given coordinates
     62  1.1  cgd  *		int x,y,amt;
     63  1.1  cgd  *
     64  1.1  cgd  *	hitplayer(x,y) 		Function for the monster to hit the player from (x,y)
     65  1.1  cgd  *		int x,y;
     66  1.1  cgd  *
     67  1.1  cgd  *	dropsomething(monst) 	Function to create an object when a monster dies
     68  1.1  cgd  *		int monst;
     69  1.1  cgd  *
     70  1.1  cgd  *	dropgold(amount) 		Function to drop some gold around player
     71  1.1  cgd  *		int amount;
     72  1.1  cgd  *
     73  1.1  cgd  *	something(level) 		Function to create a random item around player
     74  1.1  cgd  *		int level;
     75  1.1  cgd  *
     76  1.1  cgd  *	newobject(lev,i) 		Routine to return a randomly selected new object
     77  1.1  cgd  *		int lev,*i;
     78  1.1  cgd  *
     79  1.1  cgd  *  spattack(atckno,xx,yy) 	Function to process special attacks from monsters
     80  1.1  cgd  *  	int atckno,xx,yy;
     81  1.1  cgd  *
     82  1.1  cgd  *	checkloss(x) 	Routine to subtract hp from user and flag bottomline display
     83  1.1  cgd  *		int x;
     84  1.1  cgd  *
     85  1.1  cgd  *	annihilate()   Routine to annihilate monsters around player, playerx,playery
     86  1.1  cgd  *
     87  1.1  cgd  *	newsphere(x,y,dir,lifetime)  Function to create a new sphere of annihilation
     88  1.1  cgd  *		int x,y,dir,lifetime;
     89  1.1  cgd  *
     90  1.1  cgd  *	rmsphere(x,y)		Function to delete a sphere of annihilation from list
     91  1.1  cgd  *		int x,y;
     92  1.1  cgd  *
     93  1.1  cgd  *	sphboom(x,y)		Function to perform the effects of a sphere detonation
     94  1.1  cgd  *		int x,y;
     95  1.1  cgd  *
     96  1.1  cgd  *	genmonst()			Function to ask for monster and genocide from game
     97  1.1  cgd  *
     98  1.1  cgd  */
     99  1.1  cgd #include "header.h"
    100  1.1  cgd 
    101  1.1  cgd struct isave	/* used for altar reality */
    102  1.1  cgd 	{
    103  1.1  cgd 	char type;	/* 0=item,  1=monster */
    104  1.1  cgd 	char id;	/* item number or monster number */
    105  1.1  cgd 	short arg;	/* the type of item or hitpoints of monster */
    106  1.1  cgd 	};
    107  1.1  cgd 
    108  1.1  cgd /*
    109  1.1  cgd  *	createmonster(monstno) 		Function to create a monster next to the player
    110  1.1  cgd  *		int monstno;
    111  1.1  cgd  *
    112  1.1  cgd  *	Enter with the monster number (1 to MAXMONST+8)
    113  1.1  cgd  *	Returns no value.
    114  1.1  cgd  */
    115  1.1  cgd createmonster(mon)
    116  1.1  cgd 	int mon;
    117  1.1  cgd 	{
    118  1.1  cgd 	register int x,y,k,i;
    119  1.1  cgd 	if (mon<1 || mon>MAXMONST+8)	/* check for monster number out of bounds */
    120  1.1  cgd 		{
    121  1.1  cgd 		beep(); lprintf("\ncan't createmonst(%d)\n",(long)mon); nap(3000); return;
    122  1.1  cgd 		}
    123  1.1  cgd 	while (monster[mon].genocided && mon<MAXMONST) mon++; /* genocided? */
    124  1.1  cgd 	for (k=rnd(8), i= -8; i<0; i++,k++)	/* choose direction, then try all */
    125  1.1  cgd 		{
    126  1.1  cgd 		if (k>8) k=1;	/* wraparound the diroff arrays */
    127  1.1  cgd 		x = playerx + diroffx[k];		y = playery + diroffy[k];
    128  1.1  cgd 		if (cgood(x,y,0,1))	/* if we can create here */
    129  1.1  cgd 			{
    130  1.1  cgd 			mitem[x][y] = mon;
    131  1.1  cgd 			hitp[x][y] = monster[mon].hitpoints;
    132  1.1  cgd 			stealth[x][y]=know[x][y]=0;
    133  1.1  cgd 			switch(mon)
    134  1.1  cgd 				{
    135  1.1  cgd 				case ROTHE: case POLTERGEIST: case VAMPIRE: stealth[x][y]=1;
    136  1.1  cgd 				};
    137  1.1  cgd 			return;
    138  1.1  cgd 			}
    139  1.1  cgd 		}
    140  1.1  cgd 	}
    141  1.1  cgd 
    142  1.1  cgd /*
    143  1.1  cgd  *	int cgood(x,y,itm,monst)	  Function to check location for emptiness
    144  1.1  cgd  *		int x,y,itm,monst;
    145  1.1  cgd  *
    146  1.1  cgd  *	Routine to return TRUE if a location does not have itm or monst there
    147  1.1  cgd  *	returns FALSE (0) otherwise
    148  1.1  cgd  *	Enter with itm or monst TRUE or FALSE if checking it
    149  1.1  cgd  *	Example:  if itm==TRUE check for no item at this location
    150  1.1  cgd  *			  if monst==TRUE check for no monster at this location
    151  1.1  cgd  *	This routine will return FALSE if at a wall or the dungeon exit on level 1
    152  1.1  cgd  */
    153  1.1  cgd int cgood(x,y,itm,monst)
    154  1.1  cgd 	register int x,y;
    155  1.1  cgd 	int itm,monst;
    156  1.1  cgd 	{
    157  1.1  cgd 	if ((y>=0) && (y<=MAXY-1) && (x>=0) && (x<=MAXX-1)) /* within bounds? */
    158  1.1  cgd 	  if (item[x][y]!=OWALL)	/* can't make anything on walls */
    159  1.1  cgd 		if (itm==0 || (item[x][y]==0))	/* is it free of items? */
    160  1.1  cgd 		  if (monst==0 || (mitem[x][y]==0))	/* is it free of monsters? */
    161  1.1  cgd 		    if ((level!=1) || (x!=33) || (y!=MAXY-1)) /* not exit to level 1 */
    162  1.1  cgd 			  return(1);
    163  1.1  cgd 	return(0);
    164  1.1  cgd 	}
    165  1.1  cgd 
    166  1.1  cgd /*
    167  1.1  cgd  *	createitem(it,arg) 		Routine to place an item next to the player
    168  1.1  cgd  *		int it,arg;
    169  1.1  cgd  *
    170  1.1  cgd  *	Enter with the item number and its argument (iven[], ivenarg[])
    171  1.1  cgd  *	Returns no value, thus we don't know about createitem() failures.
    172  1.1  cgd  */
    173  1.1  cgd createitem(it,arg)
    174  1.1  cgd 	int it,arg;
    175  1.1  cgd 	{
    176  1.1  cgd 	register int x,y,k,i;
    177  1.1  cgd 	if (it >= MAXOBJ) return;	/* no such object */
    178  1.1  cgd 	for (k=rnd(8), i= -8; i<0; i++,k++)	/* choose direction, then try all */
    179  1.1  cgd 		{
    180  1.1  cgd 		if (k>8) k=1;	/* wraparound the diroff arrays */
    181  1.1  cgd 		x = playerx + diroffx[k];		y = playery + diroffy[k];
    182  1.1  cgd 		if (cgood(x,y,1,0))	/* if we can create here */
    183  1.1  cgd 			{
    184  1.1  cgd 			item[x][y] = it;  know[x][y]=0;  iarg[x][y]=arg;  return;
    185  1.1  cgd 			}
    186  1.1  cgd 		}
    187  1.1  cgd 	}
    188  1.1  cgd 
    189  1.1  cgd /*
    190  1.1  cgd  *	cast() 		Subroutine called by parse to cast a spell for the user
    191  1.1  cgd  *
    192  1.1  cgd  *	No arguments and no return value.
    193  1.1  cgd  */
    194  1.1  cgd static char eys[] = "\nEnter your spell: ";
    195  1.1  cgd cast()
    196  1.1  cgd 	{
    197  1.1  cgd 	register int i,j,a,b,d;
    198  1.1  cgd 	cursors();
    199  1.1  cgd 	if (c[SPELLS]<=0) {	lprcat("\nYou don't have any spells!");	return;	}
    200  1.1  cgd 	lprcat(eys);		--c[SPELLS];
    201  1.1  cgd 	while ((a=getchar())=='D')
    202  1.1  cgd 		{ seemagic(-1); cursors();  lprcat(eys); }
    203  1.1  cgd 	if (a=='\33') goto over; /*	to escape casting a spell	*/
    204  1.1  cgd 	if ((b=getchar())=='\33') goto over; /*	to escape casting a spell	*/
    205  1.1  cgd 	if ((d=getchar())=='\33')
    206  1.1  cgd 		{ over: lprcat(aborted); c[SPELLS]++; return; } /*	to escape casting a spell	*/
    207  1.1  cgd #ifdef EXTRA
    208  1.1  cgd 	c[SPELLSCAST]++;
    209  1.1  cgd #endif
    210  1.1  cgd 	for (lprc('\n'),j= -1,i=0; i<SPNUM; i++) /*seq search for his spell, hash?*/
    211  1.1  cgd 		if ((spelcode[i][0]==a) && (spelcode[i][1]==b) && (spelcode[i][2]==d))
    212  1.1  cgd 			if (spelknow[i])
    213  1.1  cgd 				{  speldamage(i);  j = 1;  i=SPNUM; }
    214  1.1  cgd 
    215  1.1  cgd 	if (j == -1) lprcat("  Nothing Happened ");
    216  1.1  cgd 	bottomline();
    217  1.1  cgd 	}
    218  1.1  cgd 
    219  1.1  cgd static int dirsub();
    220  1.1  cgd 
    221  1.1  cgd /*
    222  1.1  cgd  *	speldamage(x) 		Function to perform spell functions cast by the player
    223  1.1  cgd  *		int x;
    224  1.1  cgd  *
    225  1.1  cgd  *	Enter with the spell number, returns no value.
    226  1.1  cgd  *	Please insure that there are 2 spaces before all messages here
    227  1.1  cgd  */
    228  1.1  cgd speldamage(x)
    229  1.1  cgd 	int x;
    230  1.1  cgd 	{
    231  1.1  cgd 	register int i,j,clev;
    232  1.1  cgd 	int xl,xh,yl,yh;
    233  1.1  cgd 	register char *p,*kn,*pm;
    234  1.1  cgd 	if (x>=SPNUM) return;	/* no such spell */
    235  1.1  cgd 	if (c[TIMESTOP])  { lprcat("  It didn't seem to work"); return; }  /* not if time stopped */
    236  1.1  cgd 	clev = c[LEVEL];
    237  1.1  cgd 	if ((rnd(23)==7) || (rnd(18) > c[INTELLIGENCE]))
    238  1.1  cgd 		{ lprcat("  It didn't work!");  return; }
    239  1.1  cgd 	if (clev*3+2 < x) { lprcat("  Nothing happens.  You seem inexperienced at this"); return; }
    240  1.1  cgd 
    241  1.1  cgd 	switch(x)
    242  1.1  cgd 		{
    243  1.1  cgd /* ----- LEVEL 1 SPELLS ----- */
    244  1.1  cgd 
    245  1.1  cgd 		case 0:	if (c[PROTECTIONTIME]==0)	c[MOREDEFENSES]+=2; /* protection field +2 */
    246  1.1  cgd 				c[PROTECTIONTIME] += 250;   return;
    247  1.1  cgd 
    248  1.1  cgd 		case 1: i = rnd(((clev+1)<<1)) + clev + 3;
    249  1.1  cgd 				godirect(x,i,(clev>=2)?"  Your missiles hit the %s":"  Your missile hit the %s",100,'+'); /* magic missile */
    250  1.1  cgd 
    251  1.1  cgd 				return;
    252  1.1  cgd 
    253  1.1  cgd 		case 2:	if (c[DEXCOUNT]==0)	c[DEXTERITY]+=3; /*	dexterity	*/
    254  1.1  cgd 				c[DEXCOUNT] += 400;  	return;
    255  1.1  cgd 
    256  1.1  cgd 		case 3: i=rnd(3)+1;
    257  1.1  cgd 				p="  While the %s slept, you smashed it %d times";
    258  1.1  cgd 			ws:	direct(x,fullhit(i),p,i); /*	sleep	*/	return;
    259  1.1  cgd 
    260  1.1  cgd 		case 4:	/*	charm monster	*/	c[CHARMCOUNT] += c[CHARISMA]<<1;	return;
    261  1.1  cgd 
    262  1.1  cgd 		case 5:	godirect(x,rnd(10)+15+clev,"  The sound damages the %s",70,'@'); /*	sonic spear */
    263  1.1  cgd 				return;
    264  1.1  cgd 
    265  1.1  cgd /* ----- LEVEL 2 SPELLS ----- */
    266  1.1  cgd 
    267  1.1  cgd 		case 6: i=rnd(3)+2;	p="  While the %s is entangled, you hit %d times";
    268  1.1  cgd 				goto ws; /* web */
    269  1.1  cgd 
    270  1.1  cgd 		case 7:	if (c[STRCOUNT]==0) c[STREXTRA]+=3;	/*	strength	*/
    271  1.1  cgd 				c[STRCOUNT] += 150+rnd(100);    return;
    272  1.1  cgd 
    273  1.1  cgd 		case 8:	yl = playery-5;     /* enlightenment */
    274  1.1  cgd 				yh = playery+6;   xl = playerx-15;   xh = playerx+16;
    275  1.1  cgd 				vxy(&xl,&yl);   vxy(&xh,&yh); /* check bounds */
    276  1.1  cgd 				for (i=yl; i<=yh; i++) /* enlightenment	*/
    277  1.1  cgd 					for (j=xl; j<=xh; j++)	know[j][i]=1;
    278  1.1  cgd 				draws(xl,xh+1,yl,yh+1);	return;
    279  1.1  cgd 
    280  1.1  cgd 		case 9:	raisehp(20+(clev<<1));  return;  /* healing */
    281  1.1  cgd 
    282  1.1  cgd 		case 10:	c[BLINDCOUNT]=0;	return;	/* cure blindness	*/
    283  1.1  cgd 
    284  1.1  cgd 		case 11:	createmonster(makemonst(level+1)+8);  return;
    285  1.1  cgd 
    286  1.1  cgd 		case 12:	if (rnd(11)+7 <= c[WISDOM]) direct(x,rnd(20)+20+clev,"  The %s believed!",0);
    287  1.1  cgd 					else lprcat("  It didn't believe the illusions!");
    288  1.1  cgd 					return;
    289  1.1  cgd 
    290  1.1  cgd 		case 13:	/* if he has the amulet of invisibility then add more time */
    291  1.1  cgd 					for (j=i=0; i<26; i++)
    292  1.1  cgd 						if (iven[i]==OAMULET) j+= 1+ivenarg[i];
    293  1.1  cgd 					c[INVISIBILITY] += (j<<7)+12;   return;
    294  1.1  cgd 
    295  1.1  cgd /* ----- LEVEL 3 SPELLS ----- */
    296  1.1  cgd 
    297  1.1  cgd 		case 14:	godirect(x,rnd(25+clev)+25+clev,"  The fireball hits the %s",40,'*'); return; /*	fireball */
    298  1.1  cgd 
    299  1.1  cgd 		case 15:	godirect(x,rnd(25)+20+clev,"  Your cone of cold strikes the %s",60,'O');	/*	cold */
    300  1.1  cgd 					return;
    301  1.1  cgd 
    302  1.1  cgd 		case 16:	dirpoly(x);  return;	/*	polymorph */
    303  1.1  cgd 
    304  1.1  cgd 		case 17:	c[CANCELLATION]+= 5+clev;	return;	/*	cancellation	*/
    305  1.1  cgd 
    306  1.1  cgd 		case 18:	c[HASTESELF]+= 7+clev;  return;  /*	haste self	*/
    307  1.1  cgd 
    308  1.1  cgd 		case 19:	omnidirect(x,30+rnd(10),"  The %s gasps for air");	/* cloud kill */
    309  1.1  cgd 					return;
    310  1.1  cgd 
    311  1.1  cgd 		case 20:	xh = min(playerx+1,MAXX-2);		yh = min(playery+1,MAXY-2);
    312  1.1  cgd 					for (i=max(playerx-1,1); i<=xh; i++) /* vaporize rock */
    313  1.1  cgd 					  for (j=max(playery-1,1); j<=yh; j++)
    314  1.1  cgd 						{
    315  1.1  cgd 						kn = &know[i][j];    pm = &mitem[i][j];
    316  1.1  cgd 						switch(*(p= &item[i][j]))
    317  1.1  cgd 						  {
    318  1.1  cgd 						  case OWALL: if (level < MAXLEVEL+MAXVLEVEL-1)
    319  1.1  cgd 											*p = *kn = 0;
    320  1.1  cgd 										break;
    321  1.1  cgd 
    322  1.1  cgd 						  case OSTATUE: if (c[HARDGAME]<3)
    323  1.1  cgd 											 {
    324  1.1  cgd 											 *p=OBOOK; iarg[i][j]=level;  *kn=0;
    325  1.1  cgd 											 }
    326  1.1  cgd 										break;
    327  1.1  cgd 
    328  1.1  cgd 						  case OTHRONE: *pm=GNOMEKING;  *kn=0;  *p= OTHRONE2;
    329  1.1  cgd 										hitp[i][j]=monster[GNOMEKING].hitpoints; break;
    330  1.1  cgd 
    331  1.1  cgd 						  case OALTAR:	*pm=DEMONPRINCE;  *kn=0;
    332  1.1  cgd 										hitp[i][j]=monster[DEMONPRINCE].hitpoints; break;
    333  1.1  cgd 						  };
    334  1.1  cgd 						switch(*pm)
    335  1.1  cgd 							{
    336  1.1  cgd 							case XORN:	ifblind(i,j);  hitm(i,j,200); break; /* Xorn takes damage from vpr */
    337  1.1  cgd 							}
    338  1.1  cgd 						}
    339  1.1  cgd 					return;
    340  1.1  cgd 
    341  1.1  cgd /* ----- LEVEL 4 SPELLS ----- */
    342  1.1  cgd 
    343  1.1  cgd 		case 21:	direct(x,100+clev,"  The %s shrivels up",0); /* dehydration */
    344  1.1  cgd 					return;
    345  1.1  cgd 
    346  1.1  cgd 		case 22:	godirect(x,rnd(25)+20+(clev<<1),"  A lightning bolt hits the %s",1,'~');	/*	lightning */
    347  1.1  cgd 					return;
    348  1.1  cgd 
    349  1.1  cgd 		case 23:	i=min(c[HP]-1,c[HPMAX]/2);	/* drain life */
    350  1.1  cgd 					direct(x,i+i,"",0);	c[HP] -= i;  	return;
    351  1.1  cgd 
    352  1.1  cgd 		case 24:	if (c[GLOBE]==0) c[MOREDEFENSES] += 10;
    353  1.1  cgd 					c[GLOBE] += 200;  loseint();  /* globe of invulnerability */
    354  1.1  cgd 					return;
    355  1.1  cgd 
    356  1.1  cgd 		case 25:	omnidirect(x,32+clev,"  The %s struggles for air in your flood!"); /* flood */
    357  1.1  cgd 					return;
    358  1.1  cgd 
    359  1.1  cgd 		case 26:	if (rnd(151)==63) { beep(); lprcat("\nYour heart stopped!\n"); nap(4000);  died(270); return; }
    360  1.1  cgd 					if (c[WISDOM]>rnd(10)+10) direct(x,2000,"  The %s's heart stopped",0); /* finger of death */
    361  1.1  cgd 					else lprcat("  It didn't work"); return;
    362  1.1  cgd 
    363  1.1  cgd /* ----- LEVEL 5 SPELLS ----- */
    364  1.1  cgd 
    365  1.1  cgd 		case 27:	c[SCAREMONST] += rnd(10)+clev;  return;  /* scare monster */
    366  1.1  cgd 
    367  1.1  cgd 		case 28:	c[HOLDMONST] += rnd(10)+clev;  return;  /* hold monster */
    368  1.1  cgd 
    369  1.1  cgd 		case 29:	c[TIMESTOP] += rnd(20)+(clev<<1);  return;  /* time stop */
    370  1.1  cgd 
    371  1.1  cgd 		case 30:	tdirect(x);  return;  /* teleport away */
    372  1.1  cgd 
    373  1.1  cgd 		case 31:	omnidirect(x,35+rnd(10)+clev,"  The %s cringes from the flame"); /* magic fire */
    374  1.1  cgd 					return;
    375  1.1  cgd 
    376  1.1  cgd /* ----- LEVEL 6 SPELLS ----- */
    377  1.1  cgd 
    378  1.1  cgd 		case 32:	if ((rnd(23)==5) && (wizard==0)) /* sphere of annihilation */
    379  1.1  cgd 						{
    380  1.1  cgd 						beep(); lprcat("\nYou have been enveloped by the zone of nothingness!\n");
    381  1.1  cgd 						nap(4000);  died(258); return;
    382  1.1  cgd 						}
    383  1.1  cgd 					xl=playerx; yl=playery;
    384  1.1  cgd 					loseint();
    385  1.1  cgd 					i=dirsub(&xl,&yl); /* get direction of sphere */
    386  1.1  cgd 					newsphere(xl,yl,i,rnd(20)+11);	/* make a sphere */
    387  1.1  cgd 					return;
    388  1.1  cgd 
    389  1.1  cgd 		case 33:	genmonst();  spelknow[33]=0;  /* genocide */
    390  1.1  cgd 					loseint();
    391  1.1  cgd 					return;
    392  1.1  cgd 
    393  1.1  cgd 		case 34:	/* summon demon */
    394  1.1  cgd 					if (rnd(100) > 30) { direct(x,150,"  The demon strikes at the %s",0);  return; }
    395  1.1  cgd 					if (rnd(100) > 15) { lprcat("  Nothing seems to have happened");  return; }
    396  1.1  cgd 					lprcat("  The demon turned on you and vanished!"); beep();
    397  1.1  cgd 					i=rnd(40)+30;  lastnum=277;
    398  1.1  cgd 					losehp(i); /* must say killed by a demon */ return;
    399  1.1  cgd 
    400  1.1  cgd 		case 35:	/* walk through walls */
    401  1.1  cgd 					c[WTW] += rnd(10)+5;	return;
    402  1.1  cgd 
    403  1.1  cgd 		case 36:	/* alter reality */
    404  1.1  cgd 					{
    405  1.1  cgd 					struct isave *save;	/* pointer to item save structure */
    406  1.1  cgd 					int sc;	sc=0;	/* # items saved */
    407  1.1  cgd 					save = (struct isave *)malloc(sizeof(struct isave)*MAXX*MAXY*2);
    408  1.1  cgd 					for (j=0; j<MAXY; j++)
    409  1.1  cgd 						for (i=0; i<MAXX; i++) /* save all items and monsters */
    410  1.1  cgd 							{
    411  1.1  cgd 							xl = item[i][j];
    412  1.1  cgd 							if (xl && xl!=OWALL && xl!=OANNIHILATION)
    413  1.1  cgd 								{
    414  1.1  cgd 								save[sc].type=0;  save[sc].id=item[i][j];
    415  1.1  cgd 								save[sc++].arg=iarg[i][j];
    416  1.1  cgd 								}
    417  1.1  cgd 							if (mitem[i][j])
    418  1.1  cgd 								{
    419  1.1  cgd 								save[sc].type=1;  save[sc].id=mitem[i][j];
    420  1.1  cgd 								save[sc++].arg=hitp[i][j];
    421  1.1  cgd 								}
    422  1.1  cgd 							item[i][j]=OWALL;   mitem[i][j]=0;
    423  1.1  cgd 							if (wizard) know[i][j]=1; else know[i][j]=0;
    424  1.1  cgd 							}
    425  1.1  cgd 					eat(1,1);	if (level==1) item[33][MAXY-1]=0;
    426  1.1  cgd 					for (j=rnd(MAXY-2), i=1; i<MAXX-1; i++) item[i][j]=0;
    427  1.1  cgd 					while (sc>0) /* put objects back in level */
    428  1.1  cgd 						{
    429  1.1  cgd 						--sc;
    430  1.1  cgd 						if (save[sc].type == 0)
    431  1.1  cgd 							{
    432  1.1  cgd 							int trys;
    433  1.1  cgd 							for (trys=100, i=j=1; --trys>0 && item[i][j]; i=rnd(MAXX-1), j=rnd(MAXY-1));
    434  1.1  cgd 							if (trys) { item[i][j]=save[sc].id; iarg[i][j]=save[sc].arg; }
    435  1.1  cgd 							}
    436  1.1  cgd 						else
    437  1.1  cgd 							{ /* put monsters back in */
    438  1.1  cgd 							int trys;
    439  1.1  cgd 							for (trys=100, i=j=1; --trys>0 && (item[i][j]==OWALL || mitem[i][j]); i=rnd(MAXX-1), j=rnd(MAXY-1));
    440  1.1  cgd 							if (trys) { mitem[i][j]=save[sc].id; hitp[i][j]=save[sc].arg; }
    441  1.1  cgd 							}
    442  1.1  cgd 						}
    443  1.1  cgd 					loseint();
    444  1.1  cgd 					draws(0,MAXX,0,MAXY);  if (wizard==0) spelknow[36]=0;
    445  1.1  cgd 					free((char*)save);	 positionplayer();  return;
    446  1.1  cgd 					}
    447  1.1  cgd 
    448  1.1  cgd 		case 37:	/* permanence */ adjtime(-99999L);  spelknow[37]=0; /* forget */
    449  1.1  cgd 					loseint();
    450  1.1  cgd 					return;
    451  1.1  cgd 
    452  1.1  cgd 		default:	lprintf("  spell %d not available!",(long)x); beep();  return;
    453  1.1  cgd 		};
    454  1.1  cgd 	}
    455  1.1  cgd 
    456  1.1  cgd /*
    457  1.1  cgd  *	loseint()		Routine to subtract 1 from your int (intelligence) if > 3
    458  1.1  cgd  *
    459  1.1  cgd  *	No arguments and no return value
    460  1.1  cgd  */
    461  1.1  cgd loseint()
    462  1.1  cgd 	{
    463  1.1  cgd 	if (--c[INTELLIGENCE]<3)  c[INTELLIGENCE]=3;
    464  1.1  cgd 	}
    465  1.1  cgd 
    466  1.1  cgd /*
    467  1.1  cgd  *	isconfuse() 		Routine to check to see if player is confused
    468  1.1  cgd  *
    469  1.1  cgd  *	This routine prints out a message saying "You can't aim your magic!"
    470  1.1  cgd  *	returns 0 if not confused, non-zero (time remaining confused) if confused
    471  1.1  cgd  */
    472  1.1  cgd isconfuse()
    473  1.1  cgd 	{
    474  1.1  cgd 	if (c[CONFUSE]) { lprcat(" You can't aim your magic!"); beep(); }
    475  1.1  cgd 	return(c[CONFUSE]);
    476  1.1  cgd 	}
    477  1.1  cgd 
    478  1.1  cgd /*
    479  1.1  cgd  *	nospell(x,monst)	Routine to return 1 if a spell doesn't affect a monster
    480  1.1  cgd  *		int x,monst;
    481  1.1  cgd  *
    482  1.1  cgd  *	Subroutine to return 1 if the spell can't affect the monster
    483  1.1  cgd  *	  otherwise returns 0
    484  1.1  cgd  *	Enter with the spell number in x, and the monster number in monst.
    485  1.1  cgd  */
    486  1.1  cgd nospell(x,monst)
    487  1.1  cgd 	int x,monst;
    488  1.1  cgd 	{
    489  1.1  cgd 	register int tmp;
    490  1.1  cgd 	if (x>=SPNUM || monst>=MAXMONST+8 || monst<0 || x<0) return(0);	/* bad spell or monst */
    491  1.1  cgd 	if ((tmp=spelweird[monst-1][x])==0) return(0);
    492  1.1  cgd 	cursors();  lprc('\n');  lprintf(spelmes[tmp],monster[monst].name);  return(1);
    493  1.1  cgd 	}
    494  1.1  cgd 
    495  1.1  cgd /*
    496  1.1  cgd  *	fullhit(xx)		Function to return full damage against a monster (aka web)
    497  1.1  cgd  *		int xx;
    498  1.1  cgd  *
    499  1.1  cgd  *	Function to return hp damage to monster due to a number of full hits
    500  1.1  cgd  *	Enter with the number of full hits being done
    501  1.1  cgd  */
    502  1.1  cgd fullhit(xx)
    503  1.1  cgd 	int xx;
    504  1.1  cgd 	{
    505  1.1  cgd 	register int i;
    506  1.1  cgd 	if (xx<0 || xx>20) return(0);	/* fullhits are out of range */
    507  1.1  cgd 	if (c[LANCEDEATH]) return(10000);	/* lance of death */
    508  1.1  cgd 	i = xx * ((c[WCLASS]>>1)+c[STRENGTH]+c[STREXTRA]-c[HARDGAME]-12+c[MOREDAM]);
    509  1.1  cgd 	return( (i>=1) ? i : xx );
    510  1.1  cgd 	}
    511  1.1  cgd 
    512  1.1  cgd /*
    513  1.1  cgd  *	direct(spnum,dam,str,arg)	Routine to direct spell damage 1 square in 1 dir
    514  1.1  cgd  *		int spnum,dam,arg;
    515  1.1  cgd  *		char *str;
    516  1.1  cgd  *
    517  1.1  cgd  *	Routine to ask for a direction to a spell and then hit the monster
    518  1.1  cgd  *	Enter with the spell number in spnum, the damage to be done in dam,
    519  1.1  cgd  *	  lprintf format string in str, and lprintf's argument in arg.
    520  1.1  cgd  *	Returns no value.
    521  1.1  cgd  */
    522  1.1  cgd direct(spnum,dam,str,arg)
    523  1.1  cgd 	int spnum,dam,arg;
    524  1.1  cgd 	char *str;
    525  1.1  cgd 	{
    526  1.1  cgd 	int x,y;
    527  1.1  cgd 	register int m;
    528  1.1  cgd 	if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad arguments */
    529  1.1  cgd 	if (isconfuse()) return;
    530  1.1  cgd 	dirsub(&x,&y);
    531  1.1  cgd 	m = mitem[x][y];
    532  1.1  cgd 	if (item[x][y]==OMIRROR)
    533  1.1  cgd 		{
    534  1.1  cgd 		if (spnum==3) /* sleep */
    535  1.1  cgd 			{
    536  1.1  cgd 			lprcat("You fall asleep! "); beep();
    537  1.1  cgd 		fool:
    538  1.1  cgd 			arg += 2;
    539  1.1  cgd 			while (arg-- > 0) { parse2(); nap(1000); }
    540  1.1  cgd 			return;
    541  1.1  cgd 			}
    542  1.1  cgd 		else if (spnum==6) /* web */
    543  1.1  cgd 			{
    544  1.1  cgd 			lprcat("You get stuck in your own web! "); beep();
    545  1.1  cgd 			goto fool;
    546  1.1  cgd 			}
    547  1.1  cgd 		else
    548  1.1  cgd 			{
    549  1.1  cgd 			lastnum=278;
    550  1.1  cgd 			lprintf(str,"spell caster (thats you)",(long)arg);
    551  1.1  cgd 			beep(); losehp(dam); return;
    552  1.1  cgd 			}
    553  1.1  cgd 		}
    554  1.1  cgd 	if (m==0)
    555  1.1  cgd 		{	lprcat("  There wasn't anything there!");	return;  }
    556  1.1  cgd 	ifblind(x,y);
    557  1.1  cgd 	if (nospell(spnum,m)) { lasthx=x;  lasthy=y; return; }
    558  1.1  cgd 	lprintf(str,lastmonst,(long)arg);       hitm(x,y,dam);
    559  1.1  cgd 	}
    560  1.1  cgd 
    561  1.1  cgd /*
    562  1.1  cgd  *	godirect(spnum,dam,str,delay,cshow)		Function to perform missile attacks
    563  1.1  cgd  *		int spnum,dam,delay;
    564  1.1  cgd  *		char *str,cshow;
    565  1.1  cgd  *
    566  1.1  cgd  *	Function to hit in a direction from a missile weapon and have it keep
    567  1.1  cgd  *	on going in that direction until its power is exhausted
    568  1.1  cgd  *	Enter with the spell number in spnum, the power of the weapon in hp,
    569  1.1  cgd  *	  lprintf format string in str, the # of milliseconds to delay between
    570  1.1  cgd  *	  locations in delay, and the character to represent the weapon in cshow.
    571  1.1  cgd  *	Returns no value.
    572  1.1  cgd  */
    573  1.1  cgd godirect(spnum,dam,str,delay,cshow)
    574  1.1  cgd 	int spnum,dam,delay;
    575  1.1  cgd 	char *str,cshow;
    576  1.1  cgd 	{
    577  1.1  cgd 	register char *p;
    578  1.1  cgd 	register int x,y,m;
    579  1.1  cgd 	int dx,dy;
    580  1.1  cgd 	if (spnum<0 || spnum>=SPNUM || str==0 || delay<0) return; /* bad args */
    581  1.1  cgd 	if (isconfuse()) return;
    582  1.1  cgd 	dirsub(&dx,&dy);	x=dx;	y=dy;
    583  1.1  cgd 	dx = x-playerx;		dy = y-playery;		x = playerx;	y = playery;
    584  1.1  cgd 	while (dam>0)
    585  1.1  cgd 		{
    586  1.1  cgd 		x += dx;    y += dy;
    587  1.1  cgd 	    if ((x > MAXX-1) || (y > MAXY-1) || (x < 0) || (y < 0))
    588  1.1  cgd 			{
    589  1.1  cgd 			dam=0;	break;  /* out of bounds */
    590  1.1  cgd 			}
    591  1.1  cgd 		if ((x==playerx) && (y==playery)) /* if energy hits player */
    592  1.1  cgd 			{
    593  1.1  cgd 			cursors(); lprcat("\nYou are hit my your own magic!"); beep();
    594  1.1  cgd 			lastnum=278;  losehp(dam);  return;
    595  1.1  cgd 			}
    596  1.1  cgd 		if (c[BLINDCOUNT]==0) /* if not blind show effect */
    597  1.1  cgd 			{
    598  1.1  cgd 			cursor(x+1,y+1); lprc(cshow); nap(delay); show1cell(x,y);
    599  1.1  cgd 			}
    600  1.1  cgd 		if ((m=mitem[x][y]))	/* is there a monster there? */
    601  1.1  cgd 			{
    602  1.1  cgd 			ifblind(x,y);
    603  1.1  cgd 			if (nospell(spnum,m)) { lasthx=x;  lasthy=y; return; }
    604  1.1  cgd 			cursors(); lprc('\n');
    605  1.1  cgd 			lprintf(str,lastmonst);		dam -= hitm(x,y,dam);
    606  1.1  cgd 			show1cell(x,y);  nap(1000);		x -= dx;	y -= dy;
    607  1.1  cgd 			}
    608  1.1  cgd 		else switch (*(p= &item[x][y]))
    609  1.1  cgd 			{
    610  1.1  cgd 			case OWALL:	cursors(); lprc('\n'); lprintf(str,"wall");
    611  1.1  cgd 						if (dam>=50+c[HARDGAME]) /* enough damage? */
    612  1.1  cgd 						 if (level<MAXLEVEL+MAXVLEVEL-1) /* not on V3 */
    613  1.1  cgd 						  if ((x<MAXX-1) && (y<MAXY-1) && (x) && (y))
    614  1.1  cgd 							{
    615  1.1  cgd 							lprcat("  The wall crumbles");
    616  1.1  cgd 					god3:	*p=0;
    617  1.1  cgd 					god:	know[x][y]=0;
    618  1.1  cgd 							show1cell(x,y);
    619  1.1  cgd 							}
    620  1.1  cgd 				god2:	dam = 0;	break;
    621  1.1  cgd 
    622  1.1  cgd 			case OCLOSEDDOOR:	cursors(); lprc('\n'); lprintf(str,"door");
    623  1.1  cgd 						if (dam>=40)
    624  1.1  cgd 							{
    625  1.1  cgd 							lprcat("  The door is blasted apart");
    626  1.1  cgd 							goto god3;
    627  1.1  cgd 							}
    628  1.1  cgd 						goto god2;
    629  1.1  cgd 
    630  1.1  cgd 			case OSTATUE:	cursors(); lprc('\n'); lprintf(str,"statue");
    631  1.1  cgd 						if (c[HARDGAME]<3)
    632  1.1  cgd 						  if (dam>44)
    633  1.1  cgd 							{
    634  1.1  cgd 							lprcat("  The statue crumbles");
    635  1.1  cgd 							*p=OBOOK; iarg[x][y]=level;
    636  1.1  cgd 							goto god;
    637  1.1  cgd 							}
    638  1.1  cgd 						goto god2;
    639  1.1  cgd 
    640  1.1  cgd 			case OTHRONE:	cursors(); lprc('\n'); lprintf(str,"throne");
    641  1.1  cgd 					if (dam>39)
    642  1.1  cgd 						{
    643  1.1  cgd 						mitem[x][y]=GNOMEKING; hitp[x][y]=monster[GNOMEKING].hitpoints;
    644  1.1  cgd 						*p = OTHRONE2;
    645  1.1  cgd 						goto god;
    646  1.1  cgd 						}
    647  1.1  cgd 					goto god2;
    648  1.1  cgd 
    649  1.1  cgd 			case OMIRROR:	dx *= -1;	dy *= -1;	break;
    650  1.1  cgd 			};
    651  1.1  cgd 		dam -= 3 + (c[HARDGAME]>>1);
    652  1.1  cgd 		}
    653  1.1  cgd 	}
    654  1.1  cgd 
    655  1.1  cgd /*
    656  1.1  cgd  *	ifblind(x,y)	Routine to put "monster" or the monster name into lastmosnt
    657  1.1  cgd  *		int x,y;
    658  1.1  cgd  *
    659  1.1  cgd  *	Subroutine to copy the word "monster" into lastmonst if the player is blind
    660  1.1  cgd  *	Enter with the coordinates (x,y) of the monster
    661  1.1  cgd  *	Returns no value.
    662  1.1  cgd  */
    663  1.1  cgd ifblind(x,y)
    664  1.1  cgd 	int x,y;
    665  1.1  cgd 	{
    666  1.1  cgd 	char *p;
    667  1.1  cgd 	vxy(&x,&y);	/* verify correct x,y coordinates */
    668  1.1  cgd 	if (c[BLINDCOUNT]) { lastnum=279;  p="monster"; }
    669  1.1  cgd 		else { lastnum=mitem[x][y];  p=monster[lastnum].name; }
    670  1.1  cgd 	strcpy(lastmonst,p);
    671  1.1  cgd 	}
    672  1.1  cgd 
    673  1.1  cgd /*
    674  1.1  cgd  *	tdirect(spnum)		Routine to teleport away a monster
    675  1.1  cgd  *		int spnum;
    676  1.1  cgd  *
    677  1.1  cgd  *	Routine to ask for a direction to a spell and then teleport away monster
    678  1.1  cgd  *	Enter with the spell number that wants to teleport away
    679  1.1  cgd  *	Returns no value.
    680  1.1  cgd  */
    681  1.1  cgd tdirect(spnum)
    682  1.1  cgd 	int spnum;
    683  1.1  cgd 	{
    684  1.1  cgd 	int x,y;
    685  1.1  cgd 	register int m;
    686  1.1  cgd 	if (spnum<0 || spnum>=SPNUM) return; /* bad args */
    687  1.1  cgd 	if (isconfuse()) return;
    688  1.1  cgd 	dirsub(&x,&y);
    689  1.1  cgd 	if ((m=mitem[x][y])==0)
    690  1.1  cgd 		{	lprcat("  There wasn't anything there!");	return;  }
    691  1.1  cgd 	ifblind(x,y);
    692  1.1  cgd 	if (nospell(spnum,m)) { lasthx=x;  lasthy=y; return; }
    693  1.1  cgd 	fillmonst(m);  mitem[x][y]=know[x][y]=0;
    694  1.1  cgd 	}
    695  1.1  cgd 
    696  1.1  cgd /*
    697  1.1  cgd  *	omnidirect(sp,dam,str)   Routine to damage all monsters 1 square from player
    698  1.1  cgd  *		int sp,dam;
    699  1.1  cgd  *		char *str;
    700  1.1  cgd  *
    701  1.1  cgd  *	Routine to cast a spell and then hit the monster in all directions
    702  1.1  cgd  *	Enter with the spell number in sp, the damage done to wach square in dam,
    703  1.1  cgd  *	  and the lprintf string to identify the spell in str.
    704  1.1  cgd  *	Returns no value.
    705  1.1  cgd  */
    706  1.1  cgd omnidirect(spnum,dam,str)
    707  1.1  cgd 	int spnum,dam;
    708  1.1  cgd 	char *str;
    709  1.1  cgd 	{
    710  1.1  cgd 	register int x,y,m;
    711  1.1  cgd 	if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad args */
    712  1.1  cgd 	for (x=playerx-1; x<playerx+2; x++)
    713  1.1  cgd 		for (y=playery-1; y<playery+2; y++)
    714  1.1  cgd 			{
    715  1.1  cgd 			if (m=mitem[x][y])
    716  1.1  cgd 				if (nospell(spnum,m) == 0)
    717  1.1  cgd 					{
    718  1.1  cgd 					ifblind(x,y);
    719  1.1  cgd 					cursors(); lprc('\n'); lprintf(str,lastmonst);
    720  1.1  cgd 					hitm(x,y,dam);  nap(800);
    721  1.1  cgd 					}
    722  1.1  cgd 				else  { lasthx=x;  lasthy=y; }
    723  1.1  cgd 			}
    724  1.1  cgd 	}
    725  1.1  cgd 
    726  1.1  cgd /*
    727  1.1  cgd  *	static dirsub(x,y)		Routine to ask for direction, then modify x,y for it
    728  1.1  cgd  *		int *x,*y;
    729  1.1  cgd  *
    730  1.1  cgd  *	Function to ask for a direction and modify an x,y for that direction
    731  1.1  cgd  *	Enter with the origination coordinates in (x,y).
    732  1.1  cgd  *	Returns index into diroffx[] (0-8).
    733  1.1  cgd  */
    734  1.1  cgd static int
    735  1.1  cgd dirsub(x,y)
    736  1.1  cgd 	int *x,*y;
    737  1.1  cgd 	{
    738  1.1  cgd 	register int i;
    739  1.1  cgd 	lprcat("\nIn What Direction? ");
    740  1.1  cgd 	for (i=0; ; )
    741  1.1  cgd 		switch(getchar())
    742  1.1  cgd 			{
    743  1.1  cgd 			case 'b':	i++;
    744  1.1  cgd 			case 'n':	i++;
    745  1.1  cgd 			case 'y':	i++;
    746  1.1  cgd 			case 'u':	i++;
    747  1.1  cgd 			case 'h':	i++;
    748  1.1  cgd 			case 'k':	i++;
    749  1.1  cgd 			case 'l':	i++;
    750  1.1  cgd 			case 'j':	i++;		goto out;
    751  1.1  cgd 			};
    752  1.1  cgd out:
    753  1.1  cgd 	*x = playerx+diroffx[i];		*y = playery+diroffy[i];
    754  1.1  cgd 	vxy(x,y);  return(i);
    755  1.1  cgd 	}
    756  1.1  cgd 
    757  1.1  cgd /*
    758  1.1  cgd  *	vxy(x,y)	   Routine to verify/fix coordinates for being within bounds
    759  1.1  cgd  *		int *x,*y;
    760  1.1  cgd  *
    761  1.1  cgd  *	Function to verify x & y are within the bounds for a level
    762  1.1  cgd  *	If *x or *y is not within the absolute bounds for a level, fix them so that
    763  1.1  cgd  *	  they are on the level.
    764  1.1  cgd  *	Returns TRUE if it was out of bounds, and the *x & *y in the calling
    765  1.1  cgd  *	routine are affected.
    766  1.1  cgd  */
    767  1.1  cgd vxy(x,y)
    768  1.1  cgd 	int *x,*y;
    769  1.1  cgd 	{
    770  1.1  cgd 	int flag=0;
    771  1.1  cgd 	if (*x<0) { *x=0; flag++; }
    772  1.1  cgd 	if (*y<0) { *y=0; flag++; }
    773  1.1  cgd 	if (*x>=MAXX) { *x=MAXX-1; flag++; }
    774  1.1  cgd 	if (*y>=MAXY) { *y=MAXY-1; flag++; }
    775  1.1  cgd 	return(flag);
    776  1.1  cgd 	}
    777  1.1  cgd 
    778  1.1  cgd /*
    779  1.1  cgd  *	dirpoly(spnum)		Routine to ask for a direction and polymorph a monst
    780  1.1  cgd  *		int spnum;
    781  1.1  cgd  *
    782  1.1  cgd  *	Subroutine to polymorph a monster and ask for the direction its in
    783  1.1  cgd  *	Enter with the spell number in spmun.
    784  1.1  cgd  *	Returns no value.
    785  1.1  cgd  */
    786  1.1  cgd dirpoly(spnum)
    787  1.1  cgd 	int spnum;
    788  1.1  cgd 	{
    789  1.1  cgd 	int x,y,m;
    790  1.1  cgd 	if (spnum<0 || spnum>=SPNUM) return; /* bad args */
    791  1.1  cgd 	if (isconfuse()) return;	/* if he is confused, he can't aim his magic */
    792  1.1  cgd 	dirsub(&x,&y);
    793  1.1  cgd 	if (mitem[x][y]==0)
    794  1.1  cgd 		{	lprcat("  There wasn't anything there!");	return;  }
    795  1.1  cgd 	ifblind(x,y);
    796  1.1  cgd 	if (nospell(spnum,mitem[x][y])) { lasthx=x;  lasthy=y; return; }
    797  1.1  cgd 	while ( monster[m = mitem[x][y] = rnd(MAXMONST+7)].genocided );
    798  1.1  cgd 	hitp[x][y] = monster[m].hitpoints;
    799  1.1  cgd 	show1cell(x,y);  /* show the new monster */
    800  1.1  cgd 	}
    801  1.1  cgd 
    802  1.1  cgd /*
    803  1.1  cgd  *	hitmonster(x,y) 	Function to hit a monster at the designated coordinates
    804  1.1  cgd  *		int x,y;
    805  1.1  cgd  *
    806  1.1  cgd  *	This routine is used for a bash & slash type attack on a monster
    807  1.1  cgd  *	Enter with the coordinates of the monster in (x,y).
    808  1.1  cgd  *	Returns no value.
    809  1.1  cgd  */
    810  1.1  cgd hitmonster(x,y)
    811  1.1  cgd 	int x,y;
    812  1.1  cgd 	{
    813  1.1  cgd 	register int tmp,monst,damag,flag;
    814  1.1  cgd 	if (c[TIMESTOP])  return;  /* not if time stopped */
    815  1.1  cgd 	vxy(&x,&y);	/* verify coordinates are within range */
    816  1.1  cgd 	if ((monst = mitem[x][y]) == 0) return;
    817  1.1  cgd 	hit3flag=1;  ifblind(x,y);
    818  1.1  cgd 	tmp = monster[monst].armorclass + c[LEVEL] + c[DEXTERITY] + c[WCLASS]/4 - 12;
    819  1.1  cgd 	cursors();
    820  1.1  cgd 	if ((rnd(20) < tmp-c[HARDGAME]) || (rnd(71) < 5)) /* need at least random chance to hit */
    821  1.1  cgd 		{
    822  1.1  cgd 		lprcat("\nYou hit");  flag=1;
    823  1.1  cgd 		damag = fullhit(1);
    824  1.1  cgd 		if (damag<9999) damag=rnd(damag)+1;
    825  1.1  cgd 		}
    826  1.1  cgd 	else
    827  1.1  cgd 		{
    828  1.1  cgd 		lprcat("\nYou missed");  flag=0;
    829  1.1  cgd 		}
    830  1.1  cgd 	lprcat(" the "); lprcat(lastmonst);
    831  1.1  cgd 	if (flag)	/* if the monster was hit */
    832  1.1  cgd 	  if ((monst==RUSTMONSTER) || (monst==DISENCHANTRESS) || (monst==CUBE))
    833  1.1  cgd 		if (c[WIELD]>0)
    834  1.1  cgd 		  if (ivenarg[c[WIELD]] > -10)
    835  1.1  cgd 			{
    836  1.1  cgd 			lprintf("\nYour weapon is dulled by the %s",lastmonst); beep();
    837  1.1  cgd 			--ivenarg[c[WIELD]];
    838  1.1  cgd 			}
    839  1.1  cgd 	if (flag)  hitm(x,y,damag);
    840  1.1  cgd 	if (monst == VAMPIRE) if (hitp[x][y]<25)  { mitem[x][y]=BAT; know[x][y]=0; }
    841  1.1  cgd 	}
    842  1.1  cgd 
    843  1.1  cgd /*
    844  1.1  cgd  *	hitm(x,y,amt)		Function to just hit a monster at a given coordinates
    845  1.1  cgd  *		int x,y,amt;
    846  1.1  cgd  *
    847  1.1  cgd  *	Returns the number of hitpoints the monster absorbed
    848  1.1  cgd  *	This routine is used to specifically damage a monster at a location (x,y)
    849  1.1  cgd  *	Called by hitmonster(x,y)
    850  1.1  cgd  */
    851  1.1  cgd hitm(x,y,amt)
    852  1.1  cgd 	int x,y;
    853  1.1  cgd 	register amt;
    854  1.1  cgd 	{
    855  1.1  cgd 	register int monst;
    856  1.1  cgd 	int hpoints,amt2;
    857  1.1  cgd 	vxy(&x,&y);	/* verify coordinates are within range */
    858  1.1  cgd 	amt2 = amt;		/* save initial damage so we can return it */
    859  1.1  cgd 	monst = mitem[x][y];
    860  1.1  cgd 	if (c[HALFDAM]) amt >>= 1;	/* if half damage curse adjust damage points */
    861  1.1  cgd 	if (amt<=0) amt2 = amt = 1;
    862  1.1  cgd 	lasthx=x;  lasthy=y;
    863  1.1  cgd 	stealth[x][y]=1;	/* make sure hitting monst breaks stealth condition */
    864  1.1  cgd 	c[HOLDMONST]=0;	/* hit a monster breaks hold monster spell	*/
    865  1.1  cgd 	switch(monst) /* if a dragon and orb(s) of dragon slaying	*/
    866  1.1  cgd 		{
    867  1.1  cgd 		case WHITEDRAGON:		case REDDRAGON:			case GREENDRAGON:
    868  1.1  cgd 		case BRONZEDRAGON:		case PLATINUMDRAGON:	case SILVERDRAGON:
    869  1.1  cgd 			amt *= 1+(c[SLAYING]<<1);	break;
    870  1.1  cgd 		}
    871  1.1  cgd /* invincible monster fix is here */
    872  1.1  cgd 	if (hitp[x][y] > monster[monst].hitpoints)
    873  1.1  cgd 		hitp[x][y] = monster[monst].hitpoints;
    874  1.1  cgd 	if ((hpoints = hitp[x][y]) <= amt)
    875  1.1  cgd 		{
    876  1.1  cgd #ifdef EXTRA
    877  1.1  cgd 		c[MONSTKILLED]++;
    878  1.1  cgd #endif
    879  1.1  cgd 		lprintf("\nThe %s died!",lastmonst);
    880  1.1  cgd 		raiseexperience((long)monster[monst].experience);
    881  1.1  cgd 		amt = monster[monst].gold;  if (amt>0) dropgold(rnd(amt)+amt);
    882  1.1  cgd 		dropsomething(monst);	disappear(x,y);	bottomline();
    883  1.1  cgd 		return(hpoints);
    884  1.1  cgd 		}
    885  1.1  cgd 	hitp[x][y] = hpoints-amt;	return(amt2);
    886  1.1  cgd 	}
    887  1.1  cgd 
    888  1.1  cgd /*
    889  1.1  cgd  *	hitplayer(x,y) 		Function for the monster to hit the player from (x,y)
    890  1.1  cgd  *		int x,y;
    891  1.1  cgd  *
    892  1.1  cgd  *	Function for the monster to hit the player with monster at location x,y
    893  1.1  cgd  *	Returns nothing of value.
    894  1.1  cgd  */
    895  1.1  cgd hitplayer(x,y)
    896  1.1  cgd 	int x,y;
    897  1.1  cgd 	{
    898  1.1  cgd 	register int dam,tmp,mster,bias;
    899  1.1  cgd 	vxy(&x,&y);	/* verify coordinates are within range */
    900  1.1  cgd 	lastnum = mster = mitem[x][y];
    901  1.1  cgd /*	spirit naga's and poltergeist's do nothing if scarab of negate spirit	*/
    902  1.1  cgd 	if (c[NEGATESPIRIT] || c[SPIRITPRO])  if ((mster ==POLTERGEIST) || (mster ==SPIRITNAGA))  return;
    903  1.1  cgd /*	if undead and cube of undead control	*/
    904  1.1  cgd 	if (c[CUBEofUNDEAD] || c[UNDEADPRO]) if ((mster ==VAMPIRE) || (mster ==WRAITH) || (mster ==ZOMBIE)) return;
    905  1.1  cgd 	if ((know[x][y]&1) == 0)
    906  1.1  cgd 		{
    907  1.1  cgd 		know[x][y]=1; show1cell(x,y);
    908  1.1  cgd 		}
    909  1.1  cgd 	bias = (c[HARDGAME]) + 1;
    910  1.1  cgd 	hitflag = hit2flag = hit3flag = 1;
    911  1.1  cgd 	yrepcount=0;
    912  1.1  cgd 	cursors();	ifblind(x,y);
    913  1.1  cgd 	if (c[INVISIBILITY]) if (rnd(33)<20)
    914  1.1  cgd 		{
    915  1.1  cgd 		lprintf("\nThe %s misses wildly",lastmonst);	return;
    916  1.1  cgd 		}
    917  1.1  cgd 	if (c[CHARMCOUNT]) if (rnd(30)+5*monster[mster].level-c[CHARISMA]<30)
    918  1.1  cgd 		{
    919  1.1  cgd 		lprintf("\nThe %s is awestruck at your magnificence!",lastmonst);
    920  1.1  cgd 		return;
    921  1.1  cgd 		}
    922  1.1  cgd 	if (mster==BAT) dam=1;
    923  1.1  cgd 	else
    924  1.1  cgd 		{
    925  1.1  cgd 		dam = monster[mster].damage;
    926  1.1  cgd 		dam += rnd((int)((dam<1)?1:dam)) + monster[mster].level;
    927  1.1  cgd 		}
    928  1.1  cgd 	tmp = 0;
    929  1.1  cgd 	if (monster[mster].attack>0)
    930  1.1  cgd 	  if (((dam + bias + 8) > c[AC]) || (rnd((int)((c[AC]>0)?c[AC]:1))==1))
    931  1.1  cgd 		{ if (spattack(monster[mster].attack,x,y)) { flushall(); return; }
    932  1.1  cgd 		  tmp = 1;  bias -= 2; cursors(); }
    933  1.1  cgd 	if (((dam + bias) > c[AC]) || (rnd((int)((c[AC]>0)?c[AC]:1))==1))
    934  1.1  cgd 		{
    935  1.1  cgd 		lprintf("\n  The %s hit you ",lastmonst);	tmp = 1;
    936  1.1  cgd 		if ((dam -= c[AC]) < 0) dam=0;
    937  1.1  cgd 		if (dam > 0) { losehp(dam); bottomhp(); flushall(); }
    938  1.1  cgd 		}
    939  1.1  cgd 	if (tmp == 0)  lprintf("\n  The %s missed ",lastmonst);
    940  1.1  cgd 	}
    941  1.1  cgd 
    942  1.1  cgd /*
    943  1.1  cgd  *	dropsomething(monst) 	Function to create an object when a monster dies
    944  1.1  cgd  *		int monst;
    945  1.1  cgd  *
    946  1.1  cgd  *	Function to create an object near the player when certain monsters are killed
    947  1.1  cgd  *	Enter with the monster number
    948  1.1  cgd  *	Returns nothing of value.
    949  1.1  cgd  */
    950  1.1  cgd dropsomething(monst)
    951  1.1  cgd 	int monst;
    952  1.1  cgd 	{
    953  1.1  cgd 	switch(monst)
    954  1.1  cgd 		{
    955  1.1  cgd 		case ORC:			  case NYMPH:	   case ELF:	  case TROGLODYTE:
    956  1.1  cgd 		case TROLL:			  case ROTHE:	   case VIOLETFUNGI:
    957  1.1  cgd 		case PLATINUMDRAGON:  case GNOMEKING:  case REDDRAGON:
    958  1.1  cgd 			something(level); return;
    959  1.1  cgd 
    960  1.1  cgd 		case LEPRECHAUN: if (rnd(101)>=75) creategem();
    961  1.1  cgd 						 if (rnd(5)==1) dropsomething(LEPRECHAUN);   return;
    962  1.1  cgd 		}
    963  1.1  cgd 	}
    964  1.1  cgd 
    965  1.1  cgd /*
    966  1.1  cgd  *	dropgold(amount) 	Function to drop some gold around player
    967  1.1  cgd  *		int amount;
    968  1.1  cgd  *
    969  1.1  cgd  *	Enter with the number of gold pieces to drop
    970  1.1  cgd  *	Returns nothing of value.
    971  1.1  cgd  */
    972  1.1  cgd dropgold(amount)
    973  1.1  cgd 	register int amount;
    974  1.1  cgd 	{
    975  1.1  cgd 	if (amount > 250) createitem(OMAXGOLD,amount/100);  else  createitem(OGOLDPILE,amount);
    976  1.1  cgd 	}
    977  1.1  cgd 
    978  1.1  cgd /*
    979  1.1  cgd  *	something(level) 	Function to create a random item around player
    980  1.1  cgd  *		int level;
    981  1.1  cgd  *
    982  1.1  cgd  *	Function to create an item from a designed probability around player
    983  1.1  cgd  *	Enter with the cave level on which something is to be dropped
    984  1.1  cgd  *	Returns nothing of value.
    985  1.1  cgd  */
    986  1.1  cgd something(level)
    987  1.1  cgd 	int level;
    988  1.1  cgd 	{
    989  1.1  cgd 	register int j;
    990  1.1  cgd 	int i;
    991  1.1  cgd 	if (level<0 || level>MAXLEVEL+MAXVLEVEL) return;	/* correct level? */
    992  1.1  cgd 	if (rnd(101)<8) something(level); /* possibly more than one item */
    993  1.1  cgd 	j = newobject(level,&i);		createitem(j,i);
    994  1.1  cgd 	}
    995  1.1  cgd 
    996  1.1  cgd /*
    997  1.1  cgd  *	newobject(lev,i) 	Routine to return a randomly selected new object
    998  1.1  cgd  *		int lev,*i;
    999  1.1  cgd  *
   1000  1.1  cgd  *	Routine to return a randomly selected object to be created
   1001  1.1  cgd  *	Returns the object number created, and sets *i for its argument
   1002  1.1  cgd  *	Enter with the cave level and a pointer to the items arg
   1003  1.1  cgd  */
   1004  1.1  cgd static char nobjtab[] = { 0, OSCROLL,  OSCROLL,  OSCROLL,  OSCROLL, OPOTION,
   1005  1.1  cgd 	OPOTION, OPOTION, OPOTION, OGOLDPILE, OGOLDPILE, OGOLDPILE, OGOLDPILE,
   1006  1.1  cgd 	OBOOK, OBOOK, OBOOK, OBOOK, ODAGGER, ODAGGER, ODAGGER, OLEATHER, OLEATHER,
   1007  1.1  cgd 	OLEATHER, OREGENRING, OPROTRING, OENERGYRING, ODEXRING, OSTRRING, OSPEAR,
   1008  1.1  cgd 	OBELT, ORING, OSTUDLEATHER, OSHIELD, OFLAIL, OCHAIN, O2SWORD, OPLATE,
   1009  1.1  cgd 	OLONGSWORD };
   1010  1.1  cgd 
   1011  1.1  cgd newobject(lev,i)
   1012  1.1  cgd 	register int lev,*i;
   1013  1.1  cgd 	{
   1014  1.1  cgd 	register int tmp=32,j;
   1015  1.1  cgd 	if (level<0 || level>MAXLEVEL+MAXVLEVEL) return(0);	/* correct level? */
   1016  1.1  cgd 	if (lev>6) tmp=37; else if (lev>4) tmp=35;
   1017  1.1  cgd 	j = nobjtab[tmp=rnd(tmp)];	/* the object type */
   1018  1.1  cgd 	switch(tmp)
   1019  1.1  cgd 		{
   1020  1.1  cgd 		case 1: case 2: case 3: case 4:	*i=newscroll();	break;
   1021  1.1  cgd 		case 5: case 6: case 7: case 8:	*i=newpotion();	break;
   1022  1.1  cgd 		case 9: case 10: case 11: case 12: *i=rnd((lev+1)*10)+lev*10+10; break;
   1023  1.1  cgd 		case 13: case 14: case 15: case 16:	*i=lev;	break;
   1024  1.1  cgd 		case 17: case 18: case 19: if (!(*i=newdagger()))  return(0);  break;
   1025  1.1  cgd 		case 20: case 21: case 22: if (!(*i=newleather()))  return(0);  break;
   1026  1.1  cgd 		case 23: case 32: case 35: *i=rund(lev/3+1); break;
   1027  1.1  cgd 		case 24: case 26: *i=rnd(lev/4+1);   break;
   1028  1.1  cgd 		case 25: *i=rund(lev/4+1); break;
   1029  1.1  cgd 		case 27: *i=rnd(lev/2+1);   break;
   1030  1.1  cgd 		case 30: case 33: *i=rund(lev/2+1);   break;
   1031  1.1  cgd 		case 28: *i=rund(lev/3+1); if (*i==0) return(0); break;
   1032  1.1  cgd 		case 29: case 31: *i=rund(lev/2+1); if (*i==0) return(0); break;
   1033  1.1  cgd 		case 34: *i=newchain();   	break;
   1034  1.1  cgd 		case 36: *i=newplate();   	break;
   1035  1.1  cgd 		case 37: *i=newsword();		break;
   1036  1.1  cgd 		}
   1037  1.1  cgd 	return(j);
   1038  1.1  cgd 	}
   1039  1.1  cgd 
   1040  1.1  cgd /*
   1041  1.1  cgd  *  spattack(atckno,xx,yy) 	Function to process special attacks from monsters
   1042  1.1  cgd  *  	int atckno,xx,yy;
   1043  1.1  cgd  *
   1044  1.1  cgd  *	Enter with the special attack number, and the coordinates (xx,yy)
   1045  1.1  cgd  *		of the monster that is special attacking
   1046  1.1  cgd  *	Returns 1 if must do a show1cell(xx,yy) upon return, 0 otherwise
   1047  1.1  cgd  *
   1048  1.1  cgd  * atckno   monster     effect
   1049  1.1  cgd  * ---------------------------------------------------
   1050  1.1  cgd  *	0	none
   1051  1.1  cgd  *	1	rust monster	eat armor
   1052  1.1  cgd  *	2	hell hound		breathe light fire
   1053  1.1  cgd  *	3	dragon			breathe fire
   1054  1.1  cgd  *	4	giant centipede	weakening sing
   1055  1.1  cgd  *	5	white dragon	cold breath
   1056  1.1  cgd  *	6	wraith			drain level
   1057  1.1  cgd  *	7	waterlord		water gusher
   1058  1.1  cgd  *	8	leprechaun		steal gold
   1059  1.1  cgd  *	9	disenchantress	disenchant weapon or armor
   1060  1.1  cgd  *	10	ice lizard		hits with barbed tail
   1061  1.1  cgd  *	11	umber hulk		confusion
   1062  1.1  cgd  *	12	spirit naga		cast spells	taken from special attacks
   1063  1.1  cgd  *	13	platinum dragon	psionics
   1064  1.1  cgd  *	14	nymph			steal objects
   1065  1.1  cgd  *	15	bugbear			bite
   1066  1.1  cgd  *	16	osequip			bite
   1067  1.1  cgd  *
   1068  1.1  cgd  *	char rustarm[ARMORTYPES][2];
   1069  1.1  cgd  *	special array for maximum rust damage to armor from rustmonster
   1070  1.1  cgd  *	format is: { armor type , minimum attribute
   1071  1.1  cgd  */
   1072  1.1  cgd #define ARMORTYPES 6
   1073  1.1  cgd static char rustarm[ARMORTYPES][2] = { OSTUDLEATHER,-2,	ORING,-4, OCHAIN,-5,
   1074  1.1  cgd 	OSPLINT,-6,		OPLATE,-8,		OPLATEARMOR,-9  };
   1075  1.1  cgd static char spsel[] = { 1, 2, 3, 5, 6, 8, 9, 11, 13, 14 };
   1076  1.1  cgd spattack(x,xx,yy)
   1077  1.1  cgd 	int x,xx,yy;
   1078  1.1  cgd 	{
   1079  1.1  cgd 	register int i,j=0,k,m;
   1080  1.1  cgd 	register char *p=0;
   1081  1.1  cgd 	if (c[CANCELLATION]) return(0);
   1082  1.1  cgd 	vxy(&xx,&yy);	/* verify x & y coordinates */
   1083  1.1  cgd 	switch(x)
   1084  1.1  cgd 		{
   1085  1.1  cgd 		case 1:	/* rust your armor, j=1 when rusting has occurred */
   1086  1.1  cgd 				m = k = c[WEAR];
   1087  1.1  cgd 				if ((i=c[SHIELD]) != -1)
   1088  1.1  cgd 					if (--ivenarg[i] < -1) ivenarg[i]= -1; else j=1;
   1089  1.1  cgd 				if ((j==0) && (k != -1))
   1090  1.1  cgd 				  {
   1091  1.1  cgd 				  m = iven[k];
   1092  1.1  cgd 				  for (i=0; i<ARMORTYPES; i++)
   1093  1.1  cgd 					if (m == rustarm[i][0]) /* find his armor in table */
   1094  1.1  cgd 						{
   1095  1.1  cgd 						if (--ivenarg[k]< rustarm[i][1])
   1096  1.1  cgd 							ivenarg[k]= rustarm[i][1]; else j=1;
   1097  1.1  cgd 						break;
   1098  1.1  cgd 						}
   1099  1.1  cgd 				  }
   1100  1.1  cgd 				if (j==0)	/* if rusting did not occur */
   1101  1.1  cgd 				  switch(m)
   1102  1.1  cgd 					{
   1103  1.1  cgd 					case OLEATHER:	p = "\nThe %s hit you -- Your lucky you have leather on";
   1104  1.1  cgd 									break;
   1105  1.1  cgd 				    case OSSPLATE:	p = "\nThe %s hit you -- Your fortunate to have stainless steel armor!";
   1106  1.1  cgd 									break;
   1107  1.1  cgd 					}
   1108  1.1  cgd 				else  { beep(); p = "\nThe %s hit you -- your armor feels weaker"; }
   1109  1.1  cgd 				break;
   1110  1.1  cgd 
   1111  1.1  cgd 		case 2:		i = rnd(15)+8-c[AC];
   1112  1.1  cgd 			spout:	p="\nThe %s breathes fire at you!";
   1113  1.1  cgd 					if (c[FIRERESISTANCE])
   1114  1.1  cgd 					  p="\nThe %s's flame doesn't phase you!";
   1115  1.1  cgd 					else
   1116  1.1  cgd 			spout2: if (p) { lprintf(p,lastmonst); beep(); }
   1117  1.1  cgd 					checkloss(i);
   1118  1.1  cgd 					return(0);
   1119  1.1  cgd 
   1120  1.1  cgd 		case 3:		i = rnd(20)+25-c[AC];  goto spout;
   1121  1.1  cgd 
   1122  1.1  cgd 		case 4:	if (c[STRENGTH]>3)
   1123  1.1  cgd 					{
   1124  1.1  cgd 					p="\nThe %s stung you!  You feel weaker"; beep();
   1125  1.1  cgd 					--c[STRENGTH];
   1126  1.1  cgd 					}
   1127  1.1  cgd 				else p="\nThe %s stung you!";
   1128  1.1  cgd 				break;
   1129  1.1  cgd 
   1130  1.1  cgd 		case 5:		p="\nThe %s blasts you with his cold breath";
   1131  1.1  cgd 					i = rnd(15)+18-c[AC];  goto spout2;
   1132  1.1  cgd 
   1133  1.1  cgd 		case 6:		lprintf("\nThe %s drains you of your life energy!",lastmonst);
   1134  1.1  cgd 					loselevel();  beep();  return(0);
   1135  1.1  cgd 
   1136  1.1  cgd 		case 7:		p="\nThe %s got you with a gusher!";
   1137  1.1  cgd 					i = rnd(15)+25-c[AC];  goto spout2;
   1138  1.1  cgd 
   1139  1.1  cgd 		case 8:		if (c[NOTHEFT]) return(0); /* he has a device of no theft */
   1140  1.1  cgd 					if (c[GOLD])
   1141  1.1  cgd 						{
   1142  1.1  cgd 						p="\nThe %s hit you -- Your purse feels lighter";
   1143  1.1  cgd 						if (c[GOLD]>32767)  c[GOLD]>>=1;
   1144  1.1  cgd 							else c[GOLD] -= rnd((int)(1+(c[GOLD]>>1)));
   1145  1.1  cgd 						if (c[GOLD] < 0) c[GOLD]=0;
   1146  1.1  cgd 						}
   1147  1.1  cgd 					else  p="\nThe %s couldn't find any gold to steal";
   1148  1.1  cgd 					lprintf(p,lastmonst); disappear(xx,yy); beep();
   1149  1.1  cgd 					bottomgold();  return(1);
   1150  1.1  cgd 
   1151  1.1  cgd 		case 9:	for(j=50; ; )	/* disenchant */
   1152  1.1  cgd 					{
   1153  1.1  cgd 					i=rund(26);  m=iven[i]; /* randomly select item */
   1154  1.1  cgd 					if (m>0 && ivenarg[i]>0 && m!=OSCROLL && m!=OPOTION)
   1155  1.1  cgd 						{
   1156  1.1  cgd 						if ((ivenarg[i] -= 3)<0) ivenarg[i]=0;
   1157  1.1  cgd 						lprintf("\nThe %s hits you -- you feel a sense of loss",lastmonst);
   1158  1.1  cgd 						srcount=0; beep(); show3(i);  bottomline();  return(0);
   1159  1.1  cgd 						}
   1160  1.1  cgd 					if (--j<=0)
   1161  1.1  cgd 						{
   1162  1.1  cgd 						p="\nThe %s nearly misses"; break;
   1163  1.1  cgd 						}
   1164  1.1  cgd 					break;
   1165  1.1  cgd 					}
   1166  1.1  cgd 				break;
   1167  1.1  cgd 
   1168  1.1  cgd 		case 10:   p="\nThe %s hit you with his barbed tail";
   1169  1.1  cgd 				   i = rnd(25)-c[AC];  goto spout2;
   1170  1.1  cgd 
   1171  1.1  cgd 		case 11:	p="\nThe %s has confused you"; beep();
   1172  1.1  cgd 					c[CONFUSE]+= 10+rnd(10);		break;
   1173  1.1  cgd 
   1174  1.1  cgd 		case 12:	/*	performs any number of other special attacks	*/
   1175  1.1  cgd 					return(spattack(spsel[rund(10)],xx,yy));
   1176  1.1  cgd 
   1177  1.1  cgd 		case 13:	p="\nThe %s flattens you with his psionics!";
   1178  1.1  cgd 					i = rnd(15)+30-c[AC];  goto spout2;
   1179  1.1  cgd 
   1180  1.1  cgd 		case 14:	if (c[NOTHEFT]) return(0); /* he has device of no theft */
   1181  1.1  cgd 					if (emptyhanded()==1)
   1182  1.1  cgd 					  {
   1183  1.1  cgd 					  p="\nThe %s couldn't find anything to steal";
   1184  1.1  cgd 					  break;
   1185  1.1  cgd 					  }
   1186  1.1  cgd 					lprintf("\nThe %s picks your pocket and takes:",lastmonst);
   1187  1.1  cgd 					beep();
   1188  1.1  cgd 					if (stealsomething()==0) lprcat("  nothing"); disappear(xx,yy);
   1189  1.1  cgd 					bottomline();  return(1);
   1190  1.1  cgd 
   1191  1.1  cgd 		case 15:	i= rnd(10)+ 5-c[AC];
   1192  1.1  cgd 			spout3:	p="\nThe %s bit you!";
   1193  1.1  cgd 					goto spout2;
   1194  1.1  cgd 
   1195  1.1  cgd 		case 16:	i= rnd(15)+10-c[AC];  goto spout3;
   1196  1.1  cgd 		};
   1197  1.1  cgd 	if (p) { lprintf(p,lastmonst); bottomline(); }
   1198  1.1  cgd 	return(0);
   1199  1.1  cgd 	}
   1200  1.1  cgd 
   1201  1.1  cgd /*
   1202  1.1  cgd  *	checkloss(x) 	Routine to subtract hp from user and flag bottomline display
   1203  1.1  cgd  *		int x;
   1204  1.1  cgd  *
   1205  1.1  cgd  *	Routine to subtract hitpoints from the user and flag the bottomline display
   1206  1.1  cgd  *	Enter with the number of hit points to lose
   1207  1.1  cgd  *	Note: if x > c[HP] this routine could kill the player!
   1208  1.1  cgd  */
   1209  1.1  cgd checkloss(x)
   1210  1.1  cgd 	int x;
   1211  1.1  cgd 	{
   1212  1.1  cgd 	if (x>0) { losehp(x);  bottomhp(); }
   1213  1.1  cgd 	}
   1214  1.1  cgd 
   1215  1.1  cgd /*
   1216  1.1  cgd  *	annihilate() 	Routine to annihilate all monsters around player (playerx,playery)
   1217  1.1  cgd  *
   1218  1.1  cgd  *	Gives player experience, but no dropped objects
   1219  1.1  cgd  *	Returns the experience gained from all monsters killed
   1220  1.1  cgd  */
   1221  1.1  cgd annihilate()
   1222  1.1  cgd 	{
   1223  1.1  cgd 	int i,j;
   1224  1.1  cgd 	register long k;
   1225  1.1  cgd 	register char *p;
   1226  1.1  cgd 	for (k=0, i=playerx-1; i<=playerx+1; i++)
   1227  1.1  cgd 	  for (j=playery-1; j<=playery+1; j++)
   1228  1.1  cgd 		if (!vxy(&i,&j)) /* if not out of bounds */
   1229  1.1  cgd 			if (*(p= &mitem[i][j]))	/* if a monster there */
   1230  1.1  cgd 				if (*p<DEMONLORD+2)
   1231  1.1  cgd 					{
   1232  1.1  cgd 					k += monster[*p].experience;	*p=know[i][j]=0;
   1233  1.1  cgd 					}
   1234  1.1  cgd 				else
   1235  1.1  cgd 					{
   1236  1.1  cgd 					lprintf("\nThe %s barely escapes being annihilated!",monster[*p].name);
   1237  1.1  cgd 					hitp[i][j] = (hitp[i][j]>>1) + 1; /* lose half hit points*/
   1238  1.1  cgd 					}
   1239  1.1  cgd 	if (k>0)
   1240  1.1  cgd 		{
   1241  1.1  cgd 		lprcat("\nYou hear loud screams of agony!");	raiseexperience((long)k);
   1242  1.1  cgd 		}
   1243  1.1  cgd 	return(k);
   1244  1.1  cgd 	}
   1245  1.1  cgd 
   1246  1.1  cgd /*
   1247  1.1  cgd  *	newsphere(x,y,dir,lifetime)  Function to create a new sphere of annihilation
   1248  1.1  cgd  *		int x,y,dir,lifetime;
   1249  1.1  cgd  *
   1250  1.1  cgd  *	Enter with the coordinates of the sphere in x,y
   1251  1.1  cgd  *	  the direction (0-8 diroffx format) in dir, and the lifespan of the
   1252  1.1  cgd  *	  sphere in lifetime (in turns)
   1253  1.1  cgd  *	Returns the number of spheres currently in existence
   1254  1.1  cgd  */
   1255  1.1  cgd newsphere(x,y,dir,life)
   1256  1.1  cgd 	int x,y,dir,life;
   1257  1.1  cgd 	{
   1258  1.1  cgd 	int m;
   1259  1.1  cgd 	struct sphere *sp;
   1260  1.1  cgd 	if (((sp=(struct sphere *)malloc(sizeof(struct sphere)))) == 0)
   1261  1.1  cgd 		return(c[SPHCAST]);	/* can't malloc, therefore failure */
   1262  1.1  cgd 	if (dir>=9) dir=0;	/* no movement if direction not found */
   1263  1.1  cgd 	if (level==0) vxy(&x,&y);	/* don't go out of bounds */
   1264  1.1  cgd 	else
   1265  1.1  cgd 		{
   1266  1.1  cgd 		if (x<1) x=1;  if (x>=MAXX-1) x=MAXX-2;
   1267  1.1  cgd 		if (y<1) y=1;  if (y>=MAXY-1) y=MAXY-2;
   1268  1.1  cgd 		}
   1269  1.1  cgd 	if ((m=mitem[x][y]) >= DEMONLORD+4)	/* demons dispel spheres */
   1270  1.1  cgd 		{
   1271  1.1  cgd 		know[x][y]=1; show1cell(x,y);	/* show the demon (ha ha) */
   1272  1.1  cgd 		cursors(); lprintf("\nThe %s dispels the sphere!",monster[m].name);
   1273  1.1  cgd 		beep(); rmsphere(x,y);	/* remove any spheres that are here */
   1274  1.1  cgd 		return(c[SPHCAST]);
   1275  1.1  cgd 		}
   1276  1.1  cgd 	if (m==DISENCHANTRESS) /* disenchantress cancels spheres */
   1277  1.1  cgd 		{
   1278  1.1  cgd 		cursors(); lprintf("\nThe %s causes cancellation of the sphere!",monster[m].name); beep();
   1279  1.1  cgd boom:	sphboom(x,y);	/* blow up stuff around sphere */
   1280  1.1  cgd 		rmsphere(x,y);	/* remove any spheres that are here */
   1281  1.1  cgd 		return(c[SPHCAST]);
   1282  1.1  cgd 		}
   1283  1.1  cgd 	if (c[CANCELLATION]) /* cancellation cancels spheres */
   1284  1.1  cgd 		{
   1285  1.1  cgd 		cursors(); lprcat("\nAs the cancellation takes effect, you hear a great earth shaking blast!"); beep();
   1286  1.1  cgd 		goto boom;
   1287  1.1  cgd 		}
   1288  1.1  cgd 	if (item[x][y]==OANNIHILATION) /* collision of spheres detonates spheres */
   1289  1.1  cgd 		{
   1290  1.1  cgd 		cursors(); lprcat("\nTwo spheres of annihilation collide! You hear a great earth shaking blast!"); beep();
   1291  1.1  cgd 		rmsphere(x,y);
   1292  1.1  cgd 		goto boom;
   1293  1.1  cgd 		}
   1294  1.1  cgd 	if (playerx==x && playery==y) /* collision of sphere and player! */
   1295  1.1  cgd 		{
   1296  1.1  cgd 		cursors();
   1297  1.1  cgd 		lprcat("\nYou have been enveloped by the zone of nothingness!\n");
   1298  1.1  cgd 		beep(); rmsphere(x,y);	/* remove any spheres that are here */
   1299  1.1  cgd 		nap(4000);  died(258);
   1300  1.1  cgd 		}
   1301  1.1  cgd 	item[x][y]=OANNIHILATION;  mitem[x][y]=0;  know[x][y]=1;
   1302  1.1  cgd 	show1cell(x,y);	/* show the new sphere */
   1303  1.1  cgd 	sp->x=x;  sp->y=y;  sp->lev=level;  sp->dir=dir;  sp->lifetime=life;  sp->p=0;
   1304  1.1  cgd 	if (spheres==0) spheres=sp;	/* if first node in the sphere list */
   1305  1.1  cgd 	else	/* add sphere to beginning of linked list */
   1306  1.1  cgd 		{
   1307  1.1  cgd 		sp->p = spheres;	spheres = sp;
   1308  1.1  cgd 		}
   1309  1.1  cgd 	return(++c[SPHCAST]);	/* one more sphere in the world */
   1310  1.1  cgd 	}
   1311  1.1  cgd 
   1312  1.1  cgd /*
   1313  1.1  cgd  *	rmsphere(x,y)		Function to delete a sphere of annihilation from list
   1314  1.1  cgd  *		int x,y;
   1315  1.1  cgd  *
   1316  1.1  cgd  *	Enter with the coordinates of the sphere (on current level)
   1317  1.1  cgd  *	Returns the number of spheres currently in existence
   1318  1.1  cgd  */
   1319  1.1  cgd rmsphere(x,y)
   1320  1.1  cgd 	int x,y;
   1321  1.1  cgd 	{
   1322  1.1  cgd 	register struct sphere *sp,*sp2=0;
   1323  1.1  cgd 	for (sp=spheres; sp; sp2=sp,sp=sp->p)
   1324  1.1  cgd 	  if (level==sp->lev)	/* is sphere on this level? */
   1325  1.1  cgd 	    if ((x==sp->x) && (y==sp->y))	/* locate sphere at this location */
   1326  1.1  cgd 			{
   1327  1.1  cgd 			item[x][y]=mitem[x][y]=0;  know[x][y]=1;
   1328  1.1  cgd 			show1cell(x,y);	/* show the now missing sphere */
   1329  1.1  cgd 			--c[SPHCAST];
   1330  1.1  cgd 			if (sp==spheres) { sp2=sp; spheres=sp->p; free((char*)sp2); }
   1331  1.1  cgd 			else
   1332  1.1  cgd 				{ sp2->p = sp->p;  free((char*)sp); }
   1333  1.1  cgd 			break;
   1334  1.1  cgd 			}
   1335  1.1  cgd 	return(c[SPHCAST]);	/* return number of spheres in the world */
   1336  1.1  cgd 	}
   1337  1.1  cgd 
   1338  1.1  cgd /*
   1339  1.1  cgd  *	sphboom(x,y)	Function to perform the effects of a sphere detonation
   1340  1.1  cgd  *		int x,y;
   1341  1.1  cgd  *
   1342  1.1  cgd  *	Enter with the coordinates of the blast, Returns no value
   1343  1.1  cgd  */
   1344  1.1  cgd sphboom(x,y)
   1345  1.1  cgd 	int x,y;
   1346  1.1  cgd 	{
   1347  1.1  cgd 	register int i,j;
   1348  1.1  cgd 	if (c[HOLDMONST]) c[HOLDMONST]=1;
   1349  1.1  cgd 	if (c[CANCELLATION]) c[CANCELLATION]=1;
   1350  1.1  cgd 	for (j=max(1,x-2); j<min(x+3,MAXX-1); j++)
   1351  1.1  cgd 	  for (i=max(1,y-2); i<min(y+3,MAXY-1); i++)
   1352  1.1  cgd 		{
   1353  1.1  cgd 		item[j][i]=mitem[j][i]=0;
   1354  1.1  cgd 		show1cell(j,i);
   1355  1.1  cgd 		if (playerx==j && playery==i)
   1356  1.1  cgd 			{
   1357  1.1  cgd 			cursors(); beep();
   1358  1.1  cgd 			lprcat("\nYou were too close to the sphere!");
   1359  1.1  cgd 			nap(3000);
   1360  1.1  cgd 			died(283); /* player killed in explosion */
   1361  1.1  cgd 			}
   1362  1.1  cgd 		}
   1363  1.1  cgd 	}
   1364  1.1  cgd 
   1365  1.1  cgd /*
   1366  1.1  cgd  *	genmonst()		Function to ask for monster and genocide from game
   1367  1.1  cgd  *
   1368  1.1  cgd  *	This is done by setting a flag in the monster[] structure
   1369  1.1  cgd  */
   1370  1.1  cgd genmonst()
   1371  1.1  cgd 	{
   1372  1.1  cgd 	register int i,j;
   1373  1.1  cgd 	cursors();  lprcat("\nGenocide what monster? ");
   1374  1.1  cgd 	for (i=0; (!isalpha(i)) && (i!=' '); i=getchar());
   1375  1.1  cgd 	lprc(i);
   1376  1.1  cgd 	for (j=0; j<MAXMONST; j++)	/* search for the monster type */
   1377  1.1  cgd 		if (monstnamelist[j]==i)	/* have we found it? */
   1378  1.1  cgd 			{
   1379  1.1  cgd 			monster[j].genocided=1;	/* genocided from game */
   1380  1.1  cgd 			lprintf("  There will be no more %s's",monster[j].name);
   1381  1.1  cgd 			/* now wipe out monsters on this level */
   1382  1.1  cgd 			newcavelevel(level); draws(0,MAXX,0,MAXY); bot_linex();
   1383  1.1  cgd 			return;
   1384  1.1  cgd 			}
   1385  1.1  cgd 	lprcat("  You sense failure!");
   1386  1.1  cgd 	}
   1387  1.1  cgd 
   1388