Air combat discussion

jdog5000

Revolutionary
Joined
Nov 25, 2003
Messages
2,601
Location
California
Continuing the discussion on use of combat promotions for air units which starts here ...

A few of the posts:

Just found something in the SDK:
Code:
int CvUnit::airMaxCombatStr(const CvUnit* pOther) const
{
	...

	iModifier = getExtraCombatPercent();

	...

	if (getExtraCombatPercent() != 0)
	{
		iModifier += getExtraCombatPercent();
	}
It seems like the Combat Promotions are factored in twice during air combat. Can anyone confirm this? Should that be forwarded to Solver?

A quick WB test revealed that Combat 6 Airships (= str 10) performed surprisingly well against intercepting Fighters and Combat 6 Fighters (= str 30) just smashed Jet Fighters on patrol...
S O L V E R !!!

I think that this is not intended, due to the syntax.... if it was intended we would get a "*2" in the first line instead of a crazy check if there is a promo bonus or not for the second time.....

This is clearly undocumented in the civilopedia and thus seems a bit buggy.

However, I still kind of like it. There are only very few promotions to help you win air combat and because air combat is won in very few rounds, the combat promotions won't help a lot (that's a mathematical issue). Using the rules explained by the OP Stormreaver, a combat III fighter only has a little bit better than 50% chance of winning combat against an unpromoted fighter. This means that you can't do a lot to make your fighters better than the opposing fighters or to gain air superiority. Using double effect combat promotions helps a bit.



Combat 6 fighters? That's like fighters commanded by Rambo (or the Red Baron). They should beat anything. ;) ;) ;)

Using the rules explained by the OP, combat 5 fighters (the best normally attainable promotions for a fighter) should have strength 18 versus strength 24 jet fighters. Using the actual double effect promotions, combat 5 fighters have strength 24 versus strength 24 jet fighters: an equal fight. I don't have a problem that fighters with maximum normally attainable promotions have a 50-50 chance against completely unpromoted jet fighters. That's 26 experience versus 0 experience. Unpromoted fighters also have a 26% chance of victory against jet fighters. For 26 experience, they managed to get a 50% chance of victory. That doesn't sound overpowered or something. In every area of land combat, you can do better with 26 experience.

Compare with combat 5 axemen (7.5) versus unpromoted macemen (8), combat 5 musketmen (13.5) versus unpromoted riflemen (14), combat 5 riflemen (21) versus unpromoted infantry (20) and note that there are better promotions to take in these cases for the lower tech unit.

Combat 5 airships should have strength 6, but due to the semi-bug they have strength 8. They can never shoot down a fighter or jet fighter because they can only win a maximum of 5 rounds doing 10 hitpoints of damage per round. They only need to lose 2 rounds out of 5 against superior strength unpromoted fighters (12) to be shot down. They will likely go down. There's no issue there.

IMHO, the double effect combat promotions are a good thing for air combat because they give the option to somewhat improve your odds to win air combat when you have an excellent training facility. The only issue that I have is that it's undocumented and that they might be strong compared to the normal bonus promotions versus gunpowder units and armoured units which are also available to airplanes. Or are these promotions also doubled in effect?
 
It's a pity that it isn't intended. And the issue with pinch and ambush promotions not doubling unlike the combat promotions is bad for balance (that's why I asked). Still, I wish it would be possible to promote your airplanes in an effective way. It's pretty hard to fight a somewhat efficient air superiority battle even when your guys are far more experienced. Making experience unimportant in air superiority battles isn't very good for gameplay and it's also not based on realism.

Since, I would rarely use pinch and ambush on fighters anyway and since I like the effect of the doubling of combat promotion effects on air superiority combat, I wish this bug hadn't been found. Bleh, now I guess you'll want Solver to fix it. :sad:

But yeah, it's a bug. But a nice bug. ;)

How about the following tweaks to air combat and the airplane promotions to make their XPs actually have an (un-borked) effect:
A) take the +25% EvasionChange away from ACE and give it a +50% UnitCombatMods vs other airplanes instead (air superiority)
B) give RANGE1 an extra +10% EvasionChange
C) give RANGE2 an extra +20% EvasionChange
D) decrease MAX_INTERCEPTION_DAMAGE in GlobalDefines.xml from 50 to 34 (so a healthy interceptor needs to win 3 rounds instead of just 2 to kill --> decrease the lucky-punch-factor)
These changes suggest different promotion paths for Bombers (--> Range) and Fighters (--> Ace) and can all be done just by modding the XMLs.

