/* File: borg8.c */

/* Purpose: High level functions 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"
#include "borg7.h"
#include "borg8.h"


/*
 * This file handles the highest level goals, and store interaction.
 *
 * Store interaction strategy
 *
 *   (1) Sell items to the home (for later use)
 *       We sell anything we may need later (see step 4)
 *
 *   (2) Sell items to the shops (for money)
 *       We sell anything we do not actually need
 *
 *   (3) Buy items from the shops (for the player)
 *       We buy things that we actually need
 *
 *   (4) Buy items from the home (for the player)
 *       We buy things that we actually need (see step 1)
 *
 *   (5) Buy items from the shops (for the home)
 *       We buy things we may need later (see step 1)
 *
 *   (6) Buy items from the home (for the stores)
 *       We buy things we no longer need (see step 2)
 *
 *   The basic principle is that we should always act to improve our
 *   "status", and we should sometimes act to "maintain" our status,
 *   especially if there is a monetary reward.  But first we should
 *   attempt to use the home as a "stockpile", even though that is
 *   not worth any money, since it may save us money eventually.
 */



/*
 * Step 1 -- sell "useful" things to the home (for later)
 */
static bool borg_think_home_sell_aux(void)
{
	int icky = STORE_INVEN_MAX - 1;

	int i, b_i = -1;
	s32b p, b_p = 0L;
	s32b s, b_s = 0L;

	bool fix = FALSE;


	/* Hack -- the home is full */
	if (auto_shops[7].ware[icky].iqty) return (FALSE);


	/* Base power */
	b_p = my_power;


	/* Examine the home */
	borg_notice_home();

	/* Evaluate the home */
	b_s = borg_power_home();


	/* Save the store hole */
	COPY(&safe_shops[7].ware[icky], &auto_shops[7].ware[icky], auto_item);

	/* Sell stuff */
	for (i = 0; i < INVEN_PACK; i++)
	{
		auto_item *item = &auto_items[i];

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

		/* Save the item */
		COPY(&safe_items[i], &auto_items[i], auto_item);

		/* Give the item to the shop */
		COPY(&auto_shops[7].ware[icky], &safe_items[i], auto_item);

		/* Give a single item */
		auto_shops[7].ware[icky].iqty = 1;

		/* Lose a single item */
		auto_items[i].iqty--;

		/* Fix later */
		fix = TRUE;

		/* Examine the inventory */
		borg_notice();

		/* Evaluate the inventory */
		p = borg_power();

		/* Restore the item */
		COPY(&auto_items[i], &safe_items[i], auto_item);

		/* Ignore "bad" sales */
		if (p < b_p) continue;

		/* Examine the home */
		borg_notice_home();

		/* Evaluate the home */
		s = borg_power_home();

		/* Ignore "silly" sales */
		if ((p == b_p) && (s <= b_s)) continue;

		/* Maintain the "best" */
		b_i = i; b_p = p; b_s = s;
	}

	/* Restore the store hole */
	COPY(&auto_shops[7].ware[icky], &safe_shops[7].ware[icky], auto_item);

	/* Examine the player */
	if (fix) borg_notice();

	/* Examine the home */
	borg_notice_home();

	/* Evaluate the home */
	s = borg_power_home();

	/* Stockpile */
	if (b_i >= 0)
	{
		/* Visit the home */
		goal_shop = 7;

		/* Sell that item */
		goal_item = b_i;

		/* Success */
		return (TRUE);
	}

	/* Assume not */
	return (FALSE);
}


/*
 * Determine if an item can be sold in the given store
 *
 * XXX XXX XXX Consider use of "icky" test on items
 */
