DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T s

⟦03fdaa424⟧ TextFile

    Length: 56425 (0xdc69)
    Types: TextFile
    Names: »spells.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/General/Umoria/spells.c« 

TextFile

#include <stdio.h>

#include "constants.h"
#include "config.h"
#include "types.h"
#include "externs.h"

#ifdef USG
#include <string.h>
#else
#include <strings.h>
#endif

#ifdef sun   /* correct SUN stupidity in the stdio.h file */
char *sprintf();
#endif

extern char cur_char2();

/* Following are spell procedure/functions			-RAK-	*/
/* These routines are commonly used in the scroll, potion, wands, and    */
/* staves routines, and are occasionally called from other areas.         */
/* Now included are creature spells also...                      -RAK    */

monster_name (m_name, m_ptr, r_ptr)
char *m_name;
monster_type *m_ptr;
creature_type *r_ptr;
{
  if ((!m_ptr->ml) || (py.flags.blind > 0) ||
      ((0x10000 & r_ptr->cmove) && (!py.flags.see_inv)))
    (void) strcpy (m_name, "It");
  else
    (void) sprintf (m_name, "The %s", r_ptr->name);
}

lower_monster_name (m_name, m_ptr, r_ptr)
char *m_name;
monster_type *m_ptr;
creature_type *r_ptr;
{
  if ((!m_ptr->ml) || (py.flags.blind > 0) ||
      ((0x10000 & r_ptr->cmove) && (!py.flags.see_inv)))
    (void) strcpy (m_name, "it");
  else
    (void) sprintf (m_name, "the %s", r_ptr->name);
}

/* Sleep creatures adjacent to player			-RAK-	*/
int sleep_monsters1(y, x)
int y, x;
{
  register int i, j;
  register cave_type *c_ptr;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  int sleep;
  vtype out_val;
  vtype m_name;

  sleep = FALSE;
  for (i = y-1; i <= y+1; i++)
    for (j = x-1; j <= x+1; j++)
      {
	c_ptr = &cave[i][j];
	if (c_ptr->cptr > 1)
	  {
	    m_ptr = &m_list[c_ptr->cptr];
	    r_ptr = &c_list[m_ptr->mptr];

	    monster_name (m_name, m_ptr, r_ptr);
	    if ((randint(MAX_MONS_LEVEL) < r_ptr->level) ||
		(0x1000 & r_ptr->cdefense))
	      {
		(void) sprintf(out_val, "%s is unaffected.", m_name);
		msg_print(out_val);
	      }
	    else
	      {
		sleep = TRUE;
		m_ptr->csleep = 500;
		(void) sprintf(out_val, "%s falls asleep.", m_name);
		msg_print(out_val);
	      }
	  }
      }
  return(sleep);
}

/* Detect any treasure on the current panel		-RAK-	*/
int detect_treasure()
{
  register int i, j;
  register int detect;
  register cave_type *c_ptr;

  detect = FALSE;
  for (i = panel_row_min; i <= panel_row_max; i++)
    for (j = panel_col_min; j <= panel_col_max; j++)
      {
	c_ptr = &cave[i][j];
	if (c_ptr->tptr != 0)
	  if (t_list[c_ptr->tptr].tval == 100)
	    if (!test_light(i, j))
	      {
		lite_spot(i, j);
		c_ptr->tl = TRUE;
		detect = TRUE;
	      }
      }
  return(detect);
}


/* Detect all objects on the current panel		-RAK-	*/
int detect_object()
{
  register int i, j;
  register int detect;
  register cave_type *c_ptr;

  detect = FALSE;
  for (i = panel_row_min; i <= panel_row_max; i++)
    for (j = panel_col_min; j <= panel_col_max; j++)
      {
	c_ptr = &cave[i][j];
	if (c_ptr->tptr != 0)
	  if (t_list[c_ptr->tptr].tval < 100)
	    if (!test_light(i, j))
	      {
		lite_spot(i, j);
		c_ptr->tl = TRUE;
		detect = TRUE;
	      }
      }
  return(detect);
}


/* Locates and displays traps on current panel		-RAK-	*/
int detect_trap()
{
  register int i, j;
  int detect;
  register cave_type *c_ptr;
  register treasure_type *t_ptr;

  detect = FALSE;
  for (i = panel_row_min; i <= panel_row_max; i++)
    for (j = panel_col_min; j <= panel_col_max; j++)
      {
	c_ptr = &cave[i][j];
	if (c_ptr->tptr != 0)
	  if (t_list[c_ptr->tptr].tval == 101)
	    {
	      change_trap(i, j);
	      c_ptr->fm = TRUE;
	      detect = TRUE;
	    }
	  else if (t_list[c_ptr->tptr].tval == 2)
	    {
	      t_ptr = &t_list[c_ptr->tptr];
	      known2(t_ptr->name);
	    }
      }
  return(detect);
}


/* Locates and displays all secret doors on current panel -RAK-	*/
int detect_sdoor()
{
  register int i, j;
  register int detect;
  register cave_type *c_ptr;

  detect = FALSE;
  for (i = panel_row_min; i <= panel_row_max; i++)
    for (j = panel_col_min; j <= panel_col_max; j++)
      {
	c_ptr = &cave[i][j];
	if (c_ptr->tptr != 0)
	  /* Secret doors  */
	  if (t_list[c_ptr->tptr].tval == 109)
	    {
	      c_ptr->fval = corr_floor3.ftval;
	      change_trap(i, j);
	      c_ptr->fm = TRUE;
	      detect = TRUE;
	    }
	/* Staircases    */
	  else if ((t_list[c_ptr->tptr].tval == 107) ||
		   (t_list[c_ptr->tptr].tval == 108))
	    if (!c_ptr->fm)
	      {
		c_ptr->fm = TRUE;
		lite_spot(i, j);
		detect = TRUE;
	      }
      }
  return(detect);
}


/* Locates and displays all invisible creatures on current panel -RAK-*/
int detect_invisible()
{
  register int i;
  register int flag;
  char tmp_str[2];
  register monster_type *m_ptr;

  flag = FALSE;
  i = muptr;
  while (i > 0)
    {
      m_ptr = &m_list[i];
      if (panel_contains((int)m_ptr->fy, (int)m_ptr->fx))
	if (0x10000 & c_list[m_ptr->mptr].cmove)
	  {
	    m_ptr->ml = TRUE;
	    tmp_str[0] = c_list[m_ptr->mptr].cchar;
	    tmp_str[1] = '\0';
	    print(tmp_str, (int)m_ptr->fy, (int)m_ptr->fx);
	    flag = TRUE;
	  }
      i = m_list[i].nptr;
    }
  if (flag)
    {
      msg_print("You sense the presence of invisible creatures!");
      /* make sure player sees the message */
      msg_print(" ");
      msg_flag = FALSE;
    }
  return(flag);
}


/* Light an area: 1.  If corridor  light immediate area -RAK-*/
/*                2.  If room  light entire room.            */
int light_area(y, x)
register int y, x;
{
  register int i, j;
  register int light;

  msg_print("You are surrounded by a white light.");
  light = TRUE;
  if (((cave[y][x].fval == 1) || (cave[y][x].fval == 2)) && (dun_level > 0))
    light_room(y, x);
  else
    for (i = y-1; i <= y+1; i++)
      for (j = x-1; j <=  x+1; j++)
	if (in_bounds(i, j))
	  {
	    if (!test_light(i, j))
	      lite_spot(i, j);
	    cave[i][j].pl = TRUE;
	  }
  return(light);
}


/* Darken an area, opposite of light area		-RAK-	*/
int unlight_area(y, x)
int y, x;
{
  register int i, j, k;
  int tmp1, tmp2;
  int start_row, start_col;
  int end_row, end_col;
  int flag;
  int unlight;
  register cave_type *c_ptr;
  vtype out_val;

  flag = FALSE;
  if (((cave[y][x].fval == 1) || (cave[y][x].fval == 2)) && (dun_level > 0))
    {
      tmp1 = (SCREEN_HEIGHT/2);
      tmp2 = (SCREEN_WIDTH /2);
      start_row = (y/tmp1)*tmp1 + 1;
      start_col = (x/tmp2)*tmp2 + 1;
      end_row = start_row + tmp1 - 1;
      end_col = start_col + tmp2 - 1;
      for (i = start_row; i <= end_row; i++)
	{
	  out_val[0] = '\0';
	  k = 0;
	  for (j = start_col; j <= end_col; j++)
	    {
	      c_ptr = &cave[i][j];
	      if ((c_ptr->fval == 1) || (c_ptr->fval == 2))
		{
		  c_ptr->pl = FALSE;
		  c_ptr->fval = 1;
		  if (!test_light(i, j))
		    {
		      if (k == 0)
			k = j;
		      (void) strcat(out_val, " ");
		    }
		  else if (k > 0)
		    {
		      flag = TRUE;
		      print(out_val, i, k);
		      out_val[0] = '\0';
		      k = 0;
		    }
		}
	      else if (k > 0)
		{
		  flag = TRUE;
		  print(out_val, i, k);
		  out_val[0] = '\0';
		  k = 0;
		}
	      if (k > 0)
		{
		  flag = TRUE;
		  print(out_val, i, k);
		}
	    }
	}
    }
  else
    for (i = y-1; i <= y+1; i++)
      for (j = x-1; j <= x+1; j++)
	if (in_bounds(i, j))
	  {
	    c_ptr = &cave[i][j];
	    if ((c_ptr->fval == 4) || (c_ptr->fval == 5) || (c_ptr->fval ==6))
	      if (c_ptr->pl)
		{
		  c_ptr->pl = FALSE;
		  flag = TRUE;
		}
	    if (flag)
	      {
		msg_print("Darkness surrounds you...");
		unlight = TRUE;
	      }
	  }
	else
	  unlight = FALSE;
  return(unlight);
}


