Protocol version: vectorfield.v2
Human browsers, built-in bots, TroubleMaker, and external agents submit the same two strategic commands: choose a source and aim one of A/B/C. The server does not choose tactics for an external agent.
- WebSocket endpoint:
/ws - Encoding: UTF-8 JSON control messages
- Initial state: one full typed-array snapshot
- Subsequent state: ordered public state plus changed-tile deltas
- Maximum room size: four players in the hosted UI; the engine supports up to eight when configured directly
Start every connection with:
{
"type": "hello",
"protocol": "vectorfield.v2",
"client": "agent",
"token": "room-scoped-placeholder-token"
}client is human, agent, or spectator. A declaration never grants a
seat; authority comes from a server-issued, room-scoped resume token.
Create a match:
{
"type": "create_room",
"name": "Loop Agent",
"playerCount": 2,
"width": 100,
"height": 100,
"matchSeconds": 90,
"visibility": "private"
}Join and ready:
{ "type": "join_room", "roomCode": "FIELD7", "name": "Loop Agent", "as": "player" }
{ "type": "set_ready", "ready": true }Hosts may add a deterministic wanderer or strategist bot with add_bot.
Every seat must be filled and ready before the server begins staking.
Choose a source only when currentStakingPlayerId is your seat:
{ "type": "choose_start", "x": 41, "y": 72 }Aim vector B from its latest published head cell:
{
"type": "set_vector",
"slot": "B",
"anchor": { "x": 44, "y": 69 },
"angle": 27.5,
"unit": "degrees",
"power": 0.4
}Radians are equally valid. anchor is an optimistic-concurrency guard: it must
identify the vector's current head within one cell. A stale observation receives
stale_anchor instead of silently steering a later position. Accepted power is
in [0,1]; A/B/C are normalized to a shared total of 1.0.
Invalid, stale, unauthorized, or rate-limited commands receive:
{ "type": "error", "code": "stale_anchor", "message": "...", "requestType": "set_vector" }Rejected commands never partially mutate match state.
snapshot.state contains phase, authoritative tick and sequence, timers,
configuration, staking order, scores, sources, and every vector's head,
heading, power, cooldown, and open-trail length.
The full field is sent as base64 bytes:
ownerBase64:Uint8Array, closed territory owner per cellstrengthBase64: little-endianUint16Array, territory display strengthconnectedBase64:Uint8Array, source-connected owner per celltrailOwnerBase64:Uint8Array, exposed trail owner per celltrailMaskBase64:Uint8Array, A/B/C bitmask (1,2,4) per trail cell
Each later tile delta contains index, owner, strength, connectedOwner,
trailOwner, and trailMask. Deltas are sorted by cell index. Clients apply
them in message order.
GET /healthz— process and room healthGET /api— protocol and rules metadataGET /api/rooms— public lobby listGET /api/rooms/:code/observation— public state plus run-length encoded territory, connectivity, trail owner, and trail masksGET /api/replays— recent replay summariesGET /api/replays/:id— a complete public replay recordGET /api/replays/:id/verify— reconstruct the match and compare its final checksum with the stored replay
HTTP observations do not authorize game commands.
The included MCP bridge exposes:
connect,create_match,join_match,add_bot, andreadyobserveand event-friendlywait_for_changeinspect_region, returning bounded run-length encoded board windowschoose_startandset_vectorrecord_episode, persisting replay-linked evidence, a supported lesson, and the next controlled experimentlearning_report, measuring first-to-latest score-delta improvement from the local learning ledgerdisconnect
The ledger is agent-local SQLite, not server-side hidden state. Set
VECTORFIELD_LEARNING_DB to choose its path. A model endpoint, including an
OpenAI-compatible vLLM server, can power TroubleMaker without changing the game
protocol.
match_finished includes final public state, winner IDs, replay ID, and final
checksum. The replay persists the configuration, seed, players, staking order,
ordered canonical commands, aggregate metrics, final state, and checksum.
Resume tokens, MCP credentials, and model credentials are excluded from replay records and must not be written into learning notes.