|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T t
Length: 25654 (0x6436)
Types: TextFile
Names: »tactics.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Rog-O-Matic/tactics.c«
/*
* tactics.c: Rog-O-Matic XIV (CMU) Thu Jan 31 20:31:22 1985 - mlm
* Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin
*
* This file contains all of the 'medium level intelligence' of Rog-O-Matic.
*/
# include <stdio.h>
# include <ctype.h>
# include <curses.h>
# include "types.h"
# include "globals.h"
# include "install.h"
/*
* handlearmor: This routine is called to determine whether we should
* take off or put on armor.
*
* Current strategy: Wear best armor on levels 1..7 or 19 on or
* if protected or have maintain armor.
* Wear 2nd best armor between levels 13..18.
* Wear best leather armor between levels 8..12
* or 2nd best if no leather armor. DR UTexas 12/15/83
*
* Note that leather armor does not rust.
*/
handlearmor ()
{ int obj;
/* Only check when armor status is different */
if (!newarmor || cursedarmor) return (0);
/*
* Pick the armor we want to wear. If we are worried about rust monster
* we wear the second best armor, but if we wont see any rust monsters,
* if our armor is too good for a rust monster to hit it, or we have a
* ring of maintain armor, then we should wear our best armor. On
* levels 13-18 we wear our second best no matter what.
*/
obj = havearmor (1, NOPRINT, ANY); /* Get best armor */
if (Level > 7 && Level < 19 &&
wearing ("maintain armor") == NONE &&
willrust (obj) &&
itemis (obj, KNOWN))
{ if (Level < 13)
obj = havearmor (1, NOPRINT, RUSTPROOF);
if (Level >= 13 || obj == NONE)
obj = havearmor (2, NOPRINT, ANY);
}
/* If the new armor is really bad, then don't bother wearing any */
if (obj != NONE &&
(armorclass (obj) > 9) ||
(itemis (obj, CURSED) &&
(havenamed(scroll, "remove curse") == NONE) &&
(armorclass (obj) > 6)))
{ obj = NONE; }
/* If we are wearing the right armor, then dont bother */
if (obj == currentarmor)
{ newarmor = 0; return (0); }
/* Debugging */
dwait (D_PACK, "handlearmor: obj %d, currentarmor %d", obj, currentarmor);
/* Take off the wrong armor */
if (currentarmor != NONE && takeoff ())
{ return (1); }
/* Put on the right armor, avoid wearing cursed armor */
if (obj != NONE)
{ return (wear (obj)); }
/* If we have no armor, then forget it */
newarmor = 0;
return (0);
}
/*
* handleweapon: wield our best weapon. Calls haveweapon.
*
* The current strategy is to wield the best weapon from haveweapon.
*/
handleweapon ()
{ int obj;
if ((!newweapon || cursedweapon) && !wielding (thrower)) return (0);
/* haveweapon (1) returns the index of the best weapon in the pack */
if ((obj = haveweapon (1, NOPRINT)) < 0) return (0);
/* If we are not wielding our best weapon, do so */
if (obj == currentweapon) { newweapon = 0; return (0); }
else if (obj != NONE) { return (wield (obj)); }
else { newweapon = 0; return (0); }
}
/*
* quaffpotion: check whether we should quaff a potion, and call
* quaff if so. We quaff add strength, restore strength, healing,
* extra healing, and raise level here. Potions of seeinvisible
* are handled in 'fightinvisible'.
*
* If we are at or below the exp. level, then experiment with unknown potions.
*/
# define MAXSTR (version < RV52A ? 1900 : 3100)
quaffpotion ()
{ int obj = NONE, obj2 = NONE;
/* Take advantage of double haste bug -- assures permanent haste */
if (!doublehasted && version < RV52A &&
((hasted && (obj = havenamed (potion, "haste self")) != NONE) ||
((obj = havemult (potion, "haste self", 2)) != NONE)) &&
quaff (obj))
return (1);
/*
* Can we use a gain strength to our advantage? Or a restore?
* If we have a Gain Strength, or our strength is very bad,
* then we quaff a Regain Strength.
*/
if (Str == Strmax && (obj = havenamed (potion, "gain strength")) != NONE &&
quaff (obj))
return (1);
if ((Str < 700 ||
(Str != Strmax && (havenamed (potion, "gain strength") != NONE))) &&
(obj = havenamed (potion, "restore strength")) != NONE &&
quaff (obj))
return (1);
if ((Str < 1600 || Level > 12) &&
(obj = havemult (potion, "restore strength", 2)) != NONE &&
quaff (obj))
return (1);
/* Try to get unblinded by quaffing a potion */
if (blinded &&
((obj = havenamed (potion, "healing")) != NONE ||
(obj = havenamed (potion, "extra healing")) != NONE ||
(obj = havenamed (potion, "see invisible")) != NONE) &&
quaff (obj))
return (1);
/* Try to get uncosmic by quaffing a potion */
if (cosmic &&
(obj = havenamed(potion, "extra healing")) != NONE &&
quaff (obj))
return (1);
if (cosmic && Str != Strmax &&
(obj = havenamed (potion, "poison")) != NONE)
{ if (wearing ("sustain strength") != NONE && quaff (obj) ||
findring ("sustain strength"))
return (1);
}
/*
* Quaff healing to raise our MaxHp
* Wait for cosmic known to quaff extra healing. DR,TG UTexas
*/
if (Hp == Hpmax &&
((obj = havemult (potion, "healing", 2)) != NONE ||
(obj = havemult (potion, "extra healing", 2)) != NONE ||
know ("blindness") && (obj = havenamed (potion, "healing")) != NONE ||
know ("blindness") && (know ("hallucination") || version < RV53A) &&
Level < 15 && (obj = havenamed (potion, "extra healing")) != NONE) &&
quaff (obj))
return (1);
/*
* Quaff a raise level potion?
*/
if ((Explev > 8 || Level > 13) &&
(obj = havenamed (potion, "raise level")) != NONE &&
quaff (obj))
return (1);
/* Quaff an unknown potion? */
if ((Level >= (k_exper/10) || objcount >= maxobj || Str<1000 || blinded) &&
(obj = unknown (potion)) != NONE)
{ if ((obj2 = wearing ("add strength")) != NONE && removering (obj2))
return (1);
else if (wearing ("sustain strength") < 0 &&
(obj2 = havenamed (ring, "sustain strength")) != NONE &&
puton (obj2))
return (1);
else if (quaff (obj))
return (1);
}
return (0);
}
/*
* readscroll: check whether we should read a scroll, and call reads
* to actually read it.
*
* Scrolls of identify, remove curse, genocide, enchant weapon,
* enchant armor, magic mapping are defined. Scrolls of scare
* monster and confuse monster are handled in 'battlestations'.
*
* If we are at or below (k_exper/10), experiment with unknown scrolls.
* Make certain that we are wearing our best armor when reading
* enchant armor or an unknown scroll (which could be enchant
* armor).
*/
readscroll ()
{ register int obj, obj2;
/* Check the item specific identify scrolls first */
if (((obj = havenamed (scroll, "identify armor")) != NONE &&
(obj2 = unknown (armor)) != NONE) ||
((obj = havenamed (scroll, "identify weapon")) != NONE &&
(obj2 = unknown (hitter)) != NONE) ||
((obj = havenamed (scroll, "identify potion")) != NONE &&
(obj2 = unknown (potion)) != NONE) ||
((obj = havenamed (scroll, "identify scroll")) != NONE &&
(obj2 = unknown (scroll)) != NONE) ||
((obj = havenamed (scroll, "identify ring, wand or staff")) != NONE &&
((obj2 = unknown (ring)) != NONE || (obj2 = unknown (wand)) != NONE)))
{ prepareident (obj2, obj);
return (reads (obj)); }
/* In older version, have multiple uses for generic identify scrolls */
if ((obj = havenamed (scroll, "identify")) != NONE &&
(currentweapon != NONE) &&
(!itemis (currentweapon, KNOWN) &&
(!usingarrow || goodarrow > 20)))
{ prepareident (currentweapon, obj);
return (reads (obj)); }
if ((obj = havenamed (scroll, "identify")) != NONE &&
((obj2 = unknown (ring)) != NONE ||
(obj2 = unidentified (wand)) != NONE ||
(obj2 = unidentified (scroll)) != NONE ||
Level > 10 && (obj2 = unknown (wand)) != NONE ||
((cheat || version == RV36A) &&
((obj2 = unknown (potion)) != NONE ||
(obj2 = haveother (scroll)) != NONE))))
{ prepareident (obj2, obj);
return (reads (obj)); }
if ((cursedarmor || cursedweapon) &&
(obj = havenamed (scroll, "remove curse")) != NONE)
return (reads (obj));
if ((obj = havenamed (scroll, "genocide")) != NONE)
return (reads (obj));
if (currentweapon != NONE &&
(goodweapon || usingarrow || MaxLevel > 12) &&
(obj = havenamed (scroll, "enchant weapon")) != NONE)
return (reads (obj));
if (Level != didreadmap && Level > 12 &&
(obj = havenamed (scroll, "magic mapping")) != NONE)
return (reads (obj));
/* About to read an unknown scroll. We will assure that we have */
/* a weapon in hand, and put on our best armor for the occasion */
/* We must also prepare to identify something, just in case. */
if ((obj = havenamed (scroll, "enchant armor")) != NONE ||
(obj = havenamed (scroll, "protect armor")) != NONE ||
((currentweapon != NONE) &&
(Level >= (k_exper/10) || objcount >= maxobj ||
cursedarmor || cursedweapon) &&
(exploredlevel || know ("aggravate monster")) &&
(obj = unknown (scroll)) != NONE))
{ prepareident (pickident (), obj);
/* Go to a corner to read the scroll */
if (version <= RV36B && know ("create monster") == '\0' && gotocorner ())
return (1);
/* Must put on our good armor first */
if (!cursedarmor &&
(!know("enchant armor") || stlmatch(inven[obj].str, "enchant armor") ||
!know("protect armor") || stlmatch(inven[obj].str, "protect armor")))
{ int obj2 = havearmor (1, NOPRINT, ANY); /* Pick our best armor */
if (obj2 == currentarmor);
/* Take off the bad stuff */
else if (currentarmor != NONE && takeoff ()) return (1);
/* Put on the good stuff */
else if (obj2 != NONE && wear (obj2)) return (1);
}
/* No armor handling, so read the scroll */
return (reads (obj));
}
return (0);
}
/*
* handlering: check whether we should put on a ring, and call
* puton to wear it. Calls 'havering' to find the two best rings
* and wears them if their evaluations are greater than 1000.
*
* 'havering' understands about when different rings are good, and how
* much food we need to use each ring.
*/
handlering ()
{ int ring1, ring2;
if (!newring && !beingstalked) return (0);
ring1 = havering (1, NOPRINT);
ring2 = havering (2, NOPRINT);
dwait (D_PACK, "Handlering: ring1 %d, ring2 %d, left %d, right %d",
ring1, ring2, leftring, rightring);
if ((leftring == ring1 && rightring == ring2) ||
(rightring == ring1 && leftring == ring2))
{ newring = 0; return (0);
}
if (leftring != NONE && leftring != ring1 && leftring != ring2 &&
removering (leftring))
{ return (1);
}
if (rightring != NONE && rightring != ring1 && rightring != ring2 &&
removering (rightring))
{ return (1);
}
if (ring1 != leftring && ring1 != rightring && puton (ring1))
{ return (1);
}
if (ring2 != leftring && ring2 != rightring && puton (ring2))
{ return (1);
}
return (0);
}
/*
* findring: called with the named of a ring, attempts to locate such
* a ring in the pack and wear it. It will remove rings (other than
* maintain armor) to accomplish this task if it we are wearing two
* rings.
*
* Could be extended to have an ordering of rings to wear.
*/
findring (name)
char *name;
{ int obj;
if ((obj = havenamed (ring, name)) < 0 ||
wearing (name) != NONE)
return (0);
if (leftring != NONE && rightring != NONE)
{ if (stlmatch (inven[leftring].str, "maintain armor"))
return (removering (rightring));
else
return (removering (leftring));
}
return (puton (obj));
}
/*
* grope: get to a safe square and sit and vibrate (move back and forth)
* and then sleep for 'turns' turns.
*
* Problem: We need to know which side of us the monster is on. Then
* we could zap him with wands or staves. This requires some kind of
* memory and the ability to detect when the motion command (ie 'hit'
* fails to move us). MLM
*/
grope (turns)
register int turns;
{ register int k, moves;
if (atrow < 2 || atcol < 1)
{ command (T_GROPING, "%ds", (turns > 0) ? turns : 1);
return (1);
}
/* Count adjacent CANGO squares */
for (k=0, moves=0; k<8; k++)
if (onrc(CANGO, atdrow(k), atdcol(k))) moves++;
if (moves > 2 && findsafe ()) /* find a spot with 2 or fewer moves */
return (1);
/* blindir is direction of adjacent CANGO square which is not a trap */
for (k=0; k<4; k++, blindir = (blindir+2) % 8)
if ((onrc(CANGO|TRAP, atdrow(blindir), atdcol(blindir)) == CANGO))
break;
if (turns) command (T_GROPING, "%c%c%ds", keydir[blindir],
keydir[(blindir+4)&7], turns);
else command (T_GROPING, "%c%c", keydir[blindir],
keydir[(blindir+4)&7]);
blindir = (blindir+2) % 8;
return (1);
}
/*
* findarrow: This function tries to run over an arrow trap to get a
* magic arrow. Make certain we have some food.
*/
findarrow ()
{
/* If wrong version, not cheating or must go find food, then forget it */
if (version > RV36B || !cheat || hungry())
return (0);
else if (!usingarrow && foundarrowtrap && !on (ARROW) &&
gotowards (trapr, trapc, 0))
{ display ("Trying for arrow..."); return (1); }
return (0);
}
/*
* checkcango: verify that a missile fired in direction 'dir' will
* travel 'turns' turns.
*
* Modified by mlm, 5/31/83: Return false if a monster is in the way.
* only return true if the missile will travel EXACTLY the distance
* specified. Also changed it to not check the current square (since
* we can fire from a door, even if we cant shoot through one).
*/
checkcango (dir, turns)
register int dir, turns;
{ register int r, c, dr, dc;
for (dr = deltr[dir], dc = deltc[dir], r=atrow+dr, c=atcol+dc;
turns > 0 && onrc (CANGO | DOOR, r, c) == CANGO;
r+=dr, c+=dc, turns--)
;
return (turns==0);
}
/*
* godownstairs: issues a down command and check for the halftimeshow.
*/
godownstairs (running)
register int running; /* True ==> dont do anything fancy */
{ register int p;
int genericinit(), downvalue();
/* We dont want to go down if we have just gotten an arrow, since */
/* It is probably bad, and we will want to go back to the trap; */
/* Dont go down until we have killed five monsters in one blow. */
/* While waiting, run back and forth to look for monsters. */
if (cheat && version <= RV36B && !running &&
foundarrowtrap && usingarrow &&
have (food) != NONE && goodarrow < 5 && waitaround ())
{ saynow ("Checking out arrow...");
return (1);
}
/* Check for applicability of this rule */
if (! new_stairs) return (0);
/* If we are on the stairs, perhaps we should rest up some */
p = between ((Explev+larder)*10, 60, 100);
if (atrow == stairrow && atcol == staircol &&
!running && larder > 0 && Hp < max (10, percent (Hpmax, p)))
{ command (T_RESTING, "s");
display ("Resting on stairs before next level");
return (1);
}
/* Allow other rules a chance to notice that we are done with the level */
if (on (STAIRS) && !exploredlevel)
{ exploredlevel = 1; return (1); }
/* If we are floating, we cant go down, either rest or fail */
if (floating && running)
{ saynow ("Cannot escape, floating in mid-air!"); return (0); }
else if (floating)
{ saynow ("Floating above stairs...");
command (T_RESTING, "s"); return (1); }
/* If we are on the stairs, go down */
if (on (STAIRS))
{ halftimeshow (Level);
/* Start logging at Level GOODGAME, if we arent already */
if (Level > (GOODGAME-2) && !replaying && !logging) toggleecho ();
/* Send the DOWN command and return */
command (T_MOVING, ">");
return (1);
}
/* If we are running and can run to the next level, do that */
if (running && makemove (RUNDOWN, genericinit, downvalue, REEVAL))
{ return (1);
}
/* If we see the stairs or a trap door, go there */
if (!running && makemove (DOWNMOVE, genericinit, downvalue, REUSE))
{ goalr = targetrow; goalc = targetcol; /* Set a goal (CPU time hack) */
return (1);
}
new_stairs = 0;
return (0);
}
/*
* plunge: Should we head down immediately?
*
* If we are being teleported too much or
* we are on a bad level (19 to 25) or
* we want to get past Rust Monsters (level 18) or
* we have aggravated all of the monsters then
*
* we head down immediately.
*/
plunge ()
{
/* Check for applicability of this rule */
if (stairrow < 0 && !foundtrapdoor) return (0);
if (teleported > (larder+1)*5 && godownstairs (NOTRUNNING))
{ if (!on (STAIRS)) saynow ("Giving up on level, too much teleporting");
return (1);
}
if (Level > 17 && Level < 26 && godownstairs (NOTRUNNING))
{ if (!on (STAIRS)) saynow ("Plunge mode!!!");
return (1);
}
if (aggravated && godownstairs (NOTRUNNING))
{ if (!on (STAIRS)) saynow ("Running from aggravated monsters");
return (1);
}
if (haveexplored (9) && godownstairs (NOTRUNNING))
{ if (!on (STAIRS)) saynow ("Level explored");
return (1);
}
return (0);
}
/*
* waitaround: Hang around here waiting for monsters.
*/
static struct { int vertstart,
vertend,
vertdelt,
horstart,
horend,
hordelt; } cb [4] =
{ { 3, 21, 1, 1, 78, 1}, /* Top left corner */
{ 3, 21, 1, 78, 1, -1}, /* Top right corner */
{ 21, 3, -1, 78, 1, -1}, /* Bottom right corner */
{ 21, 3, -1, 1, 78, 1} }; /* Bottom left corner */
static gc = 0; /* Goal corner from 0..3 */
/*
* waitaround: For some reason we want to stay on this level for a while.
* Try running to each corner of the level.
*/
waitaround ()
{ register int i, j;
if (gotowardsgoal ()) return (1);
gc = ++gc % 4;
for (i = cb[gc].vertstart; i != cb[gc].vertend; i += cb[gc].vertdelt)
for (j = cb[gc].horstart; j != cb[gc].horend; j += cb[gc].hordelt)
if (onrc (BEEN | CANGO | ROOM, i, j) &&
!onrc (TRAP, i, j) && gotowards (i, j, 0))
{ goalr = i; goalc = j; return (1); }
return (0);
}
/*
* goupstairs:
*
* If we have the amulet, and our score is good enough, then
* go up stairs. This function also checks for the end of the
* game, and issues the proper calls to get the score written.
*/
goupstairs (running)
int running;
{ int obj;
/* Check for applicability of this rule */
if (stairrow < 0 || have(amulet) < 0 ||
(!running && quitat < BOGUS && Gold <= quitat))
return (0);
/* If we are on the stairs, then check for win, else go up */
if (atrow == stairrow && atcol == staircol)
{
/* If we are about to win, dump any magic arrows or minus things */
if (Level == 1 &&
((obj = havearrow ()) != NONE || (obj = haveminus ()) != NONE))
{ throw (obj, 0); return (1); }
/* No magic arrows, time to leave */
else if (Level == 1)
{
/* Send an up command and a space to clear the 'You Made It' */
sendnow ("< ");
/* Now read chars until we have the end of the inventory. */
/* Note misspelling in Rogue 'Peices', so dont assume anything */
waitfor ("Gold P");
/* Note that quitrogue sends a '\n' to get the score */
quitrogue ("total winner", Gold, 0);
return (1);
}
/* Not at the top yet, keep on trucking */
else
{ command (T_MOVING, "<"); return (1); }
}
/* If we know where the stairs are, go there */
else if ((goalr = stairrow) > 0 && (goalc = staircol) > 0 &&
gotowards (goalr, goalc, running))
return (1);
return (0);
}
/*
* restup: If we are low on hit points, sit for a while. Since handlering
* was called first, we will be wearing a ring of regeneration if need be.
*
* First we find a good place to rest (we will move into a room, but not
* out of one). In lit rooms, stand far from doors so we can shoot
* arrows at things coming in. In dark rooms, stand diagonally away
* from doors (so we get a one turn warning of monsters coming in that
* door). In either case, stand on stairs or next to trap doors and
* teleport traps).
*
* Then rest by searching 's'. If one blow would not kill us, and we
* dont plan to shoot arrows, then rest up so as to heal one hit point.
* If we are critically low, rest up one turn at a time.
*
* Other considerations: Dont move if confused or cosmic.
* Drink healing potions if really low.
* Dont rest when hungry (and no food)
*/
restup ()
{ register int obj, turns;
/* If we are confused, sit still so we dont bump into anything bad */
if (confused) { command (T_RESTING, "s"); return (1); }
/* If cosmic and plenty of hit points and food, rest for long periods */
if (cosmic && (Hp >= percent (Hpmax, 80)) && larder > 2)
{ display ("Oh wow man, I'm contemplating my navel!");
command (T_RESTING, "100s"); return (1); }
/* If we are well, return */
if (Hp >= max (8, percent (Hpmax, between (Explev*10+k_rest-50, 40, 80))))
{ unrest (); return (0); }
/*
* If we are really ill then try a healing potion (save a healing
* potion for blindness, extra healing for hallucination).
*/
if (Hp < Level+10 && Hp < Hpmax/3 &&
((obj = havemult (potion, "extra healing", 2)) != NONE ||
(obj = havemult (potion, "healing", 2)) != NONE ||
(know ("hallucination") &&
(obj = havenamed (potion, "extra healing")) != NONE) ||
(know ("blindness") &&
(obj = havenamed (potion, "healing")) != NONE)) &&
quaff (obj))
{ return (1); }
/* Dont rest when we havent enough to eat */
if (hungry ()) return (0);
display ("Resting up...");
/*
* Look for a good place to rest
*/
if (movetorest ()) return (1);
/*
* If we are very ill, or we are very deep, or we are in a lit room
* and can shoot at things as they come ate us, rest only one turn so
* monsters dont get the first shot. Otherwise rest enough turns
* to heal one step.
*/
turns = (Level < 8) ? (20-Explev*2) : 3;
if ((!darkroom () && ammo) || Hp < Level*2+8 || Level > 15) turns = 1;
command (T_RESTING, "%ds", turns);
return (1);
}
/*
* If goalr and goalc are set (not -1,-1) then attempt to move towards
* that square. Calls gotowards which calls bfsearch.
*/
gotowardsgoal ()
{ if (goalr > 0 && goalc > 0) /* Keep on trucking */
{ if (goalr == atrow && goalc == atcol) { goalr = NONE; goalc = NONE; }
else if (gotowards (goalr, goalc, 0)) { return (1); }
else { goalr = NONE; goalc = NONE; }
}
return (0);
}
/*
* gotocorner: Find a corner using downright and try to go there.
* This is done so we can destroy old wands by throwing
* them into the corner (which destroys them).
*/
gotocorner ()
{ int r, c;
if (!downright (&r, &c)) return (0);
if (debug (D_SCREEN))
{ saynow ("Gotocorner called:"); mvaddch (r, c, 'T'); at (row, col); }
if (gotowards (r, c, 0)) { goalr=r; goalc=c; return (1); }
return (0);
}
/*
* lightroom: Try to light up the room if we are below level 17.
*/
light ()
{ if (Level < 17) return (0);
return (lightroom ());
}
/*
* shootindark: If we are arching at an old monster, fire another arrow.
*/
shootindark ()
{ register int obj, bow;
/* If no longer arching in the dark, fail */
if (darkturns < 1 || darkdir == NONE || !darkroom ()) return (0);
darkturns--; /* Count off turns till he reaches us */
/* If he is one turn away, switch back to our sword */
if (!cursedweapon && wielding (thrower) && darkturns==0 && handleweapon ())
{ dwait (D_BATTLE, "Switching to sword [4]"); return (1); }
/* If we have room, switch to our bow */
if (!cursedweapon && !wielding (thrower) && darkturns > 3 &&
(bow = havebow (1, NOPRINT)) != NONE && wield (bow))
return (1);
/* Fail if we have run out of arrows */
if ((obj = havemissile ()) < 0) return (0);
/* Throw the arrow in the arching direction */
return (throw (obj, darkdir));
}
/*
* dinnertime: Eat if we are hungry or if we have a surplus of food.
*/
dinnertime ()
{
if ((havefood (5) && objcount == maxobj && ! droppedscare) ||
(larder > 0 && hungry ()))
{ return (eat ()); }
return (0);
}
/*
* trywand: Zap a blank wall with an unknown and unused wand in an attempt
* to generate a message which identifies the wand.
*/
trywand ()
{ register int obj, dir, r, c, count;
/* If we arent in a room, if there are monsters around, */
/* or we are in the dark, then we cant try this strategy */
if (!on (ROOM) || mlistlen || darkroom ()) return (0);
/* Have we a wand to identify? */
if ((obj = unknown (wand)) < 0)
return (0);
/* Look for a wall either 3 or 4 away */
for (dir = 0; dir < 8; dir += 2)
{ for (count = 0, r=atrow, c=atcol;
onrc (CANGO | DOOR, r, c) == CANGO;
r += deltr[dir], c += deltc[dir])
count++;
if (count == 4 || count == 5) break; /* Found a likely wall */
}
/* If we couldnt find room, then fail */
if (dir > 7) return (0);
/* Set to do a reset inventory (usesynch) and point the wand */
usesynch = 0;
return (point (obj, dir));
}
/*
* eat: If we have food, eat it.
*/
eat ()
{ int obj;
if ((obj = have (food)) != NONE)
{ command (T_HANDLING, "e%c", LETTER (obj));
return (1);
}
return (0);
}