AI Combat Odds

The Great Apple

Big Cheese
Joined
Mar 24, 2002
Messages
3,361
Location
Oxford, England
So, I've been poking through the AI combat odds mechanism, comparing Warlords to Vanilla, and to what the human sees, and I have to admit I'm quite suprised at what I see.

Now as far as I am aware combat hasn't changed at all between 1.61 and Warlords. The human combat odds calculater hasn't changed at all, so I think this assumption is probably valid.

A comparison:

Vanilla AI:
Doesn't seem to have been updated to 1.52. As far as I can tell it gets the odds completely wrong, as there was a major change in the way combat works in 1.52. Pre 1.52 a strength 10 unit fighting a strength 5 unit would have a 66% chance of victory (post 1.52 it's ~ 99%). This was changed to be much more in favour of the higher strength unit, but the AI attack odds have not been updated. This means that the AI is overly causious when attacking with overwhealming odds, and overly optimistic when attacking with poor odds.

Spoiler Vanilla AI Code :
Code:
// Returns attack odds out of 100 (the higher, the better...)
int CvUnitAI::AI_attackOdds(const CvPlot* pPlot, bool bPotentialEnemy) const
{
	CvUnit* pDefender;
	int iOurStrength;
	int iTheirStrength;

	pDefender = pPlot->getBestDefender(NO_PLAYER, getOwnerINLINE(), this, !bPotentialEnemy, bPotentialEnemy);

	if (pDefender == NULL)
	{
		return 100;
	}

	iOurStrength = ((getDomainType() == DOMAIN_AIR) ? airCurrCombatStr() : currCombatStr(NULL, NULL));

	if (iOurStrength == 0)
	{
		return 0;
	}

	iTheirStrength = pDefender->currCombatStr(pPlot, this);

	if (getDomainType() != DOMAIN_AIR)
	{
		if (!(pDefender->immuneToFirstStrikes()))
		{
			iOurStrength *= ((((firstStrikes() * 2) + chanceFirstStrikes()) * ((GC.getDefineINT("COMBAT_DAMAGE") * 2) / 5)) + 100);
			iOurStrength /= 100;
		}
		if (!immuneToFirstStrikes())
		{
			iTheirStrength *= ((((pDefender->firstStrikes() * 2) + pDefender->chanceFirstStrikes()) * ((GC.getDefineINT("COMBAT_DAMAGE") * 2) / 5)) + 100);
			iTheirStrength /= 100;
		}
	}

	return (((iOurStrength * 100) / (iOurStrength + iTheirStrength)) + GET_PLAYER(getOwnerINLINE()).AI_getAttackOddsChange());
}
As you can see, ignoring first strikes gives us simply ((iOurStrength * 100) / (iOurStrength + iTheirStrength)) as the base (before the AI modifiers which are a combination of random numbers and leader behaviour)


Warlords AI:
Seems to have been updated to use the firepower method of calculating odds. As far as I can tell it's alot more accurate. This may be the cause of the vast improvements in the AI's military ability in Warlords - because it actually knows what it's chances of success are.

Human odds:
Excatly the same in both Warlords and Vanilla. Pretty similar to the Walords AI code, but calcualtes everything in a bit more detail. These are the true odds I think.
 
Ok. I've done some tests and the above post seems to be correct. I've done combats over a range of strengths, and here are the results:

Code:
------ Combat odds -------
Attacker strength: 1800 
Defender strength: 880 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 67
Warlords AI calculated Combat odds: 91
------ Combat odds -------
Attacker strength: 1800 
Defender strength: 660 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 73
Warlords AI calculated Combat odds: 94
------ Combat odds -------
Attacker strength: 1800 
Defender strength: 2700 
Human calculated Combat odds: 9
Vanilla AI calculated Combat odds: 40
Warlords AI calculated Combat odds: 18
------ Combat odds -------
Attacker strength: 1800 
Defender strength: 440 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 80
Warlords AI calculated Combat odds: 97
------ Combat odds -------
Attacker strength: 1800 
Defender strength: 3520 
Human calculated Combat odds: 1
Vanilla AI calculated Combat odds: 33
Warlords AI calculated Combat odds: 9
------ Combat odds -------
Attacker strength: 1800 
Defender strength: 660 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 73
Warlords AI calculated Combat odds: 94
------ Combat odds -------
Attacker strength: 1800 
Defender strength: 1000 
Human calculated Combat odds: 97
Vanilla AI calculated Combat odds: 64
Warlords AI calculated Combat odds: 87
------ Combat odds -------
Attacker strength: 1800 
Defender strength: 220 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 89
Warlords AI calculated Combat odds: 98
------ Combat odds -------
Attacker strength: 1800 
Defender strength: 3520 
Human calculated Combat odds: 1
Vanilla AI calculated Combat odds: 33
Warlords AI calculated Combat odds: 9
------ Combat odds -------
Attacker strength: 600 
Defender strength: 1280 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 31
Warlords AI calculated Combat odds: 8
------ Combat odds -------
Attacker strength: 600 
Defender strength: 660 
Human calculated Combat odds: 31
Vanilla AI calculated Combat odds: 47
Warlords AI calculated Combat odds: 31
------ Combat odds -------
Attacker strength: 600 
Defender strength: 2200 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 21
Warlords AI calculated Combat odds: 3
------ Combat odds -------
Attacker strength: 600 
Defender strength: 440 
Human calculated Combat odds: 79
Vanilla AI calculated Combat odds: 57
Warlords AI calculated Combat odds: 73
------ Combat odds -------
Attacker strength: 600 
Defender strength: 3520 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 14
Warlords AI calculated Combat odds: 1
------ Combat odds -------
Attacker strength: 600 
Defender strength: 660 
Human calculated Combat odds: 31
Vanilla AI calculated Combat odds: 47
Warlords AI calculated Combat odds: 31
------ Combat odds -------
Attacker strength: 600 
Defender strength: 500 
Human calculated Combat odds: 72
Vanilla AI calculated Combat odds: 54
Warlords AI calculated Combat odds: 70
------ Combat odds -------
Attacker strength: 600 
Defender strength: 3520 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 14
Warlords AI calculated Combat odds: 1
------ Combat odds -------
Attacker strength: 500 
Defender strength: 1280 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 28
Warlords AI calculated Combat odds: 6
------ Combat odds -------
Attacker strength: 500 
Defender strength: 660 
Human calculated Combat odds: 22
Vanilla AI calculated Combat odds: 43
Warlords AI calculated Combat odds: 27
------ Combat odds -------
Attacker strength: 500 
Defender strength: 2200 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 18
Warlords AI calculated Combat odds: 2
------ Combat odds -------
Attacker strength: 500 
Defender strength: 440 
Human calculated Combat odds: 69
Vanilla AI calculated Combat odds: 53
Warlords AI calculated Combat odds: 69
------ Combat odds -------
Attacker strength: 500 
Defender strength: 3520 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 12
Warlords AI calculated Combat odds: 1
------ Combat odds -------
Attacker strength: 500 
Defender strength: 660 
Human calculated Combat odds: 22
Vanilla AI calculated Combat odds: 43
Warlords AI calculated Combat odds: 27
------ Combat odds -------
Attacker strength: 500 
Defender strength: 500 
Human calculated Combat odds: 50
Vanilla AI calculated Combat odds: 50
Warlords AI calculated Combat odds: 50
------ Combat odds -------
Attacker strength: 500 
Defender strength: 3520 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 12
Warlords AI calculated Combat odds: 1
------ Combat odds -------
Attacker strength: 800 
Defender strength: 880 
Human calculated Combat odds: 44
Vanilla AI calculated Combat odds: 54
Warlords AI calculated Combat odds: 31
------ Combat odds -------
Attacker strength: 800 
Defender strength: 428 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 71
Warlords AI calculated Combat odds: 91
------ Combat odds -------
Attacker strength: 800 
Defender strength: 2200 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 32
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 800 
Defender strength: 285 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 78
Warlords AI calculated Combat odds: 95
------ Combat odds -------
Attacker strength: 800 
Defender strength: 3520 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 23
Warlords AI calculated Combat odds: 2
------ Combat odds -------
Attacker strength: 800 
Defender strength: 428 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 71
Warlords AI calculated Combat odds: 91
------ Combat odds -------
Attacker strength: 800 
Defender strength: 1000 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 600 
Defender strength: 1280 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 31
Warlords AI calculated Combat odds: 8
------ Combat odds -------
Attacker strength: 600 
Defender strength: 660 
Human calculated Combat odds: 31
Vanilla AI calculated Combat odds: 47
Warlords AI calculated Combat odds: 31
------ Combat odds -------
Attacker strength: 600 
Defender strength: 2200 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 21
Warlords AI calculated Combat odds: 3
------ Combat odds -------
Attacker strength: 600 
Defender strength: 1280 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 31
Warlords AI calculated Combat odds: 8
------ Combat odds -------
Attacker strength: 600 
Defender strength: 660 
Human calculated Combat odds: 31
Vanilla AI calculated Combat odds: 47
Warlords AI calculated Combat odds: 31
------ Combat odds -------
Attacker strength: 600 
Defender strength: 1280 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 31
Warlords AI calculated Combat odds: 8
------ Combat odds -------
Attacker strength: 600 
Defender strength: 660 
Human calculated Combat odds: 31
Vanilla AI calculated Combat odds: 47
Warlords AI calculated Combat odds: 31
------ Combat odds -------
Attacker strength: 600 
Defender strength: 2200 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 21
Warlords AI calculated Combat odds: 3
------ Combat odds -------
Attacker strength: 600 
Defender strength: 440 
Human calculated Combat odds: 79
Vanilla AI calculated Combat odds: 57
Warlords AI calculated Combat odds: 73
------ Combat odds -------
Attacker strength: 600 
Defender strength: 3520 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 14
Warlords AI calculated Combat odds: 1
------ Combat odds -------
Attacker strength: 600 
Defender strength: 660 
Human calculated Combat odds: 31
Vanilla AI calculated Combat odds: 47
Warlords AI calculated Combat odds: 31
------ Combat odds -------
Attacker strength: 600 
Defender strength: 1000 
Human calculated Combat odds: 3
Vanilla AI calculated Combat odds: 37
Warlords AI calculated Combat odds: 13
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 660 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 80
Warlords AI calculated Combat odds: 97
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 1000 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 73
Warlords AI calculated Combat odds: 94
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 1000 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 73
Warlords AI calculated Combat odds: 94
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 880 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 76
Warlords AI calculated Combat odds: 96
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 660 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 80
Warlords AI calculated Combat odds: 97
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 2200 
Human calculated Combat odds: 75
Vanilla AI calculated Combat odds: 56
Warlords AI calculated Combat odds: 71
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 440 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 86
Warlords AI calculated Combat odds: 98
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 660 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 80
Warlords AI calculated Combat odds: 97
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 1000 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 73
Warlords AI calculated Combat odds: 94
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 440 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 86
Warlords AI calculated Combat odds: 98
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 660 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 80
Warlords AI calculated Combat odds: 97
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 1000 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 73
Warlords AI calculated Combat odds: 94
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 660 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 80
Warlords AI calculated Combat odds: 97
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 1000 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 73
Warlords AI calculated Combat odds: 94
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 880 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 76
Warlords AI calculated Combat odds: 96
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 660 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 80
Warlords AI calculated Combat odds: 97
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 2200 
Human calculated Combat odds: 75
Vanilla AI calculated Combat odds: 56
Warlords AI calculated Combat odds: 71
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 440 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 86
Warlords AI calculated Combat odds: 98
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 660 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 80
Warlords AI calculated Combat odds: 97
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 1000 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 73
Warlords AI calculated Combat odds: 94
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 440 
Defender strength: 600 
Human calculated Combat odds: 20
Vanilla AI calculated Combat odds: 42
Warlords AI calculated Combat odds: 26
------ Combat odds -------
Attacker strength: 880 
Defender strength: 800 
Human calculated Combat odds: 55
Vanilla AI calculated Combat odds: 45
Warlords AI calculated Combat odds: 68
------ Combat odds -------
Attacker strength: 880 
Defender strength: 400 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 68
Warlords AI calculated Combat odds: 91
------ Combat odds -------
Attacker strength: 660 
Defender strength: 1200 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 29
Warlords AI calculated Combat odds: 8
------ Combat odds -------
Attacker strength: 660 
Defender strength: 600 
Human calculated Combat odds: 67
Vanilla AI calculated Combat odds: 52
Warlords AI calculated Combat odds: 68
------ Combat odds -------
Attacker strength: 660 
Defender strength: 600 
Human calculated Combat odds: 67
Vanilla AI calculated Combat odds: 52
Warlords AI calculated Combat odds: 68
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 1656 
Human calculated Combat odds: 3
Vanilla AI calculated Combat odds: 37
Warlords AI calculated Combat odds: 13
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 1656 
Human calculated Combat odds: 3
Vanilla AI calculated Combat odds: 37
Warlords AI calculated Combat odds: 13
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 1656 
Human calculated Combat odds: 3
Vanilla AI calculated Combat odds: 37
Warlords AI calculated Combat odds: 13
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2800 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 26
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 1656 
Defender strength: 440 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 79
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 1656 
Defender strength: 3520 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 31
Warlords AI calculated Combat odds: 8
------ Combat odds -------
Attacker strength: 1656 
Defender strength: 1000 
Human calculated Combat odds: 96
Vanilla AI calculated Combat odds: 62
Warlords AI calculated Combat odds: 86
------ Combat odds -------
Attacker strength: 1656 
Defender strength: 3520 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 31
Warlords AI calculated Combat odds: 8
------ Combat odds -------
Attacker strength: 600 
Defender strength: 1280 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 31
Warlords AI calculated Combat odds: 8
------ Combat odds -------
Attacker strength: 600 
Defender strength: 660 
Human calculated Combat odds: 31
Vanilla AI calculated Combat odds: 47
Warlords AI calculated Combat odds: 31
------ Combat odds -------
Attacker strength: 600 
Defender strength: 2200 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 21
Warlords AI calculated Combat odds: 3
------ Combat odds -------
Attacker strength: 600 
Defender strength: 440 
Human calculated Combat odds: 79
Vanilla AI calculated Combat odds: 57
Warlords AI calculated Combat odds: 73
------ Combat odds -------
Attacker strength: 600 
Defender strength: 3520 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 14
Warlords AI calculated Combat odds: 1
------ Combat odds -------
Attacker strength: 600 
Defender strength: 1280 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 31
Warlords AI calculated Combat odds: 8
------ Combat odds -------
Attacker strength: 600 
Defender strength: 660 
Human calculated Combat odds: 31
Vanilla AI calculated Combat odds: 47
Warlords AI calculated Combat odds: 31
------ Combat odds -------
Attacker strength: 600 
Defender strength: 2200 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 21
Warlords AI calculated Combat odds: 3
------ Combat odds -------
Attacker strength: 600 
Defender strength: 1280 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 31
Warlords AI calculated Combat odds: 8
------ Combat odds -------
Attacker strength: 600 
Defender strength: 660 
Human calculated Combat odds: 31
Vanilla AI calculated Combat odds: 47
Warlords AI calculated Combat odds: 31
------ Combat odds -------
Attacker strength: 600 
Defender strength: 1280 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 31
Warlords AI calculated Combat odds: 8
------ Combat odds -------
Attacker strength: 600 
Defender strength: 660 
Human calculated Combat odds: 31
Vanilla AI calculated Combat odds: 47
Warlords AI calculated Combat odds: 31
------ Combat odds -------
Attacker strength: 600 
Defender strength: 2200 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 21
Warlords AI calculated Combat odds: 3
------ Combat odds -------
Attacker strength: 600 
Defender strength: 440 
Human calculated Combat odds: 79
Vanilla AI calculated Combat odds: 57
Warlords AI calculated Combat odds: 73
------ Combat odds -------
Attacker strength: 600 
Defender strength: 3520 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 14
Warlords AI calculated Combat odds: 1
------ Combat odds -------
Attacker strength: 500 
Defender strength: 1280 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 28
Warlords AI calculated Combat odds: 6
------ Combat odds -------
Attacker strength: 500 
Defender strength: 660 
Human calculated Combat odds: 22
Vanilla AI calculated Combat odds: 43
Warlords AI calculated Combat odds: 27
------ Combat odds -------
Attacker strength: 500 
Defender strength: 2200 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 18
Warlords AI calculated Combat odds: 2
------ Combat odds -------
Attacker strength: 500 
Defender strength: 440 
Human calculated Combat odds: 69
Vanilla AI calculated Combat odds: 53
Warlords AI calculated Combat odds: 69
------ Combat odds -------
Attacker strength: 500 
Defender strength: 3520 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 12
Warlords AI calculated Combat odds: 1
------ Combat odds -------
Attacker strength: 800 
Defender strength: 880 
Human calculated Combat odds: 44
Vanilla AI calculated Combat odds: 54
Warlords AI calculated Combat odds: 31
------ Combat odds -------
Attacker strength: 800 
Defender strength: 428 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 71
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 800 
Defender strength: 2200 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 32
Warlords AI calculated Combat odds: 5
------ Combat odds -------
Attacker strength: 800 
Defender strength: 285 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 78
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 800 
Defender strength: 3520 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 23
Warlords AI calculated Combat odds: 2
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 440 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 86
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 1000 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 73
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 440 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 86
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 1000 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 73
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 880 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 76
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 660 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 80
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 2200 
Human calculated Combat odds: 75
Vanilla AI calculated Combat odds: 56
Warlords AI calculated Combat odds: 71
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 1000 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 73
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 2200 
Human calculated Combat odds: 75
Vanilla AI calculated Combat odds: 56
Warlords AI calculated Combat odds: 71
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 1000 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 73
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 880 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 76
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 660 
Human calculated Combat odds: 100
Vanilla AI calculated Combat odds: 80
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 2200 
Human calculated Combat odds: 75
Vanilla AI calculated Combat odds: 56
Warlords AI calculated Combat odds: 71
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 1000 
Human calculated Combat odds: 99
Vanilla AI calculated Combat odds: 73
Warlords AI calculated Combat odds: 89
------ Combat odds -------
Attacker strength: 2800 
Defender strength: 3520 
Human calculated Combat odds: 24
Vanilla AI calculated Combat odds: 44
Warlords AI calculated Combat odds: 28
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2000 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 33
Warlords AI calculated Combat odds: 9
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2000 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 33
Warlords AI calculated Combat odds: 9
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2000 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 33
Warlords AI calculated Combat odds: 9
------ Combat odds -------
Attacker strength: 1000 
Defender strength: 2000 
Human calculated Combat odds: 0
Vanilla AI calculated Combat odds: 33
Warlords AI calculated Combat odds: 9

