/* File: borg6.c */

/* Purpose: Medium level stuff for the Borg -BEN- */

#include "angband.h"

#ifdef ALLOW_BORG

#include "borg1.h"
#include "borg2.h"
#include "borg3.h"
#include "borg4.h"
#include "borg5.h"
#include "borg6.h"



/*
 * This file is responsible for the low level dungeon goals.
 *
 * This includes calculating the danger from monsters, determining
 * how and when to attack monsters, and calculating "flow" paths
 * from place to place for various reasons.
 *
 * Notes:
 *   We assume that invisible/offscreen monsters are dangerous
 *   We consider physical attacks, missile attacks, spell attacks,
 *     wand attacks, etc, as variations on a single theme.
 *   We take account of monster resistances and susceptibilities
 *   We try not to wake up sleeping monsters by throwing things
 *
 * To Do:
 *   Consider various "special" attacks like sleep and slow
 *
 * Bugs:
 *   We use missiles and bolt spells against ghosts in walls
 *   Currently the "twitchy()" function is not very smart
 *   We get "twitchy" when we are afraid of the monsters
 *   Annoyance and Danger are very different things (!)
 */





/*
 * Given a "source" and "target" locations, extract a "direction",
 * which will move one step from the "source" towards the "target".
 *
 * Note that we use "diagonal" motion whenever possible.
 *
 * We return "5" if no motion is needed.
 */
static int borg_extract_dir(int y1, int x1, int y2, int x2)
{
	/* No movement required */
	if ((y1 == y2) && (x1 == x2)) return (5);

	/* South or North */
	if (x1 == x2) return ((y1 < y2) ? 2 : 8);

	/* East or West */
	if (y1 == y2) return ((x1 < x2) ? 6 : 4);

	/* South-east or South-west */
	if (y1 < y2) return ((x1 < x2) ? 3 : 1);

	/* North-east or North-west */
	if (y1 > y2) return ((x1 < x2) ? 9 : 7);

	/* Paranoia */
	return (5);
}


/*
 * Given a "source" and "target" locations, extract a "direction",
 * which will move one step from the "source" towards the "target".
 *
 * We prefer "non-diagonal" motion, which allows us to save the
 * "diagonal" moves for avoiding pillars and other obstacles.
 *
 * If no "obvious" path is available, we use "borg_extract_dir()".
 *
 * We return "5" if no motion is needed.
 */
static int borg_goto_dir(int y1, int x1, int y2, int x2)
{
	int d, e;

	int ay = (y2 > y1) ? (y2 - y1) : (y1 - y2);
	int ax = (x2 > x1) ? (x2 - x1) : (x1 - x2);


	/* Default direction */
	e = borg_extract_dir(y1, x1, y2, x2);


	/* Adjacent location, use default */
	if ((ay <= 1) && (ax <= 1)) return (e);


	/* Try south/north (primary) */
	if (ay > ax)
	{
		d = (y1 < y2) ? 2 : 8;
		if (borg_cave_floor_bold(y1 + ddy[d], x1 + ddx[d])) return (d);
	}

	/* Try east/west (primary) */
	if (ay < ax)
	{
		d = (x1 < x2) ? 6 : 4;
		if (borg_cave_floor_bold(y1 + ddy[d], x1 + ddx[d])) return (d);
	}


	/* Try diagonal */
	d = borg_extract_dir(y1, x1, y2, x2);

	/* Check for walls */
	if (borg_cave_floor_bold(y1 + ddy[d], x1 + ddx[d])) return (d);


	/* Try south/north (secondary) */
	if (ay <= ax)
	{
		d = (y1 < y2) ? 2 : 8;
		if (borg_cave_floor_bold(y1 + ddy[d], x1 + ddx[d])) return (d);
	}

	/* Try east/west (secondary) */
	if (ay >= ax)
	{
		d = (x1 < x2) ? 6 : 4;
		if (borg_cave_floor_bold(y1 + ddy[d], x1 + ddx[d])) return (d);
	}


	/* Circle obstacles */
	if (!ay)
	{
		/* Circle to the south */
		d = (x1 < x2) ? 3 : 1;
		if (borg_cave_floor_bold(y1 + ddy[d], x1 + ddx[d])) return (d);

		/* Circle to the north */
		d = (x1 < x2) ? 9 : 7;
		if (borg_cave_floor_bold(y1 + ddy[d], x1 + ddx[d])) return (d);
	}

	/* Circle obstacles */
	if (!ax)
	{
		/* Circle to the east */
		d = (y1 < y2) ? 3 : 9;
		if (borg_cave_floor_bold(y1 + ddy[d], x1 + ddx[d])) return (d);

		/* Circle to the west */
		d = (y1 < y2) ? 1 : 7;
		if (borg_cave_floor_bold(y1 + ddy[d], x1 + ddx[d])) return (d);
	}


	/* Oops */
	return (e);
}



/*
 * Clear the "flow" information
 *
 * This function was once a major bottleneck, so we now use several
 * slightly bizarre, but highly optimized, memory copying methods.
 */
static void borg_flow_clear(void)
{
	/* Reset the "cost" fields */
	COPY(auto_data_cost, auto_data_hard, auto_data);

	/* Wipe costs and danger */
	if (auto_danger_wipe)
	{
		/* Wipe the "know" flags */
		WIPE(auto_data_know, auto_data);

		/* Wipe the "icky" flags */
		WIPE(auto_data_icky, auto_data);

		/* Wipe complete */
		auto_danger_wipe = FALSE;
	}

	/* Start over */
	flow_head = 0;
	flow_tail = 0;
}




/*
 * Spread a "flow" from the "destination" grids outwards
 *
 * We fill in the "cost" field of every grid that the player can
 * "reach" with the number of steps needed to reach that grid,
 * if the grid is "reachable", and otherwise, with "255", which
 * is the largest possible value that can be stored in a byte.
 *
 * Thus, certain grids which are actually "reachable" but only by
 * a path which is at least 255 steps in length will thus appear
 * to be "unreachable", but this is not a major concern.
 *
 * We use the "flow" array as a "circular queue", and thus we must
 * be careful not to allow the "queue" to "overflow".  This could
 * only happen with a large number of distinct destination points,
 * each several units away from every other destination point, and
 * in a dungeon with no walls and no dangerous monsters.  But this
 * is technically possible, so we must check for it just in case.
 *
 * We do not need a "priority queue" because the cost from grid to
 * grid is always "one" and we process them in order.  If we did
 * use a priority queue, this function might become unusably slow,
 * unless we reactivated the "room building" code.
 *
 * We handle both "walls" and "danger" by marking every grid which
 * is "impassible", due to either walls, or danger, as "ICKY", and
 * marking every grid which has been "checked" as "KNOW", allowing
 * us to only check the wall/danger status of any grid once.  This
 * provides some important optimization, since many "flows" can be
 * done before the "ICKY" and "KNOW" flags must be reset.
 *
 * Note that the "borg_enqueue_grid()" function should refuse to
 * enqueue "dangeous" destination grids, but does not need to set
 * the "KNOW" or "ICKY" flags, since having a "cost" field of zero
 * means that these grids will never be queued again.  In fact,
 * the "borg_enqueue_grid()" function can be used to enqueue grids
 * which are "walls", such as "doors" or "rubble".
 *
 * This function is extremely expensive, and is a major bottleneck
 * in the code, due more to internal processing than to the use of
 * the "borg_danger()" function, especially now that the use of the
 * "borg_danger()" function has been optimized several times.
 *
 * The "optimize" flag allows this function to stop as soon as it
 * finds any path which reaches the player, since in general we are
 * looking for paths to destination grids which the player can take,
 * and we can stop this function as soon as we find any usable path,
 * since it will always be as short a path as possible.
 *
 * We queue the "children" in reverse order, to allow any "diagonal"
 * neighbors to be processed first, since this may boost efficiency.
 *
 * Note that we should recalculate "danger", and reset all "flows"
 * if we notice that a wall has disappeared, and if one appears, we
 * must give it a maximal cost, and mark it as "icky", in case it
 * was currently included in any flow.
 *
 * If a "depth" is given, then the flow will only be spread to that
 * depth, note that the maximum legal value of "depth" is 250.
 */
static void borg_flow_spread(int depth, bool optimize, bool avoid)
{
	int i;
	int n, o = 0;
	int x1, y1;
	int x, y;


	/* Now process the queue */
	while (flow_head != flow_tail)
	{
		/* Extract the next entry */
		x1 = auto_flow_x[flow_tail];
		y1 = auto_flow_y[flow_tail];

		/* Circular queue -- dequeue the next entry */
		if (++flow_tail == AUTO_FLOW_MAX) flow_tail = 0;


		/* Cost (one per movement grid) */
		n = auto_data_cost->data[y1][x1] + 1;

		/* New depth */
		if (n > o)
		{
			/* Optimize (if requested) */
			if (optimize && (n > auto_data_cost->data[c_y][c_x])) break;

			/* Limit depth */
			if (n > depth) break;

			/* Save */
			o = n;
		}

		/* Queue the "children" */
		for (i = 0; i < 8; i++)
		{
			int old_head;

			auto_grid *ag;


			/* Neighbor grid */
			x = x1 + ddx_ddd[i];
			y = y1 + ddy_ddd[i];


			/* Skip "reached" grids */
			if (auto_data_cost->data[y][x] <= n) continue;


			/* Access the grid */
			ag = &auto_grids[y][x];


			/* Avoid "wall" grids (not doors) */
			if (ag->feat >= FEAT_SECRET) continue;


			/* Avoid unknown grids (if requested) */
			if (avoid && (ag->feat == FEAT_NONE)) continue;


			/* Ignore "icky" grids */
			if (auto_data_icky->data[y][x]) continue;

			/* Analyze every grid once */
			if (!auto_data_know->data[y][x])
			{
				int p;


				/* Mark as known */
				auto_data_know->data[y][x] = TRUE;


				/* Get the danger */
				p = borg_danger(y, x, 1);

				/* Dangerous grid */
				if (p > avoidance / 2)
				{
					/* Mark as icky */
					auto_data_icky->data[y][x] = TRUE;

					/* Ignore this grid */
					continue;
				}
			}


			/* Save the flow cost */
			auto_data_cost->data[y][x] = n;

			/* Enqueue that entry */
			auto_flow_x[flow_head] = x;
			auto_flow_y[flow_head] = y;


			/* Circular queue -- memorize head */
			old_head = flow_head;

			/* Circular queue -- insert with wrap */
			if (++flow_head == AUTO_FLOW_MAX) flow_head = 0;

			/* Circular queue -- handle overflow (badly) */
			if (flow_head == flow_tail) flow_head = old_head;
		}
	}

	/* Forget the flow info */
	flow_head = flow_tail = 0;
}



/*
 * Enqueue a fresh (legal) starting grid, if it is safe
 */
static void borg_flow_enqueue_grid(int y, int x)
{
	int old_head;


	/* Avoid icky grids */
	if (auto_data_icky->data[y][x]) return;

	/* Unknown */
	if (!auto_data_know->data[y][x])
	{
		/* Mark as known */
		auto_data_know->data[y][x] = TRUE;

		/* Mark dangerous grids as icky */
		if (borg_danger(y, x, 1) > avoidance / 2)
		{
			/* Icky */
			auto_data_icky->data[y][x] = TRUE;

			/* Avoid */
			return;
		}
	}


	/* Only enqueue a grid once */
	if (!auto_data_cost->data[y][x]) return;


	/* Save the flow cost (zero) */
	auto_data_cost->data[y][x] = 0;

	/* Enqueue that entry */
	auto_flow_y[flow_head] = y;
	auto_flow_x[flow_head] = x;


	/* Circular queue -- memorize head */
	old_head = flow_head;

	/* Circular queue -- insert with wrap */
	if (++flow_head == AUTO_FLOW_MAX) flow_head = 0;

	/* Circular queue -- handle overflow */
	if (flow_head == flow_tail) flow_head = old_head;
}



/*
 * Do a "reverse" flow from the player outwards
 */
static void borg_flow_reverse(void)
{
	/* Clear the flow codes */
	borg_flow_clear();

	/* Enqueue the player's grid */
	borg_flow_enqueue_grid(c_y, c_x);

	/* Spread, but do NOT optimize */
	borg_flow_spread(250, FALSE, FALSE);
}





/*
 * Attempt to induce "word of recall"
 */
bool borg_recall(void)
{
	/* Multiple "recall" fails */
	if (!goal_recalling)
	{
		/* Try to "recall" */
		if (borg_spell(5, 4) ||
		    borg_prayer(4, 4) ||
		    borg_zap_rod(SV_ROD_RECALL) ||
		    borg_read_scroll(SV_SCROLL_WORD_OF_RECALL))
		{
			/* Success */
			return (TRUE);
		}
	}

	/* Nothing */
	return (FALSE);
}



/*
 * Prevent starvation by any means possible
 */
static bool borg_eat_food_any(void)
{
	int i;

	/* Scan the inventory for "normal" food */
	for (i = 0; i < INVEN_PACK; i++)
	{
		auto_item *item = &auto_items[i];

		/* Skip empty items */
		if (!item->iqty) continue;

		/* Skip unknown food */
		if (!item->kind) continue;

		/* Skip non-food */
		if (item->tval != TV_FOOD) continue;

		/* Skip "flavored" food */
		if (item->sval < SV_FOOD_MIN_FOOD) continue;

		/* Eat something of that type */
		if (borg_eat_food(item->sval)) return (TRUE);
	}

	/* Scan the inventory for "okay" food */
	for (i = 0; i < INVEN_PACK; i++)
	{
		auto_item *item = &auto_items[i];

		/* Skip empty items */
		if (!item->iqty) continue;

		/* Skip unknown food */
		if (!item->kind) continue;

		/* Skip non-food */
		if (item->tval != TV_FOOD) continue;

		/* Skip "icky" food */
		if (item->sval < SV_FOOD_MIN_OKAY) continue;

		/* Eat something of that type */
		if (borg_eat_food(item->sval)) return (TRUE);
	}

	/* Nothing */
	return (FALSE);
}


/*
 * Mega-Hack -- evaluate the "freedom" of the given location
 *
 * The theory is that often, two grids will have equal "danger",
 * but one will be "safer" than the other, perhaps because it
 * is closer to stairs, or because it is in a corridor, or has
 * some other characteristic that makes it "safer".
 *
 * Then, if the Borg is in danger, say, from a normal speed monster
 * which is standing next to him, he will know that walking away from
 * the monster is "pointless", because the monster will follow him,
 * but if the resulting location is "safer" for some reason, then
 * he will consider it.  This will allow him to flee towards stairs
 * in the town, and perhaps towards corridors in the dungeon.
 *
 * This method is used in town to chase the stairs.
 *
 * XXX XXX XXX We should attempt to walk "around" buildings.
 */
static int borg_freedom(int y, int x)
{
	int d, f = 0;

	/* Hack -- chase stairs in town */
	if (!auto_depth && track_more_num)
	{
		/* Love the stairs! */
		d = double_distance(y, x, track_more_y[0], track_more_x[0]);

		/* Proximity is good */
		f += (1000 - d);

		/* Close proximity is great */
		if (d < 4) f += (2000 - (d * 500));
	}

	/* Freedom */
	return (f);
}


/*
 * Check a floor grid for "happy" status
 *
 * These grids are floor grids which contain stairs, or which
 * are non-corners in corridors, or which are directly adjacent
 * to pillars.  Stairs are good because they can be used to leave
 * the level.  Corridors are good because you can back into them
 * to avoid groups of monsters and because they can be used for
 * escaping.  Pillars are good because while standing next to a
 * pillar, you can walk "around" it in two different directions,
 * allowing you to retreat from a single normal monster forever.
 */
