/* File: borg7.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"


/*
 * This file handles various high level inventory related goals.
 *
 * Problems:
 *   Use "time stamps" (and not "random" checks) for several routines,
 *   including "kill junk" and "wear stuff", and maybe even "free space".
 *   But be careful with the "free space" routine, wear stuff first.
 *   Make sure nothing is "destroyed" if we do not do them every turn.
 *   Consider some special routines in stores (and in the home).
 *
 * Hack -- We should perhaps consider wearing "harmless" items into empty
 * slots when in the dungeon, to allow rings/amulets to be brought back up
 * to town to be sold.
 *
 * We should take account of possible combinations of equipment.  This may
 * be a potentially expensive computation, but could be done occasionally.
 * It is important to use a "state-less" formula to allow the exchange to
 * be spread over multiple turns.
 *
 * Hack -- We should attempt to only collect non-discounted items, at least
 * for the "expensive" slots, such as books, since we do not want to lose
 * value due to stacking.  We seem to sell the non-discounted items first,
 * and to buy the discounted items first, since they are cheap.  Oh well,
 * we may just be stuck with using discounted books.  Unless we actually
 * do correct "combining" in the simulations, and reward free slots.  Ick!
 *
 * XXX XXX XXX We really need a better "twitchy" function.
 *
 * XXX XXX XXX We need a better "flee this level" function
 *
 * XXX XXX XXX We need to stockpile possible useful items at home.
 *
 * XXX XXX XXX Perhaps we could simply maintain a list of abilities
 * that we might need at some point, such as the ability to identify, and
 * simply allow the Borg to "sell" items to the home which satisfy this
 * desire for "abilities".
 *
 * XXX XXX XXX Also, we should probably attempt to track the "best" item
 * in the home for each equipment slot, using some form of heuristic, and
 * reward that item based on its power, so that the Borg would always
 * have a "backup" item in case of disenchantment.
 *
 * XXX XXX XXX Also, we could reward equipment based on possible enchantment,
 * up to the maximal amount available in the home, which would induce item
 * switching when the item could be enchanted sufficiently.
 *
 * Fleeing from fast spell-casters is probably not a very smart idea, nor is
 * fleeing from fast monsters, nor is attempting to clear a room full of fast
 * moving breeding monsters, such as lice.
 */



/*
 * Hack -- importance of the various "level feelings"
 * Try to explore the level for at least this many turns
 */
static s16b value_feeling[] =
{
    500,
    8000,
    8000,
    6000,
    4000,
    2000,
    1000,
    800,
    600,
    400,
    200,
    0
};




/*
 * Determine if an item is "probably" worthless
 *
 * This (very heuristic) function is a total hack, designed only to prevent
 * a very specific annoying situation described below.
 *
 * Note that a "cautious" priest (or low level mage/ranger) will leave town
 * with a few identify scrolls, wander around dungeon level 1 for a few turns,
 * and use all of the scrolls on leather gloves and broken daggers, and must
 * then return to town for more scrolls.  This may repeat indefinitely.
 *
 * The problem is that some characters (priests, mages, rangers) never get an
 * "average" feeling about items, and have no way to keep track of how long
 * they have been holding a given item for, so they cannot even attempt to
 * gain knowledge from the lack of "good" or "cursed" feelings.  But they
 * cannot afford to just identify everything they find by using scrolls of
 * identify, because, in general, some items are, on average, "icky", and
 * not even worth the price of a new scroll of identify.
 *
 * Even worse, the current algorithm refuses to sell un-identified items, so
 * the poor character will throw out all his good stuff to make room for crap.
 *
 * This function simply examines the item and assumes that certain items are
 * "icky", which is probably a total hack.  Perhaps we could do something like
 * compare the item to the item we are currently wearing, or perhaps we could
 * analyze the expected value of the item, or guess at the likelihood that the
 * item might be a blessed, or something.
 *
 * Currently, only characters who do not get "average" feelings are allowed
 * to decide that something is "icky", others must wait for an "average"
 * feeling.
 */