Warlords AI is pretty accurate, although slightly normailzed, Vanilla AI is still very normalized toward 50%.

This, as above, means that the Vanilla AI will beleive a combat which is doomed to failure actually has a chance of success, as well as believing almost certain wins to have some doubt in them. While I'm not sure it's really leagal to just copy the Walords AI odds caluclator over the top of the vanilla one (Walords SDK isn't available to free download), I would certainly advise changing this function to more accurately represent the way that the human odds are calculated.
 
While I'm not sure it's really leagal to just copy the Walords AI odds caluclator over the top of the vanilla one

hmm.. very interesting. Unfortunate that we cant get the Warlords SDK, but... can't someone just make a mod that replaces the vanilla?
 
This sounds like something that Sid, Firaxis and Take2 would want to fix if they knew about it, no?
:confused:
 
sidwannabe said:
This sounds like something that Sid, Firaxis and Take2 would want to fix if they knew about it, no?
:confused:

They know about it. They fixed it in Warlords.

I doubt there will be any more patches to vanilla civ, if you want improved AI, you are going to have to get Warlords.

-Iustus
 
or paste over the relevant lines of AI code, many mods arent quite ready to migrate yet.
 
Wow. Great find, TGA. I've had a lot of commentary in my mod that that AI has been particularly, well, lame for lack of a better word.

But looking at the code it's obvious they were miscalculating. This will make a lot of vanilla players happy...
 
Okay, so in an effort to help fix this, I've poked around a bit myself and I think this will provide a 90% or-so fix for this. I haven't loaded up Warlords yet and haven't been able to look at the code therein, so this shouldn't create any legal issues.

Based on my understanding the current 1.61 combat system calculates strength based on (current strength + maximum strength)/2, instead of the previous current strength only.

That being said if you just include that in the function it should bring the odds much closer to the "true" odds being calculated:

Code:
int CvUnitAI::AI_attackOdds(const CvPlot* pPlot, bool bPotentialEnemy) const
{
	CvUnit* pDefender;
	int iOurStrength;
	int iTheirStrength;

	pDefender = pPlot->getBestDefender(NO_PLAYER, getOwnerINLINE(), this, !bPotentialEnemy, bPotentialEnemy);

	if (pDefender == NULL)
	{
		return 100;
	}

	[B]iOurStrength = ((getDomainType() == DOMAIN_AIR) ? airCurrCombatStr() : int((currCombatStr(NULL, NULL) + currFirepower(NULL,NULL))/2)  );[/B]

	if (iOurStrength == 0)
	{
		return 0;
	}

	[B]iTheirStrength = int((pDefender->currCombatStr(pPlot, this) + pDefender->currFirepower(pPlot, this)) /2 );[/B]

...so on


Does this seem about right? The human calculated odds, as you stated TGA, are much more complex and take much closer account of the first strike system and whatnot. I originally wanted to use the function getCombatOdds() to replace this function altogether, but the CvUnitAI* pointer didn't want to play nice as a CvUnit* called for in the function and I didn't think the getCombatOdds function would port over to the CvUnitAI class easily. I figure the fix above should be close enough.

Any thoughts?
 
I managed to get getCombatOdds working fine. I can't quite remember how I did it, but it was easy enough. I think the reason they don't use it is because there are quite a few places where odds are calcualted for each unit each turn and the accuracy isn't needed.

That change you made certainly looks better then the original.
 
The Great Apple said:
I managed to get getCombatOdds working fine. I can't quite remember how I did it, but it was easy enough. I think the reason they don't use it is because there are quite a few places where odds are calcualted for each unit each turn and the accuracy isn't needed.

That change you made certainly looks better then the original.

Cool.

I'd be curious to see how you did it with getCombatOdds. My C++ is all self-taught and my understanding of base & derived classes, while functional, is certainly less than exhaustive. It would be helpful to see what you did as I couldn't get the pointers to play nice.
 
I originally wanted to use the function getCombatOdds() to replace this function altogether, but the CvUnitAI* pointer didn't want to play nice as a CvUnit*

CvUnitAI is a subclass of CVUnit, you should be able to pass it to getCombatOdds, what is the error you were getting. That said, I agree with TGA, you do not wall to call that slow routine every time the AI wants to calculate odds, you will slow the game down.

As far as your change to AI_attackOdds, I think the best thing to do is to run it against some of the same numbers that TGA did, to see what kind of numbers you get.

That is definitely a different (and less complicated) solution than what was done with this function in Warlords (which is still much less complicated than getCombatOdds()).

You also do not need the int() wrapper, that is not going to do anything (other than perhaps generate some extra calls). The math is already integer math.

-Iustus
 
Unfortunately I now have to edited it to add events that are dependent on the amount of life both units have left at the time of the event.

My reading of it says that it does take account for the current health (hit points, whatever) of each unit.

What do you mean?

-Iustus
 
hmmm...

after reading this thread....and especially TGA´s and sevo´s posts....
i remembered that the calculation now in Warlords isn´t as good as it should be....or it was in vanilla Civ4.

Many times, the battle-calculator (ctrl) says something about 99%....but i loose much more the one such battles in 100 attempts....

...and the same in the opposite. Sometimes the calculator says...10%....but i win much often than 1 of ten such battles.

Surely this is only a prediction.....but i have the very strong feeling...the prediction is not realistic enough. imho there are big errors in this Combat-Calculator routine for humans....since Warlords is out.

Didn´t have made others here, the same observation since WL ??
 
I think the combat odds displayed for humans are accurate. This is not the problem. The problem is that the internal workings of the AI use a different system which takes less proccessing time. This system is flawed in the vanilla version, and could perhaps be better with Warlords.
 
Lord Olleus said:
thats exactly what I mean. I have to know the health of both units after each round of combat. I think I have found a way of doing that that won't take up too much processing time.

What are you working on, if you do not mind saying? I thought you meant you were working on changing how the combat odds function works, but it seems that perhaps I was wrong about this, and you are using it for something else?

My reading of how the current function works is that it already takes into account how many hit points each unit has, that is how it determines how many hits it will take to kill a unit.

Many times, the battle-calculator (ctrl) says something about 99%....but i loose much more the one such battles in 100 attempts....

I too have noticed this, but I cannot find a bug in the code. It does use some complicated probabilistic math, so it is entirely possible there is a math error somewhere here.

Personally, I think it is just as likely that the odds are correct, and it is us, as humans that do not believe it. Humans are really really really bad at probability. It works contrary to how our brains work. The whole way we pick up patterns means that we are going to notice the few times when we lose much more frequenly than all the times when we win. You do not remember the 99 times you win easy battles as much as you remember that one time when you lost one.

That said, I still am not convinced the odds are right. But in order to check it, you are going to have to do a lot of work on that function, as it is quite complicated (perhaps Lord Olleus has a comment, I think he walked through it more than I did).

If I had to hazard a guess, I would suspect any potential bug would be more of an 'off by one' type bug, rather than a flaw in the probability math, but thats possible, it is even possible that combinatorial function is not working properly I suppose. That part would be easy enough to test.

-Iustus
 
Interesting thread,

not being a modder and all, can someone build a mod component with the above function fixed so that all of us can benefit from this finding?
 
I'll work on it if you like. I have C++ and am pretty good with it and I'm able to rebuild the .dll.
However, I'm pretty busy so it might take a while. Also I need to know the name of the file.
 
ClassicThunder said:
I'll work on it if you like. I have C++ and am pretty good with it and I'm able to rebuild the .dll.
However, I'm pretty busy so it might take a while. Also I need to know the name of the file.

getCombatOdds is located at about line 530 in CvGameCoreUtils.cpp

That said, the C++ code is rather simple.

It is the probabilistic math that is rather complicated. That and just knowledge of the way the combat is actually resolved. Knowing these two is much more important than knowing much at all about C or C++.

If you wanted to, you could also test getBinomialCoefficient to see if it gives mathematically accurate results in ranges typically used. I suspect that it works right (it seems right from my reading, and it is the kind of thing that is easy to test, so likely was already tested at Firaxis)
Code:
__int64 getBinomialCoefficient(int iN, int iK)

Well, here is the function, I have added some comments, replaced the defines from xml (die roll = 1000, combat damage = 20) with those constants to make it more readable. If you wanted to, you could change the inputs from two units to be the values of str, firepower, first strikes, first strike chances for each side, and make this a totally independant function for testing.

edit: no bug, but I left the confusing part bolded

Code:
int getCombatOdds(CvUnit* pAttacker, CvUnit* pDefender)
{
	float fOddsEvent;
	float fOddsAfterEvent;
	int iAttackerStrength;
	int iAttackerFirepower;
	int iDefenderStrength;
	int iDefenderFirepower;
	int iDefenderOdds;
	int iAttackerOdds;
	int iStrengthFactor;
	int iDamageToAttacker;
	int iDamageToDefender;
	int iNeededRoundsAttacker;
	int iNeededRoundsDefender;
	int iMaxRounds;
	int iAttackerLowFS;
	int iAttackerHighFS;
	int iDefenderLowFS;
	int iDefenderHighFS;
	int iFirstStrikes;
	int iI;
	int iJ;
	int iI3;
	int iI4;
	int iOdds = 0;
	
	iAttackerStrength = pAttacker->currCombatStr(NULL, NULL);
	iAttackerFirepower = pAttacker->currFirepower(NULL, NULL);

	iDefenderStrength = pDefender->currCombatStr(pDefender->plot(), pAttacker);
	iDefenderFirepower = pDefender->currFirepower(pDefender->plot(), pAttacker);
	
	iDefenderOdds = ((1000 * iDefenderStrength) / (iAttackerStrength + iDefenderStrength));
	iAttackerOdds = ((1000 * iAttackerStrength) / (iAttackerStrength + iDefenderStrength));	
	[COLOR="SeaGreen"]// note: iDefenderOdds + iAttackerOdds  = 1000[/COLOR]
	
	[COLOR="SeaGreen"]// **** asserts removed ****[/COLOR]
	if (iDefenderOdds == 0)
		return 1000;
	if (iAttackerOdds == 0)
		return 0;

	iStrengthFactor = ((iAttackerFirepower + iDefenderFirepower + 1) / 2);

	[COLOR="SeaGreen"]// calculate damage done in one round
	//////[/COLOR]

	iDamageToAttacker = max(1,
		((20 * (iDefenderFirepower + iStrengthFactor)) / (iAttackerFirepower + iStrengthFactor)));
	iDamageToDefender = max(1,
		((20 * (iAttackerFirepower + iStrengthFactor)) / (iDefenderFirepower + iStrengthFactor)));

	[COLOR="SeaGreen"]// calculate needed rounds.
	// Needed rounds = round_up(health/damage)
	//////[/COLOR]

	iNeededRoundsAttacker = (pDefender->currHitPoints() + iDamageToDefender - 1 ) / iDamageToDefender;
	iNeededRoundsDefender = (pAttacker->currHitPoints() + iDamageToAttacker - 1 ) / iDamageToAttacker;
	iMaxRounds = iNeededRoundsAttacker + iNeededRoundsDefender - 1;

	[COLOR="SeaGreen"]// calculate possible first strikes distribution.
	// We can't use the getCombatFirstStrikes() function (only one result,
	// no distribution), so we need to mimic it.
	//////[/COLOR]

	iAttackerLowFS = (pDefender->immuneToFirstStrikes()) ? 0 : pAttacker->firstStrikes();
	iAttackerHighFS = (pDefender->immuneToFirstStrikes()) ? 0 : (pAttacker->firstStrikes() + pAttacker->chanceFirstStrikes());

	iDefenderLowFS = (pAttacker->immuneToFirstStrikes()) ? 0 : pDefender->firstStrikes();
	iDefenderHighFS = (pAttacker->immuneToFirstStrikes()) ? 0 : (pDefender->firstStrikes() + pDefender->chanceFirstStrikes());

	[COLOR="seagreen"]// For every possible first strike event, calculate the odds of combat.
	// Then, add these to the total, weighted to the chance of that first 
	// strike event occurring
	//////[/COLOR]

	for (iI = iAttackerLowFS; iI < iAttackerHighFS + 1; iI++)
	{
		for (iJ = iDefenderLowFS; iJ < iDefenderHighFS + 1; iJ++)
		{
			[COLOR="seagreen"]// for every possible combination of fs results, calculate the chance[/COLOR]

			if (iI >= iJ)
			{
				[COLOR="seagreen"]// Attacker gets more or equal first strikes than defender[/COLOR]
				iFirstStrikes = iI - iJ;

				[COLOR="seagreen"]// For every possible first strike getting hit, calculate both
				// the chance of that event happening, as well as the rest of 
				// the chance assuming the event has happened. Multiply these 
				// together to get the total chance (Bayes rule). 
				// iI3 counts the number of successful first strikes
				//////[/COLOR]
				for (iI3 = 0; iI3 < (iFirstStrikes + 1); iI3++)
				{
					[COLOR="seagreen"]// event: iI3 first strikes hit the defender

					// calculate chance of iI3 first strikes hitting: fOddsEvent
					// f(k;n,p)=C(n,k)*(p^k)*((1-p)^(n-k)) 
					// this needs to be in floating point math
					// k = iI3
					// n = iFirstStrikes
					// p = [B]iAttackerOdds[/B] / 1000
					//////[/COLOR]

					fOddsEvent = ( (float)getBinomialCoefficient(iFirstStrikes, iI3)) 
						* pow((((float)[B]iAttackerOdds[/B])/1000), iI3) 
						* pow((1.0f - (((float)[B]iAttackerOdds[/B])/1000)), (iFirstStrikes - iI3));

					[COLOR="SeaGreen"]// calculate chance assuming iI3 first strike hits: fOddsAfterEvent
					//////[/COLOR]

					if (iI3 >= iNeededRoundsAttacker)
					{
						fOddsAfterEvent = 1;
					}
					else
					{
						fOddsAfterEvent = 0;

						[COLOR="seagreen"]// odds for _at_least_ (iNeededRoundsAttacker - iI3) (the remaining hits 
						// the attacker needs to make) out of (iMaxRounds - iI3) (the left over 
						// rounds) is the sum of each _exact_ draw
						//////[/COLOR]

						for (iI4 = (iNeededRoundsAttacker - iI3); iI4 < (iMaxRounds - iI3 + 1); iI4++)
						{
							[COLOR="seagreen"]// 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
							// k = iI4
							// n = iMaxRounds - iI3
							// p = [B]iAttackerOdds [/B]/ 1000
							//////[/COLOR]

							fOddsAfterEvent += ((float)getBinomialCoefficient((iMaxRounds - iI3), iI4)) 
								* pow((((float)[B]iAttackerOdds[/B]) / 1000), iI4) 
								* pow((1.0f - (((float)[B]iAttackerOdds[/B]) / 1000)), ((iMaxRounds - iI3) - iI4));
						}
					}

					[COLOR="seagreen"]// Multiply these together, round them properly, and add 
					// the result to the total iOdds
					//////[/COLOR]

					iOdds += ((int)(1000.0 * (fOddsEvent*fOddsAfterEvent + 0.0005)));
				}
			}
			else // (iI < iJ)
			{
				[COLOR="seagreen"]// Attacker gets less first strikes than defender[/COLOR]

				iFirstStrikes = iJ - iI;

				[COLOR="seagreen"]// For every possible first strike getting hit, calculate both
				// the chance of that event happening, as well as the rest of 
				// the chance assuming the event has happened. Multiply these 
				// together to get the total chance (Bayes rule). 
				// iI3 counts the number of successful first strikes
				//////[/COLOR]

				for (iI3 = 0; iI3 < (iFirstStrikes + 1); iI3++)
				{
					[COLOR="seagreen"]// event: iI3 first strikes hit the defender

					// First of all, check if the attacker is still alive.
					// Otherwise, no further calculations need to occur 
					/////[/COLOR]

					if (iI3 < iNeededRoundsDefender)
					{
						[COLOR="seagreen"]// calculate chance of iI3 first strikes hitting: fOddsEvent
						// f(k;n,p)=C(n,k)*(p^k)*((1-p)^(n-k)) 
						// this needs to be in floating point math
						// k = iI3
						// n = iFirstStrikes
						// p = [B]iDefenderOdds [/B]/ 1000
						//////[/COLOR]
						fOddsEvent = ((float)getBinomialCoefficient(iFirstStrikes, iI3)) 
							* pow((((float)[B]iDefenderOdds[/B]) / 1000), iI3) 
							* pow((1.0f - (((float)[B]iDefenderOdds[/B]) / 1000)), (iFirstStrikes - iI3));

						[COLOR="seagreen"]// calculate chance assuming iI3 first strike hits: fOddsAfterEvent
						//////[/COLOR]

						fOddsAfterEvent = 0;

						[COLOR="seagreen"]// odds for _at_least_ iNeededRoundsAttacker (the remaining hits 
						// the attacker needs to make) out of (iMaxRounds - iI3) (the left over 
						// rounds) is the sum of each _exact_ draw
						//////[/COLOR]

						for (iI4 = iNeededRoundsAttacker; iI4 < (iMaxRounds - iI3 + 1); iI4++)
						{

							[COLOR="seagreen"]// 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
							// k = iI4
							// n = iMaxRounds - iI3
							// p = [B]iAttackerOdds [/B]/ 1000
							//////[/COLOR]

							fOddsAfterEvent += ((float)getBinomialCoefficient((iMaxRounds - iI3), iI4)) 
								* pow((((float)[B]iAttackerOdds[/B]) / 1000), iI4) 
								* pow((1.0f - (((float)[B]iAttackerOdds[/B]) / 1000)), ((iMaxRounds - iI3) - iI4));
						}

						[COLOR="seagreen"]// Multiply these together, round them properly, and add 
						// the result to the total iOdds
						//////[/COLOR]

						iOdds += ((int)(1000.0 * (fOddsEvent*fOddsAfterEvent + 0.0005)));
					}
				}				
			}
		}
	}

	[COLOR="seagreen"]// Weigh the total to the number of possible combinations of first strikes events
	// note: the integer math breaks down when #FS > 656 (with a die size of 1000)
	//////[/COLOR]

	iOdds /= (((pDefender->immuneToFirstStrikes()) ? 0 : pAttacker->chanceFirstStrikes()) + 1) 
			* (((pAttacker->immuneToFirstStrikes()) ? 0 : pDefender->chanceFirstStrikes()) + 1); 

	[COLOR="seagreen"]// finished!
	//////[/COLOR]

	return iOdds;
}

Since the whole point is to see the odds of the attacker winning, it looks like the bolded parts are correct. In the case of a defender getting more first strikes, then those are removed.

Here is the entirety of getBinomialCoefficient in case someone wants to make a test app (just change the above function to take those int inputs and you do not need anything else).
Code:
__int64 getBinomialCoefficient(int iN, int iK)
{
	__int64 iTemp = 1;
	//take advantage of symmetry in combination, eg. 15C12 = 15C3
	iK = min(iK, iN - iK);
	
	//eg. 15C3 = (15 * 14 * 13) / (1 * 2 * 3) = 15 / 1 * 14 / 2 * 13 / 3 = 455
	for(int i=1;i<=iK;i++)
		iTemp = (iTemp * (iN - i + 1)) / i;

	// Make sure iTemp fits in an integer (and thus doesn't overflow)
	FAssert(iTemp < MAX_INT);

	return iTemp;
}

-Iustus
 
Back
Top Bottom