Here's what you're coding with
When you're writing code for Future Terminal, the main object to code against is found at api.
There are
also a bunch of global CONSTANTS.
Functions take time to run and so have a cost or delay associated with them. Any function that is a server command might be rejected: your code will continue to run, but the command will not be accepted by the server. Make sure your code handles this gracefully.
Here are some simple code examples to get you started:
// Get your base position
let basePos = api.getBasePosition();
let baseX = basePos[0];
let baseY = basePos[1];
// Get your units
const units = api.getUnits() || [];
// Get enemy units
const enemies = api.getEnemyUnits() || [];
// Spawn a worker at your base
api.spawnUnit(UNIT_WORKER, baseX, baseY);
// Spawn a soldier for defense
api.spawnUnit(UNIT_SOLDIER, baseX, baseY);
// Spawn a crawler for attack
api.spawnUnit(UNIT_CRAWLER, baseX, baseY);
// Move a unit to a specific location
const myUnits = api.getUnits() || [];
if (myUnits.length > 0) {
api.moveUnit(myUnits[0].id, baseX + 100, baseY + 100);
}
// Build a cannon near your base
api.spawnBuilding(BUILDING_CANNON, baseX + 200, baseY);
// Build a solar farm
api.spawnBuilding(BUILDING_SOLAR_FARM, baseX - 200, baseY);
// Get ores and workers
let ores = api.getOres() || [];
const workers = api.getUnits().filter(u => u.k === UNIT_WORKER);
// Send first worker to nearest ore
if (workers.length > 0 && ores.length > 0) {
const worker = workers[0];
const nearestOre = ores[0];
api.moveUnit(worker.id, nearestOre.x, nearestOre.y);
}
Units will attack nearby enemies whenever they can.
Why would you do it manually? Why not let the units attack nearby enemies whenever they can?
Agree.
These functions are sent to the server as requests and have a cost or delay associated with them. They might be rejected.
| Function | Description |
|---|---|
getBasePosition() |
Get your base position as [x, y] or null |
getData() |
Get your persistent data string |
setData(data) |
Set your persistent data string |
consoleLogToUser(message) |
Log a message to the user console |
consoleErrorToUser(message) |
Log an error message to the user console |
moveUnit(id, x, y)
|
Move a unit to a point |
setUnitStance(id, stance)
|
Set a unit's stance (1=StandGround, 2=Defensive, 3=Aggressive) |
getUnits() |
Get all your units |
getBuildings() |
Get all your buildings |
getResources() |
Get your resources (ore, metal, energy) |
spawnBuilding(k, x, y)
|
Spawn a building (k is BuildingType value) |
spawnUnit(k, x, y)
|
Spawn a unit (k is UnitType value) |
destroyUnit(id) |
Destroy one of your units |
destroyBuilding(id) |
Destroy one of your buildings |
getOres() |
Get all ores |
getEnemyUnits() |
Get enemy units |
getEnemyBuildings() |
Get enemy buildings |
mine(id, targetId) |
Mine an ore (id is unit id, targetId is ore id) |
load(id, targetId, x, y)
|
Load ore into a building (id is unit id, targetId is building id, x/y are coordinates) |
getBasePosition()Returns your base position as [x, y] or null if no base exists.
getData()Returns your persistent data string.
setData(data)Sets your persistent data string. data is a string.
consoleLogToUser(message)Logs a message to the user console. message is a string.
consoleErrorToUser(message)Logs an error message to the user console. message is an object.
moveUnit(id, x, y)
Moves a unit to a point. id is the unit ID, x and y are coordinates.
setUnitStance(id, stance)Sets a unit's stance. id is the unit ID, stance is 1 (StandGround), 2 (Defensive), or
3 (Aggressive).
getUnits()Returns a list of PlayerUnit objects that are yours.
getBuildings()Returns a list of PlayerBuilding objects that are yours.
getResources()Returns an object with ore, metal, and energy properties.
spawnBuilding(k, x, y)
Creates a building. k is the BuildingType value (see BuildingType),
x and y are coordinates. May be rejected if you have reached the control limit of 100 units and buildings combined.
spawnUnit(k, x, y)
Creates a unit. k is the UnitType value (see UnitType), x and
y are coordinates. May be rejected if you have reached the control limit of 100 units and buildings combined.
destroyUnit(id)Destroys one of your units. id is the unit ID.
destroyBuilding(id)Destroys one of your buildings. id is the building ID.
getOres()Returns a list of OreRoot objects.
getEnemyUnits()Returns a list of PlayerUnit objects that are enemies.
getEnemyBuildings()Returns a list of PlayerBuilding objects that are enemies.
mine(id, targetId)Mines an ore. id is the unit ID, targetId is the ore ID.
load(id, targetId, x, y)
Loads ore into a building. id is the unit ID, targetId is the building ID,
x and y are coordinates.
| Name | Value | Cost | Energy Cost | Life | Build Limit | Description |
|---|---|---|---|---|---|---|
Hub |
1 | 1000 | 0 | 10000 | 1 | Build other buildings, process ore, and spawn units |
House |
2 | 5 | 5 | 1000 | 0 (unlimited) | Increase control limit |
Cannon |
3 | 20 | 15 | 1000 | 4 | Shoot at enemy units and buildings |
OreProcessor |
4 | 10 | 10 | 200 | 3 | Process ore into metal |
OrbitalMassDriver |
5 | 50 | 50 | 500 | 1 | Send metal as required |
Artillery |
6 | 100 | 40 | 1500 | 2 | Shoot at enemy units and buildings but far away |
LightFactory |
7 | 75 | 30 | 2500 | 2 | Factory for producing light units |
SolarFarm |
8 | 5 | 0 | 200 | 10 | Generates energy |
EnergyStorage |
9 | 10 | 5 | 200 | 10 | Stores energy |
ArtilleryFactory |
10 | 200 | 60 | 1000 | 1 | Factory for producing artillery units |
Wall |
11 | 1 | 1 | 100 | 0 (unlimited) | Defensive wall structure |
LaserCannon |
12 | 30 | 20 | 1200 | 4 | Energy-based defensive cannon |
MissileCannon |
13 | 40 | 25 | 1100 | 4 | Missile-based defensive cannon |
| Name | Value | Cost | Energy Cost | Life | Sight Range | Description |
|---|---|---|---|---|---|---|
Worker |
1 | 10 | 5 | 10 | 300 | Harvest ore |
Tank |
2 | 50 | 20 | 100 | 500 | Attack enemy units and buildings |
Archer |
3 | 80 | 30 | 100 | 400 | Attack enemy units and buildings from a distance |
Crawler |
5 | 20 | 10 | 300 | 350 | Cheap numerous units that attack enemy units and buildings at close range |
LightTank |
6 | 100 | 40 | 120 | 500 | Light armored combat unit |
MediumTank |
7 | 200 | 60 | 180 | 500 | Medium armored combat unit |
HeavyTank |
8 | 300 | 80 | 250 | 500 | Heavy armored combat unit |
Artillery |
9 | 400 | 100 | 100 | 500 | Long-range artillery unit |
ScoutPlane |
10 | 25 | 15 | 50 | 900 | Air unit for reconnaissance and scouting |
Unit stance determines whether a unit will move to attack enemies or not.
| Name | Value | Description |
|---|---|---|
StandGround |
1 | Unit will only move when told to do so |
Defensive |
2 | Unit will move to attack nearby enemies |
Aggressive |
3 | Unit will move to attack enemies, even if they are far away |
Weapon types define the offensive capabilities of units and buildings.
| Name | Value | Damage | Range | Cooldown | Shot Count |
|---|---|---|---|---|---|
KineticLightMachineGun |
1 | 1 | 300 | 1 | 1 |
ExplosiveMediumMissileRack |
2 | 5 | 700 | 5 | 1 |
KineticLightShotgun |
3 | 5 | 250 | 2 | 1 |
KineticMediumAutocannon |
4 | 20 | 500 | 1 | 5 |
ExplosiveHeavyProjectile |
5 | 100 | 3000 | 30 | 1 |
KineticLightTank |
6 | 5 | 300 | 5 | 1 |
KineticMediumTank |
7 | 10 | 350 | 7 | 1 |
KineticHeavyTank |
8 | 20 | 400 | 8 | 1 |
KineticArtillery |
9 | 50 | 500 | 10 | 1 |
EnergyLaserBeam |
10 | 15 | 600 | 2 | 1 |
ExplosiveMissile |
11 | 30 | 800 | 5 | 1 |
AirScoutMachineGun |
12 | 1 | 350 | 1 | 1 |
Future requirements may require operation of more customisable units. This is not yet confirmed.
Let's discuss.
Global constants are available in your code. These correspond to enum values and can be used directly in API calls.
| Constant | Value | Corresponds To |
|---|---|---|
BUILDING_HUB |
1 | BuildingType.Hub |
BUILDING_HOUSE |
2 | BuildingType.House |
BUILDING_CANNON |
3 | BuildingType.Cannon |
BUILDING_ORE_PROCESSOR |
4 | BuildingType.OreProcessor |
BUILDING_ORBITAL_MASS_DRIVER |
5 | BuildingType.OrbitalMassDriver |
BUILDING_ARTILLERY |
6 | BuildingType.Artillery |
BUILDING_LIGHT_FACTORY |
7 | BuildingType.LightFactory |
BUILDING_SOLAR_FARM |
8 | BuildingType.SolarFarm |
BUILDING_ENERGY_STORAGE |
9 | BuildingType.EnergyStorage |
BUILDING_ARTILLERY_FACTORY |
10 | BuildingType.ArtilleryFactory |
BUILDING_WALL |
11 | BuildingType.Wall |
BUILDING_LASER_CANNON |
12 | BuildingType.LaserCannon |
BUILDING_MISSILE_CANNON |
13 | BuildingType.MissileCannon |
| Constant | Value | Corresponds To |
|---|---|---|
UNIT_WORKER |
1 | UnitType.Worker |
UNIT_TANK |
2 | UnitType.Tank |
UNIT_ARCHER |
3 | UnitType.Archer |
UNIT_CRAWLER |
5 | UnitType.Crawler |
UNIT_LIGHT_TANK |
6 | UnitType.LightTank |
UNIT_MEDIUM_TANK |
7 | UnitType.MediumTank |
UNIT_HEAVY_TANK |
8 | UnitType.HeavyTank |
UNIT_ARTILLERY |
9 | UnitType.Artillery |
UNIT_SCOUT_PLANE |
10 | UnitType.ScoutPlane |
| Constant | Value | Corresponds To |
|---|---|---|
WEAPON_KINETIC_LIGHT_MACHINE_GUN |
1 | WeaponType.KineticLightMachineGun |
WEAPON_EXPLOSIVE_MEDIUM_MISSILE_RACK |
2 | WeaponType.ExplosiveMediumMissileRack |
WEAPON_KINETIC_LIGHT_SHOTGUN |
3 | WeaponType.KineticLightShotgun |
WEAPON_KINETIC_MEDIUM_AUTOCANNON |
4 | WeaponType.KineticMediumAutocannon |
WEAPON_EXPLOSIVE_HEAVY_PROJECTILE |
5 | WeaponType.ExplosiveHeavyProjectile |
WEAPON_KINETIC_LIGHT_TANK |
6 | WeaponType.KineticLightTank |
WEAPON_KINETIC_MEDIUM_TANK |
7 | WeaponType.KineticMediumTank |
WEAPON_KINETIC_HEAVY_TANK |
8 | WeaponType.KineticHeavyTank |
WEAPON_KINETIC_ARTILLERY |
9 | WeaponType.KineticArtillery |
WEAPON_ENERGY_LASER_BEAM |
10 | WeaponType.EnergyLaserBeam |
WEAPON_EXPLOSIVE_MISSILE |
11 | WeaponType.ExplosiveMissile |
WEAPON_AIR_SCOUT_MACHINE_GUN |
12 | WeaponType.AirScoutMachineGun |
| Constant | Value | Corresponds To |
|---|---|---|
STANCE_STAND_GROUND |
1 | UnitStance.StandGround |
STANCE_DEFENSIVE |
2 | UnitStance.Defensive |
STANCE_AGGRESSIVE |
3 | UnitStance.Aggressive |
Here's how your commands compete
Most commands received by the server are queued and run in order, after a little bit of grouping. The server will run as many commands as it can. If you send too many commands, only the first few will run. The rest will be ignored.
In more technical terms, the server runs commands in batches. Each batch is a set of commands that were received within a certain time period. The size of each batch varies according to server performance.
When commands are rejected
Server commands may be rejected for various reasons. When a command is rejected, the server returns a rejection code. Your code should handle these gracefully.
| Code | Value | Description |
|---|---|---|
OK |
0 | Command was accepted |
FAULT_BLOCKED_BY_TERRAIN |
11 | Command blocked by terrain, insufficient resources (metal), invalid location, or other general failure |
FAULT_INSUFFICIENT_ENERGY |
12 | Insufficient energy to perform the command |
FAULT_CONTROL_LIMIT_EXCEEDED |
13 | Control limit exceeded - you can control a maximum of 100 units and buildings combined |
FAULT_MISSING_PAYLOAD |
127 | Command payload is missing |
FAULT_MISSING_PLAYER_ID |
128 | Player ID is missing from the command |
Add some helpful global functions for yourself, they will run locally and have little cost. Here are some ideas:
| Function | Description |
|---|---|
distanceBetweenEntities(a, b)
|
Get the distance between two entities |
distanceBetween(x1, y1, x2, y2)
|
Get the distance between two points |
getNearest(entities, x1, y1)
|
Get the nearest entity to a point |
getNearestWithinRange(entities, x1, y1, range)
|
Get the nearest entity to a point within a range |