Making the AI More Aggressive

Joined
Jul 28, 2006
Messages
4,016
In the course of my scenario making I have often found that the level of AI aggression, even with the "Aggressive AI" option turned on, was less than what I wanted. I am aware of several different avenues for improving this, such as modifying leader personalities, but since the Civ4wiki site is now down (permanently, it seems), and since there are others out there already engaged in similar efforts, I thought I'd pose the question publicly: what are the best ways to go about making the AI more aggressive?

By aggressive, I mean that during war, they are more likely to invade and attack you, they try take as many cities as possible, and they resist your invasions/raids on their territory with more force.

Broad and difficult criteria, I know, but there must specific lines in XML/SDK that can easily be modified for dramatic effect.
 
My friend, welcome to the world of AI_STRATEGIES and AI_WARPLANS. It sounds like its time for you to join the club. :D

AI_STRATEGY - defines the goal of the AI (prod, economy, military, total war, etc)
AI_WARPLAN - defines the AI's war goals (whether raid, all-out, final, etc)

Take a look through the SDK and python at some of the uses. :)
 
In order to be more aggressive during war they need more units and they need to stay out of financial trouble. Staying out of financial trouble is the biggest single factor, so if you want to improve their ability to wage war focus on improving their ability to run their economy first or take the easy way out and give them more handicap bonuses on unit upkeep and particularly unit supply costs (in Civ4handicapInfos.xml).

They also need some 'encouragement' to produce appropriate units, or more correctly to not produce so many useless units (ships mainly, especially in the early game). I imposed limits to the number of ships they can build, by unitclass, in the SDK using the number of players, number of coastal cities and world size in general. The normal AI build descisions don't have limits built into them so the AI will continue building what it determines to be the best build for that city with little regard to anything else aside from some encouragement to build specific UNIT_AI types. This plays a part in their financial trouble as well, if the build hundreds of ships that they never use those ships are little more than a burden on their economy that pushes them into financial trouble which in turn forces them to stop attacking. This can be done in Python but can cause slowdowns if you're counting too many different unit types. You can also cheat and do it in xml alone with national unit limits.

From another angle, stack size limitations will impact the quality of the AI's war since they give orders to stacks rather than individual units. So, by limiting stack size you end up with more stacks which can result in more targets and better overall strategy.

And finally, you can modifiy the AI so that it will attack with lower odds of winning. Although this won't always help them in the short run it has a number of positive effects in the long run such. Since the AI doesn't like to disband units this is a good way to weed out their weaker units through attrition. If they AI thinks they'll win they will also be more likely to continue attacking, even after sustaining some losses, which can cause them to win battles they would not have otherwise fought. In the SDK you can control this very specifically and use different calculations for various units, targets, terrains and whether they're in friendly or hostile terriroty. This does not affect the actual combat odds, only what the AI thinks the odds are when deciding if it should attack, so it would be similar to modifiying the odds displayed to human players. In my mod I use this in a couple of places, most notably with ships dealing with privateers, my rule in that case is that any unit with hidden nationality that is blockading in the AI's territory is treated as if they have a 99% chance of victory so they go at them with a vengence. In another example if the attack unit can flank any units in the target stack it thinks it has better odds than it really does, I also do something similar for units that cause collateral damage.

That should give you some ideas, if you want specific details I have a lot of SDK code I'd be happy to share. My xml changes to the AI are a combination of several aspects such as traits, flavors, attitude adjustments (heh) and AI weights to achieve the desired results for me.
 
@Dale: I had a feeling you would join in on this discussion sooner or later. :D

As I understand it, there are at least two types of war: limited and total. I have seen how this is used in scenarios like FFH2 or RtW (example: self.pGermanyTeam.declareWar(self.pPolandID, false, WarPlanTypes.WARPLAN_TOTAL) ) but I have very little idea where to start modding the SDK. I suppose the first place is to force total war, which I presume is automatically more brutal. :evil:

Is there a default war plan selected when you declare war on somebody and then pass control to the AI? For instance, if I declare war, then save in the worldbuilder, and after reloading choose another civ, will the civ that I originally controlled automatically pick limited war?

XML question: What exactly does this do in LeaderheadInfos?