static bool borg_happy_grid_bold(int y, int x)
{
	auto_grid *ag = &auto_grids[y][x];


	/* Accept stairs */
	if (ag->feat == FEAT_LESS) return (TRUE);
	if (ag->feat == FEAT_MORE) return (TRUE);


	/* Hack -- weak/dark is very unhappy */
	if (do_weak || !my_cur_lite) return (FALSE);


	/* Case 1a: north-south corridor */
	if (borg_cave_floor_bold(y-1, x) && borg_cave_floor_bold(y+1, x) &&
	    !borg_cave_floor_bold(y, x-1) && !borg_cave_floor_bold(y, x+1))
	{
		/* Happy */
		return (TRUE);
	}

	/* Case 1b: east-west corridor */
	if (borg_cave_floor_bold(y, x-1) && borg_cave_floor_bold(y, x+1) &&
	    !borg_cave_floor_bold(y-1, x) && !borg_cave_floor_bold(y+1, x))
	{
		/* Happy */
		return (TRUE);
	}


	/* Case 2a: north pillar */
	if (!borg_cave_floor_bold(y-1, x) &&
	    borg_cave_floor_bold(y-1, x-1) &&
	    borg_cave_floor_bold(y-1, x+1) &&
	    borg_cave_floor_bold(y-2, x))
	{
		/* Happy */
		return (TRUE);
	}

	/* Case 2b: south pillar */
	if (!borg_cave_floor_bold(y+1, x) &&
	    borg_cave_floor_bold(y+1, x-1) &&
	    borg_cave_floor_bold(y+1, x+1) &&
	    borg_cave_floor_bold(y+2, x))
	{
		/* Happy */
		return (TRUE);
	}

	/* Case 2c: east pillar */
	if (!borg_cave_floor_bold(y, x+1) &&
	    borg_cave_floor_bold(y-1, x+1) &&
	    borg_cave_floor_bold(y+1, x+1) &&
	    borg_cave_floor_bold(y, x+2))
	{
		/* Happy */
		return (TRUE);
	}

	/* Case 2d: west pillar */
	if (!borg_cave_floor_bold(y, x-1) &&
	    borg_cave_floor_bold(y-1, x-1) &&
	    borg_cave_floor_bold(y+1, x-1) &&
	    borg_cave_floor_bold(y, x-2))
	{
		/* Happy */
		return (TRUE);
	}


	/* Not happy */
	return (FALSE);
}


/*
 * Help determine if "phase door" seems like a good idea
 */
static bool borg_caution_phase(int dis)
{
	int n, k, i, d, x, y, p;

	int min = dis / 2;

	auto_grid *ag;

	/* Simulate 100 attempts */
	for (n = k = 0; k < 100; k++)
	{
		/* Pick a location */
		for (i = 0; i < 100; i++)
		{
			/* Pick a (possibly illegal) location */
			while (1)
			{
				y = rand_spread(c_y, dis);
				x = rand_spread(c_x, dis);
				d = distance(c_y, c_x, y, x);
				if ((d >= min) && (d <= dis)) break;
			}

			/* Ignore illegal locations */
			if ((y <= 0) || (y >= AUTO_MAX_Y - 1)) continue;
			if ((x <= 0) || (x >= AUTO_MAX_X - 1)) continue;

			/* Access */
			ag = &auto_grids[y][x];

			/* Skip unknown grids */
			if (ag->feat == FEAT_NONE) continue;

			/* Skip weird grids */
			if (ag->feat == FEAT_INVIS) continue;

			/* Skip walls */
			if (!borg_cave_floor_bold(y, x)) continue;

			/* Skip monsters */
			if (ag->kill) continue;

			/* Stop looking */
			break;
		}

		/* No location */
		if (i >= 100) return (FALSE);

		/* Examine */
		p = borg_danger(y, x, 2);

		/* Count "safe" locations */
		if (p <= avoidance / 2) n++;
	}

	/* Too much danger */
	if (n < 90) return (FALSE);

	/* Okay */
	return (TRUE);
}


/*
 * Be "cautious" and attempt to prevent death or dishonor.
 *
 * Strategy:
 *
 *   (1) Caution
 *   (1a) Analyze the situation
 *   (1b) Teleport from danger
 *   (1c) Handle critical stuff
 *   (1d) Retreat to happy grids
 *   (1e) Back away from danger
 *   (1f) Heal various conditions
 *
 *   (2) Attack
 *   (2a) Simulate possible attacks
 *   (2b) Perform optimal attack
 *
 *   (3) Recover
 *   (3a) Recover by spells/prayers
 *   (3b) Recover by items/etc
 *   (3c) Recover by resting
 *
 * XXX XXX XXX
 * In certain situations, the "proper" course of action is to simply
 * attack a nearby monster, since often most of the danger is due to
 * a single monster which can sometimes be killed in a single blow.
 *
 * Actually, both "borg_caution()" and "borg_recover()" need to
 * be more intelligent, and should probably take into account
 * such things as nearby monsters, and/or the relative advantage
 * of simply pummeling nearby monsters instead of recovering.
 *
 * Note that invisible/offscreen monsters contribute to the danger
 * of an extended "region" surrounding the observation, so we will
 * no longer rest near invisible monsters if they are dangerous.
 *
 * We sometimes try to "rest" to restore mana near "wimpy" monsters
 * which happen to drain mana, which is counter-productive.
 *
 * XXX XXX XXX
 * We should perhaps reduce the "fear" values of each region over
 * time, to take account of obsolete invisible monsters.
 *
 * Note that walking away from a fast monster is counter-productive,
 * since the monster will often just follow us, so we use a special
 * method which allows us to factor in the speed of the monster and
 * predict the state of the world after we move one step.  Of course,
 * walking away from a spell casting monster is even worse, since the
 * monster will just get to use the spell attack multiple times.  But,
 * if we are trying to get to known safety, then fleeing in such a way
 * might make sense.  Actually, this has been done too well, note that
 * it makes sense to flee some monsters, if they "stumble", or if we
 * are trying to get to stairs.  XXX XXX XXX
 *
 * Note that the "flow" routines attempt to avoid entering into
 * situations that are dangerous, but sometimes we do not see the
 * danger coming, and then we must attempt to survive by any means.
 *
 * We will attempt to "teleport" if the danger in the current situation,
 * as well as that resulting from attempting to "back away" from danger,
 * are sufficient to kill us in one or two blows.  This allows us to
 * avoid teleportation in situations where simply backing away is the
 * proper course of action, for example, when standing next to a nasty
 * stationary monster, but also to teleport when backing away will not
 * reduce the danger sufficiently.
 *
 * But note that in "nasty" situations (when we are running out of light,
 * or when we are starving, blind, confused, or hallucinating), we will
 * ignore the possibility of "backing away" from danger, when considering
 * the possibility of using "teleport" to escape.  But if the teleport
 * fails, we will still attempt to "retreat" or "back away" if possible.
 *
 * XXX XXX XXX Note that it should be possible to do some kind of nasty
 * "flow" algorithm which would use a priority queue, or some reasonably
 * efficient normal queue stuff, to determine the path which incurs the
 * smallest "cumulative danger", and minimizes the total path length.
 * It may even be sufficient to treat each step as having a cost equal
 * to the danger of the destination grid, plus one for the actual step.
 * This would allow the Borg to prefer a ten step path passing through
 * one grid with danger 10, to a five step path, where each step has
 * danger 9.  Currently, he often chooses paths of constant danger over
 * paths with small amounts of high danger.  However, the current method
 * is very fast, which is certainly a point in its favor...
 *
 * When in danger, attempt to "flee" by "teleport" or "recall", and if
 * this is not possible, attempt to "heal" damage, if needed, and else
 * attempt to "flee" by "running".
 *
 * XXX XXX XXX Both "borg_caution()" and "borg_recover()" should only
 * perform the "healing" tasks if they will cure more "damage"/"stuff"
 * than may be re-applied in the next turn, this should prevent using
 * wimpy healing spells next to dangerous monsters, and resting to regain
 * mana near a mana-drainer.
 *
 * Whenever we are in a situation in which, even when fully healed, we
 * could die in a single round, we set the "goal_fleeing" flag, and if
 * we could die in two rounds, we set the "goal_leaving" flag.
 *
 * In town, whenever we could die in two rounds if we were to stay still,
 * we set the "goal_leaving" flag.  In combination with the "retreat" and
 * the "back away" code, this should allow us to leave town before getting
 * into situations which might be fatal.
 *
 * Flag "goal_fleeing" means get off this level right now, using recall
 * if possible when we get a chance, and otherwise, take stairs, even if
 * it is very dangerous to do so.
 *
 * Flag "goal_leaving" means get off this level when possible, using
 * stairs if possible when we get a chance.
 *
 * We will also take stairs if we happen to be standing on them, and we
 * could die in two rounds.  This is often "safer" than teleportation,
 * and allows the "retreat" code to retreat towards stairs, knowing that
 * once there, we will leave the level.
 */
