|
Scubywasm API
C ABI for WebAssembly agents and engine
|
#include <stdint.h>
Go to the source code of this file.
Enumerations | |
| enum | ActionFlags : unsigned int { ACTION_NONE = 0U , ACTION_THRUST = 1U , ACTION_TURN_LEFT = 2U , ACTION_TURN_RIGHT = 4U , ACTION_FIRE = 8U } |
| Action bitmask. More... | |
| enum | ConfigParameter : unsigned int { CFG_SHIP_MAX_TURN_RATE = 0U , CFG_SHIP_MAX_VELOCITY = 1U , CFG_SHIP_HIT_RADIUS = 2U , CFG_SHOT_VELOCITY = 3U , CFG_SHOT_LIFETIME = 4U } |
| Engine configuration parameters. More... | |
Functions | |
| struct Context * | init_agent (uint32_t n_agents, uint32_t agent_multiplicity, uint32_t seed) |
| Create a new per-round agent context. | |
| void | free_context (struct Context *ctx) |
| Destroy an agent context created by init_agent(). | |
| void | set_config_parameter (struct Context *ctx, enum ConfigParameter param, float value) |
| Set an immutable configuration parameter. | |
| void | clear_world_state (struct Context *ctx) |
| Clear all observations for the next tick. | |
| void | update_ship (struct Context *ctx, uint32_t agent_id, int32_t hp, float x, float y, float heading) |
| Provide the current state of a ship. | |
| void | update_shot (struct Context *ctx, uint32_t agent_id, int32_t lifetime, float x, float y, float heading) |
| Provide the current state of a shot. | |
| void | update_score (struct Context *ctx, uint32_t agent_id, int32_t score) |
| Provide the current score for one agent. | |
| uint32_t | make_action (struct Context *ctx, uint32_t agent_id, uint32_t tick) |
| Compute the action for one controlled team member. | |
Scubywasm agent ABI.
Scubywasm executes user-provided bots ("agents") as WebAssembly (WASM) modules. The host interacts with an agent module exclusively through the functions declared in this header.
Teams and per-ship agent IDs
A single WASM module controls a team with agent_multiplicity members. Each team member controls exactly one ship, and is identified by a 32-bit agent_id. For each agent_id there is exactly one ship, and at most one active shot at a time. Consequently, ships and shots are referred to by their respective agent_id (there are no separate ship/shot IDs in this ABI).
Agent IDs are opaque 32-bit identifiers
The host provides agent_id values as 32-bit identifiers. They are neither required to be zero-based nor sequential and the agent must not assume any particular numbering scheme. If the agent implementation requires an internal indexing scheme, it must build and maintain it explicitly.
Opaque context handle (no global state)
init_agent() returns a pointer to an implementation-defined Context. For the host, this pointer is an opaque handle that must only be passed back to subsequent API calls and never dereferenced.
The Context is the place to store all agent state. In particular:
Context.Context pointer.Therefore, agent implementations should avoid module-level global mutable state.
Required exported functions
A valid agent WASM module must export and implement these entry points (C ABI). All other declarations in this header exist to document the semantics of these functions and their parameter types.
Context.agent_id).agent_id).agent_id).agent_id.Context and release resources.Typical call pattern
The host drives an agent instance in three phases:
1) Initialization (once per round)
Context* as an opaque handle.Context for later planning.2) Per-tick update and decision (repeated for each tick)
The host then streams a snapshot of the current world state to the agent by calling:
agent_id),agent_id; a lifetime of 0 indicates an inactive shot), andagent_id).In a typical setup, the host broadcasts the same complete snapshot to every agent module, so each agent can observe all teams, not only itself. Agents must not assume a particular ordering of the update_* calls; they should treat them as an unordered stream that fully describes the current tick's state between clear_world_state() and the subsequent action queries.
After the snapshot has been provided, the host requests actions for this team by calling make_action() once for each team member controlled by this WASM module. The host applies the returned ActionFlags bitmask to the engine for that agent_id.
The host will not call make_action() for dead ships.
engine.tick()) and then repeats the process for the next tick.3) Shutdown (once per round)
Discovering the team's agent IDs
The agent does not receive an explicit list of the agent_id values it controls. Instead, the host calls make_action() once per tick for each agent_id that belongs to the team controlled by this WASM module. Agents that need a stable roster must infer and maintain the set of controlled agent_id values from these calls (e.g., by recording each agent_id observed in make_action()).
Fuel metering and unresponsive agents
All agent interactions within a tick (including calls to clear_world_state(), update_ship(), update_shot(), update_score(), and make_action()) are metered in units of wasmtime fuel. Before each tick, the host refuels the agent instance to a fixed budget; the agent must not exceed this budget over the tick. If the fuel is exhausted during a tick, the agent becomes unresponsive and the host will stop calling make_action() for that agent for the remainder of the round.
Coordinate conventions
The implicit coordinate conventions are:
x and y live on a unit torus with values in [0, 1).heading is in degrees in [0, 360) with:| enum ActionFlags : unsigned int |
Action bitmask.
The host interprets the return value of make_action() as a bitwise OR of these flags. Unless explicitly stated otherwise, flags are combinable.
Dynamics (turn rate, max velocity, shot velocity, lifetimes, etc.) are defined by the current configuration as provided via set_config_parameter() using ConfigParameter.
ACTION_TURN_LEFT and ACTION_TURN_RIGHT are logically mutually exclusive. If an agent sets both, the host may ignore both, pick one deterministically, or apply a host-defined tie-breaker.
| enum ConfigParameter : unsigned int |
Engine configuration parameters.
These parameters define the relevant game dynamics and constraints that agents should use for planning (movement, turning, shooting, collision avoidance, etc.).
Configuration parameters are set exactly once during initialization (after init_agent() and before the first tick). They are never changed thereafter. Each round uses a fresh WASM instance, so agents must not rely on configuration carrying over between rounds.
| void clear_world_state | ( | struct Context * | ctx | ) |
Clear all observations for the next tick.
Called at the beginning of each tick, before any update_* calls.
| ctx | Context pointer returned by init_agent(). |
| void free_context | ( | struct Context * | ctx | ) |
Destroy an agent context created by init_agent().
Releases all resources owned by ctx. The host will not use ctx after this call.
| ctx | Context pointer returned by init_agent(). |
| struct Context * init_agent | ( | uint32_t | n_agents, |
| uint32_t | agent_multiplicity, | ||
| uint32_t | seed | ||
| ) |
Create a new per-round agent context.
| n_agents | Total number of agents in the world (across all teams). |
| agent_multiplicity | Number of team members. |
| seed | 32 random bits that can be used to seed PRNGs. |
Context instance, or NULL on failure. | uint32_t make_action | ( | struct Context * | ctx, |
| uint32_t | agent_id, | ||
| uint32_t | tick | ||
| ) |
Compute the action for one controlled team member.
Called once per tick for each agent_id in the team.
| ctx | Context pointer returned by init_agent(). |
| agent_id | 32-bit ID of the ship/agent to act for. |
| tick | Current tick number. |
| void set_config_parameter | ( | struct Context * | ctx, |
| enum ConfigParameter | param, | ||
| float | value | ||
| ) |
Set an immutable configuration parameter.
Called exactly once per parameter during initialization, before the first tick.
| ctx | Context pointer returned by init_agent(). |
| param | Parameter to set. |
| value | Parameter value (units implied by param). |
| void update_score | ( | struct Context * | ctx, |
| uint32_t | agent_id, | ||
| int32_t | score | ||
| ) |
Provide the current score for one agent.
Called once per agent per tick to stream the scores.
| ctx | Context pointer returned by init_agent(). |
| agent_id | 32-bit agent ID. |
| score | Current score. |
| void update_ship | ( | struct Context * | ctx, |
| uint32_t | agent_id, | ||
| int32_t | hp, | ||
| float | x, | ||
| float | y, | ||
| float | heading | ||
| ) |
Provide the current state of a ship.
Called once per ship per tick to stream the full world state.
| ctx | Context pointer returned by init_agent(). |
| agent_id | 32-bit ID of the ship (and its controlling agent). |
| hp | Ship "health": 1 if alive, 0 if not alive. |
| x | Ship x-position on the unit torus. |
| y | Ship y-position on the unit torus. |
| heading | Ship heading in degrees. |
| void update_shot | ( | struct Context * | ctx, |
| uint32_t | agent_id, | ||
| int32_t | lifetime, | ||
| float | x, | ||
| float | y, | ||
| float | heading | ||
| ) |
Provide the current state of a shot.
Called once per (active) shot per tick to stream the full world state.
Whether the host calls this function for dead shots (i.e., lifetime == 0) is engine-defined.
| ctx | Context pointer returned by init_agent(). |
| agent_id | 32-bit id of the shot owner (and associated ship). |
| lifetime | Remaining lifetime in ticks. A value of 0 indicates that the shot is no longer active. |
| x | Shot x-position on the unit torus. |
| y | Shot y-position on the unit torus. |
| heading | Shot heading in degrees. |