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

Michael Mauldin mlm at cmu-cs-cad.ARPA
Sat Feb 2 02:27:20 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 03 of 10:'
echo 'x - mess.c'
sed 's/^X//' > mess.c << '/'
X/*
X * mess.c: Rog-O-Matic XIV (CMU) Thu Jan 31 15:33:12 1985 - mlm
X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin
X *
X * mess.c: This file contains all of the functions which parse the 
X * message line.
X */
X
X# include <curses.h>
X# include <ctype.h>
X# include "types.h"
X# include "globals.h"
X
X/* Matching macros */
X# define MATCH(p) smatch(mess,p,result)
X
X/* Local data recording statistics */
Xstatic int monkilled[] = {
X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Xstatic int totalkilled=0, timeshit=0, timesmissed=0, hits=0, misses=0;
Xstatic int sumgold=0, sumsqgold=0, numgold=0;
X
Xstatic mhit=0, mmiss=0, mtarget= NONE;
X
X/* Other local data */
Xidentifying = 0;		/* Next message is from identify scroll */
Xstatic int justreadid = 0;	/* True if just read identify scroll */
Xstatic int gushed = 0;		/* True ==> water on the head msg recently */
Xstatic int echoit;		/* True ==> echo this message to the user */
X
X/* Results from star matcher */
Xstatic char res1[NAMSIZ], res2[NAMSIZ], res3[NAMSIZ], res4[NAMSIZ];
Xstatic char *result[] = { res1, res2, res3, res4 };
X
X/*
X * terpmes: called when a message from Rogue is on the top line, 
X * this function parses the message and notes the information.
X * Note that the messages are all lower cased, to help with 
X * compatability bewtween 3.6 and 5.2, since 5.2 capitalizes more
X * messages than does 3.6.  Trailing punctuation is also ignored.
X * 
X * As of Rogue 5.3, multiple messages are broken into single
X * messages before being passed to parsemsg.  Periods separate
X * multiple messages.
X */
X
Xterpmes ()
X{ char mess[128];
X  register char *m, *mend, *s = screen[0], *t;
X
X  /* Set 't' to the tail of the message, skip backward over blank & dot */  
X  for (t=s+79; *t==' ' || *t=='.'; t--) ;	/* Find last non-blank */
X  t++;						/* t -> beyond string */
X  
X  /* 
X   * Loop through each message, finding the beginning and end, and 
X   * copying it to mess, lower-casing it as we go. Then call parsemsg.
X   */
X 
X  while (s<t)				      /* While more chars in msg */
X  { while (*s==' ' && s<t) s++;			/* Skip leading blanks */
X    for (m = mess;				/* Copy text */
X	 s<t && (version < RV53A || *s != '.');
X	 s++)	
X      *m++ = isupper (*s) ? tolower (*s) : *s;	  /* Lower case the char */
X    s++;					/* Skip the period, if any */
X    *(mend = m) = '\0';				/* Add trailing null */
X    if (mess != mend) parsemsg (mess, mend);	/* Parse it */
X  }
X}
X
X/* 
X * parsemsg: Parse a single message, and if necessary set variables
X * or call functions.
X */
X
Xparsemsg (mess, mend)
Xregister char *mess, *mend;
X{ int unknown = 0;
X
X  echoit = 1;
X
X  /*----------------Take action based on type of message-------------*/
X
X  if (MATCH("was wearing *")) ;
X
X  /* Message indicates we picked up a new item */
X  else if (mend[-1]==')' && mend[-3]=='(')
X  { inventory (mess, mend); identifying = justreadid = 0; }
X
X  /* Message describes an old item already in our pack */
X  else if (mess[1]==')')
X  { echoit = identifying; identifying = justreadid = 0; inventory(mess,mend); }
X
X  /* A random message, switch of first char to save some time... */
X  else switch (mess[0])
X  { case 'a':
X      if (MATCH("as you read the scroll, it vanishes")) echoit=0;
X      else if (MATCH("a cloak of darkness falls around you"))
X      { infer ("blindness"); blinded=1; }
X      else if (MATCH("a teleport trap")) nametrap (TELTRAP,NEAR);
X      else if (MATCH("a trapdoor")) nametrap (TRAPDOR,NEAR);
X      else if (MATCH("an arrow shoots *"))
X      { arrowshot=1; nametrap(ARROW,HERE); }
X      else if (MATCH("an arrow trap")) nametrap (ARROW,NEAR);
X      else if (MATCH("a beartrap")) nametrap (BEARTRP,NEAR);
X      else if (MATCH("a strange white mist *")) nametrap (GASTRAP,HERE);
X      else if (MATCH("a sleeping gas trap")) nametrap (GASTRAP,NEAR);
X      else if (MATCH("a small dart *")) nametrap (DARTRAP,HERE);
X      else if (MATCH("a dart trap")) nametrap (DARTRAP,NEAR);
X      else if (MATCH("a poison dart trap")) nametrap (DARTRAP,NEAR);
X      else if (MATCH("a rust trap")) nametrap (WATERAP,NEAR);
X      else if (MATCH("a gush of water hits you on the head")) gushed++;
X      else if (MATCH("a sting has weakened you")) ;
X      else if (MATCH("a bite has weakened you")) ;
X      else if (MATCH("a ring *")) ;
X      else if (MATCH("a wand *")) ;
X      else if (MATCH("a staff *")) ;
X      else if (MATCH("a scroll *")) ;
X      else if (MATCH("a potion *")) ;
X      else if (MATCH("a +*")) ;
X      else if (MATCH("a -*")) ;
X      else unknown++;
X      break;
X
X    case 'b':
X      if (MATCH("bolt bounces")) infer ("lightning");
X      else if (MATCH("bolt hits")) infer ("lightning");
X      else if (MATCH("bolt misses")) infer ("lightning");
X      else if (MATCH("bummer, this food tastes awful")) ;
X      else if (MATCH("bummer!  you've hit the ground")) floating=0;
X      else if (MATCH("bite has no effect")) ;
X      else unknown++;
X      break;
X
X    case 'c': 
X      if (MATCH("call it*")) echoit=0;   /* Handled in getrogue() */
X      else unknown++;
X      break;
X
X    case 'd':
X      if (MATCH("defeated the *")) { echoit=0; killed(res1); }
X      else if (MATCH("defeated it")) { echoit=0; killed("it"); }
X      else if (MATCH("defeated *")) { echoit=0; killed(res1); }
X      else if (MATCH("drop what*")) echoit=0;
X      else if (MATCH("dropped *")) ;
X      else unknown++;
X      break;
X
X    case 'e':
X      if (MATCH("eat what*")) echoit=0;
X      else if (MATCH("everything looks so boring now")) cosmic=0;
X      else unknown++;
X      break;
X
X    case 'f': 
X      if (MATCH("flame *")) ;
X      else if (MATCH("far out!  everything is all cosmic again")) blinded=0;
X      else unknown++;
X      break;
X
X    case 'g':
X      if (MATCH("getting hungry")) echoit=0;
X      else if (MATCH("getting the munchies")) echoit=0;
X      else unknown++;
X      break;
X
X    case 'h':
X      if (MATCH("hey, this tastes great*")) infer ("restore strength");
X      else if (MATCH("huh? what? who?")) ;
X      else if (MATCH("heavy!  that's a nasty critter!")) ;
X      else unknown++;
X      break;
X
X    case 'i':
X      if (MATCH("it hit")) { washit ("it"); echoit=0; }
X      else if (MATCH("it misses"))  { wasmissed ("it"); echoit=0; }
X      else if (MATCH("it appears confused")) ;
X      else if (MATCH("ice *")) ;
X      else if (MATCH("identify what*")) echoit=0;
X      else if (MATCH("illegal command*")) echoit=0;
X      else if (MATCH("i see no way*")) {unset(STAIRS); findstairs();}
X      else if (MATCH("it appears to be cursed")) curseditem ();
X      else if (MATCH("it make*")) ;
X      else unknown++;
X      break;
X
X    case 'j':
X    case 'k':
X      unknown++;
X      break;
X
X    case 'l':
X      if (MATCH("left or*")) echoit=0;
X      else unknown++;
X      break;
X
X    case 'm':
X      if (MATCH("missile vanishes")) infer ("magic missile");
X      else if (MATCH("missle vanishes")) infer ("magic missile");
X      else if (MATCH("my, that was a yummy *")) ;
X      else if (MATCH("moved onto *")) set (STUFF);
X      else unknown++;
X      break;
X
X    case 'n':
X      if (MATCH("nothing happens")) inven[lastwand].charges = 0;
X      else if (MATCH("no more *")) ;
X      else if (MATCH("nothing appropriate")) ;
X      else if (MATCH("no room")) ;
X      else unknown++;
X      break;
X
X    case 'o':
X      if (MATCH("oh no! an arrow shot *"))
X      { arrowshot=1; nametrap(ARROW,HERE); }
X      else if (MATCH("oh, now this scroll has a map *"))
X      { infer ("magic mapping"); didreadmap = Level; }
X      else if (MATCH("oh, bummer!  everything is dark!  help!"))
X      { infer ("blindness"); blinded=1; }
X      else if (MATCH("oh, wow!  everything seems so cosmic!"))
X      { infer ("hallucination"); cosmic=1; }
X      else if (MATCH("oh, wow!  you're floating in the air!"))
X      { infer ("levitation"); floating=1; }
X      else if (MATCH("oh, wow, that tasted good")) ;
X      else unknown++;
X      break;
X
X    case 'p':
X      if (MATCH("please spec*")) echoit=0;
X      else if (MATCH("put on what*")) echoit=0;
X      else unknown++;
X      break;
X
X    case 'q':
X      if (MATCH("quaff what*")) echoit=0;
X      else unknown++;
X      break;
X
X    case 'r':
X      if (MATCH("range is 'a' to '*'")) 
X      { echoit=0;
X        if (*res1-'a'+1 != invcount)
X        { dwait (D_INFORM, "Range check failed..."); usesynch = 0; }
X      }
X      else if (MATCH("read what*")) echoit=0;
X      else unknown++;
X      break;
X
X    case 's':
X      if (MATCH("she stole *")) usesynch = 0;
X      else if (MATCH("sting has no effect")) ;
X      else unknown++;
X      break;
X
X    case 't':
X      if (MATCH("throw what*")) echoit=0;
X      else if (MATCH("the * bounces")) ;
X      else if (MATCH("the bolt *")) ;
X      else if (MATCH("the flame *")) ;
X      else if (MATCH("the ice hits")) ;
X      else if (MATCH("the ice misses")) ;
X      else if (MATCH("the ice whizzes by you")) wasmissed ("ice monster");
X      else if (MATCH("the * hits it")) {echoit=0; mshit ("it");}
X      else if (MATCH("the * misses it")) {echoit=0; msmiss ("it");}
X      else if (MATCH("the * hits the *")) {echoit=0; mshit (res2);}
X      else if (MATCH("the * misses the *")) {echoit=0; msmiss (res2);}
X      else if (MATCH("the * hit")) { washit (res1); gushed=0; echoit=0; }
X      else if (MATCH("the * misses")) { wasmissed (res1); echoit=0; }
X      else if (MATCH("the * appears confused")) ;
X      else if (MATCH("the rust vanishes instantly"))
X      { if (gushed) { gushed = 0; nametrap (WATERAP, HERE); } }
X      else if (MATCH("the room is lit")) { setnewgoal (); infer ("light"); }
X      else if (MATCH("the * has confused you")) confused = 1;
X      else if (MATCH("this scroll is an * scroll"))
X      { if (stlmatch (res1, "identify")) readident (res1); }
X      else if (MATCH("that's not a valid item"))
X      { echoit = justreadid < 1; if (justreadid-- == 0) sendnow (" *");
X        if (justreadid < -50) dwait (D_FATAL, "Caught in invalid item loop"); }
X      else if (MATCH("the veil of darkness lifts")) blinded=0;
X      else if (MATCH("the scroll turns to dust*")) 
X      { deletestuff (atrow, atcol); unset(SCAREM | STUFF); droppedscare--; }
X      else if (MATCH("this potion tastes * dull")) infer ("thirst quenching");
X      else if (MATCH("this potion tastes pretty")) infer ("thirst quenching");
X      else if (MATCH("this potion tastes like apricot juice"))
X      { infer ("see invisible"); if (version == RV36A) sendnow ("%c", ESC); }
X      else if (MATCH("this scroll seems to be blank")) infer ("blank paper");
X      else if (MATCH("the * bounces")) ;
X      else if (MATCH("the * vanishes as it hits the ground"))
X      { darkturns = 0; darkdir = NONE; targetmonster = 0; echoit=0; }
X      else if (MATCH("there is something here*")) { usesynch=0; set(STUFF); }
X      else if (MATCH("the munchies are interfering*")) ;
X      else if (MATCH("the monsters around you freeze")) holdmonsters ();
X      else if (MATCH("the monster freezes")) holdmonsters ();
X      else if (MATCH("that's inedible")) usesynch = 0; 
X      else unknown++;
X      break;
X
X    case 'u':
X    case 'v':
X      unknown++;
X      break;
X
X    case 'w':
X      if (MATCH("what do you want*")) echoit=0;
X      else if (MATCH("wield what*")) echoit=0;
X      else if (MATCH("wielding a*")) echoit=0;
X      else if (MATCH("wear what*")) echoit=0;
X      else if (MATCH("what monster*")) echoit=0;
X      else if (MATCH("wait, what's going*")) {infer("confusion"); confused=1;}
X      else if (MATCH("wait!  that's a *")) ;
X      else if (MATCH("what a*feeling*")) { infer("confusion"); confused=1; }
X      else if (MATCH("what a*piece of paper")) infer ("blank paper");
X      else if (MATCH("welcome to level *")) ;
X      else if (MATCH("was wearing*")) ;
X      else if (MATCH("what bulging muscles*")) ;
X      else if (MATCH("wearing *")) ;
X      else unknown++;
X      break;
X
X    case 'x':
X      unknown++;
X      break;
X
X    case 'y':
X      if (MATCH("you hit*")) { echoit=0; didhit (); }
X      else if (MATCH("you miss*")) { echoit=0; didmiss (); }
X      else if (MATCH("you are starting to feel weak")) echoit=0;
X      else if (MATCH("you are weak from hunger")) {echoit=0; eat();}
X      else if (MATCH("you are being held")) beingheld=30;
X      else if (MATCH("you can move again")) echoit=0;
X      else if (MATCH("you are still stuck *")) nametrap (BEARTRP,HERE);
X      else if (MATCH("you can't move")) echoit=0;
X      else if (MATCH("you can't carry anything else"))
X      { echoit=0; set (STUFF); maxobj=objcount; }
X      else if (MATCH("you can't *")) {echoit=0; curseditem ();}
X      else if (MATCH("you can't")) echoit=0;
X      else if (MATCH("you begin to feel better")) infer ("healing");
X      else if (MATCH("you begin to feel much better")) infer("extra healing");
X      else if (MATCH("you begin to sense the presence of monsters"))
X      { infer("monster detection"); }
X      else if (MATCH("you feel a strange sense of loss")) ;
X      else if (MATCH("you feel stronger, now*")) infer ("gain strength");
X      else if (MATCH("you feel very sick now")) infer ("poison");
X      else if (MATCH("you feel momentarily sick")) infer ("poison");
X      else if (MATCH("you suddenly feel much more skillful"))
X      { infer("raise level"); }
X      else if (MATCH("your nose tingles")) infer ("food detection");
X      else if (MATCH("you start to float in the air"))
X      { infer ("levitation"); floating=1; }
X      else if (MATCH("you're floating off the ground!")) floating=1;
X      else if (MATCH("you float gently to the ground")) floating=0;
X      else if (MATCH("you feel yourself moving much faster"))
X      { infer ("haste self"); hasted = 1; }
X      else if (MATCH("you feel yourself slowing down")) 
X      { hasted = 0; doublehasted = 0; }
X      else if (MATCH("you faint from exhaustion"))
X      { if (version < RV52A) doublehasted = 1; else hasted = 0; }
X      else if (MATCH("you feel less confused now")) confused = 0;
X      else if (MATCH("you feel less trip*")) confused = 0;
X      else if (MATCH("your * vanishes as it hits the ground"))
X      { darkturns = 0; darkdir = NONE; echoit=0; }
X      else if (MATCH("your hands begin to glow *"))
X      { infer ("monster confusion"); redhands = 1; }
X      else if (MATCH("your hands stop glowing *")) redhands = 0;
X      else if (MATCH("you feel as if somebody is watching over you") ||
X               MATCH("you feel in touch with the universal onenes")) 
X      { infer ("remove curse"); cursedarmor = cursedweapon = 0; 
X        newarmor = newweapon = 1;}
X      else if (MATCH("your armor weakens"))
X      { inven[currentarmor].phit--; 
X        if (gushed) { gushed=0; nametrap (WATERAP,HERE); } }
X      else if (MATCH("your armor is covered by a shimmering * shield"))
X      { infer ("protect armor"); protected++;
X	remember (currentarmor, PROTECTED); }
X      else if (MATCH("your armor glows * for a moment"))
X      { infer ("enchant armor"); inven[currentarmor].phit++;
X        cursedarmor = 0; newarmor = 1; }
X      else if (MATCH("your * glows * for a moment"))
X      { infer ("enchant weapon"); plusweapon (); newweapon = 1; }
X      else if (MATCH("you hear a high pitched humming noise")) 
X      { infer ("aggravate monsters"); wakemonster (9); aggravated = 1; }
X      else if (MATCH("you hear maniacal laughter*")) infer ("scare monster");
X      else if (MATCH("you hear a faint cry*")) infer ("create monster");
X      else if (MATCH("you fall asleep")) infer ("sleep");
X      else if (MATCH("you have been granted the boon of genocide"))
X      { infer ("genocide"); echoit=0; rampage (); }
X      else if (MATCH("you have a tingling feeling")) infer ("drain life");
X      else if (MATCH("you are too weak to use it")) infer ("drain life");
X      else if (MATCH("you begin to feel greedy")) infer ("gold detection");
X      else if (MATCH("you feel a pull downward")) infer ("gold detection");
X      else if (MATCH("you begin to feel a pull downward"))
X      { infer ("gold detection"); }
X      else if (MATCH("you are caught *")) nametrap (BEARTRP,HERE);
X      else if (MATCH("your purse feels lighter")) ;
X      else if (MATCH("you suddenly feel weaker")) ;
X      else if (MATCH("you must identify something")) ;
X      else if (MATCH("you have a * feeling for a moment, then it passes")) ;
X      else if (MATCH("you are transfixed")) ;
X      else if (MATCH("you are frozen")) washit ("ice monster");
X      else if (MATCH("you faint")) {echoit=0; if (version<RV36B) eat();}
X      else if (MATCH("you freak out")) echoit = 0;
X      else if (MATCH("you fell into a trap!")) ;
X      else if (MATCH("yum*")) echoit=0;
X      else if (MATCH("yuk*")) echoit=0;
X      else if (MATCH("you sense the presence of magic*")) echoit=0;
X      else unknown++;
X      break;
X
X    case 'z':
X      if (MATCH("zap with what*")) echoit=0;
X      else unknown++;
X      break;
X
X    default:
X      if (MATCH( "* gold pieces")) { echoit=0; countgold (res1); }
X      else if (MATCH("'*'*: *")) { echoit=0; mapcharacter (*res1, res3); }
X      else if (*mess == '+' || *mess == '-' || ISDIGIT (*mess)) ;
X      else unknown++;      
X      break;
X  }
X
X  /* Log unknown or troublesome messages */
X  if (morecount > 50)	dwait (D_WARNING, "More loop msg '%s'", mess);
X  else if (unknown)	dwait (D_WARNING, "Unknown message '%s'", mess);
X
X  /* Send it to dwait; if dwait doesnt print it (and echo is on) echo it */
X  if (echoit & !dwait (D_MESSAGE, mess))
X    saynow (mess);
X}
X
X/* 
X * smatch: Given a data string and a pattern containing one or
X * more embedded stars (*) (which match any number of characters)
X * return true if the match succeeds, and set res[i] to the
X * characters matched by the 'i'th *.
X */
X
Xsmatch (dat, pat, res)
Xregister char *dat, *pat, **res;
X{ register char *star = 0, *starend, *resp;
X  int nres = 0;
X
X  while (1)
X  { if (*pat == '*')
X    { star = ++pat; 			     /* Pattern after * */
X      starend = dat; 			     /* Data after * match */
X      resp = res[nres++]; 		     /* Result string */
X      *resp = '\0'; 			     /* Initially null */
X    }
X    else if (*dat == *pat) 		     /* Characters match */
X    { if (*pat == '\0') 		     /* Pattern matches */
X	return (1);
X      pat++; 				     /* Try next position */
X      dat++;
X    }
X    else
X    { if (*dat == '\0') 		     /* Pattern fails - no more */
X	return (0); 			     /* data */
X      if (star == 0) 			     /* Pattern fails - no * to */
X	return (0); 			     /* adjust */
X      pat = star; 			     /* Restart pattern after * */
X      *resp++ = *starend; 		     /* Copy character to result */
X      *resp = '\0'; 			     /* null terminate */
X      dat = ++starend; 			     /* Rescan after copied char */
X    }
X  }
X}
X
X/*
X * readident: read an identify scroll.
X */
X
Xreadident (name)
Xchar *name;
X{ int obj; char id = '*';	/* Default is "* for list" */
X
X  if (!replaying && version <= RV53A &&
X      (nextid < LETTER (0) || nextid > LETTER (invcount))) 
X  { dwait (D_FATAL, "Readident: nextid %d, afterid %d, invcount %d.",
X           nextid, afterid, invcount); }
X
X  infer (name);		/* Record what kind of scroll this is */
X
X  if (version < RV53A)		/* Rogue 3.6, Rogue 5.2 */
X  { deleteinv (OBJECT (afterid));	/* Assume object gone */
X    sendnow (" %c", nextid);		/* Identify it */
X    send ("I%c", afterid);		/* Generate a message about it */
X    knowident = identifying = 1;	/* Set variables */
X  }
X  else				/* Rogue 5.3 */
X  { if (streq (name, "identify scroll"))
X    { if ((obj = unknown (scroll)) != NONE || (obj = have (scroll)) != NONE)
X        id = LETTER (obj);
X    }
X    else if (streq (name, "identify potion"))
X    { if ((obj = unknown (potion)) != NONE || (obj = have (potion)) != NONE)
X        id = LETTER (obj);
X    }
X    else if (streq (name, "identify armor"))
X    { if ((obj = unknown (armor)) != NONE || (obj = have (armor)) != NONE)
X        id = LETTER (obj);
X    }
X    else if (streq (name, "identify weapon"))
X    { if ((obj = unknown (hitter)) != NONE ||
X	  (obj = unknown (thrower)) != NONE || 
X          (obj = unknown (missile)) != NONE ||
X	  (obj = have (hitter)) != NONE ||
X          (obj = have (thrower)) != NONE ||
X	  (obj = have (missile)) != NONE)
X        id = LETTER (obj);
X    }
X    else if (streq (name, "identify ring, wand or staff"))
X    { if ((obj = unknown (ring)) != NONE || (obj = unknown (wand)) != NONE ||
X          (obj = have (ring)) != NONE    || (obj = have (wand)) != NONE)
X        id = LETTER (obj);
X    }
X    else dwait (D_FATAL, "Unknown identify scroll '%s'", name);
X
X    waitfor ("not a valid item"); waitfor ("--More--");
X    sendnow (" %c;", id);		/* Pick an object to identify */
X    usesynch = 0; justreadid=1;		/* Must resest inventory */
X  }
X
X  newring = newweapon = 1; afterid = nextid = '\0';
X}
X
X/*
X * rampage: read a scroll of genocide.
X */
X 
Xrampage ()
X{ char monc;
X
X  /* Check the next monster in the list, we may not fear him */ 
X  while (monc = *genocide)
X  { /* Do not waste genocide on stalkers if we have the right ring */
X    if ((streq (monname (monc), "invisible stalker") ||
X         streq (monname (monc), "phantom")) &&
X        havenamed (ring, "see invisible") != NONE)
X    { genocide++; }
X
X    /* Do not waste genocide on rusties if we have the right ring */
X    else if ((streq (monname (monc), "rust monster") || 
X              streq (monname (monc), "aquator")) &&
X             havenamed (ring, "maintain armor") != NONE)
X    { genocide++; }
X    
X    /* No fancy magic for this monster, use the genocide scroll */
X    else break;
X  }
X
X  /* If we found a monster, send his character, else send ESC */
X  if (monc)
X  { saynow ("About to rampage against %s", monname (monc));
X    sendnow (" %c;", monc);	/* Send the monster */
X
X    /* Add to the list of 'gone' monsters */
X    sprintf (genocided, "%s%c", genocided, monc);
X    genocide++;
X  }
X  else
X  { dwait (D_ERROR, "Out of monsters to genocide!");
X    sendnow (" %c;", ESC);	/* Cancel the command */
X  }
X}
X
X/*
X * curseditem: the last object we tried to drop (unwield, etc.)  was cursed.
X *
X * Note that cursed rings are not a problem since we only put on
X * Good rings we have identified, so dont bother marking rings.
X */
X
Xcurseditem ()
X{ usesynch = 0;    /* Force a reset inventory */
X
X  /* lastdrop is index of last item we tried to use which could be cursed */
X  if (lastdrop != NONE && lastdrop < invcount)
X  { remember (lastdrop, CURSED);
X
X    /* Is our armor cursed? */
X    if (inven[lastdrop].type == armor)
X    { currentarmor = lastdrop; cursedarmor = 1; return; }
X    
X    /* Is it our weapon (may be wielding a hitter or a bogus magic arrow)? */
X    else if (inven[lastdrop].type==hitter || inven[lastdrop].type==missile)
X    { currentweapon = lastdrop; cursedweapon = 1; return; }
X  }
X
X  /* Dont know what was cursed, so assume the worst */
X  cursedarmor=1;
X  cursedweapon=1; 
X}
X
X/* 
X * First copy the title of the last scroll into the appropriate slot,  
X * then find the real name of the object by looking through the data
X * base, and then zap that name into all of the same objects 
X */
X
Xinfer (roguename)
Xchar *roguename;
X{ register int i;
X
X  if (*lastname && *roguename && !stlmatch (roguename, lastname))
X  { infername (lastname, roguename);
X  
X    for (i=0; i<MAXINV; i++)
X      if (stlmatch (inven[i].str, lastname))
X      { strcpy (inven[i].str, roguename);
X        remember (i, KNOWN);
X      }
X  }  
X}
X
X/*
X * Killed: called whenever we defeat a monster.
X */
X
Xkilled (monster)
Xregister char *monster;
X{ register int m = 0, mh = 0;
X
X  /* Find out what we really killed */
X  if (!cosmic && !blinded && targetmonster>0 && streq (monster, "it"))
X  { monster = monname (targetmonster); }
X  if ((mh = getmonhist (monster, 0)) != NONE)
X  { monster = monhist[mh].m_name; m = monsternum (monster); }
X
X  /* Tell the user what we killed */
X  dwait (D_BATTLE | D_MONSTER, "Killed '%s'", monster);
X
X  /* If cheating against Rogue 3.6, check out our arrow */
X  if (version < RV52A && cheat)
X  { if (usingarrow && hitstokill > 1 && !beingstalked && goodarrow < 20)
X    { saynow ("Oops, bad arrow...");
X      newweapon = badarrow = 1; remember (currentweapon, WORTHLESS); }
X    else if (usingarrow) goodarrow++;
X  }
X
X  /* Echo the number arrows we pumped into him */
X  if (mh >=0 && mhit+mmiss > 0 && mtarget == mh)
X    dwait (D_BATTLE | D_MONSTER, "%d out of %d missiles hit the %s", 
X           mhit, mhit+mmiss, monster);
X
X  /* If we killed it by hacking, add the result to long term memory */
X  if (hitstokill > 0 && mh != NONE)
X    addstat (&monhist[mh].htokill, hitstokill); 
X
X  /* If we killed it with arrows, add that fact to long term memory */
X  if (mhit > 0 && mh != NONE)
X    addstat (&monhist[mh].atokill, mhit);
X
X  /* Stop shooting arrows if we killed the right monster */
X  if (targetmonster == (m+'A'-1))
X  { darkturns = 0; darkdir = NONE; targetmonster = 0; }
X
X  goalr = goalc = NONE;			/* Clear old movement goal */
X  killmonster (m+'A'-1);		/* Notify lost monster functions */
X  monkilled[m]++; totalkilled++;	/* Bump kill count */
X  hitstokill = mhit = mmiss = 0;	/* Clear indiviual monster stats */
X  mtarget = NONE;				/* Clear target */
X  beingheld = cancelled = 0;		/* Clear flags */
X
X  /* If we killed an invisible, assume no more invisible around */
X  if (!cosmic && !blinded &&
X      (streq (monster, "invisible stalker") || streq (monster, "phantom")))
X    beingstalked = 0;
X}
X
X/*
X * washit: Record being hit by a monster.
X */
X
Xwashit (monster)
Xchar *monster;
X{ register int mh = 0, m = 0;
X
X  /* Find out what really hit us */
X  if ((mh = getmonhist (monster, 1)) != NONE)
X  { monster = monhist[mh].m_name; m = monsternum (monster); }
X
X  dwait (D_MONSTER, "was hit by a '%s'", monster);
X
X  timeshit++;			/* Bump global count */
X  if (m>0) wakemonster(-m);	/* Wake him up */
X  terpbot ();			/* Hit points changed, read bottom */
X
X  /* Add data about the event to long term memory */
X  if (mh != NONE)
X  { addprob (&monhist[mh].theyhit, SUCCESS);
X    addstat (&monhist[mh].damage, lastdamage);
X    analyzeltm ();
X  }
X}
X
X/*
X * wasmissed: Record being missed by a monster.
X */
X
Xwasmissed (monster)
Xchar *monster;
X{ register int mh = 0, m = 0;
X
X  /* Find out what really missed us */
X  if ((mh = getmonhist (monster, 1)) != NONE)
X  { monster = monhist[mh].m_name; m = monsternum (monster); }
X
X  dwait (D_MONSTER, "was missed by a '%s'", monster);
X
X  timesmissed++;		/* Bump global count */
X  if (m>0) wakemonster(-m);	/* Wake him up */
X
X  /* Add data to long term memory */
X  if (mh != NONE)
X  { addprob (&monhist[mh].theyhit, FAILURE);
X    analyzeltm ();
X  }
X}
X
X/*
X * didhit: Record hitting a monster.
X */
X
Xdidhit ()
X{ register int m = 0;
X
X  /* Record our hit */
X  if (!cosmic) m = lastmonster;
X
X  hits++; hitstokill++;
X  addprob (&monhist[monindex[m]].wehit, SUCCESS);
X
X  if (wielding (wand))
X  { inven[currentweapon].charges--; newweapon++; }
X}
X
X/*
X * didmiss: Record missing a monster.
X */
X
Xdidmiss ()
X{ register int m = 0;
X
X  /* Record our miss */
X  if (!cosmic) m = lastmonster;
X
X  misses++;
X  addprob (&monhist[monindex[m]].wehit, FAILURE);
X
X  if (usingarrow && goodarrow < 20)
X  { newweapon = badarrow = 1; remember (currentweapon, WORTHLESS); }
X}
X
X/*
X * mshit: Record hitting a monster with a missile.
X */
X
Xmshit (monster)
Xchar *monster;
X{ register int mh;
X
X  /* Arching in a dark room? */
X  if (!cosmic && !blinded && targetmonster > 0 && streq (monster, "it"))
X    monster = monname (targetmonster);
X
X  /* Add data about the event to long term memory */
X  if ((mh = getmonhist (monster, 0)) < 0) return;
X  { addprob (&monhist[monindex[mh]].arrowhit, SUCCESS);
X    if (mh == mtarget) { mhit++; }
X    else { mhit=1; mmiss = 0; mtarget=mh; }
X  }
X}
X
X/*
X * msmiss: Record missing a monster with a missile.
X */
X
Xmsmiss (monster)
Xchar *monster;
X{ register int mh;
X
X  /* Arching in a dark room? */
X  if (!cosmic && !blinded && targetmonster > 0 && streq (monster, "it"))
X    monster = monname (targetmonster);
X
X  /* Add data about the event to long term memory */
X  if ((mh = getmonhist (monster, 0)) < 0) return;
X  { addprob (&monhist[monindex[mh]].arrowhit, FAILURE);
X    if (mh == mtarget) { mmiss++; }
X    else { mmiss=1; mhit=0; mtarget=mh; }
X  }
X}
X
X/*
X * Countgold: called whenever msg contains a message about the number
X *            of gold pieces we just picked up. This routine keeps
X *            statistics about the amount of gold picked up.
X */
X
Xcountgold (amount)
Xregister char *amount;
X{ int pot;
X
X  if ((pot = atoi (amount)) > 0)
X  { sumgold += pot; sumsqgold += pot*pot; numgold ++; }
X}
X
X/* 
X * Summary: print a summary of the game.
X */
X
Xsummary (f, sep)
XFILE *f;
Xchar sep;
X{ register int m;
X  char s[1024], *monname ();
X
X  sprintf (s, "Monsters killed:%c%c", sep, sep);
X
X  for (m=0; m<=26; m++)
X    if (monkilled[m] > 0)
X    { sprintf (s, "%s\t%d %s%s%c", s, monkilled[m],  monname (m+'A'-1),
X               plural (monkilled[m]), sep);
X    }
X
X  sprintf (s, "%s%cTotal: %d%c%c", s, sep, totalkilled, sep, sep);
X  
X  sprintf (s, "%sHit %d out of %d times, was hit %d out of %d times.%c", s,
X           hits, misses+hits,
X           timeshit, timesmissed+timeshit, sep);
X
X  if (numgold > 0)
X    sprintf (s, "%sGold %d total, %d pots, %d average.%c",  s,
X             sumgold, numgold, (sumgold*10+5) / (numgold*10), sep);
X
X  if (f == NULL)
X    addstr (s);
X  else
X    fprintf (f, "%s", s);
X}
X
X/*
X * versiondep: Set version dependent variables.
X */
X
Xversiondep ()
X{
X  if (version >= RV53A)		genocide = "DMJGU";
X  else if (version >= RV52A)	genocide = "UDVPX";
X  else				genocide = "UXDPW";  
X
X  analyzeltm ();
X}
X
X/* 
X * getmonhist: Retrieve the index in the history array of a monster,
X * taking our status into account.  This code is responsible for determining
X * when we are being stalked by an invisible monster.
X */
X
Xgetmonhist (monster, hitormiss)
Xchar *monster;
Xint hitormiss;
X{ if (cosmic || blinded)
X  { return (findmonster ("it")); }
X  else
X  { if (streq (monster, "it") && hitormiss)
X    { if (version < RV53A)
X      { if (! seemonster ("invisible stalker")) beingstalked=INVHIT;
X        return (findmonster ("invisible stalker"));
X      }
X      else
X      { if (! seemonster ("phantom")) beingstalked=INVHIT;
X	return (findmonster ("phantom"));
X      }
X    }
X    else
X    { if (version < RV52B && streq (monster, "invisible stalker") &&
X          ! seemonster (monster))
X	beingstalked = INVHIT;
X      return (findmonster (monster));
X    }
X  }
X}
/
echo 'x - search.c'
sed 's/^X//' > search.c << '/'
X/*
X * search.c: Rog-O-Matic XIV (CMU) Mon Jan 28 18:28:07 1985 - mlm
X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin
X *
X * This file contains the very basic search mechanisms for exploration etc.
X */
X
X# include <stdio.h>
X# include <curses.h>
X# include "types.h"
X# include "globals.h"
X
X# define QSIZE (4000)
X
X# define QUEUEBREAK  (111)
X# define FROM         (20)
X# define UNREACHABLE  (12)
X# define NOTTRIED     (11)
X# define TARGET       (10)
X
Xstatic int moveavd[24][80], moveval[24][80], movecont[24][80],
X	movedepth[24][80];
Xstatic char mvdir[24][80];
Xstatic int mvtype=0;
Xstatic int didinit=0;
X
X/* 
X * makemove: repeat move from here towards some sort of target.
X * Modified to use findmove.			5/13	MLM
X */
X
Xmakemove (movetype, evalinit, evaluate, reevaluate)
Xint movetype, (*evalinit)(), (*evaluate)(), reevaluate;
X{ 
X  if (findmove (movetype, evalinit, evaluate, reevaluate))
X    return (followmap (movetype));
X
X  return (0);
X}
X
X/* 
X * findmove: search for a move of type movetype.  The move map is left in
X *           the correct state for validatemap or followmap to work.	MLM
X */
X
Xfindmove (movetype, evalinit, evaluate, reevaluate)
Xint movetype, (*evalinit)(), (*evaluate)(), reevaluate;
X{ int result;
X
X  didinit = ontarget = 0;
X
X  if (!reevaluate)		/* First try to reuse the movement map */
X  { result = validatemap (movetype, evalinit, evaluate);
X    if (result == 1) return (1);	/* Success */
X    if (result == 2) return (0);	/* Evalinit failed, no move */
X  }
X
X  /* Must rebuild the movement map */
X  mvtype = 0;	/* Will become 'if (mvtype==movetype) movetype=0;' */
X
X  dwait (D_SEARCH, "Findmove: computing new search path.");
X
X  /* currentrectangle(); */     /* always done after each move of the rogue */
X
X  searchstartr = atrow; searchstartc = atcol;
X
X  if (!(*evalinit)())    /* Compute evalinit from current location */
X  { dwait (D_SEARCH, "Findmove: evalinit failed."); return (0); }
X
X  if (!searchfrom (atrow, atcol, evaluate, mvdir, &targetrow, &targetcol))
X  { return (0); }	/* move failed */
X
X  if (targetrow == atrow && targetcol == atcol)
X  { ontarget = 1; return (0); }
X
X  /* <<copy the newly created map to save*[][]>> */
X  mvtype = movetype;	/* mvtype will be the type of saved map */
X
X  return (1);
X}
X
X/* 
X * followmap: Assuming that the mvdir map is correct, send a movement
X *            command following the map (possibly searching first).
X *
X *	<<Must be changed to use the saved map, when that code is added>>
X *
X * May 13, MLM
X */
X
Xfollowmap (movetype)
Xregister int movetype;
X{ register int dir, dr, dc, r, c;
X  int timemode, searchit, count=1;
X
X  dir=mvdir[atrow][atcol]-FROM; dr=deltr[dir]; dc=deltc[dir];
X
X  if (dir > 7 || dir < 0)
X  { dwait (D_ERROR, "Followmap: direction invalid!");
X    return (0);			      /* Something Broke */
X  }
X
X  r=atrow+dr; c=atcol+dc;		/* Save next square in registers */
X
X  /* If exploring and are moving to a new hall square, use fmove */
X  if (movetype == EXPLORE &&
X      onrc (HALL|BEEN, targetrow, targetcol) != HALL|BEEN &&
X      onrc (HALL,r,c))
X  { fmove (dir); return (1); }
X
X  /* Timemode tells why we are moving this way, T_RUNNING ==> no search */
X  timemode = (movetype == GOTOMOVE)    ? T_MOVING :
X             (movetype == EXPLORE)     ? T_EXPLORING :
X             (movetype == EXPLOREROOM) ? T_EXPLORING :
X             (movetype == FINDROOM)    ? T_EXPLORING :
X             (movetype == EXPLORERUN)  ? T_RUNNING :
X             (movetype == RUNTODOOR)   ? T_RUNNING :
X             (movetype == RUNAWAY)     ? T_RUNNING :
X             (movetype == UNPIN)       ? T_RUNNING :
X             (movetype == UNPINEXP)    ? T_RUNNING :
X             (movetype == RUNAWAY)     ? T_RUNNING :
X             (movetype == RUNDOWN)     ? T_RUNNING :
X             (movetype == ATTACKSLEEP) ? T_FIGHTING :  T_MOVING;
X
X  /* How many times do we wish to search each square before moving? */
X  /* Search up to k times if 2 or more foods and deeper than level 6 */
X  searchit = max (0, min (k_srch/20, min (larder - 1, Level - 6)));
X
X  /* Can we move more than one square at a time? */
X  if (compression)
X  { while (mvdir[r][c]-FROM==dir && (onrc (SAFE, r+=dr, c+=dc) || !searchit))
X      count++;
X  }
X
X  /* Maybe search unsafe square before moving onto it */
X  if (timemode != T_RUNNING && !onrc (SAFE, atrow+dr, atcol+dc) &&
X      timessearched[atrow+dr][atcol+dc] < searchit)
X  { command (T_SEARCHING, "s"); return (1); }
X
X  /* Maybe take armor off before stepping on rust trap */
X  if (timemode != T_RUNNING && onrc (WATERAP, atrow+dr, atcol+dc) &&
X      currentarmor != NONE && willrust () && takeoff ())
X  { rmove (1, dir, timemode); return (1); }
X  
X  /* If we are about to step onto a scare monster scroll, use the 'm' cmd */
X  if (version >= RV53A && onrc (SCAREM, atrow+dr, atcol+dc))
X  { mmove (dir, timemode); return (1); }
X
X  /* Send the movement command and return success */
X  rmove (count, dir, timemode); return (1);
X}
X
X/*
X * validatemap: If we have a stored move, make it and return true.
X *
X *	<<Must be changed to use the saved map, when that code is added>>
X *
X * Called only by findmove.	MLM
X */
X
Xvalidatemap (movetype, evalinit, evaluate)
Xint movetype, (*evalinit)(), (*evaluate)();
X{ register int thedir, dir, r, c;
X  int val, avd, cont;
X
X  dwait (D_CONTROL | D_SEARCH, "Validatemap: type %d", movetype);
X
X  if (mvtype != movetype)
X  { dwait (D_SEARCH, "Validatemap: move type mismatch, map invalid.");
X    return (0);
X  }
X
X  thedir = mvdir[atrow][atcol] - FROM;
X  if (thedir > 7 || thedir < 0)
X  { dwait (D_SEARCH, "Validatemap: direction in map invalid.");
X    return (0);  /* Something Broke */
X  }
X
X  /*
X   * Check that the planned path is still valid.  This is done by
X   * proceeding along it and checking that the value and avoidance
X   * returned from the evaluation function are the same as
X   * when the search was first performed.  The initialisation function
X   * is re-performed and then the evaluation function done.
X   */
X
X  if (!didinit && !(*evalinit)())
X  { dwait (D_SEARCH, "Validatemap: evalinit failed.");
X    return (2);  /* evalinit failed */
X  }
X  didinit=1;
X
X  r=atrow; c=atcol;
X  while (1)
X  { val = avd = cont = 0;
X    if (!(*evaluate)(r, c, movedepth[r][c], &val, &avd, &cont))
X    { dwait (D_SEARCH, "Validatemap: evaluate failed.");
X      return (0);
X    }
X    if (!onrc (CANGO, r, c) ||
X        avd!=moveavd[r][c] || val!=moveval[r][c] || cont!=movecont[r][c])
X    { dwait (D_SEARCH, "Validatemap: map invalidated.");
X      return (0);
X    }
X    if ((dir=mvdir[r][c]-FROM) == TARGET)
X    { dwait (D_SEARCH, "Validatemap: existing map validated.");
X      break;
X    }
X    if (dir < 0 || dir > 7)
X    { dwait (D_SEARCH, "Validatemap: direction in map invalid.");
X      return (0);
X    }
X    r += deltr[dir];  c += deltc[dir];
X  }
X  return (1);
X}
X
X/*
X * cancelmove: Invalidate all stored moves of a particular type.
X */
X
Xcancelmove (movetype)
Xint movetype;
X{ if (movetype == mvtype) mvtype = 0;
X}
X
X/*
X * setnewgoal: Invalidate all stored moves.
X */
X
Xsetnewgoal ()
X{ mvtype = 0;
X  goalr = goalc = NONE;
X}
X
X/* 
X * searchfrom: By means of breadth first search, find a path
X * from the given row and column to a target.  This is done by using
X * searchto and then reversing the path to the row, col from the selected
X * target.  Note that this means that the resultant direction map can
X * only be re-used if the new row, col is on the existing path.  The
X * reversed path consists of directions offset by FROM.
X * arguments and results otherwise the same as searchto.	LGCH
X */
X
Xsearchfrom (row, col, evaluate, dir, trow, tcol)
Xint row, col, *trow, *tcol;
Xint (*evaluate)();
Xchar dir[24][80];
X{ register int r, c, sdir, tempdir;
X  if (!searchto (row, col, evaluate, dir, trow, tcol))
X  { return (0);
X  }
X
X  for (r = *trow, c = *tcol, sdir = FROM+TARGET; ; )
X  { tempdir = dir[r][c];
X    dir[r][c] = sdir;
X    if (debug (D_SCREEN | D_INFORM | D_SEARCH))
X    { at (r, c);  printw ("%c", ">/^\\</v\\  ~"[sdir-FROM]);}
X    sdir = (tempdir + 4) % 8 + FROM;  /* reverse direction and offset */
X    if (tempdir == TARGET) break;
X    r += deltr[tempdir];  c += deltc[tempdir];
X  }
X  dwait (D_SEARCH, "Searchfrom wins.");
X  return (1);
X}
X
X/*
X * searchto: By means of a breadth first search, find a path to the
X * given row and column from a target.  A target is defined as a
X * location which has +ve value returned by the evaluation function and
X * for which the avoidance value has been decremented to zero. The most
X * valuable target found in the first successful iteration of the
X * search, is selected. (i.e. the most valuable square at the lowest
X * level of the search).  Returns dir the direction map of paths to
X * row,col from target Also returns trow, tcol the position of the
X * selected target (NOTE: To use this search directly, e.g. to find
X * paths to a single actual target such as the staircase, the
X * evaluation function should give zero value to everything except the
X * current Rog-O-Matic location To re-use the results of a search,
X * ensure that dir[row][col] is still set to TARGET and check that a
X * valid direction exists at the target position.)
X *
X * The search prefers horizontal movements to vertical movements, and
X * prefers moves onto SAFE squares to moves onto other squares.	       LGCH
X */
X
X/* 
X * Since this code is the single most time consuming subroutine, I am
X * attempting to hack it into a faster form. 			11/6/82 MLM
X */
X
Xsearchto (row, col, evaluate, dir, trow, tcol)
Xint row, col, *trow, *tcol;
Xint (*evaluate)();
Xchar dir[24][80];
X{ int searchcontinue = 10000000, type, havetarget=0, depth=0;
X  register int r, c, nr, nc;
X  register int k;
X  char begin[QSIZE], *end, *head, *tail;
X  int saveavd[24][80], val, avd, cont;
X  int any;
X  static int sdirect[8] = {4, 6, 0, 2, 5, 7, 1, 3},
X	     sdeltr[8]  = {0,-1, 0, 1,-1,-1, 1, 1},
X	     sdeltc[8]  = {1, 0,-1, 0, 1,-1,-1, 1};
X
X  head = tail = begin;
X  end = begin + QSIZE;
X
X  for (c = 23*80; c--; ) dir[0][c] = NOTTRIED;		/* MLM */
X  for (c = 80; c--; ) dir[0][c] = 0;			/* MLM */
X
X  *(tail++) = row;  *(tail++) = col; 
X  *(tail++) = QUEUEBREAK;  *(tail++) = QUEUEBREAK;
X  dir[row][col] = TARGET;  moveval[row][col] = NONE;
X  any = 1;
X
X  while (1)
X  { /* Process the next queued square. */
X    r = *(head++);  c = *(head++);
X    if (head == end) head = begin;  /* wrap-around queue */
X
X    if (r==QUEUEBREAK)
X    { /* If we have completed an evaluation loop */
X      if (searchcontinue <= 0 || !any)
X      { if (havetarget) dwait (D_SEARCH, "Searchto wins.");
X	else dwait (D_SEARCH, "Searchto fails.");
X	
X        return (havetarget);  /* have found somewhere to go */
X      }
X
X      searchcontinue--;   depth++;
X
X      /* ----------------------------------------------------------------
X      if (debug (D_SCREEN))
X        dwait (D_SEARCH, "Searchto: at queue break, cont=%d, havetarget=%d",
X	       searchcontinue, havetarget);
X      ---------------------------------------------------------------- */
X
X      any = 0;    /* None found in queue this time round */
X
X      *(tail++) = QUEUEBREAK;  *(tail++) = QUEUEBREAK;
X      if (tail == end) tail = begin;
X      continue;
X    }
X
X    any = 1;   /* Something in queue */
X
X    if (moveval[r][c] == NONE)
X    { /* unevaluated: evaluate it */
X      val = avd = cont = 0;
X      if ((*evaluate)(r,c,depth,&val,&avd,&cont)) /* Evaluate it. */
X      { movedepth[r][c] = depth;
X        moveavd[r][c] = avd;
X        moveval[r][c] = val;
X	movecont[r][c] = cont;
X
X        if (avd >= INFINITY)
X        { /* Infinite avoidance */
X	  dir[r][c]=UNREACHABLE;  /* we cant get here */
X	  continue;	/* discard the square from consideration. */
X        }
X        else
X        { saveavd[r][c]=avd;
X        }
X      }
X      else 		/* If evaluate fails, forget it for now. */
X      { dwait (D_SEARCH, "Searchto: evaluate failed.");
X	continue;
X      }
X    }
X
X    if (saveavd[r][c])
X    { /* If to be avoided, leave in queue for a while */
X      *(tail++) = r;  *(tail++) = c;   --(saveavd[r][c]);  /* Dec avoidance */
X      if (tail == end) tail = begin;
X      continue;
X    }
X
X    if (moveval[r][c] > havetarget)
X    { /* It becomes the target if it has value bigger than the best found
X      so far, and if it has a non-zero value.
X       */
X
X      if (debug (D_SCREEN | D_SEARCH | D_INFORM))
X      { mvprintw (r, c, "=");
X	dwait (D_SEARCH, "Searchto: target value %d.", moveval[r][c]);
X      }
X      searchcontinue = movecont[r][c];
X      *trow = r;  *tcol = c;  havetarget = moveval[r][c];
X    }
X
X    type = SAFE;
X    while (1)
X    { for (k=0; k<8; k++)
X      { register int S;
X
X	/* examine adjacent squares. */
X	nr = r + sdeltr[k];
X	nc = c + sdeltc[k];
X	S = scrmap[nr][nc];
X
X	/* IF we have not considered stepping on the square yet */
X	/* and if it is accessible    THEN: Put it on the queue */
X        if (dir[nr][nc] == NOTTRIED && (CANGO&S) && (type&S) == type &&
X	    (k<4 || onrc (CANGO,r,nc) && onrc (CANGO,nr,c)))
X        { moveval[nr][nc] = NONE;  /* flag unevaluated */
X
X	  *(tail++) = nr;  *(tail++) = nc; if (tail == end) tail = begin;
X
X	  dir[nr][nc] = sdirect[k];  /* direction we used to get here */
X
X	  if (debug (D_SCREEN | D_SEARCH | D_INFORM))
X	  { at (nr, nc); printw ("%c", ">/^\\</v\\  ~"[dir[nr][nc]]);}
X        }
X      }
X      if (type == 0) break;
X      type = 0;
X    }
X  }
X}
/
echo 'Part 03 of Rog-O-Matic XIV complete.'
exit



More information about the Comp.sources.unix mailing list