AI base planning and building
Lays a computer house's base out as an ordered node list, then resolves what to build next and where to put it.
A computer house does not weigh up what to build next. It works down a base node list: an ordered list in which each entry — a node — names one BuildingType and the cell that structure belongs on. Position in the list is the build order, and nothing else bears on it: there is no priority scoring, and the house always takes the first node it has not built yet.
Not every node names a structure at a place. A cell of 0,0 names no cell, and hands the spot to the placement search instead. And three of the values that would otherwise name a BuildingType are instructions to the planner: -1 asks for a base defense whose type the planner chooses, -2 stops the scan there, and -3 runs the perimeter wall planner.
Where the plan comes from
Section titled “Where the plan comes from”The list is carried in the house’s own map section, not in a section of its own. NodeCount gives the entry count and entries are read in order from zero-padded three-digit keys; a value beginning with - is one of the three instructions, otherwise the first field is an ObjectType ID and the next two are the cell X and Y. Structures a scenario starts with are ordinary map objects, which the node list then matches.
[GDI]NodeCount=4000=MYCONST,42,58 ; example construction yard BuildingType001=MYWEAP,45,58 ; example war factory BuildingType002=-1,0,0 ; base defense; the planner picks the type and the cell003=MYPOWR,0,0 ; example power plant BuildingType; cell picked at build timeA house whose list is empty generates one when either of two things happens: an MCV of a non-human house deploys into a ConstructionYard=yes BuildingType outside a campaign game, or a house passes to the computer. A scenario-supplied list suppresses generation entirely.
Building the plan
Section titled “Building the plan”- Candidates. A BuildingType is a candidate while all of this holds:
- its
Ownerincludes this house; - it is
AIBuildThis=yes; - its
TechLevelis within the house’s scenario tech level; - it is not
Weeder=yes, or the map carries a veinhole monster; - it is not the excluded plug — under the Firestorm addon one of the hard-coded IDs
GAPLUG2,GAPLUG3andGAPLUG4is drawn at random and left out.
- its
- Seed. Entry 0 of
BuildConst, which must also pass that filter, then unconditionally the firstBuildPowerentry the house may own. The first ownableBuildBarracksentry moves to the head of the candidate list and the first ownableBuildWeaponsentry to second place. - Expansion. Repeated passes append every candidate whose
Prerequisitelist the queue already satisfies, resolving a generic prerequisite throughBuildWeapons,BuildBarracks,BuildRadarorBuildTechand treating theBuildConstconstruction yard as always satisfied. AHelipad=yestype is appended one to three extra times; the hard-codedGAPLUGwaits for a pass that adds nothing else. - Refineries.
2 - Difficultyextra copies of the first ownableBuildRefineryentry, at random positions after the first refinery. - Defenses. A build cost running from the cost of queue entries 1 and 2 accumulates entry by entry, and before each entry the plan calls for
(cost - 2000) / 1500defenses scaled byNodBaseDefenseCoefficientfor a house named “Nod” and byGDIBaseDefenseCoefficientfor every other house. Each unit of shortfall becomes a-1placeholder, preceded by aWallTowernode for GDI. When the house is Nod, or whenAIBuildsWalls=no, further placeholders follow:(3 - Difficulty) * 3of them for a house named GDI, and(3 - Difficulty) * 2for every other house. - Wall. A
-3node closes the list whenAIBuildsWalls=yesand the house is either not Nod or hasNodAIBuildsWalls=yes.
Difficulty in steps 4 and 5 is the house’s own difficulty slot — [Easy] is 0, [Normal] 1 and [Difficult] 2 — and a computer house is handed the inverse of the setting the player chose. The table works both terms out for each setting. Read the two right-hand columns downward: the harder the player set the game, the more extra refineries the plan carries and the larger the placeholder counts in step 5 come out.
| Setting chosen | Slot the computer house holds | 2 - Difficulty, the extra refineries | 3 - Difficulty, the term in the placeholder counts |
|---|---|---|---|
| Easy | 2, the [Difficult] section | 0 | 1 |
| Normal | 1, the [Normal] section | 1 | 2 |
| Hard | 0, the [Easy] section | 2 | 3 |
The same 3 - Difficulty term caps the wall defenses a GDI house appends after its perimeter wall.
Choosing what to build next
Section titled “Choosing what to build next”A house takes the first node not counted as built while all of this holds:
- it is not a human player’s house;
- its country is not
MultiplayPassive=yes; - its production mode allows structure work;
- it has no structure already committed;
- it owns a construction yard.
A node counts as built under any of these:
- a building of the node’s own type, owned by this house, stands on the node’s cell;
- the node names a wall type and its cell carries that wall’s overlay;
- the node names a wall type and its cell carries any building.
A node whose cell is 0,0 never counts as built. A -3 node deletes itself before running the wall planner, and a -1 node or a cell-less WallTower node is deleted when the defense planner fails on it, taking the following node with it when it is a wall tower. Any other node becomes the house’s pending structure. Because the first unbuilt node is always the one taken, a node no owned factory can produce holds up every node behind it.
Choosing a spot
Section titled “Choosing a spot”Placement is resolved when the finished structure leaves the construction yard. A real cell on the matching node is used when the type is an upgrade or the compactness test accepts that cell, and otherwise a search runs and writes its result back into the node.
Placing any structure flags its footprint, expanded by AIBaseSpacing on all sides, as occupied by its house and grows that house’s base rectangle to contain it. The search ranks the frontier of that area — cells with at least one, but not all eight, occupied neighbors — nearest the base center for an ordinary structure and thinnest in existing defense coverage for a base defense, then steps outward from each ranked cell away from the mass of the base, clear of the structure’s own footprint plus AIBaseSpacing. A step is accepted while all of this holds:
- the step’s footprint rectangle, grown by that spacing, holds no cell this house already occupies;
- that same rectangle lies inside the playable area;
- every cell of the structure’s own foundation is clear to build on, except that a type laying its own tile underneath itself needs only one clear cell;
- the ground height at the step is within 2 of the height under the base center;
- the compactness test accepts the step.
The first two terms are settled together as one test, and that test is skipped altogether on a second pass over the ranked cells, so a cramped base still builds. A search that accepts nothing returns cell 0,0.
That compactness test passes unconditionally in a campaign game, so campaign bases spread wherever the other tests allow. Every other session type requires an already-occupied cell within the candidate footprint padded by AIBaseSpacing — one cell beyond that margin to the north and west, and twice the spacing plus one to the south and east — welding a skirmish or multiplayer base to what it holds.
An allied ground object standing in the placement zone is ordered to move and the factory waits PlacementDelay minutes. A permanent obstruction — an overlay, a terrain object, a building that cannot take the structure as an upgrade, or another house’s object — and a failed placement both abandon the structure: the factory refunds the cost already paid, deletes the object under construction, and clears the pending structure. The node is deleted when its type is a wall or a gate, and otherwise every node claiming that cell has its cell reset to 0,0. After a WallTower is placed, the next base-defense node moves onto the tower’s cell.
Base defenses
Section titled “Base defenses”The planner is handed a list of cells the base is expected to be attacked through: each one is a threat cell, and the list as a whole is the house’s threat ring. Exactly one thing ever fills it — the perimeter wall planner records the wall cells it laid, and only for a house named GDI — so every other house reaches the defense planner with no threat ring at all. The qualifications below all turn on which of those two cases applies.
A defense node is filled in against the quadrant of the base that needs it most. Each owned building’s anti-air, anti-armor and anti-infantry values are summed per quadrant and stamped into three per-cell coverage maps out to radius 6, falling off as value / ((distance - 1) * 0.1 + 1), and the lowest-total quadrant wins — restricted, where a threat ring was supplied, to the quadrants holding at least one of its cells. The category is the one least represented in that quadrant — ties resolve to anti-infantry first, then anti-armor over anti-air — because the predicted enemy composition it is measured against is a fixed 0.33 in each of the three.
A BuildingType is a candidate for that category while all of this holds:
- the house may own it;
- its value in that category is above zero;
- its
TechLevelis within the house’s reach; - its prerequisites are met by the non-defense buildings the house owns, plus
WallTowerfor GDI.
An empty list falls back to anti-armor, then anti-infantry, then anti-air, and all three empty deletes the node. One candidate is drawn at random, weighted by 10000 / cost + its value in that category, so cheap defenses dominate. It consumes the best-scoring cell of the threat ring where one was supplied, and takes the placement search’s result otherwise.
What the node then receives depends on which kind of node it is. A -1 placeholder takes both the chosen type and the chosen cell. A WallTower node keeps its own type and takes only the cell, and the chosen defense is written into the node after it at that same cell — but only while that following node is still a -1 placeholder. In that case a wall node already claiming the cell is deleted as well, and only when a threat ring was supplied.
A BuildingType’s three category values are computed from rules once the weapons are loaded, and only for a type with IsBaseDefense=yes. From its primary weapon, damage is Damage / (ROF * 0.025) truncated to a whole number. An anti-aircraft projectile sets AntiAirValue to damage multiplied by the warhead’s Verses percentage against heavy armor; an anti-ground projectile sets AntiArmorValue from that same heavy figure and AntiInfantryValue from the Verses percentage against none. All three are capped at MaximumBaseDefenseValue. A type without IsBaseDefense=yes, or with no primary weapon, keeps all three at zero and never enters a candidate list; at runtime a building whose own value is zero reports the first non-zero value among its plugged-in upgrades instead.
Walls and gates
Section titled “Walls and gates”The wall ring is the base rectangle grown by one cell on each side, walked along its four edges. A cell takes a wall while all of this holds:
- its height is within 2 of the height under the base center;
- neither it nor its outward neighbor is rock, water or ice;
- it carries no overlay;
- neither it nor its outward neighbor holds a building;
- neither it nor its outward neighbor holds a terrain object;
- its ramp is flat;
- it lies inside the playable area.
A run becomes wall nodes once it reaches five cells, or sooner when an overlay or a ramp cuts it short.
Wall nodes come from the first ownable ConcreteWalls entry and are all appended before any gate node. Gate nodes — EWGates on the north and south edges, NSGates on the east and west — take the midpoint of a run and consume three wall slots each; a run cut short by an overlay or a ramp is laid as plain wall. For GDI the wall cells also become the threat ring the defense planner draws from, and pairs of a WallTower node and a -1 node are appended, 0.2 per wall node and capped at (3 - Difficulty) * GDIWallDefenseCoefficient+GDIWallDefense. The base rectangle then becomes the wall ring, so the next wall is planned one ring further out.
Power and money interventions
Section titled “Power and money interventions”A power plant node is inserted immediately before the node the house is about to build while all of this holds:
- the session is not a campaign game;
- the node’s own drain added to the house’s current drain exceeds its current power output;
- the node is not the
BuildConstconstruction yard; - the node’s type draws power at all.
Which plant goes in depends on the house. GDI inserts GDIPowerTurbine when it owns a GDIPowerPlant with a free upgrade slot and a random draw falls under AIUseTurbineUpgradeProbability — a fraction of 1 that defaults to 1, so the turbine is taken whenever a slot is free unless the value is lowered — and GDIPowerPlant otherwise; every other house inserts NodAdvancedPower when the buildings it owns meet that type’s prerequisites, and NodRegularPower otherwise.
A house that cannot make money, again only outside campaign games, sells its base from the back of the node list forward until the proceeds cover a harvester — where it owns both a refinery and a war factory — or a refinery otherwise, abandons its factories, and either orders that harvester or inserts a refinery node at the current build position. Selling out the whole list without raising enough sends every unit it owns to hunt.
Rebuilding
Section titled “Rebuilding”Rebuilding needs no separate mechanism: a destroyed structure stops matching its node, and the node becomes the next hole in the list. When a building is taken off the map, every other node claiming its cell has its cell cleared, and outside campaign games an IsBaseDefense=yes node is retired to a -1 placeholder so the planner picks a fresh type and cell for it.
Parsed settings without effect
Section titled “Parsed settings without effect”[AI] carries a block of ratio and limit settings that no decision reads: RefineryRatio, RefineryLimit, BarracksRatio, BarracksLimit, WarRatio, WarLimit, DefenseRatio, DefenseLimit, AARatio, AALimit, TeslaRatio, TeslaLimit, HelipadRatio, HelipadLimit, AirstripRatio, AirstripLimit, BaseSizeAdd, InfantryReserve, InfantryBaseMult and PowerEmergency. The type lists BuildDefense, BuildPDefense, BuildAA and BuildHelipad are parsed but never consulted; base defenses come from the computed values above, not from a list. PowerSurplus is parsed into the rules but never reaches a house, whose own power margin stays at zero, so the power interjection fires on the first shortfall rather than on a configured cushion. PercentBuilt in a house’s map section is read and written back unchanged and controls nothing.
Related settings
32 of 32
| Key | Description | Value | When omitted |
|---|---|---|---|
AIBaseSpacingglobal rules | Cells of clearance kept around a building when base ground is reserved and computer placements are searched. | integer | 1 |
AIBuildThisBuildingType | Allows a computer house to put the BuildingType into the base plan it generates. | boolean | no |
AIBuildsWallsglobal rules | Lets a computer house close its base plan with the node that runs the perimeter wall planner. | boolean | yes |
AIUseTurbineUpgradeProbabilityglobal rules | The chance that a computer house named "GDI" answers a power shortfall with a turbine upgrade rather than another power plant. | floating point | 1 |
BuildBarracksglobal rules | The barracks a computer house resolves a generic barracks prerequisite to, in order of preference. | typelist | (empty) |
BuildConstglobal rules | The construction yard BuildingType; only the first entry is read. | typelist | (empty) |
BuildPowerglobal rules | The power plants a computer house plans first, in order of preference. | typelist | (empty) |
BuildRadarglobal rules | The buildings a computer house resolves a generic radar prerequisite to, in order of preference. | typelist | (empty) |
BuildRefineryglobal rules | The refineries a computer house plans and measures its income against, in order of preference. | typelist | (empty) |
BuildTechglobal rules | The buildings a computer house resolves a generic tech prerequisite to, in order of preference. | typelist | (empty) |
BuildWeaponsglobal rules | The war factories a computer house resolves a generic factory prerequisite to, in order of preference. | typelist | (empty) |
ConcreteWallsglobal rules | The walls a computer house builds its base perimeter from, in order of preference. | typelist | (empty) |
ConstructionYardBuildingType | A BuildingType with this flag animates while it produces, refuses ordinary undeploy orders, and starts a computer house's base when an MCV deploys into it. | boolean | no |
EWGatesglobal rules | The gates a computer house fits into the east-west runs of its base perimeter, in order of preference. | typelist | (empty) |
GDIBaseDefenseCoefficientglobal rules | Scales how many base defenses every computer house except one named "Nod" plans against its accumulated build cost. | floating point | 1 |
GDIPowerPlantglobal rules | The BuildingType a computer house named "GDI" inserts to cover a power shortfall. | class | none |
GDIPowerTurbineglobal rules | The BuildingType a computer house named "GDI" inserts to cover a power shortfall while it owns a power plant with a free upgrade slot. | class | none |
GDIWallDefenseglobal rules | The fixed part of the cap on wall tower and base defense pairs a computer house named "GDI" appends after planning its perimeter wall. | floating point | 6 |
GDIWallDefenseCoefficientglobal rules | The difficulty-scaled part of the cap on wall tower and base defense pairs a computer house named "GDI" appends after planning its perimeter wall. | floating point | 3 |
HelipadBuildingType | Lets a BuildingType accept an aircraft as a docking target and be approached at its docking cell rather than its center. | boolean | no |
IsBaseDefenseBuildingType, TeamType | Gives a BuildingType the computed ratings the computer picks base defenses by, or counts a TeamType against its house's defensive team total. | boolean | no |
MaximumBaseDefenseValueglobal rules | Caps each of the three defense values computed for a base defense BuildingType. | integer | 60 |
NSGatesglobal rules | The gates a computer house fits into the north-south runs of its base perimeter, in order of preference. | typelist | (empty) |
NodAIBuildsWallsglobal rules | Lets a computer house named "Nod" close its base plan with the node that runs the perimeter wall planner. | boolean | yes |
NodAdvancedPowerglobal rules | The BuildingType every computer house except one named "GDI" inserts to cover a power shortfall once it can build it. | class | none |
NodBaseDefenseCoefficientglobal rules | Scales how many base defenses a computer house named "Nod" plans against its accumulated build cost. | floating point | 1 |
NodRegularPowerglobal rules | The BuildingType every computer house except one named "GDI" inserts to cover a power shortfall. | class | none |
NodeCountscenario bases | The number of base node entries read from the house's section. | integer | 0 |
PlacementDelayglobal rules | Minutes a factory waits before trying again when the object it finished cannot leave yet. | floating point | .05 |
VersesWarheadType | The percentage of a weapon's damage the warhead delivers against each armor class, in armor order. | string | 100%,100%,100%,100%,100% |
WallTowerglobal rules | The BuildingType that joins a brick or sandbag wall run from any direction. | class | none |
WeederBuildingType, UnitType | Makes a BuildingType the structure vein harvesters dock at, or a UnitType a vein harvester. | boolean | no |
No keys match the current filters.