Code:
<iBaseAttackOddsChange>0</iBaseAttackOddsChange>
<iAttackOddsChangeRand>16</iAttackOddsChangeRand>

I presume this changes how willingly a leader will attack you when the odds are not in favor of victory?
 
In order to be more aggressive during war they need more units and they need to stay out of financial trouble. Staying out of financial trouble is the biggest single factor, so if you want to improve their ability to wage war focus on improving their ability to run their economy first or take the easy way out and give them more handicap bonuses on unit upkeep and particularly unit supply costs (in Civ4handicapInfos.xml).

Yeah, I've had experience there... one of the problems in making the Japanese aggressive in my Pacific scenario was that they start out with a bad financial situation. So basically, what you are saying is that if a civ starts out badly, it will not seek to behave aggressively to try to remedy that situation by capturing other cities and weakening its opponents?

They also need some 'encouragement' to produce appropriate units, or more correctly to not produce so many useless units (ships mainly, especially in the early game). I imposed limits to the number of ships they can build, by unitclass, in the SDK using the number of players, number of coastal cities and world size in general. The normal AI build descisions don't have limits built into them so the AI will continue building what it determines to be the best build for that city with little regard to anything else aside from some encouragement to build specific UNIT_AI types. This plays a part in their financial trouble as well, if the build hundreds of ships that they never use those ships are little more than a burden on their economy that pushes them into financial trouble which in turn forces them to stop attacking. This can be done in Python but can cause slowdowns if you're counting too many different unit types. You can also cheat and do it in xml alone with national unit limits.

My problem was not so much the production of useless units, but rather that they didn't use the ones they had to the greatest extent. I saw what seemed like dozens of ships just sitting in port while the enemy was running about wreaking havoc! :crazyeye: Artillery also sat outside of a city and bombarded it forever (I was using Dale's Ranged Bombardment mod) and the infantry didn't rush the enemy even though they could've easily won after two or three initial losses. Which brings me to the next point...

And finally, you can modifiy the AI so that it will attack with lower odds of winning. Although this won't always help them in the short run it has a number of positive effects in the long run such. Since the AI doesn't like to disband units this is a good way to weed out their weaker units through attrition.

Is that handled through the XML tag I listed earlier? I noticed that the attack odds are much higher for Napoleon and Montezuma, so I presume that's related to the overall leader aggressiveness. I wish the Civ 4 wiki hadn't disappeared...

Here's something that I noticed when I was making my recent mod: whenever I scripted reinforcements for a civ, I found that the AI would disband the new units if they did not have a promotion. Didn't seem to matter how bad off they were, or how much the units would've helped. They kept maybe one or two for city defense and the rest disappeared. I spent a lot of time trying to figure out why before I discovered that they only seemed to retain units that had promotions. Sort of a digression, but an interesting find anyway.
 
Here's some pointers that I had to finely tine to get a more aggressive AI.

First I will point out that I went too far with the RtW AI in 1.1 and it concentrated way too much on naval warfare and not enough on land. Though this is now fixed in RtW 1.2. :)

1. Make sure your AI's are making LOADS of money! Why? Because when an AI truelly flicks over to TOTALWAR and FINALWAR modes, it can spend up to 75% of its resources on the military alone, leaving not much to survive on. ;)

2. Make sure you have your UNITCOMBAT and UNITAI's all correct. It's pointless having UNITAI's such as UNITAI_SEA_EXPLORE on destroyers in a WW2 mod as the world is already known. Why? This cuts out useless choices from the AI (which incidentally work in full Civ, but not mods like ours). ;)

3. You need to increase the negative stuff happened to us remembers in leaderheads. This makes an AI hate you for longer (and hate you stronger) for doing something dodgy to it. :)

4. You will need to do some manipulation of the AI to point it towards the correct warplans. For instance, in RtW I do a check on if the AI isAtWar. If yes, then I force its warplan to TOTAL_WAR. Personally I think this one is the better plan as TOTAL_WAR will make the AI fight strongly for a long time to overcome a strong enemy. It affects every part of the AI to work towards the goal. Whereas DAGGER, RAID or other such warplans are short-term strong bursts with specific objectives. Be careful with FINAL_WAR as that will force the AI to hit with literally everything they have. But this leaves them undefended. :)

