[Lua] AI Control

Tiramisu

Warlord
Joined
Aug 16, 2013
Messages
148
Location
Leonberg (BW, Germany)
This can be a very big topic, so I want to to subdivide this in smaller projects:

Tactical AI
- creating a path finding algorithm (in progress)
- choosing destinations (pending task)
- moving units in formations (pending task)
Combat AI
- simulating combats (pending task)
- letting the AI conquer cities (pending task)
Builder AI
no specific tasks yet
 

Attachments

  • Multiple A Star.png
    Multiple A Star.png
    51.5 KB · Views: 1,307
  • Multiple A Star (narrow way).png
    Multiple A Star (narrow way).png
    46.5 KB · Views: 1,357
Last edited:
Tactical AI
At first I want to start to improve the tactical AI, i.e. simply moving the AI in a way that their units get in advantageous positions or simply to get their endangered units out of the danger zones.
In order to avoid that the AI does its own unit movements we can set their unit movement to 0 at first, which is an easy task.

Now the first important step for this sub-project is creating a function that actually moves a unit from one field to the another. For this purpose we need a path-finding algorithm, because Firaxis did not provide us with a proper move-unit-to-function. The only proper way to move units is using
Code:
UnitManager.RequestOperation
but it can only be accessed for the local player, which it is not easy to use for AI players .

Now there is another function called UnitManager.MoveUnit to move units. You can use it like this:

Code:
function MoveUnitToPlot(pUnit, pPlot)
    UnitManager.RestoreMovementToFormation(pUnit)
    UnitManager.RestoreUnitAttacks(pUnit)
    UnitManager.MoveUnit(pUnit, pPlot)
end
However, in my tests this function often cannot find the right path. Also bugs can occur if you want to move units more than one tile away (e.g. the unit graphics can be displayed on a wrong spot).

Luckily the MoveUnit-function works very well, if you only move to an adjacent tile. So if we had a path finding algorithm like the A* algorihm we would be able to use the MoveUnit-function even for long distances by moving units one tile after the other along the calculated path.
(Btw. my tests confirmed that MoveUnit is able to embark units with the right tech and move them together with ships. Only special operations like unit swapping or attacking cannot be done with MoveUnit.)

Another application of such an path algorithm is moving more than one unit in a formation:
When using our path finding algorithm we can also set which plots may be used and which not. Of course impassable plots like mountains cannot be used by default, but you can also set tiles of an existing path as impassable for any further paths to avoid path crossings.
In the path finding algorithm we can also give plots next to existing paths a higher priority to make units move in a closed formation. It should look something like this:

Spoiler :
multiple-a-star-png.498630


The orange hex fields in this image are the starting and the ending plot. The first path is the black one in this example. Then we create the two blue paths on the left and on the right side of the black one, and so on. Then we sent units to the starting points of these different paths one by one. Finally these units can start to move along their paths until they reach the enemy.

Only when there are too many obstacles (grey plots) we can allow paths to cross sometimes:

Spoiler :
multiple-a-star-narrow-way-png.498631


Of course there are more details to think of to make this work properly, but I think I will share my further thoughts on this later, once we actually have a good path finding algorithm.

So here are the first goals for this project:

  1. Implement a suitable path finding algorithm that does not cost too much performance .
  2. Decide which plots the AI needs to go to or which plots need to be avoided.
  3. Reuse the path algorithm in a way that allows units to move in a proper formation.
  4. Find paths for situations when the enemy is nearby: avoiding exposed units, retreating units, replacing low health units with fresh ones, etc.
 
Last edited:
Combat AI
This is a step further than the tactical AI. In this sub-project we need tools that allow the AI to attack and conquer cities in addition to only being able to move around.
Finally we need to tell the AI how to move units during combat and which enemy targets should be attacked first.

As I have already mentioned it is not easy to make the AI attack other units or cities, because some Lua functions are restricted to the local player. It would be doable to set an AI player as the new local player and avoid that the human players sees the UI of another player, but due to my tests it can cause some annoying lags to do that. So we should not use the functions for the local player in every turn for every AI player.

Combats are actually not a big deal, because we can simply simulate them by calculating and setting the unit damages (also we can use combat unit animations, if we want). For this purpose we need to have a correct combat damage formula. Right now there is a formula, but it probably needs to be confirmend and also we need a formula for attacking city defenses.

Now letting the AI conquer a city is harder to simulate. We could destroy the old city and create a similar city for the conqueror with the attributes of the old city like buildings or city plots of the original city (like in my free city states mod), but unfortunately you cannot set the original owner or original capital property for that city.
Another possible way to conquer cities is to use something like
Code:
local pMilitaryAI = pAttacker:GetAi_Military();
pMilitaryAI:StartScriptedOperationWithTargetAndRally("Attack Enemy City", ...)
...
pMilitaryAI:AddUnitToScriptedOperation(iOperationID, pUnit:GetID())

to make the AI attack a city. I have not tried this yet, but apparently it works in the Nubia Scenario script.
The reason you need to set a city as an AI target is that otherwise the AI would probably not use its melee units for conquering it. Even if you let an AI unit spawn next to city with 0 hitpoints the AI would be too dumb to conquer it.
 
Last edited:
Now there is another function called UnitManager.MoveUnit to move units. You can use it like this:
However, in my tests this function often cannot find the right path. Also bugs can occur if you want to move units more than one tile away (e.g. the unit graphics can be displayed on a wrong spot).
So... are you saying that this function can be used by AI (non-LocalPlayer) and it actually moves a unit?
 
Before Gathering Storm I have tested it and it worked. Since UnitManager.MoveUnit can move units only one tile reliably I was also working on a pathfinding algorithm, which also worked (with very good performance). I just needed to finish my work on checking movement modifiers, but I am not finished yet, because it is not easy to check which unit modifiers are active.
 
It was not just the graphics. When there were obstacles the pathfinding for this lua function failed even on a short route. E.g. I saw units moving back and forth without ever reaching their goal. I have not tested the behavior in GS, but I do not think Firaxis fixed this. Still you can try it on your own, if you wish.
 
Back
Top Bottom