Home | History | Annotate | Line # | Download | only in larn
monster.c revision 1.13
      1  1.13  dholland /*	$NetBSD: monster.c,v 1.13 2008/01/28 05:38:54 dholland Exp $	*/
      2   1.2   mycroft 
      3   1.1       cgd /*
      4   1.5  christos  * monster.c	Larn is copyrighted 1986 by Noah Morgan.
      5   1.1       cgd  *
      6   1.5  christos  * This file contains the following functions:
      7   1.5  christos  * ----------------------------------------------------------------------------
      8   1.1       cgd  *
      9   1.5  christos  * createmonster(monstno) 	Function to create a monster next to the player
     10   1.5  christos  * int monstno;
     11   1.1       cgd  *
     12   1.5  christos  * int cgood(x,y,itm,monst)Function to check location for emptiness
     13   1.5  christos  * int x,y,itm,monst;
     14   1.1       cgd  *
     15   1.5  christos  * createitem(it,arg) 		Routine to place an item next to the player
     16   1.5  christos  * int it,arg;
     17   1.1       cgd  *
     18   1.5  christos  * cast() 			Subroutine called by parse to cast a spell for the user
     19   1.1       cgd  *
     20   1.5  christos  * speldamage(x) 	Function to perform spell functions cast by the player
     21   1.5  christos  * int x;
     22   1.1       cgd  *
     23   1.5  christos  * loseint()		Routine to decrement your int (intelligence) if > 3
     24   1.1       cgd  *
     25   1.5  christos  * isconfuse() 	Routine to check to see if player is confused
     26   1.1       cgd  *
     27   1.5  christos  * nospell(x,monst)Routine to return 1 if a spell doesn't affect a monster
     28   1.5  christos  * int x,monst;
     29   1.1       cgd  *
     30   1.5  christos  * fullhit(xx)		Function to return full damage against a monst (aka web)
     31   1.5  christos  * int xx;
     32   1.1       cgd  *
     33   1.5  christos  * direct(spnum,dam,str,arg)Routine to direct spell damage 1 square in 1 dir
     34   1.5  christos  * int spnum,dam,arg;
     35   1.5  christos  * char *str;
     36   1.1       cgd  *
     37   1.5  christos  * godirect(spnum,dam,str,delay,cshow)	Function to perform missile attacks
     38   1.5  christos  * int spnum,dam,delay;
     39   1.5  christos  * char *str,cshow;
     40   1.1       cgd  *
     41   1.5  christos  * ifblind(x,y)Routine to put "monster" or the monster name into lastmosnt
     42   1.5  christos  * int x,y;
     43   1.1       cgd  *
     44   1.5  christos  * tdirect(spnum)		Routine to teleport away a monster
     45   1.5  christos  * int spnum;
     46   1.1       cgd  *
     47   1.5  christos  * omnidirect(sp,dam,str)  Routine to damage all monsters 1 square from player
     48   1.5  christos  * int sp,dam;
     49   1.5  christos  * char *str;
     50   1.1       cgd  *
     51   1.5  christos  * dirsub(x,y)		Routine to ask for direction, then modify x,y for it
     52   1.5  christos  * int *x,*y;
     53   1.1       cgd  *
     54   1.5  christos  * vxy(x,y)	  	Routine to verify/fix (*x,*y) for being within bounds
     55   1.5  christos  * int *x,*y;
     56   1.1       cgd  *
     57   1.5  christos  * dirpoly(spnum)	Routine to ask for a direction and polymorph a monst
     58   1.5  christos  * int spnum;
     59   1.1       cgd  *
     60   1.5  christos  * hitmonster(x,y) Function to hit a monster at the designated coordinates
     61   1.5  christos  * int x,y;
     62   1.1       cgd  *
     63   1.5  christos  * hitm(x,y,amt)	Function to just hit a monster at a given coordinates
     64   1.5  christos  * int x,y,amt;
     65   1.1       cgd  *
     66   1.5  christos  * hitplayer(x,y) 	Function for the monster to hit the player from (x,y)
     67   1.5  christos  * int x,y;
     68   1.1       cgd  *
     69   1.5  christos  * dropsomething(monst) Function to create an object when a monster dies
     70   1.5  christos  * int monst;
     71   1.1       cgd  *
     72   1.5  christos  * dropgold(amount) 	Function to drop some gold around player
     73   1.5  christos  * int amount;
     74   1.1       cgd  *
     75   1.5  christos  * something(level) 	Function to create a random item around player
     76   1.5  christos  * int level;
     77   1.1       cgd  *
     78   1.5  christos  * newobject(lev,i) 	Routine to return a randomly selected new object
     79   1.5  christos  * int lev,*i;
     80   1.1       cgd  *
     81   1.5  christos  *  spattack(atckno,xx,yy)  Function to process special attacks from monsters
     82   1.5  christos  *   int atckno,xx,yy;
     83   1.1       cgd  *
     84   1.5  christos  * checkloss(x) Routine to subtract hp from user and flag bottomline display
     85   1.5  christos  * int x;
     86   1.1       cgd  *
     87   1.5  christos  * annihilate()   Routine to annihilate monsters around player, playerx,playery
     88   1.1       cgd  *
     89   1.5  christos  * newsphere(x,y,dir,lifetime)  Function to create a new sphere of annihilation
     90   1.5  christos  * int x,y,dir,lifetime;
     91   1.1       cgd  *
     92   1.5  christos  * rmsphere(x,y)	Function to delete a sphere of annihilation from list
     93   1.5  christos  * int x,y;
     94   1.1       cgd  *
     95   1.5  christos  * sphboom(x,y)	Function to perform the effects of a sphere detonation
     96   1.5  christos  * int x,y;
     97   1.1       cgd  *
     98   1.5  christos  * genmonst()		Function to ask for monster and genocide from game
     99   1.1       cgd  *
    100   1.1       cgd  */
    101   1.5  christos #include <sys/cdefs.h>
    102   1.5  christos #ifndef lint
    103  1.13  dholland __RCSID("$NetBSD: monster.c,v 1.13 2008/01/28 05:38:54 dholland Exp $");
    104   1.5  christos #endif				/* not lint */
    105   1.5  christos 
    106   1.5  christos #include <string.h>
    107   1.5  christos #include <stdlib.h>
    108   1.1       cgd #include "header.h"
    109   1.5  christos #include "extern.h"
    110   1.1       cgd 
    111   1.5  christos struct isave {			/* used for altar reality */
    112   1.5  christos 	char            type;	/* 0=item,  1=monster */
    113   1.5  christos 	char            id;	/* item number or monster number */
    114   1.5  christos 	short           arg;	/* the type of item or hitpoints of monster */
    115   1.5  christos };
    116   1.1       cgd 
    117   1.8       jsm static int dirsub(int *, int *);
    118   1.1       cgd /*
    119   1.5  christos  * createmonster(monstno)	Function to create a monster next to the player
    120   1.5  christos  * 	int monstno;
    121   1.1       cgd  *
    122   1.5  christos  * Enter with the monster number (1 to MAXMONST+8)
    123   1.5  christos  * Returns no value.
    124   1.1       cgd  */
    125   1.5  christos void
    126   1.1       cgd createmonster(mon)
    127   1.5  christos 	int             mon;
    128   1.5  christos {
    129   1.5  christos 	int    x, y, k, i;
    130   1.5  christos 	if (mon < 1 || mon > MAXMONST + 8) {	/* check for monster number
    131   1.5  christos 						 * out of bounds */
    132   1.5  christos 		beep();
    133  1.12  dholland 		lprintf("\ncan't createmonst(%ld)\n", (long) mon);
    134   1.5  christos 		nap(3000);
    135   1.5  christos 		return;
    136   1.5  christos 	}
    137   1.5  christos 	while (monster[mon].genocided && mon < MAXMONST)
    138   1.5  christos 		mon++;		/* genocided? */
    139   1.5  christos 	for (k = rnd(8), i = -8; i < 0; i++, k++) {	/* choose direction,
    140   1.5  christos 							 * then try all */
    141   1.5  christos 		if (k > 8)
    142   1.5  christos 			k = 1;	/* wraparound the diroff arrays */
    143   1.5  christos 		x = playerx + diroffx[k];
    144   1.5  christos 		y = playery + diroffy[k];
    145   1.5  christos 		if (cgood(x, y, 0, 1)) {	/* if we can create here */
    146   1.1       cgd 			mitem[x][y] = mon;
    147   1.1       cgd 			hitp[x][y] = monster[mon].hitpoints;
    148   1.5  christos 			stealth[x][y] = know[x][y] = 0;
    149   1.5  christos 			switch (mon) {
    150   1.5  christos 			case ROTHE:
    151   1.5  christos 			case POLTERGEIST:
    152   1.5  christos 			case VAMPIRE:
    153   1.5  christos 				stealth[x][y] = 1;
    154   1.5  christos 			};
    155   1.1       cgd 			return;
    156   1.1       cgd 		}
    157   1.1       cgd 	}
    158   1.5  christos }
    159   1.1       cgd 
    160   1.1       cgd /*
    161   1.5  christos  * int cgood(x,y,itm,monst)	  Function to check location for emptiness
    162   1.5  christos  * 	int x,y,itm,monst;
    163   1.1       cgd  *
    164   1.5  christos  * Routine to return TRUE if a location does not have itm or monst there
    165   1.5  christos  * returns FALSE (0) otherwise
    166   1.5  christos  * Enter with itm or monst TRUE or FALSE if checking it
    167   1.5  christos  * Example:  if itm==TRUE check for no item at this location
    168   1.5  christos  * 		  if monst==TRUE check for no monster at this location
    169   1.5  christos  * This routine will return FALSE if at a wall or the dungeon exit on level 1
    170   1.5  christos  */
    171   1.5  christos int
    172  1.13  dholland cgood(int x, int y, int theitem, int monst)
    173   1.5  christos {
    174  1.13  dholland #define itm __lose
    175   1.5  christos 	if ((y >= 0) && (y <= MAXY - 1) && (x >= 0) && (x <= MAXX - 1))
    176   1.5  christos 		/* within bounds? */
    177   1.5  christos 		if (item[x][y] != OWALL) /* can't make anything on walls */
    178   1.5  christos 			/* is it free of items? */
    179  1.13  dholland 			if (theitem == 0 || (item[x][y] == 0))
    180   1.5  christos 				/* is it free of monsters? */
    181   1.5  christos 				if (monst == 0 || (mitem[x][y] == 0))
    182   1.5  christos 					if ((level != 1) || (x != 33) ||
    183   1.5  christos 					    (y != MAXY - 1))
    184   1.5  christos 						/* not exit to level 1 */
    185   1.5  christos 						return (1);
    186   1.5  christos 	return (0);
    187   1.5  christos }
    188   1.5  christos 
    189   1.5  christos /*
    190   1.5  christos  * createitem(it,arg) 	Routine to place an item next to the player
    191   1.5  christos  * 	int it,arg;
    192   1.5  christos  *
    193   1.5  christos  * Enter with the item number and its argument (iven[], ivenarg[])
    194   1.5  christos  * Returns no value, thus we don't know about createitem() failures.
    195   1.5  christos  */
    196   1.5  christos void
    197   1.5  christos createitem(it, arg)
    198   1.5  christos 	int             it, arg;
    199   1.5  christos {
    200   1.5  christos 	int    x, y, k, i;
    201   1.5  christos 	if (it >= MAXOBJ)
    202   1.5  christos 		return;		/* no such object */
    203   1.5  christos 	for (k = rnd(8), i = -8; i < 0; i++, k++) {	/* choose direction,
    204   1.5  christos 							 * then try all */
    205   1.5  christos 		if (k > 8)
    206   1.5  christos 			k = 1;	/* wraparound the diroff arrays */
    207   1.5  christos 		x = playerx + diroffx[k];
    208   1.5  christos 		y = playery + diroffy[k];
    209   1.5  christos 		if (cgood(x, y, 1, 0)) {	/* if we can create here */
    210   1.5  christos 			item[x][y] = it;
    211   1.5  christos 			know[x][y] = 0;
    212   1.5  christos 			iarg[x][y] = arg;
    213   1.5  christos 			return;
    214   1.1       cgd 		}
    215   1.1       cgd 	}
    216   1.5  christos }
    217   1.1       cgd 
    218   1.1       cgd /*
    219   1.5  christos  * cast() 		Subroutine called by parse to cast a spell for the user
    220   1.1       cgd  *
    221   1.5  christos  * No arguments and no return value.
    222   1.1       cgd  */
    223   1.5  christos static char     eys[] = "\nEnter your spell: ";
    224   1.5  christos void
    225   1.1       cgd cast()
    226   1.5  christos {
    227   1.5  christos 	int    i, j, a, b, d;
    228   1.1       cgd 	cursors();
    229   1.5  christos 	if (c[SPELLS] <= 0) {
    230   1.5  christos 		lprcat("\nYou don't have any spells!");
    231   1.5  christos 		return;
    232   1.5  christos 	}
    233   1.5  christos 	lprcat(eys);
    234   1.5  christos 	--c[SPELLS];
    235   1.7  christos 	while ((a = lgetchar()) == 'D') {
    236   1.5  christos 		seemagic(-1);
    237   1.5  christos 		cursors();
    238   1.5  christos 		lprcat(eys);
    239   1.5  christos 	}
    240   1.5  christos 	if (a == '\33')
    241   1.5  christos 		goto over;	/* to escape casting a spell	 */
    242   1.7  christos 	if ((b = lgetchar()) == '\33')
    243   1.5  christos 		goto over;	/* to escape casting a spell	 */
    244   1.7  christos 	if ((d = lgetchar()) == '\33') {
    245   1.5  christos over:		lprcat(aborted);
    246   1.5  christos 		c[SPELLS]++;
    247   1.5  christos 		return;
    248   1.5  christos 	}			/* to escape casting a spell	 */
    249   1.1       cgd #ifdef EXTRA
    250   1.1       cgd 	c[SPELLSCAST]++;
    251   1.1       cgd #endif
    252   1.5  christos 	for (lprc('\n'), j = -1, i = 0; i < SPNUM; i++)	/* seq search for his
    253   1.5  christos 							 * spell, hash? */
    254   1.5  christos 		if ((spelcode[i][0] == a) && (spelcode[i][1] == b) && (spelcode[i][2] == d))
    255   1.5  christos 			if (spelknow[i]) {
    256   1.5  christos 				speldamage(i);
    257   1.5  christos 				j = 1;
    258   1.5  christos 				i = SPNUM;
    259   1.5  christos 			}
    260   1.5  christos 	if (j == -1)
    261   1.5  christos 		lprcat("  Nothing Happened ");
    262   1.1       cgd 	bottomline();
    263   1.5  christos }
    264   1.1       cgd 
    265   1.1       cgd /*
    266   1.5  christos  * speldamage(x) 		Function to perform spell functions cast by the player
    267   1.5  christos  * 	int x;
    268   1.1       cgd  *
    269   1.5  christos  * Enter with the spell number, returns no value.
    270   1.5  christos  * Please insure that there are 2 spaces before all messages here
    271   1.1       cgd  */
    272   1.5  christos void
    273  1.13  dholland speldamage(int x)
    274   1.5  christos {
    275   1.5  christos 	int    i, j, clev;
    276   1.5  christos 	int             xl, xh, yl, yh;
    277  1.13  dholland 	u_char  *p, *kn, *pm;
    278  1.13  dholland 
    279   1.5  christos 	if (x >= SPNUM)
    280   1.5  christos 		return;		/* no such spell */
    281   1.5  christos 	if (c[TIMESTOP]) {
    282   1.5  christos 		lprcat("  It didn't seem to work");
    283   1.5  christos 		return;
    284   1.5  christos 	}			/* not if time stopped */
    285   1.1       cgd 	clev = c[LEVEL];
    286   1.5  christos 	if ((rnd(23) == 7) || (rnd(18) > c[INTELLIGENCE])) {
    287   1.5  christos 		lprcat("  It didn't work!");
    288   1.5  christos 		return;
    289   1.5  christos 	}
    290   1.5  christos 	if (clev * 3 + 2 < x) {
    291   1.5  christos 		lprcat("  Nothing happens.  You seem inexperienced at this");
    292   1.5  christos 		return;
    293   1.5  christos 	}
    294   1.5  christos 	switch (x) {
    295   1.5  christos 		/* ----- LEVEL 1 SPELLS ----- */
    296   1.5  christos 
    297   1.5  christos 	case 0:
    298   1.5  christos 		if (c[PROTECTIONTIME] == 0)
    299   1.5  christos 			c[MOREDEFENSES] += 2;	/* protection field +2 */
    300   1.5  christos 		c[PROTECTIONTIME] += 250;
    301   1.5  christos 		return;
    302   1.5  christos 
    303   1.5  christos 	case 1:
    304   1.5  christos 		i = rnd(((clev + 1) << 1)) + clev + 3;
    305   1.5  christos 		godirect(x, i, (clev >= 2) ? "  Your missiles hit the %s" : "  Your missile hit the %s", 100, '+');	/* magic missile */
    306   1.5  christos 
    307   1.5  christos 		return;
    308   1.5  christos 
    309   1.5  christos 	case 2:
    310   1.5  christos 		if (c[DEXCOUNT] == 0)
    311   1.5  christos 			c[DEXTERITY] += 3;	/* dexterity	 */
    312   1.5  christos 		c[DEXCOUNT] += 400;
    313   1.5  christos 		return;
    314   1.5  christos 
    315  1.13  dholland 	case 3:		/* sleep		 */
    316   1.5  christos 		i = rnd(3) + 1;
    317  1.13  dholland 		direct(x, fullhit(i),
    318  1.13  dholland 		       "  While the %s slept, you smashed it %ld times", i);
    319   1.5  christos 		return;
    320   1.1       cgd 
    321   1.5  christos 	case 4:		/* charm monster	 */
    322   1.5  christos 		c[CHARMCOUNT] += c[CHARISMA] << 1;
    323   1.5  christos 		return;
    324   1.5  christos 
    325   1.5  christos 	case 5:
    326   1.5  christos 		godirect(x, rnd(10) + 15 + clev, "  The sound damages the %s", 70, '@');	/* sonic spear */
    327   1.5  christos 		return;
    328   1.5  christos 
    329   1.5  christos 		/* ----- LEVEL 2 SPELLS ----- */
    330   1.1       cgd 
    331  1.13  dholland 	case 6:		/* web 			*/
    332   1.5  christos 		i = rnd(3) + 2;
    333  1.13  dholland 		direct(x, fullhit(i),
    334  1.13  dholland 		       "  While the %s is entangled, you hit %ld times", i);
    335  1.13  dholland 		return;
    336   1.5  christos 
    337   1.5  christos 	case 7:
    338   1.5  christos 		if (c[STRCOUNT] == 0)
    339   1.5  christos 			c[STREXTRA] += 3;	/* strength	 */
    340   1.5  christos 		c[STRCOUNT] += 150 + rnd(100);
    341   1.5  christos 		return;
    342   1.1       cgd 
    343   1.5  christos 	case 8:
    344   1.5  christos 		yl = playery - 5;	/* enlightenment */
    345   1.5  christos 		yh = playery + 6;
    346   1.5  christos 		xl = playerx - 15;
    347   1.5  christos 		xh = playerx + 16;
    348   1.5  christos 		vxy(&xl, &yl);
    349   1.5  christos 		vxy(&xh, &yh);	/* check bounds */
    350   1.5  christos 		for (i = yl; i <= yh; i++)	/* enlightenment	 */
    351   1.5  christos 			for (j = xl; j <= xh; j++)
    352   1.5  christos 				know[j][i] = 1;
    353   1.5  christos 		draws(xl, xh + 1, yl, yh + 1);
    354   1.5  christos 		return;
    355   1.1       cgd 
    356   1.5  christos 	case 9:
    357   1.5  christos 		raisehp(20 + (clev << 1));
    358   1.5  christos 		return;		/* healing */
    359   1.5  christos 
    360   1.5  christos 	case 10:
    361   1.5  christos 		c[BLINDCOUNT] = 0;
    362   1.5  christos 		return;		/* cure blindness	 */
    363   1.1       cgd 
    364   1.5  christos 	case 11:
    365   1.5  christos 		createmonster(makemonst(level + 1) + 8);
    366   1.5  christos 		return;
    367   1.1       cgd 
    368   1.5  christos 	case 12:
    369   1.5  christos 		if (rnd(11) + 7 <= c[WISDOM])
    370   1.5  christos 			direct(x, rnd(20) + 20 + clev, "  The %s believed!", 0);
    371   1.5  christos 		else
    372   1.5  christos 			lprcat("  It didn't believe the illusions!");
    373   1.5  christos 		return;
    374   1.1       cgd 
    375   1.5  christos 	case 13:		/* if he has the amulet of invisibility then
    376   1.5  christos 				 * add more time */
    377   1.5  christos 		for (j = i = 0; i < 26; i++)
    378   1.5  christos 			if (iven[i] == OAMULET)
    379   1.5  christos 				j += 1 + ivenarg[i];
    380   1.5  christos 		c[INVISIBILITY] += (j << 7) + 12;
    381   1.5  christos 		return;
    382   1.1       cgd 
    383   1.5  christos 		/* ----- LEVEL 3 SPELLS ----- */
    384   1.1       cgd 
    385   1.5  christos 	case 14:
    386   1.5  christos 		godirect(x, rnd(25 + clev) + 25 + clev, "  The fireball hits the %s", 40, '*');
    387   1.5  christos 		return;		/* fireball */
    388   1.1       cgd 
    389   1.5  christos 	case 15:
    390   1.5  christos 		godirect(x, rnd(25) + 20 + clev, "  Your cone of cold strikes the %s", 60, 'O');	/* cold */
    391   1.5  christos 		return;
    392   1.1       cgd 
    393   1.5  christos 	case 16:
    394   1.5  christos 		dirpoly(x);
    395   1.5  christos 		return;		/* polymorph */
    396   1.5  christos 
    397   1.5  christos 	case 17:
    398   1.5  christos 		c[CANCELLATION] += 5 + clev;
    399   1.5  christos 		return;		/* cancellation	 */
    400   1.5  christos 
    401   1.5  christos 	case 18:
    402   1.5  christos 		c[HASTESELF] += 7 + clev;
    403   1.5  christos 		return;		/* haste self	 */
    404   1.1       cgd 
    405   1.5  christos 	case 19:
    406   1.5  christos 		omnidirect(x, 30 + rnd(10), "  The %s gasps for air");	/* cloud kill */
    407   1.5  christos 		return;
    408   1.1       cgd 
    409   1.5  christos 	case 20:
    410   1.5  christos 		xh = min(playerx + 1, MAXX - 2);
    411   1.5  christos 		yh = min(playery + 1, MAXY - 2);
    412   1.5  christos 		for (i = max(playerx - 1, 1); i <= xh; i++)	/* vaporize rock */
    413   1.5  christos 			for (j = max(playery - 1, 1); j <= yh; j++) {
    414   1.5  christos 				kn = &know[i][j];
    415   1.5  christos 				pm = &mitem[i][j];
    416   1.5  christos 				switch (*(p = &item[i][j])) {
    417   1.5  christos 				case OWALL:
    418   1.5  christos 					if (level < MAXLEVEL + MAXVLEVEL - 1)
    419   1.5  christos 						*p = *kn = 0;
    420   1.5  christos 					break;
    421   1.1       cgd 
    422   1.5  christos 				case OSTATUE:
    423   1.5  christos 					if (c[HARDGAME] < 3) {
    424   1.5  christos 						*p = OBOOK;
    425   1.5  christos 						iarg[i][j] = level;
    426   1.5  christos 						*kn = 0;
    427   1.5  christos 					}
    428   1.5  christos 					break;
    429   1.1       cgd 
    430   1.5  christos 				case OTHRONE:
    431   1.5  christos 					*pm = GNOMEKING;
    432   1.5  christos 					*kn = 0;
    433   1.5  christos 					*p = OTHRONE2;
    434   1.5  christos 					hitp[i][j] = monster[GNOMEKING].hitpoints;
    435   1.5  christos 					break;
    436   1.1       cgd 
    437   1.5  christos 				case OALTAR:
    438   1.5  christos 					*pm = DEMONPRINCE;
    439   1.5  christos 					*kn = 0;
    440   1.5  christos 					hitp[i][j] = monster[DEMONPRINCE].hitpoints;
    441   1.5  christos 					break;
    442   1.5  christos 				};
    443   1.5  christos 				switch (*pm) {
    444   1.5  christos 				case XORN:
    445   1.5  christos 					ifblind(i, j);
    446   1.5  christos 					hitm(i, j, 200);
    447   1.5  christos 					break;	/* Xorn takes damage from vpr */
    448   1.5  christos 				}
    449   1.5  christos 			}
    450   1.5  christos 		return;
    451   1.1       cgd 
    452   1.5  christos 		/* ----- LEVEL 4 SPELLS ----- */
    453   1.1       cgd 
    454   1.5  christos 	case 21:
    455   1.5  christos 		direct(x, 100 + clev, "  The %s shrivels up", 0);	/* dehydration */
    456   1.5  christos 		return;
    457   1.1       cgd 
    458   1.5  christos 	case 22:
    459   1.5  christos 		godirect(x, rnd(25) + 20 + (clev << 1), "  A lightning bolt hits the %s", 1, '~');	/* lightning */
    460   1.5  christos 		return;
    461   1.1       cgd 
    462   1.5  christos 	case 23:
    463   1.5  christos 		i = min(c[HP] - 1, c[HPMAX] / 2);	/* drain life */
    464   1.5  christos 		direct(x, i + i, "", 0);
    465   1.5  christos 		c[HP] -= i;
    466   1.5  christos 		return;
    467   1.1       cgd 
    468   1.5  christos 	case 24:
    469   1.5  christos 		if (c[GLOBE] == 0)
    470   1.5  christos 			c[MOREDEFENSES] += 10;
    471   1.5  christos 		c[GLOBE] += 200;
    472   1.5  christos 		loseint();	/* globe of invulnerability */
    473   1.5  christos 		return;
    474   1.1       cgd 
    475   1.5  christos 	case 25:
    476   1.5  christos 		omnidirect(x, 32 + clev, "  The %s struggles for air in your flood!");	/* flood */
    477   1.5  christos 		return;
    478   1.1       cgd 
    479   1.5  christos 	case 26:
    480   1.5  christos 		if (rnd(151) == 63) {
    481   1.5  christos 			beep();
    482   1.5  christos 			lprcat("\nYour heart stopped!\n");
    483   1.5  christos 			nap(4000);
    484   1.5  christos 			died(270);
    485   1.5  christos 			return;
    486   1.5  christos 		}
    487   1.5  christos 		if (c[WISDOM] > rnd(10) + 10)
    488   1.5  christos 			direct(x, 2000, "  The %s's heart stopped", 0);	/* finger of death */
    489   1.5  christos 		else
    490   1.5  christos 			lprcat("  It didn't work");
    491   1.5  christos 		return;
    492   1.1       cgd 
    493   1.5  christos 		/* ----- LEVEL 5 SPELLS ----- */
    494   1.1       cgd 
    495   1.5  christos 	case 27:
    496   1.5  christos 		c[SCAREMONST] += rnd(10) + clev;
    497   1.5  christos 		return;		/* scare monster */
    498   1.5  christos 
    499   1.5  christos 	case 28:
    500   1.5  christos 		c[HOLDMONST] += rnd(10) + clev;
    501   1.5  christos 		return;		/* hold monster */
    502   1.5  christos 
    503   1.5  christos 	case 29:
    504   1.5  christos 		c[TIMESTOP] += rnd(20) + (clev << 1);
    505   1.5  christos 		return;		/* time stop */
    506   1.5  christos 
    507   1.5  christos 	case 30:
    508   1.5  christos 		tdirect(x);
    509   1.5  christos 		return;		/* teleport away */
    510   1.1       cgd 
    511   1.5  christos 	case 31:
    512   1.5  christos 		omnidirect(x, 35 + rnd(10) + clev, "  The %s cringes from the flame");	/* magic fire */
    513   1.5  christos 		return;
    514   1.1       cgd 
    515   1.5  christos 		/* ----- LEVEL 6 SPELLS ----- */
    516   1.5  christos 
    517   1.5  christos 	case 32:
    518   1.5  christos 		if ((rnd(23) == 5) && (wizard == 0)) {	/* sphere of
    519   1.5  christos 							 * annihilation */
    520   1.5  christos 			beep();
    521   1.5  christos 			lprcat("\nYou have been enveloped by the zone of nothingness!\n");
    522   1.5  christos 			nap(4000);
    523   1.5  christos 			died(258);
    524   1.5  christos 			return;
    525   1.5  christos 		}
    526   1.5  christos 		xl = playerx;
    527   1.5  christos 		yl = playery;
    528   1.5  christos 		loseint();
    529   1.5  christos 		i = dirsub(&xl, &yl);	/* get direction of sphere */
    530   1.5  christos 		newsphere(xl, yl, i, rnd(20) + 11);	/* make a sphere */
    531   1.5  christos 		return;
    532   1.5  christos 
    533   1.5  christos 	case 33:
    534   1.5  christos 		genmonst();
    535   1.5  christos 		spelknow[33] = 0;	/* genocide */
    536   1.5  christos 		loseint();
    537   1.5  christos 		return;
    538   1.5  christos 
    539   1.5  christos 	case 34:		/* summon demon */
    540   1.5  christos 		if (rnd(100) > 30) {
    541   1.5  christos 			direct(x, 150, "  The demon strikes at the %s", 0);
    542   1.5  christos 			return;
    543   1.5  christos 		}
    544   1.5  christos 		if (rnd(100) > 15) {
    545   1.5  christos 			lprcat("  Nothing seems to have happened");
    546   1.5  christos 			return;
    547   1.5  christos 		}
    548   1.5  christos 		lprcat("  The demon turned on you and vanished!");
    549   1.5  christos 		beep();
    550   1.5  christos 		i = rnd(40) + 30;
    551   1.5  christos 		lastnum = 277;
    552   1.5  christos 		losehp(i);	/* must say killed by a demon */
    553   1.5  christos 		return;
    554   1.5  christos 
    555   1.5  christos 	case 35:		/* walk through walls */
    556   1.5  christos 		c[WTW] += rnd(10) + 5;
    557   1.5  christos 		return;
    558   1.5  christos 
    559   1.5  christos 	case 36:		/* alter reality */
    560   1.5  christos 		{
    561   1.5  christos 			struct isave   *save;	/* pointer to item save
    562   1.5  christos 						 * structure */
    563   1.5  christos 			int             sc;
    564   1.5  christos 			sc = 0;	/* # items saved */
    565   1.5  christos 			save = (struct isave *) malloc(sizeof(struct isave) * MAXX * MAXY * 2);
    566   1.5  christos 			for (j = 0; j < MAXY; j++)
    567   1.5  christos 				for (i = 0; i < MAXX; i++) {	/* save all items and
    568   1.5  christos 								 * monsters */
    569   1.5  christos 					xl = item[i][j];
    570   1.5  christos 					if (xl && xl != OWALL && xl != OANNIHILATION) {
    571   1.5  christos 						save[sc].type = 0;
    572   1.5  christos 						save[sc].id = item[i][j];
    573   1.5  christos 						save[sc++].arg = iarg[i][j];
    574   1.5  christos 					}
    575   1.5  christos 					if (mitem[i][j]) {
    576   1.5  christos 						save[sc].type = 1;
    577   1.5  christos 						save[sc].id = mitem[i][j];
    578   1.5  christos 						save[sc++].arg = hitp[i][j];
    579   1.5  christos 					}
    580   1.5  christos 					item[i][j] = OWALL;
    581   1.5  christos 					mitem[i][j] = 0;
    582   1.5  christos 					if (wizard)
    583   1.5  christos 						know[i][j] = 1;
    584   1.5  christos 					else
    585   1.5  christos 						know[i][j] = 0;
    586   1.5  christos 				}
    587   1.5  christos 			eat(1, 1);
    588   1.5  christos 			if (level == 1)
    589   1.5  christos 				item[33][MAXY - 1] = 0;
    590   1.5  christos 			for (j = rnd(MAXY - 2), i = 1; i < MAXX - 1; i++)
    591   1.5  christos 				item[i][j] = 0;
    592   1.5  christos 			while (sc > 0) {	/* put objects back in level */
    593   1.5  christos 				--sc;
    594   1.5  christos 				if (save[sc].type == 0) {
    595   1.5  christos 					int             trys;
    596   1.5  christos 					for (trys = 100, i = j = 1; --trys > 0 && item[i][j]; i = rnd(MAXX - 1), j = rnd(MAXY - 1));
    597   1.5  christos 					if (trys) {
    598   1.5  christos 						item[i][j] = save[sc].id;
    599   1.5  christos 						iarg[i][j] = save[sc].arg;
    600   1.5  christos 					}
    601   1.5  christos 				} else {	/* put monsters back in */
    602   1.5  christos 					int             trys;
    603   1.5  christos 					for (trys = 100, i = j = 1; --trys > 0 && (item[i][j] == OWALL || mitem[i][j]); i = rnd(MAXX - 1), j = rnd(MAXY - 1));
    604   1.5  christos 					if (trys) {
    605   1.5  christos 						mitem[i][j] = save[sc].id;
    606   1.5  christos 						hitp[i][j] = save[sc].arg;
    607   1.1       cgd 					}
    608   1.5  christos 				}
    609   1.5  christos 			}
    610   1.5  christos 			loseint();
    611   1.5  christos 			draws(0, MAXX, 0, MAXY);
    612   1.5  christos 			if (wizard == 0)
    613   1.5  christos 				spelknow[36] = 0;
    614   1.5  christos 			free((char *) save);
    615   1.5  christos 			positionplayer();
    616   1.5  christos 			return;
    617   1.5  christos 		}
    618   1.1       cgd 
    619   1.5  christos 	case 37:		/* permanence */
    620   1.5  christos 		adjusttime(-99999L);
    621   1.5  christos 		spelknow[37] = 0;	/* forget */
    622   1.5  christos 		loseint();
    623   1.5  christos 		return;
    624   1.1       cgd 
    625   1.5  christos 	default:
    626  1.12  dholland 		lprintf("  spell %ld not available!", (long) x);
    627   1.5  christos 		beep();
    628   1.5  christos 		return;
    629   1.5  christos 	};
    630   1.5  christos }
    631   1.1       cgd 
    632   1.1       cgd /*
    633   1.5  christos  * loseint()		Routine to subtract 1 from your int (intelligence) if > 3
    634   1.1       cgd  *
    635   1.5  christos  * No arguments and no return value
    636   1.1       cgd  */
    637   1.5  christos void
    638   1.1       cgd loseint()
    639   1.5  christos {
    640   1.5  christos 	if (--c[INTELLIGENCE] < 3)
    641   1.5  christos 		c[INTELLIGENCE] = 3;
    642   1.5  christos }
    643   1.1       cgd 
    644   1.1       cgd /*
    645   1.5  christos  * isconfuse() 		Routine to check to see if player is confused
    646   1.1       cgd  *
    647   1.5  christos  * This routine prints out a message saying "You can't aim your magic!"
    648   1.5  christos  * returns 0 if not confused, non-zero (time remaining confused) if confused
    649   1.1       cgd  */
    650   1.5  christos int
    651   1.1       cgd isconfuse()
    652   1.5  christos {
    653   1.5  christos 	if (c[CONFUSE]) {
    654   1.5  christos 		lprcat(" You can't aim your magic!");
    655   1.5  christos 		beep();
    656   1.5  christos 	}
    657   1.5  christos 	return (c[CONFUSE]);
    658   1.5  christos }
    659   1.5  christos 
    660   1.5  christos /*
    661   1.5  christos  * nospell(x,monst)	Routine to return 1 if a spell doesn't affect a monster
    662   1.5  christos  * 	int x,monst;
    663   1.5  christos  *
    664   1.5  christos  * Subroutine to return 1 if the spell can't affect the monster
    665   1.5  christos  *   otherwise returns 0
    666   1.5  christos  * Enter with the spell number in x, and the monster number in monst.
    667   1.5  christos  */
    668   1.5  christos int
    669   1.5  christos nospell(x, monst)
    670   1.5  christos 	int             x, monst;
    671   1.5  christos {
    672   1.5  christos 	int    tmp;
    673   1.5  christos 	if (x >= SPNUM || monst >= MAXMONST + 8 || monst < 0 || x < 0)
    674   1.5  christos 		return (0);	/* bad spell or monst */
    675   1.5  christos 	if ((tmp = spelweird[monst - 1][x]) == 0)
    676   1.5  christos 		return (0);
    677   1.5  christos 	cursors();
    678   1.5  christos 	lprc('\n');
    679   1.5  christos 	lprintf(spelmes[tmp], monster[monst].name);
    680   1.5  christos 	return (1);
    681   1.5  christos }
    682   1.1       cgd 
    683   1.1       cgd /*
    684   1.5  christos  * fullhit(xx)		Function to return full damage against a monster (aka web)
    685   1.5  christos  * 	int xx;
    686   1.1       cgd  *
    687   1.5  christos  * Function to return hp damage to monster due to a number of full hits
    688   1.5  christos  * Enter with the number of full hits being done
    689   1.1       cgd  */
    690   1.5  christos int
    691   1.1       cgd fullhit(xx)
    692   1.5  christos 	int             xx;
    693   1.5  christos {
    694   1.5  christos 	int    i;
    695   1.5  christos 	if (xx < 0 || xx > 20)
    696   1.5  christos 		return (0);	/* fullhits are out of range */
    697   1.5  christos 	if (c[LANCEDEATH])
    698   1.5  christos 		return (10000);	/* lance of death */
    699   1.5  christos 	i = xx * ((c[WCLASS] >> 1) + c[STRENGTH] + c[STREXTRA] - c[HARDGAME] - 12 + c[MOREDAM]);
    700   1.5  christos 	return ((i >= 1) ? i : xx);
    701   1.5  christos }
    702   1.5  christos 
    703   1.5  christos /*
    704   1.5  christos  * direct(spnum,dam,str,arg)	Routine to direct spell damage 1 square in 1 dir
    705   1.5  christos  * 	int spnum,dam,arg;
    706   1.5  christos  * 	char *str;
    707   1.5  christos  *
    708   1.5  christos  * Routine to ask for a direction to a spell and then hit the monster
    709   1.5  christos  * Enter with the spell number in spnum, the damage to be done in dam,
    710   1.5  christos  *   lprintf format string in str, and lprintf's argument in arg.
    711   1.5  christos  * Returns no value.
    712   1.5  christos  */
    713   1.5  christos void
    714   1.5  christos direct(spnum, dam, str, arg)
    715   1.5  christos 	int             spnum, dam, arg;
    716  1.13  dholland 	const char     *str;
    717   1.5  christos {
    718   1.5  christos 	int             x, y;
    719   1.5  christos 	int    m;
    720   1.5  christos 	if (spnum < 0 || spnum >= SPNUM || str == 0)
    721   1.5  christos 		return;		/* bad arguments */
    722   1.5  christos 	if (isconfuse())
    723   1.5  christos 		return;
    724   1.5  christos 	dirsub(&x, &y);
    725   1.1       cgd 	m = mitem[x][y];
    726   1.5  christos 	if (item[x][y] == OMIRROR) {
    727   1.5  christos 		if (spnum == 3) {	/* sleep */
    728   1.5  christos 			lprcat("You fall asleep! ");
    729   1.5  christos 			beep();
    730   1.5  christos 	fool:
    731   1.1       cgd 			arg += 2;
    732   1.5  christos 			while (arg-- > 0) {
    733   1.5  christos 				parse2();
    734   1.5  christos 				nap(1000);
    735   1.5  christos 			}
    736   1.1       cgd 			return;
    737   1.5  christos 		} else if (spnum == 6) {	/* web */
    738   1.5  christos 			lprcat("You get stuck in your own web! ");
    739   1.5  christos 			beep();
    740   1.1       cgd 			goto fool;
    741   1.5  christos 		} else {
    742   1.5  christos 			lastnum = 278;
    743  1.11     mouse 			lprintf(str, "spell caster (that's you)", (long) arg);
    744   1.5  christos 			beep();
    745   1.5  christos 			losehp(dam);
    746   1.5  christos 			return;
    747   1.1       cgd 		}
    748   1.1       cgd 	}
    749   1.5  christos 	if (m == 0) {
    750   1.5  christos 		lprcat("  There wasn't anything there!");
    751   1.5  christos 		return;
    752   1.5  christos 	}
    753   1.5  christos 	ifblind(x, y);
    754   1.5  christos 	if (nospell(spnum, m)) {
    755   1.5  christos 		lasthx = x;
    756   1.5  christos 		lasthy = y;
    757   1.5  christos 		return;
    758   1.5  christos 	}
    759   1.5  christos 	lprintf(str, lastmonst, (long) arg);
    760   1.5  christos 	hitm(x, y, dam);
    761   1.5  christos }
    762   1.5  christos 
    763   1.5  christos /*
    764   1.5  christos  * godirect(spnum,dam,str,delay,cshow)		Function to perform missile attacks
    765   1.5  christos  * 	int spnum,dam,delay;
    766   1.5  christos  * 	char *str,cshow;
    767   1.5  christos  *
    768   1.5  christos  * Function to hit in a direction from a missile weapon and have it keep
    769   1.5  christos  * on going in that direction until its power is exhausted
    770   1.5  christos  * Enter with the spell number in spnum, the power of the weapon in hp,
    771   1.5  christos  *   lprintf format string in str, the # of milliseconds to delay between
    772   1.5  christos  *   locations in delay, and the character to represent the weapon in cshow.
    773   1.5  christos  * Returns no value.
    774   1.5  christos  */
    775   1.5  christos void
    776   1.5  christos godirect(spnum, dam, str, delay, cshow)
    777   1.5  christos 	int             spnum, dam, delay;
    778  1.13  dholland 	const char     *str, cshow;
    779   1.5  christos {
    780  1.13  dholland 	u_char  *p;
    781   1.5  christos 	int    x, y, m;
    782   1.5  christos 	int             dx, dy;
    783   1.5  christos 	if (spnum < 0 || spnum >= SPNUM || str == 0 || delay < 0)
    784   1.5  christos 		return;		/* bad args */
    785   1.5  christos 	if (isconfuse())
    786   1.5  christos 		return;
    787   1.5  christos 	dirsub(&dx, &dy);
    788   1.5  christos 	x = dx;
    789   1.5  christos 	y = dy;
    790   1.5  christos 	dx = x - playerx;
    791   1.5  christos 	dy = y - playery;
    792   1.5  christos 	x = playerx;
    793   1.5  christos 	y = playery;
    794   1.5  christos 	while (dam > 0) {
    795   1.5  christos 		x += dx;
    796   1.5  christos 		y += dy;
    797   1.5  christos 		if ((x > MAXX - 1) || (y > MAXY - 1) || (x < 0) || (y < 0)) {
    798   1.5  christos 			dam = 0;
    799   1.5  christos 			break;	/* out of bounds */
    800   1.5  christos 		}
    801   1.5  christos 		if ((x == playerx) && (y == playery)) {	/* if energy hits player */
    802   1.5  christos 			cursors();
    803  1.11     mouse 			lprcat("\nYou are hit by your own magic!");
    804   1.5  christos 			beep();
    805   1.5  christos 			lastnum = 278;
    806   1.5  christos 			losehp(dam);
    807   1.5  christos 			return;
    808   1.5  christos 		}
    809   1.5  christos 		if (c[BLINDCOUNT] == 0) {	/* if not blind show effect */
    810   1.5  christos 			cursor(x + 1, y + 1);
    811   1.5  christos 			lprc(cshow);
    812   1.5  christos 			nap(delay);
    813   1.5  christos 			show1cell(x, y);
    814   1.5  christos 		}
    815   1.5  christos 		if ((m = mitem[x][y])) {	/* is there a monster there? */
    816   1.5  christos 			ifblind(x, y);
    817   1.5  christos 			if (nospell(spnum, m)) {
    818   1.5  christos 				lasthx = x;
    819   1.5  christos 				lasthy = y;
    820   1.5  christos 				return;
    821   1.1       cgd 			}
    822   1.5  christos 			cursors();
    823   1.5  christos 			lprc('\n');
    824   1.5  christos 			lprintf(str, lastmonst);
    825   1.5  christos 			dam -= hitm(x, y, dam);
    826   1.5  christos 			show1cell(x, y);
    827   1.5  christos 			nap(1000);
    828   1.5  christos 			x -= dx;
    829   1.5  christos 			y -= dy;
    830   1.5  christos 		} else
    831   1.5  christos 			switch (*(p = &item[x][y])) {
    832   1.5  christos 			case OWALL:
    833   1.5  christos 				cursors();
    834   1.5  christos 				lprc('\n');
    835   1.5  christos 				lprintf(str, "wall");
    836   1.5  christos 				if (dam >= 50 + c[HARDGAME])	/* enough damage? */
    837   1.5  christos 					if (level < MAXLEVEL + MAXVLEVEL - 1)	/* not on V3 */
    838   1.5  christos 						if ((x < MAXX - 1) && (y < MAXY - 1) && (x) && (y)) {
    839   1.1       cgd 							lprcat("  The wall crumbles");
    840   1.5  christos 					god3:		*p = 0;
    841   1.5  christos 					god:		know[x][y] = 0;
    842   1.5  christos 							show1cell(x, y);
    843   1.5  christos 						}
    844   1.5  christos 		god2:		dam = 0;
    845   1.5  christos 				break;
    846   1.5  christos 
    847   1.5  christos 			case OCLOSEDDOOR:
    848   1.5  christos 				cursors();
    849   1.5  christos 				lprc('\n');
    850   1.5  christos 				lprintf(str, "door");
    851   1.5  christos 				if (dam >= 40) {
    852   1.5  christos 					lprcat("  The door is blasted apart");
    853   1.5  christos 					goto god3;
    854   1.5  christos 				}
    855   1.5  christos 				goto god2;
    856   1.5  christos 
    857   1.5  christos 			case OSTATUE:
    858   1.5  christos 				cursors();
    859   1.5  christos 				lprc('\n');
    860   1.5  christos 				lprintf(str, "statue");
    861   1.5  christos 				if (c[HARDGAME] < 3)
    862   1.5  christos 					if (dam > 44) {
    863   1.5  christos 						lprcat("  The statue crumbles");
    864   1.5  christos 						*p = OBOOK;
    865   1.5  christos 						iarg[x][y] = level;
    866   1.1       cgd 						goto god;
    867   1.5  christos 					}
    868   1.5  christos 				goto god2;
    869   1.1       cgd 
    870   1.5  christos 			case OTHRONE:
    871   1.5  christos 				cursors();
    872   1.5  christos 				lprc('\n');
    873   1.5  christos 				lprintf(str, "throne");
    874   1.5  christos 				if (dam > 39) {
    875   1.5  christos 					mitem[x][y] = GNOMEKING;
    876   1.5  christos 					hitp[x][y] = monster[GNOMEKING].hitpoints;
    877   1.5  christos 					*p = OTHRONE2;
    878   1.5  christos 					goto god;
    879   1.5  christos 				}
    880   1.5  christos 				goto god2;
    881   1.5  christos 
    882   1.5  christos 			case OMIRROR:
    883   1.5  christos 				dx *= -1;
    884   1.5  christos 				dy *= -1;
    885   1.5  christos 				break;
    886   1.1       cgd 			};
    887   1.5  christos 		dam -= 3 + (c[HARDGAME] >> 1);
    888   1.1       cgd 	}
    889   1.5  christos }
    890   1.1       cgd 
    891   1.1       cgd /*
    892   1.5  christos  * ifblind(x,y)	Routine to put "monster" or the monster name into lastmosnt
    893   1.5  christos  * 	int x,y;
    894   1.1       cgd  *
    895   1.5  christos  * Subroutine to copy the word "monster" into lastmonst if the player is blind
    896   1.5  christos  * Enter with the coordinates (x,y) of the monster
    897   1.5  christos  * Returns no value.
    898   1.1       cgd  */
    899   1.5  christos void
    900  1.13  dholland ifblind(int x, int y)
    901   1.5  christos {
    902  1.13  dholland 	const char *p;
    903  1.13  dholland 
    904   1.5  christos 	vxy(&x, &y);		/* verify correct x,y coordinates */
    905   1.5  christos 	if (c[BLINDCOUNT]) {
    906   1.5  christos 		lastnum = 279;
    907   1.5  christos 		p = "monster";
    908   1.5  christos 	} else {
    909   1.5  christos 		lastnum = mitem[x][y];
    910   1.5  christos 		p = monster[lastnum].name;
    911   1.1       cgd 	}
    912   1.5  christos 	strcpy(lastmonst, p);
    913   1.5  christos }
    914   1.1       cgd 
    915   1.1       cgd /*
    916   1.5  christos  * tdirect(spnum)		Routine to teleport away a monster
    917   1.5  christos  * 	int spnum;
    918   1.1       cgd  *
    919   1.5  christos  * Routine to ask for a direction to a spell and then teleport away monster
    920   1.5  christos  * Enter with the spell number that wants to teleport away
    921   1.5  christos  * Returns no value.
    922   1.1       cgd  */
    923   1.5  christos void
    924   1.1       cgd tdirect(spnum)
    925   1.5  christos 	int             spnum;
    926   1.5  christos {
    927   1.5  christos 	int             x, y;
    928   1.5  christos 	int    m;
    929   1.5  christos 	if (spnum < 0 || spnum >= SPNUM)
    930   1.5  christos 		return;		/* bad args */
    931   1.5  christos 	if (isconfuse())
    932   1.5  christos 		return;
    933   1.5  christos 	dirsub(&x, &y);
    934   1.5  christos 	if ((m = mitem[x][y]) == 0) {
    935   1.5  christos 		lprcat("  There wasn't anything there!");
    936   1.5  christos 		return;
    937   1.1       cgd 	}
    938   1.5  christos 	ifblind(x, y);
    939   1.5  christos 	if (nospell(spnum, m)) {
    940   1.5  christos 		lasthx = x;
    941   1.5  christos 		lasthy = y;
    942   1.5  christos 		return;
    943   1.1       cgd 	}
    944   1.5  christos 	fillmonst(m);
    945   1.5  christos 	mitem[x][y] = know[x][y] = 0;
    946   1.5  christos }
    947   1.5  christos 
    948   1.5  christos /*
    949   1.5  christos  * omnidirect(sp,dam,str)   Routine to damage all monsters 1 square from player
    950   1.5  christos  * 	int sp,dam;
    951   1.5  christos  * 	char *str;
    952   1.5  christos  *
    953   1.5  christos  * Routine to cast a spell and then hit the monster in all directions
    954   1.5  christos  * Enter with the spell number in sp, the damage done to wach square in dam,
    955   1.5  christos  *   and the lprintf string to identify the spell in str.
    956   1.5  christos  * Returns no value.
    957   1.5  christos  */
    958   1.5  christos void
    959  1.13  dholland omnidirect(int spnum, int dam, const char *str)
    960   1.5  christos {
    961   1.5  christos 	int    x, y, m;
    962  1.13  dholland 
    963   1.5  christos 	if (spnum < 0 || spnum >= SPNUM || str == 0)
    964   1.5  christos 		return;		/* bad args */
    965   1.5  christos 	for (x = playerx - 1; x < playerx + 2; x++)
    966   1.5  christos 		for (y = playery - 1; y < playery + 2; y++) {
    967   1.6     veego 			if ((m = mitem[x][y]) != 0) {
    968   1.5  christos 				if (nospell(spnum, m) == 0) {
    969   1.5  christos 					ifblind(x, y);
    970   1.5  christos 					cursors();
    971   1.5  christos 					lprc('\n');
    972   1.5  christos 					lprintf(str, lastmonst);
    973   1.5  christos 					hitm(x, y, dam);
    974   1.5  christos 					nap(800);
    975   1.5  christos 				} else {
    976   1.5  christos 					lasthx = x;
    977   1.5  christos 					lasthy = y;
    978   1.5  christos 				}
    979   1.6     veego 			}
    980   1.5  christos 		}
    981   1.5  christos }
    982   1.5  christos 
    983   1.5  christos /*
    984   1.5  christos  * static dirsub(x,y)		Routine to ask for direction, then modify x,y for it
    985   1.5  christos  * 	int *x,*y;
    986   1.5  christos  *
    987   1.5  christos  * Function to ask for a direction and modify an x,y for that direction
    988   1.5  christos  * Enter with the origination coordinates in (x,y).
    989   1.5  christos  * Returns index into diroffx[] (0-8).
    990   1.1       cgd  */
    991   1.1       cgd static int
    992   1.5  christos dirsub(x, y)
    993   1.5  christos 	int            *x, *y;
    994   1.5  christos {
    995   1.5  christos 	int    i;
    996   1.1       cgd 	lprcat("\nIn What Direction? ");
    997   1.5  christos 	for (i = 0;;)
    998   1.7  christos 		switch (lgetchar()) {
    999   1.5  christos 		case 'b':
   1000   1.5  christos 			i++;
   1001   1.5  christos 		case 'n':
   1002   1.5  christos 			i++;
   1003   1.5  christos 		case 'y':
   1004   1.5  christos 			i++;
   1005   1.5  christos 		case 'u':
   1006   1.5  christos 			i++;
   1007   1.5  christos 		case 'h':
   1008   1.5  christos 			i++;
   1009   1.5  christos 		case 'k':
   1010   1.5  christos 			i++;
   1011   1.5  christos 		case 'l':
   1012   1.5  christos 			i++;
   1013   1.5  christos 		case 'j':
   1014   1.5  christos 			i++;
   1015   1.5  christos 			goto out;
   1016   1.5  christos 		};
   1017   1.1       cgd out:
   1018   1.5  christos 	*x = playerx + diroffx[i];
   1019   1.5  christos 	*y = playery + diroffy[i];
   1020   1.5  christos 	vxy(x, y);
   1021   1.5  christos 	return (i);
   1022   1.5  christos }
   1023   1.5  christos 
   1024   1.5  christos /*
   1025   1.5  christos  * vxy(x,y)	   Routine to verify/fix coordinates for being within bounds
   1026   1.5  christos  * 	int *x,*y;
   1027   1.5  christos  *
   1028   1.5  christos  * Function to verify x & y are within the bounds for a level
   1029   1.5  christos  * If *x or *y is not within the absolute bounds for a level, fix them so that
   1030   1.5  christos  *   they are on the level.
   1031   1.5  christos  * Returns TRUE if it was out of bounds, and the *x & *y in the calling
   1032   1.5  christos  * routine are affected.
   1033   1.5  christos  */
   1034   1.5  christos int
   1035   1.5  christos vxy(x, y)
   1036   1.5  christos 	int            *x, *y;
   1037   1.5  christos {
   1038   1.5  christos 	int             flag = 0;
   1039   1.5  christos 	if (*x < 0) {
   1040   1.5  christos 		*x = 0;
   1041   1.5  christos 		flag++;
   1042   1.5  christos 	}
   1043   1.5  christos 	if (*y < 0) {
   1044   1.5  christos 		*y = 0;
   1045   1.5  christos 		flag++;
   1046   1.5  christos 	}
   1047   1.5  christos 	if (*x >= MAXX) {
   1048   1.5  christos 		*x = MAXX - 1;
   1049   1.5  christos 		flag++;
   1050   1.5  christos 	}
   1051   1.5  christos 	if (*y >= MAXY) {
   1052   1.5  christos 		*y = MAXY - 1;
   1053   1.5  christos 		flag++;
   1054   1.5  christos 	}
   1055   1.5  christos 	return (flag);
   1056   1.5  christos }
   1057   1.5  christos 
   1058   1.5  christos /*
   1059   1.5  christos  * dirpoly(spnum)	Routine to ask for a direction and polymorph a monst
   1060   1.5  christos  * 	int spnum;
   1061   1.5  christos  *
   1062   1.5  christos  * Subroutine to polymorph a monster and ask for the direction its in
   1063   1.5  christos  * Enter with the spell number in spmun.
   1064   1.5  christos  * Returns no value.
   1065   1.5  christos  */
   1066   1.5  christos void
   1067   1.5  christos dirpoly(spnum)
   1068   1.5  christos 	int             spnum;
   1069   1.5  christos {
   1070   1.5  christos 	int             x, y, m;
   1071   1.5  christos 	if (spnum < 0 || spnum >= SPNUM)
   1072   1.5  christos 		return;		/* bad args */
   1073   1.5  christos 	if (isconfuse())
   1074   1.5  christos 		return;		/* if he is confused, he can't aim his magic */
   1075   1.5  christos 	dirsub(&x, &y);
   1076   1.5  christos 	if (mitem[x][y] == 0) {
   1077   1.5  christos 		lprcat("  There wasn't anything there!");
   1078   1.5  christos 		return;
   1079   1.1       cgd 	}
   1080   1.5  christos 	ifblind(x, y);
   1081   1.5  christos 	if (nospell(spnum, mitem[x][y])) {
   1082   1.5  christos 		lasthx = x;
   1083   1.5  christos 		lasthy = y;
   1084   1.5  christos 		return;
   1085   1.1       cgd 	}
   1086   1.5  christos 	while (monster[m = mitem[x][y] = rnd(MAXMONST + 7)].genocided);
   1087   1.1       cgd 	hitp[x][y] = monster[m].hitpoints;
   1088   1.5  christos 	show1cell(x, y);	/* show the new monster */
   1089   1.5  christos }
   1090   1.1       cgd 
   1091   1.1       cgd /*
   1092   1.5  christos  * hitmonster(x,y) 	Function to hit a monster at the designated coordinates
   1093   1.5  christos  * 	int x,y;
   1094   1.1       cgd  *
   1095   1.5  christos  * This routine is used for a bash & slash type attack on a monster
   1096   1.5  christos  * Enter with the coordinates of the monster in (x,y).
   1097   1.5  christos  * Returns no value.
   1098   1.5  christos  */
   1099   1.5  christos void
   1100   1.5  christos hitmonster(x, y)
   1101   1.5  christos 	int             x, y;
   1102   1.5  christos {
   1103   1.5  christos 	int    tmp, monst, damag = 0, flag;
   1104   1.5  christos 	if (c[TIMESTOP])
   1105   1.5  christos 		return;		/* not if time stopped */
   1106   1.5  christos 	vxy(&x, &y);		/* verify coordinates are within range */
   1107   1.5  christos 	if ((monst = mitem[x][y]) == 0)
   1108   1.5  christos 		return;
   1109   1.5  christos 	hit3flag = 1;
   1110   1.5  christos 	ifblind(x, y);
   1111   1.5  christos 	tmp = monster[monst].armorclass + c[LEVEL] + c[DEXTERITY] +
   1112   1.5  christos 	    c[WCLASS] / 4 - 12;
   1113   1.1       cgd 	cursors();
   1114   1.5  christos 	/* need at least random chance to hit */
   1115   1.5  christos 	if ((rnd(20) < tmp - c[HARDGAME]) || (rnd(71) < 5)) {
   1116   1.5  christos 		lprcat("\nYou hit");
   1117   1.5  christos 		flag = 1;
   1118   1.5  christos 		damag = fullhit(1);
   1119   1.5  christos 		if (damag < 9999)
   1120   1.5  christos 			damag = rnd(damag) + 1;
   1121   1.5  christos 	} else {
   1122   1.5  christos 		lprcat("\nYou missed");
   1123   1.5  christos 		flag = 0;
   1124   1.5  christos 	}
   1125   1.5  christos 	lprcat(" the ");
   1126   1.5  christos 	lprcat(lastmonst);
   1127   1.5  christos 	if (flag)		/* if the monster was hit */
   1128   1.5  christos 		if ((monst == RUSTMONSTER) || (monst == DISENCHANTRESS) || (monst == CUBE))
   1129   1.5  christos 			if (c[WIELD] > 0)
   1130   1.5  christos 				if (ivenarg[c[WIELD]] > -10) {
   1131   1.5  christos 					lprintf("\nYour weapon is dulled by the %s", lastmonst);
   1132   1.5  christos 					beep();
   1133   1.5  christos 					--ivenarg[c[WIELD]];
   1134   1.5  christos 				}
   1135   1.5  christos 	if (flag)
   1136   1.5  christos 		hitm(x, y, damag);
   1137   1.5  christos 	if (monst == VAMPIRE)
   1138   1.5  christos 		if (hitp[x][y] < 25) {
   1139   1.5  christos 			mitem[x][y] = BAT;
   1140   1.5  christos 			know[x][y] = 0;
   1141   1.5  christos 		}
   1142   1.5  christos }
   1143   1.5  christos 
   1144   1.5  christos /*
   1145   1.5  christos  * hitm(x,y,amt)	Function to just hit a monster at a given coordinates
   1146   1.5  christos  * 	int x,y,amt;
   1147   1.5  christos  *
   1148   1.5  christos  * Returns the number of hitpoints the monster absorbed
   1149   1.5  christos  * This routine is used to specifically damage a monster at a location (x,y)
   1150   1.5  christos  * Called by hitmonster(x,y)
   1151   1.5  christos  */
   1152   1.5  christos int
   1153   1.5  christos hitm(x, y, amt)
   1154   1.5  christos 	int x, y;
   1155   1.5  christos 	int amt;
   1156   1.5  christos {
   1157   1.5  christos 	int    monst;
   1158   1.5  christos 	int    hpoints, amt2;
   1159   1.5  christos 	vxy(&x, &y);		/* verify coordinates are within range */
   1160   1.1       cgd 	amt2 = amt;		/* save initial damage so we can return it */
   1161   1.1       cgd 	monst = mitem[x][y];
   1162   1.5  christos 	if (c[HALFDAM])
   1163   1.5  christos 		amt >>= 1;	/* if half damage curse adjust damage points */
   1164   1.5  christos 	if (amt <= 0)
   1165   1.5  christos 		amt2 = amt = 1;
   1166   1.5  christos 	lasthx = x;
   1167   1.5  christos 	lasthy = y;
   1168   1.5  christos 	stealth[x][y] = 1;	/* make sure hitting monst breaks stealth
   1169   1.5  christos 				 * condition */
   1170   1.5  christos 	c[HOLDMONST] = 0;	/* hit a monster breaks hold monster spell	 */
   1171   1.5  christos 	switch (monst) {	/* if a dragon and orb(s) of dragon slaying	 */
   1172   1.5  christos 	case WHITEDRAGON:
   1173   1.5  christos 	case REDDRAGON:
   1174   1.5  christos 	case GREENDRAGON:
   1175   1.5  christos 	case BRONZEDRAGON:
   1176   1.5  christos 	case PLATINUMDRAGON:
   1177   1.5  christos 	case SILVERDRAGON:
   1178   1.5  christos 		amt *= 1 + (c[SLAYING] << 1);
   1179   1.5  christos 		break;
   1180   1.5  christos 	}
   1181   1.5  christos 	/* invincible monster fix is here */
   1182   1.1       cgd 	if (hitp[x][y] > monster[monst].hitpoints)
   1183   1.1       cgd 		hitp[x][y] = monster[monst].hitpoints;
   1184   1.5  christos 	if ((hpoints = hitp[x][y]) <= amt) {
   1185   1.1       cgd #ifdef EXTRA
   1186   1.1       cgd 		c[MONSTKILLED]++;
   1187   1.1       cgd #endif
   1188   1.5  christos 		lprintf("\nThe %s died!", lastmonst);
   1189   1.5  christos 		raiseexperience((long) monster[monst].experience);
   1190   1.5  christos 		amt = monster[monst].gold;
   1191   1.5  christos 		if (amt > 0)
   1192   1.5  christos 			dropgold(rnd(amt) + amt);
   1193   1.5  christos 		dropsomething(monst);
   1194   1.5  christos 		disappear(x, y);
   1195   1.5  christos 		bottomline();
   1196   1.5  christos 		return (hpoints);
   1197   1.5  christos 	}
   1198   1.5  christos 	hitp[x][y] = hpoints - amt;
   1199   1.5  christos 	return (amt2);
   1200   1.5  christos }
   1201   1.5  christos 
   1202   1.5  christos /*
   1203   1.5  christos  * hitplayer(x,y) 	Function for the monster to hit the player from (x,y)
   1204   1.5  christos  * 	int x,y;
   1205   1.5  christos  *
   1206   1.5  christos  * Function for the monster to hit the player with monster at location x,y
   1207   1.5  christos  * Returns nothing of value.
   1208   1.5  christos  */
   1209   1.5  christos void
   1210   1.5  christos hitplayer(x, y)
   1211   1.5  christos 	int             x, y;
   1212   1.5  christos {
   1213   1.5  christos 	int    dam, tmp, mster, bias;
   1214   1.5  christos 	vxy(&x, &y);		/* verify coordinates are within range */
   1215   1.5  christos 	lastnum = mster = mitem[x][y];
   1216   1.5  christos 	/*
   1217  1.11     mouse 	 * spirit nagas and poltergeists do nothing if scarab of negate
   1218   1.5  christos 	 * spirit
   1219   1.5  christos 	 */
   1220   1.5  christos 	if (c[NEGATESPIRIT] || c[SPIRITPRO])
   1221   1.5  christos 		if ((mster == POLTERGEIST) || (mster == SPIRITNAGA))
   1222   1.5  christos 			return;
   1223   1.5  christos 	/* if undead and cube of undead control	 */
   1224   1.5  christos 	if (c[CUBEofUNDEAD] || c[UNDEADPRO])
   1225   1.5  christos 		if ((mster == VAMPIRE) || (mster == WRAITH) || (mster == ZOMBIE))
   1226   1.5  christos 			return;
   1227   1.5  christos 	if ((know[x][y] & 1) == 0) {
   1228   1.5  christos 		know[x][y] = 1;
   1229   1.5  christos 		show1cell(x, y);
   1230   1.1       cgd 	}
   1231   1.1       cgd 	bias = (c[HARDGAME]) + 1;
   1232   1.1       cgd 	hitflag = hit2flag = hit3flag = 1;
   1233   1.5  christos 	yrepcount = 0;
   1234   1.5  christos 	cursors();
   1235   1.5  christos 	ifblind(x, y);
   1236   1.5  christos 	if (c[INVISIBILITY])
   1237   1.5  christos 		if (rnd(33) < 20) {
   1238   1.5  christos 			lprintf("\nThe %s misses wildly", lastmonst);
   1239   1.5  christos 			return;
   1240   1.1       cgd 		}
   1241   1.5  christos 	if (c[CHARMCOUNT])
   1242   1.5  christos 		if (rnd(30) + 5 * monster[mster].level - c[CHARISMA] < 30) {
   1243   1.5  christos 			lprintf("\nThe %s is awestruck at your magnificence!", lastmonst);
   1244   1.5  christos 			return;
   1245   1.1       cgd 		}
   1246   1.5  christos 	if (mster == BAT)
   1247   1.5  christos 		dam = 1;
   1248   1.5  christos 	else {
   1249   1.1       cgd 		dam = monster[mster].damage;
   1250   1.5  christos 		dam += rnd((int) ((dam < 1) ? 1 : dam)) + monster[mster].level;
   1251   1.5  christos 	}
   1252   1.1       cgd 	tmp = 0;
   1253   1.5  christos 	if (monster[mster].attack > 0)
   1254   1.5  christos 		if (((dam + bias + 8) > c[AC]) || (rnd((int) ((c[AC] > 0) ? c[AC] : 1)) == 1)) {
   1255   1.5  christos 			if (spattack(monster[mster].attack, x, y)) {
   1256   1.5  christos 				flushall();
   1257   1.5  christos 				return;
   1258   1.5  christos 			}
   1259   1.5  christos 			tmp = 1;
   1260   1.5  christos 			bias -= 2;
   1261   1.5  christos 			cursors();
   1262   1.5  christos 		}
   1263   1.5  christos 	if (((dam + bias) > c[AC]) || (rnd((int) ((c[AC] > 0) ? c[AC] : 1)) == 1)) {
   1264   1.5  christos 		lprintf("\n  The %s hit you ", lastmonst);
   1265   1.5  christos 		tmp = 1;
   1266   1.5  christos 		if ((dam -= c[AC]) < 0)
   1267   1.5  christos 			dam = 0;
   1268   1.5  christos 		if (dam > 0) {
   1269   1.5  christos 			losehp(dam);
   1270   1.5  christos 			bottomhp();
   1271   1.5  christos 			flushall();
   1272   1.5  christos 		}
   1273   1.5  christos 	}
   1274   1.5  christos 	if (tmp == 0)
   1275   1.5  christos 		lprintf("\n  The %s missed ", lastmonst);
   1276   1.5  christos }
   1277   1.5  christos 
   1278   1.5  christos /*
   1279   1.5  christos  * dropsomething(monst) 	Function to create an object when a monster dies
   1280   1.5  christos  * 	int monst;
   1281   1.5  christos  *
   1282   1.5  christos  * Function to create an object near the player when certain monsters are killed
   1283   1.5  christos  * Enter with the monster number
   1284   1.5  christos  * Returns nothing of value.
   1285   1.1       cgd  */
   1286   1.5  christos void
   1287   1.1       cgd dropsomething(monst)
   1288   1.5  christos 	int             monst;
   1289   1.5  christos {
   1290   1.5  christos 	switch (monst) {
   1291   1.5  christos 	case ORC:
   1292   1.5  christos 	case NYMPH:
   1293   1.5  christos 	case ELF:
   1294   1.5  christos 	case TROGLODYTE:
   1295   1.5  christos 	case TROLL:
   1296   1.5  christos 	case ROTHE:
   1297   1.5  christos 	case VIOLETFUNGI:
   1298   1.5  christos 	case PLATINUMDRAGON:
   1299   1.5  christos 	case GNOMEKING:
   1300   1.5  christos 	case REDDRAGON:
   1301   1.5  christos 		something(level);
   1302   1.5  christos 		return;
   1303   1.1       cgd 
   1304   1.5  christos 	case LEPRECHAUN:
   1305   1.5  christos 		if (rnd(101) >= 75)
   1306   1.5  christos 			creategem();
   1307   1.5  christos 		if (rnd(5) == 1)
   1308   1.5  christos 			dropsomething(LEPRECHAUN);
   1309   1.5  christos 		return;
   1310   1.1       cgd 	}
   1311   1.5  christos }
   1312   1.1       cgd 
   1313   1.1       cgd /*
   1314   1.5  christos  * dropgold(amount) 	Function to drop some gold around player
   1315   1.5  christos  * 	int amount;
   1316   1.1       cgd  *
   1317   1.5  christos  * Enter with the number of gold pieces to drop
   1318   1.5  christos  * Returns nothing of value.
   1319   1.1       cgd  */
   1320   1.5  christos void
   1321   1.1       cgd dropgold(amount)
   1322   1.5  christos 	int    amount;
   1323   1.5  christos {
   1324   1.5  christos 	if (amount > 250)
   1325   1.5  christos 		createitem(OMAXGOLD, amount / 100);
   1326   1.5  christos 	else
   1327   1.5  christos 		createitem(OGOLDPILE, amount);
   1328   1.5  christos }
   1329   1.1       cgd 
   1330   1.1       cgd /*
   1331   1.5  christos  * something(level) 	Function to create a random item around player
   1332   1.5  christos  * 	int level;
   1333   1.1       cgd  *
   1334   1.5  christos  * Function to create an item from a designed probability around player
   1335   1.5  christos  * Enter with the cave level on which something is to be dropped
   1336   1.5  christos  * Returns nothing of value.
   1337   1.1       cgd  */
   1338   1.5  christos void
   1339  1.13  dholland something(int cavelevel)
   1340   1.5  christos {
   1341   1.5  christos 	int    j;
   1342   1.5  christos 	int             i;
   1343  1.13  dholland 	if (cavelevel < 0 || cavelevel > MAXLEVEL + MAXVLEVEL)
   1344   1.5  christos 		return;		/* correct level? */
   1345   1.5  christos 	if (rnd(101) < 8)
   1346  1.13  dholland 		something(cavelevel);	/* possibly more than one item */
   1347  1.13  dholland 	j = newobject(cavelevel, &i);
   1348   1.5  christos 	createitem(j, i);
   1349   1.5  christos }
   1350   1.5  christos 
   1351   1.5  christos /*
   1352   1.5  christos  * newobject(lev,i) 	Routine to return a randomly selected new object
   1353   1.5  christos  * 	int lev,*i;
   1354   1.5  christos  *
   1355   1.5  christos  * Routine to return a randomly selected object to be created
   1356   1.5  christos  * Returns the object number created, and sets *i for its argument
   1357   1.5  christos  * Enter with the cave level and a pointer to the items arg
   1358   1.5  christos  */
   1359   1.5  christos static char     nobjtab[] = {
   1360   1.5  christos 	0, OSCROLL, OSCROLL, OSCROLL, OSCROLL, OPOTION, OPOTION,
   1361   1.5  christos 	OPOTION, OPOTION, OGOLDPILE, OGOLDPILE, OGOLDPILE, OGOLDPILE,
   1362   1.5  christos 	OBOOK, OBOOK, OBOOK, OBOOK, ODAGGER, ODAGGER, ODAGGER,
   1363   1.5  christos 	OLEATHER, OLEATHER, OLEATHER, OREGENRING, OPROTRING,
   1364   1.5  christos 	OENERGYRING, ODEXRING, OSTRRING, OSPEAR, OBELT, ORING,
   1365   1.5  christos 	OSTUDLEATHER, OSHIELD, OFLAIL, OCHAIN, O2SWORD, OPLATE,
   1366   1.5  christos 	OLONGSWORD};
   1367   1.5  christos 
   1368   1.5  christos int
   1369   1.5  christos newobject(lev, i)
   1370   1.5  christos 	int    lev, *i;
   1371   1.5  christos {
   1372   1.5  christos 	int    tmp = 32, j;
   1373   1.5  christos 	if (level < 0 || level > MAXLEVEL + MAXVLEVEL)
   1374   1.5  christos 		return (0);	/* correct level? */
   1375   1.5  christos 	if (lev > 6)
   1376   1.5  christos 		tmp = 37;
   1377   1.5  christos 	else if (lev > 4)
   1378   1.5  christos 		tmp = 35;
   1379   1.5  christos 	j = nobjtab[tmp = rnd(tmp)];	/* the object type */
   1380   1.5  christos 	switch (tmp) {
   1381   1.5  christos 	case 1:
   1382   1.5  christos 	case 2:
   1383   1.5  christos 	case 3:
   1384   1.5  christos 	case 4:
   1385   1.5  christos 		*i = newscroll();
   1386   1.5  christos 		break;
   1387   1.5  christos 	case 5:
   1388   1.5  christos 	case 6:
   1389   1.5  christos 	case 7:
   1390   1.5  christos 	case 8:
   1391   1.5  christos 		*i = newpotion();
   1392   1.5  christos 		break;
   1393   1.5  christos 	case 9:
   1394   1.5  christos 	case 10:
   1395   1.5  christos 	case 11:
   1396   1.5  christos 	case 12:
   1397   1.5  christos 		*i = rnd((lev + 1) * 10) + lev * 10 + 10;
   1398   1.5  christos 		break;
   1399   1.5  christos 	case 13:
   1400   1.5  christos 	case 14:
   1401   1.5  christos 	case 15:
   1402   1.5  christos 	case 16:
   1403   1.5  christos 		*i = lev;
   1404   1.5  christos 		break;
   1405   1.5  christos 	case 17:
   1406   1.5  christos 	case 18:
   1407   1.5  christos 	case 19:
   1408   1.5  christos 		if (!(*i = newdagger()))
   1409   1.5  christos 			return (0);
   1410   1.5  christos 		break;
   1411   1.5  christos 	case 20:
   1412   1.5  christos 	case 21:
   1413   1.5  christos 	case 22:
   1414   1.5  christos 		if (!(*i = newleather()))
   1415   1.5  christos 			return (0);
   1416   1.5  christos 		break;
   1417   1.5  christos 	case 23:
   1418   1.5  christos 	case 32:
   1419   1.5  christos 	case 35:
   1420   1.5  christos 		*i = rund(lev / 3 + 1);
   1421   1.5  christos 		break;
   1422   1.5  christos 	case 24:
   1423   1.5  christos 	case 26:
   1424   1.5  christos 		*i = rnd(lev / 4 + 1);
   1425   1.5  christos 		break;
   1426   1.5  christos 	case 25:
   1427   1.5  christos 		*i = rund(lev / 4 + 1);
   1428   1.5  christos 		break;
   1429   1.5  christos 	case 27:
   1430   1.5  christos 		*i = rnd(lev / 2 + 1);
   1431   1.5  christos 		break;
   1432   1.5  christos 	case 30:
   1433   1.5  christos 	case 33:
   1434   1.5  christos 		*i = rund(lev / 2 + 1);
   1435   1.5  christos 		break;
   1436   1.5  christos 	case 28:
   1437   1.5  christos 		*i = rund(lev / 3 + 1);
   1438   1.5  christos 		if (*i == 0)
   1439   1.5  christos 			return (0);
   1440   1.5  christos 		break;
   1441   1.5  christos 	case 29:
   1442   1.5  christos 	case 31:
   1443   1.5  christos 		*i = rund(lev / 2 + 1);
   1444   1.5  christos 		if (*i == 0)
   1445   1.5  christos 			return (0);
   1446   1.5  christos 		break;
   1447   1.5  christos 	case 34:
   1448   1.5  christos 		*i = newchain();
   1449   1.5  christos 		break;
   1450   1.5  christos 	case 36:
   1451   1.5  christos 		*i = newplate();
   1452   1.5  christos 		break;
   1453   1.5  christos 	case 37:
   1454   1.5  christos 		*i = newsword();
   1455   1.5  christos 		break;
   1456   1.1       cgd 	}
   1457   1.5  christos 	return (j);
   1458   1.5  christos }
   1459   1.1       cgd 
   1460   1.1       cgd /*
   1461   1.5  christos  *  spattack(atckno,xx,yy) Function to process special attacks from monsters
   1462   1.1       cgd  *  	int atckno,xx,yy;
   1463   1.1       cgd  *
   1464   1.5  christos  * Enter with the special attack number, and the coordinates (xx,yy)
   1465   1.5  christos  * 	of the monster that is special attacking
   1466   1.5  christos  * Returns 1 if must do a show1cell(xx,yy) upon return, 0 otherwise
   1467   1.1       cgd  *
   1468   1.1       cgd  * atckno   monster     effect
   1469   1.1       cgd  * ---------------------------------------------------
   1470   1.5  christos  * 0	none
   1471   1.5  christos  * 1	rust monster	eat armor
   1472   1.5  christos  * 2	hell hound	breathe light fire
   1473   1.5  christos  * 3	dragon		breathe fire
   1474   1.5  christos  * 4	giant centipede	weakening sing
   1475   1.5  christos  * 5	white dragon	cold breath
   1476   1.5  christos  * 6	wraith		drain level
   1477   1.5  christos  * 7	waterlord	water gusher
   1478   1.5  christos  * 8	leprechaun	steal gold
   1479   1.5  christos  * 9	disenchantress	disenchant weapon or armor
   1480   1.5  christos  * 10	ice lizard	hits with barbed tail
   1481   1.5  christos  * 11	umber hulk	confusion
   1482   1.5  christos  * 12	spirit naga	cast spells	taken from special attacks
   1483   1.5  christos  * 13	platinum dragon	psionics
   1484   1.5  christos  * 14	nymph		steal objects
   1485   1.5  christos  * 15	bugbear		bite
   1486   1.5  christos  * 16	osequip		bite
   1487   1.5  christos  *
   1488   1.5  christos  * char rustarm[ARMORTYPES][2];
   1489   1.5  christos  * special array for maximum rust damage to armor from rustmonster
   1490   1.5  christos  * format is: { armor type , minimum attribute
   1491   1.1       cgd  */
   1492   1.1       cgd #define ARMORTYPES 6
   1493   1.5  christos static char     rustarm[ARMORTYPES][2] = {
   1494   1.5  christos 	{ OSTUDLEATHER, -2 },
   1495   1.5  christos 	{ ORING, -4 },
   1496   1.5  christos 	{ OCHAIN, -5 },
   1497   1.5  christos 	{ OSPLINT, -6 },
   1498   1.5  christos 	{ OPLATE, -8 },
   1499   1.5  christos 	{ OPLATEARMOR, -9}
   1500   1.5  christos };
   1501   1.5  christos static char     spsel[] = {1, 2, 3, 5, 6, 8, 9, 11, 13, 14};
   1502   1.5  christos int
   1503   1.5  christos spattack(x, xx, yy)
   1504   1.5  christos 	int             x, xx, yy;
   1505   1.5  christos {
   1506   1.5  christos 	int    i, j = 0, k, m;
   1507  1.13  dholland 	const char *p = NULL;
   1508  1.13  dholland 
   1509   1.5  christos 	if (c[CANCELLATION])
   1510   1.5  christos 		return (0);
   1511   1.5  christos 	vxy(&xx, &yy);		/* verify x & y coordinates */
   1512   1.5  christos 	switch (x) {
   1513   1.5  christos 	case 1:		/* rust your armor, j=1 when rusting has occurred */
   1514   1.5  christos 		m = k = c[WEAR];
   1515   1.6     veego 		if ((i = c[SHIELD]) != -1) {
   1516   1.5  christos 			if (--ivenarg[i] < -1)
   1517   1.5  christos 				ivenarg[i] = -1;
   1518   1.5  christos 			else
   1519   1.5  christos 				j = 1;
   1520   1.6     veego 		}
   1521   1.5  christos 		if ((j == 0) && (k != -1)) {
   1522   1.5  christos 			m = iven[k];
   1523   1.5  christos 			for (i = 0; i < ARMORTYPES; i++)
   1524   1.5  christos 				/* find his armor in table */
   1525   1.5  christos 				if (m == rustarm[i][0]) {
   1526   1.5  christos 					if (--ivenarg[k] < rustarm[i][1])
   1527   1.5  christos 						ivenarg[k] = rustarm[i][1];
   1528   1.5  christos 					else
   1529   1.5  christos 						j = 1;
   1530   1.5  christos 					break;
   1531   1.5  christos 				}
   1532   1.5  christos 		}
   1533   1.5  christos 		if (j == 0)	/* if rusting did not occur */
   1534   1.5  christos 			switch (m) {
   1535   1.5  christos 			case OLEATHER:
   1536  1.11     mouse 				p = "\nThe %s hit you -- You're lucky you have leather on";
   1537   1.1       cgd 				break;
   1538   1.5  christos 			case OSSPLATE:
   1539  1.11     mouse 				p = "\nThe %s hit you -- You're fortunate to have stainless steel armor!";
   1540   1.1       cgd 				break;
   1541   1.5  christos 			}
   1542   1.5  christos 		else {
   1543   1.5  christos 			beep();
   1544   1.5  christos 			p = "\nThe %s hit you -- your armor feels weaker";
   1545   1.5  christos 		}
   1546   1.5  christos 		break;
   1547   1.5  christos 
   1548   1.5  christos 	case 2:
   1549   1.5  christos 		i = rnd(15) + 8 - c[AC];
   1550   1.5  christos spout:		p = "\nThe %s breathes fire at you!";
   1551   1.5  christos 		if (c[FIRERESISTANCE])
   1552  1.11     mouse 			p = "\nThe %s's flame doesn't faze you!";
   1553   1.5  christos 		else
   1554   1.5  christos spout2:	if (p) {
   1555   1.5  christos 			lprintf(p, lastmonst);
   1556   1.5  christos 			beep();
   1557   1.5  christos 		}
   1558   1.5  christos 		checkloss(i);
   1559   1.5  christos 		return (0);
   1560   1.5  christos 
   1561   1.5  christos 	case 3:
   1562   1.5  christos 		i = rnd(20) + 25 - c[AC];
   1563   1.5  christos 		goto spout;
   1564   1.5  christos 
   1565   1.5  christos 	case 4:
   1566   1.5  christos 		if (c[STRENGTH] > 3) {
   1567   1.5  christos 			p = "\nThe %s stung you!  You feel weaker";
   1568   1.5  christos 			beep();
   1569   1.5  christos 			--c[STRENGTH];
   1570   1.5  christos 		} else
   1571   1.5  christos 			p = "\nThe %s stung you!";
   1572   1.5  christos 		break;
   1573   1.5  christos 
   1574   1.5  christos 	case 5:
   1575   1.5  christos 		p = "\nThe %s blasts you with his cold breath";
   1576   1.5  christos 		i = rnd(15) + 18 - c[AC];
   1577   1.5  christos 		goto spout2;
   1578   1.5  christos 
   1579   1.5  christos 	case 6:
   1580   1.5  christos 		lprintf("\nThe %s drains you of your life energy!", lastmonst);
   1581   1.5  christos 		loselevel();
   1582   1.5  christos 		beep();
   1583   1.5  christos 		return (0);
   1584   1.5  christos 
   1585   1.5  christos 	case 7:
   1586   1.5  christos 		p = "\nThe %s got you with a gusher!";
   1587   1.5  christos 		i = rnd(15) + 25 - c[AC];
   1588   1.5  christos 		goto spout2;
   1589   1.5  christos 
   1590   1.5  christos 	case 8:
   1591   1.5  christos 		if (c[NOTHEFT])
   1592   1.5  christos 			return (0);	/* he has a device of no theft */
   1593   1.5  christos 		if (c[GOLD]) {
   1594   1.5  christos 			p = "\nThe %s hit you -- Your purse feels lighter";
   1595   1.5  christos 			if (c[GOLD] > 32767)
   1596   1.5  christos 				c[GOLD] >>= 1;
   1597   1.5  christos 			else
   1598   1.5  christos 				c[GOLD] -= rnd((int) (1 + (c[GOLD] >> 1)));
   1599   1.5  christos 			if (c[GOLD] < 0)
   1600   1.5  christos 				c[GOLD] = 0;
   1601   1.5  christos 		} else
   1602   1.5  christos 			p = "\nThe %s couldn't find any gold to steal";
   1603   1.5  christos 		lprintf(p, lastmonst);
   1604   1.5  christos 		disappear(xx, yy);
   1605   1.5  christos 		beep();
   1606   1.5  christos 		bottomgold();
   1607   1.5  christos 		return (1);
   1608   1.5  christos 
   1609   1.5  christos 	case 9:
   1610   1.5  christos 		for (j = 50;;) {/* disenchant */
   1611   1.5  christos 			i = rund(26);
   1612   1.5  christos 			m = iven[i];	/* randomly select item */
   1613   1.5  christos 			if (m > 0 && ivenarg[i] > 0 && m != OSCROLL && m != OPOTION) {
   1614   1.5  christos 				if ((ivenarg[i] -= 3) < 0)
   1615   1.5  christos 					ivenarg[i] = 0;
   1616   1.5  christos 				lprintf("\nThe %s hits you -- you feel a sense of loss", lastmonst);
   1617   1.5  christos 				srcount = 0;
   1618   1.5  christos 				beep();
   1619   1.5  christos 				show3(i);
   1620   1.5  christos 				bottomline();
   1621   1.5  christos 				return (0);
   1622   1.5  christos 			}
   1623   1.5  christos 			if (--j <= 0) {
   1624   1.5  christos 				p = "\nThe %s nearly misses";
   1625   1.1       cgd 				break;
   1626   1.5  christos 			}
   1627   1.5  christos 			break;
   1628   1.5  christos 		}
   1629   1.5  christos 		break;
   1630   1.1       cgd 
   1631   1.5  christos 	case 10:
   1632   1.5  christos 		p = "\nThe %s hit you with his barbed tail";
   1633   1.5  christos 		i = rnd(25) - c[AC];
   1634   1.5  christos 		goto spout2;
   1635   1.5  christos 
   1636   1.5  christos 	case 11:
   1637   1.5  christos 		p = "\nThe %s has confused you";
   1638   1.5  christos 		beep();
   1639   1.5  christos 		c[CONFUSE] += 10 + rnd(10);
   1640   1.5  christos 		break;
   1641   1.5  christos 
   1642   1.5  christos 	case 12:		/* performs any number of other special
   1643   1.5  christos 				 * attacks	 */
   1644   1.5  christos 		return (spattack(spsel[rund(10)], xx, yy));
   1645   1.5  christos 
   1646   1.5  christos 	case 13:
   1647   1.5  christos 		p = "\nThe %s flattens you with his psionics!";
   1648   1.5  christos 		i = rnd(15) + 30 - c[AC];
   1649   1.5  christos 		goto spout2;
   1650   1.5  christos 
   1651   1.5  christos 	case 14:
   1652   1.5  christos 		if (c[NOTHEFT])
   1653   1.5  christos 			return (0);	/* he has device of no theft */
   1654   1.5  christos 		if (emptyhanded() == 1) {
   1655   1.5  christos 			p = "\nThe %s couldn't find anything to steal";
   1656   1.5  christos 			break;
   1657   1.5  christos 		}
   1658   1.5  christos 		lprintf("\nThe %s picks your pocket and takes:", lastmonst);
   1659   1.5  christos 		beep();
   1660   1.5  christos 		if (stealsomething() == 0)
   1661   1.5  christos 			lprcat("  nothing");
   1662   1.5  christos 		disappear(xx, yy);
   1663   1.5  christos 		bottomline();
   1664   1.5  christos 		return (1);
   1665   1.5  christos 
   1666   1.5  christos 	case 15:
   1667   1.5  christos 		i = rnd(10) + 5 - c[AC];
   1668   1.5  christos spout3:	p = "\nThe %s bit you!";
   1669   1.5  christos 		goto spout2;
   1670   1.5  christos 
   1671   1.5  christos 	case 16:
   1672   1.5  christos 		i = rnd(15) + 10 - c[AC];
   1673   1.5  christos 		goto spout3;
   1674   1.5  christos 	};
   1675   1.5  christos 	if (p) {
   1676   1.5  christos 		lprintf(p, lastmonst);
   1677   1.5  christos 		bottomline();
   1678   1.1       cgd 	}
   1679   1.5  christos 	return (0);
   1680   1.5  christos }
   1681   1.1       cgd 
   1682   1.1       cgd /*
   1683   1.5  christos  * checkloss(x) Routine to subtract hp from user and flag bottomline display
   1684   1.5  christos  * 	int x;
   1685   1.1       cgd  *
   1686   1.5  christos  * Routine to subtract hitpoints from the user and flag the bottomline display
   1687   1.5  christos  * Enter with the number of hit points to lose
   1688   1.5  christos  * Note: if x > c[HP] this routine could kill the player!
   1689   1.1       cgd  */
   1690   1.5  christos void
   1691   1.1       cgd checkloss(x)
   1692   1.5  christos 	int             x;
   1693   1.5  christos {
   1694   1.5  christos 	if (x > 0) {
   1695   1.5  christos 		losehp(x);
   1696   1.5  christos 		bottomhp();
   1697   1.1       cgd 	}
   1698   1.5  christos }
   1699   1.1       cgd 
   1700   1.1       cgd /*
   1701   1.5  christos  * annihilate() 	Routine to annihilate all monsters around player (playerx,playery)
   1702   1.1       cgd  *
   1703   1.5  christos  * Gives player experience, but no dropped objects
   1704   1.5  christos  * Returns the experience gained from all monsters killed
   1705   1.1       cgd  */
   1706   1.5  christos int
   1707   1.1       cgd annihilate()
   1708   1.5  christos {
   1709   1.5  christos 	int             i, j;
   1710   1.5  christos 	long   k;
   1711   1.5  christos 	u_char  *p;
   1712   1.5  christos 	for (k = 0, i = playerx - 1; i <= playerx + 1; i++)
   1713   1.5  christos 		for (j = playery - 1; j <= playery + 1; j++)
   1714   1.6     veego 			if (!vxy(&i, &j)) {	/* if not out of bounds */
   1715   1.6     veego 				if (*(p = &mitem[i][j])) {	/* if a monster there */
   1716   1.5  christos 					if (*p < DEMONLORD + 2) {
   1717   1.5  christos 						k += monster[*p].experience;
   1718   1.5  christos 						*p = know[i][j] = 0;
   1719   1.5  christos 					} else {
   1720   1.5  christos 						lprintf("\nThe %s barely escapes being annihilated!", monster[*p].name);
   1721   1.5  christos 						hitp[i][j] = (hitp[i][j] >> 1) + 1;	/* lose half hit points */
   1722   1.1       cgd 					}
   1723   1.6     veego 				}
   1724   1.6     veego 			}
   1725   1.5  christos 	if (k > 0) {
   1726   1.5  christos 		lprcat("\nYou hear loud screams of agony!");
   1727   1.5  christos 		raiseexperience((long) k);
   1728   1.5  christos 	}
   1729   1.5  christos 	return (k);
   1730   1.5  christos }
   1731   1.5  christos 
   1732   1.5  christos /*
   1733   1.5  christos  * newsphere(x,y,dir,lifetime)  Function to create a new sphere of annihilation
   1734   1.5  christos  * 	int x,y,dir,lifetime;
   1735   1.5  christos  *
   1736   1.5  christos  * Enter with the coordinates of the sphere in x,y
   1737   1.5  christos  *   the direction (0-8 diroffx format) in dir, and the lifespan of the
   1738   1.5  christos  *   sphere in lifetime (in turns)
   1739   1.5  christos  * Returns the number of spheres currently in existence
   1740   1.5  christos  */
   1741   1.5  christos int
   1742   1.5  christos newsphere(x, y, dir, life)
   1743   1.5  christos 	int             x, y, dir, life;
   1744   1.5  christos {
   1745   1.5  christos 	int             m;
   1746   1.5  christos 	struct sphere  *sp;
   1747   1.5  christos 	if (((sp = (struct sphere *) malloc(sizeof(struct sphere)))) == 0)
   1748   1.5  christos 		return (c[SPHCAST]);	/* can't malloc, therefore failure */
   1749   1.5  christos 	if (dir >= 9)
   1750   1.5  christos 		dir = 0;	/* no movement if direction not found */
   1751   1.5  christos 	if (level == 0)
   1752   1.5  christos 		vxy(&x, &y);	/* don't go out of bounds */
   1753   1.5  christos 	else {
   1754   1.5  christos 		if (x < 1)
   1755   1.5  christos 			x = 1;
   1756   1.5  christos 		if (x >= MAXX - 1)
   1757   1.5  christos 			x = MAXX - 2;
   1758   1.5  christos 		if (y < 1)
   1759   1.5  christos 			y = 1;
   1760   1.5  christos 		if (y >= MAXY - 1)
   1761   1.5  christos 			y = MAXY - 2;
   1762   1.5  christos 	}
   1763   1.5  christos 	if ((m = mitem[x][y]) >= DEMONLORD + 4) {	/* demons dispel spheres */
   1764   1.5  christos 		know[x][y] = 1;
   1765   1.5  christos 		show1cell(x, y);/* show the demon (ha ha) */
   1766   1.5  christos 		cursors();
   1767   1.5  christos 		lprintf("\nThe %s dispels the sphere!", monster[m].name);
   1768   1.5  christos 		beep();
   1769   1.5  christos 		rmsphere(x, y);	/* remove any spheres that are here */
   1770  1.10  christos 		free(sp);
   1771   1.5  christos 		return (c[SPHCAST]);
   1772   1.5  christos 	}
   1773   1.5  christos 	if (m == DISENCHANTRESS) {	/* disenchantress cancels spheres */
   1774   1.5  christos 		cursors();
   1775   1.5  christos 		lprintf("\nThe %s causes cancellation of the sphere!", monster[m].name);
   1776   1.5  christos 		beep();
   1777   1.5  christos boom:		sphboom(x, y);	/* blow up stuff around sphere */
   1778   1.5  christos 		rmsphere(x, y);	/* remove any spheres that are here */
   1779  1.10  christos 		free(sp);
   1780   1.5  christos 		return (c[SPHCAST]);
   1781   1.1       cgd 	}
   1782   1.5  christos 	if (c[CANCELLATION]) {	/* cancellation cancels spheres */
   1783   1.5  christos 		cursors();
   1784   1.5  christos 		lprcat("\nAs the cancellation takes effect, you hear a great earth shaking blast!");
   1785   1.5  christos 		beep();
   1786   1.1       cgd 		goto boom;
   1787   1.5  christos 	}
   1788   1.5  christos 	if (item[x][y] == OANNIHILATION) {	/* collision of spheres
   1789   1.5  christos 						 * detonates spheres */
   1790   1.5  christos 		cursors();
   1791   1.5  christos 		lprcat("\nTwo spheres of annihilation collide! You hear a great earth shaking blast!");
   1792   1.5  christos 		beep();
   1793   1.5  christos 		rmsphere(x, y);
   1794   1.1       cgd 		goto boom;
   1795   1.5  christos 	}
   1796   1.5  christos 	if (playerx == x && playery == y) {	/* collision of sphere and
   1797   1.5  christos 						 * player! */
   1798   1.1       cgd 		cursors();
   1799   1.1       cgd 		lprcat("\nYou have been enveloped by the zone of nothingness!\n");
   1800   1.5  christos 		beep();
   1801   1.5  christos 		rmsphere(x, y);	/* remove any spheres that are here */
   1802   1.5  christos 		nap(4000);
   1803   1.5  christos 		died(258);
   1804   1.5  christos 	}
   1805   1.5  christos 	item[x][y] = OANNIHILATION;
   1806   1.5  christos 	mitem[x][y] = 0;
   1807   1.5  christos 	know[x][y] = 1;
   1808   1.5  christos 	show1cell(x, y);	/* show the new sphere */
   1809   1.5  christos 	sp->x = x;
   1810   1.5  christos 	sp->y = y;
   1811   1.5  christos 	sp->lev = level;
   1812   1.5  christos 	sp->dir = dir;
   1813   1.5  christos 	sp->lifetime = life;
   1814   1.5  christos 	sp->p = 0;
   1815   1.5  christos 	if (spheres == 0)
   1816   1.5  christos 		spheres = sp;	/* if first node in the sphere list */
   1817   1.5  christos 	else {			/* add sphere to beginning of linked list */
   1818   1.5  christos 		sp->p = spheres;
   1819   1.5  christos 		spheres = sp;
   1820   1.5  christos 	}
   1821   1.5  christos 	return (++c[SPHCAST]);	/* one more sphere in the world */
   1822   1.5  christos }
   1823   1.5  christos 
   1824   1.5  christos /*
   1825   1.5  christos  * rmsphere(x,y)		Function to delete a sphere of annihilation from list
   1826   1.5  christos  * 	int x,y;
   1827   1.5  christos  *
   1828   1.5  christos  * Enter with the coordinates of the sphere (on current level)
   1829   1.5  christos  * Returns the number of spheres currently in existence
   1830   1.5  christos  */
   1831   1.5  christos int
   1832   1.5  christos rmsphere(x, y)
   1833   1.5  christos 	int             x, y;
   1834   1.5  christos {
   1835   1.5  christos 	struct sphere *sp, *sp2 = 0;
   1836   1.5  christos 	for (sp = spheres; sp; sp2 = sp, sp = sp->p)
   1837   1.5  christos 		if (level == sp->lev)	/* is sphere on this level? */
   1838   1.5  christos 			if ((x == sp->x) && (y == sp->y)) {	/* locate sphere at this
   1839   1.5  christos 								 * location */
   1840   1.5  christos 				item[x][y] = mitem[x][y] = 0;
   1841   1.5  christos 				know[x][y] = 1;
   1842   1.5  christos 				show1cell(x, y);	/* show the now missing
   1843   1.5  christos 							 * sphere */
   1844   1.5  christos 				--c[SPHCAST];
   1845   1.5  christos 				if (sp == spheres) {
   1846   1.5  christos 					sp2 = sp;
   1847   1.5  christos 					spheres = sp->p;
   1848   1.5  christos 					free((char *) sp2);
   1849   1.5  christos 				} else {
   1850   1.9  christos 					if (sp2)
   1851   1.9  christos 						sp2->p = sp->p;
   1852   1.5  christos 					free((char *) sp);
   1853   1.5  christos 				}
   1854   1.5  christos 				break;
   1855   1.1       cgd 			}
   1856   1.5  christos 	return (c[SPHCAST]);	/* return number of spheres in the world */
   1857   1.5  christos }
   1858   1.1       cgd 
   1859   1.1       cgd /*
   1860   1.5  christos  * sphboom(x,y)	Function to perform the effects of a sphere detonation
   1861   1.5  christos  * 	int x,y;
   1862   1.1       cgd  *
   1863   1.5  christos  * Enter with the coordinates of the blast, Returns no value
   1864   1.1       cgd  */
   1865   1.5  christos void
   1866   1.5  christos sphboom(x, y)
   1867   1.5  christos 	int             x, y;
   1868   1.5  christos {
   1869   1.5  christos 	int    i, j;
   1870   1.5  christos 	if (c[HOLDMONST])
   1871   1.5  christos 		c[HOLDMONST] = 1;
   1872   1.5  christos 	if (c[CANCELLATION])
   1873   1.5  christos 		c[CANCELLATION] = 1;
   1874   1.5  christos 	for (j = max(1, x - 2); j < min(x + 3, MAXX - 1); j++)
   1875   1.5  christos 		for (i = max(1, y - 2); i < min(y + 3, MAXY - 1); i++) {
   1876   1.5  christos 			item[j][i] = mitem[j][i] = 0;
   1877   1.5  christos 			show1cell(j, i);
   1878   1.5  christos 			if (playerx == j && playery == i) {
   1879   1.5  christos 				cursors();
   1880   1.5  christos 				beep();
   1881   1.5  christos 				lprcat("\nYou were too close to the sphere!");
   1882   1.5  christos 				nap(3000);
   1883   1.5  christos 				died(283);	/* player killed in explosion */
   1884   1.1       cgd 			}
   1885   1.1       cgd 		}
   1886   1.5  christos }
   1887   1.1       cgd 
   1888   1.1       cgd /*
   1889   1.5  christos  * genmonst()		Function to ask for monster and genocide from game
   1890   1.1       cgd  *
   1891   1.5  christos  * This is done by setting a flag in the monster[] structure
   1892   1.1       cgd  */
   1893   1.5  christos void
   1894   1.1       cgd genmonst()
   1895   1.5  christos {
   1896   1.5  christos 	int    i, j;
   1897   1.5  christos 	cursors();
   1898   1.5  christos 	lprcat("\nGenocide what monster? ");
   1899   1.7  christos 	for (i = 0; (!isalpha(i)) && (i != ' '); i = lgetchar());
   1900   1.1       cgd 	lprc(i);
   1901   1.5  christos 	for (j = 0; j < MAXMONST; j++)	/* search for the monster type */
   1902   1.5  christos 		if (monstnamelist[j] == i) {	/* have we found it? */
   1903   1.5  christos 			monster[j].genocided = 1;	/* genocided from game */
   1904   1.5  christos 			lprintf("  There will be no more %s's", monster[j].name);
   1905   1.1       cgd 			/* now wipe out monsters on this level */
   1906   1.5  christos 			newcavelevel(level);
   1907   1.5  christos 			draws(0, MAXX, 0, MAXY);
   1908   1.5  christos 			bot_linex();
   1909   1.1       cgd 			return;
   1910   1.5  christos 		}
   1911   1.1       cgd 	lprcat("  You sense failure!");
   1912   1.5  christos }
   1913