Seems sensible enough. I have only one gripe about this - it also decreases the amount of damaged dished out by sub-100% intercept units. MAX_INTERCEPTION_DAMAGE doubles as the Interception % multiplier to calculate damage, and lowering this will also lower, for example, SAM inf damage (from 20 to 13 hp/won round).

Bombers and units with up to 20% intercept prob aren't affected because of the MIN_INTERCEPTION_DAMAGE, though. I suppose it nerfs mainly SAM Inf, Mobile SAM and Destroyers?

It would work decently for a mod, I think.

You could also lower the min_interception damage and increase the number of air combat rounds to 7 or something like that to make everything scale.

Note that the OP didn't want a lengthy discussion about how to change air combat in his thread. We probably should respect that.


So, options include leaving things as they are, simply fixing the bug with double counted combat promotions, or figuring out some more advanced fix to allow for better air superiority.

Discuss.
 
I'm clearly in favour of a more advanced fix which slightly changes the algorithm behind air combat (while fixing the promotion). If you increase the number of rounds of air combat and lower the damage per round, then the fighters with more promotions and thus a higher strength will get better odds to win the entire thing while on average the percentage hitpoints left on the victor will remain the same. However, that might change this AI-mod into something more than a pure AI-mod. The creators of this mod should decide if they are even willing to go that way.

Note that if you simply remove the combat promotion double effect, then you'll also change air combat in such a way that promotions have less effect. It will also change the game and not just the AI.

It's unclear whether the designers at Firaxis wished a certain effect of combat promotions and were content with play tests unaware of the fact that the combat promotions were counted double or they just wished an air combat model where promotions weren't very effective and they made an error that went unnoticed in play tests.
 
I'd support a fix to this in the "unofficial patch", but this doesn't look like an AI problem or bug.
 