static bool borg_good_sell(auto_item *item, int who)
{
	/* Never sell worthless items */
	if (item->value <= 0) return (FALSE);

	/* Hack -- never sell artifacts */
	if (item->name1) return (FALSE);

	/* Analyze the type */
	switch (item->tval)
	{
		case TV_POTION:
		case TV_SCROLL:

		/* Never sell if not "known" and interesting */
		if (!item->able && (auto_max_depth > 5)) return (FALSE);
		break;

		case TV_FOOD:
		case TV_ROD:
		case TV_WAND:
		case TV_STAFF:
		case TV_RING:
		case TV_AMULET:
		case TV_LITE:

		/* Never sell if not "known" */
		if (!item->able) return (FALSE);
		break;

		case TV_BOW:
		case TV_DIGGING:
		case TV_HAFTED:
		case TV_POLEARM:
		case TV_SWORD:
		case TV_BOOTS:
		case TV_GLOVES:
		case TV_HELM:
		case TV_CROWN:
		case TV_SHIELD:
		case TV_CLOAK:
		case TV_SOFT_ARMOR:
		case TV_HARD_ARMOR:
		case TV_DRAG_ARMOR:

		/* Only sell "known" (or "average") items (unless "icky") */
		if (!item->able && !streq(item->note, "{average}") &&
		    !borg_item_icky(item)) return (FALSE);

		break;
	}


	/* Switch on the store */
	switch (who + 1)
	{
		/* General Store */
		case 1:

		/* Analyze the type */
		switch (item->tval)
		{
			case TV_DIGGING:
			case TV_CLOAK:
			case TV_FOOD:
			case TV_FLASK:
			case TV_LITE:
			case TV_SPIKE:
			return (TRUE);
		}
		break;

		/* Armoury */
		case 2:

		/* Analyze the type */
		switch (item->tval)
		{
			case TV_BOOTS:
			case TV_GLOVES:
#if 0
			case TV_CLOAK:
#endif
			case TV_HELM:
			case TV_CROWN:
			case TV_SHIELD:
			case TV_SOFT_ARMOR:
			case TV_HARD_ARMOR:
			case TV_DRAG_ARMOR:
			return (TRUE);
		}
		break;

		/* Weapon Shop */
		case 3:

		/* Analyze the type */
		switch (item->tval)
		{
			case TV_SHOT:
			case TV_BOLT:
			case TV_ARROW:
			case TV_BOW:
#if 0
			case TV_DIGGING:
			case TV_HAFTED:
#endif
			case TV_POLEARM:
			case TV_SWORD:
			return (TRUE);
		}
		break;

		/* Temple */
		case 4:

		/* Analyze the type */
		switch (item->tval)
		{
			case TV_HAFTED:
#if 0
			case TV_SCROLL:
			case TV_POTION:
#endif
			case TV_PRAYER_BOOK:
			return (TRUE);
		}
		break;

		/* Alchemist */
		case 5:

		/* Analyze the type */
		switch (item->tval)
		{
			case TV_SCROLL:
			case TV_POTION:
			return (TRUE);
		}
		break;

		/* Magic Shop */
		case 6:

		/* Analyze the type */
		switch (item->tval)
		{
			case TV_MAGIC_BOOK:
			case TV_AMULET:
			case TV_RING:
#if 0
			case TV_SCROLL:
			case TV_POTION:
#endif
			case TV_STAFF:
			case TV_WAND:
			case TV_ROD:
			return (TRUE);
		}
		break;


		/* Black Market */
		case 7:

		/* Analyze the type */
		switch (item->tval)
		{
			case TV_CHEST:
			return (TRUE);
		}
		break;
	}

	/* Assume not */
	return (FALSE);
}



/*
 * Step 2 -- sell "useless" items to a shop (for cash)
 */
static bool borg_think_shop_sell_aux(void)
{
	int icky = STORE_INVEN_MAX - 1;

	int k, b_k = -1;
	int i, b_i = -1;
	s32b p, b_p = 0L;
	s32b c, b_c = 0L;

	bool fix = FALSE;


	/* Evaluate */
	b_p = my_power;


	/* Check each shop */
	for (k = 0; k < 7; k++)
	{
		/* Hack -- Skip "full" shops */
		if (auto_shops[k].ware[icky].iqty) continue;

		/* Save the store hole */
		COPY(&safe_shops[k].ware[icky], &auto_shops[k].ware[icky], auto_item);

		/* Sell stuff */
		for (i = 0; i < INVEN_PACK; i++)
		{
			auto_item *item = &auto_items[i];

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

			/* Skip "bad" sales */
			if (!borg_good_sell(item, k)) continue;

			/* Save the item */
			COPY(&safe_items[i], &auto_items[i], auto_item);

			/* Give the item to the shop */
			COPY(&auto_shops[k].ware[icky], &safe_items[i], auto_item);

			/* Give a single item */
			auto_shops[k].ware[icky].iqty = 1;

			/* Lose a single item */
			auto_items[i].iqty--;

			/* Fix later */
			fix = TRUE;

			/* Examine the inventory */
			borg_notice();

			/* Evaluate the inventory */
			p = borg_power();

			/* Restore the item */
			COPY(&auto_items[i], &safe_items[i], auto_item);

			/* Ignore "bad" sales */
			if (p < b_p) continue;

			/* Extract the "price" */
			c = ((item->value < 30000L) ? item->value : 30000L);

			/* Ignore "cheaper" items */
			if ((p == b_p) && (c <= b_c)) continue;

			/* Maintain the "best" */
			b_k = k; b_i = i; b_p = p; b_c = c;
		}

		/* Restore the store hole */
		COPY(&auto_shops[k].ware[icky], &safe_shops[k].ware[icky], auto_item);
	}

	/* Examine the inventory */
	if (fix) borg_notice();

	/* Sell something (if useless) */
	if ((b_k >= 0) && (b_i >= 0))
	{
		/* Visit that shop */
		goal_shop = b_k;

		/* Sell that item */
		goal_item = b_i;

		/* Success */
		return (TRUE);
	}

	/* Assume not */
	return (FALSE);
}



/*
 * Help decide if an item should be bought from a real store
 *
 * We prevent the purchase of enchanted (or expensive) ammo,
 * so we do not spend all our money on temporary power.
 *
 * We prevent the purchase of low level discounted books,
 * so we will not waste slots on cheap books.
 *
 * We prevent the purchase of items from the black market
 * which are often available at normal stores, currently,
 * this includes low level books, and all wands and staffs.
 */
