summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/items.cc
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 /crawl-ref/source/items.cc
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.
Diffstat (limited to 'crawl-ref/source/items.cc')
-rw-r--r--crawl-ref/source/items.cc223
1 files changed, 219 insertions, 4 deletions
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);