/* Map the current area plus some			-RAK-	*/
int map_area()
{
  register cave_type *c_ptr;
  register int i7, i8, n, m;
  int i, j, k, l;
  int map;

  map = TRUE;
  i = panel_row_min - randint(10);
  j = panel_row_max + randint(10);
  k = panel_col_min - randint(20);
  l = panel_col_max + randint(20);
  for (m = i; m <= j; m++)
    for (n = k; n <= l; n++)
      if (in_bounds(m, n))
	if (set_floor(cave[m][n].fval))
	  for (i7 = m-1; i7 <= m+1; i7++)
	    for (i8 = n-1; i8 <= n+1; i8++)
	      {
		c_ptr = &cave[i7][i8];
		if (((c_ptr->fval >= 10) && (c_ptr->fval <= 12)) ||
		    (c_ptr->fval == 15))
		  c_ptr->pl = TRUE;
		else if (c_ptr->tptr != 0)
		  if ((t_list[c_ptr->tptr].tval >= 102) &&
		      (t_list[c_ptr->tptr].tval <= 110) &&
		      (t_list[c_ptr->tptr].tval != 106))
		    c_ptr->fm = TRUE;
	      }
  prt_map();
  return(map);
}


/* Identify an object					-RAK-	*/
int ident_spell()
{
  int item_val;
  vtype out_val, tmp_str;
  int redraw;
  int ident;
  register treasure_type *i_ptr;

  ident = FALSE;
  redraw = FALSE;
  if (get_item(&item_val, "Item you wish identified?",
	       &redraw, 0, inven_ctr-1))
    {
      i_ptr = &inventory[item_val];
      ident = TRUE;
      identify(inventory[item_val]);
      known2(i_ptr->name);
      objdes(tmp_str, item_val, TRUE);
      (void) sprintf(out_val, "%c%c %s", item_val+97, cur_char2(item_val),
		     tmp_str);
      msg_print(out_val);
    }
  if (redraw)
    {
      /* make sure player sees message before draw cave erases it */
      msg_print(" ");
      draw_cave();
    }
  return(ident);
}


/* Get all the monsters on the level pissed off...	-RAK-	*/
int aggravate_monster  (dis_affect)
int dis_affect;
{
  register int i;
  int aggravate;
  register monster_type *m_ptr;

  aggravate = TRUE;
  i = muptr;
  while (i > 0)
    {
      m_ptr = &m_list[i];
      m_ptr->csleep = 0;
      if (m_ptr->cdis <= dis_affect)
	if (m_ptr->cspeed < 2)
	  m_ptr->cspeed++;
      i = m_list[i].nptr;
    }
  return(aggravate);
}


/* Surround the fool with traps (chuckle)		-RAK-	*/
int trap_creation()
{
  register int i, j;
  register int trap;
  register cave_type *c_ptr;

  trap = TRUE;
  for (i = char_row-1; i <= char_row+1; i++)
    for (j = char_col-1; j <= char_col+1; j++)
      {
	c_ptr = &cave[i][j];
	if (set_floor(c_ptr->fval))
	  {
	    if (c_ptr->tptr != 0)
	      (void) delete_object(i, j);
	    place_trap(i, j, 1, randint(MAX_TRAPA)-1);
	  }
      }
  return(trap);
}


/* Surround the player with doors...			-RAK-	*/
int door_creation()
{
  register int i, j;
  int k;
  register int door;
  register cave_type *c_ptr;

  door = TRUE;
  for (i = char_row-1; i <= char_row+1; i++)
    for (j = char_col-1; j <=  char_col+1; j++)
      if ((i != char_row) || (j != char_col))
	{
	  c_ptr = &cave[i][j];
	  if (set_floor(c_ptr->fval))
	    {
	      popt(&k);
	      if (c_ptr->tptr != 0)
		(void) delete_object(i, j);
	      c_ptr->fopen = FALSE;
	      c_ptr->tptr = k;
	      t_list[k] = door_list[1];
	      if (test_light(i, j))
		lite_spot(i, j);
	    }
	}
  return(door);
}


/* Destroys any adjacent door(s)/trap(s) 		-RAK-	*/
int td_destroy()
{
  register int i, j;
  register int destroy;
  register cave_type *c_ptr;
  char *tmp_str;

  destroy = FALSE;
  for (i = char_row-1; i <= char_row+1; i++)
    for (j = char_col-1; j <= char_col+1; j++)
      {
	c_ptr = &cave[i][j];
	if (c_ptr->tptr != 0)
	  {
	    if (((t_list[c_ptr->tptr].tval >= 101) &&
		 (t_list[c_ptr->tptr].tval <= 105) &&
		 (t_list[c_ptr->tptr].tval != 103)) ||
		(t_list[c_ptr->tptr].tval == 109))
	      {
		if (delete_object(i, j))
		  destroy = TRUE;
	      }
	    else if (t_list[c_ptr->tptr].tval == 2)
	      {
		/* destroy traps on chest and unlock */
		t_list[c_ptr->tptr].flags &= 0xFF000000;
		tmp_str = index(t_list[c_ptr->tptr].name, '(');
		if (tmp_str != 0)
		  tmp_str[0] = '\0';
		(void) strcat (t_list[c_ptr->tptr].name, "(Disarmed)");
		msg_print ("You have disarmed the chest.");
		known2 (t_list[c_ptr->tptr].name);
	      }
	  }
      }
  return(destroy);
}


/* Display all creatures on the current panel		-RAK-	*/
int detect_monsters()
{
  register int i;
  register int flag, detect;
  char tmp_str[2];
  register monster_type *m_ptr;

  flag = FALSE;
  i = muptr;
  while (i > 0)
    {
      m_ptr = &m_list[i];
      if (panel_contains((int)m_ptr->fy, (int)m_ptr->fx))
	if ((0x10000 & c_list[m_ptr->mptr].cmove) == 0)
	  {
	    m_ptr->ml = TRUE;
	    tmp_str[0] = c_list[m_ptr->mptr].cchar;
	    tmp_str[1] = '\0';
	    print(tmp_str, (int)m_ptr->fy, (int)m_ptr->fx);
	    flag = TRUE;
	  }
      i = m_list[i].nptr;
    }
  if (flag)
    {
      msg_print("You sense the presence of monsters!");
      /* make sure player sees the message */
      msg_print(" ");
      msg_flag = FALSE;
      detect = TRUE;
    }
  detect = flag;
  return(detect);
}


/* Leave a line of light in given dir, blue light can sometimes	*/
/* hurt creatures...                                     -RAK-   */
light_line(dir, y, x)
int dir, y, x;
{
  register int i;
  register cave_type *c_ptr;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  vtype out_val;
  vtype m_name;
  char tmp_str[2];

  while (cave[y][x].fopen){
      c_ptr = &cave[y][x];
      if (panel_contains(y, x))
	{
	  if ((!c_ptr->tl) && (!c_ptr->pl))
	    if (c_ptr->fval == 2)
	      light_room(y, x);
	    else
	      lite_spot(y, x);
	  if (c_ptr->cptr > 1)
	    {
	      m_ptr = &m_list[c_ptr->cptr];
	      r_ptr = &c_list[m_ptr->mptr];
	      m_ptr->ml = TRUE;
	      tmp_str[0] = r_ptr->cchar;
	      tmp_str[1] = '\0';
	      print(tmp_str, (int)m_ptr->fy, (int)m_ptr->fx);
	      monster_name (m_name, m_ptr, r_ptr);
	      if (0x0100 & r_ptr->cdefense)
		{
		  (void) sprintf(out_val, "%s wails out in pain!", m_name);
		  msg_print(out_val);
		  i = mon_take_hit((int)c_ptr->cptr, damroll("2d8"));
		  if (i >= 0)
		    {
		      (void) sprintf(out_val, "%s dies in a fit of agony.",
				     m_name);
		      msg_print(out_val);
		    }
		}
	    }
	  c_ptr->pl = TRUE;
	}
      (void) move(dir, &y, &x);
    }
}


/* Light line in all directions				-RAK-	*/
int starlite(y, x)
register int y, x;
{
  register int i;

  msg_print("The end of the staff bursts into a blue shimmering light.");
  for (i = 1; i <= 9; i++)
    if (i != 5)
      light_line(i, y, x);
  return(TRUE);
}