static bool borg_good_buy(auto_item *item, int who)
{
	/* Check the object */
	switch (item->tval)
	{
		case TV_DIGGING:
		return (FALSE);

		case TV_SHOT:
		case TV_ARROW:
		case TV_BOLT:
		if (item->to_h) return (FALSE);
		if (item->to_d) return (FALSE);
		if (who == 6) return (FALSE);
		break;

		case TV_MAGIC_BOOK:
		case TV_PRAYER_BOOK:
		if (item->sval >= 4) break;
		if (item->discount) return (FALSE);
		if (who == 6) return (FALSE);
		break;

		case TV_WAND:
		case TV_STAFF:
		if (who == 6) return (FALSE);
		break;
	}


	/* Okay */
	return (TRUE);
}



/*
 * Step 3 -- buy "useful" things from a shop (to be used)
 */
static bool borg_think_shop_buy_aux(void)
{
	int hole = INVEN_PACK - 1;

	int slot;

	int k, b_k = -1;
	int n, b_n = -1;
	s32b p, b_p = 0L;
	s32b c, b_c = 0L;

	bool fix = FALSE;


	/* Require one empty slot */
	if (auto_items[hole].iqty) return (FALSE);


	/* Extract the "power" */
	b_p = my_power;


	/* Check the shops */
	for (k = 0; k < 7; k++)
	{
		/* Scan the wares */
		for (n = 0; n < STORE_INVEN_MAX; n++)
		{
			auto_item *item = &auto_shops[k].ware[n];

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

			/* Skip "bad" buys */
			if (!borg_good_buy(item, k)) continue;

			/* Hack -- Require "sufficient" cash */
			if (auto_gold < item->cost * 12 / 10) continue;

			/* Save shop item */
			COPY(&safe_shops[k].ware[n], &auto_shops[k].ware[n], auto_item);

			/* Save hole */
			COPY(&safe_items[hole], &auto_items[hole], auto_item);

			/* Remove one item from shop */
			auto_shops[k].ware[n].iqty--;

			/* Obtain "slot" */
			slot = borg_wield_slot(item);

			/* Consider new equipment */
			if (slot >= 0)
			{
				/* Save old item */
				COPY(&safe_items[slot], &auto_items[slot], auto_item);

				/* Move equipment into inventory */
				COPY(&auto_items[hole], &safe_items[slot], auto_item);

				/* Move new item into equipment */
				COPY(&auto_items[slot], &safe_shops[k].ware[n], auto_item);

				/* Only a single item */
				auto_items[slot].iqty = 1;

				/* Fix later */
				fix = TRUE;

				/* Examine the inventory */
				borg_notice();

				/* Evaluate the inventory */
				p = borg_power();

				/* Restore old item */
				COPY(&auto_items[slot], &safe_items[slot], auto_item);
			}

			/* Consider new inventory */
			else
			{
				/* Move new item into inventory */
				COPY(&auto_items[hole], &safe_shops[k].ware[n], auto_item);

				/* Only a single item */
				auto_items[hole].iqty = 1;

				/* Fix later */
				fix = TRUE;

				/* Examine the inventory */
				borg_notice();

				/* Evaluate the equipment */
				p = borg_power();
			}

			/* Restore hole */
			COPY(&auto_items[hole], &safe_items[hole], auto_item);

			/* Restore shop item */
			COPY(&auto_shops[k].ware[n], &safe_shops[k].ware[n], auto_item);

			/* Obtain the "cost" of the item */
			c = item->cost;

			/* Penalize the cost of expensive items */
			if (c > auto_gold / 10) p -= c;

			/* Ignore "bad" purchases */
			if (p < b_p) continue;

			/* Ignore "expensive" purchases */
			if ((p == b_p) && (c >= b_c)) continue;

			/* Save the item and cost */
			b_k = k; b_n = n; b_p = p; b_c = c;
		}
	}

	/* Examine the inventory */
	if (fix) borg_notice();

	/* Buy something */
	if ((b_k >= 0) && (b_n >= 0))
	{
		/* Visit that shop */
		goal_shop = b_k;

		/* Buy that item */
		goal_ware = b_n;

		/* Success */
		return (TRUE);
	}

	/* Nope */
	return (FALSE);
}


/*
 * Step 4 -- buy "useful" things from the home (to be used)
 */
