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