That would be my starting tips at this point. There's some SDK stuff you can do centred around AI_STRATEGY's, but that'll get you started. :D

Enjoy!
 
Yeah, I've had experience there... one of the problems in making the Japanese aggressive in my Pacific scenario was that they start out with a bad financial situation. So basically, what you are saying is that if a civ starts out badly, it will not seek to behave aggressively to try to remedy that situation by capturing other cities and weakening its opponents?
No, if you look in the code you'll see that the AI practically shuts down it's military (and military operations) if it gets into financial trouble. Considering how the AI handles it's economy this is probably a good thing as they'll seldom earn more GPT after capturing a city and the quick boost in gold from the capture won't last them long.

Is that handled through the XML tag I listed earlier? I noticed that the attack odds are much higher for Napoleon and Montezuma, so I presume that's related to the overall leader aggressiveness. I wish the Civ 4 wiki hadn't disappeared...
I tried that some time ago and couldn't see a substantial effect, but let me check the SDK for your answer, I'll post that in a few minutes. Even if it does work as expected it will likely apply to ALL odds which won't have a very good overall effect, it will just make that leader more suicidal.

Here's something that I noticed when I was making my recent mod: whenever I scripted reinforcements for a civ, I found that the AI would disband the new units if they did not have a promotion. Didn't seem to matter how bad off they were, or how much the units would've helped. They kept maybe one or two for city defense and the rest disappeared. I spent a lot of time trying to figure out why before I discovered that they only seemed to retain units that had promotions. Sort of a digression, but an interesting find anyway.
That sounds about right. The problem with standard 'epic' games is that most units produced normally will have promotions, sometimes several, with about the only exception being drafted units. In these cases the AI can frequently sit on massive armies of outdated units until it can afford to upgrade them.
 
XML question: What exactly does this do in LeaderheadInfos?

Code:
<iBaseAttackOddsChange>0</iBaseAttackOddsChange>
<iAttackOddsChangeRand>16</iAttackOddsChangeRand>

I presume this changes how willingly a leader will attack you when the odds are not in favor of victory?
I may have missed something but as far as I can tell this doesn't actually do anything in the game. It is used to set a variable (m_iAttackOddsChange) that never gets used anywhere :)
 
1. Make sure your AI's are making LOADS of money! Why? Because when an AI truelly flicks over to TOTALWAR and FINALWAR modes, it can spend up to 75% of its resources on the military alone, leaving not much to survive on. ;)

So will a lack of cash cause the AI to switch back over to limited war and lesser modes?

2. Make sure you have your UNITCOMBAT and UNITAI's all correct. It's pointless having UNITAI's such as UNITAI_SEA_EXPLORE on destroyers in a WW2 mod as the world is already known. Why? This cuts out useless choices from the AI (which incidentally work in full Civ, but not mods like ours). ;)

Did that. :D Don't know why I originally did some but not all.

3. You need to increase the negative stuff happened to us remembers in leaderheads. This makes an AI hate you for longer (and hate you stronger) for doing something dodgy to it. :)

Will that actually make them more likely to engage you once war has started, or does this simply increase the likelihood of war breaking out? (Either way it's good, since I want to focus on general AI issues and not necessarily ones specific to my scenarios.)

4. You will need to do some manipulation of the AI to point it towards the correct warplans. For instance, in RtW I do a check on if the AI isAtWar. If yes, then I force its warplan to TOTAL_WAR. Personally I think this one is the better plan as TOTAL_WAR will make the AI fight strongly for a long time to overcome a strong enemy. It affects every part of the AI to work towards the goal. Whereas DAGGER, RAID or other such warplans are short-term strong bursts with specific objectives. Be careful with FINAL_WAR as that will force the AI to hit with literally everything they have. But this leaves them undefended. :)

Ah, this must be it. :D

