From 3b26cc15e34a9f92dc28924c5f6f5c2ed230600a Mon Sep 17 00:00:00 2001 From: Jyrki Vesterinen Date: Fri, 6 Jul 2018 22:52:34 +0300 Subject: [PATCH] Damage prediction: round very close slow probabilities to 0 or 1 In the case in bug #3321, damage prediction code somehow receives a combatant whose probability to be slowed is very close to one of those values but not quite it. I couldn't figure out how it's possible because only damage prediction code itself is supposed to emit slow probabilities, and it's not producing such a probability in this case. Without more information, I'm simply fixing the bug by force. If the probability is in the problematic area, we simply round it to 0 or 1. This way such probabilities are impossible later on when we try to scale the HP distributions so that they add to 1. Fixes #3321. (cherry-picked from commit 00d8548c24a70365f1b02116e129c8835dff206a) --- src/attack_prediction.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/attack_prediction.cpp b/src/attack_prediction.cpp index 99650dc3903..81706de3b0b 100644 --- a/src/attack_prediction.cpp +++ b/src/attack_prediction.cpp @@ -1820,6 +1820,16 @@ double calculate_probability_of_debuff(double initial_prob, bool enemy_gives, do return prob_debuff; } +// Rounds a probability that's extremely close to 0 or 1 to exactly 0 or 1. +void round_prob_if_close_to_sure(double& prob) +{ + if(prob < 1.0e-9) { + prob = 0.0; + } else if(prob > 1.0 - 1.0e-9) { + prob = 1.0; + } +} + /** * Returns the smallest HP we could possibly have based on the provided * hit point distribution. @@ -2309,6 +2319,10 @@ void combatant::fight(combatant& opponent, bool levelup_considered) double self_already_dead = hp_dist[0]; double opp_already_dead = opponent.hp_dist[0]; + // If incoming slow probabilities are extremely close to 0 or 1, round them to exactly 0 or 1 (bug #3321) + round_prob_if_close_to_sure(slowed); + round_prob_if_close_to_sure(opponent.slowed); + // If we've fought before and we have swarm, we might have to split the // calculation by number of attacks. const std::vector split = split_summary(u_, summary);