Artificial Intelligence

 

Introduction to Artificial Intelligence

Artificial intelligence (AI) in Armada encompasses the way in which a Craft or a group of Craft function (such as choosing special weapons to use, how the vessels fit in formations, deciding which target to attack, etc). Likewise this AI determines how non-player controlled factions behave (what the faction builds and when and where it sends Craft and why).

Although this AI is relatively inflexible, it can still be modified using a variety of files:

Build List files allow you to decide how the AI constructs its base, which units it constructs.

Goal Parameter files enable the AI to choose how to defend its base, units, and how to attack and withdraw dependent on rough situations.

Faction Configuration ODF files determine some of the tendencies for the AI (such as when to retreat an individual ship, or which special weapons have an effect on the faction).

Formation files determine how Craft sort themselves within formations.

Individual Craft AI is largely determined by the classlabel, AI process of the ODF and other hardcoded processes, but it is also influenced by the weapon ODF files and the parameters within. This latter part largely not understood, but is occasionally explained in the appropriate ODF commands pages.

Build List Files

Path: Fleet Operations/Data/AI/AIPs

When making an artificial intelligence (AI) for a new faction, or even modifying an existing faction's AI, you will need to edit the Artificial Intelligence Personality (.aip) Build Lists files. These are the files that determine the units that the AI will build, how many, in what order, and what requirements the AI will need to meet in order to make them. Each faction has a set of these files which can be edited with any text editor:

{faction name}_build_list
{faction name}_defensive_list
{faction name}_endgame_list
{faction name}_instant_action_build_list
{faction name}_offensive_list

In an unmodified version of Fleet Ops, only the {faction name}_instant_action_build_list file is used, and the others are left empty. Note that it is not understood how the AI switches between different build lists at this time.

The {faction name} portion of the build list name is identical to the name used by the Faction configuration name ODF command. For instance, romulanempire_instant_action_build_list is named accordingly because in the romulan.odf, there is the entry, name = romulanempire. This is important if you want to create an AI for a new faction for Fleet Operations, as you must ensure that the prefix of your AI build lists are named identically to that of your {faction}.odf, so that Fleet Ops knows that this is the AI to be used for the faction in question.

When you create a new set of AIPs you will need this header:

#include "aipdef.h" // Includes a file with generic codes

int checkTechnologyAvailable = 0; // Tells the AI to ignore the techtree (allows the AI to build ships that are not in the techtree files, yet are in the build lists). An entry of "1" would cause the AI to obey the techtree files