/* Disarms all traps/chests in a given direction 	-RAK-	*/
int disarm_all(dir, y, x)
int dir, y, x;
{
  register cave_type *c_ptr;
  register treasure_type *t_ptr;
  register int i, oldy, oldx;
  int disarm;
  char *string;

  disarm = FALSE;
  do
    {
      c_ptr = &cave[y][x];
      if (c_ptr->tptr != 0)
	{
	  t_ptr = &t_list[c_ptr->tptr];
	  if ((t_ptr->tval == 101) || (t_ptr->tval == 102))
	    {
	      if (delete_object(y, x))
		disarm = TRUE;
	    }
	  else if (t_ptr->tval == 105)
	    {
	      t_ptr->p1 = 0;
	    }
	  else if (t_ptr->tval == 109)
	    {
	      c_ptr->fval = corr_floor3.ftval;
	      change_trap(y, x);
	      c_ptr->fm = TRUE;
	      disarm = TRUE;
	    }
	  else if (t_ptr->tval == 2)
	    if (t_ptr->flags != 0)
	      {
		msg_print("Click!");
		t_ptr->flags = 0;
		disarm = TRUE;
		string = index(t_ptr->name, '(');
		if (string)
		  i = strlen(t_ptr->name) - strlen(string);
		else
		  i = -1;
		if (i >= 0)
		  t_ptr->name[i] = '\0';
		(void) strcat(t_ptr->name, "(Unlocked)");
		known2(t_ptr->name);
	      }
	}
      oldy = y;
      oldx = x;
      (void) move(dir, &y, &x);
    }
  while (cave[oldy][oldx].fopen);
  return(disarm);
}


/* Return flags for given type area affect		-RAK-	*/
get_flags(typ, weapon_type, harm_type, destroy)
int typ;
int *weapon_type, *harm_type;
int (**destroy)();
{
  int set_null(), set_fire_destroy(), set_frost_destroy();
  int set_acid_destroy(), set_lightning_destroy();

  switch(typ)
    {
    case 1:      /* Lightning     */
      *weapon_type = 0x00080000;
      *harm_type   = 0x0100;
      *destroy     = set_lightning_destroy;
      break;
    case 2:      /* Poison Gas    */
      *weapon_type = 0x00100000;
      *harm_type   = 0x0040;
      *destroy     = set_null;
      break;
    case 3:      /* Acid          */
      *weapon_type = 0x00200000;
      *harm_type   = 0x0080;
      *destroy     = set_acid_destroy;
      break;
    case 4:      /* Frost         */
      *weapon_type = 0x00400000;
      *harm_type   = 0x0010;
      *destroy     = set_frost_destroy;
      break;
    case 5:      /* Fire          */
      *weapon_type = 0x00800000;
      *harm_type   = 0x0020;
      *destroy     = set_fire_destroy;
      break;
    case 6:      /* Holy Orb      */
      *weapon_type = 0x00000000;
      *harm_type   = 0x0004;
      *destroy     = set_null;
      break;
    default:
      *weapon_type = 0;
      *harm_type   = 0;
      *destroy     = set_null;
    }
}


/* Shoot a bolt in a given direction			-RAK-	*/
int fire_bolt(typ, dir, y, x, dam, bolt_typ)
int typ, dir, y, x, dam;
char *bolt_typ;
{
  int i, oldy, oldx, dist;
  int weapon_type, harm_type;
  int flag;
  int (*dummy)();
  register cave_type *c_ptr;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  vtype out_val;
  vtype m_name;
  char tmp_str[2];

  flag = FALSE;
  get_flags(typ, &weapon_type, &harm_type, &dummy);
  oldy = y;
  oldx = x;
  dist = 0;
  do
    {
      (void) move(dir, &y, &x);
      if (test_light(oldy, oldx))
	lite_spot(oldy, oldx);
      else
	unlite_spot(oldy, oldx);
      dist++;
      if (dist > OBJ_BOLT_RANGE)
	flag = TRUE;
      else
	{
	  c_ptr = &cave[y][x];
	  if (c_ptr->fopen)
	    {
	      if (c_ptr->cptr > 1)
		{
		  flag = TRUE;
		  m_ptr = &m_list[c_ptr->cptr];
		  r_ptr = &c_list[m_ptr->mptr];
		  /* light it up first, then check to see if visible */
		  m_list[c_ptr->cptr].ml = TRUE;
		  lower_monster_name(m_name, m_ptr, r_ptr);
		  (void) sprintf(out_val, "The %s strikes %s.", bolt_typ,
			  m_name);
		  msg_print(out_val);
		  if (harm_type & r_ptr->cdefense)
		    dam = dam*2;
		  else if (weapon_type & r_ptr->spells)
		    dam = (dam / 4);
		  i = mon_take_hit((int)c_ptr->cptr, dam);
		  monster_name(m_name, m_ptr, r_ptr);
		  if (i >= 0)
		    {
		      (void) sprintf(out_val, "%s dies in a fit of agony.",
			      m_name);
		      msg_print(out_val);
		    }
		  else
		    {
		      if (panel_contains(y, x))
			{
			  tmp_str[0] = c_list[m_ptr->mptr].cchar;
			  tmp_str[1] = '\0';
			  print(tmp_str, y, x);
			}
		      if (dam > 0)
			{
			  (void) sprintf (out_val, "%s screams in agony.",
					  m_name);
			  msg_print (out_val);
			}
		    }
		}
	      else if (panel_contains(y, x))
		{
		  print("*", y, x);
		  /* show the bolt */
		  put_qio();
		}
	    }
	  else
	    flag = TRUE;
	}
      oldy = y;
      oldx = x;
    }
  while (!flag);
}


/* Shoot a ball in a given direction.  Note that balls have an	*/
/* area affect....                                       -RAK-   */
int fire_ball(typ, dir, y, x, dam_hp, descrip)
int typ, dir, y, x, dam_hp;
char *descrip;
{
  register int i, j;
  int dam, max_dis, thit, tkill, k;
  int oldy, oldx, dist;
  int weapon_type, harm_type;
  int flag;
  int (*destroy)();
  register cave_type *c_ptr;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  vtype out_val;
  char tmp_str[2];

  thit   = 0;
  tkill  = 0;
  max_dis = 2;
  get_flags(typ, &weapon_type, &harm_type, &destroy);
  flag = FALSE;
  oldy = y;
  oldx = x;
  dist = 0;
  do
    {
      (void) move(dir, &y, &x);
      dist++;
      if (test_light(oldy, oldx))
	lite_spot(oldy, oldx);
      else
	unlite_spot(oldy, oldx);
      if (dist > OBJ_BOLT_RANGE)
	flag = TRUE;
      else
	{
	  c_ptr = &cave[y][x];
	  if ((!c_ptr->fopen) || (c_ptr->cptr > 1))
	    {
	      flag = TRUE;
	      if (!c_ptr->fopen)
		{
		  y = oldy;
		  x = oldx;
		}
	      /* The ball hits and explodes...                 */
	      /* The explosion...                      */
	      for (i = y-max_dis; i <= y+max_dis; i++)
		for (j = x-max_dis; j <= x+max_dis; j++)
		  if (in_bounds(i, j))
		    if (distance(y, x, i, j) <= max_dis)
		      if (los(y, x, i, j))     /* FIXED BUG V4.5        */
			{
			  c_ptr = &cave[i][j];
			  if (c_ptr->tptr != 0)
			    if ((*destroy)(t_list[c_ptr->tptr].tval))
			      (void) delete_object(i, j);
			  if (c_ptr->fopen)
			    {
			      if (panel_contains(i, j))  print("*", i, j);
			      if (c_ptr->cptr > 1)
				{
				  m_ptr = &m_list[c_ptr->cptr];
				  r_ptr = &c_list[m_ptr->mptr];
				  thit++;
				  dam = dam_hp;
				  if (harm_type & r_ptr->cdefense)
				    dam = dam*2;
				  else if (weapon_type & r_ptr->spells)
				    dam = dam / 4;
				  dam = (dam/(distance(i, j, y, x)+1));
				  k = mon_take_hit((int)c_ptr->cptr, dam);
				  if (k >= 0)
				    tkill++;
				  else
				    {
				      if (panel_contains(i, j))
					{
					  tmp_str[0] = r_ptr->cchar;
					  tmp_str[1] = '\0';
					  print(tmp_str, i, j);
					  m_ptr->ml = TRUE;
					}
				    }
				}
			    }
			}
	      /* show ball of whatever */
	      put_qio();

	      for (i = (y - 2); i <= (y + 2); i++)
		for (j = (x - 2); j <= (x + 2); j++)
		  if (in_bounds(i, j))
		    if (panel_contains(i, j))
		      if (distance(y, x, i, j) <= max_dis)
			{
			  c_ptr = &cave[i][j];
			  if (test_light(i, j))
			    lite_spot(i, j);
			  else if (c_ptr->cptr == 1)
			    lite_spot(i, j);
			  else if (c_ptr->cptr > 1)
			    if (m_list[c_ptr->cptr].ml)
			      lite_spot(i, j);
			    else
			      unlite_spot(i, j);
			  else
			    unlite_spot(i, j);
			}
	      /* End  explosion...                     */
	      if (thit == 1)
		{
		  (void) sprintf(out_val,
				 "The %s envelopes a creature!",
				 descrip);
		  msg_print(out_val);
		}
	      else if (thit > 1)
		{
		  (void) sprintf(out_val,
				 "The %s envelopes several creatures!",
				 descrip);
		  msg_print(out_val);
		}
	      if (tkill == 1)
		msg_print("There is a scream of agony!");
	      else if (tkill > 1)
		msg_print("There are several screams of agony!");
	      /* End ball hitting...                   */
	    }
	  else if (panel_contains(y, x))
	    {
	      print("*", y, x);
	      /* show bolt */
	      put_qio();
	    }
	  oldy = y;
	  oldx = x;
	}
    }
  while (!flag);
}


