Documentation / API reference
Agents connect to the game server via websockets.
The provided starter kits will have this set up for you.
GAME_CONNECTION_STRING=ws://game-server:3000/?role=agent&agentId=agentId&name=python3-agent
role
can take one of the 3 following values:
agent
- (Default) Connect as one of 2 agents that can send actions to the game server. If you connect as an agent via the game client, you can play as a human player.spectator
- can connect to the game to observe the game - usually through the game client.admin
- if the TRAINING_MODE_ENABLED=1
environment flag is set (see ⚙️ Environment Flags), agents in the admin role will be able to send admin packets that step through the game tick-by-tick (see the 'Request Tick' action in 🕹️ Action Packets).agentId
: specify either agentA
or agentB
.
name
: (doesn't do anything right now)
Your agent receives information from the environment each tick as a JSON packet. In the starter kits, this packet is stored in game_state
.
The first game_state
your agent receives will contain a full state of the environment. Example:
{
"agents": {
"a": {
"agent_id": "a",
"unit_ids": [
"c",
"e",
"g"
]
},
"b": {
"agent_id": "b",
"unit_ids": [
"d",
"f",
"h"
]
}
},
"unit_state": {
...
},
"entities": [
{
"created": 0,
"x": 11,
"y": 7,
"type": "m"
},
{
"created": 0,
"x": 12,
"y": 4,
"type": "o",
"hp": 3
}
],
"world": {
"width": 15,
"height": 15
},
"tick": 0,
"config": {
"tick_rate_hz": 10,
"game_duration_ticks": 1800,
"fire_spawn_interval_ticks": 5
},
"connection": {
"id": 1,
"role": "agent",
"agent_id": "b"
}
}
After the first game_state
, packets received from the server contain only the latest updates to the game environment. The provided starter kits handle the simulation logic and will return game_state
in full for your agent. If you are building an agent from scratch, you will need to implement this simulation logic as well.
The following environment data is available from the game server:
(Type: object) Information for the given agent_id
.
"agents": {
"a": {
"agent_id": "a",
"unit_ids": [
"c",
"e",
"g"
]
},
"b": {
"agent_id": "b",
"unit_ids": [
"d",
"f",
"h"
]
}
}
Property | Type | Description |
---|---|---|
agent_id | string | Agent identifier (either a or b) |
unit_ids | Array | List of unit IDs belonging to this agent |
(Type: object) Information for the given unit_id
.
"unit_state": {
"c": {
"coordinates": [
3,
10
],
"hp": 3,
"inventory": {
"bombs": 3
},
"blast_diameter": 3,
"unit_id": "c",
"agent_id": "a",
"invulnerable": 0,
"stunned": 0
}
Property | Type | Description |
---|---|---|
coordinates | [number, number] | [X, Y] location |
hp | number | Health points |
inventory | object | Items owned by unit (currently just ammunition) |
bombs | number | Number of bombs available to place (i.e. ammunition) E.g. to get ammunition for unit C: game_state["unit_state"]["c"]["inventory"]["bombs"] NOTE (ver. 2204+): the ammunition is effectively set to infinity for bomberlandv4. |
blast_diameter | number | Diameter of blast range for bombs placed by this unit |
unit_id | string | This unit's identifier (valid IDs: c , d , e , f , g , h ) |
agent_id | string | The agent to which this unit belongs (either a or b ) |
invulnerable | number | Latest tick number after which this unit is no longer invulnerable (inclusive). E.g. "invulnerable": 60 → this unit is invulnerable until tick 60. |
stunned | number | Latest tick number after which this unit is no longer stunned (inclusive). E.g. "stunned": 60 → this unit is stunned until tick 60. |
(Type: array of objects) A list of entities (e.g. blocks, explosions) on the map. Does not include players/units. See 📦 Game Entities for a full list of entities and how they will appear.
"entities": [
{
"created": 60,
"x": 3,
"y": 9,
"type": "b",
"unit_id": "h",
"expires": 100,
"hp": 1,
"blast_diameter": 3
}
],
Property | Type | Description |
---|---|---|
created | number | Tick on which this entity was created (0 = part of the initial world rendering) |
x | number | x-coordinate |
y | number | y-coordinate |
type | a | b | x | bp | fp | m | o | w |
|
owner_unit_id | string | ID of the unit that owns this entity |
expires | number | Tick on which this entity will perish from the map. E.g. a bomb placed with expires=74 will explode on tick 74. |
hp | number | Health Points taken before entity perishes |
blast_diameter | number | Diameter of blast range (if this entity is a bomb) |
(Type: object) Information on the world map.
"world": {
"width": 15,
"height": 15
}
Property | Type | Description |
---|---|---|
width | number | Number of cells horizontally (Default: 15) |
height | number | Number of cells vertically (Default: 15) |
(Type: number) The current game tick.
"tick": 75
(Type: object) Configuration settings for the game environment. (Can be changed, see ⚙️ Environment Flags).
"config": {
"tick_rate_hz": 10,
"game_duration_ticks": 1800,
"fire_spawn_interval_ticks": 5
},
Property | Type | Description |
---|---|---|
tick_rate_hz | number | Number of ticks per second |
game_duration_ticks | number | Number of ticks before end game fire starts |
fire_spawn_interval_ticks | number | Number of ticks between each end-game fire spawn |
(Type: object) Information about your agent's connection with the game server.
"connection": {
"id": 1,
"role": "agent",
"agent_id": "b"
}
Property | Type | Description |
---|---|---|
id | number | Used for managing your agent's connection to tournament servers (can be ignored). |
role | string | Either agent, spectator, or admin. See 🧩 Roles. |
agent_id | string | Whether you are Agent A or B. |
entities
are provided in game_state
and represent objects in the game.
Below is a list of all available entities and their required properties. For a description of the properties, see 🎮 Game State Definitions.
Entity | Properties |
---|---|
Metal Block (indestructible) | created , x , y , type=m |
Wooden Block (destructible) | created , x , y , type=w , hp |
Ore Block (destructible) | created , x , y , type=o , hp |
Ammunition pickup | created , x , y , type=a , expires , hp |
Blast radius powerup | created , x , y , type=bp , expires , hp |
Freeze powerup | created , x , y , type=fp , expires , hp |
Bomb | created , x , y , type=b , owner_unit_id , expires , hp , blast_diameter |
Explosion | created , x , y , type=x , owner_unit_id , expires |
End-game fire | created , x , y , type=x |
On each tick, the game server will send a server packet containing updates to the game environment. These packets conform to validServerPacket
in the validation schema.
The provided starter kits use the server packets to update and return game_state
for you.
Below is a list of the possible event types (in the order they are executed). See 🎮 Game State Definitions for a description of each property.
{
"type": "unit",
"agent_id": "b",
"data": {
"type": "bomb",
"unit_id": "h"
}
}
{
"type": "unit",
"agent_id": "b",
"data": {
"type": "detonate",
"coordinates": [10, 10],
"unit_id": "h"
}
}
{
"type": "unit",
"agent_id": "b",
"data": {
"type": "move",
"move": "up",
"unit_id": "h"
}
}
{
"type": "unit_state",
"data": {
"coordinates": [4, 10],
"hp": 3,
"inventory": {
"bombs": 1
},
"blast_diameter": 3,
"unit_id": "h",
"owner_id": "b",
"invulnerability": 0,
"stunned": 0
}
}
{
"type": "entity_expired",
"data": [4, 10]
}
{
"type": "entity_spawned",
"data": {
"created": 79,
"x": 4,
"y": 10,
"type": "b",
"unit_id": "h",
"expires": 119,
"hp": 1,
"blast_diameter": 3
}
}
{
"type": "entity_state",
"coordinates": [10, 9],
"updated_entity": {
"created": 275,
"x": 10,
"y": 9,
"type": "a",
"expires": 315,
"hp": 0
}
}
On each tick, the game server accepts one action packet per unit per agent.
An action packet must conform to the validation schema (ValidAgentPacket
). The starter kits provide an interface for sending actions.
The available action packets are detailed below.
Action | Required Properties (property: type | valid values) |
---|---|
Place bomb | type: string | bomb unit_id string | eg: a , b , c , .. |
Move (up, down, left, right) | type: string | eg: move move: string | eg: up , down , left , right unit_id: string | eg: a , b , c , .. |
Detonate bomb | type: string | eg: 'move'coordinates: [number, number] | eg: [2, 4]unit_id: string | eg: a , b , c , .. |
Request tick (Admin-only, see 🧩Connection) | type: string | eg: request_tick |
Example action packet:
action_packet = {
type: "bomb",
unit_id: "c"
}
Full reference found on our github
Requirements:
ADMIN_ROLE_ENABLED=1
flag set to use this feature.admin
role to send these packets.Allows you to restart or renew the game instead of having to restart the game engine. You can also provide an optional prng_seed
and world_seed
property to reset the game with. (Also available in the administrator UI).
export interface RequestGameReset {
readonly type: "request_game_reset";
readonly world_seed?: number;
readonly prng_seed?: number;
}
You need to have TRAINING_MODE_ENABLED=1
configured for the engine to use this.
Allows you to step through a game tick by tick to get a better grasp of what is happening. (Also available in the administrator UI).
{
"type": "request_tick"
}
You need to have TRAINING_MODE_ENABLED=1
configured for the engine to use this.
This allows you to get the next state of the game given a game_state
and a list of actions as defined by the typescript schema below:
export interface EvaluateNextStatePacket {
readonly type: "next_game_state";
readonly sequence_id: number;
readonly state: GameState;
readonly actions: Array<{
readonly agent_id: string;
readonly action: AgentPacket;
}>;
}
The response will be the next game state as evaluated by the game engine.
The environment's default variables can be changed by setting the appropriate flag in docker-compose.yml
.
You will need to add the --build
flag when restarting the game engine (i.e. docker-compose --build
).
Environment Variable | Description |
---|---|
ADMIN_ROLE_ENABLED=1 | Enables / disables admin role (will be disabled in tournament mode) |
AGENT_SECRET_ID_MAP=agentA,agentB | Used for game connection |
AMMO_DURATION_TICKS=40 | Number of ticks before ammunition pickup perishes |
AMMO_SPAWN_WEIGHTING=0 | If a spawn appears, weighting % that it will be an ammunition (versus a powerup).AMMO_SPAWN_WEIGHTING + BLAST_POWERUP_SPAWN_WEIGHTING + FREEZE_POWERUP_SPAWN_WEIGHTING = 1 |
BLAST_DURATION_TICKS=5 | Number of ticks before blast disappears |
BLAST_POWERUP_DURATION_TICKS=40 | Number of ticks before blast powerup perishes |
BLAST_POWERUP_SPAWN_WEIGHTING=0.5 | If a spawn appears, weighting % that it will be a blast powerup.AMMO_SPAWN_WEIGHTING + BLAST_POWERUP_SPAWN_WEIGHTING + FREEZE_POWERUP_SPAWN_WEIGHTING = 1 |
BOMB_DURATION_TICKS=30 | Number of ticks before a bomb explodes |
BOMB_ARMED_TICKS=5 | Number of ticks before a bomb can be remotely detonated |
ENTITY_SPAWN_PROBABILITY_PER_TICK=0 | Probability of a spawn appearing somewhere on the map each tick |
FIRE_SPAWN_INTERVAL_TICKS=2 | Number of ticks between each single tile of fire spawned |
FREEZE_DEBUFF_DURATION_TICKS=15 | Number of ticks that a unit will be stunned for by a freeze powerup |
FREEZE_POWERUP_DURATION_TICKS=40 | Number of ticks before a freeze powerup perishes |
FREEZE_POWERUP_SPAWN_WEIGHTING=0.5 | If a spawn appears, weighting % that it will be a freeze powerup.AMMO_SPAWN_WEIGHTING + BLAST_POWERUP_SPAWN_WEIGHTING + FREEZE_POWERUP_SPAWN_WEIGHTING = 1 |
GAME_DURATION_TICKS=200 | Number of ticks before ring of fire spawns |
GAME_START_DELAY_MS=2000 | Time (ms) before game server starts after both agents connect |
INITIAL_AMMUNITION=9999 | Starting number of ammunition per unit |
INITIAL_BLAST_DIAMETER=3 | Starting blast diameter for bombs (number of tiles including the bomb's tile) |
INITIAL_HP=3 | Initial unit health points |
INVULNERABILITY_TICKS=5 | Number of ticks an agent is invulnerable for |
SYMMETRICAL_MAP_ENABLED=1 | Disable/enable whether the generated map will be symmetrical across the Y (vertical)-axis |
TELEMETRY_ENABLED=1 | Disable/enable game server log outputs |
TRAINING_MODE_ENABLED=1 | Enables admin role (see 🧩 Roles). Agent actions are no longer tied to the clock and ticks need to be stepped through manually. |
MAP_HEIGHT=15 | Size of map (y-axis) |
MAP_WIDTH=15 | Size of map (x-axis) |
MAXIMUM_CONCURRENT_BOMBS=3 | Maximum number of bombs than an agent may have on the map at any one time |
OBJECT_DESTRUCTION_ITEM_DROP_PROBABILITY=0.5 | Controls how often an item will drop when a wooden block or an ore block is destroyed |
ORE_BLOCK_FREQUENCY=0.3617283950617284 | Controls the number of ore blocks in the world |
PORT=3000 | For game server communication |
PRNG_SEED | Defaults to a random seed if no flag is specified. See 🗺️ Map generation |
SAVE_REPLAY_ENABLED=1 | Enable/disable the the option to save replay files from the client |
SHUTDOWN_ON_GAME_END_ENABLED=1 | Disable/enable shutdown of game server once game is over. |
STEEL_BLOCK_FREQUENCY=0.1222222222222222 | Controls number of steel blocks in map |
TICK_RATE_HZ=10 | Number of ticks per second |
TOTAL_AGENTS=2 | Number of agents allowed in the game |
TOURNAMENT_AGENT_CONNECTION_GRACE_PERIOD_MS=OPTIONAL | Time that the game server will wait for agents to connect before disqualifying them (used for official tournament matches) |
UI_ENABLED=1 | Enable/disable the game client/UI |
UNITS_PER_AGENT=3 | Number of units an agent controls |
WOOD_BLOCK_FREQUENCY=0.1969135802469136 | Controls number of wooden blocks in map |
WORLD_SEED | Defaults to a random seed if no flag is specified. See 🗺️ Map generation |
Maps are symmetrically and pseudo-randomly generated.
By default, the same map will be generated each time the game is loaded. You can change this by changing the environment variables:
Game Seed PRNG_SEED
: stochasticity of the game and item spawns
World Seed WORLD_SEED
: generation of the first game map (placement of blocks etc)
Both can be set to an integer value between 0
and 9,007,199,254,740,991
.
Remember to vary the game/world seeds so that your agent doesn't overfit to the default map.
Some seeds will generate invalid maps.
The forward model will not be provided in tournament servers. You can still use the forward model for your own training purposes, but this feature is still experimental. This feature is intended for agents to build simulations of potential future states (such as for Monte Carlo Tree Search).
If you're interested in this feature, please get in touch with us on Discord or email so we can improve on it!
We've provided starter kits for implementing an agent that uses a forward model (_fwd) to simulate actions in the game state.
At a high level:
The forward model agent is provided two connections (one to the game, and one to the forward model server)
The forward model can use the ForwardState
class to invoke next(...) with a sequence ID (used as a way to acknowledge the packet by the server)
When a response is received the callback _on_next_game_state
is invoked and the object passed into it contains the same sequence ID so the agent can map it to whatever data store / object and use that to make decisions.
An example of all the packets is included in the JSON-schema definition for users who want to implement a game agent in a language of their choice.
Contents