Anti-piracy / blockade breaking naval AI

Maniac

Apolyton Sage
Joined
Nov 27, 2004
Messages
5,603
Location
Gent, Belgium
In the Planetfall mod, one of the biggest problems the AI is having, is fighting off naval native life units created by offshore fungal blooms, or just fighting off random naval native life wandering into its waters. From the Better AI code I saw that some code for naval blockade breaking was added. I hadn't examined it too closely yet at that point, but hoped that the naval situation would improve.

Unfortunately, after having added Better AI now, this doesn't seem the case. In good old fashioned Civ2 style, the AI just sends out single ships to attack the native life camping in its waters, the turn they're built on. What I do myself, is build up a numerical superiority, a critical mass, and only then move out of my coastal port cities to clear my waters from 'piracy' and hopefully establish a lasting dominance over my coastal waters. That way, with a numerical superiority, if I go one-on-one with a native life unit, and I lose, I still have other units to finish off the enemy unit, instead of just having given the enemy some free XP.

To try to improve the naval AI, it's useful to know the reasoning behind the current AI, in case I missed or misunderstand something.

So, jdog5000, would you be willing to share your thoughts on the current naval unit AI code?

I've had a look at the ATTACK_SEA unit AI, and I am confused about the eagerness of naval units to attack at bad odds.

Code:
	if (AI_anyAttack(1, 35))
	{
		return;
	}

	if (AI_anyAttack(2, 40))
	{
		return;
	}
(This is vanilla code for the record.)

If I understand this correctly, this means the AI is willing to attack any target if it has a 35% chance of success? Why would the AI want to do that?? :confused: They know they're likely to lose. Also, does the AI not look at all if the enemy is a single unit or part of a stack? Do they not look at the cost of its attacking unit? (Eg 35% odds with a 40 hammer unit is better than with a 80 hammer unit?)

The blockading code a bit lower I find even more confusing:

Code:
				if( iAttackers > (iBlockaders + 1) )
				{
					if( iAttackers > GC.getGameINLINE().getSorenRandNum(2*iBlockaders + 1, "AI - Break blockade") )
					{
						// BBAI TODO: Make odds scale by # of blockaders vs number of attackers
						if (AI_anyAttack(1, 5))
						{
							return;
						}

Why would the AI want to attack with 5% odds, unless it has really overwhelming numbers and the first units are just meant to soften up the target?

Also, I don't understand this part:

Code:
						if( getMoves() > 2 )  // be able pull back to city
						{
							if (AI_anyAttack(2, 5))
							{
								return;
							}

							if (AI_anyAttack(3, 10))
							{
								return;
							}
						}

My understanding of AI_anyAttack and AI_searchRange is that with AI_anyAttack(2, x) for instance, the AI will look for enemy units within a 2 * baseMoves() range. Thus if the AI unit has only three movement points left and the enemy unit is more than one baseMoves range away from the AI unit, it's never gonna get back to the city, as you state is the intention of that code.

Hope to hear your thoughts! :)
 
Basically, the naval and air unit AI in BTS is much less advanced than the land AI. It's quite clear they got it to a passable state (all the units move and will attack sometimes) and then focused on other things, it's simply not very smart.

So, yes, a UNITAI_ATTACK_SEA unit will attack a nearby enemy unit if it has 35% odds or better ... the 35% is misleading, there are several additional factors that can lower it significantly. This is going off memory, but for one thing when there are several units in a group, the odds threshold is lowered depending on how many units there are. In addition, the different AI leaders have craziness/courage ratings which adjust how much they're willing to fight at long odds.

The hammer value of the enemy unit is not taken into account as far as I know.

One reason why the odd thresholds are so low is that in vanilla Civ4 the lack of variety in boats for two-thirds of the game meant that attack odds were often 50% or less unless the enemy was already wounded. With triremes, privateers, and ship-of-the-line, etc in BTS, there's much more variety and chance for winning odds against healthy boats, but I don't think this section of code was tweaked for BTS.

The blockade code you looked at was intended to address a particular problem: During the Galleon & Caravel window, AI players used to produce many Caravel attack units. If a more-advanced enemy started a privateer blockade, the poor AI would have a bunch of these attack caravels sitting there in its city but they wouldn't fight back because they wouldn't form a big group. Like land attack units, attack sea units operate in ones and twos (on land there are attack city units which act like collection points for large stacks) and so these Caravels wouldn't see they had sufficient numbers to fight off the privateer. The thresholds were set so low because the Caravels only needed to damage the Privateer enough, then it would leave or other nearby unit AI types (escort, reserve, or even idle assault transports) would try to take it out.

I've been meaning for a while now to go back and rework that blockade code. Other parts of the AI have been tweaked so that AI players won't be sitting on huge stacks of mostly harmless Caravels any more. Beyond that, the existing logic doesn't really work and I could now write it much better. Among other things, I thought at the time that the range in AI_anyAttack was in tiles, not movement turns, so that part of it doesn't make sense as you pointed out.
 
Thanks for the informative reply!

Besides naval blockading, do you intend to ever revisit other naval AI in the future, or will I have to venture into that myself one day? :scared:

Anyway, I had another look at CvUnitAI::AI_finalOddsThreshold. As you say there's code that lowers the minimum required odds if the attacker has a bigger stack. But there isn't code that increases the odds if the defender has a bigger stack! That seems equally important. There's often little point in destroying an enemy stack, if the next turn my own now weakened stack will get counterattacked by nearby enemy units. Could AI_getPlotDanger and AI_getWaterdanger not be used in this function to improve the AI awareness of when it's a good idea to attack?
 
There are several Naval AI pieces on my todo list, but there's also a lot of stuff on my todo list ... so, yes I am going to look at Naval AI more, but not sure when.

I agree with you that that behavior needs some work, so it's just a matter of inspiration and time now.

As for AI_finalOddsThreshold, you are certainly right that it could use some scaling based on the number of enemies on the target plot or even nearby for opportunistic AI_anyAttack function. This function is used in four places, so I'll check whether scaling by number of enemies would be good in all cases. Also, it's going to be called a lot, so it has to be efficient.
 
Back
Top Bottom