bool borg_caution(void)
{
	int j, p;

	int q, b_q = -1;

	bool nasty = FALSE;


	/*** Notice "nasty" situations ***/

	/* About to run out of light is extremely nasty */
	if (!my_lite && auto_items[INVEN_LITE].pval < 250) nasty = TRUE;

	/* Starvation is nasty */
	if (do_weak) nasty = TRUE;

	/* Blind-ness is nasty */
	if (do_blind) nasty = TRUE;

	/* Confusion is nasty */
	if (do_confused) nasty = TRUE;

	/* Hallucination is nasty */
	if (do_image) nasty = TRUE;


	/*** Evaluate local danger ***/

	/* Look around */
	p = borg_danger(c_y, c_x, 1);

	/* Unless "nasty"... */
	if (!nasty || !auto_depth)
	{
		int i;

		/* Attempt to find a better grid */
		for (i = 0; i < 8; i++)
		{
			int x = c_x + ddx_ddd[i];
			int y = c_y + ddy_ddd[i];

			/* Access the grid */
			auto_grid *ag = &auto_grids[y][x];

			/* Skip walls/doors */
			if (!borg_cave_floor_grid(ag)) continue;

			/* Skip unknown grids */
			if (ag->feat == FEAT_NONE) continue;

			/* Skip monster grids */
			if (ag->kill) continue;

			/* Mega-Hack -- skip stores XXX XXX XXX */
			if ((ag->feat >= FEAT_SHOP_HEAD) && (ag->feat <= FEAT_SHOP_TAIL)) continue;

			/* Mega-Hack -- skip traps XXX XXX XXX */
			if ((ag->feat >= FEAT_TRAP_HEAD) && (ag->feat <= FEAT_TRAP_TAIL)) continue;

			/* Extract the danger there */
			q = borg_danger(y, x, 2);

			/* Skip larger danger */
			if ((b_q >= 0) && (b_q < q)) continue;

			/* Track */
			b_q = q;
		}
	}

	/* Danger (ignore stupid "fear" danger) */
	if ((p > avoidance / 2) || (p > auto_fear_region[c_y/11][c_x/11]))
	{
		/* Describe (briefly) the current situation */
		borg_note(format("# Loc:%d,%d Dep:%d Lev:%d HP:%d/%d SP:%d/%d Danger:%d/%d",
		                 c_x, c_y, auto_depth, auto_level,
		                 auto_chp, auto_mhp, auto_csp, auto_msp,
		                 b_q, p));
	}

	/* No (good) retreat */
	if ((b_q < 0) || (b_q > p)) b_q = p;


	/*** Danger ***/

	/* Impending doom */
	if (borg_restock())
	{
		/* Start leaving */
		if (!goal_leaving)
		{
			/* Note */
			borg_note("# Leaving (restock)");

			/* Start leaving */
			goal_leaving = TRUE;
		}

		/* Start fleeing */
		if (!goal_fleeing)
		{
			/* Note */
			borg_note("# Fleeing (restock)");

			/* Start fleeing */
			goal_fleeing = TRUE;
		}
	}

	/* Excessive danger */
	else if (b_q > auto_mhp)
	{
		/* Start leaving */
		if (!goal_leaving)
		{
			/* Note */
			borg_note("# Leaving (excessive danger)");

			/* Start leaving */
			goal_leaving = TRUE;
		}

		/* Start fleeing */
		if (!goal_fleeing)
		{
			/* Note */
			borg_note("# Fleeing (excessive danger)");

			/* Start fleeing */
			goal_fleeing = TRUE;

			/* Fear this depth */
			auto_fear_depth[auto_depth] = TRUE;
		}
	}

	/* Moderate danger */
	else if (b_q > auto_mhp / 2)
	{
		/* Start leaving */
		if (!goal_leaving)
		{
			/* Flee! */
			borg_note("# Leaving (moderate danger)");

			/* Start leaving */
			goal_leaving = TRUE;
		}
	}

	/* Potential danger (near death) in town */
	else if (!auto_depth && (p > auto_chp))
	{
		/* Flee now */
		if (!goal_leaving)
		{
			/* Flee! */
			borg_note("# Leaving (potential danger)");

			/* Start leaving */
			goal_leaving = TRUE;
		}
	}


	/*** Stairs ***/

	/* Leaving or Fleeing, take stairs */
	if (goal_leaving || goal_fleeing)
	{
		/* Take next stairs */
		stair_less = stair_more = TRUE;
	}

	/* Take stairs up */
	if (stair_less || (b_q > auto_chp / 2))
	{
		/* Current grid */
		auto_grid *ag = &auto_grids[c_y][c_x];

		/* Usable stairs */
		if (ag->feat == FEAT_LESS)
		{
			/* Take the stairs */
			borg_keypress('<');

			/* Success */
			return (TRUE);
		}
	}

	/* Take stairs down */
	if (stair_more || (b_q > auto_chp / 2))
	{
		/* Current grid */
		auto_grid *ag = &auto_grids[c_y][c_x];

		/* Usable stairs */
		if (ag->feat == FEAT_MORE)
		{
			/* Take the stairs */
			borg_keypress('>');

			/* Success */
			return (TRUE);
		}
	}


	/*** Escape if possible ***/

	/* Attempt to escape */
	if (b_q > avoidance)
	{
		/* XXX XXX XXX Count close calls */

		/* Phase door, if useful */
		if (borg_caution_phase(10) &&
		    (borg_spell(0, 2) ||
		     borg_prayer(4, 0) ||
		     borg_read_scroll(SV_SCROLL_PHASE_DOOR)))
		{
			/* Hack -- reset the "goal" location */
			g_x = g_y = 0;

			/* Success */
			return (TRUE);
		}

		/* Teleport */
		if (TRUE &&
		    (borg_spell(1, 5) ||
		     borg_prayer(4, 1) ||
		     borg_prayer(1, 1) ||
		     borg_read_scroll(SV_SCROLL_TELEPORT) ||
		     borg_use_staff(SV_STAFF_TELEPORTATION)))
		{
			/* Hack -- reset the "goal" location */
			g_x = g_y = 0;

			/* Success */
			return (TRUE);
		}
	}

	/* Attempt to teleport (usually) */
	if (b_q > avoidance / 2)
	{
		/* XXX XXX XXX Count close calls */

		/* Phase door, if useful */
		if (borg_caution_phase(10) &&
		    (borg_spell(0, 2) ||
		     borg_prayer(4, 0) ||
		     borg_read_scroll(SV_SCROLL_PHASE_DOOR)))
		{
			/* Hack -- reset the "goal" location */
			g_x = g_y = 0;

			/* Success */
			return (TRUE);
		}

		/* Try teleportation */
		if ((rand_int(100) < 50) &&
		    (borg_spell(1, 5) ||
		     borg_prayer(4, 1) ||
		     borg_prayer(1, 1)))
		{
			/* Hack -- reset the "goal" location */
			g_x = g_y = 0;

			/* Success */
			return (TRUE);
		}
	}


	/*** Deal with critical situations ***/

	/* Hack -- require light */
	if (!my_lite)
	{
		auto_item *item = &auto_items[INVEN_LITE];

		/* Must have light -- Refuel current torch */
		if ((item->tval == TV_LITE) && (item->sval == SV_LITE_TORCH))
		{
			/* Try to refuel the torch */
			if ((item->pval < 500) && borg_refuel_torch()) return (TRUE);
		}

		/* Must have light -- Refuel current lantern */
		if ((item->tval == TV_LITE) && (item->sval == SV_LITE_LANTERN))
		{
			/* Try to refill the lantern */
			if ((item->pval < 1000) && borg_refuel_lantern()) return (TRUE);
		}

		/* Flee for fuel */
		if (auto_depth && (item->pval < 250))
		{
			/* Start leaving */
			if (!goal_leaving)
			{
				/* Flee */
				borg_note("# Leaving (need fuel)");

				/* Start leaving */
				goal_leaving = TRUE;
			}

			/* Start fleeing */
			if (!goal_fleeing)
			{
				/* Flee */
				borg_note("# Fleeing (need fuel)");

				/* Start fleeing */
				goal_fleeing = TRUE;
			}
		}
	}

	/* Hack -- prevent starvation */
	if (do_weak)
	{
		/* Attempt to satisfy hunger */
		if (borg_eat_food_any() ||
		    borg_spell(2, 0) ||
		    borg_prayer(1, 5))
		{
			/* Success */
			return (TRUE);
		}

		/* Flee for food */
		if (auto_depth)
		{
			/* Start leaving */
			if (!goal_leaving)
			{
				/* Flee */
				borg_note("# Leaving (need food)");

				/* Start leaving */
				goal_leaving = TRUE;
			}

			/* Start fleeing */
			if (!goal_fleeing)
			{
				/* Flee */
				borg_note("# Fleeing (need food)");

				/* Start fleeing */
				goal_fleeing = TRUE;
			}
		}
	}


	/*** Flee on foot ***/

	/* Strategic retreat */
	if (p > avoidance / 2)
	{
		int d, b_d = -1;
		int r, b_r = -1;

		int b_x = c_x;
		int b_y = c_y;


		/* Scan the useful viewable grids */
		for (j = 1; j < auto_view_n; j++)
		{
			int x1 = c_x;
			int y1 = c_y;

			int x2 = auto_view_x[j];
			int y2 = auto_view_y[j];


			/* Require "floor" grids */
			if (!borg_cave_floor_bold(y2, x2)) continue;

			/* Require "happy" grids */
			if (!borg_happy_grid_bold(y2, x2)) continue;

			/* Track "nearest" grid */
			if (b_r >= 0)
			{
				int ay = ((y2 > y1) ? (y2 - y1) : (y1 - y2));
				int ax = ((x2 > x1) ? (x2 - x1) : (x1 - x2));

				/* Ignore "distant" locations */
				if ((ax > b_r) || (ay > b_r)) continue;
			}


			/* Reset */
			r = 0;

			/* Simulate movement */
			while (1)
			{
				auto_grid *ag;

				/* Obtain direction */
				d = borg_goto_dir(y1, x1, y2, x2);

				/* Verify direction */
				if ((d == 0) || (d == 5)) break;

				/* Track distance */
				r++;

				/* Simulate the step */
				y1 += ddy[d];
				x1 += ddx[d];

				/* Obtain the grid */
				ag = &auto_grids[y1][x1];


				/* Require floor */
				if (!borg_cave_floor_grid(ag)) break;

				/* Require line of sight */
				if (!borg_los(y1, x1, y2, x2)) break;

				/* Check danger (over time) */
				if (borg_danger(y1, x1, r+1) > p) break;


				/* Skip monsters */
				if (ag->kill) break;

				/* Skip traps */
				if ((ag->feat >= FEAT_TRAP_HEAD) && (ag->feat <= FEAT_TRAP_TAIL)) break;


				/* Safe arrival */
				if ((x1 == x2) && (y1 == y2))
				{
					/* Save distance */
					b_r = r;

					/* Save location */
					b_x = x2;
					b_y = y2;

					/* Done */
					break;
				}
			}
		}

		/* Retreat */
		if (b_r >= 0)
		{
			/* Save direction */
			b_d = borg_goto_dir(c_y, c_x, b_y, b_x);

			/* Hack -- set goal */
			g_x = c_x + ddx[b_d];
			g_y = c_y + ddy[b_d];

			/* Note */
			borg_note(format("# Retreating to %d,%d (distance %d) via %d,%d (%d >= %d)",
			                 b_x, b_y, b_r, g_x, g_y, p, borg_danger(g_y, g_x, 2)));

			/* Strategic retreat */
			borg_keypress('0' + b_d);

			/* Success */
			return (TRUE);
		}
	}


	/* Want to back away */
	if (p > avoidance / 2)
	{
		int i, b_i = -1;
		int k, b_k = -1;
		int f, b_f = -1;

		/* Current danger */
		b_k = p;

		/* Check the freedom */
		b_f = borg_freedom(c_y, c_x);

		/* Attempt to find a better grid */
		for (i = 0; i < 8; i++)
		{
			int x = c_x + ddx_ddd[i];
			int y = c_y + ddy_ddd[i];

			/* Access the grid */
			auto_grid *ag = &auto_grids[y][x];

			/* Skip walls/doors */
			if (!borg_cave_floor_grid(ag)) continue;

			/* Skip monster grids */
			if (ag->kill) continue;

			/* Mega-Hack -- skip stores XXX XXX XXX */
			if ((ag->feat >= FEAT_SHOP_HEAD) && (ag->feat <= FEAT_SHOP_TAIL)) continue;

			/* Mega-Hack -- skip traps XXX XXX XXX */
			if ((ag->feat >= FEAT_TRAP_HEAD) && (ag->feat <= FEAT_TRAP_TAIL)) continue;

			/* Extract the danger there */
			k = borg_danger(y, x, 2);

			/* Skip higher danger */
			if (b_k < k) continue;

			/* Check the freedom */
			f = borg_freedom(y, x);

			/* Skip bad locations */
			if ((b_k == k) && (b_f > f)) continue;

			/* Save the info */
			b_i = i; b_k = k; b_f = f;
		}

		/* Back away */
		if (b_i >= 0)
		{
			/* Hack -- set goal */
			g_x = c_x + ddx_ddd[b_i];
			g_y = c_y + ddy_ddd[b_i];

			/* Note */
			borg_note(format("# Backing up to %d,%d (%d >= %d)",
			                 g_x, g_y, p, borg_danger(g_y, g_x, 2)));

			/* Back away from danger */
			borg_keypress('0' + ddd[b_i]);

			/* Success */
			return (TRUE);
		}

		/* Note */
		borg_note(format("# Cornered (danger %d)", p));
	}


	/*** Try healing ***/

	/* Hack -- heal when wounded (prayers) */
	if ((auto_chp <= auto_mhp / 2) && (rand_int(100) < 20))
	{
		if (borg_prayer(2, 2) ||
		    borg_prayer(2, 7) ||
		    borg_prayer(6, 0) ||
		    borg_prayer(6, 1))
		{
			return (TRUE);
		}
	}

	/* Hack -- heal when wounded */
	if ((auto_chp <= auto_mhp / 2) && (rand_int(100) < 20))
	{
		if (borg_quaff_potion(SV_POTION_CURE_CRITICAL) ||
		    borg_quaff_potion(SV_POTION_CURE_SERIOUS))
		{
			return (TRUE);
		}
	}

	/* Hack -- heal when blind/confused */
	if ((do_blind || do_confused) && (rand_int(100) < 20))
	{
		if (borg_quaff_potion(SV_POTION_CURE_SERIOUS) ||
		    borg_quaff_potion(SV_POTION_CURE_CRITICAL))
		{
			return (TRUE);
		}
	}

	/* Hack -- cure wounds when bleeding */
	if (do_cut && (rand_int(100) < 10))
	{
		if (borg_quaff_potion(SV_POTION_CURE_SERIOUS) ||
		    borg_quaff_potion(SV_POTION_CURE_CRITICAL))
		{
			return (TRUE);
		}
	}

	/* Hack -- cure poison when poisoned */
	if (do_poisoned && (rand_int(100) < 10))
	{
		if (borg_spell(1, 4) ||
		    borg_prayer(2, 0) ||
		    borg_quaff_potion(SV_POTION_CURE_POISON) ||
		    borg_quaff_potion(SV_POTION_CURE_CRITICAL))
		{
			return (TRUE);
		}
	}

	/* Hack -- cure fear when afraid */
	if (do_afraid && (rand_int(100) < 10))
	{
		if (borg_prayer(0, 3) ||
		    borg_quaff_potion(SV_POTION_BOLDNESS) ||
		    borg_quaff_potion(SV_POTION_HEROISM) ||
		    borg_quaff_potion(SV_POTION_BESERK_STRENGTH))
		{
			return (TRUE);
		}
	}


	/*** Note impending death XXX XXX XXX ***/

	/* Flee from low hit-points */
	if ((auto_chp < auto_mhp / 2) &&
	    (amt_cure_critical < 5))
	{
		/* Flee from low hit-points */
		if (auto_depth && (rand_int(100) < 25))
		{
			/* Start leaving */
			if (!goal_leaving)
			{
				/* Flee */
				borg_note("# Leaving (low hit-points)");

				/* Start leaving */
				goal_leaving = TRUE;
			}

			/* Start fleeing */
			if (!goal_fleeing)
			{
				/* Flee */
				borg_note("# Fleeing (low hit-points)");

				/* Start fleeing */
				goal_fleeing = TRUE;

				/* Fear this depth */
				auto_fear_depth[auto_depth] = TRUE;
			}
		}
	}

	/* Hack -- use "recall" to flee if possible */
	if (goal_fleeing && auto_depth && (borg_recall()))
	{
		/* Note */
		borg_note("# Fleeing the level (recall)");

		/* Success */
		return (TRUE);
	}


	/* Nothing */
	return (FALSE);
}



/*
 * New method for handling attacks, missiles, and spells
 *
 * Every turn, we evaluate every known method of causing damage
 * to monsters, and evaluate the "reward" inherent in each of
 * the known methods which is usable at that time, and then
 * we actually use whichever method, if any, scores highest.
 *
 * For each attack, we need a function which will determine the best
 * possible result of using that attack, and return its value.  Also,
 * if requested, the function should actually perform the action.
 *
 * Note that the functions should return zero if the action is not
 * usable, or if the action is not useful.
 *
 * These functions need to apply some form of "cost" evaluation, to
 * prevent the use of expensive spells with minimal reward.  Also,
 * we should always prefer attacking by hand to using spells if the
 * damage difference is "small", since there is no "cost" in making
 * a physical attack.
 *
 * We should take account of "spell failure", as well as "missile
 * missing" and "blow missing" probabilities.
 *
 * Note that the functions may store local state information when
 * doing a "simulation" and then they can use this information if
 * they are asked to implement their strategy.
 *
 * XXX XXX XXX
 *
 * We should "reward" doing damage to monsters which are "dangerous",
 * unless they are sleeping, in which case we should penalize waking
 * them up, unless we can kill them instantly.  Note that this means
 * that killing a single "gnome mage" with 10 hitpoints should be
 * considered "better" than doing 30 damage to a "white jelly",
 * since the "gnome mage" is much more "dangerous".  We should
 * check the danger over several turns, to take account of nasty
 * monsters which are not right next to us.
 *
 * We should attempt to apply any "brand" effects of the current
 * "weapon" and/or "ammo".
 *
 * We should "attempt" to keep track of each monsters "hitpoints",
 * since this will make the attack code "smarter", but we should
 * not be too optimistic, since mistakes could be fatal.
 *
 * We should try to avoid damaging objects on the ground, that is,
 * we should not use "frost ball" near potions, etc.
 *
 * Note that all "fire" commands have a minimum range of 20, but the
 * various "throw" commands have a range which is limited by strength
 * and weight, and is limited to a total distance of ten.  We should
 * attempt to take into to account the "effective" range.  XXX XXX XXX
 *
 * There are several types of damage inducers:
 *
 *   Attacking physically
 *   Launching missiles
 *   Throwing objects
 *   Casting spells
 *   Praying prayers
 *   Using wands
 *   Using rods
 *   Using staffs
 *   Using scrolls
 */
enum
{
	BF_THRUST,

	BF_LAUNCH,

	BF_OBJECT,

	BF_SPELL_MAGIC_MISSILE,
	BF_SPELL_ELEC_BOLT,
	BF_SPELL_COLD_BOLT,
	BF_SPELL_FIRE_BOLT,
	BF_SPELL_ACID_BOLT,

	BF_SPELL_LITE_BEAM,

	BF_SPELL_POISON_BALL,
	BF_SPELL_COLD_BALL,
	BF_SPELL_ACID_BALL,
	BF_SPELL_FIRE_BALL,

	BF_SPELL_POISON_STORM,
	BF_SPELL_COLD_STORM,
	BF_SPELL_METEOR_STORM,
	BF_SPELL_MANA_STORM,

	BF_PRAYER_HOLY_ORB_BALL,

	BF_ROD_ELEC_BOLT,
	BF_ROD_COLD_BOLT,
	BF_ROD_ACID_BOLT,
	BF_ROD_FIRE_BOLT,

	BF_ROD_LITE_BEAM,

	BF_ROD_ELEC_BALL,
	BF_ROD_COLD_BALL,
	BF_ROD_ACID_BALL,
	BF_ROD_FIRE_BALL,

	BF_WAND_MAGIC_MISSILE,
	BF_WAND_ELEC_BOLT,
	BF_WAND_COLD_BOLT,
	BF_WAND_ACID_BOLT,
	BF_WAND_FIRE_BOLT,

	BF_WAND_LITE_BEAM,

	BF_WAND_STINKING_CLOUD,
	BF_WAND_ELEC_BALL,
	BF_WAND_COLD_BALL,
	BF_WAND_ACID_BALL,
	BF_WAND_FIRE_BALL,

	BF_WAND_DRAGON_COLD,
	BF_WAND_DRAGON_FIRE,

	BF_MAX
};



/*
 * Guess how much damage a physical attack will do to a monster
 *
 * We ignore "brands" and such for now
 */
static int borg_thrust_damage_one(int i)
{
	int dam;

	auto_kill *kill;

	monster_race *r_ptr;

	auto_item *item;


	/* Examine current weapon */
	item = &auto_items[INVEN_WIELD];


	/* Monster record */
	kill = &auto_kills[i];

	/* Monster race */
	r_ptr = &r_info[kill->r_idx];


	/* Damage */
	dam = (item->dd * (item->ds + 1) / 2);
	dam = dam + item->to_d + my_to_dam;
	dam = dam * my_num_blow;


	/* Limit damage to twice maximal hitpoints */
	if (dam > kill->power * 2) dam = kill->power * 2;


	/* Damage */
	return (dam);
}



/*
 * Simulate/Apply the optimal result of making a physical attack
 */
static int borg_attack_aux_thrust(void)
{
	int p, dir;

	int num = 0;

	int i, b_i = -1;
	int d, b_d = -1;

	auto_grid *ag;

	auto_kill *kill;


	/* Too afraid to attack */
	if (do_afraid) return (0);


	/* Examine possible destinations */
	for (i = 0; i < auto_temp_n; i++)
	{
		int x = auto_temp_x[i];
		int y = auto_temp_y[i];

		/* Require "adjacent" */
		if (distance(c_y, c_x, y, x) > 1) continue;

		/* Acquire grid */
		ag = &auto_grids[y][x];

		/* Calculate "average" damage */
		d = borg_thrust_damage_one(ag->kill);

		/* No damage */
		if (d <= 0) continue;

		/* Obtain the monster */
		kill = &auto_kills[ag->kill];

		/* Calculate danger */
		p = borg_danger_aux(y, x, 1, ag->kill);

		/* Hack -- avoid waking most "hard" sleeping monsters */
		if (!kill->awake && (p > avoidance / 2) && (d <= kill->power))
		{
			continue;
		}

		/* Calculate "danger" to player */
		p = borg_danger_aux(c_y, c_x, 4, ag->kill);

		/* Reduce "bonus" of partial kills */
		if (d <= kill->power) p = p / 10;

		/* Add the danger to the damage */
		d += p;

		/* Ignore lower damage */
		if ((b_i >= 0) && (d < b_d)) continue;

		/* Hack -- reset chooser */
		if ((b_i >= 0) && (d > b_d)) num = 0;

		/* Apply the randomizer */
		if ((num > 1) && (rand_int(num) != 0)) continue;

		/* Save the info */
		b_i = i;
		b_d = d;
	}

	/* Nothing to attack */
	if (b_i < 0) return (0);


	/* Simulation */
	if (auto_simulate) return (b_d);


	/* Save the location */
	g_x = auto_temp_x[b_i];
	g_y = auto_temp_y[b_i];


	/* Note */
	borg_note(format("# Facing location (%d,%d)",
	                 g_x, g_y));

	/* Note */
	borg_note(format("# Attacking with weapon '%s'",
	                 auto_items[INVEN_WIELD].desc));

	/* Get a direction for attacking */
	dir = borg_extract_dir(c_y, c_x, g_y, g_x);

	/* Attack */
	borg_keypress('+');

	/* Attack the grid */
	borg_keypress('0' + dir);

	/* Success */
	return (b_d);
}