Code:
        def doAIWarPlans(self, playerNum):
                pPlayer = gc.getPlayer(playerNum)
                iTeam = pPlayer.getTeam()
                pTeam = gc.getTeam(iTeam)
                if (not pPlayer.isHuman() and pPlayer.isAlive()):
                    if (pTeam.getAtWarCount(false) > 0):
                        for iLoopTeam in range(gc.getMAX_CIV_TEAMS()):
                            if (iTeam != iLoopTeam):
                                if (pTeam.isAtWar(iLoopTeam)):
                                    pTeam.AI_setWarPlan(iLoopTeam, WarPlanTypes.WARPLAN_TOTAL)
                    else:
                        for iLoopTeam in range(gc.getMAX_CIV_TEAMS()):
                            if (iTeam != iLoopTeam):
                                pTeam.AI_setWarPlan(iLoopTeam, WarPlanTypes.WARPLAN_PREPARING_TOTAL)
                return

Where are all the warplans defined in the SDK? I didn't see the preparing war plan when I checked earlier.

I may have missed something but as far as I can tell this doesn't actually do anything in the game. It is used to set a variable (m_iAttackOddsChange) that never gets used anywhere :)

Why does that not surprise me? :lol: I just figured since Montezuma's was the highest, it must make the leader more suicidal.

Thanks to both of you for the useful information so far. :goodjob:
 
Where are all the warplans defined in the SDK? I didn't see the preparing war plan when I checked earlier.
CvEnums.h has the enum definition for the warplan types if you just want to see a list.

Code:
enum DllExport WarPlanTypes					// Exposed to Python
{
	NO_WARPLAN = -1,

	WARPLAN_ATTACKED_RECENT,
	WARPLAN_ATTACKED,
	WARPLAN_PREPARING_LIMITED,
	WARPLAN_PREPARING_TOTAL,
	WARPLAN_LIMITED,
	WARPLAN_TOTAL,
	WARPLAN_DOGPILE,

#ifdef _USRDLL
	NUM_WARPLAN_TYPES
#endif
};

You also have the Area AI types (same file):
Code:
enum DllExport AreaAITypes					// Exposed to Python
{
	NO_AREAAI = -1,

	AREAAI_OFFENSIVE,
	AREAAI_DEFENSIVE,
	AREAAI_MASSING,
	AREAAI_ASSAULT,
	AREAAI_ASSAULT_MASSING,
	AREAAI_ASSAULT_ASSIST,
	AREAAI_NEUTRAL,

#ifdef _USRDLL
	NUM_AREAAI_TYPES
#endif
};

Remember, an area is typically a landmass or body of water, a contiguos section of similar (land/water) tiles. So Washington DC and Los Angeles are in the same area along with Mexico City, Toronto, Nome, etc... So the area ai type can affect a potentially large area. A lot of people mis-read that to mean the same as vicinity, which in Civ4 it doesn't.
 
I strongly suggest against playing with the AREAAI's. I did for RtW 1.1 and completely screwed the AI. :(
 
So will a lack of cash cause the AI to switch back over to limited war and lesser modes?

No, their economy collapses and they go into revolt. Fun to watch really. :D

Will that actually make them more likely to engage you once war has started, or does this simply increase the likelihood of war breaking out? (Either way it's good, since I want to focus on general AI issues and not necessarily ones specific to my scenarios.)

The AI will remember longer and stronger what actions you took against them. It may influence war declarations, but it definitely influences them not to make peace with you. :)

Ah, this must be it. :D

Code:
        def doAIWarPlans(self, playerNum):
                pPlayer = gc.getPlayer(playerNum)
                iTeam = pPlayer.getTeam()
                pTeam = gc.getTeam(iTeam)
                if (not pPlayer.isHuman() and pPlayer.isAlive()):
                    if (pTeam.getAtWarCount(false) > 0):
                        for iLoopTeam in range(gc.getMAX_CIV_TEAMS()):
                            if (iTeam != iLoopTeam):
                                if (pTeam.isAtWar(iLoopTeam)):
                                    pTeam.AI_setWarPlan(iLoopTeam, WarPlanTypes.WARPLAN_TOTAL)
                    else:
                        for iLoopTeam in range(gc.getMAX_CIV_TEAMS()):
                            if (iTeam != iLoopTeam):
                                pTeam.AI_setWarPlan(iLoopTeam, WarPlanTypes.WARPLAN_PREPARING_TOTAL)
                return

Where are all the warplans defined in the SDK? I didn't see the preparing war plan when I checked earlier.

Yep, that's it. :)
 
Back
Top Bottom