/* Breath weapon works like a fire_ball, but affects the player. */
/* Note the area affect....                              -RAK-   */
breath(typ, y, x, dam_hp, ddesc)
int typ, y, x, dam_hp;
char *ddesc;
{
  register int i, j;
  int dam, max_dis;
  int weapon_type, harm_type;
  int (*destroy)();
  register cave_type *c_ptr;
  register monster_type *m_ptr;
  register creature_type *r_ptr;

  max_dis = 2;
  get_flags(typ, &weapon_type, &harm_type, &destroy);
  for (i = y-2; i <= y+2; i++)
    for (j = x-2; j <= x+2; j++)
      if (in_bounds(i, j))
	if (distance(y, x, i, j) <= max_dis)
	  {
	    c_ptr = &cave[i][j];
	    if (c_ptr->tptr != 0)
	      if ((*destroy)(t_list[c_ptr->tptr].tval))
		(void) delete_object(i, j);
	    if (c_ptr->fopen)
	      {
		if (panel_contains(i, j))
		  print("*", i, j);
		if (c_ptr->cptr > 1)
		  {
		    m_ptr = &m_list[c_ptr->cptr];
		    r_ptr = &c_list[m_ptr->mptr];
		    dam = dam_hp;
		    if (harm_type & r_ptr->cdefense)
		      dam = dam*2;
		    else if (weapon_type & r_ptr->spells)
		      dam = (dam / 4);
		    dam = (dam/(distance(i, j, y, x)+1));
		    m_ptr->hp = m_ptr->hp - dam;
		    m_ptr->csleep = 0;
		    if (m_ptr->hp < 0)
		      {
			monster_death((int)m_ptr->fy, (int)m_ptr->fx,
				      r_ptr->cmove);
			delete_monster((int)c_ptr->cptr);
		      }
		  }
		else if (c_ptr->cptr == 1)
		  {
		    dam = (dam_hp/(distance(i, j, y, x)+1));
		    /* let's do at least one point of damage */
                    /* prevents randint(0) problem with poison_gas, also */
                    if (dam == 0)
                      dam = 1;
		    switch(typ)
		      {
		      case 1: light_dam(dam, ddesc); break;
		      case 2: poison_gas(dam, ddesc); break;
		      case 3: acid_dam(dam, ddesc); break;
		      case 4: cold_dam(dam, ddesc); break;
		      case 5: fire_dam(dam, ddesc); break;
		      }
		  }
	      }
	  }
  /* show the ball of gas */
  put_qio();

  for (i = (y - 2); i <= (y + 2); i++)
    for (j = (x - 2); j <= (x + 2); j++)
      if (in_bounds(i, j))
	if (panel_contains(i, j))
	  if (distance(y, x, i, j) <= max_dis)
	    {
	      c_ptr = &cave[i][j];
	      if (test_light(i, j))
		lite_spot(i, j);
	      else if (c_ptr->cptr == 1)
		lite_spot(i, j);
	      else if (c_ptr->cptr > 1)
		if (m_list[c_ptr->cptr].ml)
		  lite_spot(i, j);
		else
		  unlite_spot(i, j);
	      else
		unlite_spot(i, j);
	    }
}


/* Recharge a wand, staff, or rod.  Sometimes the item breaks. -RAK-*/
int recharge(num)
register int num;
{
  int item_val;
  int redraw;
  register int res;
  register treasure_type *i_ptr;

  res = FALSE;
  redraw = FALSE;
  if (get_item(&item_val, "Recharge which item?", &redraw, 0, inven_ctr-1))
    {
      i_ptr = &inventory[item_val];
      if ((i_ptr->tval == 55) || (i_ptr->tval == 60) || (i_ptr->tval == 65))
	/* recharge I = recharge(20) = 1/6 failure */
	/* recharge II = recharge(60) = 1/10 failure */
	if (randint((num + 40)/10) == 1)
	  {
	    res = TRUE;
	    msg_print("There is a bright flash of light...");
	    inven_destroy(item_val);
	  }
	else
	  {
	    res = TRUE;
	    num = (num/(i_ptr->level+2)) + 1;
	    i_ptr->p1 += 2 + randint(num);
	    if (index(i_ptr->name, '^') == 0)
	      insert_str(i_ptr->name, " (%P1", "^ (%P1");
	  }
    }
  if (redraw)
    {
      /* make sure player sees message before draw cave erases it */
      msg_print(" ");
      draw_cave();
    }
  return(res);
}


/* Increase or decrease a creatures hit points		-RAK-	*/
int hp_monster(dir, y, x, dam)
int dir, y, x, dam;
{
  register int i;
  int flag;
  int monster;
  cave_type *c_ptr;
  monster_type *m_ptr;
  creature_type *r_ptr;
  vtype out_val;
  vtype m_name;

  monster = FALSE;
  flag = FALSE;
  do
    {
      (void) move(dir, &y, &x);
      c_ptr = &cave[y][x];
      if (c_ptr->fopen)
	{
	  if (c_ptr->cptr > 1)
	    {
	      flag = TRUE;
	      m_ptr = &m_list[c_ptr->cptr];
	      r_ptr = &c_list[m_ptr->mptr];
	      monster_name (m_name, m_ptr, r_ptr);
	      monster = TRUE;
	      i = mon_take_hit((int)c_ptr->cptr, dam);
	      if (i >= 0)
		{
		  (void) sprintf(out_val, "%s dies in a fit of agony.",
			  m_name);
		  msg_print(out_val);
		}
	      else
		{
		  if (dam > 0)
		    {
		      (void) sprintf(out_val, "%s screams in agony.",
				     m_name);
		      msg_print(out_val);
		    }
		}
	    }
	}
      else
	flag = TRUE;
    }
  while (!flag);
  return(monster);
}


/* Drains life; note it must be living...		-RAK-	*/
int drain_life(dir, y, x)
int dir, y, x;
{
  register int i;
  int flag;
  int drain;
  register cave_type *c_ptr;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  vtype out_val;
  vtype m_name;

  drain = FALSE;
  flag = FALSE;
  do
    {
      (void) move(dir, &y, &x);
      c_ptr = &cave[y][x];
      if (c_ptr->fopen)
	{
	  if (c_ptr->cptr > 1)
	    {
	      flag = TRUE;
	      m_ptr = &m_list[c_ptr->cptr];
	      r_ptr = &c_list[m_ptr->mptr];
	      if ((r_ptr->cdefense & 0x0008) == 0)
		{
		  drain = TRUE;
		  monster_name (m_name, m_ptr, r_ptr);
		  i = mon_take_hit((int)c_ptr->cptr, 50);
		  if (i >= 0)
		    {
		      (void) sprintf(out_val, "%s dies in a fit of agony.",
			      m_name);
		      msg_print(out_val);
		    }
		  else
		    {
		      (void) sprintf(out_val, "%s screams in agony.",
			      m_name);
		      msg_print(out_val);
		    }
		}
	    }
	  else
	    flag = TRUE;
	}
    }
  while (!flag);
  return(drain);
}


/* Increase or decrease a creatures speed		-RAK-	*/
/* NOTE: cannot slow a winning creature (BALROG)                 */
int speed_monster(dir, y, x, spd)
int dir, y, x, spd;
{
  int speed;
  int flag;
  register cave_type *c_ptr;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  vtype out_val;
  vtype m_name;

  speed = FALSE;
  flag = FALSE;
  do
    {
      (void) move(dir, &y, &x);
      c_ptr = &cave[y][x];
      if (c_ptr->fopen)
	{
	  if (c_ptr->cptr > 1)
	    {
	      flag = TRUE;
	      m_ptr = &m_list[c_ptr->cptr];
	      r_ptr = &c_list[m_ptr->mptr];
	      monster_name (m_name, m_ptr, r_ptr);
	      if (spd > 0)
		{
		  m_ptr->cspeed += spd;
		  m_ptr->csleep = 0;
		  (void) sprintf (out_val, "%s starts moving faster.", m_name);
		  msg_print (out_val);
		  speed = TRUE;
		}
	      else if (randint(MAX_MONS_LEVEL) > r_ptr->level)
		{
		  m_ptr->cspeed += spd;
		  m_ptr->csleep = 0;
		  (void) sprintf (out_val, "%s starts moving slower.", m_name);
		  msg_print (out_val);
		  speed = TRUE;
		}
	      else
		{
		  (void) sprintf(out_val, "%s is unaffected.", m_name);
		  msg_print(out_val);
		}
	    }
	}
      else
	flag = TRUE;
    }
  while (!flag);
  return(speed);
}