/*
 * Target a location.  Can be used alone or at "Direction?" prompt.
 *
 * Warning -- This will only work for locations on the current panel
 */
static bool borg_target(int y, int x)
{
	int x1, y1, x2, y2;

	/* Log */
	borg_note(format("# Targetting location (%d,%d)", x, y));

	/* Target mode */
	borg_keypress('*');

	/* Target a location */
	borg_keypress('p');

	/* Determine "path" */
	x1 = c_x;
	y1 = c_y;
	x2 = x;
	y2 = y;

	/* Move to the location (diagonals) */
	for (; (y1 < y2) && (x1 < x2); y1++, x1++) borg_keypress('3');
	for (; (y1 < y2) && (x1 > x2); y1++, x1--) borg_keypress('1');
	for (; (y1 > y2) && (x1 < x2); y1--, x1++) borg_keypress('9');
	for (; (y1 > y2) && (x1 > x2); y1--, x1--) borg_keypress('7');

	/* Move to the location */
	for (; y1 < y2; y1++) borg_keypress('2');
	for (; y1 > y2; y1--) borg_keypress('8');
	for (; x1 < x2; x1++) borg_keypress('6');
	for (; x1 > x2; x1--) borg_keypress('4');

	/* Select the target */
	borg_keypress('5');

	/* Success */
	return (TRUE);
}



/*
 * Guess how much damage a spell attack will do to a monster
 *
 * We only handle the "standard" damage types.
 *
 * We are paranoid about monster resistances
 *
 * We ignore "special" effects for now
 */
static int borg_launch_damage_one(int i, int dam, int typ)
{
	auto_kill *kill;

	monster_race *r_ptr;


	/* Monster record */
	kill = &auto_kills[i];

	/* Monster race */
	r_ptr = &r_info[kill->r_idx];


	/* Analyze the damage type */
	switch (typ)
	{
		/* Magic Missile */
		case GF_MISSILE:
		{
			break;
		}

		/* Arrow */
		case GF_ARROW:
		{
			break;
		}

		/* Pure damage */
		case GF_MANA:
		{
			break;
		}

		/* Meteor -- powerful magic missile */
		case GF_METEOR:
		{
			break;
		}


		/* Acid */
		case GF_ACID:
		{
			if (r_ptr->flags3 & RF3_IM_ACID) dam /= 9;
			break;
		}

		/* Electricity */
		case GF_ELEC:
		{
			if (r_ptr->flags3 & RF3_IM_ELEC) dam /= 9;
			break;
		}

		/* Fire damage */
		case GF_FIRE:
		{
			if (r_ptr->flags3 & RF3_IM_FIRE) dam /= 9;
			break;
		}

		/* Cold */
		case GF_COLD:
		{
			if (r_ptr->flags3 & RF3_IM_COLD) dam /= 9;
			break;
		}

		/* Poison */
		case GF_POIS:
		{
			if (r_ptr->flags3 & RF3_IM_POIS) dam /= 9;
			break;
		}

		/* Ice */
		case GF_ICE:
		{
			if (r_ptr->flags3 & RF3_IM_COLD) dam /= 9;
			break;
		}


		/* Holy Orb */
		case GF_HOLY_ORB:
		{
			if (r_ptr->flags3 & RF3_EVIL) dam *= 2;
			break;
		}


		/* Weak Lite */
		case GF_LITE_WEAK:
		{
			if (!(r_ptr->flags3 & RF3_HURT_LITE)) dam = 0;
			break;
		}


		/* Drain Life */
		case GF_OLD_DRAIN:
		{
			if ((r_ptr->flags3 & RF3_UNDEAD) ||
			    (r_ptr->flags3 & RF3_DEMON) ||
			    (strchr("Egv", r_ptr->d_char)))
			{
				dam = 0;
			}
			break;
		}


		/* Weird attacks */
		case GF_PLASMA:
		case GF_NETHER:
		case GF_WATER:
		case GF_CHAOS:
		case GF_SHARD:
		case GF_SOUND:
		case GF_CONFUSION:
		case GF_DISENCHANT:
		case GF_NEXUS:
		case GF_FORCE:
		case GF_INERTIA:
		case GF_TIME:
		case GF_GRAVITY:
		case GF_LITE:
		case GF_DARK:
		{
			dam /= 2;
			break;
		}


		/* Various */
		case GF_OLD_SLOW:
		case GF_OLD_CONF:
		case GF_OLD_SLEEP:
		case GF_OLD_POLY:
		case GF_OLD_HEAL:
		case GF_OLD_CLONE:
		case GF_OLD_SPEED:
		case GF_DARK_WEAK:
		case GF_KILL_WALL:
		case GF_KILL_DOOR:
		case GF_KILL_TRAP:
		case GF_MAKE_WALL:
		case GF_MAKE_DOOR:
		case GF_MAKE_TRAP:
		case GF_AWAY_UNDEAD:
		case GF_AWAY_EVIL:
		case GF_AWAY_ALL:
		case GF_TURN_UNDEAD:
		case GF_TURN_EVIL:
		case GF_TURN_ALL:
		case GF_DISP_UNDEAD:
		case GF_DISP_EVIL:
		case GF_DISP_ALL:
		{
			dam = 0;
			break;
		}
	}


	/* Limit damage to twice maximal hitpoints */
	if (dam > kill->power * 2) dam = kill->power * 2;


	/* Damage */
	return (dam);
}



/*
 * Simulate / Invoke the launching of a bolt at a monster
 */
static int borg_launch_bolt_aux_hack(int i, int dam, int typ)
{
	int d, p, x, y;

	auto_grid *ag;

	auto_kill *kill;


	/* Monster */
	kill = &auto_kills[i];

	/* Skip dead monsters */
	if (!kill->r_idx) return (0);

	/* Require current knowledge */
	if (kill->when < c_t) return (0);

	/* Acquire location */
	x = kill->x;
	y = kill->y;

	/* Acquire the grid */
	ag = &auto_grids[y][x];

	/* Never shoot walls/doors */
	if (!borg_cave_floor_grid(ag)) return (0);

	/* Hack -- Unknown grids should be avoided some of the time */
	if ((ag->feat == FEAT_NONE) && ((c_t % 8) == 0)) return (0);

	/* Hack -- Weird grids should be avoided some of the time */
	if ((ag->feat == FEAT_INVIS) && ((c_t % 8) == 0)) return (0);

	/* Calculate damage */
	d = borg_launch_damage_one(i, dam, typ);

	/* No damage */
	if (d <= 0) return (0);

	/* Calculate danger */
	p = borg_danger_aux(y, x, 1, i);

	/* Hack -- avoid waking most "hard" sleeping monsters */
	if (!kill->awake && (p > avoidance / 2) && (d <= kill->power))
	{
		return (-999);
	}

	/* Hack -- ignore "easy" / "sleeping" town monsters */
	if (!auto_depth && (!kill->awake || (p <= 0)))
	{
		return (0);
	}

	/* Calculate "danger" to player */
	p = borg_danger_aux(c_y, c_x, 4, i);

	/* Reduce "bonus" of partial kills */
	if (d <= kill->power) p = p / 10;

	/* Add in power */
	d += p;

	/* Result */
	return (d);
}


/*
 * Determine the "reward" of launching a beam/bolt/ball at a location
 *
 * An "unreachable" location always has zero reward.
 *
 * Basically, we sum the "rewards" of doing the appropriate amount of
 * damage to each of the "affected" monsters.
 */
static int borg_launch_bolt_aux(int y, int x, int rad, int dam, int typ, int max)
{
	int i;

	int x1, y1;
	int x2, y2;

	int dist;

	int r, n;

	auto_grid *ag;


	/* Reset damage */
	n = 0;

	/* Initial location */
	x1 = c_x; y1 = c_y;

	/* Final location */
	x2 = x; y2 = y;

	/* Start over */
	x = x1; y = y1;

	/* Simulate the spell/missile path */
	for (dist = 0; dist < max; dist++)
	{
		/* Get the grid */
		ag = &auto_grids[y][x];

		/* Stop at walls */
		if (dist && !borg_cave_floor_grid(ag)) return (0);

		/* Collect damage (bolts/beams) */
		if (rad <= 0) n += borg_launch_bolt_aux_hack(ag->kill, dam, typ);

		/* Check for arrival at "final target" */
		if ((x == x2) && (y == y2)) break;

		/* Stop at monsters (bolts) */
		if (!rad && ag->kill) return (0);

		/* Stop at unknown grids (see above) */
		if (dist && (ag->feat == FEAT_NONE)) return (0);

		/* Stop at weird grids (see above) */
		if (dist && (ag->feat == FEAT_INVIS)) return (0);

		/* Calculate the new location */
		mmove2(&y, &x, y1, x1, y2, x2);
	}

	/* Bolt/Beam attack */
	if (rad <= 0) return (n);

	/* Excessive distance */
	if (dist >= MAX_RANGE) return (0);

	/* Check monsters in blast radius */
	for (i = 0; i < auto_temp_n; i++)
	{
		/* Acquire location */
		x = auto_temp_x[i];
		y = auto_temp_y[i];

		/* Get the grid */
		ag = &auto_grids[y][x];

		/* Check distance */
		r = distance(y2, x2, y, x);

		/* Maximal distance */
		if (r > rad) continue;

		/* Never pass through walls */
		if (!borg_los(y2, x2, y, x)) continue;

		/* Collect damage, lowered by distance */
		n += borg_launch_bolt_aux_hack(ag->kill, dam / (r + 1), typ);
	}

	/* Result */
	return (n);
}


/*
 * Simulate/Apply the optimal result of launching a beam/bolt/ball
 *
 * Note that "beams" have a "rad" of "-1", "bolts" have a "rad" of "0",
 * and "balls" have a "rad" of "2" or "3", depending on "blast radius".
 */
static int borg_launch_bolt(int rad, int dam, int typ, int max)
{
	int num = 0;

	int i, b_i = -1;
	int n, b_n = 0;


	/* Examine possible destinations */
	for (i = 0; i < auto_temp_n; i++)
	{
		int x = auto_temp_x[i];
		int y = auto_temp_y[i];

		/* Consider it */
		n = borg_launch_bolt_aux(y, x, rad, dam, typ, max);

		/* Skip useless attacks */
		if (n <= 0) continue;

		/* Collect best attack */
		if ((b_i >= 0) && (n < b_n)) continue;

		/* Hack -- reset chooser */
		if ((b_i >= 0) && (n > b_n)) num = 0;

		/* Apply the randomizer */
		if ((num > 1) && (rand_int(num) != 0)) continue;

		/* Track it */
		b_i = i;
		b_n = n;
	}

	/* Simulation */
	if (auto_simulate) return (b_n);


	/* Save the location */
	g_x = auto_temp_x[b_i];
	g_y = auto_temp_y[b_i];

	/* Target the location */
	(void)borg_target(g_y, g_x);

	/* Result */
	return (b_n);
}


/*
 * Simulate/Apply the optimal result of launching a normal missile
 *
 * First, pick the "optimal" ammo, then pick the optimal target
 */
static int borg_attack_aux_launch(void)
{
	int b_n;

	int k, b_k = -1;
	int d, b_d = -1;

	auto_item *bow = &auto_items[INVEN_BOW];


	/* Scan the pack */
	for (k = 0; k < INVEN_PACK; k++)
	{
		auto_item *item = &auto_items[k];

		/* Skip empty items */
		if (!item->iqty) continue;

		/* Skip bad missiles */
		if (item->tval != my_ammo_tval) continue;

		/* Skip worthless missiles */
		if (item->value <= 0) continue;

		/* Skip un-identified, non-average, missiles */
		if (!item->able && !streq(item->note, "{average}")) continue;

		/* Determine average damage */
		d = (item->dd * (item->ds + 1) / 2);
		d = d + item->to_d + bow->to_d;
		d = d * my_ammo_power * my_num_fire;

		/* Paranoia */
		if (d <= 0) continue;

		/* Ignore worse damage */
		if ((b_k >= 0) && (d <= b_d)) continue;

		/* Track */
		b_k = k;
		b_d = d;
	}

	/* Nothing to use */
	if (b_k < 0) return (0);


	/* No firing while blind, confused, or hallucinating */
	if (do_blind || do_confused || do_image) return (0);


	/* Choose optimal location */
	b_n = borg_launch_bolt(0, b_d, GF_ARROW, MAX_RANGE);

	/* Cost one point */
	b_n = b_n - 1;

	/* Simulation */
	if (auto_simulate) return (b_n);


	/* Do it */
	borg_note(format("# Firing standard missile '%s'",
	                 auto_items[b_k].desc));

	/* Fire */
	borg_keypress('f');

	/* Use the missile */
	borg_keypress(I2A(b_k));

	/* Use target */
	borg_keypress('5');

	/* Value */
	return (b_n);
}



/*
 * Simulate/Apply the optimal result of throwing an object
 *
 * First choose the "best" object to throw, then check targets.
 */
static int borg_attack_aux_object(void)
{
	int b_n;

	int b_r = 0;

	int k, b_k = -1;
	int d, b_d = -1;

	int div, mul;

	/* Scan the pack */
	for (k = 0; k < INVEN_PACK; k++)
	{
		auto_item *item = &auto_items[k];

		/* Skip empty items */
		if (!item->iqty) continue;

		/* Skip un-identified, non-average, objects */
		if (!item->able && !streq(item->note, "{average}")) continue;

		/* Skip "equipment" items (not ammo) */
		if (borg_wield_slot(item) >= 0) continue;

		/* Determine average damage from object */
		d = (k_info[item->kind].dd * (k_info[item->kind].ds + 1) / 2);

		/* Skip useless stuff */
		if (d <= 0) continue;

		/* Skip "expensive" stuff */
		if (d < item->value) continue;

		/* Hack -- Save last five flasks for fuel, if needed */
		if ((item->tval == TV_FLASK) && (amt_fuel <= 5)) continue;

		/* Ignore worse damage */
		if ((b_k >= 0) && (d <= b_d)) continue;

		/* Track */
		b_k = k;
		b_d = d;

		/* Extract a "distance multiplier" */
		mul = 10;

		/* Enforce a minimum "weight" of one pound */
		div = ((item->weight > 10) ? item->weight : 10);

		/* Hack -- Distance -- Reward strength, penalize weight */
		b_r = (adj_str_blow[my_stat_ind[A_STR]] + 20) * mul / div;

		/* Max distance of 10 */
		if (b_r > 10) b_r = 10;
	}

	/* Nothing to use */
	if (b_k < 0) return (0);


	/* No firing while blind, confused, or hallucinating */
	if (do_blind || do_confused || do_image) return (0);


	/* Choose optimal location */
	b_n = borg_launch_bolt(0, b_d, GF_ARROW, b_r);

	/* Cost one point */
	b_n = b_n - 1;

	/* Simulation */
	if (auto_simulate) return (b_n);


	/* Do it */
	borg_note(format("# Throwing painful object '%s'",
	                 auto_items[b_k].desc));

	/* Fire */
	borg_keypress('v');

	/* Use the object */
	borg_keypress(I2A(b_k));

	/* Use target */
	borg_keypress('5');

	/* Value */
	return (b_n);
}




/*
 * Simulate/Apply the optimal result of using a "normal" attack spell
 *
 * Take into account the failure rate of spells/objects/etc.  XXX XXX XXX
 */
static int borg_attack_aux_spell_bolt(int book, int what, int rad, int dam, int typ)
{
	int b_n;

	auto_magic *as = &auto_magics[book][what];


	/* No firing while blind, confused, or hallucinating */
	if (do_blind || do_confused || do_image) return (0);


	/* Paranoia */
	if (auto_simulate && (rand_int(100) < 10)) return (0);


	/* Require ability (right now) */
	if (!borg_spell_okay(book, what)) return (0);


	/* Choose optimal location */
	b_n = borg_launch_bolt(rad, dam, typ, MAX_RANGE);

	/* Penalize mana usage */
	b_n = b_n - as->power;

	/* Penalize use of reserve mana */
	if (auto_csp - as->power < auto_msp / 2) b_n = b_n - as->power * 10;

	/* Simulation */
	if (auto_simulate) return (b_n);


	/* Cast the spell */
	(void)borg_spell(book, what);

	/* Use target */
	borg_keypress('5');

	/* Value */
	return (b_n);
}