bool borg_item_icky(auto_item *item)
{
    /* Mega-Hack -- allow "icky" items */
    if ((auto_class != CLASS_PRIEST) &&
        (auto_class != CLASS_RANGER) &&
        (auto_class != CLASS_MAGE)) return (FALSE);

    /* Broken dagger/sword, Filthy rag */
    if (((item->tval == TV_SWORD) && (item->sval == SV_BROKEN_DAGGER)) ||
        ((item->tval == TV_SWORD) && (item->sval == SV_BROKEN_SWORD)) ||
        ((item->tval == TV_SOFT_ARMOR) && (item->sval == SV_FILTHY_RAG)))
    {
        return (TRUE);
    }

    /* Dagger, Sling */
    if (((item->tval == TV_SWORD) && (item->sval == SV_DAGGER)) ||
        ((item->tval == TV_BOW) && (item->sval == SV_SLING)))
    {
        return (TRUE);
    }

    /* Cloak, Robe */
    if (((item->tval == TV_CLOAK) && (item->sval == SV_CLOAK)) ||
        ((item->tval == TV_SOFT_ARMOR) && (item->sval == SV_ROBE)))
    {
        return (TRUE);
    }

    /* Leather Gloves */
    if ((item->tval == TV_GLOVES) &&
        (item->sval == SV_SET_OF_LEATHER_GLOVES))
    {
        return (TRUE);
    }

    /* Hack -- Diggers */
    if (item->tval == TV_DIGGING) return (TRUE);

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



/*
 * Use things in a useful, but non-essential, manner
 */
bool borg_use_things(void)
{
    int i;

    /* Quaff experience restoration potion */
    if (do_fix_exp &&
       (borg_prayer(6,4) ||
        borg_quaff_potion(SV_POTION_RESTORE_EXP)))
    {
        return (TRUE);
    }

    if ((my_stat_cur[A_STR] < (18+100 + 10 * p_ptr->maximize *
         (rp_ptr->r_adj[A_STR] + cp_ptr->c_adj[A_STR])) &&
         borg_quaff_potion(SV_POTION_INC_STR)) ||
        (my_stat_cur[A_INT] < (18+100 + 10 * p_ptr->maximize *
         (rp_ptr->r_adj[A_INT] + cp_ptr->c_adj[A_INT])) &&
         borg_quaff_potion(SV_POTION_INC_INT)) ||
        (my_stat_cur[A_WIS] < (18+100 + 10 * p_ptr->maximize *
         (rp_ptr->r_adj[A_WIS] + cp_ptr->c_adj[A_WIS])) &&
         borg_quaff_potion(SV_POTION_INC_WIS)) ||
        (my_stat_cur[A_DEX] < (18+100 + 10 * p_ptr->maximize *
         (rp_ptr->r_adj[A_DEX] + cp_ptr->c_adj[A_DEX])) &&
         borg_quaff_potion(SV_POTION_INC_DEX)) ||
        (my_stat_cur[A_CON] < (18+100 + 10 * p_ptr->maximize *
         (rp_ptr->r_adj[A_CON] + cp_ptr->c_adj[A_CON])) &&
         borg_quaff_potion(SV_POTION_INC_CON)) ||
        (my_stat_cur[A_CHR] < (18+100 + 10 * p_ptr->maximize *
         (rp_ptr->r_adj[A_CHR] + cp_ptr->c_adj[A_CHR])) &&
         borg_quaff_potion(SV_POTION_INC_CHR))     )
    {
        return (TRUE);
    }

    /* Quaff potions of "restore" stat if needed */
    if ( (do_fix_stat[A_STR] &&
         (borg_quaff_potion(SV_POTION_RES_STR) ||
          borg_quaff_potion(SV_POTION_INC_STR))) ||
        (do_fix_stat[A_INT] &&
         (borg_quaff_potion(SV_POTION_RES_INT) ||
          borg_quaff_potion(SV_POTION_INC_INT))) ||
        (do_fix_stat[A_WIS] &&
         (borg_quaff_potion(SV_POTION_RES_WIS) ||
          borg_quaff_potion(SV_POTION_INC_WIS))) ||
        (do_fix_stat[A_DEX] &&
         (borg_quaff_potion(SV_POTION_RES_DEX) ||
          borg_quaff_potion(SV_POTION_INC_DEX))) ||
        (do_fix_stat[A_CON] &&
         (borg_quaff_potion(SV_POTION_RES_CON) ||
          borg_quaff_potion(SV_POTION_INC_CON))) ||
        ((do_fix_stat[A_CHR]) &&
         (borg_quaff_potion(SV_POTION_RES_CHR) ||
          borg_quaff_potion(SV_POTION_INC_CHR))))
    {
        return (TRUE);
    }


    /* Use some items right away */
    for (i = 0; i < INVEN_PACK; i++)
    {
        auto_item *item = &auto_items[i];

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

        /* Process "force" items */
        switch (item->tval)
        {
            case TV_POTION:
            {
                /* Check the scroll */
                switch (item->sval)
                {
                    case SV_POTION_ENLIGHTENMENT:

                        /* Never quaff these in town */
                        if (!auto_depth) break;

                    case SV_POTION_AUGMENTATION:
                    case SV_POTION_EXPERIENCE:

                        /* Try quaffing the potion */
                        if (borg_quaff_potion(item->sval)) return (TRUE);
                }

                break;
            }
            case TV_SCROLL:
            {
                /* Hack -- check Blind/Confused */
                if (do_blind || do_confused) break;

                /* XXX XXX XXX Dark */

                /* Check the scroll */
                switch (item->sval)
                {
                    case SV_SCROLL_MAPPING:
                    case SV_SCROLL_DETECT_TRAP:
                    case SV_SCROLL_DETECT_DOOR:
                    case SV_SCROLL_ACQUIREMENT:
                    case SV_SCROLL_STAR_ACQUIREMENT:
                    case SV_SCROLL_PROTECTION_FROM_EVIL:
                    {
                        /* Never read these in town */
                        if (!auto_depth) break;

                        /* Try reading the scroll */
                        if (borg_read_scroll(item->sval)) return (TRUE);
                        break;
                    }
                }

                break;
            }
        }
    }


    /* Eat food */
    if (do_hungry)
    {
        /* Attempt to satisfy hunger */
        if (borg_spell(2, 0) ||
            borg_prayer(1, 5) ||
            borg_eat_food(SV_FOOD_RATION))
        {
            return (TRUE);
        }
    }


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



/*
 * Refuel, call lite, detect traps/doors/walls, etc
 *
 * Note that we refuel whenever our lite starts to get low.
 *
 * Note that we detect traps/doors/walls at least once in each
 * panel, as soon as possible after entering a new panel.
 *
 * Note that we call lite whenever the current grid is dark, and
 * all the grids touching the current grid diagonally are known
 * floors, which catches all rooms, including "checkerboard" rooms,
 * and only occasionally calls lite in corridors, and then only once.
 *
 * Note that we also sometimes call lite whenever we are using a
 * lantern or artifact lite, and when all of the grids in the box
 * of grids containing the maximal torch-lit region (the 5x5 or 7x7
 * region centered at the player) are non-glowing floor grids, and
 * when at least one of them is known to be "dark".  This catches
 * most of the "probable rooms" before the standard check succeeds.
 *
 * We use the special "SELF" messages to "borg_react()" to delay the
 * processing of "detection" and "call lite" until we know if it has
 * worked or not.
 */
bool borg_check_lite(void)
{
    int i, x, y;

    int q_x, q_y;

    auto_grid *ag;


    bool do_lite;

    bool do_trap;
    bool do_door;
    bool do_wall;

    bool do_lite_aux = FALSE;


    /* Never in town */
    if (!auto_depth) return (FALSE);

    /* Never when blind or confused or hallucinating */
    if (do_blind || do_confused || do_image) return (FALSE);

    /* XXX XXX XXX Dark */


    /* Extract the panel */
    q_x = w_x / 33;
    q_y = w_y / 11;


    /* Start */
    do_trap = FALSE;

    /* Determine if we need to detect traps */
    if (!auto_detect_trap[q_y+0][q_x+0]) do_trap = TRUE;
    if (!auto_detect_trap[q_y+0][q_x+1]) do_trap = TRUE;
    if (!auto_detect_trap[q_y+1][q_x+0]) do_trap = TRUE;
    if (!auto_detect_trap[q_y+1][q_x+1]) do_trap = TRUE;

    /* Hack -- check traps every few turns anyway */
    if (!when_detect_traps || (c_t - when_detect_traps >= 183)) do_trap = TRUE;


    /* Start */
    do_door = FALSE;

    /* Determine if we need to detect doors */
    if (!auto_detect_door[q_y+0][q_x+0]) do_door = TRUE;
    if (!auto_detect_door[q_y+0][q_x+1]) do_door = TRUE;
    if (!auto_detect_door[q_y+1][q_x+0]) do_door = TRUE;
    if (!auto_detect_door[q_y+1][q_x+1]) do_door = TRUE;

    /* Hack -- check doors every few turns anyway */
    if (!when_detect_doors || (c_t - when_detect_doors >= 731)) do_door = TRUE;


    /* Start */
    do_wall = FALSE;

    /* Determine if we need to detect walls */
    if (!auto_detect_wall[q_y+0][q_x+0]) do_wall = TRUE;
    if (!auto_detect_wall[q_y+0][q_x+1]) do_wall = TRUE;
    if (!auto_detect_wall[q_y+1][q_x+0]) do_wall = TRUE;
    if (!auto_detect_wall[q_y+1][q_x+1]) do_wall = TRUE;

    /* Hack -- check walls every few turns anyway */
    if (!when_detect_walls || (c_t - when_detect_walls >= 937)) do_wall = TRUE;


    /* Hack -- find traps and doors */
    if ((do_trap || do_door) &&
        ((!when_detect_traps || (c_t - when_detect_traps >= 5)) ||
         (!when_detect_doors || (c_t - when_detect_doors >= 5))))
    {
        /* Check for traps and doors */
        if (borg_zap_rod(SV_ROD_DETECTION) ||
            borg_spell(0, 7) ||
            borg_prayer(5, 1))
        {
            borg_note("# Checking for traps and doors.");

            borg_react("SELF:both", "SELF:both");

            when_detect_traps = c_t;
            when_detect_doors = c_t;

            return (TRUE);
        }
    }


    /* Hack -- find traps */
    if (do_trap &&
        (!when_detect_traps || (c_t - when_detect_traps >= 7)))
    {
        /* Check for traps */
        if (borg_read_scroll(SV_SCROLL_DETECT_TRAP) ||
            borg_use_staff(SV_STAFF_DETECT_TRAP) ||
            borg_zap_rod(SV_ROD_DETECT_TRAP) ||
            borg_prayer(0, 5))
        {
            borg_note("# Checking for traps.");

            borg_react("SELF:trap", "SELF:trap");

            when_detect_traps = c_t;

            return (TRUE);
        }
    }


    /* Hack -- find doors */
    if (do_door &&
        (!when_detect_doors || (c_t - when_detect_doors >= 9)))
    {
        /* Check for traps */
        if (borg_read_scroll(SV_SCROLL_DETECT_DOOR) ||
            borg_use_staff(SV_STAFF_DETECT_DOOR) ||
            borg_zap_rod(SV_ROD_DETECT_DOOR) ||
            borg_prayer(0, 6))
        {
            borg_note("# Checking for doors.");

            borg_react("SELF:door", "SELF:door");

            when_detect_doors = c_t;

            return (TRUE);
        }
    }


    /* Hack -- find walls */
    if (do_wall &&
        (!when_detect_walls || (c_t - when_detect_walls >= 15)))
    {
        /* Check for walls */
        if (borg_activate_artifact(ART_ELENDIL) ||
            borg_read_scroll(SV_SCROLL_MAPPING) ||
            borg_use_staff(SV_STAFF_MAPPING) ||
            borg_prayer(2, 6))
        {
            borg_note("# Checking for walls.");

            borg_react("SELF:wall", "SELF:wall");

            when_detect_walls = c_t;

            return (TRUE);
        }
    }


    /* Start */
    do_lite = FALSE;

    /* Get central grid */
    ag = &auto_grids[c_y][c_x];

    /* Dark central grid */
    if (ag->info & BORG_DARK)
    {
        /* Assume okay */
        do_lite = TRUE;

        /* Scan diagonal neighbors */
        for (i = 4; i < 8; i++)
        {
            /* Get location */
            x = c_x + ddx_ddd[i];
            y = c_y + ddy_ddd[i];

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

            /* Location must be known */
            if (ag->feat == FEAT_NONE) do_lite = FALSE;

            /* Location must not be a wall/door */
            if (!borg_cave_floor_grid(ag)) do_lite = FALSE;
        }
    }

    /* Hack */
    if (!do_lite && (my_cur_lite >= 2) &&
        (c_x >= my_cur_lite) && (c_x < AUTO_MAX_X - my_cur_lite) &&
        (c_y >= my_cur_lite) && (c_y < AUTO_MAX_Y - my_cur_lite) &&
        (rand_int(100) < 90))
    {
        bool f1 = TRUE;
        bool f2 = FALSE;

        /* Scan the "local" grids (5x5 or 7x7) */
        for (y = c_y - my_cur_lite; y <= c_y + my_cur_lite; y++)
        {
            /* Scan the "local" grids (5x5 or 7x7) */
            for (x = c_x - my_cur_lite; x <= c_x + my_cur_lite; x++)
            {
                /* Get grid */
                ag = &auto_grids[y][x];

                /* Location must be a floor */
                if (!borg_cave_floor_grid(ag)) f1 = FALSE;

                /* Location must not be glowing */
                if (ag->info & BORG_GLOW) f1 = FALSE;

                /* Notice any known dark grids */
                if (ag->info & BORG_DARK) f2 = TRUE;
            }
        }

        /* Sounds good XXX XXX XXX */
        if (f1 && f2) do_lite = do_lite_aux = TRUE;
    }


    /* Hack -- call lite */
    if (do_lite &&
        (!when_call_lite || (c_t - when_call_lite >= 7)))
    {
        /* Call light */
        if (borg_activate_artifact(ART_GALADRIEL) ||
            borg_zap_rod(SV_ROD_ILLUMINATION) ||
            borg_use_staff(SV_STAFF_LITE) ||
            borg_read_scroll(SV_SCROLL_LIGHT) ||
            borg_spell(0, 3) ||
            borg_prayer(0, 4))
        {
            if (do_lite_aux) borg_note("# Gratuitous illumination");

            borg_note("# Illuminating the room");

            borg_react("SELF:lite", "SELF:lite");

            when_call_lite = c_t;

            return (TRUE);
        }
    }


    /* Hack -- Wizard Lite */
    if (TRUE &&
        (!when_wizard_lite || (c_t - when_wizard_lite >= 1000)))
    {
        /* Wizard lite */
        if (borg_activate_artifact(ART_THRAIN) ||
            borg_prayer(5, 4))
        {
            borg_note("# Illuminating the dungeon");

            /* borg_react("SELF:wizard lite", "SELF:wizard lite"); */

            when_wizard_lite = c_t;

            return (TRUE);
        }
    }


    /* Oops */
    return (FALSE);
}



/*
 * Enchant armor
 */
static bool borg_enchant_to_a(void)
{
    int i, b_i = -1;
    int a, b_a = 99;


    /* Nothing to enchant */
    if (!my_need_enchant_to_a) return (FALSE);

    /* Need "enchantment" ability */
    if (!amt_enchant_to_a) return (FALSE);


    /* Look for armor that needs enchanting */
    for (i = INVEN_BODY; i <= INVEN_FEET; i++)
    {
        auto_item *item = &auto_items[i];

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

        /* Skip non-identified items */
        if (!item->able) continue;

        /* Obtain the bonus */
        a = item->to_a;

        /* Skip "boring" items */
        if (borg_prayer_legal(7, 4) && !auto_depth)
        {
            if (a >= 15) continue;
        }
        else
        {
            if (a >= 8) continue;
        }

        /* Find the least enchanted item */
        if ((b_i >= 0) && (b_a < a)) continue;

        /* Save the info */
        b_i = i; b_a = a;
    }

    /* Nothing */
    if (b_i < 0) return (FALSE);

    /* Enchant it */
    if (borg_prayer(7, 4) ||
        borg_read_scroll(SV_SCROLL_ENCHANT_ARMOR))
    {
        /* Choose from equipment */
        borg_keypress('/');

        /* Choose that item */
        borg_keypress(I2A(b_i - INVEN_WIELD));

        /* Success */
        return (TRUE);
    }

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


/*
 * Enchant weapons to hit
 */
static bool borg_enchant_to_h(void)
{
    int i, b_i = -1;
    int a, b_a = 99;


    /* Nothing to enchant */
    if (!my_need_enchant_to_h) return (FALSE);

    /* Need "enchantment" ability */
    if (!amt_enchant_to_h) return (FALSE);


    /* Look for a weapon that needs enchanting */
    for (i = INVEN_WIELD; i <= INVEN_BOW; i++)
    {
        auto_item *item = &auto_items[i];

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

        /* Skip non-identified items */
        if (!item->able) continue;

        /* Obtain the bonus */
        a = item->to_h;

        /* Skip "boring" items */
        if (borg_prayer_legal(7, 3) && !auto_depth)
        {
            if (a >= 12) continue;
        }
        else
        {
            if (a >= 8) continue;
        }

        /* Find the least enchanted item */
        if ((b_i >= 0) && (b_a < a)) continue;

        /* Save the info */
        b_i = i; b_a = a;
    }

    /* Nothing, check ammo */
    if (b_i < 0)
    {
        /* look through inventory for ammo */
        for (i = 0; i < INVEN_PACK; i++)
        {
            auto_item *item = &auto_items[i];

            /* Only enchant if qty >= 10 */
            if (item->iqty < 10) continue;

            /* Skip non-identified items  */
            if (!item->able) continue;

            /* Make sure it is the right type if missile */
            if (item->tval != my_ammo_tval) continue;

            /* Obtain the bonus  */
            a = item->to_h;

            /* Skip items that are already enchanted */
            if (borg_prayer_legal(7, 3) && !auto_depth)
            {
                if (a >= 10) continue;
            }
            else
            {
                if (a >= 8) continue;
            }

            /* Find the least enchanted item */
            if ((b_i >= 0) && (b_a < a)) continue;

            /* Save the info  */
            b_i = i; b_a = a;

        }
    }

    /* Nothing */
    if (b_i < 0) return (FALSE);

    /* Enchant it */
    if (borg_prayer(7, 3) ||
        borg_read_scroll(SV_SCROLL_ENCHANT_WEAPON_TO_HIT))
    {
        /* Choose from equipment */
        if (b_i >= INVEN_WIELD)
        {
            borg_keypress('/');

            /* Choose that item */
            borg_keypress(I2A(b_i - INVEN_WIELD));
        }
        else
        {
            borg_keypress(I2A(b_i));
        }


        /* Success */
        return (TRUE);
    }

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


/*
 * Enchant weapons
 */
static bool borg_enchant_to_d(void)
{
    int i, b_i = -1;
    int a, b_a = 99;


    /* Nothing to enchant */
    if (!my_need_enchant_to_d) return (FALSE);

    /* Need "enchantment" ability */
    if (!amt_enchant_to_d) return (FALSE);


    /* Look for a weapon that needs enchanting */
    for (i = INVEN_WIELD; i <= INVEN_BOW; i++)
    {
        auto_item *item = &auto_items[i];

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

        /* Skip non-identified items */
        if (!item->able) continue;

        /* Obtain the bonus */
        a = item->to_d;

        /* Skip "boring" items */
        if (borg_prayer_legal(7, 3) && !auto_depth)
        {
            if (a >= 12) continue;
        }
        else
        {
            if (a >= 8) continue;
        }

        /* Find the least enchanted item */
        if ((b_i >= 0) && (b_a < a)) continue;

        /* Save the info */
        b_i = i; b_a = a;
    }

    /* Nothing, check ammo */
    if (b_i < 0)
    {
        /* look through inventory for ammo */
        for (i = 0; i < INVEN_PACK; i++)
        {
            auto_item *item = &auto_items[i];

            /* Only enchant if qty >= 10 */
            if (item->iqty < 10) continue;

            /* Skip non-identified items */
            if (!item->able) continue;

            /* Make sure it is the right type if missile */
            if (item->tval != my_ammo_tval) continue;

            /* Obtain the bonus  */
            a = item->to_d;

            /* Skip items that are already enchanted */
            if (borg_prayer_legal(7, 3) && !auto_depth)
            {
                if (a >= 10) continue;
            }
            else
            {
                if (a >= 8) continue;
            }

            /* Find the least enchanted item */
            if ((b_i >= 0) && (b_a < a)) continue;

            /* Save the info */
            b_i = i; b_a = a;

        }
    }

    /* Nothing */
    if (b_i < 0) return (FALSE);

    /* Enchant it */
    if (borg_prayer(7, 3) ||
        borg_read_scroll(SV_SCROLL_ENCHANT_WEAPON_TO_DAM))
    {
        /* Choose from equipment */
        if (b_i >= INVEN_WIELD)
        {
            borg_keypress('/');

            /* Choose that item */
            borg_keypress(I2A(b_i - INVEN_WIELD));
        }
        else
        {
            /* Choose that item */
            borg_keypress(I2A(b_i));
        }

        /* Success */
        return (TRUE);
    }

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


/*
 * Enchant things
 */
bool borg_enchanting(void)
{
    /* Forbid blind/confused */
    if (do_blind || do_confused) return (FALSE);

    /* XXX XXX XXX Dark */

    /* Enchant things */
    if (borg_enchant_to_d()) return (TRUE);
    if (borg_enchant_to_a()) return (TRUE);
    if (borg_enchant_to_h()) return (TRUE);

    /* Nope */
    return (FALSE);
}


/*
 * Recharge things
 *
 * XXX XXX XXX Prioritize available items
 */
bool borg_recharging(void)
{
    int i = -1;
    bool charge = FALSE;


    /* Forbid blind/confused */
    if (do_blind || do_confused) return (FALSE);

    /* XXX XXX XXX Dark */

    /* Look for an item to recharge */
    for (i = 0; i < INVEN_PACK; i++)
    {
        auto_item *item = &auto_items[i];

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

        /* Skip non-identified items */
        if (!item->able) continue;

        /* assume we can't charge it. */
        charge = FALSE;

        /* Wands with no charges can be charged */
        if ((item->tval == TV_WAND) && (item->pval < 1))
            charge = TRUE;

        /* recharge staves sometimes */
        if (item->tval == TV_STAFF) 
        {
            /* allow staves to be recharged at 2 charges if */
            /* the borg has the big recharge spell */
            if ((item->pval < 3) && borg_spell_okay(6, 2))
                charge = TRUE;

            /* recharge any staff at 0 charges */
            if (item->pval < 1)
                charge = TRUE;

            /* Staves of teleport get recharged at 2 charges in town */
            if ((item->sval == SV_STAFF_TELEPORTATION) && 
                (item->pval < 3) &&
                !auto_depth)
                charge = TRUE;
        }

        /* recharge rods that are 'charging' if we have the big recharge */
        /* spell */
        if ((item->tval == TV_ROD) && (!item->pval) && 
            borg_spell_okay(6, 2))
        {
            charge = TRUE;
        }

        /* get the next item if we are not to charge this one */
        if (!charge) continue;

        /* Attempt to recharge */
        if (borg_spell(6, 2) ||
            borg_spell(3, 1) ||
            borg_spell(2, 1) ||
            borg_prayer(7, 1) ||
            borg_read_scroll(SV_SCROLL_RECHARGING))
        {
            /* Message */
            borg_note(format("Recharging %s", item->desc));

            /* Recharge the item */
            borg_keypress(I2A(i));

            /* Success */
            return (TRUE);
        }
        else
            /* if we fail once, no need to try again. */
            break;
    }

    /* Nope */
    return (FALSE);
}


/*
 * Attempt to consume an item
 */
static bool borg_consume(int i)
{
    auto_item *item = &auto_items[i];


    /* Special destruction */
    switch (item->tval)
    {
        case TV_POTION:

        /* Check the potion */
        switch (item->sval)
        {
            case SV_POTION_WATER:
            case SV_POTION_APPLE_JUICE:
            case SV_POTION_SLIME_MOLD:
            case SV_POTION_CURE_LIGHT:
            case SV_POTION_CURE_SERIOUS:
            case SV_POTION_CURE_CRITICAL:
            case SV_POTION_HEALING:
            case SV_POTION_STAR_HEALING:
            case SV_POTION_LIFE:
            case SV_POTION_RES_STR:
            case SV_POTION_RES_INT:
            case SV_POTION_RES_WIS:
            case SV_POTION_RES_DEX:
            case SV_POTION_RES_CON:
            case SV_POTION_RES_CHR:
            case SV_POTION_RESTORE_EXP:
            case SV_POTION_RESTORE_MANA:
            case SV_POTION_HEROISM:
            case SV_POTION_BESERK_STRENGTH:
            case SV_POTION_RESIST_HEAT:
            case SV_POTION_RESIST_COLD:
            case SV_POTION_INFRAVISION:
            case SV_POTION_DETECT_INVIS:
            case SV_POTION_SLOW_POISON:
            case SV_POTION_CURE_POISON:
            case SV_POTION_SPEED:

            /* Try quaffing the potion */
            if (borg_quaff_potion(item->sval)) return (TRUE);
        }

        break;

        case TV_SCROLL:

        /* Check the scroll */
        switch (item->sval)
        {
            case SV_SCROLL_REMOVE_CURSE:
            case SV_SCROLL_LIGHT:
            case SV_SCROLL_MONSTER_CONFUSION:
            case SV_SCROLL_RUNE_OF_PROTECTION:
            case SV_SCROLL_STAR_REMOVE_CURSE:
            case SV_SCROLL_DETECT_GOLD:
            case SV_SCROLL_DETECT_ITEM:
            case SV_SCROLL_TRAP_DOOR_DESTRUCTION:
            case SV_SCROLL_SATISFY_HUNGER:
            case SV_SCROLL_DISPEL_UNDEAD:
            case SV_SCROLL_BLESSING:
            case SV_SCROLL_HOLY_CHANT:
            case SV_SCROLL_HOLY_PRAYER:

            /* Try reading the scroll */
            if (borg_read_scroll(item->sval)) return (TRUE);
        }

        break;

        case TV_FOOD:

        /* Check the scroll */
        switch (item->sval)
        {
            case SV_FOOD_CURE_POISON:
            case SV_FOOD_CURE_BLINDNESS:
            case SV_FOOD_CURE_PARANOIA:
            case SV_FOOD_CURE_CONFUSION:
            case SV_FOOD_CURE_SERIOUS:
            case SV_FOOD_RESTORE_STR:
            case SV_FOOD_RESTORE_CON:
            case SV_FOOD_RESTORING:
            case SV_FOOD_BISCUIT:
            case SV_FOOD_JERKY:
            case SV_FOOD_RATION:
            case SV_FOOD_SLIME_MOLD:
            case SV_FOOD_WAYBREAD:
            case SV_FOOD_PINT_OF_ALE:
            case SV_FOOD_PINT_OF_WINE:

            /* Try eating the food (unless Bloated) */
            if (!do_full && borg_eat_food(item->sval)) return (TRUE);
        }

        break;
    }


    /* Nope */
    return (FALSE);
}




/*
 * Destroy "junk" items
 */
bool borg_crush_junk(void)
{
    int i;
    bool fix = FALSE;
    s32b p;
    s32b value;

    /* Hack -- no need */
    if (!auto_do_crush_junk) return (FALSE);

    /* Destroy actual "junk" items */
    for (i = 0; i < INVEN_PACK; i++)
    {
        auto_item *item = &auto_items[i];

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

        /* save the items value */
        value = item->value;

        /* Skip non "worthless" items */
        if (item->tval > TV_CHEST)
        {
            /* unknow and not worthless */
            if (!item->able && !streq(item->note, "{average}") &&
                 value > 0) 
                continue;

            /* skip items that are 'valuable'.  This is level dependent */
            /* try to make the borg junk +1,+1 dagger at level 40 */

            /* if the item gives a bonus to a stat, boost its value */
            if (((item->flags1 & TR1_STR) ||
                (item->flags1 & TR1_INT) ||
                (item->flags1 & TR1_WIS) ||
                (item->flags1 & TR1_DEX) ||
                (item->flags1 & TR1_CON)) && value > 0)
            {
                value += 20000L;
            }

            /* up to level 5, keep anything of any value */
            if (auto_depth < 5 && value > 0) 
                continue;
            /* up to level 15, keep anything of value 100 or better */
            if (auto_depth < 15 && value > 100) 
                continue;
            /* up to level 30, keep anything of value 500 or better */
            if (auto_depth < 30 && value > 500) 
                continue;
            /* up to level 40, keep anything of value 1000 or better */
            if (auto_depth < 40 && value > 1000) 
                continue;
            /* below level 40, keep anything of value 1200 or better */
            if (auto_depth >= 40 && value > 1200) 
                continue;

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

            /* Destroy the item */
            WIPE(&auto_items[i], auto_item);

            /* 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);

            /* skip things we are using */
            if (p < my_power) continue;
        }

        /* re-examine the inventory */
        if (fix) borg_notice();

        /* Hack -- skip good un-id'd "artifacts" */
        if (streq(item->note, "{special}")) continue;

        /* Message */
        borg_note(format("# Junking junk (junk)"));

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

        /* Destroy all items */
        borg_keypress('0');

        /* Destroy that item */
        if (!item->name1 && !streq(item->note, "{terrible}"))
                borg_keypress('k');
        else
        {
            int a;

            /* worthless artifacts are dropped. */
            borg_keypress('d');
    
            /* mark the spot that the object was dropped so that  */
            /* it will not be picked up again. */
            for (a = 0; a < 10; a++)
            {
                if (bad_obj_x[a] != -1) continue;
                if (bad_obj_y[a] != -1) continue;

                bad_obj_x[a] = c_x;
                bad_obj_y[a] = c_y;
            }
        }
        borg_keypress(I2A(i));

        /* Verify destruction */
        /* borg_keypress('y'); */

        /* Success */
        return (TRUE);
    }

    /* re-examine the inventory */
    if (fix) borg_notice();

    /* Hack -- no need */
    auto_do_crush_junk = FALSE;


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



/*
 * Destroy something to make a free inventory slot.
 *
 * This function evaluates the possible worlds that result from
 * the destruction of each inventory slot, and attempts to destroy
 * that slot which causes the best possible resulting world.
 *
 * We attempt to avoid destroying unknown items by "rewarding" the
 * presence of unknown items by a massively heuristic value.
 *
 * If the Borg cannot find something to destroy, which should only
 * happen if he fills up with artifacts, then he will probably act
 * rather twitchy for a while.
 *
 * This function does not have to be very efficient.
 */
bool borg_crush_hole(void)
{
    int i, b_i = -1;
    s32b p, b_p = 0L;

    s32b value;

    bool fix = FALSE;


    /* Hack -- no need */
    if (!auto_do_crush_hole) return (FALSE);


    /* Do not destroy items unless we need the space */
    if (!auto_items[INVEN_PACK-1].iqty) return (FALSE);

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

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

        /* Hack -- skip "artifacts" */
        if (item->name1) continue;

        /* Hack -- skip "artifacts" */
        if (streq(item->note, "{special}")) continue;
        if (streq(item->note, "{terrible}")) continue;

        /* save the items value */
        value = item->value;

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

        /* Destroy the item */
        WIPE(&auto_items[i], auto_item);

        /* Fix later */
        fix = TRUE;

        /* Examine the inventory */
        borg_notice();

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

        /* power is much more important than gold. */
        p *= 100;

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

        /* Penalize loss of "gold" */

        /* if the item gives a bonus to a stat, boost its value */
        if ((item->flags1 & TR1_STR) ||
            (item->flags1 & TR1_INT) ||
            (item->flags1 & TR1_WIS) ||
            (item->flags1 & TR1_DEX) ||
            (item->flags1 & TR1_CON))
        {
            value += 20000L;
        }

        /* Hack  show prefrence for destroying things we will not use */
        /* if we are high enough level not to worry about gold. */
        if (auto_level > 35)
        {
            switch (item->tval)
            {
                /* rings are under valued. */
                case TV_RING:  
                    p -= (item->iqty * value * 10);
                    break;

                case TV_AMULET:
                case TV_BOW:
                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:
                    p -= (item->iqty * value * 5);
                    break;

                case TV_ROD:
                    p -= (item->iqty * value);
                    break;

                case TV_STAFF:
                case TV_WAND:
                    p -= (item->iqty * (value/2));
                    break;

                /* scrolls and potions crush easy */
                case TV_SCROLL:
                    p -= (item->iqty * (value/10));
                    break;

                case TV_POTION:
                    /* BIG HACK! don't crush heal/mana potions.  It could be */
                    /* that we are in town and are collecting them. */
                    if ((item->sval != SV_POTION_HEALING) ||
                        (item->sval != SV_POTION_RESTORE_MANA))
                        p -= (item->iqty * (30000L));  /* value at 30k */
                    else
                        p -= (item->iqty * (value/10));
                    break;

                default:
                    p -= (item->iqty * (value/3));
                    break;
            }
        }
        else
        {
            p -= (item->iqty * value);
        }

        /* Hack -- try not to destroy "unaware" items */
        if (!item->kind && (value > 0))
        {
            /* Hack -- Reward "unaware" items */
            switch (item->tval)
            {
                case TV_RING:
                case TV_AMULET:
                p -= (auto_max_depth * 5000L);
                break;

                case TV_ROD:
                p -= (auto_max_depth * 3000L);
                break;

                case TV_STAFF:
                case TV_WAND:
                p -= (auto_max_depth * 2000L);
                break;

                case TV_SCROLL:
                case TV_POTION:
                p -= (auto_max_depth * 500L);
                break;

                case TV_FOOD:
                p -= (auto_max_depth * 10L);
                break;
            }
        }

        /* Hack -- try not to destroy "unknown" items (unless "icky") */
        if (!item->able && !streq(item->note, "{average}") &&
            (value > 0) && !borg_item_icky(item))
        {
            /* Reward "unknown" items */
            switch (item->tval)
            {
                case TV_SHOT:
                case TV_ARROW:
                case TV_BOLT:
                p -= 100L;
                break;

                case TV_BOW:
                p -= 20000L;
                break;

                case TV_DIGGING:
                p -= 10L;
                break;

                case TV_HAFTED:
                case TV_POLEARM:
                case TV_SWORD:
                p -= 10000L;
                break;

                case TV_BOOTS:
                case TV_GLOVES:
                case TV_HELM:
                case TV_CROWN:
                case TV_SHIELD:
                case TV_CLOAK:
                p -= 15000L;
                break;

                case TV_SOFT_ARMOR:
                case TV_HARD_ARMOR:
                case TV_DRAG_ARMOR:
                p -= 15000L;
                break;

                case TV_AMULET:
                case TV_RING:
                p -= 5000L;
                break;

                case TV_STAFF:
                case TV_WAND:
                p -= 1000L;
                break;
            }
        }

        /* Ignore "bad" swaps */
        if ((b_i >= 0) && (p < b_p)) continue;

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

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

    /* Attempt to destroy it */
    if (b_i >= 0)
    {
        auto_item *item = &auto_items[b_i];

        /* Debug */
        borg_note(format("# Junking %ld gold (full)", my_power*100 - b_p));

        /* Try to consume the junk */
        if (borg_consume(b_i)) return (TRUE);

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

        /* Destroy all items */
        borg_keypress('0');

        /* Destroy that item */
        borg_keypress('k');
        borg_keypress(I2A(b_i));

        /* Verify destruction */
        /* borg_keypress('y'); */

        /* Success */
        return (TRUE);
    }


    /* Hack -- no need */
    auto_do_crush_hole = FALSE;


    /* Paranoia */
    return (FALSE);
}



/*
 * Destroy "junk" when slow (in the dungeon).
 *
 * We penalize the loss of both power and monetary value, and reward
 * the loss of weight that may be slowing us down.  The weight loss
 * is worth one gold per tenth of a pound.  This causes things like
 * lanterns and chests and spikes to be considered "annoying".
 */
bool borg_crush_slow(void)
{
    int i, b_i = -1;
    s32b p, b_p = 0L;

    s32b temp;

    s32b greed;

    bool fix = FALSE;


    /* Hack -- no need */
    if (!auto_do_crush_slow) return (FALSE);


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


    /* Do not crush items unless we are slow */
    if (auto_speed >= 110) return (FALSE);


    /* Calculate "greed" factor */
    greed = (auto_gold / 100L) + 100L;

    /* Minimal greed */
    if (greed < 500L && auto_level > 35) greed = 500L;
    if (greed > 25000L) greed = 25000L;


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

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

        /* Skip "good" unknown items (unless "icky") */
        if (!item->able && !streq(item->note, "{average}") &&
            (item->value > 0) && !borg_item_icky(item)) continue;

        /* Hack -- Skip artifacts */
        if (item->name1) continue;

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

        /* Destroy one of the items */
        auto_items[i].iqty--;

        /* Fix later */
        fix = TRUE;

        /* Examine the inventory */
        borg_notice();

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

        /* power is much more important than gold. */
        p *= 100;

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

        /* Obtain the base price */
        temp = ((item->value < 30000L) ? item->value : 30000L);

        /* Hack -- ignore very cheap items */
        if (temp < greed) temp = 0L;

        /* Penalize */
        p -= temp;

        /* Obtain the base weight */
        temp = item->weight;

        /* Reward */
        p += (temp*10);

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

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

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

    /* Destroy "useless" things */
    if ((b_i >= 0) && (b_p >= (my_power*100)))
    {
        auto_item *item = &auto_items[b_i];

        /* Message */
        borg_note(format("# Junking %ld gold (slow)", (my_power*100) - b_p));

        /* Attempt to consume it */
        if (borg_consume(b_i)) return (TRUE);

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

        /* Destroy one item */
        borg_keypress('0');
        borg_keypress('1');

        /* Destroy that item */
        borg_keypress('k');
        borg_keypress(I2A(b_i));

        /* Verify destruction */
        /* borg_keypress('y'); */
    }


    /* Hack -- no need */
    auto_do_crush_slow = FALSE;


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


/*
 * Identify items if possible
 *
 * Note that "borg_parse()" will "cancel" the identification if it
 * detects a "You failed..." message.  This is VERY important!!!
 * Otherwise the "identify" might induce bizarre actions by sending
 * the "index" of an item as a command.
 *
 * Hack -- recover from mind blanking by re-identifying the equipment.
 *
 * We instantly identify items known to be "good" (or "terrible").
 *
 * We identify most un-aware items as soon as possible.
 *
 * We identify most un-known items as soon as possible.
 *
 * We play games with items that get "feelings" to try and wait for
 * "sensing" to take place if possible.
 *
 * XXX XXX XXX Make sure not to sell "non-aware" items, unless
 * we are really sure we want to lose them.  For example, we should
 * wait for feelings on (non-icky) wearable items or else make sure
 * that we identify them before we try and sell them.
 *
 * Mega-Hack -- the whole "sometimes identify things" code is a total
 * hack.  Slightly less bizarre would be some form of "occasionally,
 * pick a random item and identify it if necessary", which might lower
 * the preference for identifying items that appear early in the pack.
 * Also, preventing inventory motion would allow proper time-stamping.
 *
 * This function is also used to *ID* objects.  Right now only objects 
 * with random high resist or random powers are *ID*'d
 */
bool borg_test_stuff(bool star_id)
{
    int i, b_i = -1;
    s32b v, b_v = -1;


    /* Look for an item to identify (equipment) */
    for (i = INVEN_WIELD; i <= INVEN_FEET; i++)
    {
        auto_item *item = &auto_items[i];

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

        /* Skip known items */
        if (!star_id)
        {
            if (item->able) continue;
        }
        else
        {
            if (item->fully_identified) continue;
            switch (item->name2)
            {
                /* Weapon (Blessed) */
                case EGO_BLESS_BLADE:
                /* Robe of Permanance */
                case EGO_PERMANENCE:
                /* Armor of Elvenkind */
                case EGO_ELVENKIND:
                /* Crown of the Magi */
                case EGO_MAGI:
                /* Cloak of Aman */
                case EGO_AMAN:
                    break;
                /* Weapon (Holy Avenger) */
                case EGO_HA:
                /* Weapon (Defender) */
                case EGO_DF:
                /* anything else */
                default:
                    continue;
            }
        }

        /* Get the value */
        v = item->value + 100000L;

        /* Track the best */
        if (v < b_v) continue;

        /* Track it */
        b_i = i; b_v = v;
    }

    /* Look for an item to identify (inventory) */
    for (i = 0; i < INVEN_PACK; i++)
    {
        auto_item *item = &auto_items[i];

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

        /* Skip known items */
        if (!star_id)
        {
            if (item->able) continue;
        }
        else
        {
            if (item->fully_identified) continue;
            switch (item->name2)
            {
                /* Weapon (Blessed) */
                case EGO_BLESS_BLADE:
                /* Robe of Permanance */
                case EGO_PERMANENCE:
                /* Armor of Elvenkind */
                case EGO_ELVENKIND:
                /* Crown of the Magi */
                case EGO_MAGI:
                /* Cloak of Aman */
                case EGO_AMAN:
                    break;
                /* Weapon (Holy Avenger) */
                case EGO_HA:
                /* Weapon (Defender) */
                case EGO_DF:
                /* anything else */
                default:
                    continue;
            }
        }

        /* Assume nothing */
        v = 0;

        /* Identify "good" (and "terrible") items */
        if (streq(item->note, "{good}")) v = item->value + 10000L;
        else if (streq(item->note, "{excellent}")) v = item->value + 20000L;
        else if (streq(item->note, "{special}")) v = item->value + 50000L;
        else if (streq(item->note, "{terrible}")) v = item->value + 50000L;

        /* Nothing */
        if (!v) continue;

        /* Track the best */
        if (v < b_v) continue;

        /* Track it */
        b_i = i; b_v = v;
    }

    /* Look for an item to identify (inventory) */
    for (i = 0; i < INVEN_PACK; i++)
    {
        auto_item *item = &auto_items[i];

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

        /* Skip known items */
        if (!star_id)
        {
            if (item->able) continue;
        }
        else
        {
            if (item->fully_identified) continue;
            switch (item->name2)
            {
                /* Weapon (Blessed) */
                case EGO_BLESS_BLADE:
                /* Robe of Permanance */
                case EGO_PERMANENCE:
                /* Armor of Elvenkind */
                case EGO_ELVENKIND:
                /* Crown of the Magi */
                case EGO_MAGI:
                /* Cloak of Aman */
                case EGO_AMAN:
                    break;
                /* Weapon (Holy Avenger) */
                case EGO_HA:
                /* Weapon (Defender) */
                case EGO_DF:
                /* anything else */
                default:
                    continue;
            }
        }

        /* Hack -- never identify "average" things */
        if (streq(item->note, "{average}")) continue;

        /* Hack -- assume no value */
        v = 0;

        /* Hack -- reward "unaware" items */
        if (!item->kind && !star_id)
        {
            /* Analyze the type */
            switch (item->tval)
            {
                case TV_RING:
                case TV_AMULET:

                /* Hack -- reward depth */
                v += (auto_max_depth * 5000L);

                break;

                case TV_ROD:

                /* Hack -- reward depth */
                v += (auto_max_depth * 3000L);

                break;

                case TV_WAND:
                case TV_STAFF:

                /* Hack -- reward depth */
                v += (auto_max_depth * 2000L);

                break;

                case TV_POTION:
                case TV_SCROLL:

                /* Hack -- boring levels */
                if (auto_max_depth < 5) break;

                /* Hack -- reward depth */
                v += (auto_max_depth * 500L);

                break;

                case TV_FOOD:

                /* Hack -- reward depth */
                v += (auto_max_depth * 10L);

                break;
            }
        }

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

            /* Hack -- Always identify chests */
            v = item->value;
            break;

            case TV_WAND:
            case TV_STAFF:

            /* Hack -- Always identify (get charges) */
            v = item->value;
            break;

            case TV_RING:
            case TV_AMULET:

            /* Hack -- Always identify (get information) */
            v = item->value;
            break;

            case TV_LITE:

            /* Hack -- Always identify (get artifact info) */
            v = item->value;
            break;

            case TV_SHOT:
            case TV_ARROW:
            case TV_BOLT:
            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:

            /* Mega-Hack -- use identify spell/prayer */
            if (borg_spell_legal(2, 4) || borg_prayer_legal(5, 2))
            {
                v = item->value;
            }

            /* Mega-Hack -- mages get bored */
            if ((auto_class == 1) && (rand_int(1000) < auto_level))
            {

                /* Mega-Hack -- ignore "icky" items */
                if (!borg_item_icky(item)) v = item->value;
            }

            /* Mega-Hack -- rangers get bored */
            if ((auto_class == 4) && (rand_int(3000) < auto_level))
            {

                /* Mega-Hack -- ignore "icky" items */
                if (!borg_item_icky(item)) v = item->value;
            }

            /* Mega-Hack -- priests get bored */
            if ((auto_class == 2) && (rand_int(5000) < auto_level))
            {

                /* Mega-Hack -- ignore "icky" items */
                if (!borg_item_icky(item)) v = item->value;
            }

            break;
        }

        /* Ignore */
        if (!v) continue;

        /* Track the best */
        if (v < b_v) continue;

        /* Track it */
        b_i = i; b_v = v;
    }


    /* Found something */
    if (b_i >= 0)
    {
        auto_item *item = &auto_items[b_i];

        if (star_id)
        {
            if (borg_read_scroll(SV_SCROLL_STAR_IDENTIFY))
            {
                /* Log -- may be cancelled */
                borg_note(format("# *IDENTIFY*ing %s.", item->desc));

                /* we need to look at the screen next time through */
                auto_do_star_id = TRUE;
                item->needs_I = TRUE;
                item->fully_identified = TRUE;

                /* Equipment */
                if (b_i >= INVEN_WIELD)
                {
                    /* Select the equipment */
                    borg_keypress('/');

                    /* Select the item */
                    borg_keypress(I2A(b_i - INVEN_WIELD));

                    /* HACK need to recheck stats if we id something on us. */
                    for (i = 0;i < 6; i++)
                    {
                        my_need_stat_check[i] = TRUE;
                        my_stat_max[i] = 0;
                    }
                }

                /* Inventory */
                else
                {
                    /* Select the item */
                    borg_keypress(I2A(b_i));
                }

                /* press enter a few time (get rid of display) */
                borg_keypress('\r');
                borg_keypress('\r');
                borg_keypress('\r');
                borg_keypress('\r');

                /* Success */
                return (TRUE);
            }

        } 
        else
        {

            /* Use a Spell/Prayer/Rod/Staff/Scroll of Identify */
            if (borg_spell(2, 4) ||
                borg_prayer(5, 2) ||
                borg_zap_rod(SV_ROD_IDENTIFY) ||
                borg_use_staff(SV_STAFF_IDENTIFY) ||
                borg_read_scroll(SV_SCROLL_IDENTIFY))
            {
                /* Log -- may be cancelled */
                borg_note(format("# Identifying %s.", item->desc));

                /* Equipment */
                if (b_i >= INVEN_WIELD)
                {
                    /* Select the equipment */
                    borg_keypress('/');

                    /* Select the item */
                    borg_keypress(I2A(b_i - INVEN_WIELD));

                    /* HACK need to recheck stats if we id something on us. */
                    for (i = 0; i < 6; i++)
                    {
                        my_need_stat_check[i] = TRUE;
                        my_stat_max[i] = 0;
                    }
                }

                /* Inventory */
                else
                {
                    /* Select the item */
                    borg_keypress(I2A(b_i));
                }

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

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




/*
 * Attempt to take off useless equipment
 */
bool borg_takeoff_stuff(void)
{
    int hole = INVEN_PACK - 1;

    int i, b_i = -1;

    s32b v, b_v = 0L;

    bool fix = FALSE;


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


    /* Scan equipment */
    for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
    {
        auto_item *item = &auto_items[i];

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

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

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

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

        /* Erase the item */
        WIPE(&auto_items[i], auto_item);

        /* Fix later */
        fix = TRUE;

        /* Examine the inventory */
        borg_notice();

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

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

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

        /* Track best */
        if ((b_i >= 0) && (b_v >= v)) continue;

        /* Track best */
        b_i = i; b_v = v;
    }

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

    /* Prepare to "swap" if needed */
    if ((b_i >= 0) && (b_v >= my_power))
    {
        auto_item *item = &auto_items[b_i];

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

        /* Take off item */
        borg_keypress('t');
        borg_keypress(I2A(b_i - INVEN_WIELD));

        /* Success */
        return (TRUE);
    }

    /* Nope */
    return (FALSE);
}



/*
 * This function is responsible for making sure that, if possible,
 * the "best" ring we have is always on the "right" (tight) finger,
 * so that the other functions, such as "borg_best_stuff()", do not
 * have to think about the "tight" ring, but instead, can just assume
 * that the "right" ring is "good for us" and should never be removed.
 *
 * In general, this will mean that our "best" ring of speed will end
 * up on the "right" finger, if we have one, or a ring of free action,
 * or a ring of see invisible, or some other "useful" ring.
 *
 * This routine is only called in shops, to allow us to "safely" play
 * the ring shuffling game, since this routine may take several steps,
 * and we must be able to do them all without being attacked.
 */
bool borg_swap_rings(void)
{
    int hole = INVEN_PACK - 1;
    int icky = INVEN_PACK - 2;

    s32b v1, v2;

    bool fix = FALSE;


    /*** Check conditions ***/

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


    /*** Remove naked "loose" rings ***/

    /* Remove any naked loose ring */
    if (auto_items[INVEN_LEFT].iqty &&
        !auto_items[INVEN_RIGHT].iqty)
    {
        /* Log */
        borg_note("# Taking off naked loose ring.");

        /* Remove it */
        borg_keypress('t');
        borg_keypress(I2A(INVEN_LEFT - INVEN_WIELD));

        /* Success */
        return (TRUE);
    }


    /*** Check conditions ***/

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

    /* Require "tight" ring */
    if (!auto_items[INVEN_RIGHT].iqty) return (FALSE);


    /*** Remove nasty "tight" rings ***/

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

    /* Save the ring */
    COPY(&safe_items[INVEN_LEFT], &auto_items[INVEN_LEFT], auto_item);

    /* Take off the ring */
    COPY(&auto_items[hole], &auto_items[INVEN_LEFT], auto_item);

    /* Erase left ring */
    WIPE(&auto_items[INVEN_LEFT], auto_item);

    /* Fix later */
    fix = TRUE;

    /* Examine the inventory */
    borg_notice();

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

    /* Restore the ring */
    COPY(&auto_items[INVEN_LEFT], &safe_items[INVEN_LEFT], auto_item);

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


    /*** Consider taking off the "right" ring ***/

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

    /* Save the ring */
    COPY(&safe_items[INVEN_RIGHT], &auto_items[INVEN_RIGHT], auto_item);

    /* Take off the ring */
    COPY(&auto_items[hole], &auto_items[INVEN_RIGHT], auto_item);

    /* Erase left ring */
    WIPE(&auto_items[INVEN_RIGHT], auto_item);

    /* Fix later */
    fix = TRUE;

    /* Examine the inventory */
    borg_notice();

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

    /* Restore the ring */
    COPY(&auto_items[INVEN_RIGHT], &safe_items[INVEN_RIGHT], auto_item);

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


    /*** Swap rings if necessary ***/

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

    /* Remove "useless" ring */
    if (v2 > v1)
    {
        /* Log */
        borg_note("# Taking off nasty tight ring.");

        /* Take it off */
        borg_keypress('t');
        borg_keypress(I2A(INVEN_RIGHT - INVEN_WIELD));

        /* Success */
        return (TRUE);
    }

    /* Nope */
    return (FALSE);
}



/*
 * Place our "best" ring on the "tight" finger if needed
 *
 * This function is adopted from "borg_wear_stuff()"
 *
 * Basically, we evaluate the world in which each ring is added
 * to the current set of equipment, and we wear the ring, if any,
 * that gives us the most "power".
 *
 * The "borg_swap_rings()" code above occasionally allows us to remove
 * both rings, at which point this function will place the "best" ring
 * on the "tight" finger, and then the "borg_best_stuff()" function will
 * allow us to put on our second "best" ring on the "loose" finger.
 *
 * This function should only be used when a ring finger is empty.
 */
bool borg_wear_rings(void)
{
    int slot;

    s32b p, b_p = 0L;

    int i, b_i = -1;

    auto_item *item;

    bool fix = FALSE;


    /* Require no rings */
    if (auto_items[INVEN_LEFT].iqty) return (FALSE);
    if (auto_items[INVEN_RIGHT].iqty) return (FALSE);


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


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


        /* Require "aware" */
        if (!item->kind) continue;

        /* Require "known" (or average) */
        if (!item->able && !streq(item->note, "{average}")) continue;

        /* Hack -- ignore "worthless" items */
        if (!item->value) continue;


        /* Where does it go */
        slot = borg_wield_slot(item);

        /* Only process "rings" */
        if (slot != INVEN_LEFT) continue;

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

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

        /* Wear new item */
        COPY(&auto_items[slot], &safe_items[i], auto_item);

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

        /* Reduce the inventory quantity by one */
        auto_items[i].iqty--;

        /* Fix later */
        fix = TRUE;

        /* Examine the inventory */
        borg_notice();

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

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

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

        /* Ignore "bad" swaps */
        if ((b_i >= 0) && (p < b_p)) continue;

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

    /* Restore bonuses */
    if (fix) borg_notice();

    /* No item */
    if ((b_i >= 0) && (b_p > my_power))
    {
        /* Get the item */
        item = &auto_items[b_i];

        /* Log */
        borg_note("# Putting on best tight ring.");

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

        /* Wear it */
        borg_keypress('w');
        borg_keypress(I2A(b_i));

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

    /* Nope */
    return (FALSE);
}



/*
 * Wear useful equipment.
 *
 * Look through the inventory for equipment that is better than
 * the current equipment, and wear it, in an optimal order.
 *
 * Basically, we evaluate the world both with the current set of
 * equipment, and in the alternate world in which various items
 * are used instead of the items they would replace, and we take
 * one step towards the world in which we have the most "power".
 *
 * Although a player can actually wear two rings, we pretend that only
 * the "loose" ring can be removed, which is the semantics induced by
 * the "wear" command.
 *
 * The "borg_swap_rings()" code above occasionally allows us to remove
 * both rings, at which point this function will replace the "best" ring
 * on the "tight" finger, and the second "best" ring on the "loose" finger.
 */
bool borg_wear_stuff(void)
{
    int hole = INVEN_PACK - 1;

    int slot;

    s32b p, b_p = 0L;

    int i, b_i = -1;

    auto_item *item;

    bool fix = FALSE;


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


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


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


        /* Require "aware" */
        if (!item->kind) continue;

        /* Require "known" (or average, good, etc) */
        if (!item->able &&
            !streq(item->note, "{average}") &&
            !streq(item->note, "{good}") &&
            !streq(item->note, "{excellent}") &&
            !streq(item->note, "{special}")) continue;

        /* Hack -- ignore "worthless" items */
        if (!item->value) continue;


        /* Where does it go */
        slot = borg_wield_slot(item);

        /* Cannot wear this item */
        if (slot < 0) continue;

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

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

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

        /* Take off old item */
        COPY(&auto_items[hole], &safe_items[slot], auto_item);

        /* Wear new item */
        COPY(&auto_items[slot], &safe_items[i], auto_item);

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

        /* Reduce the inventory quantity by one */
        auto_items[i].iqty--;

        /* Fix later */
        fix = TRUE;

        /* Examine the inventory */
        borg_notice();

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

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

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

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

        /* Ignore "bad" swaps */
        if ((b_i >= 0) && (p < b_p)) continue;

        /* XXX XXX XXX Consider if slot is empty */

        /* Hack -- Ignore "equal" swaps */
        if ((b_i >= 0) && (p == b_p)) continue;

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

    /* Restore bonuses */
    if (fix) borg_notice();

    /* No item */
    if ((b_i >= 0) && (b_p > my_power))
    {
        /* Get the item */
        item = &auto_items[b_i];

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

        /* Wear it */
        borg_keypress('w');
        borg_keypress(I2A(b_i));

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

    /* Nope */
    return (FALSE);
}



/*
 * Hack -- order of the slots
 *
 * XXX XXX XXX Note that we ignore the "tight" ring, and we
 * assume that we will always be wearing our "best" ring on
 * our "right" (tight) finger, and if we are not, then the
 * "borg_swap_rings()" function will remove both the rings,
 * which will induce the "borg_best_stuff()" function to put
 * the rings back on in the "optimal" order.
 */
static byte borg_best_stuff_order[] =
{
    INVEN_BOW,
    INVEN_WIELD,
    INVEN_BODY,
    INVEN_OUTER,
    INVEN_ARM,
    INVEN_HEAD,
    INVEN_HANDS,
    INVEN_FEET,
    INVEN_LITE,
    INVEN_NECK,
    INVEN_LEFT,
    255
};


/*
 * Helper function (see below)
 */
static void borg_best_stuff_aux(int n, byte *test, byte *best, s32b *vp)
{
    int i;

    int slot;


    /* Extract the slot */
    slot = borg_best_stuff_order[n];

    /* All done */
    if (slot == 255)
    {
        s32b p;

        /* Examine */
        borg_notice();

        /* Evaluate */
        p = borg_power();

        /* Track best */
        if (p > *vp)
        {

#if 0
            /* dump list and power...  for debugging */
            borg_note(format("Trying Combo (best power %ld)", *vp));
            borg_note(format("             (borg_power %ld)", p));
            for (i = 0; i < INVEN_PACK; i++)
                borg_note(format("inv %d %s.",  i, auto_items[i].desc));
            for (i=0; borg_best_stuff_order[i] != 255; i++)
                borg_note(format("stuff %s.", 
                    auto_items[borg_best_stuff_order[i]].desc));
#endif
            /* Save the results */
            for (i = 0; i < n; i++) best[i] = test[i];

            /* Use it */
            *vp = p;
        }

        /* Success */
        return;
    }


    /* Note the attempt */
    test[n] = slot;

    /* Evaluate the default item */
    borg_best_stuff_aux(n + 1, test, best, vp);


    /* Try other possible objects */
    for (i = 0; i < ((shop_num == 7) ? (INVEN_PACK + STORE_INVEN_MAX) : INVEN_PACK); i++)
    {
        auto_item *item;
        if (i < INVEN_PACK)
            item = &auto_items[i];
        else 
            item = &auto_shops[7].ware[i - INVEN_PACK];

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

        /* Require "aware" */
        if (!item->kind) continue;

        /* Require "known" (or average, good, etc) */
        if (!item->able &&
            !streq(item->note, "{average}") &&
            !streq(item->note, "{good}") &&
            !streq(item->note, "{excellent}") &&
            !streq(item->note, "{special}")) continue;

        /* Hack -- ignore "worthless" items */
        if (!item->value) continue;


        /* Make sure it goes in this slot */
        if (slot != borg_wield_slot(item)) continue;

        /* Wear the new item */
        COPY(&auto_items[slot], item, auto_item);

        /* Note the attempt */
        if (i < INVEN_PACK)
            test[n] = i;
        else
            /* if in home, note by adding 100 to item number. */
            test[n] = (i - INVEN_PACK) + 100;
            

        /* Evaluate the possible item */
        borg_best_stuff_aux(n + 1, test, best, vp);

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


/*
 * Attempt to instantiate the *best* possible equipment.
 */
bool borg_best_stuff(void)
{
    int hole = INVEN_PACK - 1;

    int k;

    int n = 0;

    s32b value;

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

    byte test[12];
    byte best[12];

    bool fix = FALSE;

    /* Hack -- Initialize */
    for (k = 0; k < 12; k++)
    {
        /* Initialize */
        best[k] = test[k] = 255;
    }

    /* Hack -- Copy all the slots */
    for (i = 0; i < INVEN_TOTAL; i++)
    {
        /* Save the item */
        COPY(&safe_items[i], &auto_items[i], auto_item);
    }

    if (shop_num == 7)
    {
        /* Hack -- Copy all the store slots */
        for (i = 0; i < STORE_INVEN_MAX; i++)
        {
            /* Save the item */
            COPY(&safe_home[i], &auto_shops[7].ware[i], auto_item);
        }
    }

    /* Evaluate the inventory */
    value = my_power;

    /* Determine the best possible equipment */
    (void)borg_best_stuff_aux(0, test, best, &value);

    /* Restore bonuses */
    borg_notice();

    /* Make first change. */
    for (k = 0; k < 12; k++)
    {
        /* Get choice */
        i = best[k];

        /* Ignore non-changes */
        if (i == borg_best_stuff_order[k] || 255 == i) continue;

        if (i < 100)
        {
            /* weild the item */
            auto_item *item = &auto_items[i];
            borg_note(format("# Best Combo %s.", item->desc));

            borg_keypress('w');
            borg_keypress(I2A(i));
            return (TRUE);
        } 
        else
        {
            auto_item *item;

            /* can't get an item if full. */
            if (auto_items[hole].iqty) return (FALSE);

            i-=100;

            item = &auto_shops[7].ware[i];

            /* Get the item */
            borg_note(format("# Getting (Best Fit) %s.", item->desc));

            /* Take the stuff from home and put in inv. and try again. */
            /* make sure on right page */

            /* Minor Hack -- Go to the correct page */
            if ((i / 12) != auto_shops[7].page) 
            {
                borg_keypress(' ');
            }

            borg_keypress('p');
            borg_keypress(I2A(i % 12));

            /* press enter a few time (mulitple objects) */
            borg_keypress('\r');
            borg_keypress('\r');
            borg_keypress('\r');
            borg_keypress('\r');

            return (TRUE);
        }
    }

    /* Nope */
    return (FALSE);
}






/*
 * Study and/or Test spells/prayers
 */
bool borg_play_magic(bool bored)
{
    int book, what;

    int i, b_i = -1;
    int j, b_j = -1;
    int r, b_r = -1;


    /* Hack -- must use magic or prayers */
    if (!mb_ptr->spell_book) return (FALSE);


    /* Hack -- blind/confused */
    if (do_blind || do_confused) return (FALSE);

    /* XXX XXX XXX Dark */


    /* Check each book (backwards) */
    for (book = 9 - 1; book >= 0; book--)
    {
        /* Look for the book */
        i = auto_book[book];

        /* No such book */
        if (i < 0) continue;

        /* Check each spells */
        for (what = 9 - 1; what >= 0; what--)
        {
            auto_magic *as = &auto_magics[book][what];

            /* Require "learnable" status */
            if (as->status != BORG_MAGIC_OKAY) continue;

            /* Obtain "index" */
            j = what;

            /* Obtain "rating" */
            r = as->rating;

            /* Skip "boring" spells/prayers */
            if (!bored && (r <= 50)) continue;

            /* Skip "icky" spells/prayers */
            if (r <= 0) continue;

            /* Skip "worse" spells/prayers */
            if (r <= b_r) continue;

            /* Track it */
            b_i = i;
            b_j = j;
            b_r = r;
        }
    }


    /* Study */
    if (do_study && (b_r > 0))
    {
        auto_magic *as = &auto_magics[b_i][b_j];

        /* Debugging Info */
        borg_note(format("# Studying spell/prayer %s.", as->name));

        /* Learn the spell */
        borg_keypress('G');

        /* Specify the book */
        borg_keypress(I2A(b_i));

        /* Specify the spell (but not the prayer) */
        if (mb_ptr->spell_book == TV_MAGIC_BOOK)
        {
            /* Specify the spell */
            borg_keypress(I2A(b_j));
        }

        /* Success */
        return (TRUE);
    }


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

    /* Hack -- only when bored */
    if (!bored) return (FALSE);


    /* Check each book (backwards) */
    for (book = 9 - 1; book >= 0; book--)
    {
        /* Look for the book */
        i = auto_book[book];

        /* No such book */
        if (i < 0) continue;

        /* Check every spell (backwards) */
        for (what = 9 - 1; what >= 0; what--)
        {
            auto_magic *as = &auto_magics[book][what];

            /* Only try "untried" spells/prayers */
            if (as->status != BORG_MAGIC_TEST) continue;

            /* Ignore "bizarre" spells/prayers */
            if (as->method == BORG_MAGIC_OBJ) continue;
            if (as->method == BORG_MAGIC_WHO) continue;

            /* Note */
            borg_note("# Testing untried spell/prayer");

            /* Hack -- Use spell or prayer */
            if (borg_spell(book, what) ||
                borg_prayer(book, what))
            {
                /* Hack -- Allow attack spells */
                if (as->method == BORG_MAGIC_AIM)
                {
                    /* Hack -- target self */
                    borg_keypress('*');
                    borg_keypress('p');
                    borg_keypress('t');
                }

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

    /* Nope */
    return (FALSE);
}


/*
 * Count the number of items worth "selling"
 *
 * This determines the choice of stairs.
 *
 * XXX XXX XXX Total hack, by the way...
 */
static int borg_count_sell(void)
{
    int i, k = 0;

    s32b price;
    s32b greed;


    /* Calculate "greed" factor */
    greed = (auto_gold / 100L) + 100L;

    /* Minimal greed */
    if (greed < 1000L) greed = 1000L;
    if (greed > 25000L) greed = 25000L;


    /* Count "sellable" items */
    for (i = 0; i < INVEN_PACK; i++)
    {
        auto_item *item = &auto_items[i];

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

        /* Skip "crappy" items */
        if (item->value <= 0) continue;

        /* Obtain the base price */
        price = ((item->value < 30000L) ? item->value : 30000L);

        /* Skip cheap "known" (or "average") items */
        if ((price * item->iqty < greed) &&
            (item->able || streq(item->note, "{average}"))) continue;

        /* Count remaining items */
        k++;
    }

    /* Result */
    return (k);
}



/*
 * Leave the level if necessary (or bored)
 */
bool borg_leave_level(bool bored)
{
    int k, g = 0;

    /* Hack -- waiting for "recall" */
    if (goal_recalling) return (FALSE);

    if (bored)
    {
        
        /* count this level as finished */
        if (auto_depth >= fear_depth && !finished_level)
        {
            finished_level = TRUE;
            auto_fear_depth++;

            /* do not stay at the same level TOO long.  This will */
            /* only help if it is the death of a unique we are waiting  */
            /* for.  If we are hanging out looking for an item then we  */
            /* still will not go lower than the depth we are prepaired for */
            if (auto_fear_depth > 25 && fear_depth < 95)
            {
                /* go to the next level */
                auto_fear_depth = 0;
                fear_depth++;
            }
            
            /* if we are hanging out for a while, start scumming. */
            /* NOTE:  Do not scum for MORGOTH.  That is just too scary! */
            if (auto_fear_depth > 15  && fear_depth < 95)
                auto_scum = TRUE;
            else
                auto_scum = FALSE;
                

        }
    }


    /* Town */
    if (!auto_depth)
    {
        /* Cancel rising */
        goal_rising = FALSE;

        /* Wait until bored */
        if (!bored) return (FALSE);

        /* Hack -- Recall into dungeon */
        if ((auto_max_depth >= 5) &&
            (amt_recall > 4) &&
            ((cptr)NULL == borg_prepared(auto_max_depth)) &&
            borg_recall())
        {
            /* Note */
            borg_note("# Recalling into dungeon (for fun)...");

            /* Give it a shot */
            return (TRUE);
        } 
        else
        {
            /* note why we didn't recall. */
            if (auto_max_depth < 5)
                borg_note("# not deep enough to recall");
            else
                if (amt_recall <= 4)
                    borg_note("# not enough recalls to recall");
                else
                    if ((cptr)NULL != borg_prepared(auto_max_depth))
                        borg_note(format("# not prepared to recall: %s", 
                            borg_prepared(auto_max_depth)));
                    else
                        borg_note("# failed to recall when I wanted to");
        }

        stair_more = TRUE;

        /* Attempt to use those stairs */
        if (borg_flow_stair_more(GOAL_BORE)) return (TRUE);

        /* Oops */
        return (FALSE);
    }

    /* do not hangout on boring levels for *too* long */
    if ((cptr)NULL == borg_prepared(auto_depth + 1)) g = 1;

    /* Count sellable items */
    k = borg_count_sell();

    /* Do not dive when "full" of items */
    if (g && (k >= 12)) g = 0;

    /* Do not dive when drained */
    if (g && do_fix_exp) g = 0;

    /* Hack -- Power-dive upwards when needed */
    if ((cptr)NULL != borg_prepared(auto_depth)) 
    {
        borg_note(format("# heading up (too deep: %s)", 
                            borg_prepared(auto_depth)));
        g = -1;
    }

    /* Hack -- Stay on each level for a minimal amount of time */
    if (0 != g && (c_t - auto_began < value_feeling[auto_feeling])) 
    {
        g = 0;
    }

    /* Rise a level if bored and unable to dive. */
    if (bored && ((cptr)NULL != borg_prepared(auto_depth + 1))) 
    {
        g = -1;
        borg_note(format("# heading up (bored and unable to dive: %s)", 
                    borg_prepared(auto_depth + 1)));

    }

    /* Return to town to sell stuff */
    if (bored && (k >= 12)) 
    {
        borg_note("# Going to town (Sell Stuff).");
        goal_rising = TRUE;
    }

    /* Return to town when level drained */
    if (do_fix_lev) 
    {
        borg_note("# Going to town (Fix Level).");
        goal_rising = TRUE;
    }

    /* Return to town to restore experience */
    if (bored && do_fix_exp) 
    {
        borg_note("# Going to town (Fix Experience).");
        goal_rising = TRUE;
    }

    /* return to town if it has been a while */
    if (!goal_rising && bored && 
        ((auto_time_town + (c_t - auto_began)) > 8000))
    {
        borg_note("# Going to town (I miss my home).");
        goal_rising = TRUE;
    }

    /* if returning to town, try to go upstairs */
    if (goal_rising) g = -1;

    /* don't go back to town if we just left */
    if (goal_rising && (auto_time_town + (c_t - auto_began)) < 200)
    {
        goal_rising = FALSE;
    }

    /* Mega-Hack -- spend time on the first level to rotate shops */
    if ((auto_depth == 1) && (c_t - auto_began < 100) && (g < 0)) g = 0;

    /* Use random stairs when really bored */
    if (bored && (c_t - auto_began >= 5000))
    {
        /* Note */
        borg_note("# Choosing random stairs.");

        /* Use random stairs */
        g = ((rand_int(100) < 50) ? -1 : 1);
    }

    /* stay on level 100 if going after Morgoth and he isn't dead yet */
    if ((auto_depth == 100) && (borg_ready_morgoth == 1))
    {
        goal_rising = FALSE;
        g = 0;
    }

    /* Go Up */
    if (g < 0)
    {
        /* Take next stairs */
        stair_less = TRUE;

        /* Hack -- recall if going to town */
        if (goal_rising &&
            ((auto_time_town + (c_t - auto_began)) > 200) && 
            (auto_depth >= 5) &&
            borg_recall())
        {
            borg_note("# Recalling to town (goal rising)");
            return (TRUE);
        }

        /* Attempt to use stairs */
        if (borg_flow_stair_less(GOAL_BORE)) return (TRUE);

        /* Cannot find any stairs */
        if (goal_rising && bored && (c_t - auto_began) >= 1000)
        {
            if (borg_recall())
            {
                borg_note("# Recalling to town (no stairs)");
                return (TRUE);
            }
        }
    }


    /* Go Down */
    if (g > 0)
    {
        /* Take next stairs */
        stair_more = TRUE;

        /* Attempt to use those stairs */
        if (borg_flow_stair_more(GOAL_BORE)) return (TRUE);
    }


    /* Failure */
    return (FALSE);
}





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



#else

#ifdef MACINTOSH
static int HACK = 0;
#endif

#endif
