[comp.sources.games] v05i045: umoria2 - single player dungeon simulation

games@tekred.TEK.COM (07/29/88)

Submitted by: "James E. Wilson" <wilson@ji.berkeley.edu>
Comp.sources.games: Volume 5, Issue 45
Archive-name: umoria2/Part11



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 11 (of 18)."
# Contents:  creature.c save.c
# Wrapped by billr@saab on Wed Jul 13 11:16:29 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'creature.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'creature.c'\"
else
echo shar: Extracting \"'creature.c'\" \(35194 characters\)
sed "s/^X//" >'creature.c' <<'END_OF_FILE'
X#include <stdio.h>
X
X#include "constants.h"
X#include "config.h"
X#include "types.h"
X#include "externs.h"
X
X#ifdef USG
X#include <string.h>
X#else
X#include <strings.h>
X#endif
X
X#ifdef sun   /* correct SUN stupidity in the stdio.h file */
Xchar *sprintf();
X#endif
X
Xextern int search_flag;
Xextern int moria_flag;
X
X/* Updates screen when monsters move about		-RAK-	*/
Xupdate_mon(monptr)
Xint monptr;
X{
X  int flag;
X  char tmp_str[2];
X  register cave_type *c_ptr;
X  register monster_type *m_ptr;
X  register creature_type *r_ptr;
X
X  m_ptr = &m_list[monptr];
X  c_ptr = &cave[m_ptr->fy][m_ptr->fx];
X  flag = FALSE;
X  if (m_ptr->cdis <= MAX_SIGHT)
X    if (py.flags.blind < 1)
X      if (panel_contains((int)m_ptr->fy, (int)m_ptr->fx))
X	/* Wizard sight...       */
X	if (wizard2)
X	  flag = TRUE;
X        /* Normal sight...       */
X	else if (los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx))
X	  {
X	    r_ptr = &c_list[m_ptr->mptr];
X	    if ((c_ptr->pl) || (c_ptr->tl))
X	      {
X		if (py.flags.see_inv)
X		  flag = TRUE;
X		else if ((0x10000 & r_ptr->cmove) == 0)
X		  flag = TRUE;
X	      }
X	    /* Infra vision...       */
X	    else if (py.flags.see_infra > 0)
X	      if (m_ptr->cdis <= py.flags.see_infra)
X		if (0x2000 & r_ptr->cdefense)
X		  flag = TRUE;
X	  }
X  /* Light it up...        */
X  if (flag)
X    {
X      if (!m_ptr->ml)
X	{
X	  tmp_str[0] = c_list[m_ptr->mptr].cchar;
X	  tmp_str[1] = '\0';
X	  print(tmp_str, (int)m_ptr->fy, (int)m_ptr->fx);
X	  m_ptr->ml = TRUE;
X	  if (search_flag)
X	    search_off();
X	  if (py.flags.rest > 0)
X	    rest_off();
X	  flush();
X	  if (find_flag)
X	    {
X	      find_flag = FALSE;
X	      move_light (char_row, char_col, char_row, char_col);
X	    }
X	}
X    }
X  /* Turn it off...        */
X  else if (m_ptr->ml)
X    {
X      m_ptr->ml = FALSE;
X      if ((c_ptr->tl) || (c_ptr->pl))
X	lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
X      else
X	unlite_spot((int)m_ptr->fy, (int)m_ptr->fx);
X    }
X}
X
X
X/* Choose correct directions for monster movement	-RAK-	*/
Xget_moves(monptr, mm)
Xint monptr;
Xregister int *mm;
X{
X  int y, ay, x, ax, move_val;
X
X  y = m_list[monptr].fy - char_row;
X  x = m_list[monptr].fx - char_col;
X  if (y < 0)
X    {
X      move_val = 8;
X      ay = -y;
X    }
X  else
X    {
X      move_val = 0;
X      ay = y;
X    }
X  if (x > 0)
X    {
X      move_val += 4;
X      ax = x;
X    }
X  else
X    ax = -x;
X  if (ay > (ax*1.7321))
X    move_val += 2;
X  else if (ax > (ay*1.7321))
X    move_val++;
X  switch(move_val)
X    {
X    case 0:
X      mm[0] = 9;
X      if (ay > ax)
X	{
X	  mm[1] = 8;
X	  mm[2] = 6;
X	  mm[3] = 7;
X	  mm[4] = 3;
X	}
X      else
X	{
X	  mm[1] = 6;
X	  mm[2] = 8;
X	  mm[3] = 3;
X	  mm[4] = 7;
X	}
X      break;
X    case 1: case 9:
X      mm[0] = 6;
X      if (y < 0)
X	{
X	  mm[1] = 3;
X	  mm[2] = 9;
X	  mm[3] = 2;
X	  mm[4] = 8;
X	}
X      else
X	{
X	  mm[1] = 9;
X	  mm[2] = 3;
X	  mm[3] = 8;
X	  mm[4] = 2;
X	}
X      break;
X    case 2: case 6:
X      mm[0] = 8;
X      if (x < 0)
X	{
X	  mm[1] = 9;
X	  mm[2] = 7;
X	  mm[3] = 6;
X	  mm[4] = 4;
X	}
X      else
X	{
X	  mm[1] = 7;
X	  mm[2] = 9;
X	  mm[3] = 4;
X	  mm[4] = 6;
X	}
X      break;
X    case 4:
X      mm[0] = 7;
X      if (ay > ax)
X	{
X	  mm[1] = 8;
X	  mm[2] = 4;
X	  mm[3] = 9;
X	  mm[4] = 1;
X	}
X      else
X	{
X	  mm[1] = 4;
X	  mm[2] = 8;
X	  mm[3] = 1;
X	  mm[4] = 9;
X	}
X      break;
X    case 5: case 13:
X      mm[0] = 4;
X      if (y < 0)
X	{
X	  mm[1] = 1;
X	  mm[2] = 7;
X	  mm[3] = 8;
X	  mm[4] = 2;
X	}
X      else
X	{
X	  mm[1] = 7;
X	  mm[2] = 1;
X	  mm[3] = 2;
X	  mm[4] = 8;
X	}
X      break;
X    case 8:
X      mm[0] = 3;
X      if (ay > ax)
X	{
X	  mm[1] = 2;
X	  mm[2] = 6;
X	  mm[3] = 1;
X	  mm[4] = 9;
X	}
X      else
X	{
X	  mm[1] = 6;
X	  mm[2] = 2;
X	  mm[3] = 9;
X	  mm[4] = 1;
X	}
X      break;
X    case 10: case 14:
X      mm[0] = 2;
X      if (x < 0)
X	{
X	  mm[1] = 1;
X	  mm[2] = 3;
X	  mm[3] = 4;
X	  mm[4] = 6;
X	}
X      else
X	{
X	  mm[1] = 3;
X	  mm[2] = 1;
X	  mm[3] = 6;
X	  mm[4] = 4;
X	}
X      break;
X    case 12:
X      mm[0] = 1;
X      if (ay > ax)
X	{
X	  mm[1] = 2;
X	  mm[2] = 4;
X	  mm[3] = 3;
X	  mm[4] = 7;
X	}
X      else
X	{
X	  mm[1] = 4;
X	  mm[2] = 2;
X	  mm[3] = 7;
X	  mm[4] = 3;
X	}
X      break;
X    }
X}
X
X
X/* Make an attack on the player (chuckle...)		-RAK-	*/
Xmake_attack(monptr)
Xint monptr;
X{
X  int xpos, attype, adesc, dam;
X  int i, j, l;
X  vtype attstr, attx;
X  vtype cdesc, ddesc, tmp_str;
X  dtype damstr;
X  int flag;
X  register creature_type *c_ptr;
X  monster_type *m_ptr;
X  register struct misc *p_ptr;
X  register struct flags *f_ptr;
X  register treasure_type *i_ptr;
X  char *string;
X
X  m_ptr = &m_list[monptr];
X  c_ptr = &c_list[m_ptr->mptr];
X  (void) strcpy(attstr, c_ptr->damage);
X  if ((0x10000 & c_ptr->cmove) && (!py.flags.see_inv))
X    (void) strcpy(cdesc, "It ");
X  else if (py.flags.blind > 0)
X    (void) strcpy(cdesc, "It ");
X  else if (!m_ptr->ml)
X    (void) strcpy(cdesc, "It ");
X  else
X    (void) sprintf(cdesc, "The %s ", c_ptr->name);
X  /* For "DIED_FROM" string        */
X  if (0x80000000 & c_ptr->cmove)
X    (void) sprintf(ddesc, "The %s", c_ptr->name);
X  else
X    (void) sprintf(ddesc, "& %s", c_ptr->name);
X  (void) strcpy(inventory[INVEN_MAX].name, ddesc);
X  inventory[INVEN_MAX].number = 1;
X  objdes(ddesc, INVEN_MAX, TRUE);
X  /* End DIED_FROM                 */
X
X  while (strlen(attstr) > 0)
X    {
X      string = index(attstr, '|');
X      if (string)
X	xpos = strlen(attstr) - strlen(string);
X      else
X	xpos = -1;
X      if (xpos >= 0)
X	{
X	  (void) strncpy(attx, attstr, xpos);
X	  attx[xpos] = '\0';
X	  (void) strcpy(attstr, &attstr[xpos+1]);
X	}
X      else
X	{
X	  (void) strcpy(attx, attstr);
X	  attstr[0] = '\0';
X	}
X      (void) sscanf(attx, "%d %d %s", &attype, &adesc, damstr);
X      flag = FALSE;
X      if (py.flags.protevil > 0)
X	if (c_ptr->cdefense & 0x0004)
X	  if ((py.misc.lev + 1) > c_ptr->level)
X	    {
X	      attype = 99;
X	      adesc = 99;
X	    }
X      p_ptr = &py.misc;
X      switch(attype)
X	{
X	case 1:       /*Normal attack  */
X	  if (test_hit(60, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 2:       /*Poison Strength*/
X	  if (test_hit(-3, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 3:       /*Confusion attack*/
X	  if (test_hit(10, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 4:       /*Fear attack    */
X	  if (test_hit(10, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 5:       /*Fire attack    */
X	  if (test_hit(10, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 6:       /*Acid attack    */
X	  if (test_hit(0, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 7:       /*Cold attack    */
X	  if (test_hit(10, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 8:       /*Lightning attack*/
X	  if (test_hit(10, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 9:       /*Corrosion attack*/
X	  if (test_hit(0, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 10:      /*Blindness attack*/
X	  if (test_hit(2, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 11:      /*Paralysis attack*/
X	  if (test_hit(2, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 12:      /*Steal Money    */
X	  if (test_hit(5, (int)c_ptr->level, 0, (int)py.misc.lev))
X	    if (py.misc.au > 0)
X	      flag = TRUE;
X	  break;
X	case 13:      /*Steal Object   */
X	  if (test_hit(2, (int)c_ptr->level, 0, (int)py.misc.lev))
X	    if (inven_ctr > 0)
X	      flag = TRUE;
X	  break;
X	case 14:      /*Poison         */
X	  if (test_hit(5, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 15:      /*Lose dexterity*/
X	  if (test_hit(0, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 16:      /*Lose constitution*/
X	  if (test_hit(0, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 17:      /*Lose intelligence*/
X	  if (test_hit(2, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 18:      /*Lose wisdom*/
X	  if (test_hit(0, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 19:      /*Lose experience*/
X	  if (test_hit(5, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 20:      /*Aggravate monsters*/
X	  flag = TRUE;
X	  break;
X	case 21:      /*Disenchant        */
X	  if (test_hit(20, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 22:      /*Eat food          */
X	  if (test_hit(5, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 23:      /*Eat light         */
X	  if (test_hit(5, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 24:      /*Eat charges       */
X	  if (test_hit(15, (int)c_ptr->level, 0, p_ptr->pac+p_ptr->ptoac))
X	    flag = TRUE;
X	  break;
X	case 99:
X	  flag = TRUE;
X	  break;
X	default:
X	  break;
X	}
X      if (flag)
X	{
X	  /* can not strcat to cdesc because the creature may have
X	     multiple attacks */
X	  (void) strcpy(tmp_str, cdesc);
X	  switch(adesc)
X	    {
X	    case 1: msg_print(strcat(tmp_str, "hits you.")); break;
X	    case 2: msg_print(strcat(tmp_str, "bites you.")); break;
X	    case 3: msg_print(strcat(tmp_str, "claws you.")); break;
X	    case 4: msg_print(strcat(tmp_str, "stings you.")); break;
X	    case 5: msg_print(strcat(tmp_str, "touches you.")); break;
X	    case 6: msg_print(strcat(tmp_str, "kicks you.")); break;
X	    case 7: msg_print(strcat(tmp_str, "gazes at you.")); break;
X	    case 8: msg_print(strcat(tmp_str, "breathes on you.")); break;
X	    case 9: msg_print(strcat(tmp_str, "spits on you.")); break;
X	    case 10: msg_print(strcat(tmp_str,"makes a horrible wail."));break;
X	    case 11: msg_print(strcat(tmp_str, "embraces you.")); break;
X	    case 12: msg_print(strcat(tmp_str, "crawls on you.")); break;
X	    case 13:
X	      msg_print(strcat(tmp_str, "releases a cloud of spores.")); break;
X	    case 14: msg_print(strcat(tmp_str, "begs you for money.")); break;
X	    case 15: msg_print("You've been slimed!"); break;
X	    case 16: msg_print(strcat(tmp_str, "crushes you.")); break;
X	    case 17: msg_print(strcat(tmp_str, "tramples you.")); break;
X	    case 18: msg_print(strcat(tmp_str, "drools on you.")); break;
X	    case 19:
X	      switch(randint(9))
X		{
X		case 1: msg_print(strcat(tmp_str, "insults you!")); break;
X		case 2:
X		  msg_print(strcat(tmp_str, "insults your mother!")); break;
X		case 3:
X		  msg_print(strcat(tmp_str, "gives you the finger!")); break;
X		case 4: msg_print(strcat(tmp_str, "humiliates you!")); break;
X		case 5: msg_print(strcat(tmp_str, "wets on your leg!")); break;
X		case 6: msg_print(strcat(tmp_str, "defiles you!")); break;
X		case 7: msg_print(strcat(tmp_str, "dances around you!"));break;
X		case 8:
X		  msg_print(strcat(tmp_str, "makes obscene gestures!")); break;
X		case 9: msg_print(strcat(tmp_str, "moons you!!!")); break;
X		}
X	      break;
X	    case 99: msg_print(strcat(tmp_str, "is repelled.")); break;
X	    default: break;
X	    }
X	  switch(attype)
X	    {
X	    case 1:    /*Normal attack  */
X	      dam = damroll(damstr);
X	      dam -= (int)((((p_ptr->pac+p_ptr->ptoac)/200.0)*dam)+.5);
X	      take_hit(dam, ddesc);
X	      prt_chp();
X	      break;
X	    case 2:    /*Poison Strength*/
X	      take_hit(damroll(damstr), ddesc);
X	      if (py.flags.sustain_str)
X		msg_print("You feel weaker for a moment,  it passes.");
X	      else if (randint(2) == 1)
X		{
X		  msg_print("You feel weaker.");
X		  py.stats.cstr = de_statp(py.stats.cstr);
X		  prt_strength();
X		  /* adjust misc stats */
X		  py_bonuses(blank_treasure, 0);
X		}
X	      prt_chp();
X	      break;
X	    case 3:    /*Confusion attack*/
X	      f_ptr = &py.flags;
X	      take_hit(damroll(damstr), ddesc);
X	      if (randint(2) == 1)
X		{
X		  if (f_ptr->confused < 1)
X		    {
X		      msg_print("You feel confused.");
X		      f_ptr->confused += randint((int)c_ptr->level);
X		    }
X		  f_ptr->confused += 3;
X		}
X	      prt_chp();
X	      break;
X	    case 4:    /*Fear attack    */
X	      f_ptr = &py.flags;
X	      take_hit(damroll(damstr), ddesc);
X	      if (player_saves(wis_adj()))
X		msg_print("You resist the effects!");
X	      else if (f_ptr->afraid < 1)
X		{
X		  msg_print("You are suddenly afraid!");
X		  f_ptr->afraid += 3 + randint((int)c_ptr->level);
X		}
X	      else
X		f_ptr->afraid += 3;
X	      prt_chp();
X	      break;
X	    case 5:    /*Fire attack    */
X	      msg_print("You are enveloped in flames!");
X	      fire_dam(damroll(damstr), ddesc);
X	      break;
X	    case 6:    /*Acid attack    */
X	      msg_print("You are covered in acid!");
X	      acid_dam(damroll(damstr), ddesc);
X	      break;
X	    case 7:    /*Cold attack    */
X	      msg_print("You are covered with frost!");
X	      cold_dam(damroll(damstr), ddesc);
X	      break;
X	    case 8:    /*Lightning attack*/
X	      msg_print("Lightning strikes you!");
X	      light_dam(damroll(damstr), ddesc);
X	      break;
X	    case 9:    /*Corrosion attack*/
X	      msg_print("A stinging red gas swirls about you.");
X	      corrode_gas(ddesc);
X	      take_hit(damroll(damstr), ddesc);
X	      prt_chp();
X	      break;
X	    case 10:    /*Blindness attack*/
X	      f_ptr = &py.flags;
X	      take_hit(damroll(damstr), ddesc);
X	      if (f_ptr->blind < 1)
X		{
X		  f_ptr->blind += 10 + randint((int)c_ptr->level);
X		  msg_print("Your eyes begin to sting.");
X		}
X	      f_ptr->blind += 5;
X	      prt_chp();
X	      break;
X	    case 11:    /*Paralysis attack*/
X		f_ptr = &py.flags;
X	      take_hit(damroll(damstr), ddesc);
X	      if (player_saves(con_adj()))
X		msg_print("You resist the effects!");
X	      else if (f_ptr->paralysis < 1)
X		{
X		  if (f_ptr->free_act)
X		    msg_print("You are unaffected.");
X		  else
X		    {
X		      f_ptr->paralysis = randint((int)c_ptr->level) + 3;
X		      msg_print("You are paralyzed.");
X		    }
X		}
X	      prt_chp();
X	      break;
X	    case 12:    /*Steal Money     */
X	      if ((randint(124) < py.stats.cdex) && (py.flags.paralysis < 1))
X		msg_print("You quickly protect your money pouch!");
X	      else
X		{
X		  i = (p_ptr->au/10) + randint(25);
X		  if (i > p_ptr->au)
X		    p_ptr->au = 0;
X		  else
X		    p_ptr->au -= i;
X		  msg_print("Your purse feels lighter.");
X		  prt_gold();
X		}
X	      if (randint(2) == 1)
X		{
X		  msg_print("There is a puff of smoke!");
X		  teleport_away(monptr, MAX_SIGHT);
X		}
X	      break;
X	    case 13:    /*Steal Object   */
X	      if ((randint(124) < py.stats.cdex) && (py.flags.paralysis < 1))
X		msg_print("You grab hold of your backpack!");
X	      else
X		{
X		  i = randint(inven_ctr) - 1;
X		  inven_destroy(i);
X		  msg_print("Your backpack feels lighter.");
X		}
X	      if (randint(2) == 1)
X		{
X		  msg_print("There is a puff of smoke!");
X		  teleport_away(monptr, MAX_SIGHT);
X		}
X	      break;
X	    case 14:    /*Poison         */
X	      f_ptr = &py.flags;
X	      take_hit(damroll(damstr), ddesc);
X	      prt_chp();
X	      msg_print("You feel very sick.");
X	      f_ptr->poisoned += randint((int)c_ptr->level)+5;
X	      break;
X	    case 15:    /*Lose dexterity */
X	      f_ptr = &py.flags;
X	      take_hit(damroll(damstr), ddesc);
X	      if (f_ptr->sustain_dex)
X		msg_print("You feel clumsy for a moment,  it passes.");
X	      else
X		{
X		  msg_print("You feel more clumsy.");
X		  py.stats.cdex = de_statp(py.stats.cdex);
X		  prt_dexterity();
X		  /* adjust misc stats */
X		  py_bonuses(blank_treasure, 0);
X		}
X	      prt_chp();
X	      break;
X	    case 16:    /*Lose constitution */
X	      f_ptr = &py.flags;
X	      take_hit(damroll(damstr), ddesc);
X	      if (f_ptr->sustain_con)
X		msg_print("Your body resists the effects of the disease.");
X	      else
X		{
X		  msg_print("Your health is damaged!");
X		  py.stats.ccon = de_statp(py.stats.ccon);
X		  prt_constitution();
X		}
X	      prt_chp();
X	      break;
X	    case 17:    /*Lose intelligence */
X	      f_ptr = &py.flags;
X	      take_hit(damroll(damstr), ddesc);
X	      if (f_ptr->sustain_int)
X		{
X		  msg_print("You feel your memories fading...");
X		  msg_print("Your memories are suddenly restored!");
X		}
X	      else
X		{
X		  msg_print("You feel your memories fading...");
X		  py.stats.cint = de_statp(py.stats.cint);
X		  prt_intelligence();
X		}
X	      prt_chp();
X	      break;
X	    case 18:    /*Lose wisdom      */
X	      f_ptr = &py.flags;
X	      take_hit(damroll(damstr), ddesc);
X	      if (f_ptr->sustain_wis)
X		msg_print("Your wisdom is sustained.");
X	      else
X		{
X		  msg_print("Your wisdom is drained.");
X		  py.stats.cwis = de_statp(py.stats.cwis);
X		  prt_wisdom();
X		}
X	      prt_chp();
X	      break;
X	    case 19:    /*Lose experience  */
X	      msg_print("You feel your life draining away!");
X	      i = damroll(damstr) + (py.misc.exp / 100)*MON_DRAIN_LIFE;
X	      lose_exp(i);
X	      break;
X	    case 20:    /*Aggravate monster*/
X	      (void) aggravate_monster(5);
X	      break;
X	    case 21:    /*Disenchant       */
X	      flag = FALSE;
X	      switch(randint(7))
X		{
X		case 1: i = INVEN_WIELD; break;
X		case 2: i = INVEN_BODY;  break;
X		case 3: i = INVEN_ARM;   break;
X		case 4: i = INVEN_OUTER; break;
X		case 5: i = INVEN_HANDS; break;
X		case 6: i = INVEN_HEAD;  break;
X		case 7: i = INVEN_FEET;  break;
X		}
X	      i_ptr = &inventory[i];
X	      if (i_ptr->tohit > 0)
X		{
X		  i_ptr->tohit -= randint(2);
X		  flag = TRUE;
X		}
X	      if (i_ptr->todam > 0)
X		{
X		  i_ptr->todam -= randint(2);
X		  flag = TRUE;
X		}
X	      if (i_ptr->toac > 0)
X		{
X		  i_ptr->toac  -= randint(2);
X		  flag = TRUE;
X		}
X	      if (flag)
X		{
X		  msg_print("There is a static feeling in the air...");
X		  py_bonuses(blank_treasure, 1);
X		}
X	      break;
X	    case 22:    /*Eat food         */
X	      if (find_range(80, -1, &i, &j))
X		inven_destroy(i);
X	      break;
X	    case 23:    /*Eat light        */
X	      i_ptr = &inventory[INVEN_LIGHT];
X	      if (i_ptr->p1 > 0)
X		{
X		  i_ptr->p1 -= (250 + randint(250));
X		  if (i_ptr->p1 < 1)  i_ptr->p1 = 1;
X		  msg_print("Your light dims...");
X		}
X	      break;
X	    case 24:    /*Eat charges     */
X	      i = randint(inven_ctr) - 1;
X	      l = c_ptr->level;
X	      i_ptr = &inventory[i];
X	      if ((i_ptr->tval == 55) || (i_ptr->tval == 60) ||
X		  (i_ptr->tval == 65))
X		if (i_ptr->p1 > 0)
X		  {
X		    m_ptr->hp += l*i_ptr->p1;
X		    i_ptr->p1 = 0;
X		    msg_print("Energy drains from your pack!");
X		  }
X	      break;
X	    case 99:  break;
X	    default: break;
X	    }
X	}
X      else
X	switch(adesc)
X	  {
X	  case 1: case 2: case 3: case 6:
X	    (void) strcpy(tmp_str, cdesc);
X	    msg_print(strcat(tmp_str, "misses you."));
X	    break;
X	  default: break;
X	  }
X    }
X}
X
X
X/* Make the move if possible, five choices		-RAK-	*/
Xint make_move(monptr, mm)
Xint monptr;
Xint *mm;
X{
X  int i, j, newy, newx;
X  unsigned int movebits;
X  int flag, tflag;
X  int res;
X  register cave_type *c_ptr;
X  register monster_type *m_ptr;
X  register treasure_type *t_ptr;
X  register creature_type *r_ptr;
X  char tmp_str[80];
X  vtype m_name;
X
X  i = 0;
X  flag = FALSE;
X  res = FALSE;
X  movebits = c_list[m_list[monptr].mptr].cmove;
X  do
X    {
X      /* Get new position               */
X      newy = m_list[monptr].fy;
X      newx = m_list[monptr].fx;
X      (void) move(mm[i], &newy, &newx);
X      c_ptr = &cave[newy][newx];
X      if (c_ptr->fval != 15)
X	{
X	  tflag = FALSE;
X	  /* Floor is open?                */
X	  if (c_ptr->fopen)
X	    tflag = TRUE;
X	      /* Creature moves through walls? */
X	  else if (movebits & 0x40000)
X	    tflag = TRUE;
X	      /* Creature can open doors?      */
X	  else if (c_ptr->tptr != 0)
X	    {
X	      t_ptr = &t_list[c_ptr->tptr];
X	      m_ptr = &m_list[monptr];
X	      if (movebits & 0x20000)
X		{     /* Creature can open doors...                    */
X		  switch(t_ptr->tval)
X		    {
X		    case 105:    /* Closed doors...       */
X		      if (t_ptr->p1 == 0)               /* Closed doors  */
X			{
X			  tflag = TRUE;
X			  if (los(char_row, char_col, newy, newx))
X			    {
X			      t_list[c_ptr->tptr] = door_list[0];
X			      c_ptr->fopen = TRUE;
X			      lite_spot(newy, newx);
X			      tflag = FALSE;
X			    }
X			}
X		      else if (t_ptr->p1 > 0)          /* Locked doors  */
X			{
X			  if (randint(100-t_ptr->level) < 5)
X			    t_ptr->p1 = 0;
X			}
X		      else if (t_ptr->p1 < 0)          /* Stuck doors   */
X			{
X			  if (randint(m_ptr->hp+1) > (10+abs(t_ptr->p1)))
X			    t_ptr->p1 = 0;
X			}
X		      break;
X		    case 109:    /* Secret doors...       */
X		      tflag = TRUE;
X		      if (los(char_row, char_col, newy, newx))
X			{
X			  t_list[c_ptr->tptr] = door_list[0];
X			  c_ptr->fopen = TRUE;
X			  lite_spot(newy, newx);
X			  tflag = FALSE;
X			}
X		      break;
X		    default: break;
X		    }
X		}
X	      else
X		{     /* Creature can not open doors, must bash them   */
X		  switch(t_ptr->tval)
X		    {
X		    case 105:    /* Closed doors...       */
X		      j = abs(t_ptr->p1) + 20;
X		      if (randint(m_ptr->hp+1) > j)
X			{
X			  tflag = TRUE;
X			  if (los(char_row, char_col, newy, newx))
X			    {
X			      t_list[c_ptr->tptr] = door_list[0];
X			      t_list[c_ptr->tptr].p1 = randint(2) - 1;
X			      c_ptr->fopen = TRUE;
X			      lite_spot(newy, newx);
X			      tflag = FALSE;
X			    }
X			}
X		      break;
X		    case 109:        /* Secret doors...       */
X		      break;
X		    default:
X		      break;
X		    }
X		}
X	    }
X	  /* Glyph of warding present?     */
X	  if (tflag)              /* Scare Monster trap    */
X	    if (c_ptr->tptr != 0)
X	      if (t_list[c_ptr->tptr].tval == 102)
X		if (t_list[c_ptr->tptr].subval == 99)
X		  {
X		    if (randint(OBJ_RUNE_PROT) <
X			c_list[m_list[monptr].mptr].level)
X		      {
X			if ((newy==char_row) && (newx==char_col))
X			  msg_print("The rune of protection is broken!");
X			(void) delete_object(newy, newx);
X		      }
X		    else
X		      tflag = FALSE;
X		  }
X	  /* Creature has attempted to move on player?     */
X	  if (tflag)
X	    if (c_ptr->cptr == 1)
X	      {
X		if (!m_list[monptr].ml)
X		  update_mon(monptr);
X		if (search_flag)  search_off();
X		if (py.flags.rest > 0)  rest_off();
X		if (find_flag)
X		  {
X		    find_flag = FALSE;
X		    move_light (char_row, char_col, char_row, char_col);
X		  }
X		flush();
X		make_attack(monptr);
X		/* Player has read a Confuse Monster?    */
X		/* Monster gets a saving throw...        */
X		if (py.flags.confuse_monster)
X		  {
X		    m_ptr = &m_list[monptr];
X		    r_ptr = &c_list[m_ptr->mptr];
X		    msg_print("Your hands stop glowing.");
X		    py.flags.confuse_monster = FALSE;
X
X		    /* Does the player know what he's fighting?      */
X		    if ((0x10000 & r_ptr->cmove) && (!py.flags.see_inv))
X		      (void) strcpy(m_name, "It");
X		    else if (py.flags.blind > 0)
X		      (void) strcpy(m_name, "It");
X		    else if (!m_ptr->ml)
X		      (void) strcpy(m_name, "It");
X		    else
X		      (void) sprintf(m_name, "The %s", r_ptr->name);
X		    if ((randint(MAX_MONS_LEVEL) < r_ptr->level) ||
X			(0x1000 & r_ptr->cdefense))
X		      {
X			(void) sprintf(tmp_str, "%s is unaffected.",
X				m_name);
X			msg_print(tmp_str);
X		      }
X		    else
X		      {
X			(void) sprintf(tmp_str, "%s appears confused.",
X				       m_name);
X			msg_print(tmp_str);
X			m_ptr->confused = TRUE;
X		      }
X		  }
X		tflag = FALSE;
X		flag  = TRUE;
X	      }
X	  /* Creature is attempting to move on other creature?     */
X	    else if ((c_ptr->cptr > 1) &&
X		     ((newy != m_list[monptr].fy) ||
X		      (newx != m_list[monptr].fx)))
X	      {
X		/* Creature eats other creatures?        */
X		if (movebits & 0x80000)
X		  delete_monster((int)c_ptr->cptr);
X		else
X		  tflag = FALSE;
X	      }
X	  /* Creature has been allowed move...     */
X	  if (tflag)
X	    {
X	      m_ptr = &m_list[monptr];
X	      /* Pick up or eat an object              */
X	      if (movebits & 0x100000)
X		{
X		  c_ptr = &cave[newy][newx];
X
X		  if (c_ptr->tptr != 0)
X		    if (t_list[c_ptr->tptr].tval < 100)
X		      (void) delete_object(newy, newx);
X		}
X	      /* Move creature record                  */
X	      move_rec((int)m_ptr->fy, (int)m_ptr->fx, newy, newx);
X	      m_ptr->fy = newy;
X	      m_ptr->fx = newx;
X	      flag = TRUE;
X	      res = TRUE;
X	    }
X	}
X      i++;
X      /* Up to 5 attempts at moving,   give up...   */
X    }
X  while ((!flag) && (i < 5));
X  return(res);
X}
X
X
X/* Creatures can cast spells too.  (Dragon Breath)	-RAK-	*/
X/* cast_spell = true if creature changes position       */
X/* took_turn  = true if creature casts a spell          */
Xint mon_cast_spell(monptr, took_turn)
Xint monptr;
Xint *took_turn;
X{
X  unsigned int i;
X  int y, x;
X  register int k;
X  int chance, thrown_spell;
X  double r1;
X  int spell_choice[30];
X  vtype cdesc, ddesc, outval;
X  int flag;
X  register monster_type *m_ptr;
X  register creature_type *r_ptr;
X  int cast;
X
X  m_ptr = &m_list[monptr];
X  r_ptr = &c_list[m_ptr->mptr];
X  chance = (int)((r_ptr->spells & 0x0000000F));
X  /* 1 in x chance of casting spell                */
X  if (randint(chance) != 1)
X    {
X      cast = FALSE;
X      *took_turn  = FALSE;
X    }
X  /* Must be within certain range                  */
X  else if (m_ptr->cdis > MAX_SPELL_DIS)
X    {
X      cast = FALSE;
X      *took_turn  = FALSE;
X    }
X  /* Must have unobstructed Line-Of-Sight          */
X  else if (!los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx))
X    {
X      cast = FALSE;
X      *took_turn  = FALSE;
X    }
X  else  /* Creature is going to cast a spell     */
X    {
X      *took_turn  = TRUE;
X      cast = TRUE;
X      /* Describe the attack                           */
X      flag = TRUE;
X      if (!m_ptr->ml)
X	flag = FALSE;
X      else if ((0x10000 & c_list[m_ptr->mptr].cmove) &&
X	       (!py.flags.see_inv))
X	flag = FALSE;
X      else if (py.flags.blind > 0)
X	flag = FALSE;
X      if (flag)
X	(void) sprintf(cdesc, "The %s ", r_ptr->name);
X      else
X	(void) strcpy(cdesc, "It ");
X      /* For "DIED_FROM" string  */
X      if (0x80000000 & r_ptr->cmove)
X	(void) sprintf(ddesc, "The %s", r_ptr->name);
X      else
X	(void) sprintf(ddesc, "& %s", r_ptr->name);
X      (void) strcpy(inventory[INVEN_MAX].name, ddesc);
X      inventory[INVEN_MAX].number = 1;
X      objdes(ddesc, INVEN_MAX, TRUE);
X      /* End DIED_FROM                 */
X
X      /* Extract all possible spells into spell_choice */
X      i = (r_ptr->spells & 0xFFFFFFF0);
X      k = 0;
X      while (i != 0)
X	{
X	  spell_choice[k] = bit_pos(&i);
X	  k++;
X	}
X      /* Choose a spell to cast                        */
X      thrown_spell = spell_choice[randint(k) - 1];
X      thrown_spell++;
X      /* Cast the spell...                             */
X      switch(thrown_spell)
X	{
X	case 5:  /*Teleport Short*/
X	  teleport_away(monptr, 5);
X	  break;
X	case 6:  /*Teleport Long */
X	  teleport_away(monptr, MAX_SIGHT);
X	  break;
X	case 7:  /*Teleport To   */
X	  (void) strcat(cdesc, "casts a spell.");
X	  msg_print(cdesc);
X	  teleport_to((int)m_ptr->fy, (int)m_ptr->fx);
X	  break;
X	case 8:  /*Light Wound   */
X	  (void) strcat(cdesc, "casts a spell.");
X	  msg_print(cdesc);
X	  if (player_saves(wis_adj()))
X	    msg_print("You resist the effects of the spell.");
X	  else
X	    take_hit(damroll("3d8"), ddesc);
X	  break;
X	case 9:  /*Serious Wound */
X	  (void) strcat(cdesc, "casts a spell.");
X	  msg_print(cdesc);
X	  if (player_saves(wis_adj()))
X	    msg_print("You resist the effects of the spell.");
X	  else
X	    take_hit(damroll("8d8"), ddesc);
X	  break;
X	case 10:  /*Hold Person   */
X	  (void) strcat(cdesc, "casts a spell.");
X	  msg_print(cdesc);
X	  if (py.flags.free_act)
X	    msg_print("You are unaffected...");
X	  else if (player_saves(wis_adj()))
X	    msg_print("You resist the effects of the spell.");
X	  else if (py.flags.paralysis > 0)
X	    py.flags.paralysis += 2;
X	  else
X	    py.flags.paralysis = randint(5)+4;
X	  break;
X	case 11:  /*Cause Blindness*/
X	  (void) strcat(cdesc, "casts a spell.");
X	  msg_print(cdesc);
X	  if (player_saves(wis_adj()))
X	    msg_print("You resist the effects of the spell.");
X	  else if (py.flags.blind > 0)
X	    py.flags.blind += 6;
X	  else
X	    py.flags.blind += 12 + randint(3);
X	  break;
X	case 12:  /*Cause Confuse */
X	  (void) strcat(cdesc, "casts a spell.");
X	  msg_print(cdesc);
X	  if (player_saves(wis_adj()))
X	    msg_print("You resist the effects of the spell.");
X	  else if (py.flags.confused > 0)
X	    py.flags.confused += 2;
X	  else
X	    py.flags.confused = randint(5) + 3;
X	  break;
X	case 13:  /*Cause Fear    */
X	  (void) strcat(cdesc, "casts a spell.");
X	  msg_print(cdesc);
X	  if (player_saves(wis_adj()))
X	    msg_print("You resist the effects of the spell.");
X	  else if (py.flags.afraid > 0)
X	    py.flags.afraid += 2;
X	  else
X	    py.flags.afraid = randint(5) + 3;
X	  break;
X	case 14:  /*Summon Monster*/
X	  (void) strcat(cdesc, "magically summons a monster!");
X	  msg_print(cdesc);
X	  y = char_row;
X	  x = char_col;
X	  (void) summon_monster(&y, &x, FALSE);
X	  check_mon_lite(y, x);
X	  break;
X	case 15:  /*Summon Undead*/
X	  (void) strcat(cdesc, "magically summons an undead!");
X	  msg_print(cdesc);
X	  y = char_row;
X	  x = char_col;
X	  (void) summon_undead(&y, &x);
X	  check_mon_lite(y, x);
X	  break;
X	case 16:  /*Slow Person  */
X	  (void) strcat(cdesc, "casts a spell.");
X	  msg_print(cdesc);
X	  if (py.flags.free_act)
X	    msg_print("You are unaffected...");
X	  else if (player_saves(wis_adj()))
X	    msg_print("You resist the effects of the spell.");
X	  else if (py.flags.slow > 0)
X	    py.flags.slow += 2;
X	  else
X	    py.flags.slow = randint(5) + 3;
X	  break;
X	case 17:  /*Drain Mana   */
X	  if ((py.misc.cmana) > 0)
X	    {
X	      (void) sprintf(outval, "%sdraws psychic energy from you!",cdesc);
X	      msg_print(outval);
X	      if (flag)
X		{
X		  (void) sprintf(outval, "%sappears healthier...", cdesc);
X		  msg_print(outval);
X		}
X	      r1 = ( randint((int)r_ptr->level) / 2 ) + 1;
X	      if (r1 > py.misc.cmana)  r1 = py.misc.cmana;
X	      py.misc.cmana -= r1;
X	      m_ptr->hp += 6*(r1);
X	    }
X	  break;
X	case 20:  /*Breath Light */
X	  (void) strcat(cdesc, "breathes lightning.");
X	  msg_print(cdesc);
X	  breath(1, char_row, char_col, (int)(m_ptr->hp/4.0), ddesc);
X	  break;
X	case 21:  /*Breath Gas   */
X	  (void) strcat(cdesc, "breathes gas.");
X	  msg_print(cdesc);
X	  breath(2, char_row, char_col, (int)(m_ptr->hp/3.0), ddesc);
X	  break;
X	case 22:  /*Breath Acid  */
X	  (void) strcat(cdesc, "breathes acid.");
X	  msg_print(cdesc);
X	  breath(3, char_row, char_col, (int)(m_ptr->hp/3.0), ddesc);
X	  break;
X	case 23:  /*Breath Frost */
X	  (void) strcat(cdesc, "breathes frost.");
X	  msg_print(cdesc);
X	  breath(4, char_row, char_col, (int)(m_ptr->hp/3.0), ddesc);
X	  break;
X	case 24:  /*Breath Fire  */
X	  (void) strcat(cdesc, "breathes fire.");
X	  msg_print(cdesc);
X	  breath(5, char_row, char_col, (int)(m_ptr->hp/3.0), ddesc);
X	  break;
X	default:
X	  msg_print("Creature cast unknown spell.");
X	  cdesc[0] = '\0';
X	}
X      /* End of spells                                 */
X    }
X  return(cast);
X}
X
X
X/* Move the critters about the dungeon			-RAK-	*/
Xint mon_move(monptr)
Xint monptr;
X{
X  register int i, j;
X  int k;
X  int move_test;
X  int movem;
X  register creature_type *c_ptr;
X  register monster_type *m_ptr;
X  int mm[5];
X
X  /* Main procedure for monster movement (MON_MOVE)	-RAK-	*/
X  movem = FALSE;
X  c_ptr = &c_list[m_list[monptr].mptr];
X  /* Does the critter multiply?                            */
X  if (c_ptr->cmove & 0x00200000)
X    if (MAX_MON_MULT >= mon_tot_mult)
X      if ((py.flags.rest % MON_MULT_ADJ) == 0)
X	{
X	  m_ptr = &m_list[monptr];
X	  k = 0;
X	  for (i = m_ptr->fy-1; i <= m_ptr->fy+1; i++)
X	    for (j = m_ptr->fx-1; j <= m_ptr->fx+1; j++)
X	      if (in_bounds(i, j))
X		if (cave[i][j].cptr > 1)
X		  k++;
X	  /* can't call randint with a value of zero, increment counter
X             to allow creature multiplication */
X	  if (k == 0)
X	    k++;
X	  if (k < 4)
X	    if (randint(k*MON_MULT_ADJ) == 1)
X	      multiply_monster((int)m_ptr->fy, (int)m_ptr->fx,
X			       (int)m_ptr->mptr, FALSE);
X	}
X  /* Creature is confused?  Chance it becomes un-confused  */
X  move_test = FALSE;
X  if (m_list[monptr].confused)
X    {
X      mm[0] = randint(9);
X      mm[1] = randint(9);
X      mm[2] = randint(9);
X      mm[3] = randint(9);
X      mm[4] = randint(9);
X      /* don't move him if he is not supposed to move! */
X      if (!(c_ptr->cmove & 0x00000001))
X	movem = make_move(monptr, mm);
X      if (randint(8) == 1)
X	m_list[monptr].confused = FALSE;
X      move_test = TRUE;
X    }
X  /* Creature may cast a spell                             */
X  else if (c_ptr->spells != 0)
X    movem = mon_cast_spell(monptr, &move_test);
X  if (!move_test)
X    {
X      /* 75% random movement                                   */
X      if ((randint(100) < 75) &&
X	  (c_ptr->cmove & 0x00000020))
X	{
X	  mm[0] = randint(9);
X	  mm[1] = randint(9);
X	  mm[2] = randint(9);
X	  mm[3] = randint(9);
X	  mm[4] = randint(9);
X	  movem = make_move(monptr, mm);
X	}
X      /* 40% random movement                                   */
X      else if ((randint(100) < 40) &&
X	       (c_ptr->cmove & 0x00000010))
X	{
X	  mm[0] = randint(9);
X	  mm[1] = randint(9);
X	  mm[2] = randint(9);
X	  mm[3] = randint(9);
X	  mm[4] = randint(9);
X	  movem = make_move(monptr, mm);
X	}
X      /* 20% random movement                                   */
X      else if ((randint(100) < 20) &&
X	       (c_ptr->cmove & 0x00000008))
X	{
X	  mm[0] = randint(9);
X	  mm[1] = randint(9);
X	  mm[2] = randint(9);
X	  mm[3] = randint(9);
X	  mm[4] = randint(9);
X	  movem = make_move(monptr, mm);
X	}
X      /* Normal movement                                       */
X      else if (c_ptr->cmove & 0x00000002)
X	{
X	  if (randint(200) == 1)
X	    {
X	      mm[0] = randint(9);
X	      mm[1] = randint(9);
X	      mm[2] = randint(9);
X	      mm[3] = randint(9);
X	      mm[4] = randint(9);
X	    }
X	  else
X	    get_moves(monptr, mm);
X	  movem = make_move(monptr, mm);
X	}
X      /* Attack,  but don't move                                */
X      else if (c_ptr->cmove & 0x00000001)
X	if (m_list[monptr].cdis < 2)
X	  {
X	    get_moves(monptr, mm);
X	    movem = make_move(monptr, mm);
X	  }
X    }
X  return(movem);
X}
X
X
X/* Creatures movement and attacking are done from here	-RAK-	*/
Xcreatures(attack)
Xint attack;
X{
X  register int i, j, k;
X  int moldy, moldx;
X  register monster_type *m_ptr;
X  /* Main procedure for creatures				-RAK-	*/
X
X  /* Process the monsters  */
X  i = muptr;
X  while ((i > 0) && (!moria_flag))
X    {
X      m_ptr = &m_list[i];
X      m_ptr->cdis = distance(char_row, char_col,
X			     (int)m_ptr->fy, (int)m_ptr->fx);
X      if (attack)   /* Attack is argument passed to CREATURE*/
X	{
X	  k = movement_rate(m_ptr->cspeed);
X	  if (k > 0)
X	    for (j = 0; j < movement_rate(m_ptr->cspeed); j++)
X	      {
X		if ((m_ptr->cdis <= c_list[m_ptr->mptr].aaf) ||
X		    (m_ptr->ml))
X		  {
X		    if (m_ptr->csleep > 0)
X		      if (py.flags.aggravate)
X			m_ptr->csleep = 0;
X		      else if (py.flags.rest < 1)
X			if (randint(10) > py.misc.stl)
X			  m_ptr->csleep -= (75.0/m_ptr->cdis);
X		    if (m_ptr->stunned > 0)
X		      m_ptr->stunned--;
X		    if ((m_ptr->csleep <= 0) && (m_ptr->stunned <= 0))
X		      {
X			moldy = m_ptr->fy;
X			moldx = m_ptr->fx;
X			if (mon_move(i))
X			  if (m_ptr->ml)
X			    {
X			      m_ptr->ml = FALSE;
X			      if (test_light(moldy, moldx))
X				lite_spot(moldy, moldx);
X			      else
X				unlite_spot(moldy, moldx);
X			    }
X		      }
X		  }
X		update_mon(i);
X	      }
X	  else
X	    update_mon(i);
X	}
X      else
X	update_mon(i);
X      i = m_list[i].nptr;
X    }
X  /* End processing monsters       */
X}
END_OF_FILE
if test 35194 -ne `wc -c <'creature.c'`; then
    echo shar: \"'creature.c'\" unpacked with wrong size!
fi
# end of 'creature.c'
fi
if test -f 'save.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'save.c'\"
else
echo shar: Extracting \"'save.c'\" \(15988 characters\)
sed "s/^X//" >'save.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include "constants.h"
X#include "config.h"
X#include "types.h"
X#include "externs.h"
X
X#ifdef USG
X#include <string.h>
X#else
X#include <strings.h>
X#endif
X
X#ifdef sun   /* correct SUN stupidity in the stdio.h file */
Xchar *sprintf();
X#endif
X
X#ifdef ultrix
Xvoid sleep();
X#endif
X
X#ifdef USG
Xunsigned sleep();
X#endif
X
X#define IREAD 00400
X#define IWRITE 00200
X
X/* This save package was brought to by			-JWT-
X   and                                                  -RAK-
X   and has been completely rewritten for UNIX by        -JEW-  */
X
X/* Wizard command for restoring character		-RAK-	*/
Xrestore_char()
X{
X  vtype fnam;
X  register int i, j;
X  register FILE *f1;
X  int error;
X  vtype temp;
X  double version;
X  struct stat buf2;
X  char char_tmp;
X  char char_tmp_array[3];
X  register cave_type *c_ptr;
X
X  clear_screen(0, 0);
X
X  prt("Enter Filename:", 0, 0);
X  if (!get_string(fnam, 0, 16, 60))
X    {
X      return(FALSE);
X    }
X  no_controlz();
X
X  if (chmod(fnam, (IREAD | IWRITE)) == -1)
X    {
X      (void) sprintf(temp, "Can not change file mode for %s", fnam);
X      prt(temp, 0, 0);
X    }
X
X  if ((f1 = fopen(fnam, "r")) == NULL)
X    {
X      (void) sprintf(temp, "Cannot open file %s for reading.", fnam);
X      prt(temp, 0, 0);
X      return(FALSE);
X    }
X
X  prt("Restoring Character...", 0, 0);
X  put_qio();
X  error = 0;
X  error |= !fread((char *)&version, sizeof(version), 1, f1);
X  error |= !fread((char *)&py, sizeof(py), 1, f1);
X  error |= !fread((char *)&char_row, sizeof(char_row), 1, f1);
X  error |= !fread((char *)&char_col, sizeof(char_col), 1, f1);
X  error |= !fread((char *)&inven_ctr, sizeof(inven_ctr), 1, f1);
X  error |= !fread((char *)&inven_weight, sizeof(inven_weight), 1, f1);
X  error |= !fread((char *)&equip_ctr, sizeof(equip_ctr), 1, f1);
X  error |= !fread((char *)&dun_level, sizeof(dun_level), 1, f1);
X  error |= !fread((char *)&missile_ctr, sizeof(missile_ctr), 1, f1);
X  error |= !fread((char *)&mon_tot_mult, sizeof(mon_tot_mult), 1, f1);
X  error |= !fread((char *)&turn, sizeof(turn), 1, f1);
X  error |= !fread((char *)inventory, sizeof(inventory), 1, f1);
X  error |= !fread((char *)magic_spell[py.misc.pclass],
X		  sizeof(spell_type), 31, f1);
X  error |= !fread((char *)&cur_height, sizeof(cur_height), 1, f1);
X  error |= !fread((char *)&cur_width, sizeof(cur_width), 1, f1);
X  error |= !fread((char *)&max_panel_rows, sizeof(max_panel_rows), 1, f1);
X  error |= !fread((char *)&max_panel_cols, sizeof(max_panel_cols), 1, f1);
X
X  for (i = 0; i < MAX_HEIGHT; i++)
X    for (j = 0; j < MAX_WIDTH; j++)
X      {
X	c_ptr = &cave[i][j];
X	error |= !fread((char *)&c_ptr->cptr, sizeof(c_ptr->cptr), 1, f1);
X	error |= !fread((char *)&c_ptr->tptr, sizeof(c_ptr->tptr), 1, f1);
X	error |= !fread((char *)&char_tmp, sizeof(char_tmp), 1, f1);
X	c_ptr->fval = char_tmp & 0xF;
X	c_ptr->fopen = (char_tmp >> 4) & 0x1;
X	c_ptr->fm = (char_tmp >> 5) & 0x1;
X	c_ptr->pl = (char_tmp >> 6) & 0x1;
X	c_ptr->tl = (char_tmp >> 7) & 0x1;
X      }
X
X  error |= !fread((char *)t_list, sizeof(t_list), 1, f1);
X  error |= !fread((char *)&tcptr, sizeof(tcptr), 1, f1);
X  error |= !fread((char *)object_ident, sizeof(object_ident), 1, f1);
X  error |= !fread((char *)m_list, sizeof(m_list), 1, f1);
X  error |= !fread((char *)&mfptr, sizeof(mfptr), 1, f1);
X  error |= !fread((char *)&muptr, sizeof(muptr), 1, f1);
X
X  if (version == 4.83)
X    {
X      /* insult_cur was a byte in 4.83, but is now a short */
X      for (i = 0; i < MAX_STORES; i++)
X	{
X	  error |= !fread((char *)&store[i].store_open,
X			 sizeof(short), 1, f1);
X	  error |= !fread((char *)&char_tmp,
X			 sizeof(char), 1, f1);   /* this is different */
X          store[i].insult_cur = (short)char_tmp;
X	  error |= !fread((char *)&store[i].owner,
X			 sizeof(char), 1, f1);
X	  error |= !fread((char *)&store[i].store_ctr,
X			 sizeof(char), 1, f1);
X          /* quick compatibility hack for a local vax */
X          /* ignore three bytes of fill character */
X	  error |= !fread((char *)char_tmp_array,
X			 sizeof(char), 3, f1);
X	  error |= !fread((char *)store[i].store_inven,
X			 sizeof(inven_record), STORE_INVEN_MAX, f1);
X	}
X    }
X  else
X    {
X      error |= !fread((char *)store, sizeof(store), 1, f1);
X    }
X
X  error |= !fread((char *)&buf2, sizeof(buf2), 1, f1);
X
X  error |= !fread((char *)norm_state, sizeof(norm_state), 1, f1);
X  error |= !fread((char *)randes_state, sizeof(randes_state), 1, f1);
X  error |= !fread((char *)&randes_seed, sizeof(randes_seed), 1, f1);
X  error |= !fread((char *)town_state, sizeof(town_state), 1, f1);
X  error |= !fread((char *)&town_seed, sizeof(town_seed), 1, f1);
X
X  if (version >= 4.87)
X    {
X      error |= !fread((char *)&panic_save, sizeof(panic_save), 1, f1);
X      /* clear the panic_save condition, which is used to indicate 
X	 cheating */
X      panic_save = 0;
X    }
X
X  error |= fclose(f1);
X
X  controlz();
X
X  if (error)
X    {
X      (void) sprintf(temp, "Error reading in file %s", fnam);
X      prt(temp, 0, 0);
X      return(FALSE);
X    }
X  if (unlink(fnam) == -1)
X    {
X      (void) sprintf(temp, "Cannot delete file %s", fnam);
X      prt(temp, 0, 0);
X    }
X
X  /* reidentify objects */
X  /* very inefficient, should write new routine perhaps? */
X  for (i = 0; i < MAX_OBJECTS; i++)
X    if (object_ident[i] == TRUE)
X      identify(object_list[i]);
X
X  return(FALSE);
X}
X
X
Xsave_char(exit, no_ask)
Xint exit;
Xint no_ask;
X{
X  register int i, j;
X  int flag;
X  int error;
X  vtype fnam, temp;
X  double version;
X  struct stat buf;
X  register FILE *f1;
X  char char_tmp;
X  register cave_type *c_ptr;
X
X  flag = FALSE;
X
X  if (!no_ask)
X    {
X      prt("Enter Filename:", 0, 0);
X      if (!get_string(fnam, 0, 16, 60))
X	{
X	  /* only return if exit TRUE, i.e. this is not a panic save */
X	  if (exit)
X	    return;
X	  else
X	    (void) strcpy(fnam, "MORIACHR.SAV");
X	}
X      /* if get_string succeeded, but returned zero length */
X      else if (strlen(fnam) == 0)
X	(void) strcpy(fnam, "MORIACHR.SAV");
X    }
X  else
X    (void) strcpy(fnam, "MORIACHR.SAV");
X
X  no_controlz();
X
X  /* Open the user's save file                             -JEW-   */
X  if ((f1 = fopen(fnam, "w")) == NULL)
X    {
X      (void) sprintf(temp, "Error creating %s", fnam);
X      msg_print(temp);
X      return;
X    }
X  flag = TRUE;
X  clear_screen(0, 0);
X  prt("Saving character...", 0, 0);
X  put_qio();
X  version = CUR_VERSION;
X  error = 0;
X  error |= !fwrite((char *)&version, sizeof(version), 1, f1);
X  error |= !fwrite((char *)&py, sizeof(py), 1, f1);
X  error |= !fwrite((char *)&char_row, sizeof(char_row), 1, f1);
X  error |= !fwrite((char *)&char_col, sizeof(char_col), 1, f1);
X  error |= !fwrite((char *)&inven_ctr, sizeof(inven_ctr), 1, f1);
X  error |= !fwrite((char *)&inven_weight, sizeof(inven_weight), 1, f1);
X  error |= !fwrite((char *)&equip_ctr, sizeof(equip_ctr), 1, f1);
X  error |= !fwrite((char *)&dun_level, sizeof(dun_level), 1, f1);
X  error |= !fwrite((char *)&missile_ctr, sizeof(missile_ctr), 1, f1);
X  error |= !fwrite((char *)&mon_tot_mult, sizeof(mon_tot_mult), 1, f1);
X  error |= !fwrite((char *)&turn, sizeof(turn), 1, f1);
X  error |= !fwrite((char *)inventory, sizeof(inventory), 1, f1);
X  error |= !fwrite((char *)magic_spell[py.misc.pclass],
X		   sizeof(spell_type), 31, f1);
X  error |= !fwrite((char *)&cur_height, sizeof(cur_height), 1, f1);
X  error |= !fwrite((char *)&cur_width, sizeof(cur_width), 1, f1);
X  error |= !fwrite((char *)&max_panel_rows, sizeof(max_panel_rows), 1, f1);
X  error |= !fwrite((char *)&max_panel_cols, sizeof(max_panel_cols), 1, f1);
X
X  for (i = 0; i < MAX_HEIGHT; i++)
X    for (j = 0; j < MAX_WIDTH; j++)
X      {
X	c_ptr = &cave[i][j];
X	char_tmp = c_ptr->fval | (c_ptr->fopen << 4) | (c_ptr->fm << 5) |
X	  (c_ptr->pl << 6) | (c_ptr->tl << 7);
X	error |= !fwrite((char *)&c_ptr->cptr, sizeof(c_ptr->cptr), 1, f1);
X	error |= !fwrite((char *)&c_ptr->tptr, sizeof(c_ptr->tptr), 1, f1);
X	error |= !fwrite((char *)&char_tmp, sizeof(char_tmp), 1, f1);
X      }
X
X  error |= !fwrite((char *)t_list, sizeof(t_list), 1, f1);
X  error |= !fwrite((char *)&tcptr, sizeof(tcptr), 1, f1);
X  error |= !fwrite((char *)object_ident, sizeof(object_ident), 1, f1);
X  error |= !fwrite((char *)m_list, sizeof(m_list), 1, f1);
X  error |= !fwrite((char *)&mfptr, sizeof(mfptr), 1, f1);
X  error |= !fwrite((char *)&muptr, sizeof(muptr), 1, f1);
X  error |= !fwrite((char *)store, sizeof(store), 1, f1);
X
X  if (stat(fnam, &buf) == -1)
X    {
X      (void) sprintf(temp, "Can not stat file %s", fnam);
X      msg_print(temp);
X      return;
X    }
X
X  error |= !fwrite((char *)&buf, sizeof(buf), 1, f1);
X
X  error |= !fwrite((char *)norm_state, sizeof(norm_state), 1, f1);
X  error |= !fwrite((char *)randes_state, sizeof(randes_state), 1, f1);
X  error |= !fwrite((char *)&randes_seed, sizeof(randes_seed), 1, f1);
X  error |= !fwrite((char *)town_state, sizeof(town_state), 1, f1);
X  error |= !fwrite((char *)&town_seed, sizeof(town_seed), 1, f1);
X
X  /* this indicates 'cheating' if it is a one */
X  error |= !fwrite((char *)&panic_save, sizeof(panic_save), 1, f1);
X
X  error |= fclose(f1);
X
X  character_saved = 1;
X
X  if (!wizard1)
X    if (chmod(fnam, 0) == -1)
X      {
X	(void) sprintf(temp, "Can not change file mode for %s", fnam);
X	msg_print(temp);
X	return;
X      }
X
X  /* make sure user can't touch save file for 5 seconds */
X  (void) sleep(5);
X
X  controlz();
X
X  if (error)
X    {
X      (void) sprintf(temp, "Error writing to file %s", fnam);
X      prt(temp, 0, 0);
X      prt("Game not saved.", 0, 0);
X    }
X  else if (flag)
X    {
X      (void) sprintf(temp,"Character saved. [Moria Version %lf]",CUR_VERSION);
X      prt(temp, 0, 0);
X      if (exit)
X	exit_game();
X    }
X}
X
X
Xget_char(fnam)
Xchar *fnam;
X{
X  register int i, j;
X  register FILE *f1;
X  int error;
X  vtype temp;
X  double version;
X#ifdef USG
X  struct stat buf, buf2;
X#else
X  struct stat lbuf, buf, buf2;
X#endif
X  char char_tmp;
X  char char_tmp_array[3];
X  register cave_type *c_ptr;
X  long age;
X
X  clear_screen(0, 0);
X
X  no_controlz();
X
X#ifdef USG
X  /* no symbolic links */
X  if (stat(fnam, &buf) == -1)
X#else
X  if ((lstat(fnam, &lbuf) == -1) || (stat(fnam, &buf) == -1))
X#endif
X    {
X      (void) sprintf(temp, "Cannot stat file %s", fnam);
X      prt(temp, 0, 0);
X      exit_game();
X    }
X
X#ifdef USG
X  /* no symbolic links */
X#else
X  if (lbuf.st_ino != buf.st_ino)
X    {
X      (void) sprintf(temp, "Cannot restore from symbolic link %s", fnam);
X      prt(temp, 0, 0);
X      exit_game();
X    }
X#endif
X
X  if (buf.st_nlink != 1)
X    {
X      (void) sprintf(temp, "Too many links to file %s", fnam);
X      prt(temp, 0, 0);
X      exit_game();
X    }
X
X  if (chmod(fnam, (IREAD | IWRITE)) == -1)
X    {
X      (void) sprintf(temp, "Can not change file mode for %s", fnam);
X      prt(temp, 0, 0);
X    }
X
X  if ((f1 = fopen(fnam, "r")) == NULL)
X    {
X      (void) sprintf(temp, "Cannot open file %s for reading", fnam);
X      prt(temp, 0, 0);
X      exit_game();
X    }
X
X  prt("Restoring Character...", 0, 0);
X  put_qio();
X  error = 0;
X  error |= !fread((char *)&version, sizeof(version), 1, f1);
X  error |= !fread((char *)&py, sizeof(py), 1, f1);
X  error |= !fread((char *)&char_row, sizeof(char_row), 1, f1);
X  error |= !fread((char *)&char_col, sizeof(char_col), 1, f1);
X  error |= !fread((char *)&inven_ctr, sizeof(inven_ctr), 1, f1);
X  error |= !fread((char *)&inven_weight, sizeof(inven_weight), 1, f1);
X  error |= !fread((char *)&equip_ctr, sizeof(equip_ctr), 1, f1);
X  error |= !fread((char *)&dun_level, sizeof(dun_level), 1, f1);
X  error |= !fread((char *)&missile_ctr, sizeof(missile_ctr), 1, f1);
X  error |= !fread((char *)&mon_tot_mult, sizeof(mon_tot_mult), 1, f1);
X  error |= !fread((char *)&turn, sizeof(turn), 1, f1);
X  error |= !fread((char *)inventory, sizeof(inventory), 1, f1);
X  error |= !fread((char *)magic_spell[py.misc.pclass],
X		  sizeof(spell_type), 31, f1);
X  error |= !fread((char *)&cur_height, sizeof(cur_height), 1, f1);
X  error |= !fread((char *)&cur_width, sizeof(cur_width), 1, f1);
X  error |= !fread((char *)&max_panel_rows, sizeof(max_panel_rows), 1, f1);
X  error |= !fread((char *)&max_panel_cols, sizeof(max_panel_cols), 1, f1);
X
X  for (i = 0; i < MAX_HEIGHT; i++)
X    for (j = 0; j < MAX_WIDTH; j++)
X      {
X	c_ptr = &cave[i][j];
X	error |= !fread((char *)&c_ptr->cptr, sizeof(c_ptr->cptr), 1, f1);
X	error |= !fread((char *)&c_ptr->tptr, sizeof(c_ptr->tptr), 1, f1);
X	error |= !fread((char *)&char_tmp, sizeof(char_tmp), 1, f1);
X	c_ptr->fval = char_tmp & 0xF;
X	c_ptr->fopen = (char_tmp >> 4) & 0x1;
X	c_ptr->fm = (char_tmp >> 5) & 0x1;
X	c_ptr->pl = (char_tmp >> 6) & 0x1;
X	c_ptr->tl = (char_tmp >> 7) & 0x1;
X      }
X
X  error |= !fread((char *)t_list, sizeof(t_list), 1, f1);
X  error |= !fread((char *)&tcptr, sizeof(tcptr), 1, f1);
X  error |= !fread((char *)object_ident, sizeof(object_ident), 1, f1);
X  error |= !fread((char *)m_list, sizeof(m_list), 1, f1);
X  error |= !fread((char *)&mfptr, sizeof(mfptr), 1, f1);
X  error |= !fread((char *)&muptr, sizeof(muptr), 1, f1);
X
X  if (version == 4.83)
X    {
X      /* insult_cur was a byte in 4.83, but is now a short */
X      for (i = 0; i < MAX_STORES; i++)
X	{
X	  error |= !fread((char *)&store[i].store_open,
X			 sizeof(short), 1, f1);
X	  error |= !fread((char *)&char_tmp,
X			 sizeof(char), 1, f1);   /* this is different */
X          store[i].insult_cur = (short)char_tmp;
X	  error |= !fread((char *)&store[i].owner,
X			 sizeof(char), 1, f1);
X	  error |= !fread((char *)&store[i].store_ctr,
X			 sizeof(char), 1, f1);
X          /* quick compatibility hack for a local vax */
X          /* ignore three bytes of fill character */
X	  error |= !fread((char *)char_tmp_array,
X			 sizeof(char), 3, f1);
X	  error |= !fread((char *)store[i].store_inven,
X			 sizeof(inven_record), STORE_INVEN_MAX, f1);
X	}
X    }
X  else
X    {
X      error |= !fread((char *)store, sizeof(store), 1, f1);
X    }
X
X  error |= !fread((char *)&buf2, sizeof(buf2), 1, f1);
X
X  error |= !fread((char *)norm_state, sizeof(norm_state), 1, f1);
X  error |= !fread((char *)randes_state, sizeof(randes_state), 1, f1);
X  error |= !fread((char *)&randes_seed, sizeof(randes_seed), 1, f1);
X  error |= !fread((char *)town_state, sizeof(town_state), 1, f1);
X  error |= !fread((char *)&town_seed, sizeof(town_seed), 1, f1);
X
X  if (version >= 4.87)
X    {
X      error |= !fread((char *)&panic_save, sizeof(panic_save), 1, f1);
X    }
X
X  error |= fclose(f1);
X
X  controlz();
X
X  if (buf.st_atime >= buf2.st_atime + 5)
X    {
X      (void) sprintf(temp, "File %s has been touched, sorry.", fnam);
X      prt(temp, 0, 0);
X      exit_game();
X    }
X
X  if (error)
X    {
X      (void) sprintf(temp, "Error reading in file %s", fnam);
X      prt(temp, 0, 0);
X      exit_game();
X    }
X
X  /* rotate store inventory, depending on how old the save file is */
X  /* foreach day or fraction thereof old, call store_maint once */
X  /* must do this before delete file */
X  if (stat (fnam, &buf2) == -1)
X    {
X      (void) sprintf(temp, "Cannot stat file %s?", fnam);
X      prt(temp, 0, 0);
X    }
X  else
X    {
X      age = (long)buf2.st_atime - (long)buf.st_atime;  /* age in seconds */
X      age = (age / 86400) + 1;  /* age in days */
X      for (i = 0; i < age; i++)
X	store_maint();
X    }
X
X  if (unlink(fnam) == -1)
X    {
X      (void) sprintf(temp, "Cannot delete file %s", fnam);
X      prt(temp, 0, 0);
X      exit_game();
X    }
X
X  if (panic_save == 1)
X    {
X      (void) sprintf(temp, "This game is from a panic save.  Score will not be added to scoreboard.");
X      msg_print (temp);
X      /* make sure player will see message before change_name is called */
X      msg_print (" ");
X    }
X
X  /* reidentify objects */
X  /* very inefficient, should write new routine perhaps? */
X  for (i = 0; i < MAX_OBJECTS; i++)
X    if (object_ident[i] == TRUE)
X      identify(object_list[i]);
X
X  /* in case restoring a dead character, this can happen if a signal
X     is caught after a characters hit points go below zero, but before
X     the game ends */
X  if (py.misc.chp <= -1)
X    {
X      prt("Your character has already died.", 23, 0);
X      (void) strcpy(died_from, "Unknown.");
X      death = 1;
X    }
X
X  return(FALSE);
X}
END_OF_FILE
if test 15988 -ne `wc -c <'save.c'`; then
    echo shar: \"'save.c'\" unpacked with wrong size!
fi
# end of 'save.c'
fi
echo shar: End of archive 11 \(of 18\).
cp /dev/null ark11isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 18 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0