/*
 * Simulate/Apply the optimal result of using a "normal" attack prayer
 */
static int borg_attack_aux_prayer_bolt(int book, int what, int rad, int dam, int typ)
{
	int b_n;

	auto_magic *as = &auto_magics[book][what];


	/* No firing while blind, confused, or hallucinating */
	if (do_blind || do_confused || do_image) return (0);


	/* Paranoia */
	if (auto_simulate && (rand_int(100) < 10)) return (0);


	/* Require ability */
	if (!borg_prayer_okay(book, what)) return (0);


	/* Choose optimal location */
	b_n = borg_launch_bolt(rad, dam, typ, MAX_RANGE);

	/* Penalize mana usage */
	b_n = b_n - as->power;

	/* Penalize use of reserve mana */
	if (auto_csp - as->power < auto_msp / 2) b_n = b_n - as->power * 10;

	/* Simulation */
	if (auto_simulate) return (b_n);


	/* Cast the prayer */
	(void)borg_prayer(book, what);

	/* Use target */
	borg_keypress('5');

	/* Value */
	return (b_n);
}



/*
 * Simulate/Apply the optimal result of using a "normal" attack rod
 */
static int borg_attack_aux_rod_bolt(int sval, int rad, int dam, int typ)
{
	int i;

	int b_n;


	/* No firing while blind, confused, or hallucinating */
	if (do_blind || do_confused || do_image) return (0);


	/* Paranoia */
	if (auto_simulate && (rand_int(100) < 10)) return (0);


	/* Look for that rod */
	i = borg_slot(TV_ROD, sval);

	/* None available */
	if (i < 0) return (0);

	/* Still "charging" */
	if (!auto_items[i].pval) return (0);


	/* Choose optimal location */
	b_n = borg_launch_bolt(rad, dam, typ, MAX_RANGE);

	/* Simulation */
	if (auto_simulate) return (b_n);


	/* Zap the rod */
	(void)borg_zap_rod(sval);

	/* Use target */
	borg_keypress('5');

	/* Value */
	return (b_n);
}



/*
 * Simulate/Apply the optimal result of using a "normal" attack wand
 */
static int borg_attack_aux_wand_bolt(int sval, int rad, int dam, int typ)
{
	int i;

	int b_n;


	/* No firing while blind, confused, or hallucinating */
	if (do_blind || do_confused || do_image) return (0);


	/* Paranoia */
	if (auto_simulate && (rand_int(100) < 10)) return (0);


	/* Look for that wand */
	i = borg_slot(TV_WAND, sval);

	/* None available */
	if (i < 0) return (0);

	/* No charges */
	if (!auto_items[i].pval) return (0);


	/* Choose optimal location */
	b_n = borg_launch_bolt(rad, dam, typ, MAX_RANGE);

	/* Penalize charge usage */
	b_n = b_n - 5;

	/* Simulation */
	if (auto_simulate) return (b_n);


	/* Aim the wand */
	(void)borg_aim_wand(sval);

	/* Use target */
	borg_keypress('5');

	/* Value */
	return (b_n);
}



/*
 * Simulate/Apply the optimal result of using the given "type" of attack
 */
static int borg_attack_aux(int what)
{
	int dam = 0, rad = 0;

	/* Analyze */
	switch (what)
	{
		/* Physical attack */
		case BF_THRUST:
		{
			return (borg_attack_aux_thrust());
		}


		/* Missile attack */
		case BF_LAUNCH:
		{
			return (borg_attack_aux_launch());
		}


		/* Object attack */
		case BF_OBJECT:
		{
			return (borg_attack_aux_object());
		}


		/* Spell -- magic missile */
		case BF_SPELL_MAGIC_MISSILE:
		{
			dam = (3+((auto_level-1)/5))*(4+1)/2;
			return (borg_attack_aux_spell_bolt(0, 0, rad, dam, GF_MISSILE));
		}

		/* Spell -- electric bolt */
		case BF_SPELL_ELEC_BOLT:
		{
			dam = (3+((auto_level-5)/4))*(8+1)/2;
			return (borg_attack_aux_spell_bolt(1, 1, rad, dam, GF_ELEC));
		}

		/* Spell -- cold bolt */
		case BF_SPELL_COLD_BOLT:
		{
			dam = (5+((auto_level-5)/4))*(8+1)/2;
			return (borg_attack_aux_spell_bolt(1, 7, rad, dam, GF_COLD));
		}

		/* Spell -- fire bolt */
		case BF_SPELL_FIRE_BOLT:
		{
			dam = (8+((auto_level-5)/4))*(8+1)/2;
			return (borg_attack_aux_spell_bolt(2, 6, rad, dam, GF_FIRE));
		}

		/* Spell -- acid bolt */
		case BF_SPELL_ACID_BOLT:
		{
			dam = (6+((auto_level-5)/4))*(8+1)/2;
			return (borg_attack_aux_spell_bolt(8, 0, rad, dam, GF_ACID));
		}


		/* Spell -- light beam */
		case BF_SPELL_LITE_BEAM:
		{
			rad = -1;
			dam = (6*(8+1)/2);
			return (borg_attack_aux_spell_bolt(8, 0, rad, dam, GF_LITE_WEAK));
		}


		/* Spell -- stinking cloud */
		case BF_SPELL_POISON_BALL:
		{
			rad = 2;
			dam = (10 + (auto_level/2));
			return (borg_attack_aux_spell_bolt(0, 8, rad, dam, GF_POIS));
		}

		/* Spell -- cold ball */
		case BF_SPELL_COLD_BALL:
		{
			rad = 2;
			dam = (30 + auto_level);
			return (borg_attack_aux_spell_bolt(3, 0, rad, dam, GF_COLD));
		}

		/* Spell -- acid ball */
		case BF_SPELL_ACID_BALL:
		{
			rad = 2;
			dam = (40 + (auto_level/2));
			return (borg_attack_aux_spell_bolt(8, 2, rad, dam, GF_ACID));
		}

		/* Spell -- fire ball */
		case BF_SPELL_FIRE_BALL:
		{
			rad = 2;
			dam = (55 + auto_level);
			return (borg_attack_aux_spell_bolt(3, 4, rad, dam, GF_FIRE));
		}


		/* Spell -- poison storm */
		case BF_SPELL_POISON_STORM:
		{
			rad = 3;
			dam = (20 + (auto_level/2));
			return (borg_attack_aux_spell_bolt(8, 1, rad, dam, GF_POIS));
		}

		/* Spell -- cold storm */
		case BF_SPELL_COLD_STORM:
		{
			rad = 3;
			dam = (70 + auto_level);
			return (borg_attack_aux_spell_bolt(8, 3, rad, dam, GF_COLD));
		}

		/* Spell -- meteor storm */
		case BF_SPELL_METEOR_STORM:
		{
			rad = 3;
			dam = (65 + auto_level);
			return (borg_attack_aux_spell_bolt(8, 4, rad, dam, GF_METEOR));
		}

		/* Spell -- mana storm */
		case BF_SPELL_MANA_STORM:
		{
			rad = 3;
			dam = (300 + (auto_level * 2));
			return (borg_attack_aux_spell_bolt(8, 5, rad, dam, GF_MANA));
		}


		/* Prayer -- orb of draining */
		case BF_PRAYER_HOLY_ORB_BALL:
		{
			rad = ((auto_level >= 30) ? 3 : 2);
			dam = ((auto_class == 2) ? 2 : 4);
			dam = (3*(8+1)/2 + auto_level + (auto_level/dam));
			return (borg_attack_aux_prayer_bolt(2, 1, rad, dam, GF_HOLY_ORB));
		}


		/* Wand -- elec bolt */
		case BF_ROD_ELEC_BOLT:
		{
			dam = 3*(8+1)/2;
			return (borg_attack_aux_rod_bolt(SV_ROD_ELEC_BOLT, rad, dam, GF_ELEC));
		}

		/* Wand -- cold bolt */
		case BF_ROD_COLD_BOLT:
		{
			dam = 5*(8+1)/2;
			return (borg_attack_aux_rod_bolt(SV_ROD_COLD_BOLT, rad, dam, GF_COLD));
		}

		/* Wand -- acid bolt */
		case BF_ROD_ACID_BOLT:
		{
			dam = 6*(8+1)/2;
			return (borg_attack_aux_rod_bolt(SV_ROD_ACID_BOLT, rad, dam, GF_ACID));
		}

		/* Wand -- fire bolt */
		case BF_ROD_FIRE_BOLT:
		{
			dam = 8*(8+1)/2;
			return (borg_attack_aux_rod_bolt(SV_ROD_FIRE_BOLT, rad, dam, GF_FIRE));
		}


		/* Spell -- light beam */
		case BF_ROD_LITE_BEAM:
		{
			rad = -1;
			dam = (6*(8+1)/2);
			return (borg_attack_aux_rod_bolt(SV_ROD_LITE, rad, dam, GF_LITE_WEAK));
		}


		/* Wand -- elec ball */
		case BF_ROD_ELEC_BALL:
		{
			rad = 2;
			dam = 32;
			return (borg_attack_aux_rod_bolt(SV_ROD_ELEC_BALL, rad, dam, GF_ELEC));
		}

		/* Wand -- acid ball */
		case BF_ROD_COLD_BALL:
		{
			rad = 2;
			dam = 48;
			return (borg_attack_aux_rod_bolt(SV_ROD_COLD_BALL, rad, dam, GF_COLD));
		}

		/* Wand -- acid ball */
		case BF_ROD_ACID_BALL:
		{
			rad = 2;
			dam = 60;
			return (borg_attack_aux_rod_bolt(SV_ROD_ACID_BALL, rad, dam, GF_ACID));
		}

		/* Wand -- fire ball */
		case BF_ROD_FIRE_BALL:
		{
			rad = 2;
			dam = 72;
			return (borg_attack_aux_rod_bolt(SV_ROD_FIRE_BALL, rad, dam, GF_FIRE));
		}


		/* Wand -- magic missile */
		case BF_WAND_MAGIC_MISSILE:
		{
			dam = 2*(6+1)/2;
			return (borg_attack_aux_wand_bolt(SV_WAND_MAGIC_MISSILE, rad, dam, GF_MISSILE));
		}

		/* Wand -- elec bolt */
		case BF_WAND_ELEC_BOLT:
		{
			dam = 3*(8+1)/2;
			return (borg_attack_aux_wand_bolt(SV_WAND_ELEC_BOLT, rad, dam, GF_ELEC));
		}

		/* Wand -- cold bolt */
		case BF_WAND_COLD_BOLT:
		{
			dam = 3*(8+1)/2;
			return (borg_attack_aux_wand_bolt(SV_WAND_COLD_BOLT, rad, dam, GF_COLD));
		}

		/* Wand -- acid bolt */
		case BF_WAND_ACID_BOLT:
		{
			dam = 5*(8+1)/2;
			return (borg_attack_aux_wand_bolt(SV_WAND_ACID_BOLT, rad, dam, GF_ACID));
		}

		/* Wand -- fire bolt */
		case BF_WAND_FIRE_BOLT:
		{
			dam = 6*(8+1)/2;
			return (borg_attack_aux_wand_bolt(SV_WAND_FIRE_BOLT, rad, dam, GF_FIRE));
		}


		/* Spell -- light beam */
		case BF_WAND_LITE_BEAM:
		{
			rad = -1;
			dam = (6*(8+1)/2);
			return (borg_attack_aux_wand_bolt(SV_WAND_LITE, rad, dam, GF_LITE_WEAK));
		}


		/* Wand -- stinking cloud */
		case BF_WAND_STINKING_CLOUD:
		{
			rad = 2;
			dam = 12;
			return (borg_attack_aux_wand_bolt(SV_WAND_STINKING_CLOUD, rad, dam, GF_POIS));
		}

		/* Wand -- elec ball */
		case BF_WAND_ELEC_BALL:
		{
			rad = 2;
			dam = 32;
			return (borg_attack_aux_wand_bolt(SV_WAND_ELEC_BALL, rad, dam, GF_ELEC));
		}

		/* Wand -- acid ball */
		case BF_WAND_COLD_BALL:
		{
			rad = 2;
			dam = 48;
			return (borg_attack_aux_wand_bolt(SV_WAND_COLD_BALL, rad, dam, GF_COLD));
		}

		/* Wand -- acid ball */
		case BF_WAND_ACID_BALL:
		{
			rad = 2;
			dam = 60;
			return (borg_attack_aux_wand_bolt(SV_WAND_ACID_BALL, rad, dam, GF_ACID));
		}

		/* Wand -- fire ball */
		case BF_WAND_FIRE_BALL:
		{
			rad = 2;
			dam = 72;
			return (borg_attack_aux_wand_bolt(SV_WAND_FIRE_BALL, rad, dam, GF_FIRE));
		}

		/* Wand -- dragon cold */
		case BF_WAND_DRAGON_COLD:
		{
			rad = 3;
			dam = 80;
			return (borg_attack_aux_wand_bolt(SV_WAND_DRAGON_COLD, rad, dam, GF_COLD));
		}

		/* Wand -- dragon fire */
		case BF_WAND_DRAGON_FIRE:
		{
			rad = 3;
			dam = 100;
			return (borg_attack_aux_wand_bolt(SV_WAND_DRAGON_FIRE, rad, dam, GF_FIRE));
		}
	}

	/* Oops */
	return (0);
}


/*
 * Attack nearby monsters, in the best possible way, if any.
 *
 * We consider a variety of possible attacks, including physical attacks
 * on adjacent monsters, missile attacks on nearby monsters, spell/prayer
 * attacks on nearby monsters, and wand/rod attacks on nearby monsters.
 *
 * Basically, for each of the known "types" of attack, we "simulate" the
 * "optimal" result of using that attack, and then we "apply" the "type"
 * of attack which appears to have the "optimal" result.
 *
 * When calculating the "result" of using an attack, we only consider the
 * effect of the attack on visible, on-screen, known monsters, which are
 * within 16 grids of the player.  This prevents most "spurious" attacks,
 * but we can still be fooled by situations like creeping coins which die
 * while out of sight, leaving behind a pile of coins, which we then find
 * again, and attack with distance attacks, which have no effect.  Perhaps
 * we should "expect" certain results, and take note of failure to observe
 * those effects.  XXX XXX XXX
 *
 * See above for the "semantics" of each "type" of attack.
 */
bool borg_attack(void)
{
	int i, x, y;

	int n, b_n = 0;
	int g, b_g = -1;

	auto_grid *ag;


	/* Nobody around */
	if (!auto_kills_cnt) return (FALSE);


	/* Reset list */
	auto_temp_n = 0;

	/* Find "nearby" monsters */
	for (i = 1; i < auto_kills_nxt; i++)
	{
		auto_kill *kill;

		/* Monster */
		kill = &auto_kills[i];

		/* Skip dead monsters */
		if (!kill->r_idx) continue;

		/* Require current knowledge */
		if (kill->when < c_t) continue;

		/* Ignore multiplying monsters */
		if (goal_ignoring && !do_afraid &&
		    (r_info[kill->r_idx].flags2 & RF2_MULTIPLY)) continue;

		/* Acquire location */
		x = kill->x;
		y = kill->y;

		/* Get grid */
		ag = &auto_grids[y][x];

		/* Never shoot off-screen */
		if (!(ag->info & BORG_OKAY)) continue;

		/* Never shoot through walls */
		if (!(ag->info & BORG_VIEW)) continue;

		/* Check the distance XXX XXX XXX */
		if (distance(c_y, c_x, y, x) > 16) continue;

		/* Save the location (careful) */
		auto_temp_x[auto_temp_n] = x;
		auto_temp_y[auto_temp_n] = y;
		auto_temp_n++;
	}

	/* No destinations */
	if (!auto_temp_n) return (FALSE);


	/* Simulate */
	auto_simulate = TRUE;

	/* Analyze the possible attacks */
	for (g = 0; g < BF_MAX; g++)
	{
		/* Simulate */
		n = borg_attack_aux(g);

		/* Track "best" attack */
		if (n <= b_n) continue;

		/* Track best */
		b_g = g;
		b_n = n;
	}

	/* Nothing good */
	if (b_n <= 0) return (FALSE);


	/* Note */
	borg_note(format("# Performing attack type %d with value %d", b_g, b_n));

	/* Instantiate */
	auto_simulate = FALSE;

	/* Instantiate */
	(void)borg_attack_aux(b_g);

	/* Success */
	return (TRUE);
}