Code:
void CvUnit::resolveAirCombat(CvUnit* pInterceptor, CvPlot* pPlot, CvAirMissionDefinition& kBattle)
{
	CvWString szBuffer;

	int iTheirStrength = (DOMAIN_AIR == pInterceptor->getDomainType() ? pInterceptor->airCurrCombatStr(this) : pInterceptor->currCombatStr(NULL, NULL));
	int iOurStrength = (DOMAIN_AIR == getDomainType() ? airCurrCombatStr(pInterceptor) : currCombatStr(NULL, NULL));
	int iTotalStrength = iOurStrength + iTheirStrength;
	if (0 == iTotalStrength)
	{
		FAssert(false);
		return;
	}

	int iOurOdds = (100 * iOurStrength) / std::max(1, iTotalStrength);

	int iOurRoundDamage = (pInterceptor->currInterceptionProbability() * GC.getDefineINT("MAX_INTERCEPTION_DAMAGE")) / 100;
	int iTheirRoundDamage = (currInterceptionProbability() * GC.getDefineINT("MAX_INTERCEPTION_DAMAGE")) / 100;
	if (getDomainType() == DOMAIN_AIR)
	{
		iTheirRoundDamage = std::max(GC.getDefineINT("MIN_INTERCEPTION_DAMAGE"), iTheirRoundDamage);
	}

	int iTheirDamage = 0;
	int iOurDamage = 0;

	for (int iRound = 0; iRound < GC.getDefineINT("INTERCEPTION_MAX_ROUNDS"); ++iRound)
	{
		if (GC.getGameINLINE().getSorenRandNum(100, "Air combat") < iOurOdds)
		{
			if (DOMAIN_AIR == pInterceptor->getDomainType())
			{
				iTheirDamage += iTheirRoundDamage;
				pInterceptor->changeDamage(iTheirRoundDamage, getOwnerINLINE());
.
.
.

This piece of code states that the amount of damage dealt by the attacker and interceptor, during aerial combat, is simply the current interception probability (defined as interception probability modified by hitpoint, so a fighter with interception 100% at 50% health can do 50% damage to it's adversary - per round, and there are five rounds of combat). MAX_INTERCEPTION_DAMAGE is default at 100, so basically has no effect. Furthermore, the chance to do damage is dependent upon strength.

It really annoys me that damage is totally unrelated to strength. If you want an interceptor to do more damage, you should give it interception promotions. If you want it to have a higher chance of actually DOING damage, you want more strength. This is counterintuitive at best, and really makes it tricky to mod the aerial aspects of the game in a balanced way.

It seems to me that aerial combat was not really developed properly. We have evasion variables in the XML for units, but it is only used to check if the attacking unit can evade interception, regardless of the interceptors interception level. And only nukes, missiles and the stealth bomber have evasion greater than zero.
 
*nod*.

I'd be tempted to go with someting like:
Str*(100%+Evasion%) vs Str*(Intercept%) intercept chance.

If intercepted, each round consists of:
Str*(100%+Combat%) vs Str*(100%+Combat%) round of combat,
then Str*(50%+Evasion%) vs Str*(100%+Intercept%) disengagement attempt.

...repeated until something is shot down, or the attacker disengages.

This would require rebalancing every intercept/evasion percentage...

X% intercept before = X%/(100%-X%) intercept after

And then evasion% would have to be completely reworked.
 
Yeah, that is a counter intuitive formula ... I took a quick look at the formulas for land combat to see how these compare. In the land case, both the odds of landing a hit and damage dealt depend on strength but the specific formulas are different in the two cases. So, the one formula that is really different from the standard setup here is the damage dealt formula ...

MAX_INTERCEPT_DAMAGE is set to 50 in XML from what I see, where did you get 100 Ninja2? Anyway, as stated up thread that means that a healthy, unpromoted fighter needs to win only two rounds to shoot down anything (with relative strength adjusting the odds of winning a round).

The current formula seems to work okay for most of the air unit vs ground/sea interceptor scenarios ... if a ground unit has a higher interception percentage, it makes sense for it to deal more damage to a plane. But when two fighters are going head to head, it certainly is more intuitive to have damage based on strength.

Perhaps we could consider just making tweaks for the air vs air scenario to keep things a bit simpler ... the "real" interactions are very different anyway, since a ground interceptor would really only get a few shots in while a fighter can give chase.
 
Sorry, I got it mixed up with MAX_INTERCEPTION_PROBABILITY, which is 100.

I don't really know what the best solution is. I like Yakk's suggestion, but I can see why that would be beyond the scope of Better_AI. However, I am biased, since I'd really like a better intercept model for my mod! :D I want to take advantage of those evasion tags, and there are also more classes of air units in my mod, so that's really my motivation for bringing this up.
 
Here's another one that baffles me:

Again, in CvUnit.cpp, there's the function
Code:
bool CvUnit::interceptTest(const CvPlot* pPlot)

This intercept test is used to determine whether or not an air attack or paradrop is intercepted. However, for the paradrop and the airbomb (attacking defenses) missions, the check is done like this:
Code:
if(interceptTest(pPlot))
	{
		return [B]true[/B];
	}

Whereas for the airstrike mission (attacking units), the test looks like this:
Code:
if (interceptTest(pPlot))
	{
		return [B]false[/B];
	}

Is this working as intended?
 
Here's what I'm trying out for the change to aircombat mechanics:

For fighter v fighter fights only, switch from the intercept style code to basically the same mechanics used for land combat. The rationale for this is that fighter v fighter combat is different than other interception scenarios ... fighters can dogfight, it's potentially a meeting of equals. Here's how the difference plays out. Combat calculations have two parts, odds of winning a round and the damage dealt if a round is won. The odds of winning a round of air combat remains based on relative strength, just like land combat. The difference is in damage dealt per round.

Previously, a fighter dealt 50*(current interception chance) damage per round where (current interception chance) is (100 + up to 30 from interceptor promotions)*(current health)/100. For a healthy fighter this meant 2 hit kills regardless of the opponent or what promotions the fighter had ... relative strength effected odds of winning a round, but two hits from a healthy fighter would bring down any other fighter. Two hits kills made these fights very much about luck ... a combat 5 fighter could be shot down by a complete rookie fighter ~30% of the time.

Now, combat damage for fighter v fighter uses a damage dealt formula just like the standard damage formula, based on relative strength. Damage per round is overall decreased so that an even fight requires 3 wins ... since there are still 5 rounds, someone always burns in an even fight. In the Combat 5 versus rookie case, the rookie has to win 3 out of 5 with 40% odds just to live and 4 out of 5 with 40% odds to shoot down the veteran. (These compare to shooting down by winning 2 out of 3 with 40% odds)

Another corner case where things are dramatically different now: A 50% injured jet fighter vs a standard fighter, no promotions. With even effective strength because of the injury, the odds of each winning a round is 50%. With the prior interception-based formula, the jet fighter only did 25 damage per round because of being 50% injured and would have to win 4 out of 5 rounds to win while the standard fighter still only needed 2 victories. With the more strength formula, a unit does damage based on the average of its effective and full strengths, so the jet fighter only needs 3 out of 5 hits to kill while the standard fighter needs 4 of 5.

As you can see, the change means that for fighter v fighter combat, strength and technology will now be much more important ... air superiority may soon really mean something!

(EDIT: The source code changes have been checked in to the sourceforge SVN in case you want to check them out ... they're in CvUnit::resolveAirCombat)
 
Meh -- I think think that evasion and intercept should factor in, to make it 'feel' somewhat like the existing game where you can disengage.

And special casing fighter-vs-fighter seems wrong.
 
Here are another two issues for consideration:

First issue: Currently, it is not possible to actively engage the enemy's air defenses, be it fighters or SAM infantry. A jet fighter has the same options to engage the enemy as a bomber - recon, bombing or airstrikes. So it is impossible for the attacker to simulate escorted bomber runs. This is despite the fact that the defender's interceptors (ground or air defenses) have a setMadeInterception flag, which makes any intercepting unit incapable of intercepting more than once during any combat round. So if I attack with a single fighter, and I know that my defender has only one fighter on patrol, and I am intercepted, I can without any danger have my bombers attack, knowing that I will not be intercepted. If my fighter is not intercepted, I have presumably attacked a ground unit, which is really a sub-optimal use of my fighter. Optimally, my fighter should have escorted my bomber, engaged the enemy fighters to protect my bomber, and allowed the bomber to complete it's mission.

Dale has in his DCM done two things: He ignores the check on the setMadeInterception when selecting the best interceptor, and he has a mission option for fighters to engage the enemy's fighters. I propose that we introduce the fighter engage mission, but continue to check for the setMadeInterception. This allows the player to simulate escorted bomber runs, although the planes do not travel simultaneously. However - this idea opens up an exploit, where you send a vastly inferior fighter to engage the enemy air. So I suggest that the setMadeInterception flag only be set, if the interceptor took damage from the dogfight. If it escapes unharmed, it should be allowed to intercept again.

Second issue: When bestÍnterceptor is chosen, the code evaluates the unit with the highest probability to intercept (i.e. the unit with the highest damage dealing potential), modified by the unit's health. This is currInterceptionProbability. So there's no regard for the unit's strenght, which under the current code determines the actual chance to DO damage... at least the game should also consider the strength of the unit?
 
Re: Evasion - Should be in the code, absolutely. Every pilot around the world (at least in the sane countries) is taught that survival is priority one; when the fight is going against you, bug out! I recommend that a withdrawal check be made by a VF when/if it loses a round of combat, along the lines of:

Code:
(more like logic flow than code, actually...)

StrVFA = Strength of fighter [U]losing[/U]round
StrVFB = Strength of fighter [U]winning[/U] round
StrVFA / StrVFB = BugOut

IF BugOut <= [40%]
[INDENT]THEN RunAway[/INDENT]
ELSE NextRound

RunAway = 50
IF StrVFB < 100 = Escape //If he's shot up, he's not likely to pursue//

IF VFA = VF
IF VFB = Jet VF
[INDENT]THEN RunAwayMod = RunAway -20  //Jets are faster, but maybe the VF pilot is Chuck Yeager and the Jet VF pilot is a nugget//[/INDENT]

IF VFA = Jet VF
IF VFB = VF
[INDENT]THEN RunAwayMod = RunAway +20 //Jets are faster, but maybe the VF pilot is Chuck Yeager and the Jet VF pilot is a nugget//[/INDENT]

IF RunAwayMod > Random 
[INDENT]THEN Escape[/INDENT]
ELSE Taps

Re: Escort Mission: I've sent VBs against targets with VFs in the same group several times. So far, the VFs have fought FIRST and the VBs only got intercepted if there were more CAP than I had VFs. I don't know if the airstrike went in as a group or if the fighters went in first because air combat doesn't get listed in the combat log (can this be fixed?) but the result is as if the VF were properly escorting the strike package.

Re: MadeIntercept: From what the Civopedia says, CAP will intercept repeatedly as long as it keeps making it's check. Methinks that the MadeIntercept flag might be used as a marker showing that the CAP flew a mission and the AI should first look to another VF for the next intercept if any are available as opposed to a "sorry, I've moved this turn" toggle. Yes, it could be exploited by using old VF as fodder to draw off the CAP, but the fodder would be killed (most likely) on it's first mission so the exploit would be a pretty limited one.

For clarity - when you say "strength", you are referring to "# of hitpoints left" or health, yes? Not "strength" as is used in the game infos to indicate hitting power?
 
SEAD: Suppression of Enemy Air Defenses aka "Wild Weasel".

This concept requires lifting some lines from the Espionage code.

  • Send a/c against tile having the AAW system (airport counts!)
  • Defense makes it's interception check as normal.
  • If the a/c survives, player is presented with an option menu ala the Espionage Mission/Destroy Building but listing ONLY AAW systems.
  • PLayer chooses target, target takes damage, a/c egresses

If I understand the way the system works correctly, the strike damage will lower the intercept chance (ie: suppress) the AAW system; kind of like taking down a SAM site's radar.

Thoughts/Comments?
 
Re: Escort Mission: I've sent VBs against targets with VFs in the same group several times. So far, the VFs have fought FIRST and the VBs only got intercepted if there were more CAP than I had VFs. I don't know if the airstrike went in as a group or if the fighters went in first because air combat doesn't get listed in the combat log (can this be fixed?) but the result is as if the VF were properly escorting the strike package.

I can't believe I haven't thought to test this approach... but what happens if the VF is not intercepted, because the intercept test fails, is the interceptor then available to intercept the VB (I'm assuming one attacking/escorting VF and one VB, and one VF on CAP)?

For clarity - when you say "strength", you are referring to "# of hitpoints left" or health, yes? Not "strength" as is used in the game infos to indicate hitting power?

Well, in the air combat routine, it's the interception variable that determines the damage dealing potential, and the strength (not health) which determines the chance of winning a combat round. Just so we're clear on that. :) So I did mean strength, and not health, since strength is the determining factor for winning a combat round.
 
I can't believe I haven't thought to test this approach... but what happens if the VF is not intercepted, because the intercept test fails, is the interceptor then available to intercept the VB (I'm assuming one attacking/escorting VF and one VB, and one VF on CAP)?

Good question! I haven't encountered that particular situation. I would think that the CAP wouldbe able to intercept the bombers; essentially it would simulate the CAP getting past the escort VF. I wouldn't expect this situation to occur very often, though. If the iIntercept is low enough to be missed for the VF, it's likely to also be low enough to be missed for the VB. Speaking in broad terms here, of course, so math guys, please don't jump on me!

I have seen consistently these situations and resolutions:

  • CAP kills/damages (to withdrawal) VF, VB continues mission
  • VF kills/damages CAP to withdrawal, VB continues mission
  • No intercept, both VF and VB bomb target
  • VF & VB both killed or both damaged and withdraw

Note that I do not know if there was a 2d CAP that failed it's check, or if there was only the one CAP. I'll have to do some experimenting on this bit.

One other question comes to mind here, too - does the AI cycle through *all* the CAP in a city, testing each one for an intercept? Or does it test just the first x with xbeing the size of the incoming raid?



Well, in the air combat routine, it's the interception variable that determines the damage dealing potential, and the strength (not health) which determines the chance of winning a combat round. Just so we're clear on that. :) So I did mean strength, and not health, since strength is the determining factor for winning a combat round.

OK. I thought you had written earlier something indicating that the strength went down after an intercept and I've always thought that STR was STR - the base number doesn't change.
 
One other question comes to mind here, too - does the AI cycle through *all* the CAP in a city, testing each one for an intercept? Or does it test just the first x with xbeing the size of the incoming raid?

I'm pretty sure it makes a single check for only the "best" interceptor. The best interceptor is the one with the highest interception level, modified by health - which also ties in to the other question about strength and best interceptor, in that health is thus implicitly checked.

Presumably, if you make an air attack using a stack, it still checks each aircraft individually, but I don't know, since I have never tried this.
 
Alright, given that machineguns and anti-tank in 3.17 are simulated to double as flak, I think the whole air defense code needs some serious overhaul.

A ground unit that intercepts an aircraft also uses the combat logic in the resolveaircombat code posted above. Which means that if intercepted, the attacking aircraft actually combats the intercepting unit. Imagine a fighter doing an airstrike. If the defending ground unit manages to intercept, the fighter aborts it's airstrike to attack the interceptor (flak) in stead. I don't think this type of mission has ever happened in aviation history...

A much better approach would be to have an intercpetion check from air units, and a separate check from ground (non-air in this case) units. The interceptions made from ground units should result in low damage to the aircraft, and no damage to the interceptor. Evasion should be particular effective at preventing interception from ground (and sea).
 
Back
Top Bottom