From 7f9df2ef6f59c408d4bc089972735e887db201f6 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 17 May 2024 12:23:51 +0000 Subject: [PATCH] Tweaks to retaliation damage calculation: - method now uses early returns to avoid deeply nested if's - assume that retaliation damage is zero if target will die from attack - account for BLOCKS_RETALIATION bonus when computing whether target will retaliate --- lib/battle/CBattleInfoCallback.cpp | 58 ++++++++++++++++-------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/lib/battle/CBattleInfoCallback.cpp b/lib/battle/CBattleInfoCallback.cpp index 15cd933c9..c5f578412 100644 --- a/lib/battle/CBattleInfoCallback.cpp +++ b/lib/battle/CBattleInfoCallback.cpp @@ -760,37 +760,43 @@ DamageEstimation CBattleInfoCallback::battleEstimateDamage(const BattleAttackInf DamageEstimation ret = calculateDmgRange(bai); - if(retaliationDmg && bai.defender->ableToRetaliate()) + if(retaliationDmg == nullptr) + return ret; + + *retaliationDmg = DamageEstimation(); + + if(bai.shooting) //FIXME: handle RANGED_RETALIATION + return ret; + + if (!bai.defender->ableToRetaliate()) + return ret; + + if (bai.attacker->hasBonusOfType(BonusType::BLOCKS_RETALIATION)) + return ret; + + //TODO: rewrite using boost::numeric::interval + //TODO: rewire once more using interval-based fuzzy arithmetic + + const auto & estimateRetaliation = [&](int64_t damage) { - if(bai.shooting) - { - //FIXME: handle RANGED_RETALIATION - *retaliationDmg = DamageEstimation(); - } + auto retaliationAttack = bai.reverse(); + auto state = retaliationAttack.attacker->acquireState(); + state->damage(damage); + retaliationAttack.attacker = state.get(); + if (state->alive()) + return calculateDmgRange(retaliationAttack); else - { - //TODO: rewrite using boost::numeric::interval - //TODO: rewire once more using interval-based fuzzy arithmetic + return DamageEstimation(); + }; - const auto & estimateRetaliation = [&](int64_t damage) - { - auto retaliationAttack = bai.reverse(); - auto state = retaliationAttack.attacker->acquireState(); - state->damage(damage); - retaliationAttack.attacker = state.get(); - return calculateDmgRange(retaliationAttack); - }; + DamageEstimation retaliationMin = estimateRetaliation(ret.damage.min); + DamageEstimation retaliationMax = estimateRetaliation(ret.damage.max); - DamageEstimation retaliationMin = estimateRetaliation(ret.damage.min); - DamageEstimation retaliationMax = estimateRetaliation(ret.damage.max); + retaliationDmg->damage.min = std::min(retaliationMin.damage.min, retaliationMax.damage.min); + retaliationDmg->damage.max = std::max(retaliationMin.damage.max, retaliationMax.damage.max); - retaliationDmg->damage.min = std::min(retaliationMin.damage.min, retaliationMax.damage.min); - retaliationDmg->damage.max = std::max(retaliationMin.damage.max, retaliationMax.damage.max); - - retaliationDmg->kills.min = std::min(retaliationMin.kills.min, retaliationMax.kills.min); - retaliationDmg->kills.max = std::max(retaliationMin.kills.max, retaliationMax.kills.max); - } - } + retaliationDmg->kills.min = std::min(retaliationMin.kills.min, retaliationMax.kills.min); + retaliationDmg->kills.max = std::max(retaliationMin.kills.max, retaliationMax.kills.max); return ret; }