/*
 * Attempt to recover from damage and such after a battle
 *
 * Note that resting while in danger is counter-productive, unless
 * the danger is low, in which case it may induce "farming".
 *
 * Note that resting while recall is active will often cause you
 * to lose hard-won treasure from nasty monsters, so we disable
 * resting when waiting for recall in the dungeon near objects.
 *
 * First we try spells/prayers, which are "free", and then we
 * try food, potions, scrolls, staffs, rods, artifacts, etc.
 *
 * XXX XXX XXX
 * Currently, we use healing spells as if they were "free", but really,
 * this is only true if the "danger" is less than the "reward" of doing
 * the healing spell, and if there are no monsters which might soon step
 * around the corner and attack.
 */
bool borg_recover(void)
{
	int p, q;


	/*** Handle annoying situations ***/

	/* Refuel current torch */
	if ((auto_items[INVEN_LITE].tval == TV_LITE) &&
	    (auto_items[INVEN_LITE].sval == SV_LITE_TORCH))
	{
		/* Refuel the torch if needed */
		if (auto_items[INVEN_LITE].pval < 2500)
		{
			if (borg_refuel_torch()) return (TRUE);
		}
	}

	/* Refuel current lantern */
	if ((auto_items[INVEN_LITE].tval == TV_LITE) &&
	    (auto_items[INVEN_LITE].sval == SV_LITE_LANTERN))
	{
		/* Refuel the lantern if needed */
		if (auto_items[INVEN_LITE].pval < 5000)
		{
			if (borg_refuel_lantern()) return (TRUE);
		}
	}


	/*** Do not recover when in danger ***/

	/* Look around for danger */
	p = borg_danger(c_y, c_x, 1);

	/* Never recover in dangerous situations */
	if (p > avoidance / 4) return (FALSE);


	/*** Roll for "paranoia" ***/

	/* Base roll */
	q = rand_int(100);

	/* Half dead */
	if (auto_chp < auto_mhp / 2) q = q - 10;

	/* Almost dead */
	if (auto_chp < auto_mhp / 4) q = q - 10;


	/*** Use "cheap" cures ***/

	/* Hack -- cure stun */
	if (do_stun && (q < 75))
	{
		if (borg_prayer(2, 7) ||
		    borg_prayer(3, 2) ||
		    borg_prayer(6, 1) ||
		    borg_prayer(6, 2))
		{
			return (TRUE);
		}
	}

	/* Hack -- cure cuts */
	if (do_cut && (q < 75))
	{
		if (borg_prayer(2, 2) ||
		    borg_prayer(2, 7) ||
		    borg_prayer(3, 2) ||
		    borg_prayer(6, 0) ||
		    borg_prayer(6, 1) ||
		    borg_prayer(6, 2))
		{
			return (TRUE);
		}
	}

	/* Hack -- cure poison */
	if (do_poisoned && (q < 75))
	{
		if (borg_spell(1, 4) ||
		    borg_prayer(2, 0))
		{
			return (TRUE);
		}
	}

	/* Hack -- cure fear */
	if (do_afraid && (q < 75))
	{
		if (borg_spell(7, 2) ||
		    borg_spell(7, 0) ||
		    borg_prayer(0, 3))
		{
			return (TRUE);
		}
	}

	/* Hack -- satisfy hunger */
	if (do_hungry && (q < 75))
	{
		if (borg_spell(2, 0) ||
		    borg_prayer(1, 5))
		{
			return (TRUE);
		}
	}

	/* Hack -- heal damage */
	if ((auto_chp < auto_mhp / 2) && (q < 75))
	{
		if (borg_spell(0, 5) ||
		    borg_prayer(3, 2) ||
		    borg_prayer(2, 7) ||
		    borg_prayer(2, 2) ||
		    borg_prayer(1, 2) ||
		    borg_prayer(6, 0) ||
		    borg_prayer(6, 1) ||
		    borg_prayer(6, 2))
		{
			return (TRUE);
		}
	}


	/*** Use "expensive" cures ***/

	/* Hack -- cure stun */
	if (do_stun && (q < 25))
	{
		if (borg_quaff_potion(SV_POTION_CURE_CRITICAL) ||
		    borg_use_staff(SV_STAFF_CURING) ||
		    borg_zap_rod(SV_ROD_CURING) ||
		    borg_zap_rod(SV_ROD_HEALING))
		{
			return (TRUE);
		}
	}

	/* Hack -- cure cuts */
	if (do_cut && (q < 25))
	{
		if (borg_quaff_potion(SV_POTION_CURE_CRITICAL) ||
		    borg_use_staff(SV_STAFF_CURING) ||
		    borg_zap_rod(SV_ROD_CURING) ||
		    borg_zap_rod(SV_ROD_HEALING))
		{
			return (TRUE);
		}
	}

	/* Hack -- cure poison */
	if (do_poisoned && (q < 25))
	{
		if (borg_quaff_potion(SV_POTION_CURE_POISON) ||
		    borg_quaff_potion(SV_POTION_SLOW_POISON) ||
		    borg_quaff_potion(SV_POTION_CURE_CRITICAL) ||
		    borg_eat_food(SV_FOOD_CURE_POISON) ||
		    borg_eat_food(SV_FOOD_WAYBREAD) ||
		    borg_use_staff(SV_STAFF_CURING) ||
		    borg_zap_rod(SV_ROD_CURING) ||
		    borg_activate_artifact(ART_DAL))
		{
			return (TRUE);
		}
	}

	/* Hack -- cure blindness */
	if (do_blind && (q < 25))
	{
		if (borg_eat_food(SV_FOOD_CURE_BLINDNESS) ||
		    borg_quaff_potion(SV_POTION_CURE_LIGHT) ||
		    borg_quaff_potion(SV_POTION_CURE_SERIOUS) ||
		    borg_quaff_potion(SV_POTION_CURE_CRITICAL) ||
		    borg_use_staff(SV_STAFF_CURING) ||
		    borg_use_staff(SV_ROD_CURING))
		{
			return (TRUE);
		}
	}

	/* Hack -- cure confusion */
	if (do_confused && (q < 25))
	{
		if (borg_eat_food(SV_FOOD_CURE_CONFUSION) ||
		    borg_quaff_potion(SV_POTION_CURE_SERIOUS) ||
		    borg_quaff_potion(SV_POTION_CURE_CRITICAL) ||
		    borg_use_staff(SV_STAFF_CURING) ||
		    borg_use_staff(SV_ROD_CURING))
		{
			return (TRUE);
		}
	}

	/* Hack -- cure fear */
	if (do_afraid && (q < 25))
	{
		if (borg_eat_food(SV_FOOD_CURE_PARANOIA) ||
		    borg_quaff_potion(SV_POTION_BOLDNESS) ||
		    borg_quaff_potion(SV_POTION_HEROISM) ||
		    borg_quaff_potion(SV_POTION_BESERK_STRENGTH) ||
		    borg_activate_artifact(ART_DAL))
		{
			return (TRUE);
		}
	}

	/* Hack -- satisfy hunger */
	if (do_hungry && (q < 25))
	{
		if (borg_read_scroll(SV_SCROLL_SATISFY_HUNGER))
		{
			return (TRUE);
		}
	}

	/* Hack -- heal damage */
	if ((auto_chp < auto_mhp / 2) && (q < 25))
	{
		if (borg_zap_rod(SV_ROD_HEALING) ||
		    borg_quaff_potion(SV_POTION_CURE_CRITICAL) ||
		    borg_quaff_potion(SV_POTION_CURE_SERIOUS))
		{
			return (TRUE);
		}
	}


	/*** Just Rest ***/

	/* Hack -- rest until healed */
	if ((do_blind || do_confused || do_image ||
	     do_poisoned || do_afraid || do_cut || do_stun ||
	     (auto_chp < auto_mhp) || (auto_csp < auto_msp)) &&
	    (!auto_depth || !auto_takes_cnt || !goal_recalling) &&
	    (rand_int(100) < 90))
	{
		/* XXX XXX XXX */

		/* Take note */
		borg_note(format("# Resting (danger %d)...", p));

		/* Rest until done */
		borg_keypress('R');
		borg_keypress('&');
		borg_keypress('\n');

		/* Done */
		return (TRUE);
	}

	/* Nope */
	return (FALSE);
}







/*
 * Take one "step" towards the given location, return TRUE if possible
 */
static bool borg_play_step(int y2, int x2)
{
	auto_grid *ag;

	int dir, x, y;


	/* Get a direction, if possible */
	dir = borg_goto_dir(c_y, c_x, y2, x2);

	/* We have arrived */
	if (dir == 5) return (FALSE);


	/* Obtain the destination */
	x = c_x + ddx[dir];
	y = c_y + ddy[dir];

	/* Access the grid we are stepping on */
	ag = &auto_grids[y][x];


	/* Hack -- set goal */
	g_x = x;
	g_y = y;


	/* Monsters -- Attack */
	if (ag->kill)
	{
		auto_kill *kill = &auto_kills[ag->kill];

		/* Message */
		borg_note(format("# Attacking a '%s' at (%d,%d)",
		                 r_name + r_info[kill->r_idx].name,
		                 kill->x, kill->y));

		/* Hack -- normally do a real attack */
		if (rand_int(100) < 90) borg_keypress('+');

		/* Attack */
		borg_keypress('0' + dir);
		return (TRUE);
	}


	/* Objects -- Take */
	if (ag->take)
	{
		auto_take *take = &auto_takes[ag->take];

		/* Message */
		borg_note(format("# Walking onto a '%s' at (%d,%d)",
		                 k_name + k_info[take->k_idx].name,
		                 take->x, take->y));

		/* Walk onto it */
		borg_keypress('0' + dir);
		return (TRUE);
	}


	/* Traps -- disarm */
	if ((ag->feat >= FEAT_TRAP_HEAD) && (ag->feat <= FEAT_TRAP_TAIL))
	{
		/* Message */
		borg_note("# Disarming a trap");

		/* Disarm */
		borg_keypress('D');
		borg_keypress('0' + dir);
		return (TRUE);
	}


	/* Closed Doors -- Open */
	if ((ag->feat >= FEAT_DOOR_HEAD) && (ag->feat <= FEAT_DOOR_HEAD + 0x07))
	{
		/* Paranoia XXX XXX XXX */
		if (!rand_int(100)) return (FALSE);

		/* Message */
		borg_note("# Opening a door");

		/* Open */
		borg_keypress('0');
		borg_keypress('9');
		borg_keypress('o');
		borg_keypress('0' + dir);
		return (TRUE);
	}


	/* Jammed Doors -- Bash or destroy */
	if ((ag->feat >= FEAT_DOOR_HEAD + 0x08) && (ag->feat <= FEAT_DOOR_TAIL))
	{
		/* Paranoia XXX XXX XXX */
		if (!rand_int(100)) return (FALSE);

		/* Mega-Hack -- allow "destroy doors" */
		if (borg_prayer(7, 0))
		{
			borg_note("# Unbarring ways");
			return (TRUE);
		}

		/* Mega-Hack -- allow "destroy doors" */
		if (borg_spell(1, 2))
		{
			borg_note("# Destroying doors");
			return (TRUE);
		}

		/* Mega-Hack -- allow "stone to mud" */
		if (borg_spell(1, 8))
		{
			borg_note("# Melting a door");
			borg_keypress('0' + dir);
			return (TRUE);
		}

		/* Message */
		borg_note("# Bashing a door");

		/* Bash */
		borg_keypress('B');
		borg_keypress('0' + dir);
		return (TRUE);
	}


	/* Rubble, Treasure, Seams, Walls -- Tunnel or Melt */
	if (ag->feat >= FEAT_SECRET)
	{
		/* Mega-Hack -- prevent infinite loops */
		if (rand_int(100) < 10) return (FALSE);

		/* Mega-Hack -- allow "stone to mud" */
		if (borg_spell(1, 8))
		{
			borg_note("# Melting a wall/etc");
			borg_keypress('0' + dir);
			return (TRUE);
		}

		/* Message */
		borg_note("# Digging through wall/etc");

		/* Tunnel */
		borg_keypress('0');
		borg_keypress('9');
		borg_keypress('9');
		borg_keypress('T');
		borg_keypress('0' + dir);
		return (TRUE);
	}


	/* Shops -- Enter */
	if ((ag->feat >= FEAT_SHOP_HEAD) && (ag->feat <= FEAT_SHOP_TAIL))
	{
		/* Message */
		borg_note(format("# Entering a '%d' shop", (ag->feat - FEAT_SHOP_HEAD) + 1));

		/* Enter the shop */
		borg_keypress('0' + dir);
		return (TRUE);
	}


	/* Walk in that direction */
	borg_keypress('0' + dir);


	/* Did something */
	return (TRUE);
}




/*
 * Act twitchy
 */
bool borg_twitchy(void)
{
	int dir;

	/* This is a bad thing */
	borg_note("# Twitchy!");

	/* Pick a random direction */
	dir = randint(9);

	/* Hack -- set goal */
	g_x = c_x + ddx[dir];
	g_y = c_y + ddy[dir];

	/* Move */
	borg_keypress('0' + dir);

	/* We did something */
	return (TRUE);
}





/*
 * Commit the current "flow"
 */
static bool borg_flow_commit(cptr who, int why)
{
	int cost;

	/* Cost of current grid */
	cost = auto_data_cost->data[c_y][c_x];

	/* Verify the total "cost" */
	if (cost >= 250) return (FALSE);

	/* Message */
	if (who) borg_note(format("# Flowing toward %s at cost %d", who, cost));

	/* Obtain the "flow" information */
	COPY(auto_data_flow, auto_data_cost, auto_data);

	/* Save the goal type */
	goal = why;

	/* Success */
	return (TRUE);
}





/*
 * Attempt to take an optimal step towards the current goal location
 *
 * Note that the "borg_update()" routine notices new monsters and objects,
 * and movement of monsters and objects, and cancels any flow in progress.
 *
 * Note that the "borg_update()" routine notices when a grid which was
 * not thought to block motion is discovered to in fact be a grid which
 * blocks motion, and removes that grid from any flow in progress.
 *
 * When given multiple alternative steps, this function attempts to choose
 * the "safest" path, by penalizing grids containing embedded gold, monsters,
 * rubble, doors, traps, store doors, and even floors.  This allows the Borg
 * to "step around" dangerous grids, even if this means extending the path by
 * a step or two, and encourages him to prefer grids such as objects and stairs
 * which are not only interesting but which are known not to be invisible traps.
 *
 * XXX XXX XXX XXX This function needs some work.  It should attempt to
 * analyze the "local region" around the player and determine the optimal
 * choice of locations based on some useful computations.
 *
 * If it works, return TRUE, otherwise, cancel the goal and return FALSE.
 */
bool borg_flow_old(int why)
{
	int x, y;

	auto_grid *ag;


	/* Continue */
	if (goal == why)
	{
		int b_n = 0;

		int i, b_i = -1;

		int c, b_c;


		/* Flow cost of current grid */
		b_c = auto_data_flow->data[c_y][c_x] * 10;

		/* Prevent loops */
		b_c = b_c - 5;


		/* Look around */
		for (i = 0; i < 8; i++)
		{
			/* Grid in that direction */
			x = c_x + ddx_ddd[i];
			y = c_y + ddy_ddd[i];

			/* Access the grid */
			ag = &auto_grids[y][x];

			/* Flow cost at that grid */
			c = auto_data_flow->data[y][x] * 10;

			/* Never backtrack */
			if (c > b_c) continue;

			/* Notice new best value */
			if (c < b_c) b_n = 0;

			/* Apply the randomizer to equivalent values */
			if ((++b_n >= 2) && (rand_int(b_n) != 0)) continue;

			/* Track it */
			b_i = i; b_c = c;
		}

		/* Try it */
		if (b_i >= 0)
		{
			/* Access the location */
			x = c_x + ddx_ddd[b_i];
			y = c_y + ddy_ddd[b_i];

			/* Attempt motion */
			if (borg_play_step(y, x)) return (TRUE);
		}

		/* Cancel goal */
		goal = 0;
	}

	/* Nothing to do */
	return (FALSE);
}