static bool borg_think_home_buy_aux(void)
{
	int hole = INVEN_PACK - 1;

	int slot;

	int n, b_n = -1;
	s32b p, b_p = 0L;

	bool fix = FALSE;


	/* Require one empty slot */
	if (auto_items[hole].iqty) return (FALSE);


	/* Extract the "power" */
	b_p = my_power;


	/* Scan the home */
	for (n = 0; n < STORE_INVEN_MAX; n++)
	{
		auto_item *item = &auto_shops[7].ware[n];

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

		/* Save shop item */
		COPY(&safe_shops[7].ware[n], &auto_shops[7].ware[n], auto_item);

		/* Save hole */
		COPY(&safe_items[hole], &auto_items[hole], auto_item);

		/* Remove one item from shop */
		auto_shops[7].ware[n].iqty--;

		/* Obtain "slot" */
		slot = borg_wield_slot(item);

		/* Consider new equipment */
		if (slot >= 0)
		{
			/* Save old item */
			COPY(&safe_items[slot], &auto_items[slot], auto_item);

			/* Move equipment into inventory */
			COPY(&auto_items[hole], &safe_items[slot], auto_item);

			/* Move new item into equipment */
			COPY(&auto_items[slot], &safe_shops[7].ware[n], auto_item);

			/* Only a single item */
			auto_items[slot].iqty = 1;

			/* Fix later */
			fix = TRUE;

			/* Examine the inventory */
			borg_notice();

			/* Evaluate the inventory */
			p = borg_power();

			/* Restore old item */
			COPY(&auto_items[slot], &safe_items[slot], auto_item);
		}

		/* Consider new inventory */
		else
		{
			/* Move new item into inventory */
			COPY(&auto_items[hole], &safe_shops[7].ware[n], auto_item);

			/* Only a single item */
			auto_items[hole].iqty = 1;

			/* Fix later */
			fix = TRUE;

			/* Examine the inventory */
			borg_notice();

			/* Evaluate the equipment */
			p = borg_power();
		}

		/* Restore hole */
		COPY(&auto_items[hole], &safe_items[hole], auto_item);

		/* Restore shop item */
		COPY(&auto_shops[7].ware[n], &safe_shops[7].ware[n], auto_item);

		/* Ignore "silly" purchases */
		if (p <= b_p) continue;

		/* Save the item and cost */
		b_n = n; b_p = p;
	}

	/* Examine the inventory */
	if (fix) borg_notice();

	/* Buy something */
	if ((b_n >= 0) && (b_p > my_power))
	{
		/* Go to the home */
		goal_shop = 7;

		/* Buy that item */
		goal_ware = b_n;

		/* Success */
		return (TRUE);
	}

	/* Nope */
	return (FALSE);
}



/*
 * Step 5 -- buy "interesting" things from a shop (to be used later)
 */
static bool borg_think_shop_grab_aux(void)
{
	int icky = STORE_INVEN_MAX - 1;

	int k, b_k = -1;
	int n, b_n = -1;
	s32b s, b_s = 0L;
	s32b c, b_c = 0L;


	/* Hack -- the home is full */
	if (auto_shops[7].ware[icky].iqty) return (FALSE);


	/* Require two empty slots */
	if (auto_items[INVEN_PACK-1].iqty) return (FALSE);
	if (auto_items[INVEN_PACK-2].iqty) return (FALSE);


	/* Examine the home */
	borg_notice_home();

	/* Evaluate the home */
	b_s = borg_power_home();


	/* Save the store hole */
	COPY(&safe_shops[7].ware[icky], &auto_shops[7].ware[icky], auto_item);

	/* Check the shops */
	for (k = 0; k < 7; k++)
	{
		/* Scan the wares */
		for (n = 0; n < STORE_INVEN_MAX; n++)
		{
			auto_item *item = &auto_shops[k].ware[n];

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

			/* Skip "bad" buys */
			if (!borg_good_buy(item, k)) continue;

			/* Hack -- Require some "extra" cash */
			if (auto_gold < 1000L + item->cost * 5) continue;

			/* Save shop item */
			COPY(&safe_shops[k].ware[n], &auto_shops[k].ware[n], auto_item);

			/* Give the item to the shop */
			COPY(&auto_shops[7].ware[icky], &auto_shops[k].ware[n], auto_item);

			/* Give a single item */
			auto_shops[7].ware[icky].iqty = 1;

			/* Remove one item from shop */
			auto_shops[k].ware[n].iqty--;

			/* Examine the home */
			borg_notice_home();

			/* Evaluate the home */
			s = borg_power_home();

			/* Restore shop item */
			COPY(&auto_shops[k].ware[n], &safe_shops[k].ware[n], auto_item);

			/* Obtain the "cost" of the item */
			c = item->cost;

			/* Penalize expensive items */
			if (c > auto_gold / 10) s -= c;

			/* Ignore "bad" sales */
			if (s < b_s) continue;

			/* Ignore "expensive" purchases */
			if ((s == b_s) && (c >= b_c)) continue;

			/* Save the item and cost */
			b_k = k; b_n = n; b_s = s; b_c = c;
		}
	}

	/* Restore the store hole */
	COPY(&auto_shops[7].ware[icky], &safe_shops[7].ware[icky], auto_item);

	/* Examine the home */
	borg_notice_home();

	/* Evaluate the home */
	s = borg_power_home();

	/* Buy something */
	if ((b_k >= 0) && (b_n >= 0))
	{
		/* Visit that shop */
		goal_shop = b_k;

		/* Buy that item */
		goal_ware = b_n;

		/* Success */
		return (TRUE);
	}

	/* Nope */
	return (FALSE);
}


/*
 * Step 6 -- take "useless" things from the home (to be sold)
 */
