Here is the function for collateral unit AI behaviour:
Code:
void CvUnitAI::AI_collateralMove()
{
PROFILE_FUNC();
if (AI_leaveAttack(1, 20, 100))
{
return;
}
if (AI_guardCity(false, true, 1))
{
return;
}
if (AI_heal(30, 1))
{
return;
}
if (AI_cityAttack(1, 35))
{
return;
}
if (AI_anyAttack(1, 45, 3))
{
return;
}
if (AI_anyAttack(1, 55, 2))
{
return;
}
if (AI_anyAttack(1, 35, 3))
{
return;
}
if (AI_anyAttack(1, 30, 4))
{
return;
}
if (AI_anyAttack(1, 20, 5))
{
return;
}
if (AI_heal())
{
return;
}
if (!noDefensiveBonus())
{
if (AI_guardCity(false, false))
{
return;
}
}
if (AI_anyAttack(2, 55, 3))
{
return;
}
if (AI_cityAttack(2, 50))
{
return;
}
if (AI_anyAttack(2, 60))
{
return;
}
if (AI_protect(50))
{
return;
}
// if (AI_group(UNITAI_ATTACK_CITY, -1, -1, -1, /*bIgnoreFaster*/ true))
// {
// return;
// }
if (AI_guardCity(false, true, 3))
{
return;
}
if (AI_retreatToCity())
{
return;
}
if (AI_safety())
{
return;
}
getGroup()->pushMission(MISSION_SKIP);
return;
}
The first bit:
if (AI_leaveAttack(1, 20, 100))
{
return;
}
is "try to find something to attack within 1 square".
Code:
bool CvUnitAI::AI_leaveAttack(int iRange, int iOddsThreshold, int iStrengthThreshold)
One problem is the last parameter: it only tries to attack if the collateral unit's plot strength is greater than the attacking plot strength.
Pratically, what "could" be done there is an attack and defense simulation: see if attacking leads to better results than defending, esp. if you are in a city.
Tricky.
As an aside, I found something interesting: CvUnit::currEffectiveStr should be changed, or the AI should use something different to approximate odds: one's ability to win a skirmish is closer to combat strength
squared, not linear with combat strength. I'd have to be careful making sure that units don't use this value for actual combat, just for AI purposes... This seems to be the case: the only use of currEffectiveStr is in "*AI.cpp" files.
To be clear:
The strength of a unit, in a last-unit-standing fight, is roughly purportional to currHP * currCombat^2 -- a bit less than that, if they don't have time to heal up between fights.
Collateral units work differently. When attacking, their power is dependant on the defender having many units.
If the defender has "enough" units, a collateral unit does damage purportional to:
(TargetAvgCollateralCombatPower / CollateralDamage)^1.5 * number_of_targets
in the collateral phase: the exact value is tricky to work out.
1: Take # of targets with less than "MAX_COLL_DAMAGE" damage.
2: Then, roughly (CollateralStr/DefenderCollateralDefense)^1.5 * 28 damage is done to each one, on average. (that takes into account both an approximation of hit chance (roughly power ratio), and damage per collateral attack (roughly sqrt of power ratio, times 28).
...
If we factor in the effects of repeated combat from smaller stacks fighting larger ones, we can simplify this.
Have the power-estimate be equal to:
HP * Combat^1.5
where the units are "estimated power damage done to an enemy stack in a suicide-charge-until-dead".
Then collateral damage adds:
85 * CollateralStr^1.5
to this value.
So, we get:
HP * CombatStr^1.5 + 85 * (CollateralPercent * CollateralStr)^1.5
as our "better than current estimate" of collateral unit power contribution to an attacking stack.
So a full-HP catapult (str 5) with +50% collateral strength contributes:
1118 from direct-attack power.
1746 from collateral-damage power.
for a total of:
2864 attack-power.
A full-HP praetorian (str 9) with combat 1 (+10%) contributes:
3115 from direct-attack power.
A full-HP axeman (str 5) with combat 2 (+20%) contributes:
1470 from direct-attack power.
You will notice that catapults read out as rather powerful under this system -- this reflects the power of catapults in the real game against target stacks.
Ideally one would factor in the enemy stack size: a single enemy unit will result in catapults overestimating their importance, while a large stack will result in catapults underestimating their importance.