From f4cd5aede38a820cc5ab7137b8cc1a0927ae7f3e Mon Sep 17 00:00:00 2001 From: zelgadis Date: Fri, 19 Dec 2008 20:29:26 +0000 Subject: First draft of god tension, and of Xom using tension. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7869 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/acr.cc | 8 +++ crawl-ref/source/religion.cc | 148 +++++++++++++++++++++++++++++++++++++++++++ crawl-ref/source/religion.h | 1 + crawl-ref/source/xom.cc | 29 ++++++--- 4 files changed, 177 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index 357ad38069..c64a720a74 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -3034,6 +3034,9 @@ static void _decrement_durations() if (_decrement_a_duration(DUR_DIVINE_STAMINA)) remove_divine_stamina(); + + _decrement_a_duration(DUR_REPEL_STAIRS_MOVE); + _decrement_a_duration(DUR_REPEL_STAIRS_CLIMB); } static void _check_banished() @@ -3240,6 +3243,11 @@ static void _world_reacts() if (you.cannot_act() && any_messages()) more(); + +#if DEBUG_TENSION || DEBUG_RELIGION + if (you.religion != GOD_NO_GOD) + mprf(MSGCH_DIAGNOSTICS, "TENSION = %d", get_tension()); +#endif } #ifdef DGL_SIMPLE_MESSAGING diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 1dddb3e31c..4dfead400b 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -6692,3 +6692,151 @@ bool tso_unchivalric_attack_safe_monster(const monsters *mon) || mons_is_evil(mon) || (holiness != MH_NATURAL && holiness != MH_HOLY)); } + +int get_tension(god_type god) +{ + ASSERT(god != GOD_NO_GOD); + + int total = 0; + + for (int midx = 0; midx < MAX_MONSTERS; midx++) + { + const monsters* mons = &menv[midx]; + + if (!mons->alive()) + continue; + + if (see_grid(mons->pos())) + ; // Monster is nearby + else + { + // Is the monster trying to get somewhere nearby? + coord_def target; + unsigned int travel_size = mons->travel_path.size(); + + if (travel_size > 0) + target = mons->travel_path[travel_size - 1]; + else + target = mons->target; + + // Monster is neither nearby nor trying to get near us. + if (!in_bounds(target) || !see_grid(target)) + continue; + } + + const mon_attitude_type att = mons_attitude(mons); + if (att == ATT_GOOD_NEUTRAL) + continue; + + if (mons_cannot_act(mons) || mons->asleep() || mons_is_fleeing(mons)) + { + continue; + } + + int exper = exper_value(mons); + if (exper <= 0) + continue; + + // Almost dead monsters don't count as much. + exper *= mons->hit_points; + exper /= mons->max_hit_points; + + const bool gift = mons_is_god_gift(mons, god); + + if (att == ATT_HOSTILE) + { + // God is punishing you with a hostile gift, so it doesn't + // count towards tension. + if (gift) + continue; + } + else if (att == ATT_FRIENDLY) + { + // Friendly monsters being around to help you reduce tension. + exper = -exper; + + // If it's a god gift it reduces tension even more, since the + // god is already helping you out. + if (gift) + exper *= 2; + } + else + // Neutral monsters aren't as much of a threat. + exper /= 2; + + if (att != ATT_FRIENDLY) + { + if (!mons_player_visible(mons)) + exper /= 2; + if (!player_monster_visible(mons)) + exper *= 2; + } + + if (mons->confused() || mons->caught()) + exper /= 2; + + if (mons->has_ench(ENCH_SLOW)) + { + exper *= 2; + exper /= 3; + } + + if (mons->has_ench(ENCH_HASTE)) + { + exper *= 3; + exper /= 2; + } + + if (mons->has_ench(ENCH_BERSERK)) + exper *= 2; + + total += exper; + } + const int scale = 1; + + int tension = total; + + // Tension goes up inversly proportional to the % of max hp you + // have. + tension *= (scale + 1) * you.hp_max; + tension /= you.hp_max + scale * you.hp; + + // Divides by 1 at level 1, 200 at level 27. + const int exp_lev = you.get_experience_level(); + const int exp_need = exp_needed(exp_lev + 1); + const int factor = ceil(sqrt(exp_need / 30.0)); + const int div = 1 + factor; + + tension /= div; + + if (you.level_type == LEVEL_ABYSS) + tension = std::max(2, tension); + + if (you.cannot_act()) + { + tension *= 10; + tension = std::max(1, tension); + + return (tension); + } + + if (you.confused()) + tension *= 2; + + if (you.caught()) + tension *= 2; + + if (you.duration[DUR_SLOW]) + { + tension *= 3; + tension /= 2; + } + + if (you.duration[DUR_HASTE]) + { + tension *= 2; + tension /= 3; + } + + return std::max(0, tension); +} diff --git a/crawl-ref/source/religion.h b/crawl-ref/source/religion.h index 1c8a4bac95..7390fdad73 100644 --- a/crawl-ref/source/religion.h +++ b/crawl-ref/source/religion.h @@ -139,4 +139,5 @@ bool god_likes_items(god_type god); void religion_turn_start(); +int get_tension(god_type god = you.religion); #endif diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc index 28d0f3dbcc..befb2ac002 100644 --- a/crawl-ref/source/xom.cc +++ b/crawl-ref/source/xom.cc @@ -707,7 +707,7 @@ static monster_type _xom_random_demon(int sever, bool use_greater_demons = true) } // The nicer stuff. Note: these things are not necessarily nice. -static bool _xom_is_good(int sever) +static bool _xom_is_good(int sever, int tension) { bool done = false; @@ -720,7 +720,8 @@ static bool _xom_is_good(int sever) // This series of random calls produces a poisson-looking // distribution: initial hump, plus a long-ish tail. - if (x_chance_in_y(2, sever)) + // Don't make player berserk if there's no danger. + if (tension > 0 && x_chance_in_y(2, sever)) { potion_type pot = static_cast( @@ -769,7 +770,8 @@ static bool _xom_is_good(int sever) } } } - else if (x_chance_in_y(5, sever)) + // Pointless to send in help if there's no danger. + else if (tension > 0 && x_chance_in_y(5, sever)) { // XXX: Can we clean up this ugliness, please? const int numdemons = @@ -1012,7 +1014,8 @@ static bool _xom_is_good(int sever) } } } - else if (x_chance_in_y(14, sever)) + // Pointless to send in help if there's no danger. + else if (tension > 0 && x_chance_in_y(14, sever)) { monster_type mon = _xom_random_demon(sever); const bool is_demonic = (mons_class_holiness(mon) == MH_DEMONIC); @@ -1089,7 +1092,7 @@ static bool _xom_is_good(int sever) return (done); } -static bool _xom_is_bad(int sever) +static bool _xom_is_bad(int sever, int tension) { bool done = false; @@ -1264,7 +1267,8 @@ static bool _xom_is_bad(int sever) } } } - else if (x_chance_in_y(11, sever)) + // Pointless to confuse player if there's no danger nearby. + else if (tension > 0 && x_chance_in_y(11, sever)) { std::string speech = _get_xom_speech("confusion"); if (confuse_player(random2(sever)+1, false)) { @@ -1395,11 +1399,12 @@ void xom_acts(bool niceness, int sever) sever = std::max(1, sever); + god_type which_god = GOD_XOM; // Drawing the Xom card from Nemelex's decks of oddities or punishment. if (crawl_state.is_god_acting() && crawl_state.which_god_acting() != GOD_XOM) { - god_type which_god = crawl_state.which_god_acting(); + which_god = crawl_state.which_god_acting(); if (crawl_state.is_god_retribution()) { @@ -1414,6 +1419,12 @@ void xom_acts(bool niceness, int sever) } } + const int tension = get_tension(which_god); + +#if DEBUG_RELIGION || DEBUG_XOM || DEBUG_TENSION + mprf(MSGCH_DIAGNOSTICS, "xom tension: %d", tension); +#endif + const dungeon_feature_type orig_feat = grd(you.pos()); const int orig_hp = you.hp; @@ -1428,13 +1439,13 @@ void xom_acts(bool niceness, int sever) if (niceness && !one_chance_in(5)) { // Good stuff. - while (!_xom_is_good(sever)) + while (!_xom_is_good(sever, tension)) ; } else { // Bad mojo. - while (!_xom_is_bad(sever)) + while (!_xom_is_bad(sever, tension)) ; } -- cgit v1.2.3-54-g00ecf