bool MarkovChain<T>::updateToNext() { const vector<pair<T, double>> t = transitions.at(state); if (t.size() == 1) return false; state = chooseRandom(getPrefix(t, 0, t.size() - 1)); return true; }
vector<Deity*> generateDeities() { set<Epithet> used; vector<Deity*> ret; for (auto elem : epithetsMap) { string deity = NameGenerator::deityNames.getNext(); Gender gend = Gender::male; if ((deity.back() == 'a' || deity.back() == 'i') && !Random.roll(4)) gend = Gender::female; vector<Epithet> ep; for (int i : Range(Random.getRandom(1, 4))) { Epithet epithet; int cnt = 100; do { epithet = chooseRandom(elem.second); } while (used.count(epithet) && --cnt > 0); if (cnt == 0) break; used.insert(epithet); ep.push_back(epithet); } if (ep.empty()) return generateDeities(); ret.push_back(new Deity(deity, gend, ep, elem.first)); } return ret; }
BodyPart CreatureAttributes::armOrWing() const { if (numGood(BodyPart::ARM) == 0) return BodyPart::WING; if (numGood(BodyPart::WING) == 0) return BodyPart::ARM; return chooseRandom({ BodyPart::WING, BodyPart::ARM }, {1, 1}); }
vector<Deity*> generateDeities() { set<EpithetId> used; vector<Deity*> ret; for (auto elem : epithetsMap) { string deity = NameGenerator::get(NameGeneratorId::DEITY)->getNext(); Gender gend = Gender::male; if ((deity.back() == 'a' || deity.back() == 'i') && !Random.roll(4)) gend = Gender::female; vector<EpithetId> ep; for (int i : Range(Random.get(1, 4))) { EpithetId epithet; int cnt = 100; do { epithet = chooseRandom(elem.second); } while (used.count(epithet) && --cnt > 0); if (cnt == 0) break; used.insert(epithet); ep.push_back(epithet); } if (ep.empty()) return generateDeities(); ret.push_back(new Deity(deity, gend, ep, elem.first)); } for (Deity* deity : ret) Debug() << deity->getName() + " lives in " + deity->getHabitatString() + ". " << deity->getGender().he() << " is the " << deity->getGender().god() << " of " << deity->getEpithetsString(); return ret; }
BodyPart CreatureAttributes::getBodyPart(AttackLevel attack, bool flying, bool collapsed) const { if (flying) return chooseRandom({BodyPart::TORSO, BodyPart::HEAD, BodyPart::LEG, BodyPart::WING, BodyPart::ARM}, {1, 1, 1, 2, 1}); switch (attack) { case AttackLevel::HIGH: return BodyPart::HEAD; case AttackLevel::MIDDLE: if (getSize() == CreatureSize::SMALL || getSize() == CreatureSize::MEDIUM || collapsed) return BodyPart::HEAD; else return chooseRandom({BodyPart::TORSO, armOrWing()}, {1, 1}); case AttackLevel::LOW: if (getSize() == CreatureSize::SMALL || collapsed) return chooseRandom({BodyPart::TORSO, armOrWing(), BodyPart::HEAD, BodyPart::LEG}, {1, 1, 1, 1}); if (getSize() == CreatureSize::MEDIUM) return chooseRandom({BodyPart::TORSO, armOrWing(), BodyPart::LEG}, {1, 1, 3}); else return BodyPart::LEG; } return BodyPart::ARM; }
virtual MoveInfo getMove() override { return chooseRandom(behaviours, weights)->getMove(); }
void MarkovChain<T>::update() { state = chooseRandom(transitions.at(state)); }
void Deity::onPrayer(Creature* c) { bool prayerAnswered = false; for (Epithet epithet : randomPermutation(epithets)) { if (contains(usedEpithets, epithet)) continue; bool noEffect = false; switch (epithet) { case Epithet::DEATH: { PCreature death = CreatureFactory::fromId(CreatureId::DEATH, Tribes::get(TribeId::KILL_EVERYONE)); for (Vec2 v : c->getPosition().neighbors8(true)) if (c->getLevel()->inBounds(v) && c->getLevel()->getSquare(v)->canEnter(death.get())) { c->privateMessage("Death appears before you."); c->getLevel()->addCreature(v, std::move(death)); break; } if (death) noEffect = true; break; } case Epithet::WAR: grantGift(c, chooseRandom( {ItemId::SPECIAL_SWORD, ItemId::SPECIAL_BATTLE_AXE, ItemId::SPECIAL_WAR_HAMMER}), name); break; case Epithet::WISDOM: grantGift(c, chooseRandom({ItemId::MUSHROOM_BOOK, ItemId::POTION_BOOK, ItemId::AMULET_BOOK}), name); break; case Epithet::DESTRUCTION: applyEffect(c, EffectType::DESTROY_EQUIPMENT, ""); break; case Epithet::SECRETS: grantGift(c, ItemId::INVISIBLE_POTION, name); break; case Epithet::LIGHTNING: c->bleed(0.9); c->you(MsgType::ARE, "struck by a lightning bolt!"); break; case Epithet::FEAR: applyEffect(c, EffectType::PANIC, name + " puts fear in your heart"); break; case Epithet::MIND: if (Random.roll(2)) applyEffect(c, EffectType::RAGE, name + " fills your head with anger"); else applyEffect(c, EffectType::HALLU, ""); break; case Epithet::CHANGE: if (Random.roll(2) && c->getEquipment().getItem(EquipmentSlot::WEAPON)) { PCreature snake = CreatureFactory::fromId(CreatureId::SNAKE, Tribes::get(TribeId::PEST)); for (Vec2 v : c->getPosition().neighbors8(true)) if (c->getLevel()->inBounds(v) && c->getLevel()->getSquare(v)->canEnter(snake.get())) { c->getLevel()->addCreature(v, std::move(snake)); c->steal({c->getEquipment().getItem(EquipmentSlot::WEAPON)}); c->privateMessage("Ouch!"); c->you(MsgType::YOUR, "weapon turns into a snake!"); break; } if (!snake) break; } for (Item* it : randomPermutation(c->getEquipment().getItems())) { if (it->getType() == ItemType::POTION) { c->privateMessage("Your " + it->getName() + " changes color!"); c->steal({it}); c->take(ItemFactory::potions().random()); break; } if (it->getType() == ItemType::SCROLL) { c->privateMessage("Your " + it->getName() + " changes label!"); c->steal({it}); c->take(ItemFactory::scrolls().random()); break; } if (it->getType() == ItemType::AMULET) { c->privateMessage("Your " + it->getName() + " changes shape!"); c->steal({it}); c->take(ItemFactory::amulets().random()); break; } } break; case Epithet::HEALTH: if (c->getHealth() < 1 || c->lostLimbs()) applyEffect(c, EffectType::HEAL, "You feel a healing power overcoming you"); else { if (Random.roll(4)) grantGift(c, ItemId::HEALING_AMULET, name); else grantGift(c, ItemId::HEALING_POTION, name, Random.getRandom(1, 4)); } break; case Epithet::NATURE: grantGift(c, ItemId::FRIENDLY_ANIMALS_AMULET, name); break; // case Epithet::LOVE: grantGift(c, ItemId::PANIC_MUSHROOM, name); break; case Epithet::WEALTH: grantGift(c, ItemId::GOLD_PIECE, name, Random.getRandom(100, 200)); break; case Epithet::DEFENSE: grantGift(c, ItemId::DEFENSE_AMULET, name); break; case Epithet::DARKNESS: applyEffect(c, EffectType::BLINDNESS, ""); break; case Epithet::CRAFTS: applyEffect(c, chooseRandom({EffectType::ENHANCE_ARMOR, EffectType::ENHANCE_WEAPON}), ""); break; // case Epithet::HUNTING: grantGift(c, ItemId::PANIC_MUSHROOM, name); break; default: noEffect = true; } usedEpithets.push_back(epithet); if (!noEffect) { prayerAnswered = true; break; } } if (!prayerAnswered) c->privateMessage("Your prayer is not answered."); }
AttackLevel CreatureAttributes::getRandomAttackLevel() const { return chooseRandom(getAttackLevels()); }