Fix wrong calculation for chance to stay unscathed with a slowing unit

Only a minor difference in most cases, but enough to trigger the Monte
Carlo simulation assertion.

Fixes #1810.
This commit is contained in:
Jyrki Vesterinen 2017-06-22 00:23:46 +03:00
parent 0f44669e59
commit edf7501043

View file

@ -280,6 +280,10 @@ public:
/// What is the chance that an indicated combatant (one of them) is at zero?
double prob_of_zero(bool check_a, bool check_b) const;
/// Sums the values in the specified row.
double row_sum(unsigned plane, unsigned row) const;
/// Sums the values in the specified column.
double col_sum(unsigned plane, unsigned column) const;
/// Sums the values in the specified plane.
void sum(unsigned plane, std::vector<double>& row_sums, std::vector<double>& col_sums) const;
@ -936,6 +940,30 @@ double prob_matrix::prob_of_zero(bool check_a, bool check_b) const
return prob;
}
/**
* Sums the values in the specified row.
*/
double prob_matrix::row_sum(unsigned plane, unsigned row) const
{
double sum = 0.0;
for(unsigned col : used_cols_[plane]) {
sum += val(plane, row, col);
}
return sum;
}
/**
* Sums the values in the specified column.
*/
double prob_matrix::col_sum(unsigned plane, unsigned column) const
{
double sum = 0.0;
for(unsigned row : used_rows_[plane]) {
sum += val(plane, row, column);
}
return sum;
}
/**
* Sums the values in the specified plane.
* The sum of each row is added to the corresponding entry in row_sums.
@ -1019,6 +1047,9 @@ public:
void forced_levelup_b();
void conditional_levelup_b();
using prob_matrix::row_sum;
using prob_matrix::col_sum;
// Its over, and here's the bill.
virtual void extract_results(
summary_t& summary_a, summary_t& summary_b)
@ -1816,6 +1847,15 @@ unsigned int fight_complexity(unsigned int num_slices,
* ((opp_stats.slows || stats.is_slowed) ? 2 : 1) * stats.max_hp * opp_stats.max_hp;
}
/**
* Returns the plane index for the slow/no-slow state of the combatants.
*/
unsigned int plane_index(const battle_context_unit_stats& stats,
const battle_context_unit_stats& opp_stats)
{
return (stats.is_slowed ? 1 : 0) | (opp_stats.is_slowed ? 2 : 0);
}
// Combat without chance of death, berserk, slow or drain is simple.
void no_death_fight(const battle_context_unit_stats& stats,
const battle_context_unit_stats& opp_stats,
@ -2057,6 +2097,19 @@ void complex_fight(attack_prediction_mode mode,
debug(("Combat ends:\n"));
pm->dump();
} while(--rounds && pm->dead_prob() < 0.99);
if(stats.slows) {
/* The calculation method for the "not hit" probability above is incorrect if either unit can slow.
* Because a slowed unit deals less damage, it is more likely for the slowing unit to be alive if it
* has hit the other unit. In that situation, the "not hit" probability can no longer be calculated
* with a simple multiplication.
* Instead, just fetch the probability from the combat matrix.
*/
opp_not_hit = pm->col_sum(plane_index(stats, opp_stats), opp_stats.hp);
}
if(opp_stats.slows) {
self_not_hit = pm->row_sum(plane_index(stats, opp_stats), stats.hp);
}
} else {
debug(("Using Monte Carlo simulation.\n"));