diff options
-rw-r--r-- | crawl-ref/source/xom.cc | 257 |
1 files changed, 147 insertions, 110 deletions
diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc index 5cf9dff5a8..5ef6dd3a88 100644 --- a/crawl-ref/source/xom.cc +++ b/crawl-ref/source/xom.cc @@ -728,156 +728,193 @@ static bool _player_is_dead() || you.did_escape_death()); } -// The nicer stuff. Note: these things are not necessarily nice. -static bool _xom_is_good(int sever, int tension) +static bool _xom_do_potion() { - bool done = false; + bool rc = false; + potion_type pot = + static_cast<potion_type>( + random_choose(POT_HEALING, POT_HEAL_WOUNDS, POT_SPEED, + POT_MIGHT, POT_INVISIBILITY, POT_BERSERK_RAGE, + POT_EXPERIENCE, -1)); - // Did Xom (already) kill the player? - if (_player_is_dead()) - return (true); + if (pot == POT_EXPERIENCE && !one_chance_in(6)) + pot = POT_BERSERK_RAGE; - god_acting gdact(GOD_XOM); + if (pot != POT_BERSERK_RAGE || you.can_go_berserk(false)) + { + god_speaks(GOD_XOM, _get_xom_speech("potion effect").c_str()); - // This series of random calls produces a poisson-looking - // distribution: initial hump, plus a long-ish tail. + if (pot == POT_BERSERK_RAGE) + you.berserk_penalty = NO_BERSERK_PENALTY; - // Don't make the player berserk if there's no danger. - if (tension > 0 && x_chance_in_y(2, sever)) - { - potion_type pot = - static_cast<potion_type>( - random_choose(POT_HEALING, POT_HEAL_WOUNDS, POT_SPEED, - POT_MIGHT, POT_INVISIBILITY, POT_BERSERK_RAGE, - POT_EXPERIENCE, -1)); + potion_effect(pot, 150); - if (pot == POT_EXPERIENCE && !one_chance_in(6)) - pot = POT_BERSERK_RAGE; + rc = true; + } + return (rc); +} - if (pot != POT_BERSERK_RAGE || you.can_go_berserk(false)) - { - god_speaks(GOD_XOM, _get_xom_speech("potion effect").c_str()); +static bool _xom_confuse_monsters(int sever) +{ + bool rc = false; + monsters *monster; + for (unsigned i = 0; i < MAX_MONSTERS; ++i) + { + monster = &menv[i]; - if (pot == POT_BERSERK_RAGE) - you.berserk_penalty = NO_BERSERK_PENALTY; + if (monster->type == -1 || !mons_near(monster) + || mons_wont_attack(monster) + || !mons_class_is_confusable(monster->type) + || one_chance_in(20)) + { + continue; + } - potion_effect(pot, 150); + if (monster->add_ench(mon_enchant(ENCH_CONFUSION, 0, + KC_FRIENDLY, random2(sever)))) + { + if (!rc) + god_speaks(GOD_XOM, _get_xom_speech("confusion").c_str()); - done = true; + simple_monster_message(monster, " looks rather confused."); + rc = true; } } - else if (x_chance_in_y(3, sever)) - { - _xom_makes_you_cast_random_spell(sever); + return (rc); +} - done = true; - } - else if (x_chance_in_y(4, sever)) - { - monsters *monster; - for (unsigned i = 0; i < MAX_MONSTERS; ++i) - { - monster = &menv[i]; - if (monster->type == -1 || !mons_near(monster) - || mons_wont_attack(monster) - || !mons_class_is_confusable(monster->type) - || one_chance_in(20)) - { - continue; - } +static bool _xom_send_allies(int sever) +{ + bool rc = false; + const int numdemons = + std::min(random2(random2(random2(sever+1)+1)+1)+2, 16); + int numdifferent = 0; - if (monster->add_ench(mon_enchant(ENCH_CONFUSION, 0, KC_FRIENDLY, random2(sever)))) - { - if (!done) - god_speaks(GOD_XOM, _get_xom_speech("confusion").c_str()); + // If we have a mix of demons and non-demons, there's a chance + // that one or both of the factions may be hostile. + int hostiletype = random_choose_weighted(3, 0, // both friendly + 4, 1, // one hostile + 4, 2, // other hostile + 1, 3, // both hostile + 0); - simple_monster_message(monster, " looks rather confused."); - done = true; - } - } - } - // It's pointless to send in help if there's no danger. - else if (tension > 0 && x_chance_in_y(5, sever)) - { - // FIXME: Can we clean up this ugliness, please? - const int numdemons = - std::min(random2(random2(random2(sever+1)+1)+1)+2, 16); - int numdifferent = 0; + std::vector<bool> is_demonic(numdemons, false); + std::vector<int> summons(numdemons); - // If we have a mix of demons and non-demons, there's a chance - // that one or both of the factions may be hostile. - int hostiletype = random_choose_weighted(3, 0, // both friendly - 4, 1, // one hostile - 4, 2, // other hostile - 1, 3, // both hostile - 0); + int num_actually_summoned = 0; - std::vector<bool> is_demonic(numdemons); - std::vector<int> summons(numdemons); + for (int i = 0; i < numdemons; ++i) + { + monster_type monster = _xom_random_demon(sever); - bool success = false; + summons[i] = + create_monster( + mgen_data(monster, BEH_FRIENDLY, + 3, MON_SUMM_AID, + you.pos(), you.pet_target, + MG_FORCE_BEH, GOD_XOM)); - for (int i = 0; i < numdemons; ++i) + if (summons[i] != -1) { - monster_type monster = _xom_random_demon(sever); - + num_actually_summoned++; is_demonic[i] = (mons_class_holiness(monster) == MH_DEMONIC); // If it's not a demon, Xom got it someplace else, so use // different messages below. if (!is_demonic[i]) numdifferent++; + } + } - summons[i] = - create_monster( - mgen_data(monster, BEH_FRIENDLY, - 3, MON_SUMM_AID, - you.pos(), you.pet_target, - MG_FORCE_BEH, GOD_XOM)); + if (num_actually_summoned) + { + const bool only_holy = (numdifferent == num_actually_summoned); + const bool only_demonic = (numdifferent == 0); - if (summons[i] != -1) - success = true; + if (only_holy) + { + god_speaks(GOD_XOM, + _get_xom_speech("multiple holy summons").c_str()); } + else if (only_demonic) + { + god_speaks(GOD_XOM, + _get_xom_speech("multiple summons").c_str()); + } + else + { + god_speaks(GOD_XOM, + _get_xom_speech("multiple mixed summons").c_str()); + } + + // If we have only non-demons, there's a chance that they + // may be hostile. + if (only_holy && one_chance_in(4)) + hostiletype = 2; + // If we have only demons, they'll always be friendly. + else if (only_demonic) + hostiletype = 0; - if (success) + for (int i = 0; i < numdemons; ++i) { - if (numdifferent == numdemons) - god_speaks(GOD_XOM, _get_xom_speech("multiple holy summons").c_str()); - else if (numdifferent > 0) - god_speaks(GOD_XOM, _get_xom_speech("multiple mixed summons").c_str()); - else - god_speaks(GOD_XOM, _get_xom_speech("multiple summons").c_str()); + if (summons[i] == -1) + continue; - // If we have only non-demons, there's a chance that they - // may be hostile. - if (numdifferent == numdemons && one_chance_in(4)) - hostiletype = 2; - // If we have only demons, they'll always be friendly. - else if (numdifferent == 0) - hostiletype = 0; + monsters *mon = &menv[summons[i]]; - for (int i = 0; i < numdemons; ++i) + if (hostiletype != 0) { - monsters *mon = &menv[summons[i]]; - - if (hostiletype != 0) + // Mark factions hostile as appropriate. + if (hostiletype == 3 + || (is_demonic[i] && hostiletype == 1) + || (!is_demonic[i] && hostiletype == 2)) { - // Mark factions hostile as appropriate. - if (hostiletype == 3 - || (is_demonic[i] && hostiletype == 1) - || (!is_demonic[i] && hostiletype == 2)) - { - mon->attitude = ATT_HOSTILE; - behaviour_event(mon, ME_ALERT, MHITYOU); - } + mon->attitude = ATT_HOSTILE; + behaviour_event(mon, ME_ALERT, MHITYOU); } - - player_angers_monster(mon); } - done = true; + player_angers_monster(mon); } + + rc = true; + } + return (rc); +} + +// The nicer stuff. Note: these things are not necessarily nice. +static bool _xom_is_good(int sever, int tension) +{ + bool done = false; + + // Did Xom (already) kill the player? + if (_player_is_dead()) + return (true); + + god_acting gdact(GOD_XOM); + + // This series of random calls produces a poisson-looking + // distribution: initial hump, plus a long-ish tail. + + // Don't make the player berserk if there's no danger. + if (tension > 0 && x_chance_in_y(2, sever)) + { + done = _xom_do_potion(); + } + else if (x_chance_in_y(3, sever)) + { + _xom_makes_you_cast_random_spell(sever); + done = true; + } + else if (x_chance_in_y(4, sever)) + { + done = _xom_confuse_monsters(sever); + } + // It's pointless to send in help if there's no danger. + else if (tension > 0 && x_chance_in_y(5, sever)) + { + done = _xom_send_allies(sever); } else if (x_chance_in_y(6, sever)) { |