/* Confuse a creature					-RAK-	*/
int confuse_monster(dir, y, x)
int dir, y, x;
{
  int flag;
  int confuse;
  register cave_type *c_ptr;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  vtype out_val;
  vtype m_name;

  confuse = FALSE;
  flag = FALSE;
  do
    {
      (void) move(dir, &y, &x);
      c_ptr = &cave[y][x];
      if (c_ptr->fopen)
	{
	  if (c_ptr->cptr > 1)
	    {
	      m_ptr = &m_list[c_ptr->cptr];
	      r_ptr = &c_list[m_ptr->mptr];
	      monster_name (m_name, m_ptr, r_ptr);
	      flag = TRUE;
	      if ((randint(MAX_MONS_LEVEL) < r_ptr->level) ||
		  (0x1000 & r_ptr->cdefense))
		{
		  (void) sprintf(out_val, "%s is unaffected.", m_name);
		  msg_print(out_val);
		}
	      else
		{
		  m_ptr->confused = TRUE;
		  confuse = TRUE;
		  m_ptr->csleep = 0;
		  (void) sprintf(out_val, "%s appears confused.", m_name);
		  msg_print(out_val);
		}
	    }
	}
      else
	flag = TRUE;
    }
  while (!flag);
  return(confuse);
}


/* Sleep a creature...					-RAK-	*/
int sleep_monster(dir, y, x)
int dir, y, x;
{
  int flag;
  int sleep;
  register cave_type *c_ptr;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  vtype out_val;
  vtype m_name;

  sleep = FALSE;
  flag = FALSE;
  do
    {
      (void) move(dir, &y, &x);
      c_ptr = &cave[y][x];
      if (c_ptr->fopen)
	{
	  if (c_ptr->cptr > 1)
	    {
	      m_ptr = &m_list[c_ptr->cptr];
	      r_ptr = &c_list[m_ptr->mptr];
	      flag = TRUE;
	      monster_name (m_name, m_ptr, r_ptr);
	      if ((randint(MAX_MONS_LEVEL) < r_ptr->level) ||
		  (0x1000 & r_ptr->cdefense))
		{
		  (void) sprintf(out_val, "%s is unaffected.", m_name);
		  msg_print(out_val);
		}
	      else
		{
		  m_ptr->csleep = 500;
		  sleep = TRUE;
		  (void) sprintf(out_val, "%s falls asleep.", m_name);
		  msg_print(out_val);
		}
	    }
	}
      else
	flag = TRUE;
    }
  while (!flag);
  return(sleep);
}


/* Turn stone to mud, delete wall....			-RAK-	*/
int wall_to_mud(dir, y, x)
int dir, y, x;
{
  int i;
  vtype out_val, tmp_str;
  register int flag;
  int wall;
  register cave_type *c_ptr;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  vtype m_name;

  wall = FALSE;
  flag = FALSE;
  do
    {
      (void) move(dir, &y, &x);
      c_ptr = &cave[y][x];
      if (in_bounds(y, x))
	{
	  if ((c_ptr->fval >= 10) && (c_ptr->fval <= 12))
	    {
	      flag = TRUE;
	      (void) twall(y, x, 1, 0);
	      if (test_light(y, x))
		{
		  msg_print("The wall turns into mud.");
		  wall = TRUE;
		}
	    }
	  else if ((c_ptr->tptr != 0) && (!c_ptr->fopen))
	    {
	      flag = TRUE;
	      if (panel_contains(y, x))
		if (test_light(y, x))
		  {
		    inventory[INVEN_MAX] = t_list[c_ptr->tptr];
		    objdes(tmp_str, INVEN_MAX, FALSE);
		    (void) sprintf(out_val, "The %s turns into mud.", tmp_str);
		    msg_print(out_val);
		    wall = TRUE;
		  }
	      (void) delete_object(y, x);
	    }
	  if (c_ptr->cptr > 1)
	    {
	      m_ptr = &m_list[c_ptr->cptr];
	      r_ptr = &c_list[m_ptr->mptr];
	      if (0x0200 & r_ptr->cdefense)
		{
		  monster_name (m_name, m_ptr, r_ptr);
		  i = mon_take_hit((int)c_ptr->cptr, 100);
		  flag = TRUE;
		  if (i >= 0)
		    {
		      (void) sprintf(out_val, "%s dies in a fit of agony.",
				     m_name);
		      msg_print(out_val);
		    }
		  else
		    {
		      (void) sprintf(out_val, "%s wails out in pain!", m_name);
		      msg_print(out_val);
		    }
		}
	    }
	}
      else
	flag = TRUE;
    }
  while (!flag);
  return(wall);
}


/* Destroy all traps and doors in a given direction	-RAK-	*/
int td_destroy2(dir, y, x)
int dir, y, x;
{
  register int destroy2;
  register cave_type *c_ptr;
  register treasure_type *t_ptr;

  destroy2 = FALSE;
  do
    {
      (void) move(dir, &y, &x);
      c_ptr = &cave[y][x];
      if (c_ptr->tptr != 0)
	{
	  t_ptr = &t_list[c_ptr->tptr];
	  if ((t_ptr->tval == 2) || (t_ptr->tval == 101) ||
	      (t_ptr->tval == 102) || (t_ptr->tval == 104) ||
	      (t_ptr->tval == 105) || (t_ptr->tval == 109))
	    {
	      if (delete_object(y, x))
		{
		  msg_print("There is a bright flash of light!");
		  c_ptr->fopen = TRUE;
		  destroy2 = TRUE;
		}
	    }
	}
    }
  while (cave[y][x].fopen);
  return(destroy2);
}


/* Polymorph a monster					-RAK-	*/
/* NOTE: cannot polymorph a winning creature (BALROG)            */
int poly_monster(dir, y, x)
int dir, y, x;
{
  int dist;
  int flag;
  int poly;
  register cave_type *c_ptr;
  register creature_type *r_ptr;
  register monster_type *m_ptr;
  vtype out_val;
  vtype m_name;

  poly = FALSE;
  flag = FALSE;
  dist = 0;
  do
    {
      (void) move(dir, &y, &x);
      dist++;
      if (dist <= OBJ_BOLT_RANGE)
	{
	  c_ptr = &cave[y][x];
	  if (c_ptr->fopen)
	    {
	      if (c_ptr->cptr > 1)
		{
		  m_ptr = &m_list[c_ptr->cptr];
		  r_ptr = &c_list[m_ptr->mptr];
		  if (randint(MAX_MONS_LEVEL) > r_ptr->level)
		    {
		      flag = TRUE;
		      delete_monster((int)c_ptr->cptr);
		      place_monster(y, x,
			  randint(m_level[MAX_MONS_LEVEL]) - 1 + m_level[0],
				    FALSE);
		      if (panel_contains(y, x))
			if (test_light(y, x))
			  poly = TRUE;
		    }
		  else
		    {
		      monster_name (m_name, m_ptr, r_ptr);
		      (void) sprintf(out_val, "%s is unaffected.", m_name);
		      msg_print(out_val);
		    }
		}
	    }
	}
      else
	flag = TRUE;
    }
  while (!flag);
  return(poly);
}


/* Create a wall...					-RAK-	*/
int build_wall(dir, y, x)
int dir, y, x;
{
  register int i;
  int build;
  register cave_type *c_ptr;

  build = FALSE;
  i = 0;
  (void) move(dir, &y, &x);
  while ((cave[y][x].fopen) && (i < 10))
    {
      c_ptr = &cave[y][x];
      if (c_ptr->tptr != 0)
	(void) delete_object(y, x);
      if (c_ptr->cptr > 1)
	/* what happens to this monster ? */
	(void) mon_take_hit((int)c_ptr->cptr, damroll("2d8"));
      c_ptr->fval  = rock_wall2.ftval;
      c_ptr->fopen = rock_wall2.ftopen;
      c_ptr->fm = FALSE;
      if (test_light(y, x))
	lite_spot(y, x);
      i++;
      build = TRUE;
      (void) move(dir, &y, &x);
    }
  return(build);
}


/* Replicate a creature					-RAK-	*/
int clone_monster(dir, y, x)
int dir, y, x;
{
  register int flag;
  register int clone;
  register cave_type *c_ptr;

  flag = FALSE;
  clone = FALSE;
  do
    {
      (void) move(dir, &y, &x);
      c_ptr = &cave[y][x];
      if (c_ptr->cptr > 1)
	{
	  multiply_monster(y, x, (int)m_list[c_ptr->cptr].mptr, FALSE);
	  if (panel_contains(y, x))
	    if (m_list[c_ptr->cptr].ml)
	      clone = TRUE;
	  flag = TRUE;
	}
    }
  while ((cave[y][x].fopen) && (!flag));
  return(clone);
}


