void Wand::onEvent(Event* const event) { if (event->id() == ReceivedItems::ID) { ReceivedItems* e = static_cast<ReceivedItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { map<const string, const data::Wand*>::const_iterator w = data::Wand::wands().find(i->second.name()); if (w == data::Wand::wands().end()) continue; // not a wand if (i->second.beatitude() == BEATITUDE_UNKNOWN) { // beatify, but it's not that important Beatify b(i->first, 10); EventBus::broadcast(&b); } if (w->second->properties() & PROPERTY_RANDOM_APPEARANCE) _engrave_test_wand_key = i->first; } } else if (event->id() == WantItems::ID) { WantItems* e = static_cast<WantItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { map<const string, const data::Wand*>::const_iterator w = data::Wand::wands().find(i->second.name()); if (w == data::Wand::wands().end()) continue; // not a wand i->second.want(i->second.count()); } } }
/* methods */ void Amulet::onEvent(Event * const event) { if (event->id() == ChangedInventoryItems::ID) { ChangedInventoryItems* e = static_cast<ChangedInventoryItems*> (event); for (set<unsigned char>::iterator i = e->keys().begin(); i != e->keys().end(); ++i) { Item item = Inventory::itemAtKey(*i); if (item.beatitude() != CURSED && item.beatitude() != BEATITUDE_UNKNOWN && data::Amulet::amulets().find(item.name()) != data::Amulet::amulets().end()) { if (item.name().find("strangulation") != string::npos && item.name().find("restful") != string::npos) _amulet_key = *i; break; } } //todo: determine best amulet } else if (event->id() == ReceivedItems::ID) { ReceivedItems* e = static_cast<ReceivedItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (i->second.beatitude() != BEATITUDE_UNKNOWN || data::Amulet::amulets().find(i->second.name()) == data::Amulet::amulets().end()) continue; // known beatitude or not an amulet else if (i->second.beatitude() == BEATITUDE_UNKNOWN && data::Amulet::amulets().find(i->second.name()) != data::Amulet::amulets().end()) { Beatify b(i->first, 175); EventBus::broadcast(&b); } else if (i->second.beatitude() != CURSED && data::Amulet::amulets().find(i->second.name()) != data::Amulet::amulets().end()) { if (i->second.name().find("strangulation") != string::npos && i->second.name().find("restful") != string::npos) _amulet_key = i->first; } } } else if (event->id() == WantItems::ID) { Debug::info() << "WantItems appeared, wearing?" << endl; WantItems* e = static_cast<WantItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (wantItem(i->second)) i->second.want(i->second.count()); } } }
void Weapon::onEvent(event::Event* const event) { if (event->id() == ChangedInventoryItems::ID) { ChangedInventoryItems* e = static_cast<ChangedInventoryItems*> (event); for (set<unsigned char>::iterator k = e->keys().begin(); k != e->keys().end(); ++k) { const Item& item = Inventory::itemAtKey(*k); if (item.count() <= 0) { /* we lost this item */ _range_weapons.erase(*k); _melee_weapons.erase(*k); continue; } map<const string, const data::Weapon*>::const_iterator w = data::Weapon::weapons().find(item.name()); if (w == data::Weapon::weapons().end()) continue; // not a weapon int score = calculateWeaponScore(item, w->second); if (isRangedWeapon(w->second)) _range_weapons[*k] = score; else _melee_weapons[*k] = score; } setBestWeapons(); } else if (event->id() == ReceivedItems::ID) { ReceivedItems* e = static_cast<ReceivedItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { map<const string, const data::Weapon*>::const_iterator w = data::Weapon::weapons().find(i->second.name()); if (w == data::Weapon::weapons().end()) continue; // not a weapon int score = calculateWeaponScore(i->second, w->second); if (isRangedWeapon(w->second)) { _range_weapons[i->first] = score; } else { _melee_weapons[i->first] = score; if (i->second.beatitude() == BEATITUDE_UNKNOWN) { Beatify b(i->first, 175); EventBus::broadcast(&b); } } } setBestWeapons(); } else if (event->id() == WantItems::ID) { WantItems* e = static_cast<WantItems*> (event); // if (e->dropping() || Saiph::encumbrance() < BURDENED) { /* dropping items or we're burdened (which means don't loot weapons) */ for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (e->dropping()) { if (_range_weapons.find(i->first) != _range_weapons.end() || _melee_weapons.find(i->first) != _melee_weapons.end()) { /* don't drop weapons in one of our lists */ i->second.want(i->second.count()); } } else { /* looting, is this better than what we got? */ if (betterThanWhatWeGot(i->second)) i->second.want(i->second.count()); } } // } } }
void Health::onEvent(event::Event* const event) { if (event->id() == ChangedInventoryItems::ID) { ChangedInventoryItems* e = static_cast<ChangedInventoryItems*> (event); for (set<unsigned char>::iterator k = e->keys().begin(); k != e->keys().end(); ++k) { map<unsigned char, Item>::iterator i = Inventory::items().find(*k); if (*k == _unihorn_key) { if (i == Inventory::items().end() || i->second.beatitude() == CURSED || data::UnicornHorn::unicornHorns().find(i->second.name()) == data::UnicornHorn::unicornHorns().end()) { _unihorn_key = ILLEGAL_ITEM; continue; } } else if (*k == _lizard_key) { if (i == Inventory::items().end()) { _lizard_key = ILLEGAL_ITEM; continue; } map<const string, const data::Corpse*>::const_iterator c = data::Corpse::corpses().find(i->second.name()); if (c == data::Corpse::corpses().end() || !(c->second->effects() & EAT_EFFECT_CURE_STONING)) { _lizard_key = ILLEGAL_ITEM; continue; } } } } else if (event->id() == ReceivedItems::ID) { ReceivedItems* e = static_cast<ReceivedItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (data::UnicornHorn::unicornHorns().find(i->second.name()) != data::UnicornHorn::unicornHorns().end()) { if (i->second.beatitude() == BEATITUDE_UNKNOWN) { Beatify b(i->first, 175); EventBus::broadcast(&b); } else if (i->second.beatitude() != CURSED) { map<unsigned char, Item>::iterator u = Inventory::items().find(_unihorn_key); if (u == Inventory::items().end() || u->second.beatitude() == UNCURSED) _unihorn_key = i->first; } continue; } map<const string, const data::Corpse*>::const_iterator c = data::Corpse::corpses().find(i->second.name()); if (c != data::Corpse::corpses().end() && (c->second->effects() & EAT_EFFECT_CURE_STONING)) { _lizard_key = i->first; continue; } } } else if (event->id() == WantItems::ID) { WantItems* e = static_cast<WantItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (i->second.beatitude() != CURSED && data::UnicornHorn::unicornHorns().find(i->second.name()) != data::UnicornHorn::unicornHorns().end()) { /* let's pick up all non-cursed unihorns */ i->second.want(i->second.count()); continue; } map<const string, const data::Corpse*>::const_iterator c = data::Corpse::corpses().find(i->second.name()); if (c != data::Corpse::corpses().end() && (c->second->effects() & EAT_EFFECT_CURE_STONING)) { /* let's pick up all lizard corpses */ i->second.want(i->second.count()); continue; } } } }
void Donate::onEvent(Event* const event) { if (event->id() == WantItems::ID) { /* we want gold to donate to priests */ WantItems* e = static_cast<WantItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (i->second.name() == "gold piece") i->second.want(i->second.count()); } } }
void Lamp::onEvent(event::Event * const event) { if (event->id() == ChangedInventoryItems::ID) { /* inventory changed, find lamp */ findLamp(); } else if (event->id() == ReceivedItems::ID) { /* received items, find lamp */ findLamp(); } else if (event->id() == WantItems::ID) { WantItems* e = static_cast<WantItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (data::Lamp::lamps().find(i->second.name()) != data::Lamp::lamps().end()) i->second.want(i->second.count()); } } }
void Armor::onEvent(event::Event * const event) { if (event->id() == ChangedInventoryItems::ID) { ChangedInventoryItems* e = static_cast<ChangedInventoryItems*> (event); for (set<unsigned char>::iterator k = e->keys().begin(); k != e->keys().end(); ++k) { if (betterThanCurrent(Inventory::itemAtKey(*k))) _put_on.insert(*k); else _put_on.erase(*k); } } else if (event->id() == ReceivedItems::ID) { ReceivedItems* e = static_cast<ReceivedItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (data::Armor::armors().find(i->second.name()) == data::Armor::armors().end()) continue; // not armor if (i->second.beatitude() != BEATITUDE_UNKNOWN) { /* known beatitude, should we wear it? */ if (i->second.beatitude() != CURSED && betterThanCurrent(i->second)) _put_on.insert(i->first); // it's not cursed and (possibly) better than what we're wearing else _put_on.erase(i->first); continue; } Beatify b(i->first, 175); EventBus::broadcast(&b); } } else if (event->id() == WantItems::ID) { WantItems* e = static_cast<WantItems*> (event); if (Saiph::encumbrance() >= BURDENED) { /* burdened and beatifying, (and is on a stash): pick up */ if (World::shortestPath(ALTAR).cost() < UNPASSABLE) { if (Saiph::encumbrance() < STRESSED) { if (e->safeStash()) { for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (betterThanCurrent(i->second)) i->second.want(i->second.count()); } } } /* burdened and not beatifying: stash */ } else if (e->safeStash()) { loopTimeout = World::turn() + 10; } /* not burdened */ } else { /* and not on safe stash: pick up */ if (!e->safeStash() && loopTimeout <= World::turn()) { /* ^ this also means 'drop at every safe stash if not burdened' */ /* TODO: to avoid this, check whether on upstair, without stashing */ for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (betterThanCurrent(i->second)) i->second.want(i->second.count()); } } } } }
void Quest::onEvent(event::Event* const event) { if (event->id() == WantItems::ID) { WantItems* e = static_cast<WantItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (i->second.name() == "silver bell" || i->second.name() == "Bell of Opening") { _seen_bell = true; i->second.want(i->second.count()); } else if (i->second.name() == artifacts[Saiph::role()]) { _seen_arti = true; i->second.want(i->second.count()); } if (_status != QUEST_STATUS_COMPLETED && _seen_bell && _seen_arti) setStatus(_portal_level, QUEST_STATUS_COMPLETED); } } }
void Shop::onEvent(event::Event* const event) { if (event->id() == WantItems::ID) { WantItems* e = static_cast<WantItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (data::Pickaxe::pickaxes().find(i->second.name()) == data::Pickaxe::pickaxes().end()) continue; int near = nearShop(Saiph::position()); if (_shopping && near == THRESHOLD) { // drop them all // setting count to 0 prevents any other analyzer from overriding i->second.count(0); } else if (near == IN_SHOP) { // a pick in a doorway is a problem and should be picked up even if shopping i->second.want(i->second.count()); } } } }
/* methods */ void Amulet::onEvent(Event* const event) { if (event->id() == ChangedInventoryItems::ID) { ChangedInventoryItems* e = static_cast<ChangedInventoryItems*> (event); map<unsigned char, Item> k; for (set<unsigned char>::iterator i = e->keys().begin(); i != e->keys().end(); ++i) { Item item = Inventory::itemAtKey(*i); k.insert(pair<unsigned char, Item>(*i, item)); } _amulet_key = bestAmulet(k); } else if (event->id() == ReceivedItems::ID) { ReceivedItems* e = static_cast<ReceivedItems*> (event); _amulet_key = bestAmulet((e->items())); } else if (event->id() == WantItems::ID) { WantItems* e = static_cast<WantItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (wantItem(i->second)) i->second.want(i->second.count()); } } }
void Door::onEvent(Event* const event) { if (event->id() == ChangedInventoryItems::ID) { /* inventory changed, see if we lost our unlocking device or got a new/better one */ if (Inventory::items().find(_unlock_tool_key) == Inventory::items().end()) _unlock_tool_key = 0; // darn, we lost our unlocking device ChangedInventoryItems* e = static_cast<ChangedInventoryItems*> (event); for (set<unsigned char>::iterator k = e->keys().begin(); k != e->keys().end(); ++k) { map<unsigned char, Item>::iterator i = Inventory::items().find(*k); if (i != Inventory::items().end() && wantItem(i->second)) _unlock_tool_key = *k; // better key than what we currently got } } else if (event->id() == ReceivedItems::ID) { ReceivedItems* e = static_cast<ReceivedItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (wantItem(i->second)) _unlock_tool_key = i->first; // better key than what we currently got } } else if (event->id() == WantItems::ID) { WantItems* e = static_cast<WantItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if ((e->dropping() && _unlock_tool_key != ILLEGAL_ITEM && i->first == _unlock_tool_key) || wantItem(i->second)) i->second.want(i->second.count()); } } else if (event->id() == ShopDetected::ID) { ShopDetected* e = static_cast<ShopDetected*> (event); stack<Point> ps; for (int x = e->ul().col(); x <= e->lr().col(); ++x) { ps.push(Point(e->ul().row() - 1, x)); ps.push(Point(e->lr().row() + 1, x)); } for (int y = e->ul().row() - 1; y <= e->lr().row() + 1; ++y) { ps.push(Point(y, e->ul().col() - 1)); ps.push(Point(y, e->lr().col() + 1)); } for (; !ps.empty(); ps.pop()) { if (World::level().tile(ps.top()).symbol() != CLOSED_DOOR) continue; World::level().setDungeonSymbolValue(ps.top(), getDoorFlags(ps.top()) | DOOR_IS_SHOP); } } }
void Armor::onEvent(event::Event * const event) { if (event->id() == ChangedInventoryItems::ID) { ChangedInventoryItems* e = static_cast<ChangedInventoryItems*> (event); for (set<unsigned char>::iterator k = e->keys().begin(); k != e->keys().end(); ++k) { if (betterThanCurrent(Inventory::itemAtKey(*k))) _put_on.insert(*k); else _put_on.erase(*k); } } else if (event->id() == ReceivedItems::ID) { ReceivedItems* e = static_cast<ReceivedItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (data::Armor::armors().find(i->second.name()) == data::Armor::armors().end()) continue; // not armor if (i->second.beatitude() != BEATITUDE_UNKNOWN) { /* known beatitude, should we wear it? */ if (i->second.beatitude() != CURSED && betterThanCurrent(i->second)) _put_on.insert(i->first); // it's not cursed and (possibly) better than what we're wearing else _put_on.erase(i->first); continue; } Beatify b(i->first, 175); EventBus::broadcast(&b); } } else if (event->id() == WantItems::ID) { WantItems* e = static_cast<WantItems*> (event); if (e->safeStash() && World::shortestPath(ALTAR).cost() >= UNPASSABLE) { /* on safe stash and can't path to altar, drop */ } else if (Saiph::encumbrance() < BURDENED && (!e->safeStash() || World::shortestPath(ALTAR).cost() < UNPASSABLE)) { /* we're not burdened and not on a safe stash or we can't reach an altar, loot armor */ /* if we are on a safe stash and can't reach an altar then we will drop armor */ for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (betterThanCurrent(i->second)) i->second.want(i->second.count()); } } } }
void Beatitude::onEvent(event::Event* const event) { if (event->id() == Beatify::ID) { Beatify* e = static_cast<Beatify*> (event); set<unsigned char>::iterator b = _beatify.find(e->key()); _beatify.insert(e->key()); if (e->priority() > _max_priority) _max_priority = e->priority(); } else if (event->id() == WantItems::ID && World::level().tile().symbol() == ALTAR) { /* looting or picking up items at an altar */ WantItems* e = static_cast<WantItems*> (event); if (e->dropping()) { for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (i->second.beatitude() != BEATITUDE_UNKNOWN) continue; // know beatitude already /* should drop this item, force it by setting count to 0 */ i->second.count(0); } _beatify.clear(); _max_priority = ILLEGAL_PRIORITY; } } }
/* methods */ void DiggingTool::onEvent(Event* const event) { if (event->id() == ChangedInventoryItems::ID || event->id() == ReceivedItems::ID) { findDigger(); } else if (event->id() == WantItems::ID) { WantItems* e = static_cast<WantItems*> (event); int key; int score; // WantItems is called once per page while dropping, but the ranking needs to see the whole list... rankDiggers(key, score, (e->dropping() ? NULL : &Inventory::items()), (e->dropping() ? &Inventory::items() : &e->items())); if (key >= 0 && e->items().find(key) != e->items().end()) { Item& item = e->items()[(unsigned char)key]; item.want(min(1, item.count())); } } }
void Health::onEvent(event::Event * const event) { if (event->id() == ChangedInventoryItems::ID) { ChangedInventoryItems* e = static_cast<ChangedInventoryItems*> (event); for (set<unsigned char>::iterator k = e->keys().begin(); k != e->keys().end(); ++k) { map<unsigned char, Item>::iterator i = Inventory::items().find(*k); if (*k == _unihorn_key) { if (i == Inventory::items().end() || i->second.beatitude() == CURSED || data::UnicornHorn::unicornHorns().find(i->second.name()) == data::UnicornHorn::unicornHorns().end()) { _unihorn_key = ILLEGAL_ITEM; continue; } } else if (*k == _lizard_key) { if (i == Inventory::items().end()) { _lizard_key = ILLEGAL_ITEM; continue; } map<const string, const data::Corpse*>::const_iterator c = data::Corpse::corpses().find(i->second.name()); if (c == data::Corpse::corpses().end() || !(c->second->effects() & EAT_EFFECT_CURE_STONING)) { _lizard_key = ILLEGAL_ITEM; continue; } } } } else if (event->id() == ReceivedItems::ID) { ReceivedItems* e = static_cast<ReceivedItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (data::UnicornHorn::unicornHorns().find(i->second.name()) != data::UnicornHorn::unicornHorns().end()) { if (i->second.beatitude() == BEATITUDE_UNKNOWN) { Beatify b(i->first, 175); EventBus::broadcast(&b); } else if (i->second.beatitude() != CURSED) { map<unsigned char, Item>::iterator u = Inventory::items().find(_unihorn_key); if (u == Inventory::items().end() || u->second.beatitude() == UNCURSED) _unihorn_key = i->first; } continue; } map<const string, const data::Corpse*>::const_iterator c = data::Corpse::corpses().find(i->second.name()); if (c != data::Corpse::corpses().end() && (c->second->effects() & EAT_EFFECT_CURE_STONING)) { _lizard_key = i->first; continue; } } } else if (event->id() == WantItems::ID) { WantItems* e = static_cast<WantItems*> (event); for (map<unsigned char, Item>::iterator i = e->items().begin(); i != e->items().end(); ++i) { if (i->second.beatitude() != CURSED && data::UnicornHorn::unicornHorns().find(i->second.name()) != data::UnicornHorn::unicornHorns().end()) { /* non-cursed unihorn */ /* if we want to limit amount of unihorns, do it here, check inventory how many we got */ int unihornNum = 0; for (map<unsigned char, Item>::iterator i2 = e->items().begin(); i2 != e->items().end(); ++i2) { if (i2->second.beatitude() != CURSED && data::UnicornHorn::unicornHorns().find(i->second.name()) != data::UnicornHorn::unicornHorns().end()) unihornNum++; } /* keep at least 3 on hand */ if (unihornNum < 3) i->second.want(i->second.count()); continue; } map<const string, const data::Corpse*>::const_iterator c = data::Corpse::corpses().find(i->second.name()); if (c != data::Corpse::corpses().end() && (c->second->effects() & EAT_EFFECT_CURE_STONING)) { /* lizard corpse */ /* if we want to limit amount of lizard corpses, do it here, check inventory how many we got */ int lizardNum = 0; for (map<unsigned char, Item>::iterator i2 = e->items().begin(); i2 != e->items().end(); ++i2) { map<const string, const data::Corpse*>::const_iterator c2 = data::Corpse::corpses().find(i2->second.name()); if (c != data::Corpse::corpses().end() && (c->second->effects() & EAT_EFFECT_CURE_STONING)) lizardNum++; } if (lizardNum < 3) i->second.want(i->second.count()); continue; } } } }