static bool borg_think_home_grab_aux(void)
{
	int n, b_n = -1;
	s32b s, b_s = 0L;


	/* Require two empty slots */
	if (auto_items[INVEN_PACK-1].iqty) return (FALSE);
	if (auto_items[INVEN_PACK-2].iqty) return (FALSE);


	/* Examine the home */
	borg_notice_home();

	/* Evaluate the home */
	b_s = borg_power_home();


	/* Scan the home */
	for (n = 0; n < STORE_INVEN_MAX; n++)
	{
		auto_item *item = &auto_shops[7].ware[n];

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

		/* Save shop item */
		COPY(&safe_shops[7].ware[n], &auto_shops[7].ware[n], auto_item);

		/* Remove one item from shop */
		auto_shops[7].ware[n].iqty--;

		/* Examine the home */
		borg_notice_home();

		/* Evaluate the home */
		s = borg_power_home();

		/* Restore shop item */
		COPY(&auto_shops[7].ware[n], &safe_shops[7].ware[n], auto_item);

		/* Ignore "bad" sales */
		if (s < b_s) continue;

		/* Maintain the "best" */
		b_n = n; b_s = s;
	}

	/* Examine the home */
	borg_notice_home();

	/* Evaluate the home */
	s = borg_power_home();

	/* Stockpile */
	if (b_n >= 0)
	{
		/* Visit the home */
		goal_shop = 7;

		/* Grab that item */
		goal_ware = b_n;

		/* Success */
		return (TRUE);
	}

	/* Assume not */
	return (FALSE);
}




/*
 * Choose a shop to visit (see above)
 */
static bool borg_choose_shop(void)
{
	int i;


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

	/* Must have complete information */
	for (i = 0; i < 8; i++)
	{
		auto_shop *shop = &auto_shops[i];

		/* Skip "visited" shops */
		if (!shop->when) return (FALSE);
	}


	/* Assume no important shop */
	goal_shop = goal_ware = goal_item = -1;


	/* Step 1 -- Sell items to the home */
	if (borg_think_home_sell_aux())
	{
		/* Message */
		borg_note(format("# Selling '%s' to the home",
		                 auto_items[goal_item].desc));

		/* Success */
		return (TRUE);
	}


	/* Step 2 -- Sell items to the shops */
	if (borg_think_shop_sell_aux())
	{
		/* Message */
		borg_note(format("# Selling '%s' at '%s'",
		                 auto_items[goal_item].desc,
		                 (f_name + f_info[0x08+goal_shop].name)));

		/* Success */
		return (TRUE);
	}


	/* Step 3 -- Buy items from the shops (for the player) */
	if (borg_think_shop_buy_aux())
	{
		/* Message */
		borg_note(format("# Buying '%s' at '%s'",
		                 auto_shops[goal_shop].ware[goal_ware].desc,
		                 (f_name + f_info[0x08+goal_shop].name)));

		/* Success */
		return (TRUE);
	}


	/* Step 4 -- Buy items from the home (for the player) */
	if (borg_think_home_buy_aux())
	{
		/* Message */
		borg_note(format("# Buying '%s' from the home",
		                 auto_shops[goal_shop].ware[goal_ware].desc));

		/* Success */
		return (TRUE);
	}


	/* Step 5 -- Buy items from the shops (for the home) */
	if (borg_think_shop_grab_aux())
	{
		/* Message */
		borg_note(format("# Grabbing '%s' at '%s'",
		                 auto_shops[goal_shop].ware[goal_ware].desc,
		                 (f_name + f_info[0x08+goal_shop].name)));

		/* Success */
		return (TRUE);
	}


	/* Step 6 -- Grab items from the home (for the shops) */
	if (borg_think_home_grab_aux())
	{
		/* Message */
		borg_note(format("# Grabbing '%s' from the home",
		                 auto_shops[goal_shop].ware[goal_ware].desc));

		/* Success */
		return (TRUE);
	}


	/* Failure */
	return (FALSE);
}




/*
 * Sell items to the current shop, if desired
 */
static bool borg_think_shop_sell(void)
{
	/* Sell something if requested */
	if ((goal_shop == shop_num) && (goal_item >= 0))
	{
		auto_item *item = &auto_items[goal_item];

#if 0
		auto_shop *shop = &auto_shops[goal_shop];
#endif

		/* Log */
		borg_note(format("# Selling %s", item->desc));

		/* Buy an item */
		borg_keypress('s');

		/* Buy the desired item */
		borg_keypress(I2A(goal_item));

		/* Hack -- Sell a single item */
		if (item->iqty > 1) borg_keypress('\n');

		/* Mega-Hack -- Accept the price */
		borg_keypress('\n');
		borg_keypress('\n');
		borg_keypress('\n');
		borg_keypress('\n');

		/* The purchase is complete */
		goal_shop = goal_item = -1;

		/* Success */
		return (TRUE);
	}

	/* Nope */
	return (FALSE);
}


/*
 * Buy items from the current shop, if desired
 */