/* Move the creature record to a new location		-RAK-	*/
teleport_away(monptr, dis)
int monptr, dis;
{
  register int yn, xn, ctr;
  register monster_type *m_ptr;

  m_ptr = &m_list[monptr];
  ctr = 0;
  do
    {
      do
	{
	  yn = m_ptr->fy + (randint(2*dis+1) - (dis + 1));
	  xn = m_ptr->fx + (randint(2*dis+1) - (dis + 1));
	}
      while (!in_bounds(yn, xn));
      ctr++;
      if (ctr > 9)
	{
	  ctr = 0;
	  dis += 5;
	}
    }
  while ((!cave[yn][xn].fopen) || (cave[yn][xn].cptr != 0));
  move_rec((int)m_ptr->fy, (int)m_ptr->fx, yn, xn);
  if (test_light((int)m_ptr->fy, (int)m_ptr->fx))
    lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
  m_ptr->fy = yn;
  m_ptr->fx = xn;
  m_ptr->ml = FALSE;
}


/* Teleport player to spell casting creature		-RAK-	*/
teleport_to(ny, nx)
int ny, nx;
{
  int dis, ctr, y, x;
  register int i, j;
  register cave_type *c_ptr;

  dis = 1;
  ctr = 0;
  do
    {
      y = ny + (randint(2*dis+1) - (dis + 1));
      x = nx + (randint(2*dis+1) - (dis + 1));
      ctr++;
      if (ctr > 9)
	{
	  ctr = 0;
	  dis++;
	}
    }
  while ((!cave[y][x].fopen) || (cave[y][x].cptr >= 2));
  move_rec(char_row, char_col, y, x);
  for (i = char_row-1; i <= char_row+1; i++)
    for (j = char_col-1; j <= char_col+1; j++)
      {
	c_ptr = &cave[i][j];
	c_ptr->tl = FALSE;
	if (!test_light(i, j))
	  unlite_spot(i, j);
      }
  if (test_light(char_row, char_col))
    lite_spot(char_row, char_col);
  char_row = y;
  char_col = x;
  move_char(5);
  /* light creatures */
  creatures(FALSE);
}


/* Teleport all creatures in a given direction away	-RAK-	*/
int teleport_monster(dir, y, x)
int dir, y, x;
{
  register int flag;
  register int teleport;
  register cave_type *c_ptr;

  flag = FALSE;
  teleport = FALSE;
  do
    {
      (void) move(dir, &y, &x);
      c_ptr = &cave[y][x];
      if (c_ptr->cptr > 1)
	{
	  teleport_away((int)c_ptr->cptr, MAX_SIGHT);
	  teleport = TRUE;
	}
    }
  while ((cave[y][x].fopen) && (!flag));
  return(teleport);
}


/* Delete all creatures within max_sight distance	-RAK-	*/
/* NOTE : Winning creatures cannot be genocided                  */
int mass_genocide()
{
  register int i, j;
  int genocide;
  register monster_type *m_ptr;
  register creature_type *r_ptr;

  genocide = FALSE;
  i = muptr;
  while (i > 0)
    {
      m_ptr = &m_list[i];
      r_ptr = &c_list[m_ptr->mptr];
      j = m_ptr->nptr;
      if (m_ptr->cdis <= MAX_SIGHT)
	if ((r_ptr->cmove & 0x80000000) == 0)
	  {
	    delete_monster(i);
	    genocide = TRUE;
	  }
      i = j;
    }
  return(genocide);
}


/* Delete all creatures of a given type from level.	-RAK-	*/
/* This does not keep creatures of type from appearing later.    */
/* NOTE : Winning creatures can not be genocided. */
int genocide()
{
  register int i, j;
  char typ;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  vtype out_val;

  i = muptr;
  if (get_com("What kind of creature shall be exterminated?", &typ))
    while (i > 0)
      {
	m_ptr = &m_list[i];
	r_ptr = &c_list[m_ptr->mptr];
	j = m_ptr->nptr;
	if (typ == c_list[m_ptr->mptr].cchar)
	  if ((r_ptr->cmove & 0x80000000) == 0)
	    delete_monster(i);
	  else
	    {
	      /* genocide is a powerful spell, so we will let the player
		 know the names of the creatures he did not destroy,
		 this message makes no sense otherwise */
	      (void) sprintf(out_val, "The %s is unaffected.", r_ptr->name);
	      msg_print(out_val);
	    }
	i = j;
      }
  return(TRUE);
}


/* Change speed of any creature player can see....	-RAK-	*/
/* NOTE: cannot slow a winning creature (BALROG)                 */
int speed_monsters(spd)
int spd;
{
  register int i, j;
  int speed;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  vtype out_val;
  vtype m_name;

  i = muptr;
  speed = FALSE;
  while (i > 0)
    {
      m_ptr = &m_list[i];
      j = m_ptr->nptr;
      if (m_ptr->ml)
	{
	  r_ptr = &c_list[m_ptr->mptr];
	  monster_name (m_name, m_ptr, r_ptr);
	  if (spd > 0)
	    {
	      m_ptr->cspeed += spd;
	      m_ptr->csleep = 0;
	      speed = TRUE;
	      (void) sprintf (out_val, "%s starts moving faster.", m_name);
	      msg_print (out_val);
	    }
	  else if (randint(MAX_MONS_LEVEL) > r_ptr->level)
	    {
	      m_ptr->cspeed += spd;
	      m_ptr->csleep = 0;
	      (void) sprintf (out_val, "%s starts moving slower.", m_name);
	      msg_print (out_val);
	      speed = TRUE;
	    }
	  else
	    {
	      (void) sprintf(out_val, "%s is unaffected.", m_name);
	      msg_print(out_val);
	    }
	}
      i = j;
    }
  return(speed);
}


/* Sleep any creature that player can see		-RAK-	*/
int sleep_monsters2()
{
  register int i, j;
  int sleep;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  vtype out_val;
  vtype m_name;

  i = muptr;
  sleep = FALSE;
  while (i > 0)
    {
      m_ptr = &m_list[i];
      r_ptr = &c_list[m_ptr->mptr];
      monster_name (m_name, m_ptr, r_ptr);
      j = m_ptr->nptr;
      if (m_ptr->ml)
	{
	  if ((randint(MAX_MONS_LEVEL) < r_ptr->level) ||
	      (0x1000 & r_ptr->cdefense))
	    {
	      (void) sprintf(out_val, "%s is unaffected.", m_name);
	      msg_print(out_val);
	    }
	  else
	    {
	      m_ptr->csleep = 500;
	      (void) sprintf(out_val, "%s falls asleep.", m_name);
	      msg_print(out_val);
	      sleep = TRUE;
	    }
	}
      i = j;
    }
  return(sleep);
}


/* Polymorph any creature that player can see... 	-RAK-	*/
/* NOTE: cannot polymorph a winning creature (BALROG)            */
int mass_poly()
{
  register int i, j;
  int y, x;
  int mass;
  register monster_type *m_ptr;
  register creature_type *r_ptr;

  i = muptr;
  mass = FALSE;
  while (i > 0)
    {
      m_ptr = &m_list[i];
      j = m_ptr->nptr;
      if (m_ptr->cdis < MAX_SIGHT)
	{
	  r_ptr = &c_list[m_ptr->mptr];
	  if ((r_ptr->cmove & 0x80000000) == 0)
	    {
	      y = m_ptr->fy;
	      x = m_ptr->fx;
	      delete_monster(i);
	      place_monster(y, x, randint(m_level[MAX_MONS_LEVEL]) - 1
			    + m_level[0], FALSE);
	      mass = TRUE;
	    }
	}
      i = j;
    }
  return(mass);
}


/* Display evil creatures on current panel		-RAK-	*/
int detect_evil()
{
  register int i;
  int flag;
  register monster_type *m_ptr;
  char temp_str[2];

  flag = FALSE;
  i = muptr;
  while (i > 0)
    {
      m_ptr = &m_list[i];
      if (panel_contains((int)m_ptr->fy, (int)m_ptr->fx))
	if (0x0004 & c_list[m_ptr->mptr].cdefense)
	  {
	    m_ptr->ml = TRUE;
	    temp_str[0] = c_list[m_ptr->mptr].cchar;
	    temp_str[1] = '\0';
	    print(temp_str, (int)m_ptr->fy, (int)m_ptr->fx);
	    flag = TRUE;
	  }
      i = m_list[i].nptr;
    }
  if (flag)
    {
      msg_print("You sense the presence of evil!");
      /* make sure player sees the message */
      msg_print(" ");
      msg_flag = FALSE;
    }
  return(flag);
}


