summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Cline <zelgadis@sourceforge.net>2009-11-19 20:32:18 -0800
committerMatthew Cline <zelgadis@sourceforge.net>2009-11-19 20:40:15 -0800
commit9c717124d2f48858824a1bfdf3fe4ff62f223e72 (patch)
treed6583372c94afdf2336cad576049149c8b3f8d5b
parent8ae09e1699c95d66263264540e13d09fcac63f59 (diff)
downloadcrawl-ref-9c717124d2f48858824a1bfdf3fe4ff62f223e72.tar.gz
crawl-ref-9c717124d2f48858824a1bfdf3fe4ff62f223e72.zip
explore_stop: greedy_pickup_smart, pickup_ignore
* Added the explore_stop option "greedy_pickup_smart", which is like greedy_pickup, but only stops for thrown items and items different than any in your inventory (and for fruit if you worship Fedhas). * Added the option explore_stop_pickup_ignore. Any items matching any of the regexes in the list will *not* cause "explore_stop = greedy_pickup" (or greedy_pickup_smart) to stop auto-explore. * "explore_stop = greedy_pickup" no longer stops when picking up gold. * "explore_stop = greedy_pickup" (or greedy_pickup_smart) now stops auto-explore after auto-pickup has happened, rather than right before it happens. * Removed obsolete ES_PICKUP.
-rw-r--r--crawl-ref/docs/options_guide.txt24
-rw-r--r--crawl-ref/settings/init.txt2
-rw-r--r--crawl-ref/source/initfile.cc11
-rw-r--r--crawl-ref/source/items.cc223
-rw-r--r--crawl-ref/source/options.h4
-rw-r--r--crawl-ref/source/travel.cc38
-rw-r--r--crawl-ref/source/travel.h25
7 files changed, 272 insertions, 55 deletions
diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt
index b2acca0d55..f527db358b 100644
--- a/crawl-ref/docs/options_guide.txt
+++ b/crawl-ref/docs/options_guide.txt
@@ -48,8 +48,8 @@ The contents of this text are:
scroll_margin
4-g Travel and Exploration.
travel_delay, explore_delay, travel_avoid_terrain,
- explore_greedy, explore_stop, explore_improved,
- tc_reachable, tc_dangerous, tc_disconnected,
+ explore_greedy, explore_stop, explore_stop_pickup_ignore,
+ explore_improved, tc_reachable, tc_dangerous, tc_disconnected,
tc_excluded, tc_exclude_circle, travel_stop_message,
runrest_ignore_message, runrest_ignore_poison,
runrest_ignore_monster, trapwalk_safe_hp,
@@ -845,8 +845,15 @@ explore_stop = items,greedy_pickup,stairs,shops,altars,gates
greedy_items: stop when items that are eligible for autopickup
come into view.
- greedy_pickup: stop when you arrive at a square which contains
- an item eligble for autopickup.
+ greedy_pickup: stop after you automatically pick up any item
+ eligible for autopickup (except for gold). You can make
+ certain items *not* trigger this with the option
+ explore_stop_pickup_ignore
+
+ greedy_pickup_smart: Similar to greedy_pickup, but tries to be
+ smart about it, meaning only stopping for thrown items and
+ items which aren't similar to any you already have in your
+ inventory.
glowing_items: like items, but only for items which are
glowing/runed/embroidered/etc.
@@ -855,6 +862,15 @@ explore_stop = items,greedy_pickup,stairs,shops,altars,gates
runes: like items, but only for runes.
+explore_stop_pickup_ignore = <regex list>
+ If explore_stop has greedy_pickup or greedy_pickup_smart set,
+ then picking up any items matching any of the regexes in the list
+ will *not* stop auto-explore. For example, by default curare-
+ tipped needles are automatically picked up to keep them out of
+ the hands of monsters, even if you don't have a blowgun, so to
+ not stop auto-explore because of this use
+ "explore_stop_pickup_ignore = curare".
+
explore_improved = false
If set to true explore will attempt to reduce zig-zagging during
auto-explore. On average it increases the number of turns taken
diff --git a/crawl-ref/settings/init.txt b/crawl-ref/settings/init.txt
index 73e317e72d..8c8068bc43 100644
--- a/crawl-ref/settings/init.txt
+++ b/crawl-ref/settings/init.txt
@@ -166,6 +166,8 @@ drop_filter = useless_item
# explore_greedy = false
# explore_stop = items,greedy_items,stairs,shops,altars,gates
# explore_improved = true
+#
+# explore_stop_pickup_ignore = curare
auto_exclude = oklob plant,silver statue,orange crystal statue,ice statue
auto_exclude = curse skull,roxanne
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index 37dfd8f952..30ade48c03 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -755,6 +755,8 @@ void game_options::reset_options()
// reading options.
explore_stop_prompt = ES_NONE;
+ explore_stop_pickup_ignore.clear();
+
explore_item_greed = 10;
explore_greedy = true;
@@ -1598,10 +1600,10 @@ int game_options::read_explore_stop_conditions(const std::string &field) const
const std::string &c = stops[i];
if (c == "item" || c == "items")
conditions |= ES_ITEM;
- else if (c == "pickup")
- conditions |= ES_PICKUP;
else if (c == "greedy_pickup" || c == "greedy pickup")
conditions |= ES_GREEDY_PICKUP;
+ else if (c == "greedy_pickup_smart" || c == "greedy pickup smart")
+ conditions |= ES_GREEDY_PICKUP_SMART;
else if (c == "shop" || c == "shops")
conditions |= ES_SHOP;
else if (c == "stair" || c == "stairs")
@@ -1975,6 +1977,7 @@ void game_options::read_option_line(const std::string &str, bool runscript)
if (key != "name" && key != "crawl_dir" && key != "macro_dir"
&& key != "species" && key != "job" && key != "ban_pickup"
&& key != "autopickup_exceptions"
+ && key != "explore_stop_pickup_ignore"
&& key != "stop_travel" && key != "sound"
&& key != "travel_stop_message" && key != "force_more_message"
&& key != "drop_filter" && key != "lua_file" && key != "terp_file"
@@ -2869,6 +2872,10 @@ void game_options::read_option_line(const std::string &str, bool runscript)
else
explore_stop_prompt |= new_conditions;
}
+ else if (key == "explore_stop_pickup_ignore")
+ {
+ append_vector(explore_stop_pickup_ignore, split_string(",", field));
+ }
else if (key == "explore_item_greed")
{
explore_item_greed = atoi( field.c_str() );
diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc
index 6ad9fb2dfe..46a7fb5fc8 100644
--- a/crawl-ref/source/items.cc
+++ b/crawl-ref/source/items.cc
@@ -2323,10 +2323,215 @@ bool can_autopickup()
return (true);
}
+typedef bool (*item_comparer)(const item_def& pickup_item,
+ const item_def& inv_item);
+
+static bool _identical_types(const item_def& pickup_item,
+ const item_def& inv_item)
+{
+ return ((pickup_item.base_type == inv_item.base_type)
+ && (pickup_item.sub_type == inv_item.sub_type));
+}
+
+static bool _edible_food(const item_def& pickup_item,
+ const item_def& inv_item)
+{
+ return (inv_item.base_type == OBJ_FOOD && !is_inedible(inv_item));
+}
+
+static bool _similar_equip(const item_def& pickup_item,
+ const item_def& inv_item)
+{
+ const equipment_type inv_slot = get_item_slot(inv_item);
+
+ if (inv_slot == EQ_NONE)
+ return (false);
+
+ // If it's an unequipped cursed item the player might be looking
+ // for a replacement.
+ if (item_known_cursed(inv_item) && !item_is_equipped(inv_item))
+ return (false);
+
+ if (get_item_slot(pickup_item) != inv_slot)
+ return (false);
+
+ // Just filling the same slot is enough for armour to be considered
+ // similar.
+ if (pickup_item.base_type == OBJ_ARMOUR)
+ return (true);
+
+ // Launchers of the same type are similar.
+ if ((pickup_item.sub_type >= WPN_BLOWGUN &&
+ pickup_item.sub_type <= WPN_LONGBOW)
+ || pickup_item.sub_type == WPN_SLING)
+ {
+ return (pickup_item.sub_type != inv_item.sub_type);
+ }
+
+ return ((weapon_skill(pickup_item) == weapon_skill(inv_item))
+ && (get_damage_type(pickup_item) == get_damage_type(inv_item)));
+}
+
+static bool _similar_wands(const item_def& pickup_item,
+ const item_def& inv_item)
+{
+ if (inv_item.base_type != OBJ_WANDS)
+ return (false);
+
+ if (pickup_item.sub_type != inv_item.sub_type)
+ return (false);
+
+ // Not similar if wand in inventory is known to be empty.
+ return (inv_item.plus2 != ZAPCOUNT_EMPTY
+ || (item_ident(inv_item, ISFLAG_KNOW_PLUSES)
+ && inv_item.plus > 0));
+}
+
+static bool _similar_jewellery(const item_def& pickup_item,
+ const item_def& inv_item)
+{
+ if (inv_item.base_type != OBJ_JEWELLERY)
+ return (false);
+
+ if (pickup_item.sub_type != inv_item.sub_type)
+ return (false);
+
+ // For jewellery of the same sub-type, unidentified jewellery is
+ // always considered similar, as is identified jewellery whose
+ // effect doesn't stack.
+ return (!item_type_known(inv_item)
+ || (!jewellery_is_amulet(inv_item)
+ && !ring_has_stackable_effect(inv_item)));
+}
+
+static bool _item_different_than_inv(const item_def& pickup_item,
+ item_comparer comparer)
+{
+ for (int i = 0; i < ENDOFPACK; i++)
+ {
+ const item_def& inv_item(you.inv[i]);
+
+ if (!inv_item.is_valid())
+ continue;
+
+ if ( (*comparer)(pickup_item, inv_item) )
+ return (false);
+ }
+
+ return (true);
+}
+
+static bool _interesting_explore_pickup(const item_def& item)
+{
+ if (!(Options.explore_stop & ES_GREEDY_PICKUP_MASK))
+ return (false);
+
+ // Gold is boring.
+ if (item.base_type == OBJ_GOLD)
+ return (false);
+
+ std::vector<text_pattern> &ignore = Options.explore_stop_pickup_ignore;
+ if (!ignore.empty())
+ {
+ const std::string name = item.name(DESC_PLAIN);
+
+ for (unsigned int i = 0; i < ignore.size(); i++)
+ if (ignore[i].matches(name))
+ return (false);
+ }
+
+ if (!(Options.explore_stop & ES_GREEDY_PICKUP_SMART))
+ return (true);
+
+ // "Smart" code follows.
+ if (item.flags & ISFLAG_THROWN)
+ return (true);
+
+ if (is_artefact(item))
+ return (true);
+
+ // Possbible ego items.
+ if (!item_type_known(item) & (item.flags & ISFLAG_COSMETIC_MASK))
+ return (true);
+
+ switch(item.base_type)
+ {
+ case OBJ_WEAPONS:
+ case OBJ_MISSILES:
+ case OBJ_ARMOUR:
+ // Ego items.
+ if (item.special != 0)
+ return (true);
+ break;
+
+ default:
+ break;
+ }
+
+ switch(item.base_type)
+ {
+ case OBJ_WEAPONS:
+ case OBJ_ARMOUR:
+ return _item_different_than_inv(item, _similar_equip);
+
+ case OBJ_WANDS:
+ return _item_different_than_inv(item, _similar_wands);
+
+ case OBJ_JEWELLERY:
+ return _item_different_than_inv(item, _similar_jewellery);
+
+ case OBJ_FOOD:
+ if (you.religion == GOD_FEDHAS && is_fruit(item))
+ return (true);
+
+ if (is_inedible(item))
+ return (false);
+
+ // Interesting if we don't have any other edible food.
+ return _item_different_than_inv(item, _edible_food);
+
+ case OBJ_STAVES:
+ // Rods are always interesting, even if you already have one of
+ // the same type, since each rod has its own mana.
+ if (item_is_rod(item))
+ return (true);
+
+ // Intentional fall-through.
+ case OBJ_MISCELLANY:
+ // Runes are always interesting.
+ if (is_rune(item))
+ return (true);
+
+ // Decks always start out unidentified.
+ if (is_deck(item))
+ return (true);
+
+ // Intentional fall-through.
+ case OBJ_SCROLLS:
+ case OBJ_POTIONS:
+ // Item is boring only if there's an identical one in inventory.
+ return _item_different_than_inv(item, _identical_types);
+
+ case OBJ_BOOKS:
+ // Books always start out unidentified.
+ return (true);
+
+ case OBJ_ORBS:
+ // Orb is always interesting.
+ return (true);
+
+ default:
+ break;
+ }
+
+ return (false);
+}
+
static void _do_autopickup()
{
- int n_did_pickup = 0;
- int n_tried_pickup = 0;
+ bool did_pickup = false;
+ int n_did_pickup = 0;
+ int n_tried_pickup = 0;
will_autopickup = false;
@@ -2370,6 +2575,12 @@ static void _do_autopickup()
}
}
+ // Do this before it's picked up, otherwise the picked up
+ // item will be in inventory and _interesting_explore_pickup()
+ // will always return false.
+ const bool interesting_pickup
+ = _interesting_explore_pickup(mitm[o]);
+
const unsigned long iflags(mitm[o].flags);
mitm[o].flags &= ~(ISFLAG_THROWN | ISFLAG_DROPPED);
@@ -2385,7 +2596,11 @@ static void _do_autopickup()
mitm[o].flags = iflags;
}
else
- n_did_pickup++;
+ {
+ did_pickup = true;
+ if (interesting_pickup)
+ n_did_pickup++;
+ }
}
o = next;
@@ -2394,7 +2609,7 @@ static void _do_autopickup()
if (!pickup_warning.empty())
mpr(pickup_warning.c_str());
- if (n_did_pickup)
+ if (did_pickup)
you.turn_is_over = true;
item_check(false);
diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h
index 4e37f4352d..9d0bc6d3d6 100644
--- a/crawl-ref/source/options.h
+++ b/crawl-ref/source/options.h
@@ -245,6 +245,10 @@ public:
int explore_stop_prompt;
+ // Don't stop greedy explore when picking up an item which matches
+ // any of these patterns.
+ std::vector<text_pattern> explore_stop_pickup_ignore;
+
bool explore_greedy; // Explore goes after items as well.
// How much more eager greedy-explore is for items than to explore.
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index 7af3080f09..f0965784ce 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -795,8 +795,8 @@ void explore_pickup_event(int did_pickup, int tried_pickup)
if (did_pickup)
{
const int estop =
- (you.running == RMODE_EXPLORE_GREEDY) ? ES_GREEDY_PICKUP
- : ES_PICKUP;
+ (you.running == RMODE_EXPLORE_GREEDY) ? ES_GREEDY_PICKUP_MASK
+ : ES_NONE;
if ((Options.explore_stop & estop) && prompt_stop_explore(estop))
{
@@ -932,35 +932,6 @@ command_type travel()
prev_travel_index = !prev_travel_index;
}
- if ((*move_x || *move_y) && you.running == RMODE_EXPLORE_GREEDY)
- {
- // Greedy explore should cut off on reaching an item. We can't
- // check after reaching the item, because at that point the stash
- // tracker will have verified the stash and say "false" to
- // needs_visit.
- const coord_def newpos = you.pos() + coord_def(*move_x, *move_y);
-
- if (newpos == you.running.pos)
- {
- const LevelStashes *lev = StashTrack.find_current_level();
- if (lev && lev->needs_visit(newpos)
- && !lev->shop_needs_visit(newpos))
- {
- const int estop =
- (you.running == RMODE_EXPLORE_GREEDY) ?
- ES_GREEDY_PICKUP : ES_PICKUP;
-
- if ((Options.explore_stop & estop)
- && prompt_stop_explore(estop))
- {
- explore_stopped_pos = newpos;
- stop_running();
- }
- return direction_to_command( *move_x, *move_y );
- }
- }
- }
-
if (!*move_x && !*move_y)
{
// If we've reached the square we were traveling towards, travel
@@ -4053,8 +4024,9 @@ void explore_discoveries::found_item(const coord_def &pos, const item_def &i)
} // if (you.running == RMODE_EXPLORE_GREEDY)
add_item(i);
- es_flags |= (you.running == RMODE_EXPLORE_GREEDY) ? ES_GREEDY_PICKUP
- : ES_PICKUP;
+ // MATT
+ es_flags |= (you.running == RMODE_EXPLORE_GREEDY) ? ES_GREEDY_PICKUP_MASK
+ : ES_NONE;
}
// Expensive O(n^2) duplicate search, but we can live with that.
diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h
index 5a79e6b046..2b0b8240b9 100644
--- a/crawl-ref/source/travel.h
+++ b/crawl-ref/source/travel.h
@@ -157,18 +157,19 @@ extern travel_distance_grid_t travel_point_distance;
enum explore_stop_type
{
- ES_NONE = 0x000,
- ES_ITEM = 0x001,
- ES_PICKUP = 0x002,
- ES_GREEDY_PICKUP = 0x004,
- ES_GREEDY_ITEM = 0x008,
- ES_STAIR = 0x010,
- ES_SHOP = 0x020,
- ES_ALTAR = 0x040,
- ES_PORTAL = 0x080,
- ES_GLOWING_ITEM = 0x100,
- ES_ARTEFACT = 0x200,
- ES_RUNE = 0x400
+ ES_NONE = 0x000,
+ ES_ITEM = 0x001,
+ ES_GREEDY_PICKUP = 0x002,
+ ES_GREEDY_PICKUP_SMART = 0x004,
+ ES_GREEDY_PICKUP_MASK = (ES_GREEDY_PICKUP | ES_GREEDY_PICKUP_SMART),
+ ES_GREEDY_ITEM = 0x008,
+ ES_STAIR = 0x010,
+ ES_SHOP = 0x020,
+ ES_ALTAR = 0x040,
+ ES_PORTAL = 0x080,
+ ES_GLOWING_ITEM = 0x100,
+ ES_ARTEFACT = 0x200,
+ ES_RUNE = 0x400
};
////////////////////////////////////////////////////////////////////////////