Rog-O-Matic XIV (part 02 of 10)

Michael Mauldin mlm at cmu-cs-cad.ARPA
Sat Feb 2 04:33:28 AEST 1985


#!/bin/sh
#
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @ Here is part of your new automatic Rogue player, Rog-O-Matic XIV! @
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# 
#     [Note: this is a Beta-Test release of version XIV, and almost
#      certainly contains bugs.  A new version will be made available
#      soon.  If you experience any problems with this version, please
#      contact Michael Mauldin as soon as possible, so your input can be
#      included in the new release]
# 
# Rog-O-Matic XIV is shipped via mail in pieces, files rgm14.01, rgm14.02,
# ..., rgm14.nn.  Each piece contains some number of smaller files. To
# retrieve them, run each file through the shell 'sh', as follows:
# 
# 	sh <rgm14.01
# 	sh <rgm14.02
# 	     ...
# 	sh <rgm14.nn
# 
# or do it all at once:
# 
# 	cat rgm14.* | sh
# 
# The README file contains all necessary information to edit the "install.h"
# file, after which "make" will build the rogomatic and player binary files.
# Please note that file 'Bugreport' contains modifications you may wish to
# make to the code BEFORE you compile it.  You can safely install ALL of
# them; depending on your version of Rogue, you may HAVE to install SOME of
# them.
# 
# Rog-O-Matic is copyrighted, but permission is given to copy and modify the
# source provided that (1) it is not used for profit (2) all authorship and
# copyright notices remain intact and (3) any person or site with a copy has
# notified Michael Mauldin either by electronic mail or US Post that they
# have Rog-O-Matic XIV.
# 
# We would appreciate hearing about any interesting additions or modifi-
# cations, and would especially like to know how well the program plays
# against your Rogue.  And we really, really want to know if Rog-O-Matic
# becomes a "Total Winner" against Rogue 5.2 or Rogue 5.3 again.
# 
# 				Michael Mauldin (Fuzzy)
# 				Department of Computer Science
# 				Carnegie-Mellon University
# 				Pittsburgh, PA  15213
# 				(412) 578-3065,  mauldin at cmu-cs-a.arpa
#
echo 'Start of Rog-O-Matic XIV, part 02 of 10:'
echo 'x - explore.c'
sed 's/^X//' > explore.c << '/'
X/*
X * explore.c: Rog-O-Matic XIV (CMU) Thu Jan 31 20:14:30 1985 - mlm
X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin
X *
X * This file contains all of the functions which are used to search out
X * paths to explore, pick up something, or run away.
X */
X
X# include <curses.h>
X# include "types.h"
X# include "globals.h"
X
X# define SEARCHES(r,c)						\
X	(onrc(DEADEND,r,c) ?					\
X	    ((version < RV53A || !isexplored (r,c)) ?		\
X		(timestosearch + k_door / 5) :			\
X		(timestosearch - k_door / 5 + 5)) :		\
X	    timestosearch)
X
Xstatic int expDor, expavoidval;
Xstatic int avdmonsters[24][80];
X
Xint connect[9][4] = {
X    /* Room  top    bot   left  right*/
X    /* 0 */  {-1,     3,    -1,     1},
X    /* 1 */  {-1,     4,     0,     2},
X    /* 2 */  {-1,     5,     1,    -1},
X    /* 3 */  { 0,     6,    -1,     4},
X    /* 4 */  { 1,     7,     3,     5},
X    /* 5 */  { 2,     8,     4,    -1},
X    /* 6 */  { 3,    -1,    -1,     7},
X    /* 7 */  { 4,    -1,     6,     8},
X    /* 8 */  { 5,    -1,     7,    -1}
X};
X
X/*
X * genericinit: Initialize a 'standard' movement search.	MLM
X */
X
Xgenericinit ()
X{ expavoidval = avoid();
X  return (1);
X}
X
X/* Secret door search values and continuance tables:
X *
X *  Number of unsearched walls adjacent.
X *
X * 	Vert	Horiz	Value		Cont	Explanation
X *	---------------------------------------------------
X *	0	0	0		0	Valueless
X *	0	1	N-24-dep	16	Prefer (0,2) 1 move later
X *	0	2	N-22-dep	15	Prefer (0,3) 1 move later
X *	0	3	N-20-dep	14	Prefer (1,0) 10 moves later
X *	1	0	N-9-dep		4	Prefer (1,1) 2 moves later
X *	1	1	N-6-dep		2	Prefer (2,0) 1 move later
X *	1	2	N-5-dep		2	Prefer (2,0) 1 move later
X *	1	3	N-5-dep		2	Impossible
X *	2	0	N-3-dep		1	Prefer (3,0) 1 move later
X *	2	1	N-2-dep		0
X *	2	2	N-1-dep		0
X *	2	3	N-1-dep		0	Impossible
X *	3	0	N		0	Best possible
X *	3	1	N		0	Impossible
X *	3	2	N		0	Impossible
X *	3	3	N		0	Impossible
X */
X
X# define N 100
Xstatic int secretvalues[16]= { 0, N-24, N-22, N-20,
X		             N-9,  N-6,  N-5,  N-5,
X		             N-3,  N-2,  N-1,  N-1,
X		               N,    N,    N,    N };
X
Xstatic int secretcont[16] =  { 0, 16, 15, 14,
X 			       4,  2,  2,  2,
X			       1,  0,  0,  0,
X			       0,  0,  0,  0 };
X
X/*
X * gotowards: Move toward a square.
X */
X
Xint gotorow = NONE, gotocol = NONE;
X
Xgotowards (row, col, running)
Xint row, col, running;
X{ int gotoinit(), gotovalue();
X
X  gotorow = row; gotocol = col;
X  return (makemove (running ? RUNAWAY:GOTOMOVE, gotoinit, gotovalue, REUSE));
X}
X
X/*
X * gotoinit: Initialize a gotowards move.
X */
X
Xgotoinit ()
X{ expavoidval = avoid();
X  return (1);
X}
X
X/*
X * gotovalue: Only the current target square has a value.
X */
X
Xgotovalue (r, c, depth, val, avd, cont)
Xint r, c, depth, *val, *avd, *cont;
X{ 
X  *avd = onrc (SAFE, r, c)    ? 0 :
X	 onrc (ARROW, r, c)   ? 50 :
X         onrc (TRAPDOR, r, c) ? 175 :
X         onrc (TELTRAP, r, c) ? 50 :
X         onrc (GASTRAP, r, c) ? 50 :
X         onrc (BEARTRP, r, c) ? 50 :
X         onrc (DARTRAP, r, c) ? 200 :
X         onrc (WATERAP, r, c) ? 50 :
X         onrc (MONSTER, r, c) ? 150 :
X         expavoidval;
X
X  if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj)
X    *avd += 200;
X
X  *val = r == gotorow && c == gotocol ? 1 : 0;
X  /*  *cont = 0; // default value when called // */
X  return (1);
X}
X
X/*
X * sleepvalue: Squares with sleeping monsters have value. 
X *             Use genericinit.		MLM
X */
X
Xsleepvalue (r, c, depth, val, avd, cont)
Xint r, c, depth, *val, *avd, *cont;
X{ 
X  *avd = onrc (SAFE, r, c)    ? 0 :
X	 onrc (ARROW, r, c)   ? 50 :
X         onrc (TRAPDOR, r, c) ? 175 :
X         onrc (TELTRAP, r, c) ? 50 :
X         onrc (GASTRAP, r, c) ? 50 :
X         onrc (BEARTRP, r, c) ? 50 :
X         onrc (DARTRAP, r, c) ? 200 :
X         onrc (WATERAP, r, c) ? 50 :
X         onrc (MONSTER, r, c) ? 150 :
X         expavoidval;
X
X  if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj)
X    *avd += 200;
X
X  if (onrc (SLEEPER, r, c))
X  { *val = 1;
X    *avd = 0;
X    /* *cont = 0;  // default value when called // */
X  }
X
X  return (1);
X}
X
X/*
X * wallkind: given a row and column, determine which kind of wall if any
X *           is there. Part of doorinit   Guy Jacobson 5/82
X */
X
Xint wallkind (r, c)
Xint r, c;
X{
X  switch (screen[r][c]) 
X  { case '|': if (onrc (ROOM, r, c+1)) return (LEFTW);
X              else return (RIGHTW);
X    case '-': if (onrc (ROOM, r+1, c)) return (TOPW); 
X              else if (onrc (ROOM, r-1, c)) return (BOTW);
X              else return (CORNERW);
X    case '+': return (DOORW);
X    default:  return (NOTW);
X  }
X}
X
X/* 
X * setpsd: Initialize secret door search 
X *
X * Guy Jacobson 5/82
X * Modified to allow searching even when there are cango bits.	MLM.   10/82
X * Modified to reuse existing map while it is valid.		LGCH.  10/82
X * Modified to understand maze room secret doors.		MLM.   10/83
X */
X
Xsetpsd (print)
X{ register int i, j, k, whereto, numberpsd=0;
X
X  if (!print && reusepsd > 0) return (reusepsd-1);
X
X  /* find what rooms are missing */
X  markmissingrooms ();
X
X  /* Changed loop boundaries to ignore border around screen -- mlm 5/18/82 */
X  for (i=2; i<22; i++) for (j=1; j<79; j++) 
X  { unsetrc (PSD|DEADEND,i,j);
X
X    /* If attempt > 3, allow ANYTHING to be a secret door! */
X    if (attempt > 3 && ! onrc (BEEN|DOOR|HALL|ROOM|WALL|STAIRS, i, j) &&
X        nextto (CANGO, i, j))
X    { if (!onrc (PSD, i, j)) numberpsd++; setrc(PSD,i,j); }
X
X    /* Set Possible Secret Door for maze room secret doors */
X    else if (attempt > 0 && ! onrc (BEEN|DOOR|HALL|ROOM|WALL|STAIRS, i, j) &&
X        mazedoor (i, j))
X    { if (!onrc (PSD, i, j)) numberpsd++; setrc(PSD,i,j); }
X
X    /* Set Possible Secret Door for corridor secret door */
X    else if (version >= RV53A &&
X             ! onrc (BEEN|DOOR|HALL|ROOM|WALL|STAIRS, i, j) &&
X             nextto (DOOR, i, j))
X    { if (!onrc (PSD, i, j)) numberpsd++; setrc(PSD,i,j); }
X
X    /* Set Possible Secret Door for dead end corridors */
X    else if (! onrc (BEEN|DOOR|HALL|ROOM|WALL|STAIRS, i, j) &&
X             (onrc (HALL, i-1, j) + onrc (HALL, i+1, j) +
X              onrc (HALL, i, j-1) + onrc (HALL, i, j+1) == HALL) &&
X             !(onrc(HALL|DOOR, i-1, j-1) || onrc(HALL|DOOR, i+1, j+1) ||
X               onrc(HALL|DOOR, i-1, j+1) || onrc(HALL | DOOR, i+1, j-1)) &&
X             canbedoor (i, j))
X    { if (!onrc (PSD, i, j)) numberpsd++;
X      setrc(DEADEND,i,j); setrc(PSD,i,j);
X    }
X
X    /* Set PSD for walls which connect to empty space */
X
X    /* Modified to allow PSD for !ROOM (including the old CANGO des.) */
X    /* since potions and scrolls of detection can cause the CANGO bit */
X    /* to be set for a square on which we have never been.            */
X    /* 							mlm 10/8/82   */
X
X    /* If attempt > 2, then relax the constraint about empty space,   */
X    /* since we might have teleported into a disconnected part of the */
X    /* level. This means after we have searched twice, we look for    */
X    /* ANY possible door, not just doors leading to empty space.      */
X    /* 							mlm 10/11/82  */
X   
X    else 
X    { if ((k = wallkind (i,j)) >= 0)
X      { /* A legit sort of wall */
X        whereto = connect[whichroom (i,j)][k];
X        if (whereto >= 0 && (attempt > 1 || room[whereto] == 0))
X	{ if (!onrc (PSD, i, j)) numberpsd++;
X	  setrc (PSD,i,j);
X	}
X      }
X    }
X  }
X  
X  /* Now remove PSD bits from walls which already have doors */
X  for (i=2; i<22; i++) for (j=1; j<79; j++)
X  { if (onrc (DOOR, i, j))
X    { for (k = i-1; onrc (WALL, k, j); k--)
X      { if (onrc (PSD, k, j)) numberpsd--; unsetrc (PSD, k, j);}
X      for (k = i+1; onrc (WALL, k, j); k++)
X      { if (onrc (PSD, k, j)) numberpsd--; unsetrc (PSD, k, j);}
X      for (k = j-1; onrc (WALL, i, k); k--)
X      { if (onrc (PSD, i, k)) numberpsd--; unsetrc (PSD, i, k);}
X      for (k = j+1; onrc (WALL, i, k); k++)
X      { if (onrc (PSD, i, k)) numberpsd--; unsetrc (PSD, i, k);}
X    }
X  }
X
X  if (print || debug (D_SCREEN))
X    for (i=0; i<24; i++) for (j=0; j<80; j++)
X      if (onrc (PSD,i,j)) { at (i,j); addch ('P'); }
X
X  reusepsd = numberpsd+1;
X  return (numberpsd);
X}
X
X/*
X * downvalue: find nearest stairs or trapdoor (use genericinit for init).
X */
X
Xdownvalue (r, c, depth, val, avd, cont)
Xint r, c, depth, *val, *avd, *cont;
X{ 
X  *avd = onrc (SAFE, r, c)    ? 0 :
X	 onrc (ARROW, r, c)   ? 50 :
X         onrc (TRAPDOR, r, c) ? 175 :
X         onrc (TELTRAP, r, c) ? 50 :
X         onrc (GASTRAP, r, c) ? 50 :
X         onrc (BEARTRP, r, c) ? 50 :
X         onrc (DARTRAP, r, c) ? 200 :
X         onrc (WATERAP, r, c) ? 50 :
X         onrc (MONSTER, r, c) ? 150 :
X         expavoidval;
X
X  if (onrc (STAIRS | TRAPDOR, r, c)) { *val = 1; *avd = 0; }
X  else			             { *val = 0; }
X
X  return (1);
X}
X
X/* 
X * expruninit: same as expinit but don't bias against doors.
X */
X
Xexpruninit ()
X{ dwait (D_CONTROL | D_SEARCH, "expruninit called.");
X  expinit();
X  expDor = 0;
X  avoidmonsters ();
X  return (1);
X}
X
X/*
X * exprunvalue: When running, avoid monsters.
X *
X * Try to see a new square when running.
X */
X
Xexprunvalue (r, c, depth, val, avd, cont)
Xint r, c, depth, *val, *avd, *cont;
X{ if (r == atrow && c == atcol)		/* Current square useless MLM */
X    *val = 0;
X  else if (onrc (MONSTER | TRAP, r, c))	/* Added TRAP useless MLM */
X    *val = 0;
X  else if (!zigzagvalue (r, c, depth, val, avd, cont))
X    return (0);
X
X  if (*val > 0) { *val = *val * 1000 + depth; *cont = INFINITY; }
X  *avd += avdmonsters[r][c];
X  return (1);
X}
X
X/* 
X * expunpininit: same as exprunnit but try to unpin.
X */
X
Xexpunpininit ()
X{ dwait (D_CONTROL | D_SEARCH, "expunpininit called.");
X  expinit();
X  expDor = 0;
X  pinavoid ();
X  return (1);
X}
X
X/*
X * expunpinvalue: When unpinning, avoid monsters.
X *
X * Try to see a new square when unpinning, but unpin anywhere if need be.
X */
X
Xexpunpinvalue (r, c, depth, val, avd, cont)
Xint r, c, depth, *val, *avd, *cont;
X{ if (r == atrow && c == atcol)		/* Current square useless MLM */
X    *val = 0;
X  else if (onrc (MONSTER | TRAP, r, c))	/* Added TRAP useless MLM */
X    *val = 0;
X  else if (!zigzagvalue (r, c, depth, val, avd, cont))
X    return (0);
X
X  if (*val > 0) { *val = *val * 1000 + depth; *cont = INFINITY; }
X  *avd += avdmonsters[r][c];
X  return (1);
X}
X
X/*
X * runinit:  R U N   A W A Y   S E A R C H
X */
X
Xruninit ()
X{ avoidmonsters();
X  return (1);
X}
X
X/*
X * runvalue:
X *
X * Evaluate square for running away. Targets, in priority order are:
X *
X * STAIRS  TRAPDOR  TELTRAP
X * RUNOK (cycle door)
X * DOOR
X * ANYWHERE
X *
X * Traps are avoided for a variable number of moves, except for target traps
X * Gave GasTraps and BearTraps infinite avoidance.	MLM 10/11/83
X */
X
Xrunvalue (r, c, depth, val, avd, cont)
Xint r, c, depth, *val, *avd, *cont;
X{ *avd = onrc (ARROW, r, c) ? 50 :
X         onrc (TRAPDOR, r, c) ? 0 :
X         onrc (TELTRAP, r, c) ? 0 :
X         onrc (GASTRAP, r, c) ? INFINITY :
X         onrc (BEARTRP, r, c) ? INFINITY :
X         onrc (DARTRAP, r, c) ? 100 :
X         onrc (WATERAP, r, c) ? 100 :
X         onrc (MONSTER, r, c) ? 150 :
X         0;
X
X  if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj)
X    *avd += 200;
X
X  if (onrc (MONSTER, r, c))
X    { *val = 0; }
X  if (onrc (STAIRS+TRAPDOR+TELTRAP, r, c))
X    { *val = 5000; *avd = 0; /* *cont = 0; */ }
X  else if (r == atrow && c == atcol)	/* If we are running, our current */
X    { *val = 0;}			/* cant be that great -- MLM      */
X  else if (onrc (RUNOK, r, c))
X    { *val = 4000; *cont = INFINITY;}
X  else if (onrc (DOOR | BEEN, r, c) == DOOR)
X    { *val = 2000+depth; *cont = INFINITY;}
X  else if (onrc (DOOR, r, c))
X    { *val = 1000+depth; *cont = INFINITY;}
X  else if (onrc (HALL, r, c))
X    { *val =      depth; *cont = INFINITY;}
X  /* ----------------------------------------------------------------
X  else if (onrc (CANGO | TRAP, r, c) == CANGO)
X    { *val = 1+depth; *cont = INFINITY;}
X  ---------------------------------------------------------------- */
X  else
X    { *val = 0; }
X
X  *avd += avdmonsters[r][c];
X}
X
X/*
X * unpininit:  U N P I N    S E A R C H
X *
X * Same as runint, but we are willing to take one hit to get away.
X */
X
Xunpininit ()
X{ pinavoid();
X  return (1);
X}
X
X/*
X * rundoorinit: Standard initialization routine.
X */
X
Xrundoorinit()
X{ avoidmonsters();
X  return (1);
X}
X
X/*
X * rundoorvalue: 
X *
X * Evaluate square for running into doorway.
X *
X * Targets, in priority order are:
X *
X * RUNOK (cycle door)
X * DOOR
X *
X * Traps are avoided for a variable number of moves, except for target traps
X * Gave GasTraps and BearTraps infinite avoidance.	MLM 10/11/83
X */
X
Xrundoorvalue (r, c, depth, val, avd, cont)
Xint r, c, depth;
Xint *val, *avd, *cont;
X{ *avd = onrc (ARROW, r, c) ? 50 :
X         onrc (TRAPDOR, r, c) ? 0 :
X         onrc (TELTRAP, r, c) ? 0 :
X         onrc (GASTRAP, r, c) ? INFINITY :
X         onrc (BEARTRP, r, c) ? INFINITY :
X         onrc (DARTRAP, r, c) ? 100 :
X         onrc (WATERAP, r, c) ? 100 :
X         onrc (MONSTER, r, c) ? 50 : 0;
X
X  if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj)
X    *avd += 200;
X
X  if (onrc (RUNOK, r, c))	{ *val = 2;}
X  else if (onrc (DOOR, r, c))	{ *val = 1; *cont = INFINITY;}
X  else				{ *val = 0;}
X
X  *avd += avdmonsters[r][c];
X}
X
X/*
X *   E X P L O R A T I O N   S E A R C H
X */
X
Xexpinit ()
X{ /* avoidance values for doors */
X  expDor = 0;
X  expavoidval = avoid();
X  return (1);
X}
X
Xroominit ()
X{ expinit ();
X  expDor = INFINITY;
X  return (1);
X}
X
X/*
X * expvalue: evaluation function for exploration.  LGCH
X *
X * In order to prevent leaving orphan unseen squares, we have heuritics
X * which cause rogomatic to use the three-step pattern to scan along the
X * boundary of a room, and also have tests which detect any orphans (e.g.
X * corners and when an object interrupts the search pattern) and cause them
X * to be seen.
X *
X * Three-step pattern:
X *
X *        @@ @@
X *       @  @  @
X *      bbbbbbbbb
X */
X
Xexpvalue (r, c, depth, val, avd, cont)
Xint r, c, depth;
Xint *val, *avd, *cont;
X{ register int k, nr, nc, l;
X  int a, v = 0, nunseenb = 0, nseenb = 0, nearb = 0;
X
X  a = onrc (SAFE|DOOR|STAIRS|HALL, r, c) ? 0 :
X      onrc (ARROW, r, c)   ? 50 :
X      onrc (TRAPDOR, r, c) ? 300 :
X      onrc (TELTRAP, r, c) ? 100 :
X      onrc (GASTRAP, r, c) ? 50 :
X      onrc (BEARTRP, r, c) ? 50 :
X      onrc (DARTRAP, r, c) ? 200 :
X      onrc (TRAP, r, c)    ? 100 :
X      onrc (MONSTER, r, c) ? 150 :
X      expavoidval;
X
X  if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj)
X  { *avd = a+1000; *val=0; return (1); }
X
X  if (onrc (BEEN+SEEN, r, c) == SEEN)  /* If been or not seen, not a target */
X  { for (k=0; k<8; k++)
X    { nr = r + deltr[k];
X      nc = c + deltc[k];
X      
X      /* For each unseen neighbour: add 10 to value. */
X      if (nr >= 1 && nr <= 22 && nc >= 0 && nc <= 80 &&
X        !onrc (SEEN, nr, nc))
X      { v += 10;
X
X        if (onrc (BOUNDARY, nr, nc))
X	{ /* Count unseen boundary neighbours. */
X	  nunseenb++;
X
X	  /* Count seen boundaries horiz/vert adjacent to unseen boundary */
X	  for (l=0; l<8; l+=2)
X	    if (onrc (SEEN+BOUNDARY, nr+deltr[l], nc+deltc[l]) ==
X	      SEEN+BOUNDARY)
X	      nseenb++;
X
X	}
X	else
X	{ /* Check for unseen boundary horiz/vert       */
X	  /* adjacent to neighbour and not a neighbour. */
X	  l = k / 2 * 2; 		     /* horizontal/vertical */
X	  if (onrc (BOUNDARY+SEEN, nr+deltr[l], nc+deltc[l]) == BOUNDARY)
X	    nearb = 1;
X	  else
X	  { l = ((k+1) / 2 * 2) % 8;
X	    if (onrc (BOUNDARY+SEEN, nr+deltr[l], nc+deltc[l]) == BOUNDARY)
X	      nearb = 1;
X	  }
X	}
X      }
X    }
X
X    /* To zig-zag: add number of unseen boundary neighbours * 6 */
X    v += nunseenb * 6;
X
X    /* To do the three-step: add 29 if an unseen neighbour had an unseen
X     * boundary horiz/vert adjacent */
X    if (nearb)
X      v += 29;
X
X    /* To prevent orphans: if three unseen neighbours are boundary and one
X     * has a seen boundary horiz/vert adjacent, add 200 */
X    if (nunseenb >= 3 && nseenb >= 1)
X      v += 200;
X
X    /* To clean up any orphans: if two seen boundaries are adjacent to any
X     * unseen boundary neighbours, add 400. */
X    if (nseenb >= 2)
X      v += 400;
X  }
X
X  if (onrc (DOOR, r, c))
X    a += expDor;
X  /* else if (onrc (BEEN+BOUNDARY, r, c) == BOUNDARY)
X    a++;   // Avoid running along the untrodden boundary. // */
X
X  *avd = a;
X  *val = v;
X  if (v < 50)
X    *cont = 4; 				     /* Look for something better */
X  if (debug (D_SCREEN) && v > 0)
X  { mvaddch (r, c, 'o'); dwait (D_SCREEN, "Value %d", v); }
X
X  return (1);
X}
X
X/*
X * zigzagvalue: evaluation function for exploration.  LGCH
X *
X * This is a copy of expvalue with the three-step code and the code to
X * detect orphans removed. It is used when running away and unpinning
X * to find a useful exploration move. The boundary moves must zig-zag
X * rather than three-step so that the door can be entered when it is seen
X * without taking a hit from the monster chasing us.
X *
X * Gave GasTraps and BearTraps infinite avoidance.	MLM 10/11/83
X */
X
Xzigzagvalue (r, c, depth, val, avd, cont)
Xint r, c, depth;
Xint *val, *avd, *cont;
X{ register int k, nr, nc, l;
X  int a, v = 0, nunseenb = 0, nseenb = 0, nearb = 0;
X
X  a = onrc (SAFE|DOOR|STAIRS|HALL, r, c) ? 0 :
X      onrc (ARROW, r, c)   ? 50 :
X      onrc (TRAPDOR, r, c) ? 300 :
X      onrc (TELTRAP, r, c) ? 100 :
X      onrc (GASTRAP, r, c) ? 50 :
X      onrc (BEARTRP, r, c) ? 50 :
X      onrc (DARTRAP, r, c) ? 200 :
X      onrc (TRAP, r, c)    ? 100 :
X      onrc (MONSTER, r, c) ? 150 :
X      expavoidval;
X
X  if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj)
X  { *avd = a+1000; *val=0; return (1); }
X
X  if (onrc (BEEN+SEEN, r, c) == SEEN)  /* If been or not seen, not a target */
X  { for (k=0; k<8; k++)
X    { nr = r + deltr[k];
X      nc = c + deltc[k];
X      
X      /* For each unseen neighbour: add 10 to value. */
X      if (nr >= 1 && nr <= 22 && nc >= 0 && nc <= 80 &&
X        !onrc (SEEN, nr, nc))
X      { v += 10;
X
X        if (onrc (BOUNDARY, nr, nc))
X	{ /* Count unseen boundary neighbours. */
X	  nunseenb++;
X	}
X        if (debug (D_SCREEN)) mvaddch (nr, nc, 'o');
X      }
X    }
X
X    /* To zig-zag: add number of unseen boundary neighbours * 6 */
X    v += nunseenb * 6;
X  }
X
X  if (onrc (DOOR, r, c))
X    a += expDor;
X  /* else if (onrc (BEEN+BOUNDARY, r, c) == BOUNDARY)
X    a++;   // Avoid running along the untrodden boundary. // */
X
X  *avd = a;
X  *val = v;
X  *cont = 0; 				     /* Look for orphans */
X
X  return (1);
X}
X
X/*
X *   S E C R E T   D O O R   S E A R C H
X */
X
Xsecretinit ()
X{ expinit ();
X  if (setpsd ())
X    return (1);
X  return (0);
X}
X
Xsecretvalue (r, c, depth, val, avd, cont)
Xint r, c, depth;
Xint *val, *avd, *cont;
X{ register int v, a, k;
X
X  *val=0;
X  v = 0;	/* establish value of square */
X  a = onrc (SAFE, r, c)    ? 0 :
X      onrc (ARROW, r, c)   ? 50 :
X      onrc (TRAPDOR, r, c) ? 175 :
X      onrc (TELTRAP, r, c) ? 50 :
X      onrc (GASTRAP, r, c) ? 50 :
X      onrc (BEARTRP, r, c) ? 50 :
X      onrc (DARTRAP, r, c) ? 200 :
X      onrc (WATERAP, r, c) ? 50 :
X      onrc (MONSTER, r, c) ? 150 :
X      expavoidval;
X
X  if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj)
X    a += 200;
X
X  for (k=0; k<8; k++)    /* examine adjacent squares */
X  { register int nr = r + deltr[k];
X    register int nc = c + deltc[k];
X    if (nr >= 1 && nr <= 22 &&
X      nc >= 0 && nc <= 80 &&
X      onrc (PSD, nr, nc) && timessearched[nr][nc] < SEARCHES(nr,nc))
X    { /* If adjacent square is on the screen */
X      /* and if it has PSD set but has not been searched completely */
X      /* count useful neighbours */
X      if (screen[nr][nc] == '|')	v += 4;
X      else				v ++;
X      if (debug (D_SCREEN | D_INFORM)) mvaddch (nr, nc, 'S');
X    }
X  }
X
X  if (v>0)
X  { if (version >= RV53A &&
X        onrc (DOOR|BEEN, r, c) == DOOR|BEEN && 
X        (onrc (CANGO|WALL, r+1, c) == 0 || onrc (CANGO|WALL, r-1, c) == 0 ||
X         onrc (CANGO|WALL, r, c+1) == 0 || onrc (CANGO|WALL, r, c-1) == 0))
X    { *val = v+100; *cont = 5; }
X    else
X    { v = min (15, v);
X      *val = secretvalues[v]; *cont = secretcont[v];  
X      if (onrc (DOOR, r, c)) a += expDor;
X    }
X  }
X  *avd = a;
X
X  return (1);
X}
X
X/*
X *   E S T A B L I S H   A V O I D A N C E   M A P   to avoid monsters.
X */
X
X# define AVOID(r,c,ch) \
X  { avdmonsters[r][c] = INFINITY; \
X    if (debug (D_SCREEN)) { at((r),(c)); addch(ch); at(row,col); }}
X
Xavoidmonsters ()
X{ register int i, r, c, wearingstealth;
X
X  /* Clear old avoid monster values */
X  for (i = 24*80; i--; ) avdmonsters[0][i] = 0;
X  
X  /* Set stealth status */
X  wearingstealth = (wearing ("stealth") != NONE);
X
X  /* Avoid each monster in turn */
X  for (i=0; i<mlistlen; i++)
X  { /* First check whether this monster is really wimpy */
X    if (maxhit(i) < Hp/2)
X    { AVOID (mlist[i].mrow, mlist[i].mcol, '$')
X    }
X    /* If not a wimp and awake, avoid him all together */
X    else if (mlist[i].q == AWAKE) 
X    { int d, dr, dc, mr = mlist[i].mrow, mc = mlist[i].mcol;
X      d = direc (searchstartr-mr,searchstartc-mc);
X      dr = (searchstartr-mr)/2+mr; dc=(searchstartc-mc)/2+mc;
X      if (d & 1)
X      { caddycorner (dr, dc, (d-1) & 7, (d-3)&7, '$');
X        caddycorner (dr, dc, (d+1) & 7, (d+3)&7, '$');
X      }
X      else 
X      { caddycorner (dr, dc, (d-2) & 7, d, '$');
X        caddycorner (dr, dc, (d+2) & 7, d, '$');
X      }
X    }
X    /* If he'll wake up, give him a wide berth */
X    else if (!wearingstealth)
X    { for (r = mlist[i].mrow-1; r<= mlist[i].mrow+1; r++)
X        for (c = mlist[i].mcol-1; c<= mlist[i].mcol+1; c++)
X          AVOID (r, c, '$')
X    }
X    /* He's asleep, don't try to run through him */
X    else 
X      AVOID (mlist[i].mrow, mlist[i].mcol, '$')
X  }
X  
X  /* Don't avoid current position */
X  avdmonsters[searchstartr][searchstartc] = 0;
X  dwait (D_SEARCH, "Avoidmonsters: avoiding the $s");
X}
X
X/* 
X * caddycorner: Find sqaures the monster can reach before we can and mark
X * them for avoidance
X */
X
Xcaddycorner (r, c, d1, d2, ch)
Xint r,c,d1,d2;
Xchar ch;
X{ while (onrc (CANGO, r, c))
X  { AVOID (r, c, ch);
X    r += deltr[d1]; c += deltc[d1];
X    if (!onrc (CANGO, r, c)) break;
X    AVOID (r, c, ch);
X    r += deltr[d2]; c += deltc[d2];
X  }
X}
X
X/*
X *   E S T A B L I S H   A V O I D A N C E   M A P   when pinned
X *
X * This routine is basically the same as avoidmonsters, except that
X * the value are calculated to allow the monster one hit instead of
X * avoiding him entirely. This allows us to escape from situations where
X * we are pinned, but could get free if we had an extra turn.   MLM
X */
X
Xpinavoid ()
X{ register int i;
X
X  /* Clear old avoid monster values */
X  for (i = 24*80; i--; ) avdmonsters[0][i] = 0;
X
X  /* Avoid each monster in turn */
X  for (i=0; i<mlistlen; i++)
X  { if (mlist[i].q == AWAKE) 
X    { register int d, dr, dc, mr = mlist[i].mrow, mc = mlist[i].mcol;
X      d = direc (searchstartr-mr,searchstartc-mc);
X      dr = (searchstartr-mr)/2+mr - deltr[d];		/* MLM */
X      dc=(searchstartc-mc)/2+mc - deltc[d];		/* MLM */
X      if (d & 1)
X      { caddycorner (dr, dc, (d-1) & 7, (d-3)&7, '&');
X        caddycorner (dr, dc, (d+1) & 7, (d+3)&7, '&');
X      }
X      else 
X      { caddycorner (dr, dc, (d-2) & 7, (d-4) & 7, '&'); /* MLM */
X        caddycorner (dr, dc, (d+2) & 7, (d+4) & 7, '&'); /* MLM */
X      }
X    }
X    AVOID (mlist[i].mrow, mlist[i].mcol, '&');
X  }
X  
X  /* Don't avoid current position */
X  avdmonsters[searchstartr][searchstartc] = 0;
X  dwait (D_SEARCH, "Pinavoid: avoiding the &s");
X}
X
X/*
X *   S E C R E T : Search dead ends for secret doors.
X */
X
Xsecret ()
X{ int secretinit(), secretvalue();
X  
X  /* Secret passage adjacent to door? */
X  if (version >= RV53A && on (DOOR) && !blinded &&
X      (seerc (' ',atrow+1,atcol) || seerc (' ',atrow-1,atcol) ||
X       seerc (' ',atrow,atcol+1) || seerc (' ',atrow,atcol-1)) &&
X      SEARCHES (atrow, atcol) < timestosearch+20)
X  { int count = timessearched[atrow][atcol]+1;
X    saynow ("Searching dead end door (%d,%d) for the %d%s time...", 
X              atrow, atcol, count, ordinal (count));
X    command (T_DOORSRCH, "s"); return (1);
X  }
X
X  /* Verify that we are actually at a dead end */
X  if (onrc (CANGO,atrow-1,atcol) + onrc (CANGO,atrow,atcol-1) + 
X      onrc (CANGO,atrow+1,atcol) + onrc (CANGO,atrow,atcol+1) != CANGO)
X    return (0);
X
X  /* If Level 1 or edge of screen: dead end cannot be room, mark and return */
X  if (Level == 1 && attempt == 0 ||
X      version < RV53A && (atrow<=1 || atrow>=22 || atcol<=0 || atcol>=79))
X  { markexplored (atrow, atcol); return (0); }
X
X  /* Have we mapped this level? */
X  if (Level == didreadmap) return (0);
X
X  /* Found a dead end, should we search it? */
X  if (nexttowall (atrow, atcol) ||
X      canbedoor (atrow, atcol) && 
X      (version >= RV53A || !isexplored (atrow, atcol)))
X  { setrc (DEADEND, atrow, atcol);
X
X    if ((SEARCHES (atrow, atcol) - timessearched[atrow][atcol]) > 0)
X    { int count = timessearched[atrow][atcol]+1;
X      saynow ("Searching dead end (%d,%d) for the %d%s time...", 
X              atrow, atcol, count, ordinal (count));
X      command (T_DOORSRCH, "s");
X      return (1);
X    }
X    else
X    { markexplored (atrow, atcol);
X      return (0);
X    }
X  }
X
X  return (0);
X}
X
X/* 
X *   F I N D R O O M :  Try to find another room.
X */
X
Xfindroom ()
X{ int expinit(), expvalue();    /* LGCH */
X
X  if (new_findroom)
X  { if (!on (ROOM) && secret ())			return (1);
X    if (makemove (EXPLORE, expinit, expvalue, REUSE))	return (1);
X  }
X
X  new_findroom = 0;
X  dwait (D_SEARCH, "findroom failed.");
X  return (0);
X}
X
X/* 
X *   E X P L O R E   R O O M :  Explore the current room.
X */
X
Xexploreroom ()
X{ int roominit(), expvalue();    /* LGCH */
X
X  if (!on (ROOM) || isexplored (atrow, atcol)) return (0);
X  if (makemove (EXPLOREROOM, roominit, expvalue, REUSE)) return (1);
X  markexplored (atrow, atcol);
X
X  dwait (D_SEARCH, "exploreroom failed.");
X  return (0);
X}
X
X/*
X *   D O O R E X P L O R E : look for secret doors
X */
X
Xdoorexplore()
X{ static searchcount = 0;
X  int secretinit(), secretvalue();
X
X  /* If no new squares or read map, dont bother */
X  if (! new_search || Level == didreadmap)
X  { searchcount = 0; return (0); }
X
X  if (makemove (SECRETDOOR, secretinit, secretvalue, REUSE))  /* move */
X  { searchcount = 0; return (1); }
X
X  if (searchcount > 20)
X  { new_search = 0; return (0); }
X
X  if (ontarget)  /* Moved to a possible secret door, search it */
X  { searchcount++;
X    saynow ("Searching square (%d,%d) for the %d%s time...", 
X            atrow, atcol, searchcount, ordinal (searchcount));
X    command (T_DOORSRCH, "s");
X    return (1);
X  }
X
X  new_search = searchcount = 0;
X  return (0);
X}
X
X/*
X *   S A F E   S Q U A R E   S E A R C H 	Use genericinit.
X */
X
Xsafevalue (r, c, depth, val, avd, cont)
Xint r, c, depth, *val, *avd, *cont;
X{ register int k, v;
X
X  *avd = onrc (SAFE, r, c)    ? 0 :
X	 onrc (TRAPDOR | BEARTRP | GASTRAP, r, c) ? INFINITY :
X	 onrc (ARROW, r, c)   ? 50 :
X         onrc (TELTRAP, r, c) ? 50 :
X         onrc (DARTRAP, r, c) ? 200 :
X         onrc (WATERAP, r, c) ? 50 :
X         onrc (MONSTER, r, c) ? 150 :
X         expavoidval;
X  *val = 0;
X
X  if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj)
X    *avd += 500;
X
X  if (onrc(CANGO, r, c))
X  { v = 0;
X    for (k=0; k<8; k++)
X      if (onrc(CANGO, r+deltr[k], c+deltc[k]) &&
X          onrc(CANGO, r+deltr[k], c) &&
X          onrc(CANGO, r, c+deltc[k])) v++;
X    if (v < 3)
X      *val = 1;        /* *cont = 0; // default // */
X  }
X  return (1);
X}
X
X/* findsafe: find a spot with 2 or fewer moves, for when blinded */
X
Xfindsafe()
X{ 
X  return (makemove (FINDSAFE, genericinit, safevalue, REEVAL));
X}
X
X/* How scared are we of hitting a trap? */
X
Xavoid ()
X{ if (cheat && !foundarrowtrap && !usingarrow) return (0);
X  else if (Level < 5) return (0);       /* Don't bother */
X  else return (2);                      /* Avoid a little */
X}
X
X/*
X * archery: Initialize a archery move. We find a good place to
X * shoot from and stand there. Then mark the monster as awake, and 
X * battlestations will handle firing at him.
X */
X
Xstatic int archrow = NONE, archcol = NONE, archturns = NONE, archval[24][80];
X
Xarchmonster (m, turns)
Xregister int m;		/* Monster to attack */
Xregister int turns;	/* Minimum number of arrows to make it worthwhile */
X{ int archeryinit(), archeryvalue();
X  register int mr, mc;
X
X  dwait (D_CONTROL | D_BATTLE, "archmonster: m=%d, turns=%d", m, turns);
X
X  if (! new_arch) return (0);
X
X  /* Useless without arrows */
X  if (havemult (missile, "", turns) < 0) 
X  { dwait (D_BATTLE, "archmonster, fewer than %d missiles", turns); 
X    return (0); }
X
X  /* For now, only work for sleeping monsters */
X  if (mlist[m].q != ASLEEP) 
X  { dwait (D_BATTLE, "archmonster, monster not asleep"); return (0); }
X
X  /* Save globals */
X  archrow = mlist[m].mrow; archcol = mlist[m].mcol; archturns = turns;
X
X  /* Can we get to a suitable square */
X  if (makemove (ARCHERYMOVE, archeryinit, archeryvalue, REUSE))
X  { dwait (D_BATTLE, "archmonster, made a move"); return (1); }
X
X  /* If no move made and not on target, no path to monster */
X  if (!ontarget) { new_arch = 0; return (0); }
X
X  /* On target: wake him up and set darkdir/turns if necessary */
X  mr = mlist[m].mrow; mc = mlist[m].mcol; targetmonster = mlist[m].chr;
X  mlist[m].q = AWAKE; dwait (D_BATTLE, "archmonster, waking him up"); 
X    
X  /* Set dark room archery variables, add goal of standing on square */
X  if (darkroom ())
X  { darkdir = direc (mr-atrow, mc-atcol);
X    darkturns = max (abs (mr-atrow), abs (mc-atcol));
X    agoalr = mr; agoalc = mc;	/* Go here to pick up what (s)he drops */
X  }
X
X  /* Tell the user about it */
X  saynow ("Arching at %s", monname (mlist[m].chr));
X
X  return (1);
X}
X
X/*
X * archeryinit: Initialize a archery move. Must avoid monsters to avoid
X * waking our potential victim up.
X */
X
Xarcheryinit ()
X{ register int dir, r, c, dr, dc, dist;
X
X   /* Clear the archery value array */
X  for (r = 24*80; r--; ) archval[0][r] = 0;
X
X  /* Scan around monster to see how far away we can shoot from */
X  for (dir = 0; dir < 8; dir++)
X  { dr = deltr[dir]; dc = deltc[dir];
X    for (dist = 1, r = archrow+dr, c = archcol+dc;
X         onrc (CANGO | HALL | MONSTER, r, c) == CANGO;
X	 r += dr, c += dc, dist++)
X      if (dist > archturns && !onrc (TRAP, r, c))
X      { archval[r][c] = dist - 1; /* number of arrows we get to shoot */
X        if (debug (D_SCREEN)) { at (r, c); addch ('=');  at (row, col); }
X      }
X  }
X
X  expavoidval = avoid();
X  avoidmonsters ();
X  return (1);
X}
X
X/*
X * archeryvalue: Get the value of the square from the archery array.
X * Value is non-zero only if we can fire arrows at beast and value is
X * number of shots we can fire.
X */
X
Xarcheryvalue (r, c, depth, val, avd, cont)
Xint r, c, depth, *val, *avd, *cont;
X{ 
X  *avd = (onrc (SAFE, r, c)	? 0 :
X	  onrc (TRAPDOR, r, c)	? INFINITY :
X	  onrc (HALL, r, c)	? INFINITY :
X	  onrc (ARROW, r, c)	? 50 :
X          onrc (TELTRAP, r, c)	? 50 :
X          onrc (GASTRAP, r, c)	? 50 :
X          onrc (BEARTRP, r, c)	? 50 :
X          onrc (DARTRAP, r, c)	? 200 :
X          onrc (WATERAP, r, c)	? 50 :
X          onrc (MONSTER, r, c)	? 150 :
X          expavoidval) + avdmonsters[r][c];
X
X  if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj)
X    *avd += 500;
X
X  *val = archval[r][c];
X  *cont = INFINITY;
X
X  return (1);
X}
X
X/* 
X *   M O V E   T O   R E S T :  Find a safe square to rest up on.
X */
X
Xstatic restinlight = 0;			/* True only in lit rooms */
Xstatic restinroom = 0;			/* True only in a room */
Xstatic restr = NONE, restc = NONE;	/* Square to rest on */
X
X/* Set new resting goal */
Xunrest ()
X{ restr = restc = NONE;
X}
X
X/* Move to a good square to rest up on */
Xmovetorest ()
X{ int restinit(), restvalue();    /* LGCH */
X
X  if (markcycles (NOPRINT))
X    unrest ();
X
X  /* If we are where we want to rest, do so */
X  if (restr >= 0 && atrow == restr && atcol == restc)
X  { dwait (D_SEARCH, "movetorest: already on square"); return (0); }
X
X  /* Try to move to a better square (remember position) */
X  if (makemove (RESTMOVE, restinit, restvalue, REUSE))
X  { dwait (D_SEARCH, "movetorest wins.");
X    restr = targetrow; restc = targetcol;
X    return (1);
X  }
X
X  /* Cant move anywhere better, stay here */
X  dwait (D_SEARCH, "movetorest fails.");
X  restr = atrow; restc = atcol;
X
X  return (0);
X}
X
Xrestinit ()
X{ expavoidval = avoid();
X  restinlight = (on (ROOM) && !darkroom ());
X  restinroom = on (ROOM);
X  return (1);
X}
X
Xrestvalue (r, c, depth, val, avd, cont)
Xregister int r, c;
Xint depth, *val, *avd, *cont;
X{ register int dr, dc, ar, ac;
X  int count, dir, rm;
X
X  /* Find room number for diagonal selection */
X  if ((rm = whichroom (r, c)) < 0) rm = 4;
X
X  /* Default is no value, no avoidance */
X  *avd = *val = 0;
X
X  /* Set base value of square */
X  if (onrc (TRAP|MONSTER,r, c))               { *avd = INFINITY; return (0); }
X  else if (restinroom && onrc (DOOR,r, c))    { *avd = INFINITY; return (0); }
X  else if (onrc (SCAREM, r, c))
X  { if (objcount == maxobj || version >= RV53A) { *val = 500; return (1); }
X    else                                      { *avd = INFINITY; return (0); }
X  }
X  else if (onrc (STAIRS, r, c))               { *val = 400; return (1); }
X  else if (onrc (ROOM, r, c))                 { *val = 1; *cont = 99;}
X  else if (!onrc (SAFE|BEEN|STUFF, r, c))     { *avd = 5; }
X
X  /* Give bonus for being next to a trap door or a teleport trap */
X  if (onrc (TRAPDOR|TELTRAP, r-1, c-1) || onrc (TRAPDOR|TELTRAP, r+1, c-1) ||
X      onrc (TRAPDOR|TELTRAP, r-1, c+1) || onrc (TRAPDOR|TELTRAP, r+1, c+1))
X  { *val += 80; *cont = 99;}
X
X  if (onrc (TRAPDOR|TELTRAP, r-1, c) || onrc (TRAPDOR|TELTRAP, r+1, c) ||
X      onrc (TRAPDOR|TELTRAP, r, c-1) || onrc (TRAPDOR|TELTRAP, r, c+1))
X  { *val += 30; *cont = 99;}
X
X  /* In lit rooms (with ammo) stay away from doors, this gives us time */
X  /* to shoot arrows at monsters coming in at us          MLM 06/21/83 */
X  if (restinlight && ammo)
X  { for (dir = 0; dir < 8; dir += 2)
X    { dr = deltr[dir]; dc = deltc[dir];
X      for (count = 0, ar = r+dr, ac = c+dc;
X           onrc (CANGO | HALL | MONSTER, ar, ac) == CANGO;
X           ar += dr, ac += dc, count++)
X      { /* Bonus of 'count' if this square covers a door */
X        if (onrc(DOOR,ar+deltr[(dir+2)%8],ac+deltc[(dir+2)%8])) *val += count;
X        if (onrc(DOOR,ar+deltr[(dir+6)%8],ac+deltc[(dir+6)%8])) *val += count;
X        if (onrc(DOOR,ar,ac)) *val += count;
X      }
X    }
X  }
X
X  /* In dark rooms, stand diagonally away from doors (1 extra turn) */
X  else if (onrc (ROOM, r, c))
X  { if (onrc (DOOR,r-1,c-1) && (rm!=0 && rm!=1 && rm!=3)) {*val+=80;*cont=99;}
X    if (onrc (DOOR,r+1,c-1) && (rm!=3 && rm!=6 && rm!=7)) {*val+=80;*cont=99;}
X    if (onrc (DOOR,r-1,c+1) && (rm!=1 && rm!=2 && rm!=5)) {*val+=80;*cont=99;}
X    if (onrc (DOOR,r+1,c+1) && (rm!=5 && rm!=7 && rm!=8)) {*val+=80;*cont=99;}
X
X    /* Bonus for door also orthogonally away */
X    if(onrc(DOOR,r,c-1)||onrc(DOOR,r-1,c)||onrc(DOOR,r,c+1)||onrc(DOOR,r+1,c))
X    { *val+=30; *cont=99; }
X  }
X
X  return (1);
X}
/
echo 'x - utility.c'
sed 's/^X//' > utility.c << '/'
X/*
X * utility.c: Rog-O-Matic XIV (CMU) Thu Jan 31 18:18:22 1985 - mlm
X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin
X *
X * This file contains all of the miscellaneous system functions which
X * determine the baud rate, time of day, etc.
X */
X
X# include <sgtty.h>
X# include <stdio.h>
X# include <signal.h>
X# include <sys/types.h>
X# include <sys/stat.h>
X
X# include "install.h"
X
X# ifdef BSD41
X#     include <time.h>
X# else
X#     include <sys/time.h>
X# endif
X
X# define TRUE 1
X# define FALSE 0
X
X/*
X * baudrate: Determine the baud rate of the terminal
X */
X
Xbaudrate ()
X{ static short  baud_convert[] =
X  { 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600 };
X  static struct sgttyb  sg;
X  static short  baud_rate;
X
X  gtty (fileno (stdin), &sg);
X  baud_rate = sg.sg_ospeed == 0 ? 1200
X    : sg.sg_ospeed < sizeof baud_convert / sizeof baud_convert[0]
X    ? baud_convert[sg.sg_ospeed] : 9600;
X
X  return (baud_rate);
X}
X
X/*
X * stlmatch  --  match leftmost part of string
X *
X *  Usage:  i = stlmatch (big,small)
X *	int i;
X *	char *small, *big;
X *
X *  Returns 1 iff initial characters of big match small exactly;
X *  else 0.
X *
X *  HISTORY
X * 18-May-82 Michael Mauldin (mlm) at Carnegie-Mellon University
X *      Ripped out of CMU lib for Rog-O-Matic portability
X * 20-Nov-79  Steven Shafer (sas) at Carnegie-Mellon University
X *	Rewritten for VAX from Ken Greer's routine.
X *
X *  Originally from klg (Ken Greer) on IUS/SUS UNIX
X */
X
Xint   stlmatch (big, small)
Xchar *small, *big;
X{ register char *s, *b;
X  s = small;
X  b = big;
X  do
X  { if (*s == '\0')
X      return (1);
X  }
X  while (*s++ == *b++);
X  return (0);
X}
X
X/*
X * getname: get userid of player.
X */
X
Xchar *getname ()
X{ static char name[100];
X  int   i;
X
X  getpw (getuid (), name);
X  i = 0;
X  while (name[i] != ':' && name[i] != ',')
X    i++;
X  name[i] = '\0';
X
X  return (name);
X}
X
X/*
X *  putenv  --  put value into environment
X *
X *  Usage:  i = putenv (name,value)
X *	int i;
X *	char *name, *value;
X *
X *  Putenv associates "value" with the environment parameter "name".
X *  If "value" is 0, then "name" will be deleted from the environment.
X *  Putenv returns 0 normally, -1 on error (not enough core for malloc).
X *
X *  Putenv may need to add a new name into the environment, or to
X *  associate a value longer than the current value with a particular
X *  name.  So, to make life simpler, putenv() copies your entire
X *  environment into the heap (i.e. malloc()) from the stack
X *  (i.e. where it resides when your process is initiated) the first
X *  time you call it.
X *
X *  HISTORY
X * 25-Nov-82 Michael Mauldin (mlm) at Carnegie-Mellon University
X *      Ripped out of CMU lib for Rog-O-Matic portability
X * 20-Nov-79  Steven Shafer (sas) at Carnegie-Mellon University
X *	Created for VAX.  Too bad Bell Labs didn't provide this.  It's
X *	unfortunate that you have to copy the whole environment onto the
X *	heap, but the bookkeeping-and-not-so-much-copying approach turns
X *	out to be much hairier.  So, I decided to do the simple thing,
X *	copying the entire environment onto the heap the first time you
X *	call putenv(), then doing realloc() uniformly later on.
X *	Note that "putenv(name,getenv(name))" is a no-op; that's the reason
X *	for the use of a 0 pointer to tell putenv() to delete an entry.
X *
X */
X
X#define EXTRASIZE 5		/* increment to add to env. size */
X
Xchar *index (), *malloc (), *realloc ();
Xint   strlen ();
X
Xstatic int  envsize = -1;	/* current size of environment */
Xextern char **environ;		/* the global which is your env. */
X
Xstatic int  findenv ();		/* look for a name in the env. */
Xstatic int  newenv ();		/* copy env. from stack to heap */
Xstatic int  moreenv ();		/* incr. size of env. */
X
Xint   putenv (name, value)
Xchar *name, *value;
X{ register int  i, j;
X  register char *p;
X
X  if (envsize < 0)
X  {				/* first time putenv called */
X    if (newenv () < 0)		/* copy env. to heap */
X      return (-1);
X  }
X
X  i = findenv (name);		/* look for name in environment */
X
X  if (value)
X  {				/* put value into environment */
X    if (i < 0)
X    {				/* name must be added */
X      for (i = 0; environ[i]; i++);
X      if (i >= (envsize - 1))
X      {				/* need new slot */
X	if (moreenv () < 0)
X	  return (-1);
X      }
X      p = malloc (strlen (name) + strlen (value) + 2);
X      if (p == 0)		/* not enough core */
X	return (-1);
X      environ[i + 1] = 0;	/* new end of env. */
X    }
X    else
X    {				/* name already in env. */
X      p = realloc (environ[i],
X	  strlen (name) + strlen (value) + 2);
X      if (p == 0)
X	return (-1);
X    }
X    sprintf (p, "%s=%s", name, value);/* copy into env. */
X    environ[i] = p;
X  }
X  else
X  {				/* delete name from environment */
X    if (i >= 0)
X    {				/* name is currently in env. */
X      free (environ[i]);
X      for (j = i; environ[j]; j++);
X      environ[i] = environ[j - 1];
X      environ[j - 1] = 0;
X    }
X  }
X
X  return (0);
X}
X
Xstatic int  findenv (name)
Xchar *name;
X{ register char *namechar, *envchar;
X  register int  i, found;
X
X  found = 0;
X  for (i = 0; environ[i] && !found; i++)
X  { envchar = environ[i];
X    namechar = name;
X    while (*namechar && (*namechar == *envchar))
X    { namechar++;
X      envchar++;
X    }
X    found = (*namechar == '\0' && *envchar == '=');
X  }
X  return (found ? i - 1 : -1);
X}
X
Xstatic int  newenv ()
X{ register char **env, *elem;
X  register int  i, esize;
X
X  for (i = 0; environ[i]; i++);
X  esize = i + EXTRASIZE + 1;
X  env = (char **) malloc (esize * sizeof (elem));
X  if (env == 0)
X    return (-1);
X
X  for (i = 0; environ[i]; i++)
X  { elem = malloc (strlen (environ[i]) + 1);
X    if (elem == 0)
X      return (-1);
X    env[i] = elem;
X    strcpy (elem, environ[i]);
X  }
X
X  env[i] = 0;
X  environ = env;
X  envsize = esize;
X  return (0);
X}
X
Xstatic int  moreenv ()
X{ register int  esize;
X  register char **env;
X
X  esize = envsize + EXTRASIZE;
X  env = (char **) realloc (environ, esize * sizeof (*env));
X  if (env == 0)
X    return (-1);
X  environ = env;
X  envsize = esize;
X  return (0);
X}
X
X/*
X * wopen: Open a file for world access.
X */
X
XFILE *wopen(fname, mode)
Xchar *fname, *mode;
X{ int oldmask;
X  FILE *newlog;
X
X  oldmask = umask (0111);
X  newlog = fopen (fname, mode);
X  umask (oldmask);
X
X  return (newlog);  
X}
X
X/*
X * fexists: return a boolean if the named file exists
X */
X
Xfexists (fn)
Xchar *fn;
X{ struct stat pbuf;
X
X  return (stat (fn, &pbuf) == 0);
X}
X
X/*
X * filelength: Do a stat and return the length of a file.
X */
X
Xint filelength (f)
X{ struct stat sbuf;
X
X  if (stat (f, &sbuf) == 0)
X    return (sbuf.st_size);
X  else
X    return (-1);
X}
X
X/*
X * critical: Disable interrupts
X */
X
Xstatic int   (*hstat)(), (*istat)(), (*qstat)();
X
Xcritical ()
X{
X  hstat = signal (SIGHUP, SIG_IGN);
X  istat = signal (SIGINT, SIG_IGN);
X  qstat = signal (SIGQUIT, SIG_IGN);
X}
X
X/*
X * uncritical: Enable interrupts
X */
X
Xuncritical ()
X{
X  signal (SIGHUP, hstat);
X  signal (SIGINT, istat);
X  signal (SIGQUIT, qstat);
X}
X
X/*
X * reset_int: Set all interrupts to default
X */
X
Xreset_int ()
X{
X  signal (SIGHUP, SIG_DFL);
X  signal (SIGINT, SIG_DFL);
X  signal (SIGQUIT, SIG_DFL);
X}
X
X/*
X * int_exit: Set up a function to call if we get an interrupt
X */
X
Xint_exit (exitproc)
Xint (*exitproc)();
X{
X  if (signal (SIGINT, SIG_IGN) != SIG_IGN)  signal (SIGINT, exitproc);
X  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN) signal (SIGPIPE, exitproc);
X  if (signal (SIGQUIT, SIG_IGN) != SIG_IGN) signal (SIGQUIT, exitproc);
X}
X
X/*
X * lock_file: lock a file for a maximum number of seconds.
X *            Based on the method used in Rogue 5.2.
X */
X
X# define NOWRITE 0
X
Xlock_file (lokfil, maxtime)
Xchar *lokfil;
Xint maxtime;
X{ int try;
X  struct stat statbuf;
X  time_t time ();
X
X  start:
X  if (creat (lokfil, NOWRITE) > 0)
X    return TRUE;
X
X  for (try = 0; try < 60; try++)
X  { sleep (1);
X    if (creat (lokfil, NOWRITE) > 0)
X      return TRUE;
X  }
X
X  if (stat (lokfil, &statbuf) < 0)
X  { creat (lokfil, NOWRITE);
X    return TRUE;
X  }
X
X  if (time (NULL) - statbuf.st_mtime > maxtime)
X  { if (unlink (lokfil) < 0)
X      return FALSE;
X    goto start;
X  }
X  else
X    return FALSE;
X}
X
X/*
X * unlock_file: Unlock a lock file.
X */
X
Xunlock_file (lokfil)
Xchar *lokfil;
X{ unlink (lokfil);
X}
X
X/*
X * quit: Defined for compatibility with Berkeley 4.2 system
X */
X
Xquit (code, fmt, a1, a2, a3, a4)
Xint code, a1, a2, a3, a4;
Xchar *fmt;
X{
X  fprintf (stderr, fmt, a1, a2, a3, a4);
X  exit (code);
X}
/
echo 'Part 02 of Rog-O-Matic XIV complete.'
exit



More information about the Comp.sources.unix mailing list