/* Change players hit points in some manner		-RAK-	*/
int hp_player(num, kind)
int num;
char *kind;
{
  register int res;
  register struct misc *m_ptr;

  res = FALSE;
  m_ptr = &py.misc;
  if (num < 0)
    {
      take_hit(num, kind);
      if (m_ptr->chp < 0)
	msg_print("You feel your life slipping away!");
      res = TRUE;
    }
  else if (m_ptr->chp < m_ptr->mhp)
    {
      m_ptr->chp += (double)num;
      if (m_ptr->chp > m_ptr->mhp)
	m_ptr->chp = (double)m_ptr->mhp;
      prt_chp();
      switch(num/5)
	{
	case 0:
	  msg_print("You feel a little better.");
	  break;
	case 1: case 2:
	  msg_print("You feel better.");
	  break;
	case 3: case 4: case 5: case 6:
	  msg_print("You feel much better.");
	  break;
	default:
	  msg_print("You feel very good.");
	  break;
	}
      res = TRUE;
    }
  return(res);
}


/* Cure players confusion				-RAK-	*/
int cure_confusion()
{
  register int cure;
  register struct flags *f_ptr;

  cure = FALSE;
  f_ptr = &py.flags;
  if (f_ptr->confused > 1)
    {
      f_ptr->confused = 1;
      cure = TRUE;
    }
  return(cure);
}


/* Cure players blindness				-RAK-	*/
int cure_blindness()
{
  register int cure;
  register struct flags *f_ptr;

  cure = FALSE;
  f_ptr = &py.flags;
  if (f_ptr->blind > 1)
    {
      f_ptr->blind = 1;
      cure = TRUE;
    }
  return(cure);
}


/* Cure poisoning					-RAK-	*/
int cure_poison()
{
  register int cure;
  register struct flags *f_ptr;

  cure = FALSE;
  f_ptr = &py.flags;
  if (f_ptr->poisoned > 1)
    {
      f_ptr->poisoned = 1;
      cure = TRUE;
    }
  return(cure);
}


/* Cure the players fear 				-RAK-	*/
int remove_fear()
{
  register int remove;
  register struct flags *f_ptr;

  remove = FALSE;
  f_ptr = &py.flags;
  if (f_ptr->afraid > 1)
    {
      f_ptr->afraid = 1;
      remove = TRUE;
    }
  return(remove);
}


/* This is a fun one.  In a given block, pick some walls and	*/
/* turn them into open spots.  Pick some open spots and turn     */
/* them into walls.  An "Earthquake" effect...           -RAK-   */
int earthquake()
{
  register int i, j;
  register cave_type *c_ptr;

  for (i = char_row-8; i <= char_row+8; i++)
    for (j = char_col-8; j <= char_col+8; j++)
      if ((i != char_row) || (j != char_col))
	if (in_bounds(i, j))
	  if (randint(8) == 1)
	    {
	      c_ptr = &cave[i][j];
	      if (c_ptr->tptr != 0)
		(void) delete_object(i, j);
	      if (c_ptr->cptr > 1)
		/* what happens to this monster ? */
		(void) mon_take_hit((int)c_ptr->cptr, damroll("2d8"));
	      if ((c_ptr->fval >= 10) && (c_ptr->fval <= 12))
		{
		  if (next_to4(i, j, 1, 2, -1) > 0)
		    {
		      c_ptr->fval  = corr_floor2.ftval;
		      c_ptr->fopen = corr_floor2.ftopen;
		    }
		  else
		    {
		      c_ptr->fval  = corr_floor1.ftval;
		      c_ptr->fopen = corr_floor1.ftopen;
		    }
		  if (test_light(i, j))
		    unlite_spot(i, j);
		  c_ptr->pl = FALSE;
		  c_ptr->fm = FALSE;
		  if (c_ptr->tl)
		    lite_spot(i, j);
		}
	      else if (set_floor(c_ptr->fval))
		{
		  switch(randint(10))
		    {
		    case 1: case 2: case 3: case 4: case 5:
		      c_ptr->fval  = rock_wall3.ftval;
		      c_ptr->fopen = rock_wall3.ftopen;
		      break;
		    case 6: case 7: case 8:
		      c_ptr->fval  = rock_wall2.ftval;
		      c_ptr->fopen = rock_wall2.ftopen;
		      break;
		    case 9: case 10:
		      c_ptr->fval  = rock_wall1.ftval;
		      c_ptr->fopen = rock_wall1.ftopen;
		      break;
		    }
		  c_ptr->fm = FALSE;
		}
	      if (test_light(i, j))
		lite_spot(i, j);
	    }
  return(TRUE);
}


/* Evil creatures don't like this...                     -RAK-   */
int protect_evil()
{
  register struct flags *f_ptr;

  f_ptr = &py.flags;
  f_ptr->protevil += randint(25) + 3*py.misc.lev;
  return(TRUE);
}


/* Create some high quality mush for the player. 	-RAK-	*/
int create_food()
{
  register cave_type *c_ptr;

  c_ptr = &cave[char_row][char_col];
  if (c_ptr->tptr != 0)
    {
      /* take no action here, don't want to destroy object under player */
      msg_print ("There is already an object under you.");
      /* set reset_flag so that scroll/spell points won't be used */
      reset_flag = TRUE;
    }
  else
    {
      place_object(char_row, char_col);
      t_list[c_ptr->tptr] = mush;
    }
  return (TRUE);
}


/* Attempts to destroy a type of creature.  Success depends on	*/
/* the creatures level VS. the player's level            -RAK-   */
int dispell_creature(cflag, damage)
int cflag;
int damage;
{
  register int i, m_next;
  vtype out_val;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  register struct misc *p_ptr;
  int dispel;
  vtype m_name;

  i = muptr;
  dispel = FALSE;
  while (i > 0)
    {
      m_next = m_list[i].nptr;
      m_ptr = &m_list[i];
      if (m_ptr->ml)
	if (cflag & c_list[m_ptr->mptr].cdefense)
	  {
	    m_ptr->hp -= randint(damage);
	    m_ptr->csleep = 0;
	    r_ptr = &c_list[m_ptr->mptr];
	    monster_name (m_name, m_ptr, r_ptr);
	    if (m_ptr->hp < 0)
	      {
		(void) sprintf(out_val, "%s dissolves!", m_name);
		msg_print(out_val);
		monster_death((int)m_ptr->fy, (int)m_ptr->fx,
			      c_list[m_ptr->mptr].cmove);
		p_ptr = &py.misc;
		p_ptr->exp += ((r_ptr->mexp * ((float) r_ptr->level / (float) p_ptr->lev))
			       + 0.5);
		delete_monster(i);
	      }
	    else
	      {
		(void) sprintf(out_val, "%s shudders.", m_name);
		msg_print(out_val);
	      }
	    dispel = TRUE;
	  }
      i = m_next;
    }
  return(dispel);
}


/* Attempt to turn (confuse) undead creatures... 	-RAK-	*/
int turn_undead()
{
  register int i;
  int turn_und;
  register monster_type *m_ptr;
  register creature_type *r_ptr;
  vtype out_val;
  vtype m_name;

  i = muptr;
  turn_und = FALSE;
  while (i > 0)
    {
      m_ptr = &m_list[i];
      r_ptr = &c_list[m_ptr->mptr];
      if (panel_contains((int)m_ptr->fy, (int)m_ptr->fx))
	if (m_ptr->ml)
	  if (0x0008 & r_ptr->cdefense)
	    {
	      monster_name (m_name, m_ptr, r_ptr);
	      if (((py.misc.lev+1) > r_ptr->level) ||
		  (randint(5) == 1))
		{
		  (void) sprintf(out_val, "%s runs frantically!", m_name);
		  msg_print(out_val);
		  m_ptr->confused = TRUE;
		  turn_und = TRUE;
		}
	      else
		{
		  (void) sprintf(out_val, "%s is unaffected.", m_name);
		  msg_print(out_val);
		}
	    }
      i = m_list[i].nptr;
    }
  return(turn_und);
}


/* Leave a glyph of warding... Creatures will not pass over! -RAK-*/
int warding_glyph()
{
  int i;
  register cave_type *c_ptr;

  c_ptr = &cave[char_row][char_col];
  if (c_ptr->tptr == 0)
    {
      popt(&i);
      c_ptr->tptr = i;
      t_list[i] = scare_monster;
    }
  return(TRUE);
}


/* Lose a strength point.				-RAK-	*/
int lose_str()
{
  if (!py.flags.sustain_str)
    {
      py.stats.cstr = de_statp(py.stats.cstr);
      msg_print("You feel very sick.");
      prt_strength();
      /* adjust misc stats */
      py_bonuses(blank_treasure, 0);
    }
  else
    msg_print("You feel sick for a moment,  it passes.");
  return(TRUE);
}


/* Lose an intelligence point.				-RAK-	*/
int lose_int()
{
  if (!py.flags.sustain_int)
    {
      py.stats.cint = de_statp(py.stats.cint);
      msg_print("You become very dizzy.");
      prt_intelligence();
    }
  else
    msg_print("You become dizzy for a moment,  it passes.");
  return(TRUE);
}


/* Lose a wisdom point.					-RAK-	*/
int lose_wis()
{
  if (!py.flags.sustain_wis)
    {
      py.stats.cwis = de_statp(py.stats.cwis);
      msg_print("You feel very naive.");
      prt_wisdom();
    }
  else
    msg_print("You feel naive for a moment,  it passes.");
  return(TRUE);
}