/*
 * Prepare to flee the level via stairs
 */
bool borg_flow_stair_both(int why)
{
	int i;

	/* None to flow to */
	if (!track_less_num && !track_more_num) return (FALSE);

	/* Clear the flow codes */
	borg_flow_clear();

	/* Enqueue useful grids */
	for (i = 0; i < track_less_num; i++)
	{
		/* Enqueue the grid */
		borg_flow_enqueue_grid(track_less_y[i], track_less_x[i]);
	}

	/* Enqueue useful grids */
	for (i = 0; i < track_more_num; i++)
	{
		/* Enqueue the grid */
		borg_flow_enqueue_grid(track_more_y[i], track_more_x[i]);
	}

	/* Spread the flow */
	borg_flow_spread(250, TRUE, FALSE);

	/* Attempt to Commit the flow */
	if (!borg_flow_commit("stairs", why)) return (FALSE);

	/* Take one step */
	if (!borg_flow_old(why)) return (FALSE);

	/* Success */
	return (TRUE);
}




/*
 * Prepare to flow towards "up" stairs
 */
bool borg_flow_stair_less(int why)
{
	int i;

	/* None to flow to */
	if (!track_less_num) return (FALSE);

	/* Clear the flow codes */
	borg_flow_clear();

	/* Enqueue useful grids */
	for (i = 0; i < track_less_num; i++)
	{
		/* Enqueue the grid */
		borg_flow_enqueue_grid(track_less_y[i], track_less_x[i]);
	}

	/* Spread the flow */
	borg_flow_spread(250, TRUE, FALSE);

	/* Attempt to Commit the flow */
	if (!borg_flow_commit("up-stairs", why)) return (FALSE);

	/* Take one step */
	if (!borg_flow_old(why)) return (FALSE);

	/* Success */
	return (TRUE);
}


/*
 * Prepare to flow towards "down" stairs
 */
bool borg_flow_stair_more(int why)
{
	int i;

	/* None to flow to */
	if (!track_more_num) return (FALSE);

	/* Clear the flow codes */
	borg_flow_clear();

	/* Enqueue useful grids */
	for (i = 0; i < track_more_num; i++)
	{
		/* Enqueue the grid */
		borg_flow_enqueue_grid(track_more_y[i], track_more_x[i]);
	}

	/* Spread the flow */
	borg_flow_spread(250, TRUE, FALSE);

	/* Attempt to Commit the flow */
	if (!borg_flow_commit("down-stairs", why)) return (FALSE);

	/* Take one step */
	if (!borg_flow_old(why)) return (FALSE);

	/* Success */
	return (TRUE);
}


/*
 * Prepare to "flow" towards any non-visited shop
 */
bool borg_flow_shop_visit(void)
{
	int i, x, y;

	/* Must be in town */
	if (auto_depth) return (FALSE);

	/* Clear the flow codes */
	borg_flow_clear();

	/* Visit the shops */
	for (i = 0; i < 8; i++)
	{
		/* Must not be visited */
		if (auto_shops[i].when) continue;

		/* Obtain the location */
		x = track_shop_x[i];
		y = track_shop_y[i];

		/* Hack -- Must be known and not under the player */
		if (!x || !y || ((c_x == x) && (c_y == y))) continue;

		/* Enqueue the grid */
		borg_flow_enqueue_grid(y, x);
	}

	/* Spread the flow */
	borg_flow_spread(250, TRUE, FALSE);

	/* Attempt to Commit the flow */
	if (!borg_flow_commit("shops", GOAL_MISC)) return (FALSE);

	/* Take one step */
	if (!borg_flow_old(GOAL_MISC)) return (FALSE);

	/* Success */
	return (TRUE);
}


/*
 * Prepare to "flow" towards a specific shop entry
 */
bool borg_flow_shop_entry(int i)
{
	int x, y;

	cptr name = (f_name + f_info[0x08+i].name);

	/* Must be in town */
	if (auto_depth) return (FALSE);

	/* Obtain the location */
	x = track_shop_x[i];
	y = track_shop_y[i];

	/* Hack -- Must be known */
	if (!x || !y) return (FALSE);

	/* Hack -- re-enter a shop if needed */
	if ((x == c_x) && (y == c_y))
	{
		/* Note */
		borg_note("# Re-entering a shop");

		/* Enter the store */
		borg_keypress('5');

		/* Success */
		return (TRUE);
	}

	/* Clear the flow codes */
	borg_flow_clear();

	/* Enqueue the grid */
	borg_flow_enqueue_grid(y, x);

	/* Spread the flow */
	borg_flow_spread(250, TRUE, FALSE);

	/* Attempt to Commit the flow */
	if (!borg_flow_commit(name, GOAL_MISC)) return (FALSE);

	/* Take one step */
	if (!borg_flow_old(GOAL_MISC)) return (FALSE);

	/* Success */
	return (TRUE);
}






/*
 * Prepare to "flow" towards monsters to "kill"
 *
 * Note that monsters under the player are always deleted
 */
bool borg_flow_kill(bool viewable)
{
	int i, x, y, p;

	auto_grid *ag;


	/* Efficiency -- Nothing to kill */
	if (!auto_kills_cnt) return (FALSE);


	/* Nothing found */
	auto_temp_n = 0;

	/* Scan the monster list */
	for (i = 1; i < auto_kills_nxt; i++)
	{
		auto_kill *kill = &auto_kills[i];

		/* Skip dead monsters */
		if (!kill->r_idx) continue;

		/* Ignore multiplying monsters */
		if (goal_ignoring && !do_afraid &&
		    (r_info[kill->r_idx].flags2 & RF2_MULTIPLY)) continue;

		/* Access the location */
		x = kill->x;
		y = kill->y;

		/* Get the grid */
		ag = &auto_grids[y][x];

		/* Require line of sight if requested */
		if (viewable && !(ag->info & BORG_VIEW)) continue;

		/* Calculate danger */
		p = borg_danger_aux(y, x, 1, i);

		/* Hack -- Skip "deadly" monsters */
		if (p > avoidance / 2) continue;

		/* Careful -- Remember it */
		auto_temp_x[auto_temp_n] = x;
		auto_temp_y[auto_temp_n] = y;
		auto_temp_n++;
	}

	/* Nothing to kill */
	if (!auto_temp_n) return (FALSE);


	/* Clear the flow codes */
	borg_flow_clear();

	/* Look for something to kill */
	for (i = 0; i < auto_temp_n; i++)
	{
		/* Enqueue the grid */
		borg_flow_enqueue_grid(auto_temp_y[i], auto_temp_x[i]);
	}

	/* Spread the flow */
	borg_flow_spread(250, TRUE, FALSE);


	/* Attempt to Commit the flow */
	if (!borg_flow_commit(NULL, GOAL_KILL)) return (FALSE);

	/* Take one step */
	if (!borg_flow_old(GOAL_KILL)) return (FALSE);

	/* Success */
	return (TRUE);
}



/*
 * Prepare to "flow" towards objects to "take"
 *
 * Note that objects under the player are always deleted
 */
bool borg_flow_take(bool viewable)
{
	int i, x, y;

	auto_grid *ag;


	/* Efficiency -- Nothing to take */
	if (!auto_takes_cnt) return (FALSE);


	/* Nothing yet */
	auto_temp_n = 0;

	/* Scan the object list */
	for (i = 1; i < auto_takes_nxt; i++)
	{
		auto_take *take = &auto_takes[i];

		/* Skip dead objects */
		if (!take->k_idx) continue;

		/* Access the location */
		x = take->x;
		y = take->y;

		/* Get the grid */
		ag = &auto_grids[y][x];

		/* Require line of sight if requested */
		if (viewable && !(ag->info & BORG_VIEW)) continue;

		/* Careful -- Remember it */
		auto_temp_x[auto_temp_n] = x;
		auto_temp_y[auto_temp_n] = y;
		auto_temp_n++;
	}

	/* Nothing to take */
	if (!auto_temp_n) return (FALSE);


	/* Clear the flow codes */
	borg_flow_clear();

	/* Look for something to take */
	for (i = 0; i < auto_temp_n; i++)
	{
		/* Enqueue the grid */
		borg_flow_enqueue_grid(auto_temp_y[i], auto_temp_x[i]);
	}

	/* Spread the flow */
	borg_flow_spread(250, TRUE, FALSE);


	/* Attempt to Commit the flow */
	if (!borg_flow_commit(NULL, GOAL_TAKE)) return (FALSE);

	/* Take one step */
	if (!borg_flow_old(GOAL_TAKE)) return (FALSE);

	/* Success */
	return (TRUE);
}



/*
 * Determine if a grid is "interesting" (and should be explored)
 *
 * A grid is "interesting" if it is a closed door, rubble, hidden treasure,
 * or a visible trap, or an "unknown" grid.
 */
static bool borg_flow_dark_interesting(int y, int x)
{
	auto_grid *ag;


	/* Get the auto_grid */
	ag = &auto_grids[y][x];


	/* Explore unknown grids */
	if (ag->feat == FEAT_NONE) return (TRUE);


	/* Efficiency -- Ignore "boring" grids */
	if (ag->feat < FEAT_TRAP_HEAD) return (FALSE);


	/* Explore "known treasure" */
	if ((ag->feat == FEAT_MAGMA_K) || (ag->feat == FEAT_QUARTZ_K))
	{
		/* Do not disarm when confused */
		if (do_confused) return (FALSE);

		/* Allow "stone to mud" ability */
		if (borg_spell_legal(1, 8)) return (TRUE);

		/* Do not dig unless we appear strong enough to succeed XXX XXX XXX */
		if (my_skill_dig < ((ag->feat & 0x01) ? 20 : 10) + 5) return (FALSE);

		/* Okay */
		return (TRUE);
	}


	/* Explore "rubble" */
	if (ag->feat == FEAT_RUBBLE)
	{
		return (TRUE);
	}


	/* Explore "closed doors" */
	if ((ag->feat >= FEAT_DOOR_HEAD) && (ag->feat <= FEAT_DOOR_TAIL))
	{
		return (TRUE);
	}


	/* Explore "visible traps" */
	if ((ag->feat >= FEAT_TRAP_HEAD) && (ag->feat <= FEAT_TRAP_TAIL))
	{
		/* Do not disarm when blind */
		if (do_blind) return (FALSE);

		/* Do not disarm when confused */
		if (do_confused) return (FALSE);

		/* Do not disarm when hallucinating */
		if (do_image) return (FALSE);

		/* Do not disarm without lite */
		if (!my_cur_lite) return (FALSE);

		/* Do not disarm when clumsy */
		if (my_skill_dis < 15) return (FALSE);

		/* Okay */
		return (TRUE);
	}


	/* Ignore other grids */
	return (FALSE);
}


/*
 * Determine if a grid is "reachable" (and can be explored)
 */
static bool borg_flow_dark_reachable(int y, int x)
{
	int j;

	auto_grid *ag;

	/* Scan neighbors */
	for (j = 0; j < 8; j++)
	{
		int y2 = y + ddy_ddd[j];
		int x2 = x + ddx_ddd[j];

		/* Get the grid */
		ag = &auto_grids[y2][x2];

		/* Skip unknown grids (important) */
		if (ag->feat == FEAT_NONE) continue;

		/* Accept known floor grids */
		if (borg_cave_floor_grid(ag)) return (TRUE);
	}

	/* Failure */
	return (FALSE);
}


/*
 * Place a "direct path" into the flow array, checking danger
 *
 * Modify the "cost" array in such a way that from any point on
 * one "direct" path from the player to the given grid, as long
 * as the rest of the path is "safe" and "clear", the Borg will
 * walk along the path to the given grid.
 *
 * This function is used by "borg_flow_dark_1()" to provide an
 * optimized "flow" during the initial exploration of a level.
 */
static void borg_flow_direct(int y, int x)
{
	int n = 0;

	int x1, y1, x2, y2;

	int ay, ax;

	int shift;

	auto_grid *ag;


	/* Avoid icky grids */
	if (auto_data_icky->data[y][x]) return;

	/* Unknown */
	if (!auto_data_know->data[y][x])
	{
		/* Mark as known */
		auto_data_know->data[y][x] = TRUE;

		/* Mark dangerous grids as icky */
		if (borg_danger(y, x, 1) > avoidance / 2)
		{
			/* Icky */
			auto_data_icky->data[y][x] = TRUE;

			/* Avoid */
			return;
		}
	}


	/* Save the flow cost (zero) */
	auto_data_cost->data[y][x] = 0;


	/* Save "origin" */
	y1 = y;
	x1 = x;

	/* Save "destination" */
	y2 = c_y;
	x2 = c_x;

	/* Calculate distance components */
	ay = (y2 < y1) ? (y1 - y2) : (y2 - y1);
	ax = (x2 < x1) ? (x1 - x2) : (x2 - x1);

	/* Path */
	while (1)
	{
		/* Check for arrival at player */
		if ((x == x2) && (y == y2)) return;

		/* Next */
		n++;

		/* Move mostly vertically */
		if (ay > ax)
		{
			/* Extract a shift factor XXX */
			shift = (n * ax + (ay-1) / 2) / ay;

			/* Sometimes move along the minor axis */
			x = (x2 < x1) ? (x1 - shift) : (x1 + shift);

			/* Always move along major axis */
			y = (y2 < y1) ? (y1 - n) : (y1 + n);
		}

		/* Move mostly horizontally */
		else
		{
			/* Extract a shift factor XXX */
			shift = (n * ay + (ax-1) / 2) / ax;

			/* Sometimes move along the minor axis */
			y = (y2 < y1) ? (y1 - shift) : (y1 + shift);

			/* Always move along major axis */
			x = (x2 < x1) ? (x1 - n) : (x1 + n);
		}


		/* Access the grid */
		ag = &auto_grids[y][x];


		/* Ignore "wall" grids */
		if (!borg_cave_floor_grid(ag)) return;


		/* Abort at "icky" grids */
		if (auto_data_icky->data[y][x]) return;

		/* Analyze every grid once */
		if (!auto_data_know->data[y][x])
		{
			/* Mark as known */
			auto_data_know->data[y][x] = TRUE;

			/* Avoid dangerous grids (forever) */
			if (borg_danger(y, x, 1) > avoidance / 2)
			{
				/* Mark as icky */
				auto_data_icky->data[y][x] = TRUE;

				/* Abort */
				return;
			}
		}

		/* Abort "pointless" paths if possible */
		if (auto_data_cost->data[y][x] <= n) break;

		/* Save the new flow cost */
		auto_data_cost->data[y][x] = n;
	}
}


/*
 * Hack -- mark off the edges of a rectangle as "avoid" or "clear"
 */
static void borg_flow_border(int y1, int x1, int y2, int x2, bool stop)
{
	int x, y;

	/* Scan west/east edges */
	for (y = y1; y <= y2; y++)
	{
		/* Avoid/Clear west edge */
		auto_data_know->data[y][x1] = stop;
		auto_data_icky->data[y][x1] = stop;

		/* Avoid/Clear east edge */
		auto_data_know->data[y][x2] = stop;
		auto_data_icky->data[y][x2] = stop;
	}

	/* Scan north/south edges */
	for (x = x1; x <= x2; x++)
	{
		/* Avoid/Clear north edge */
		auto_data_know->data[y1][x] = stop;
		auto_data_icky->data[y1][x] = stop;

		/* Avoid/Clear south edge */
		auto_data_know->data[y2][x] = stop;
		auto_data_icky->data[y2][x] = stop;
	}
}


/*
 * Prepare to "flow" towards "interesting" grids (method 1)
 *
 * This function examines the torch-lit grids for "interesting" grids.
 */
