Development:AIScripts
Vega Strike has completely programmable python AI scripts--but often times just editing an XML file with a list of actions at various distances and probabilities is sufficient and quite a bit more performant
AI scripts are selected as follows: the following two excel files in the ai/ folder are consulted ai/VegaEvents.csv The VegaEvents file is a table mapping combat_roles of the attacker to roles of his target. Combat roles are stored in the Combat_Role column in units.csv For instance if my starship is a BOMBER and I am targeting a BASE then vega strike will look in row BOMBER and column BASE and find the beginning of the name of the AI script thus it would be bomber.* where * might be .agg.xml or .civ.xml depending on the next file:
ai/VegaPersonalities.csv VegaPersonalities is a list of a factions and what AI scripts they wish to use Each listed faction is followed by a comma and then by a space separated list of extensions to use on their AI script. so if bomber was selected from VegaEvents.csv and the faction is merchant which has the second column "scared scared civ" there will be a 1/3 chance that bomber.civ.xml will be selected, otherwise bomber.scared.xml will be selected
if the file is not found bomber.agg.xml will be searched then default.civ.xml then default.agg.xml (I believe .py files are also searched)
Once an XML file is selected, it is parsed every frame to select an AI behavior for the starship to use when attacking its target.
AI scripts are selected as follows:
the following two excel files in the ai/ folder are consulted
ai/VegaEvents.csv
The VegaEvents file is a table mapping combat_roles of the attacker to roles of his target. Combat roles are stored in the Combat_Role column in units.csv
For instance if my starship is a BOMBER and I am targeting a BASE then vega strike will look in row BOMBER and column BASE and find the beginning of the name of the AI script thus it would be
bomber.* where * might be .agg.xml or .civ.xml depending on the next file:
ai/VegaPersonalities.csv VegaPersonalities is a list of a factions and what AI scripts they wish to use Each listed faction is followed by a comma and then by a space separated list of extensions to use on their AI script. so if bomber was selected from VegaEvents.csv and the faction is merchant which has the second column "scared scared civ" there will be a 1/3 chance that bomber.civ.xml will be selected, otherwise bomber.scared.xml will be selected
if the file is not found bomber.agg.xml will be searched then default.civ.xml then default.agg.xml (I believe .py files are also searched)
Once an XML file is selected, it is parsed every frame to select an AI behavior for the starship to use when attacking its target
The XML file selected has a simple format <AggressiveAI time="7"> is the header it tells the AI script how often to search for scripts and must be paired with a </AggressiveAI> at the very end of the file Between this header and footer is a list of actions that the AI is allowed to perform, each tagged by conditions that enable them to be selected and a priority to help the computer choose an action to perform
Lets take a look at an example: <hull max=".03" script="drop cargo" time="1" priority="8">
<hull max=".03" script="afterburn turn away" time="10" priority="8"> </hull>
</hull> This says if the hull is at most .03 and the hull is at most .03 drop cargo for a second and then turn away for 10 seconds with a priority of 8 nested script actions are conjoined together and if all their conditions evaluate to true they are performed in sequence. Noticed in the above example we specified the hull being at most .03 *twice* so that the condition would be evaluated in the same manner both times---this simply enables us to tell the computer to perform those two actions in sequence so that the AI computer does not drop all cargo at once but only drops cargo every 10 seconds and runs away
Lets fish up a little more complex example: <hull max=".6" script="evade up down" time="4" timetointerrupt="3" priority="7">
<fshield max=".25" script="evade up down" time="1" timetointerrupt="0" priority="7"> <rand max=".13" script="evade up down" time=".5" timetointerrupt="0" priority="7"/> </fshield>
</hull>
This translates into: if the hull is at most at 60% strength, the forward shields are at most 25% and the random number generator selects a number with 13% probability then evade up and down for 4 seconds, 3 of which are uninterruptible, then evade up and down for another 1.5 seconds which are interruptible
This timetointerrupt parameter can ensure that an AI is not constantly shifting between decisions but instead actually follows through on an action. It can help the AI "commit" to finishing a task instead of being interrupted--and hence should be used with caution with scripts that could cause collision--because a collision-imminent decision (as we shall see in a bit) needs to interrupt other choices with a high priority
Collision Avoidance:
<meterdistance max="30" script="afterburn turn away" time="7" timetointerrupt="3" priority="6">
<rand min=".4" script="afterburn fly straight" time=".5" timetointerrupt="1" priority="6"/>
</meterdistance>
This part of the script says: if the distance is at most 30 meters (this is adjusted for speed and acceleration) then turn around for 7 seconds (3 of those are uninterruptible) and then fly away for another half second. This would hopefully direct an AI to avoid a collision instead of playing chicken with a human (or computer ) opponent
However all of the scripts we have talked about before have a higher priority, so they're not considered interruptible with this particular command.. .however the above commands also move the ship AWAY from the target---so they aren't really the type of thing that could result in an intentional collision
Attacking Script: The script that needs to be interrupted by the above script follows later in the file:
<meterdistance min="60" max="500" script="turn towards itts" priority="4" time="5">
<meterdistance max="500" script="turn towards" priority="4" time="8"> <rand min=".5" script="loop around" priority="4" time="5"> </rand> </meterdistance>
</meterdistance> This says "if the distance is between 60 and 500, is at most 500 and the random number generator gives a number that has probability 50% then turn towards the target, giving it itts lead if available, then turn towards it without lead, then loop around it. Notice that this script is entirely interruptible if the AI ever gets within 30--and since the priority is lower than 6, it will indeed be overridden by the afterburn turn away listed above. But the above script is essentially the bread and butter of the AI--it directs it to turn towards its opponent and shoot like crazy (the shooting is handled in C code right now)
Another important facet of this attacking part of the AI is to have something that's true in all conditions...this means including a fallback that happens if the random number fails like so:
<meterdistance min="60" max="500" script="afterburn veer away" priority="4" tim\ e="2">
<meterdistance max="500" script="turn towards" priority="4" time="8"> </meterdistance>
</meterdistance>
and also some things to do if far away:
<meterdistance min="500" script="barrel roll" time="2" timetointerrupt="1">
<fshield max=".1" script="barrel roll" time="1"> </fshield>
</meterdistance> <meterdistance min="500" script="barrel roll" time="2" timetointerrupt="1">
<bshield max=".1" script="barrel roll" time="1"> </bshield>
</meterdistance> <meterdistance min="500" script="afterburn turn towards itts" priority="4" time="3"> </meterdistance>
Now as you may have noticed there are a lot of descriptions in script
script can be a python script (which executes turns, or fire commands, etc) or an XML script located in the scripts folder, but for the most part those scripts should simply be precanned ones that I've written in the Vega Strike C code
the prebaked scripts are listed as follows:
loop around fast aggressive loop around fast loop around slow aggressive loop around slow loop around aggressive loop around barrel roll veer away veer away itts veer and turn away veer and vector away afterburn veer away afterburn vector away match velocity fly straight fly straight afterburner afterburn fly straight do nothing take off coast to stop self destruct take off every zig afterburn turn towards afterburn turn towards itts cloak evade kick stop move to shelton slide skilled afterburner slide afterburner slide stop turn away afterburn turn away turn towards turn towards itts drop cargo drop half cargo drop one cargo roll right roll right hard roll left roll left hard evade left right evade up down afterburn evade left right afterburn evade up down
For a description of what each of these do see hard_coded_scripts.cpp