Code:
int getCombatOdds(CvUnit* pAttacker, CvUnit* pDefender)
{
// setup battle, calculate strengths and odds
//////
int iAttackerStrength = pAttacker->currCombatStr(NULL, NULL);
int iAttackerFirepower = pAttacker->currFirepower(NULL, NULL);
int iDefenderStrength = pDefender->currCombatStr(pDefender->plot(), pAttacker);
int iDefenderFirepower = pDefender->currFirepower(pDefender->plot(), pAttacker);
FAssert((iAttackerStrength + iDefenderStrength) > 0);
FAssert((iAttackerFirepower + iDefenderFirepower) > 0);
int iDefenderOdds = ((GC.getDefineINT("COMBAT_DIE_SIDES") * iDefenderStrength) / (iAttackerStrength + iDefenderStrength));
if (iDefenderOdds == 0)
{
return 1000;
}
int iAttackerOdds = GC.getDefineINT("COMBAT_DIE_SIDES") - iDefenderOdds;
if (iAttackerOdds == 0)
{
return 0;
}
int iStrengthFactor = ((iAttackerFirepower + iDefenderFirepower + 1) / 2);
// calculate damage done in one round
//////
int iDamageToAttacker = std::max(1,((GC.getDefineINT("COMBAT_DAMAGE") * (iDefenderFirepower + iStrengthFactor)) / (iAttackerFirepower + iStrengthFactor)));
int iDamageToDefender = std::max(1,((GC.getDefineINT("COMBAT_DAMAGE") * (iAttackerFirepower + iStrengthFactor)) / (iDefenderFirepower + iStrengthFactor)));
// calculate needed rounds.
// Needed rounds = round_up(health/damage)
//////
int iNeededRoundsAttacker = (std::max(0, pDefender->currHitPoints()) + iDamageToDefender - 1 ) / iDamageToDefender;
int iNeededRoundsDefender = (pAttacker->currHitPoints() + iDamageToAttacker - 1 ) / iDamageToAttacker;
int iMaxRounds = iNeededRoundsAttacker + iNeededRoundsDefender - 1;
float fOdds = 0;
for (int iI4 = iNeededRoundsAttacker; iI4 <= iMaxRounds; iI4++)
{
// odds of exactly iI4 out of (iMaxRounds - iI3) draws.
// f(k;n,p)=C(n,k)*(p^k)*((1-p)^(n-k))
// this needs to be in floating point math
//////
fOdds += ((float)getBinomialCoefficient(iMaxRounds, iI4)) * pow((((float)iAttackerOdds) / GC.getDefineINT("COMBAT_DIE_SIDES")), iI4) * pow((1.0f - (((float)iAttackerOdds) / GC.getDefineINT("COMBAT_DIE_SIDES"))), (iMaxRounds - iI4));
}
return ((int)(1000.0 * (fOdds + 0.0005f)));
}