static bool borg_flow_dark_1(void)
{
	int i;

	int x, y;


	/* Hack -- not in town */
	if (!auto_depth) return (FALSE);


	/* Reset */
	auto_temp_n = 0;

	/* Scan torch-lit grids */
	for (i = 0; i < auto_lite_n; i++)
	{
		y = auto_lite_y[i];
		x = auto_lite_x[i];

		/* Skip "boring" grids (assume reachable) */
		if (!borg_flow_dark_interesting(y, x)) continue;

		/* Careful -- Remember it */
		auto_temp_x[auto_temp_n] = x;
		auto_temp_y[auto_temp_n] = y;
		auto_temp_n++;
	}

	/* Nothing */
	if (!auto_temp_n) return (FALSE);


	/* Clear the flow codes */
	borg_flow_clear();

	/* Create paths to useful grids */
	for (i = 0; i < auto_temp_n; i++)
	{
		y = auto_temp_y[i];
		x = auto_temp_x[i];

		/* Create a path */
		borg_flow_direct(y, x);
	}


	/* Attempt to Commit the flow */
	if (!borg_flow_commit(NULL, GOAL_DARK)) return (FALSE);

	/* Take one step */
	if (!borg_flow_old(GOAL_DARK)) return (FALSE);

	/* Forget goal */
	goal = 0;

	/* Success */
	return (TRUE);
}


/*
 * Prepare to "flow" towards "interesting" grids (method 2)
 *
 * This function is only used when the player is at least 4 grids away
 * from the outer dungeon wall, to prevent any nasty memory errors.
 *
 * This function examines the grids just outside the torch-lit grids
 * for "unknown" grids, and flows directly towards them (one step).
 */
static bool borg_flow_dark_2(void)
{
	int i, r;

	int x, y;

	auto_grid *ag;


	/* Hack -- not in town */
	if (!auto_depth) return (FALSE);


	/* Maximal radius */
	r = my_cur_lite + 1;


	/* Reset */
	auto_temp_n = 0;

	/* Four directions */
	for (i = 0; i < 4; i++)
	{
		y = c_y + ddy_ddd[i] * r;
		x = c_x + ddx_ddd[i] * r;

		/* Check legality */
		if (y < 1) continue;
		if (x < 1) continue;
		if (y > AUTO_MAX_Y - 2) continue;
		if (x > AUTO_MAX_X - 2) continue;

		/* Acquire grid */
		ag = &auto_grids[y][x];

		/* Require unknown */
		if (ag->feat != FEAT_NONE) continue;

		/* Require viewable */
		if (!(ag->info & BORG_VIEW)) continue;

		/* Careful -- Remember it */
		auto_temp_x[auto_temp_n] = x;
		auto_temp_y[auto_temp_n] = y;
		auto_temp_n++;
	}

	/* Nothing */
	if (!auto_temp_n) return (FALSE);


	/* Clear the flow codes */
	borg_flow_clear();

	/* Create paths to useful grids */
	for (i = 0; i < auto_temp_n; i++)
	{
		y = auto_temp_y[i];
		x = auto_temp_x[i];

		/* Create a path */
		borg_flow_direct(y, x);
	}


	/* Attempt to Commit the flow */
	if (!borg_flow_commit(NULL, GOAL_DARK)) return (FALSE);

	/* Take one step */
	if (!borg_flow_old(GOAL_DARK)) return (FALSE);

	/* Forget goal */
	goal = 0;

	/* Success */
	return (TRUE);
}


/*
 * Prepare to "flow" towards "interesting" grids (method 3)
 *
 * Note the use of a limit on the "depth" of the flow, and of the flag
 * which avoids "unknown" grids when calculating the flow, both of which
 * help optimize this function to only handle "easily reachable" grids.
 *
 * The "auto_temp" array is much larger than any "local region".
 */
static bool borg_flow_dark_3(void)
{
	int i;

	int x, y;

	int x1, y1, x2, y2;


	/* Hack -- not in town */
	if (!auto_depth) return (FALSE);


	/* Local region */
	y1 = c_y - 4;
	x1 = c_x - 4;
	y2 = c_y + 4;
	x2 = c_x + 4;

	/* Restrict to "legal" grids */
	if (y1 < 1) y1 = 1;
	if (x1 < 1) x1 = 1;
	if (y2 > AUTO_MAX_Y - 2) y2 = AUTO_MAX_Y - 2;
	if (x2 > AUTO_MAX_X - 2) x2 = AUTO_MAX_X - 2;


	/* Reset */
	auto_temp_n = 0;

	/* Examine the region */
	for (y = y1; y <= y2; y++)
	{
		/* Examine the region */
		for (x = x1; x <= x2; x++)
		{
			/* Skip "boring" grids */
			if (!borg_flow_dark_interesting(y, x)) continue;

			/* Skip "unreachable" grids */
			if (!borg_flow_dark_reachable(y, x)) continue;

			/* Careful -- Remember it */
			auto_temp_x[auto_temp_n] = x;
			auto_temp_y[auto_temp_n] = y;
			auto_temp_n++;
		}
	}

	/* Nothing interesting */
	if (!auto_temp_n) return (FALSE);


	/* Clear the flow codes */
	borg_flow_clear();

	/* Enqueue useful grids */
	for (i = 0; i < auto_temp_n; i++)
	{
		y = auto_temp_y[i];
		x = auto_temp_x[i];

		/* Enqueue the grid */
		borg_flow_enqueue_grid(y, x);
	}

	/* Spread the flow (limit depth) */
	borg_flow_spread(5, TRUE, TRUE);


	/* Attempt to Commit the flow */
	if (!borg_flow_commit(NULL, GOAL_DARK)) return (FALSE);

	/* Take one step */
	if (!borg_flow_old(GOAL_DARK)) return (FALSE);

	/* Success */
	return (TRUE);
}


/*
 * Prepare to "flow" towards "interesting" grids (method 4)
 *
 * Note that we avoid grids close to the edge of the panel, since they
 * induce panel scrolling, which is "expensive" in terms of CPU usage,
 * and because this allows us to "expand" the border by several grids
 * to lay down the "avoidance" border in known legal grids.
 *
 * We avoid paths that would take us into different panels by setting
 * the "icky" flag for the "border" grids to prevent path construction,
 * and then clearing them when done, to prevent confusion elsewhere.
 *
 * The "auto_temp" array is large enough to hold one panel full of grids.
 */
static bool borg_flow_dark_4(void)
{
	int i, x, y;

	int x1, y1, x2, y2;


	/* Hack -- not in town */
	if (!auto_depth) return (FALSE);


	/* Local region */
	y1 = c_y - 11;
	x1 = c_x - 11;
	y2 = c_y + 11;
	x2 = c_x + 11;

	/* Restrict to "legal" grids */
	if (y1 < 1) y1 = 1;
	if (x1 < 1) x1 = 1;
	if (y2 > AUTO_MAX_Y - 2) y2 = AUTO_MAX_Y - 2;
	if (x2 > AUTO_MAX_X - 2) x2 = AUTO_MAX_X - 2;


	/* Nothing yet */
	auto_temp_n = 0;

	/* Examine the panel */
	for (y = y1; y <= y2; y++)
	{
		/* Examine the panel */
		for (x = x1; x <= x2; x++)
		{
			/* Skip "boring" grids */
			if (!borg_flow_dark_interesting(y, x)) continue;

			/* Skip "unreachable" grids */
			if (!borg_flow_dark_reachable(y, x)) continue;

			/* Careful -- Remember it */
			auto_temp_x[auto_temp_n] = x;
			auto_temp_y[auto_temp_n] = y;
			auto_temp_n++;
		}
	}

	/* Nothing useful */
	if (!auto_temp_n) return (FALSE);


	/* Clear the flow codes */
	borg_flow_clear();

	/* Enqueue useful grids */
	for (i = 0; i < auto_temp_n; i++)
	{
		y = auto_temp_y[i];
		x = auto_temp_x[i];

		/* Enqueue the grid */
		borg_flow_enqueue_grid(y, x);
	}


	/* Expand borders */
	y1--; x1--; y2++; x2++;

	/* Avoid the edges */
	borg_flow_border(y1, x1, y2, x2, TRUE);

	/* Spread the flow (limit depth) */
	borg_flow_spread(32, TRUE, TRUE);

	/* Clear the edges */
	borg_flow_border(y1, x1, y2, x2, FALSE);


	/* Attempt to Commit the flow */
	if (!borg_flow_commit("dark-4", GOAL_DARK)) return (FALSE);

	/* Take one step */
	if (!borg_flow_old(GOAL_DARK)) return (FALSE);

	/* Success */
	return (TRUE);
}


/*
 * Prepare to "flow" towards "interesting" grids (method 5)
 */
static bool borg_flow_dark_5(void)
{
	int i, x, y;


	/* Hack -- not in town */
	if (!auto_depth) return (FALSE);


	/* Nothing yet */
	auto_temp_n = 0;

	/* Examine every "legal" grid */
	for (y = 1; y < AUTO_MAX_Y-1; y++)
	{
		for (x = 1; x < AUTO_MAX_X-1; x++)
		{
			/* Skip "boring" grids */
			if (!borg_flow_dark_interesting(y, x)) continue;

			/* Skip "unreachable" grids */
			if (!borg_flow_dark_reachable(y, x)) continue;

			/* Careful -- Remember it */
			auto_temp_x[auto_temp_n] = x;
			auto_temp_y[auto_temp_n] = y;
			auto_temp_n++;

			/* Paranoia -- Check for overflow */
			if (auto_temp_n == AUTO_TEMP_MAX)
			{
				/* Hack -- Double break */
				y = AUTO_MAX_Y;
				x = AUTO_MAX_X;
				break;
			}
		}
	}

	/* Nothing useful */
	if (!auto_temp_n) return (FALSE);


	/* Clear the flow codes */
	borg_flow_clear();

	/* Enqueue useful grids */
	for (i = 0; i < auto_temp_n; i++)
	{
		y = auto_temp_y[i];
		x = auto_temp_x[i];

		/* Enqueue the grid */
		borg_flow_enqueue_grid(y, x);
	}

	/* Spread the flow */
	borg_flow_spread(250, TRUE, TRUE);


	/* Attempt to Commit the flow */
	if (!borg_flow_commit("dark-5", GOAL_DARK)) return (FALSE);

	/* Take one step */
	if (!borg_flow_old(GOAL_DARK)) return (FALSE);

	/* Success */
	return (TRUE);
}


/*
 * Prepare to "flow" towards "interesting" grids
 *
 * The "exploration" routines are broken into "nearby" and "distant"
 * exploration, and each set is chosen via the flag below.
 */
bool borg_flow_dark(bool nearby)
{
	/* Paranoia */
	if (borg_flow_dark_interesting(c_y, c_x))
	{
		borg_oops("darkness");
		return (FALSE);
	}

	/* Near */
	if (nearby)
	{
		/* Method 1 */
		if (borg_flow_dark_1()) return (TRUE);

		/* Method 2 */
		if (borg_flow_dark_2()) return (TRUE);

		/* Method 3 */
		if (borg_flow_dark_3()) return (TRUE);
	}

	/* Far */
	else
	{
		/* Method 4 */
		if (borg_flow_dark_4()) return (TRUE);

		/* Method 5 */
		if (borg_flow_dark_5()) return (TRUE);
	}

	/* Fail */
	return (FALSE);
}



/*
 * Hack -- spastic searching
 */

static byte spastic_x;
static byte spastic_y;



/*
 * Search carefully for secret doors and such
 */
bool borg_flow_spastic(bool bored)
{
	int cost;

	int i, x, y, v;

	int b_x = c_x;
	int b_y = c_y;
	int b_v = -1;

	auto_grid *ag;


	/* Hack -- not in town */
	if (!auto_depth) return (FALSE);


	/* Not bored */
	if (!bored)
	{
		/* Look around for danger */
		int p = borg_danger(c_y, c_x, 1);

		/* Avoid searching when in danger */
		if (p > avoidance / 4) return (FALSE);
	}


	/* We have arrived */
	if ((spastic_x == c_x) && (spastic_y == c_y))
	{
		/* Cancel */
		spastic_x = 0;
		spastic_y = 0;

		/* Take note */
		borg_note(format("# Spastic Searching at (%d,%d)...", c_x, c_y));

		/* Count searching */
		for (i = 0; i < 9; i++)
		{
			/* Extract the location */
			int xx = c_x + ddx_ddd[i];
			int yy = c_y + ddy_ddd[i];

			/* Current grid */
			ag = &auto_grids[yy][xx];

			/* Tweak -- Remember the search */
			if (ag->xtra < 100) ag->xtra += 5;
		}

		/* Tweak -- Search a little */
		borg_keypress('0');
		borg_keypress('5');
		borg_keypress('s');

		/* Success */
		return (TRUE);
	}


	/* Reverse flow */
	borg_flow_reverse();

	/* Scan the entire map */
	for (y = 1; y < AUTO_MAX_Y-1; y++)
	{
		for (x = 1; x < AUTO_MAX_X-1; x++)
		{
			auto_grid *ag_ptr[8];

			int wall = 0;
			int supp = 0;
			int diag = 0;


			/* Acquire the grid */
			ag = &auto_grids[y][x];

			/* Skip unknown grids */
			if (ag->feat == FEAT_NONE) continue;

			/* Skip walls/doors */
			if (!borg_cave_floor_grid(ag)) continue;


			/* Acquire the cost */
			cost = auto_data_cost->data[y][x];

			/* Skip "unreachable" grids */
			if (cost >= 250) continue;


			/* Tweak -- Limit total searches */
			if (ag->xtra >= 50) continue;

			/* Limit initial searches until bored */
			if (!bored && (ag->xtra > 5)) continue;

			/* Avoid searching detected sectors */
			if (auto_detect_door[y/11][x/33]) continue;


			/* Extract adjacent locations */
			for (i = 0; i < 8; i++)
			{
				/* Extract the location */
				int xx = x + ddx_ddd[i];
				int yy = y + ddy_ddd[i];

				/* Get the grid contents */
				ag_ptr[i] = &auto_grids[yy][xx];
			}


			/* Count possible door locations */
			for (i = 0; i < 4; i++)
			{
				ag = ag_ptr[i];
				if (ag->feat >= FEAT_WALL_EXTRA) wall++;
			}

			/* No possible secret doors */
			if (wall < 1) continue;


			/* Count supporting evidence for secret doors */
			for (i = 0; i < 4; i++)
			{
				ag = ag_ptr[i];

				/* Rubble */
				if (ag->feat == FEAT_RUBBLE) continue;

				/* Walls, Doors */
				if (((ag->feat >= FEAT_SECRET) && (ag->feat <= FEAT_PERM_SOLID)) ||
				    ((ag->feat == FEAT_OPEN) || (ag->feat == FEAT_BROKEN)) ||
				    ((ag->feat >= FEAT_DOOR_HEAD) && (ag->feat <= FEAT_DOOR_TAIL)))
				{
					supp++;
				}
			}

			/* Count supporting evidence for secret doors */
			for (i = 4; i < 8; i++)
			{
				ag = ag_ptr[i];

				/* Rubble */
				if (ag->feat == FEAT_RUBBLE) continue;

				/* Walls */
				if (ag->feat >= FEAT_SECRET)
				{
					diag++;
				}
			}

			/* No possible secret doors */
			if (diag < 2) continue;


			/* Tweak -- Reward walls, punish visitation and distance */
			v = (supp * 500) + (diag * 100) - (ag->xtra * 20) - (cost * 1);

			/* The grid is not searchable */
			if (v <= 0) continue;


			/* Tweak -- Minimal interest until bored */
			if (!bored && (v < 1500)) continue;


			/* Track "best" grid */
			if ((b_v >= 0) && (v < b_v)) continue;

			/* Save the data */
			b_v = v; b_x = x; b_y = y;
		}
	}

	/* Clear the flow codes */
	borg_flow_clear();

	/* Hack -- Nothing found */
	if (b_v < 0) return (FALSE);


	/* Access grid */
	ag = &auto_grids[b_y][b_x];

	/* Memorize */
	spastic_x = b_x;
	spastic_y = b_y;


	/* Enqueue the grid */
	borg_flow_enqueue_grid(b_y, b_x);

	/* Spread the flow */
	borg_flow_spread(250, TRUE, FALSE);

	/* Attempt to Commit the flow */
	if (!borg_flow_commit("spastic", GOAL_XTRA)) return (FALSE);

	/* Take one step */
	if (!borg_flow_old(GOAL_XTRA)) return (FALSE);

	/* Success */
	return (TRUE);
}




/*
 * Initialize this file
 */
void borg_init_6(void)
{
	/* Nothing */
}


#else

#ifdef MACINTOSH
static int HACK = 0;
#endif /* MACINTOSH */

#endif /* ALLOW_BORG */