Way_Better_Build_List_Element the_build_list[MAX_ELEMENTS] = // This line states how the AIP values are read, as indicated in the Aipdef.h file
{

For more information on the #include "aipdef.h" and Way_Better_Build_List_Element the_build_list[MAX_ELEMENTS] lines, please read Build List Customization.

Since we are using Way_Better_Build_List_Element for the build list we will require the following elements:

    "ODF name",                 build amount,base location,  max build,  techlevel,

In other words, in your AIPs, it should look something like this (note the extra comma at the end of the string and the additional spaces between numbers):

    "fed_outpostZ",             1,0, -1, -1,

Note that the ODF name does not require the .odf extension.

Build Amount

This element simply defines how many of the item (vessel, station, or research) will be built at the specific line. All the items on the line need to at least be in production before the AI will continue on to the next line.

In this example we are assuming that the AI had already been instructed to build 2 Antares Yard and 2 Eraudi Yard.

    "fed_intrepid",             3, // Build 3 Intrepids
    "fed_defiant",              2, // Then build 2 Defiants

The AI can now build 2 Intrepids at once (out of the 3 that are needed to complete the line), since one Intrepid is queued up at each Antares Yard.

However, the AI cannot build any Defiant class vessels, as it still has a single Intrepid class left to build. This means that so long as those two Antares Yards are producing the first two Intrepids, the Eraudi Yard is doing nothing.

The next example is a much better use of the AI’s resources.    "fed_intrepid",             2, // Build 2 Intrepids
    "fed_defiant",              2, // Then build 2 Defiants
    "fed_intrepid",             1, // And after that, build 1 Intrepid

The AI will use both Antares Yards to build the first 2 Intrepids. Once the Intrepids have started construction, it will proceed to queue up the 2 Defiants. Thus once at least one Intrepid has finished production, the AI will queue up an additional Intrepid to finish off the build amount list. As a result, the AI will have continuous production.

Base Location

This entry tells the AI where to build (or research) on a map. The AI will choose a location based on where a resource is located. Although this seems simple enough, due to each map having different amounts of resources, you do not want the AIP to list too many base locations for separate and important structures, or else it will be forced to build these structures within your own base!

“0” refers to the AI’s starting starbase (or if the AI does not have a beginning starbase, it refers to the resource that is closest to its starting position. "1" refers the the next closest resource and so on and so forth.

For the AI, resource priority appears to be tritanium and then dilithium (with infinite versions of these resources taking the highest priority). Metal is the highest priority of all (Armada II planets), but metal is not used in Fleet Ops for a mineable resource. Since Fleet Ops' maps always contain infinite tritanium moons, the AI will preferentially build at these locations first.

    "fed_outpost",              1,0, // Build 1 Outpost at the starting location
    "fed_storage_dock"          1,1, // Build 1 Storage Dock at the next closest and highest priority resource location

Note that if the AI cannot find space to build the Storage Dock at Base Location 2, it will build it by default at Base Location 0.

Just as structures can be built at different base locations, research and ship construction can also take place at different base locations (provided the proper structures have been built at those same locations).

    "fed_antares_yard",         1,0, // Build 1 Antares Yard at the starting location
    "fed_antares_yard",         1,1, // Build 1 Antares Yard at the next closest and highest priority resource location
    "fed_intrepid",             1,1, // Construct 1 Intrepid from the Antares Yard located at the previous location
    "fed_sf_science"            1,0, // Build 1 Starfleet Science building at the starting location
    "fedR_defpatterns"          1,0, // Research Defense Patterns at Starfleet Science at the starting location

In this example, because the Intrepid was given a base location of "1" to build from, it will build at and guard the Antares Yard that was built at Base Location 1, even if the Antares Yard at the starting location lies unused. However, if there is no Antares Yard at Base Location 1, the Intrepid will be built anyway, at the Antares Yard at Base Location 0.

Note that combat vessels by default will guard the Base Location that they have been assigned to.

Bear in mind that this value appears to be temperamental, probably because we do not understand all the nuances.

Maximum Build

The maximum number to build describes simply how many times the AI will be forced to process a particular line if it loses the unit (vessel, station, or research) indicated by the line.

In this example, it is possible to see that the maximum number of units to be built at a particular line is determined by multiplying the Build Amount value by the Maximum Build value.

    "fed_intrepid",             3,{}, 2 // Build a maximum of 6 Intrepids
    "fed_defiant",              2,{}, 2 // Build a maximum of 4 Defiants

Although normally the AI will follow a linear progression; finishing one line before moving onto the next and so on. If a unit is lost, the AI will check to see if the maximum number to build is met and reimplement that line if necessary, before moving on once again. In other words, this number determines how many times (if at all) the AI enters a loop, whereby it is forced to keep rebuilding a unit before it can move onto its next lines.

Once the maximum number of units has been built - as specified by this value - the line will be ignored for the rest of a game.

Bear in mind that when you do in fact want to create an infinite loop (rebuilding a destroyed unit over and over), the Maximum Build value can be set to -1.

    "fed_saber",                4,{}, -1 // Rebuild the Saber an infinite number of times if lost

This command can be very useful for rare items that you want the AI to always rebuild with the utmost priority, such as starbases. However, it is not necessarily wise to use this command for readily destroyed units, since you will force the AI into a loop and it will never build to higher technology levels (assuming that this line is early in the AIP) since it will be forced to keep rebuilding this line.

Remember that it is always possible to simulate a command to rebuild units by placing another (or several) non-infinite line with the units in question later in the AIP and thereby avoid a dreaded build loop.

Technology Level

This entry allows us to set items (vessels, structures, and research) that become available at the beginning of a “technology level” and unavailable once a new “technology level” is reached.

There are five possible technology levels, as indicated with the positive values 1-5. "0" indicates that the unit can always be built by the AI without any special requirement other than being added into the proper techtree files (if checkTechnologyAvailable is not set to 0).

Once the item with the next positive number has been built, the AI considers itself to have reached the next tech level.

    "fed_mediterraneanZ",       {},{}, {},  1, // Once the Mediterranean has started construction, the AI will reach Tech Level 1

Now this is all well and good, but what is the point of reaching a tech level?

Now that the AI has reached a technology level it can be instructed to not build any older weak and expensive ships any longer, as it has better cheap ships to build. To indicate this, we use negative numbers.

    "fed_mandril",              4,0, -1,  0,
    "fed_newtonZ",              1,0, -1,  0,
    "fed_venture",              1,0, -1,  0,

    //Base Vessels
    "fed_saberZ",               3,0, -1,  -1, // Saber class

    //Techphase 1
    "fed_antares_yardZ",        1,2, -1,  0,
    "fed_platform_phaserZ",     1,1, -1,  0,
    "fed_platform_phaserZ",     1,2, -1,  0,
    "fed_platform_phaserZ",     1,3, -1,  0,
    "fed_platform_phaserZ",     1,4, -1,  0,
    "fed_sf_engineeringZ",      1,0, -1,  2, // Starfleet Engineering

In this extended example, starting the production of Starfleet Engineering marks entry into Technology Level 2. Since Sabers are set at "-1", once Starfleet Engineering commences construction, the AI will no longer build the "Saber line", regardless of its Maximum Build value (meaning once the Saber is destroyed, it won't be replaced).

Note that to restrict an item from being built in Technology Level 2 we use "-1" and not "-2". This is because the minus sign is not a negative sign, but rather it indicates an "up to" sign. In other words, "-1" indicates to the AI not to build units up to Technology Level 1. "-6" appears to serve the same function as putting in "0".

Closing Build Lists

After each ship / station or research has been completed, the AI reads the file from the top and fills in anything missing before proceeding to the next line, although we believe the GameObject ODF command "originalClass" overwrites this.

To close the AIP file you need to add this at the end of the file:

};

Build List Customization

AIPdef.h File

The AIP definitions file indicated by the #include "aipdef.h" comment sets how the Build List entries are read by the game engine and as well as allowing customization of the Build Lists.

Before creating a Build List, or adding new items into a Build List, these two global values should be checked:

#define MAX_BUILD_LISTS 200 // The maximum number of different Build List files that can be made for each faction

#define MAX_ELEMENTS 200 // The maximum number of buildable / researchable entries that can be had in a Build List. If set lower than the actual number of build items in a list file, the game will crash

At the start of the Build List AIPs you will notice a line, “Way_Better_Build_List_Element”. This line refers to one of four different types of AI Build Lists. These are the

  • “Build_List_Element” - only uses the object name and Build Amount variable.
  • “Better_Build_List_Element” - uses the object name, Build Amount and Base Location variables.
  • “Mo_Better_Build_List_Element” - uses the object name, Build Amount, Base Location, and Maximum Build variables.
  • “Way_Better_Build_List_Element” - uses all four variables.

It is technically possible to make your own list using the existing elements in the Aipdef.h file. Thus, if you want to make an AI that does not use the Max Build variable and not use “0” all the time, then you can remove (or comment out) that particular element from the Aipdef.h file.

These are the elements and what they correspond to:

  • “char unit_type_name[80];” the object name. The “[80]” in the object name refers to the maximum characters the name can be. It is assumed that this can be increased.
  • “double units_to_build;” - Build Amount variable.
  • “int m_base_num;” - Base Location variable.
  • “int m_buildMAX;” - Max Build variable.
  • “int m_techLevel; - Tech Level variable.

Newdefault.aip File

The newdefault.aip file includes a whole host of parameters which are further detailed in the Personality Parameters section. It also includes some values that are not overwritten by the Goal Parameter files (some should not be modified), of which the known (important) ones will be discussed here.

These values allow you to set what resources the AI will mine, as well as what resource it values most and thus will build a base next to. If set to zero, the AI will not mine the resource.

As a consequence, if you want to allow the AI to mine metal in Fleet Ops, you will need to set resource_metal_tendency to greater than 0.0:

double resource_dilithium_tendency = 1.0;
double resource_latinum_tendency = 1.0;
double resource_metal_tendency = 0.0;
double resource_biomatter_tendency = 0.0;

Goal Parameter Files

The Artificial Intelligence Personality (.aip) Goal Parameter files are used to determine the behavior of the AI on a global scale. These parameters cannot be specified on a per-faction basis. These have the following names in the .aip files and presumable all can use the same variables:

a2_aggressive
a2_defensive
a2_exploration
a2_hard_aggressive
a2_hard_defensive
a2_hard_exploration
a2_very_aggressive
a2_modified_aggressive
a2_modified_defensive
a2_modified_exploration

Although in Armada II these files were linked to switching Build List AIPs, since Fleet Ops does not use different Build List files, it is not certain how the Personality Parameter files are operating - only that, in fact, these files are all being used.

Paramater Interactions

In one of the rare occasions of thorough commenting, Dr. Ian (who developed Armada II's AI) provided an in depth explanation of how the parameters interact and are used by the AI scheduler to assign Craft to goals.

The steps in a scheduling phase are first described followed by details of how the computations at selected steps are made.

Scheduler 12 step program:

  1. A strategic map is created by dividing the map into grid squares
  2. Each grid square has one of each goal type associated with it.
  3. Compute the raw priority of each goal at each grid square.
  4. Compute the match utility between every squad and goal.
  5. Sort matches highest to lowest.
  6. Examine highest match that contains a squad with uncommitted units.
  7. Commit units from squad in match to associated goal.
  8. If the goal has enough unit strength committed to it, command those committed units to move to the grid cell of the goal.
  9. When all units on the team have been committed to goals, go to step 11.
  10. Otherwise examine next match and go to step 7.
  11. Rollback committed units from goals that still do not have enough troop strength and mark those units invalid for the goal.
  12. Go to step 6.

Step 1, the Strategic Map

Parameters are specified in the strategic_AI_config.txt file.

Parameters that are important to the strategic AI are:

// number of map units per grid cell (i.e. 400x400 units per AI strategic grid cell)
#define goal_map_resolution 400

// Fraction of bleedover during threat relax
double relaxation_coefficient = 0.8;

// Number of threat relax cycles. This becomes how far away a threat is felt.
int relaxation_cycles = 2;

Step 2, goals are assigned to grid squares

Escort goals are the exception to this rule. One escort goal is created for every unit on your team that is of the Freighter Class. The four goals that are created for each map grid cell are the: Attack Base Goal, Attack Goal, Defend Goal and Explore Goal.

Step 3, compute the raw priority of each goal

The raw priority is computed for each goal type in this way:

Attack Goal:

If the grid cell has enemy stations or contains no enemy threat, the goal is invalid. Otherwise, the value is the SUM of these factors:

  1. Distance To Our Empire
    • * AIP->distance_from_home_priority_modifier
  2. Distance To Enemy Empire
    • * AIP->distance_from_enemy_priority_modifier
  3. Threat in Map Cell
    • * AIP->attack_troops_priority
  4. AIP->perimeter_priority (if a Perimeter Map Cell)

Defend Goal:

If the grid cell contains no friendly stations, the goal is invalid. Otherwise, the value is the SUM of these factors:

  1. Distance To Our Empire
    • * AIP->distance_from_home_priority_modifier
  2. Distance To Enemy Empire
    • * AIP->distance_from_enemy_priority_modifier
  3. Threat in Map Cell
    • * AIP->attack_troops_priority
  4. AIP->perimeter_priority (if a Perimeter Map Cell)
  5. Number of Our Stations in Cell
    • * AIP->defend_buildings_priority

Attack Base Goal:

If the grid cell contains no enemy stations, the goal is invalid. Otherwise, the value is the SUM of these factors:

  1. Distance To Our Empire
    • * AIP->distance_from_home_priority_modifier
  2. Distance To Enemy Empire
    • * AIP->distance_from_enemy_priority_modifier
  3. Threat in Map Cell
    • * AIP->attack_troops_priority
  4. AIP->perimeter_priority (if a Perimeter Map Cell)
  5. Number of Enemy Stations in Cell
    • * AIP->attack_enemy_base_priority

Explore Goal:

If the grid cell as already been explored, the goal is invalid. Otherwise, the value is the SUM of these factors:

  1. Distance To Our Empire
    • * AIP->distance_from_home_priority_modifier
  2. Distance To Enemy Empire
    • * AIP->distance_from_enemy_priority_modifier
  3. AIP->perimeter_priority (if a Perimeter Map Cell)
  4. AIP->exploration_priority

Escort Goal:

If the craft this escort goal is attached to is destroyed, the goal is invalid. Otherwise, the value is the SUM of these factors:

  1. Distance To Our Empire
    • * AIP->distance_from_home_priority_modifier
  2. Distance To Enemy Empire
    • * AIP->distance_from_enemy_priority_modifier
  3. AIP->perimeter_priority (if a Perimeter Map Cell)
  4. AIP->escort_priority           

Step 4, compute the match utilty between a squad and goal

The squad match value is computed from the average matching value for the units in a squad. The match utility of a unit the SUM of these factors:

  1. Distance from unit to goal
    • * AIP->distance_from_goal_match_modifier
  2. Raw Priority of goal.

Step 7, commit units from squad in match to associated goal

Units in a squad are committed based on their match utility; i.e. closest units are committed before further ones.

Step 8, check if the goal has enough unit strength committed to it

The Attack Goal, Defend Goal and Attack Base Goals, currently only require that the total shield strength of enemy units at the target is less than the total shields of the committed units.

Note: Force matching values are not currently used.

The Escort Goal is satisfied when units with shields that exceed 1000 * the Build Time of the ship have been committed. This obviously needs a more logical measure.

The Explore Goal is satisfied when at least one ship has been committed to it.

Parameter List and Functionality

With that noted, it is quite difficult to give any reasonable indication of how to use the codes provided, other than to place a copy of the original comments.

Note, be very careful when changing these goal evaluation values as they can cause out of sync issues in multiplayer games, as well as crashes and other unexpected behavior.

/////////////////////////////////////////////////////////////////////
// I. Threat Map
// In general this will not need to be adjusted
// Parameters used to compute the threat map.

// Iteration for relaxing grid borders
// NOTE: DO NOT CHANGE
int relaxation_cycles = 1;                

// Relaxation bleedover
// NOTE: DO NOT CHANGE
double relaxation_coefficient = 0.5;        

// How much to reduce danger recorded in grid cell each cycle
// NOTE: DO NOT CHANGE
double danger_diminishment = 1;

/////////////////////////////////////////////////////////////////////
// III. Evaluated/execute goal counts
//
// Used to specify how many of each goal type to evaluate and how many to execute.  Small counts increase performance, but decrease intelligence.  
// NOTE: The MAX_EXEC numbers have positive values that should not exceed 1000;
// NOTE: You can 'turn off' goals by specifying a MAX_EXEC count of 0 or limit the goals executed by specifying a smaller number.

// ATTACK BASE goals
// NOTE: If this value is set to 1, only the one highest priority enemy base will ever be attacked at a given time.
// NOTE: If this value is set to 'n', at most the 'n' highest priority enemy bases will ever be attacked at a given time.
// NOTE: If this value is set to 0, no enemy bases will be attacked.
int MAX_EXEC_ATTACK_BASE = 3;

// ATTACK goals
// NOTE: If this value is set to 1, only the one highest priority grid with enemy in it will be attacked at a time with enemy will be attacked at a given time.
// NOTE: If this value is set to 0, no grids with enemy units will be attacked.
int MAX_EXEC_ATTACK = 3;

// DEFEND goals
// NOTE: If this value is set to 1, only the one highest priority base will be defended at a time.
// NOTE: If this value is set to 'n', only the 'n' highest priority bases will be defended at a given time.
// NOTE: If this value is set to 0, none of your bases will be defended.
int MAX_EXEC_DEFEND = 2;

// ESCORT goals
// NOTE: If this value is set to 1, only the one highest priority escortable ship will be escorted at a time.
// NOTE: If this value is set to 'n', at most the 'n' highest priority escortable ships will be defended at a given time.
// NOTE: If this value is set to 0, none of your ships will be escorted.
int MAX_EXEC_ESCORT = 0;

// EXPLORE goals
// NOTE: If this value is set to 1, only the one highest priority unexplored grid square will be explored at a time.
// NOTE: If this value is set to 'n', at most the 'n' highest priority unexplored grid cells will be explored at a given time.
// NOTE: If this value is set to 0, none of your ships will be escorted.
int MAX_EXEC_EXPLORE = 2;

// RESOURCE goals
// NOTE: If this value is set to 1, only the one highest priority grid cell with moons will be defended at a time.
// NOTE: If this value is set to 'n', at most the 'n' highest priority grid cells with moons will be defended at a given time.
// NOTE: If this value is set to 0, none of your grid cells with moons will be defended.
int MAX_EXEC_RESOURCE = 1;

// NOTE: DO NOT change MAX_EVAL_ values.
int MAX_EVAL_ATTACK_BASE = 20;
int MAX_EVAL_ATTACK = 20;
int MAX_EVAL_DEFEND = 10;
int MAX_EVAL_ESCORT = 10;
int MAX_EVAL_EXPLORE = 10;
int MAX_EVAL_RESOURCE = 10;
/////////////////////////////////////////////////////////////////////
// IV. Raw Priority parameters
//
// The raw priority of each goal in a grid square is computed by summing the relevant values below.

/////////////////////////////////////////////////////////////////////
// ALL goals add these terms:
/////////////////////////////////////////////////////////////////////

// NOTE: Positive for emphasis away from home, negative for emphasis near home
int distance_from_home_priority_modifier = 0;

// NOTE: Positive for emphasis away from enemy, negative for emphasis near enemy
int distance_from_enemy_priority_modifier = 0;

// NOTE: Positive for emphasis in region between home and enemy
int perimeter_priority = 0;

// NOTE: Positive to avoid places where we have lost more units than we have killed (not currently computed)
int avoid_danger_priority_modifier = 0;

/////////////////////////////////////////////////////////////////////
// Selected goals add these terms (as indicated):
/////////////////////////////////////////////////////////////////////

// This priority is multiplied by each enemy craft in a grid cell for
// ATTACK and DEFEND goals; for ATTACK_BASE goals this number is multiplied by -1 * the number of enemy craft.
// NOTE: Increase positive values to make the AI more likely to attack and defend places with many enemy ships (and undefended bases).
// NOTE: Decrease negative values to make the AI less likely to attack and defend places with many enemy ships (or more likely to attack defended bases)
int attack_troops_priority = 1000;

// Added for each friendly base in a grid cell for DEFEND goals.
// NOTE: Increase this value to make the AI more likely to defend bases, or decrease to make the AI less likely to defend bases. (valid values: -99999 to 99999)
int defend_priority = 50;

// Added for each enemy base in a grid cell for ATTACK_BASE goals.
// NOTE: Increase this value to make the AI more likely to attack enemy bases, or decrease to make the AI less likely to defend bases.(valid values: -99999 to 99999)
int attack_enemy_base_priority = 1500;

// Added for each unit of intrinsic value in a grid cell for ATTACK and ATTACK_BASE goals.
// NOTE: Increase this value to make the AI more likely to attack valuable targets, or decrease to make the AI less likely to attack valuable targets.  (valid values: 0 to 99999)
int intrinsic_value_bonus = 500;

// Added to unexplored grid cell for EXPLORE goals.
// NOTE: Increase this value to make the AI more likely to explore unexplored grid cells, or decrease to make the AI less likely to explore unexplored grid cells. (valid values: -99999 to 99999)
int exploration_priority = 1000;

// Added for each escorted ship in a grid cell for ESCORT goals.
// NOTE: Increase this value to make the AI more likely to escort escortable ships, or decrease to make the AI less likely to escort escortable ships.(valid values: -99999 to 99999)
int escort_priority = 0;

// Added for each moon in a grid cell for RESOURCE goals.
// NOTE: Increase this value to make the AI more likely to defend moons, or decrease to make the AI less likely to defend moons.(valid values: -99999 to 99999)
int resource_priority = 600;                

/////////////////////////////////////////////////////////////////////
// V. Match Priority parameters
// The matching value between each goal in a grid square and a craft that can execute that goal is computed by summing the raw_priority (computed above) with the following terms:

/////////////////////////////////////////////////////////////////////
// Based on Distance:
/////////////////////////////////////////////////////////////////////

// The distance from the craft to the goal is multiplied by this term for every legal goal and craft match. 
// NOTE: The more negative the term, the more likely craft will be assigned to nearby goals before goals that are far away. 
double distance_from_goal_match_modifier = -0.01;

// Minimum number of craft to use for each goal type
// NOTE: If this value is set to 'n', then a minimum of 'n' ships will be used to escort escortable craft even when they are unthreatened by nearby enemy craft.
int min_escort_force = 1;

// NOTE: If this value is set to 'n', then a minimum of 'n' ships will be used to defend bases even when they are unthreatened by nearby enemy craft.
int min_defense_force = 2;

// NOTE: If this value is set to 'n', then a minimum of 'n' ships will be used to explore an unexplored grid cell.
int min_exploration_force = 1;

// NOTE: If this value is set to 'n', then a minimum of 'n' ships will be used to attack bases and enemy ships irregardless of the strength of enemy craft defending.
int min_attack_force = 1;            

// NOTE: If this value is set to 'n', then a minimum of 'n' ships will be used to defend grid cells with moons even when they are unthreatened by nearby enemy craft.
int min_resource_force = 1;

/////////////////////////////////////////////////////////////////////
// Resource Tendencies:
/////////////////////////////////////////////////////////////////////
// Priority for this AIP to build each type of resource mining bases.
// If you are not Borg, you cannot build metal, and the value will be ignored. Larger numbers make it more likely to build that type of base

double resource_dilithium_tendency = 1.0;
double resource_latinum_tendency = 0.0;
double resource_metal_tendency = 1.0;
double resource_biomatter_tendency = 1.0;

// How likely are we to build resource bases far from our main base
// ACTUALLY, this is how IMPORTANT it is that a base be close to our main base
// This gets multiplied by the inverse of the distance...
double resource_distance_multiplier = 10000.0;

// How likely are we to prefer resources with more health
// Since this looks at the actual value of how many units of resource something has, we need to scale this down.  A planet having 32000 resources vs. a planet with 8000
double resource_health_multiplier = 0.0001;

// how likely are we to build bases we don't already have
double resource_lack_multiplier = 2.0;

// what is the penalty for building near an enemy resource
double resource_enemy_penalty = 100.0;


/////////////////////////////////////////////////////////////////////
// VI.
//

// How much force to use for each goal
int max_escort_force = 1;
int max_defense_force = 1;
int max_exploration_force = 1;
int max_attack_force = 1;
int max_resource_force = 1;
int min_perimeter_force = 1;
int max_perimeter_force = 1;

// How much emphasis to pay to high threat regions
int attack_region_priority = 1000;

// TROOP COMMITMENT PARAMETERS
double max_matching_force_ratio = 1.5;
double min_matching_force_ratio = 0.5;

// Global value for scripted p's
int scripted_priority = 1;                

// RAW BID MODIFIERS
int max_danger_raw_bonus = 10;
int max_threat_raw_bonus = 10;
int human_target_raw_bonus = 200;
int max_misc_bid_bonus = 600;
int persistence_modifier = 100;

// PATROL CONTROL
int patrol_one_in_n = 10;

// Penalty per failure to reach an exploration cell
int explorationFailurePenalty = 50000;                   

// Use the fleet AI system
double fleetAIRatio = 100;

// STRATEGY UPKEEP VARIABLES
// How long to wait before recomputing the strategy
int recompute_strategy_period = 300;

// Bonus threat for enemy held planets
int planetThreatBonus = 300000;

scoutRandomlyRatio // unknown!!!

AI Debugging Tool

If for some reason the AI is not performing as expected in a game, or you just want to see how it "thinks", this complex tool can probably help to identify the problem(s). Although you can use the tool with more than one AI operating at the same time, it is greatly recommended to only use it when there is a single AI on a map so that the number of variables is kept to a minimum.

To gain access to the Build List Debugging Tool you must be in an Instant Action game. By pressing Alt+Shift+A it is possible to cycle through a total of four screens, each of which will give information about the AI in real-time on the left hand side of the screen, as well as on the Minimap display.

The AI player that is displayed can be changed by using the Ctrl+Up / Down Arrow. The color of the text corresponds with the AI player's color.

Build List Information

A total of two sets of information will be shown on the left hand side of the screen (the Build List and the Personality Parameters). The third set of information is non-functional in Fleet Ops.

Elapsed Time:{#.#} // Displays how long the AI has been active
Strategic AI Cycle: {#} // Displays how many times the AI has checked its build list. Does not vary with gamespeed. The AI adds new information to its strategic map every 400 cycles (so it takes 400 cycles before a Craft becomes a threat for instance, or 400 cycles before the Craft's movement to a new location is registered).

AI Debug Team 2 // The AI player currently being displayed
    Dilithium // The amount of Dilithium the AI possesses
    Latinum // The amount of Tritanium the AI possesses
    Metal // The amount of Collective Connections the AI possesses
    Biomatter // The amount of Supply the AI possesses
    Officers: 0/20 // Not a resource in Fleet Ops
    Crew: 999999999 // Not a resource in Fleet Ops

AIP: a2_{example}.aip // Indicates what 'Personality' is being used

BUILD LIST AIP: {faction}_instant_action_build_list.aip // Indicates the AIP being used

Tech Level: {#} // Indicates what Technology Level the AI is on
    Last Asked To Build: {odf name} // Indicates the next line the AI will build (for ships / research)
    From List Line: {#} // Indicates what Build List line the AI is on
    Last line is special, refer to below

As above, the last line is special - it refers to the reason as to why an item cannot be built. Note that because Fleet Ops makes use of some features not available in the original Armada II game, this feature may not always be accurate (such as for special factions like the Borg).

NO PRODUCER AVAILABLE // There is not a ship or station available to build the desired item. If all ships and stations are not busy doing something else, there is something wrong with the Build List

NO TECHNOLOGY AVAILABLE // The AI cannot build this line because the techtree will not let it (such as when a vessel is demanded before the shipyard that builds it has finished constructing). Always bear in mind that the AI will move to the next line as soon as a unit has begun construction - not finished. This is a place where a lot of mistakes happen, so check the techtree

NOT ENOUGH DILITHIUM // Not enough Dilithium available

NOT ENOUGH LATINUM // Not enough Tritanium available

NOT ENOUGH METAL // Not enough Collective Connections available

NOT ENOUGH BIOMATTER // Not enough Supply available

CONSTRUCTING // The AI is in the middle of constructing a group of units on the same line

Minimap Information

The AI adds new information to its strategic map every 400 cycles (so it takes 400 cycles before a Craft becomes a threat for instance, or 400 cycles before the Craft's movement to a new location is registered). The AI processes 60 cycles per second.

A total of four sets of information will be displayed on the Minimap as you cycle through the modes:

First Mode: Strategic Goals

Higher priority goals are brighter.

  • Purple - Explore
  • Red - Attack Base (Craft that have is_starbase = 1)
  • Yellow - Attack Vessels
  • Green - Defend Base (Craft that have is_starbase = 1)
  • Blue - Resource

Second Mode: Map Explored

Displays what the AI has explored.

Third Mode: Threat Map

Displays what parts of the map are considered a greater threat ranging from green (least) to red (greatest threat).

Fourth Mode: DeathMap

Displays whether the AI has lost more ships that it has destroyed in an area (and vice-versa).

Black indicates equal losses, lighter shades of blue indicate that the AI has killed more ships than lost, and lighter shades of red indicate that the AI has lost more ships than it has killed.

Determined by the maximum number of shield hitpoints that a Craft can have if that Craft was destroyed. For example, the AI has 3 units, each with 1000 maximum shield hitpoints and the Player has 6 units each with 500 maximum shield hitpoints. Should the Player and the AI lose all their units, the DeathMap will be black (equal losses). Should the AI lose 2 units and the Player lose 6 units, the DeathMap will be blue (the AI has killed 3000 shield hitpoints worth of units, and lost only 2000 shield hitpoints).

Craft AI Formations

Path: Fleet Operations/Data/AI/formations

When creating a new formation for grouped GameObjects to use you will need to edit or create the .frm files (assuming that you have already formatted a new formation ODF to define the button, position, and tooltip). In order to relay what formation ODF corresponds to which formation .frm file, the ODF command, param = #,  must be utilized:

param = 1 // References m_formationID = 0
param = 2 // References m_formationID = 1
param = 3 // References m_formationID = 2

The formdef.h file defines what each line in a formation file does and the maximum number of slots which may make up a formation.

int MAX_FORMATION_SIZE = 40; // In Fleet Ops only a max of 40 slots are defined (1 for each possible vessel) in each formation (this can be set higher if necessary)

When you create a new formation file you will need this header:

#include "formdef.h" // Includes the definition file

char formationName[16] = "Wedge"; // FormationName should match the tooltip string in the ODF for the formation. If it does not, the tooltip takes priority. The number in the brackets defines the maximum amount of characters in the string

int m_formationID = 0; // Determines which formation ODF uses this file

float m_shipRadius = .4; // Determines the spacing of each vessel in the formation

FormationSpecElement formationSpec[MAX_FORMATION_SIZE] = // This line states how the formation values are read, as indicated in the formdef.h file
{
//--------------------------------------------------------------------

The next line starts with four numbers. The first integer refers to the vessel identification. Numbers do not need to be in order, but they will be read in order by Armada II (meaning that a column indicated by "0" will always come first) and must not repeat.

The next value, a float, designates the X-coordinate of the offset for this column, and the one after that the Y-coordinate of the offset, and then the Z-coordinate of the offset. Floats may be positive or negative and must be separated by commas (including from the starting integer).

    0,   0.0,  7.0,   0.0,
    1,   1.0,  0.0,   4.0,

After these values come a series of characters, each of which must be separated by a comma and surrounded by apostrophes.

    0,   0.0,  0.0,   0.0, 'S', 'F', 'D', 'C', 'B', 'X', '?',
    1,   1.0,  0.0,   0.0, 'S', 'F', 'D', 'C', 'B', 'X', '?',

These characters refer to the shipType string in a GameObject's ODF. The order in which they are present indicates the priority for the AI to assign a ship type to a given position in the column. The first character receives priority, followed by the next and so on.

To close the FRM file you need to add this at the end of the file:

};