/* Lose a dexterity point.				-RAK-	*/
int lose_dex()
{
  if (!py.flags.sustain_dex)
    {
      py.stats.cdex = de_statp(py.stats.cdex);
      msg_print("You feel very sore.");
      prt_dexterity();
      /* adjust misc stats */
      py_bonuses(blank_treasure, 0);
    }
  else
    msg_print("You feel sore for a moment,  it passes.");
  return(TRUE);
}


/* Lose a constitution point.				-RAK-	*/
int lose_con()
{
  if (!py.flags.sustain_con)
    {
      py.stats.ccon = de_statp(py.stats.ccon);
      msg_print("You feel very sick.");
      prt_constitution();
    }
  else
    msg_print("You feel sick for a moment,  it passes.");
  return(TRUE);
}


/* Lose a charisma point.				-RAK-	*/
int lose_chr()
{
  if (!py.flags.sustain_chr)
    {
      py.stats.cchr = de_statp(py.stats.cchr);
      msg_print("Your skin starts to itch.");
      prt_charisma();
    }
  else
    msg_print("Your skin starts to itch, but feels better now.");
  return(TRUE);
}


/* Lose experience					-RAK-	*/
lose_exp(amount)
int amount;
{
  register int i, j;
  int av_hp, lose_hp;
  int av_mn, lose_mn;
  register struct misc *m_ptr;
  register class_type *c_ptr;
  int num_known, adjust, num_allowed, num_lose;
  double avg_spells;

  m_ptr = &py.misc;
  if (amount > m_ptr->exp)
    m_ptr->exp = 0;
  else
    m_ptr->exp -= amount;
  i = 1;
  while ((player_exp[i-1]*m_ptr->expfact) <= m_ptr->exp)
    i++;
  j = m_ptr->lev - i;
  while (j > 0)
    {
      av_hp = (int)((double)m_ptr->mhp/(double)m_ptr->lev + 0.5);
      av_mn = (int)((double)m_ptr->mana/(double)m_ptr->lev + 0.5);
      m_ptr->lev--;
      j--;
      lose_hp = randint(av_hp*2-1);
      lose_mn = randint(av_mn*2-1);
      m_ptr->mhp  -= lose_hp;
      m_ptr->mana -= lose_mn;
      if (m_ptr->mhp  < 1)  m_ptr->mhp  = 1;
      if (m_ptr->mana < 0)  m_ptr->mana = 0;

      /* perhaps lose some spells, depending on current int/wis and level */
      c_ptr = &class[m_ptr->pclass];
      if ((c_ptr->mspell) || (c_ptr->pspell))
	{
	  /* count spells known */
	  num_known = 0;
	  for (i = 0; i < 31; i++)
	    if (magic_spell[m_ptr->pclass][i].learned)
	      num_known++;
	  
	  /* calculate number of spells allowed */
	  if (c_ptr->mspell)
	    adjust = int_adj();
	  else
	    adjust = wis_adj();
	  switch (adjust)
	    {
	    case 0: avg_spells = 0.0; break;
	    case 1: avg_spells = 1.0; break;
	    case 2: avg_spells = 1.0; break;
	    case 3: avg_spells = 1.0; break;
	    case 4: avg_spells = 1.5; break;
	    case 5: avg_spells = 1.5; break;
	    case 6: avg_spells = 2.0; break;
	    case 7: avg_spells = 2.5; break;
	    default: avg_spells = 1.0; break;
	    }
	  num_allowed = (int)(m_ptr->lev * avg_spells + 0.5);
	  num_lose = num_known - num_allowed;

	  /* forget spells until both:
	     number known is less than or equal to number allowed
	     and highest spell level is lower than or equal to player level */
	  i = 30;
	  while (((magic_spell[m_ptr->pclass][i].slevel > m_ptr->lev)
		  || (num_lose > 0))
		 && (i >= 0))
	    {
	      if (magic_spell[m_ptr->pclass][i].learned)
		{
		  magic_spell[m_ptr->pclass][i].learned = FALSE;
		  num_lose--;
		  if (c_ptr->mspell)
		    msg_print("You have forgotten a magic spell!");
		  else
		    msg_print("You have forgotten a prayer!");
		}
	      i--;
	    }
	}
    }
  if (m_ptr->chp > m_ptr->mhp)
    m_ptr->chp = (double)m_ptr->mhp;
  if (m_ptr->cmana > m_ptr->mana)
    m_ptr->cmana = (double)m_ptr->mana;
  (void) strcpy(m_ptr->title, player_title[m_ptr->pclass][m_ptr->lev-1]);
  prt_experience();
  prt_mhp();
  prt_chp();
  prt_cmana();
  prt_level();
  prt_title();
}


/* Slow Poison						-RAK-	*/
int slow_poison()
{
  register int slow;
  register struct flags *f_ptr;

  slow = FALSE;
  f_ptr = &py.flags;
  if (f_ptr->poisoned > 0)
    {
      f_ptr->poisoned = f_ptr->poisoned / 2;
      if (f_ptr->poisoned < 1)  f_ptr->poisoned = 1;
      slow = TRUE;
      msg_print("The effects of the poison has been reduced.");
    }
  return(slow);
}


/* Bless 						-RAK-	*/
int bless(amount)
int amount;
{
  py.flags.blessed += amount;
  return(TRUE);
}


/* Detect Invisible for period of time			-RAK-	*/
detect_inv2(amount)
int amount;
{
  py.flags.detect_inv += amount;
}


replace_spot(y, x, typ)
int y, x, typ;
{
  register cave_type *c_ptr;

  c_ptr = &cave[y][x];
  switch(typ)
    {
    case 1: case 2: case 3:
      c_ptr->fval  = corr_floor1.ftval;
      c_ptr->fopen = corr_floor1.ftopen;
      break;
    case 4: case 7: case 10:
      c_ptr->fval  = rock_wall1.ftval;
      c_ptr->fopen = rock_wall1.ftopen;
      break;
    case 5: case 8: case 11:
      c_ptr->fval  = rock_wall2.ftval;
      c_ptr->fopen = rock_wall2.ftopen;
      break;
    case 6: case 9: case 12:
      c_ptr->fval  = rock_wall3.ftval;
      c_ptr->fopen = rock_wall3.ftopen;
      break;
    }
  c_ptr->pl = FALSE;
  c_ptr->fm = FALSE;
  if (c_ptr->tptr != 0)
    (void) delete_object(y, x);
  if (c_ptr->cptr > 1)
    delete_monster((int)c_ptr->cptr);
}


/* The spell of destruction...				-RAK-	*/
/* NOTE : Winning creatures that are deleted will be considered  */
/*        as teleporting to another level.  This will NOT win the*/
/*        game...                                                */
int destroy_area(y, x)
register int y, x;
{
  register int i, j, k;

  if (dun_level > 0)
    {
      for (i = (y-15); i <= (y+15); i++)
	for (j = (x-15); j <= (x+15); j++)
	  if (in_bounds(i, j))
	    if (cave[i][j].fval != 15)
	      {
		k = distance(i, j, y, x);
		if (k < 13)
		  replace_spot(i, j, randint(6));
		else if (k < 16)
		  replace_spot(i, j, randint(9));
	      }
    }
  msg_print("There is a searing blast of light!");
  py.flags.blind += 10 + randint(10);
  return(TRUE);
}


/* Enchants a plus onto an item...			-RAK-	*/
int enchant(plusses)
worlint *plusses;
{
  register int chance;
  register int res;

  chance = 0;
  res = FALSE;
  if (*plusses > 0)
    switch(*plusses)
      {
      case 1:  chance = 040; break;
      case 2:  chance = 100; break;
      case 3:  chance = 200; break;
      case 4:  chance = 400; break;
      case 5:  chance = 600; break;
      case 6:  chance = 700; break;
      case 7:  chance = 800; break;
      case 8:  chance = 900; break;
      case 9:  chance = 950; break;
      default: chance = 995; break;
      }
  if (randint(1000) > chance)
    {
      *plusses += 1;
      res = TRUE;
    }
  return(res);
}


/* Removes curses from items in inventory		-RAK-	*/
int remove_curse()
{
  register int i;
  register int remove;
  register treasure_type *i_ptr;

  remove = FALSE;
  for (i = 22; i <= 31; i++)
    {
      i_ptr = &inventory[i];
      if (0x80000000 & i_ptr->flags)
	{
	  i_ptr->flags &= 0x7FFFFFFF;
	  py_bonuses(blank_treasure, 0);
	  remove = TRUE;
	}
    }
  return(remove);
}


/* Restores any drained experience			-RAK-	*/
int restore_level()
{
  register int restore;
  register struct misc *m_ptr;

  restore = FALSE;
  m_ptr = &py.misc;
  if (m_ptr->max_exp > m_ptr->exp)
    {
      restore = TRUE;
      msg_print("You feel your life energies returning...");
      m_ptr->exp = m_ptr->max_exp;
      prt_experience();
    }
  return(restore);
}