static bool borg_think_shop_buy(void)
{
	/* Buy something if requested */
	if ((goal_shop == shop_num) && (goal_ware >= 0))
	{
		auto_shop *shop = &auto_shops[goal_shop];

		auto_item *item = &shop->ware[goal_ware];

		/* Minor Hack -- Go to the correct page */
		if ((goal_ware / 12) != shop->page) borg_keypress(' ');

		/* Log */
		borg_note(format("# Buying %s.", item->desc));

		/* Buy an item */
		borg_keypress('p');

		/* Buy the desired item */
		borg_keypress(I2A(goal_ware % 12));

		/* Hack -- Buy a single item */
		if (item->iqty > 1) borg_keypress('\n');

		/* Mega-Hack -- Accept the price */
		borg_keypress('\n');
		borg_keypress('\n');
		borg_keypress('\n');
		borg_keypress('\n');

		/* The purchase is complete */
		goal_shop = goal_ware = -1;

		/* Success */
		return (TRUE);
	}

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


/*
 * Deal with being in a store
 */
bool borg_think_store(void)
{
	/* Remove "backwards" rings */
	if (borg_swap_rings()) return (TRUE);

	/* Repair "backwards" rings */
	if (borg_wear_rings()) return (TRUE);

	/* Wear "optimal" equipment */
	if (borg_best_stuff()) return (TRUE);

	/* Wear "useful" equipment */
	/* if (borg_wear_stuff()) return (TRUE); */

	/* Remove "useless" equipment */
	if (borg_takeoff_stuff()) return (TRUE);

	/* Choose a shop to visit */
	if (borg_choose_shop())
	{
		/* Try to sell stuff */
		if (borg_think_shop_sell()) return (TRUE);

		/* Try to buy stuff */
		if (borg_think_shop_buy()) return (TRUE);
	}

	/* Stamp the shop with a time stamp */
	auto_shops[shop_num].when = c_t;

	/* No shop */
	shop_num = -1;

	/* Leave the store */
	borg_keypress(ESCAPE);

	/* Done */
	return (TRUE);
}



/*
 * Hack -- perform an action in the dungeon under boosted bravery
 *
 * This function is a sub-set of the standard dungeon goals, and is
 * only executed when all of the standard dungeon goals fail, because
 * of excessive danger, or because the level is "bizarre".
 */
static bool borg_think_dungeon_brave(void)
{
	/*** Local stuff ***/

	/* Attack monsters */
	if (borg_attack()) return (TRUE);

	/* Continue flowing towards monsters */
	if (borg_flow_old(GOAL_KILL)) return (TRUE);

	/* Find a (viewable) monster */
	if (borg_flow_kill(TRUE)) return (TRUE);

	/* Continue flowing towards objects */
	if (borg_flow_old(GOAL_TAKE)) return (TRUE);

	/* Find a (viewable) object */
	if (borg_flow_take(TRUE)) return (TRUE);


	/*** Flee (or leave) the level ***/

	/* Flee the level */
	if (goal_fleeing || goal_leaving)
	{
		/* Hack -- Take the next stairs */
		stair_less = stair_more = TRUE;

		/* Continue fleeing the level */
		if (borg_flow_old(GOAL_FLEE)) return (TRUE);

		/* Try to find some stairs up */
		if (borg_flow_stair_less(GOAL_FLEE)) return (TRUE);

		/* Try to find some stairs down */
		if (borg_flow_stair_more(GOAL_FLEE)) return (TRUE);
	}


	/*** Exploration ***/

	/* Continue flowing (see below) */
	if (borg_flow_old(GOAL_MISC)) return (TRUE);

	/* Continue flowing (see below) */
	if (borg_flow_old(GOAL_DARK)) return (TRUE);

	/* Continue flowing (see below) */
	if (borg_flow_old(GOAL_XTRA)) return (TRUE);

	/* Continue flowing (see below) */
	if (borg_flow_old(GOAL_BORE)) return (TRUE);


	/*** Explore the dungeon ***/

	/* Explore interesting grids */
	if (borg_flow_dark(TRUE)) return (TRUE);

	/* Explore interesting grids */
	if (borg_flow_dark(FALSE)) return (TRUE);

	/* Search for secret doors */
	if (borg_flow_spastic(FALSE)) return (TRUE);


	/*** Track down old stuff ***/

	/* Chase old objects */
	if (borg_flow_take(FALSE)) return (TRUE);

	/* Chase old monsters */
	if (borg_flow_kill(FALSE)) return (TRUE);

	/* Search for secret doors */
	if (borg_flow_spastic(TRUE)) return (TRUE);


	/* Nothing */
	return (FALSE);
}


/*
 * Perform an action in the dungeon
 *
 * Return TRUE if a "meaningful" action was performed
 * Otherwise, return FALSE so we will be called again
 *
 * Strategy:
 *   Make sure we are happy with our "status" (see above)
 *   Attack and kill visible monsters, if near enough
 *   Open doors, disarm traps, tunnel through rubble
 *   Pick up (or tunnel to) gold and useful objects
 *   Explore "interesting" grids, to expand the map
 *   Explore the dungeon and revisit old grids
 *
 * Fleeing:
 *   Use word of recall when level is "scary"
 *   Flee to stairs when there is a chance of death
 *   Avoid "stair bouncing" if at all possible
 *
 * Note that the various "flow" actions allow the Borg to flow
 * "through" closed doors, which will be opened when he attempts
 * to pass through them, so we do not have to pursue terrain until
 * all monsters and objects have been dealt with.
 *
 * XXX XXX XXX The poor Borg often kills a nasty monster, and
 * then takes a nap to recover from damage, but gets yanked
 * back to town before he can collect his reward.
 */
bool borg_think_dungeon(void)
{
	int i, j;

	/* Hack -- prevent clock wrapping */
	if (c_t >= 30000)
	{
		/* Panic */
		borg_oops("clock overflow");

		/* Oops */
		return (TRUE);
	}

	/* Prevent clock overflow */
	if (c_t - auto_began >= 10000)
	{
		/* Start leaving */
		if (!goal_leaving)
		{
			/* Note */
			borg_note("# Leaving (boredom)");

			/* Start leaving */
			goal_leaving = TRUE;
		}

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

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

	/* Avoid annoying farming */
	if (c_t - auto_began >= 5000)
	{
		/* Ignore monsters from boredom */
		if (!goal_ignoring)
		{
			/* Flee */
			borg_note("# Ignoring breeders (boredom)");

			/* Ignore multipliers */
			goal_ignoring = TRUE;
		}
	}


	/* Count the awake breeders */
	for (j = 0, i = 1; i < auto_kills_nxt; i++)
	{
		auto_kill *kill = &auto_kills[i];

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

		/* Skip sleeping monsters */
		if (!kill->awake) continue;

		/* Count the monsters which are "breeders" */
		if (r_info[kill->r_idx].flags2 & RF2_MULTIPLY) j++;
	}

	/* Hack -- caution */
	if (j && (amt_recall <= 0))
	{
		/* Ignore monsters from caution */
		if (!goal_ignoring)
		{
			/* Flee */
			borg_note("# Ignoring breeders (no recall)");

			/* Ignore multipliers */
			goal_ignoring = TRUE;
		}

		/* Start leaving */
		if (!goal_leaving)
		{
			/* Note */
			borg_note("# Leaving (no recall)");

			/* Start leaving */
			goal_leaving = TRUE;
		}

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

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

	/* Reset avoidance */
	if (avoidance != auto_chp)
	{
		/* Reset "avoidance" */
		avoidance = auto_chp;

		/* Re-calculate danger */
		auto_danger_wipe = TRUE;

		/* Forget goals */
		goal = 0;
	}


	/*** Important goals ***/

	/* Try not to die */
	if (borg_caution()) return (TRUE);

	/* Wear things that need to be worn */
	if (borg_wear_stuff()) return (TRUE);

	/* Learn useful spells immediately */
	if (borg_play_magic(FALSE)) return (TRUE);

	/* Attack monsters */
	if (borg_attack()) return (TRUE);

	/* Recover from damage */
	if (borg_recover()) return (TRUE);

	/* Continue flowing towards monsters */
	if (borg_flow_old(GOAL_KILL)) return (TRUE);

	/* Find a (viewable) monster */
	if (borg_flow_kill(TRUE)) return (TRUE);


	/*** Deal with inventory objects ***/

	/* Check the light */
	if (borg_check_lite()) return (TRUE);

	/* Use things */
	if (borg_use_things()) return (TRUE);

	/* Identify unknown things */
	if (borg_test_stuff()) return (TRUE);

	/* Enchant things */
	if (borg_enchanting()) return (TRUE);

	/* Recharge things */
	if (borg_recharging()) return (TRUE);

	/* Destroy junk */
	if (borg_crush_junk()) return (TRUE);

	/* Destroy items to make space */
	if (borg_crush_hole()) return (TRUE);

	/* Destroy items if we are slow */
	if (borg_crush_slow()) return (TRUE);


	/*** Flee the level XXX XXX XXX ***/

	/* Flee the level */
	if (goal_fleeing)
	{
		/* Hack -- Take the next stairs */
		stair_less = stair_more = TRUE;

		/* Continue fleeing the level */
		if (borg_flow_old(GOAL_FLEE)) return (TRUE);

		/* Try to find some stairs up */
		if (borg_flow_stair_less(GOAL_FLEE)) return (TRUE);

		/* Try to find some stairs down */
		if (borg_flow_stair_more(GOAL_FLEE)) return (TRUE);
	}


	/*** Flow towards objects ***/

	/* Continue flowing towards objects */
	if (borg_flow_old(GOAL_TAKE)) return (TRUE);

	/* Find a (viewable) object */
	if (borg_flow_take(TRUE)) return (TRUE);


	/*** Leave the level XXX XXX XXX ***/

	/* Leave the level */
	if (goal_leaving)
	{
		/* Hack -- Take the next stairs */
		stair_less = stair_more = TRUE;

		/* Continue leaving the level */
		if (borg_flow_old(GOAL_FLEE)) return (TRUE);

		/* Try to find some stairs up */
		if (borg_flow_stair_less(GOAL_FLEE)) return (TRUE);

		/* Try to find some stairs down */
		if (borg_flow_stair_more(GOAL_FLEE)) return (TRUE);
	}


	/*** Exploration ***/

	/* Continue flowing (see below) */
	if (borg_flow_old(GOAL_MISC)) return (TRUE);

	/* Continue flowing (see below) */
	if (borg_flow_old(GOAL_DARK)) return (TRUE);

	/* Continue flowing (see below) */
	if (borg_flow_old(GOAL_XTRA)) return (TRUE);

	/* Continue flowing (see below) */
	if (borg_flow_old(GOAL_BORE)) return (TRUE);


	/*** Explore the dungeon ***/

	/* Chase old monsters */
	if (borg_flow_kill(FALSE)) return (TRUE);

	/* Explore interesting grids */
	if (borg_flow_dark(TRUE)) return (TRUE);

	/* Chase old objects */
	if (borg_flow_take(FALSE)) return (TRUE);

	/* Leave the level (if needed) */
	if (borg_leave_level(FALSE)) return (TRUE);

	/* Explore interesting grids */
	if (borg_flow_dark(FALSE)) return (TRUE);


	/*** Deal with shops ***/

	/* Hack -- visit all the shops */
	if (borg_flow_shop_visit()) return (TRUE);

	/* Hack -- Visit the shops */
	if (borg_choose_shop())
	{
		/* Try and visit a shop, if so desired */
		if (borg_flow_shop_entry(goal_shop)) return (TRUE);
	}



	/*** Leave the Level ***/

	/* Study/Test boring spells/prayers */
	if (borg_play_magic(FALSE)) return (TRUE);

	/* Search for secret doors */
	if (borg_flow_spastic(FALSE)) return (TRUE);

	/* Leave the level (if possible) */
	if (borg_leave_level(TRUE)) return (TRUE);

	/* Search for secret doors */
	if (borg_flow_spastic(TRUE)) return (TRUE);


	/*** Wait for recall ***/

	/* Wait for recall, unless in danger */
	if (goal_recalling && (borg_danger(c_y, c_x, 1) <= 0))
	{
		/* Take note */
		borg_note("# Waiting for Recall...");

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

		/* Done */
		return (TRUE);
	}


	/*** Nothing to do ***/

	/* Start leaving */
	if (!goal_leaving)
	{
		/* Note */
		borg_note("# Leaving (twitchy)");

		/* Start leaving */
		goal_leaving = TRUE;
	}

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

		/* Start fleeing */
		goal_fleeing = TRUE;

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

	/* Recall to town */
	if (auto_depth && (borg_recall()))
	{
		/* Note */
		borg_note("# Recalling (twitchy)");

		/* Success */
		return (TRUE);
	}

	/* Boost slightly */
	if (avoidance < auto_chp * 2)
	{
		bool done = FALSE;

		/* Note */
		borg_note(format("# Boosting bravery (1) from %d to %d!",
		                 avoidance, auto_chp * 2));

		/* Hack -- ignore some danger */
		avoidance = (auto_chp * 2);

		/* Forget the danger fields */
		auto_danger_wipe = TRUE;

		/* Try anything */
		if (borg_think_dungeon_brave()) done = TRUE;

		/* Reset "avoidance" */
		avoidance = auto_chp;

		/* Re-calculate danger */
		auto_danger_wipe = TRUE;

		/* Forget goals */
		goal = 0;

		/* Done */
		if (done) return (TRUE);
	}

	/* Boost some more */
	if (avoidance < auto_mhp * 4)
	{
		bool done = FALSE;

		/* Note */
		borg_note(format("# Boosting bravery (2) from %d to %d!",
		                 avoidance, auto_mhp * 4));

		/* Hack -- ignore some danger */
		avoidance = (auto_mhp * 4);

		/* Forget the danger fields */
		auto_danger_wipe = TRUE;

		/* Try anything */
		if (borg_think_dungeon_brave()) done = TRUE;

		/* Reset "avoidance" */
		avoidance = auto_chp;

		/* Re-calculate danger */
		auto_danger_wipe = TRUE;

		/* Forget goals */
		goal = 0;

		/* Done */
		if (done) return (TRUE);
	}

	/* Boost a lot */
	if (avoidance < 30000)
	{
		bool done = FALSE;

		/* Note */
		borg_note(format("# Boosting bravery (3) from %d to %d!",
		                 avoidance, 30000));

		/* Hack -- ignore some danger */
		avoidance = 30000;

		/* Forget the danger fields */
		auto_danger_wipe = TRUE;

		/* Try anything */
		if (borg_think_dungeon_brave()) done = TRUE;

		/* Reset "avoidance" */
		avoidance = auto_chp;

		/* Re-calculate danger */
		auto_danger_wipe = TRUE;

		/* Forget goals */
		goal = 0;

		/* Done */
		if (done) return (TRUE);
	}

	/* Twitch around */
	if (borg_twitchy()) return (TRUE);

	/* Oops */
	return (FALSE);
}




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


#else

#ifdef MACINTOSH
static int HACK = 0;
#endif /* MACINTOSH */

#endif /* ALLOW_BORG */
