Skip to content

Latest commit

 

History

History
150 lines (113 loc) · 4.67 KB

protocol.md

File metadata and controls

150 lines (113 loc) · 4.67 KB

Agent and client protocol

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.

Transport and connection

  • 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.

Lobby commands

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.

Canonical game commands

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.

Snapshots and deltas

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 cell
  • strengthBase64: little-endian Uint16Array, territory display strength
  • connectedBase64: Uint8Array, source-connected owner per cell
  • trailOwnerBase64: Uint8Array, exposed trail owner per cell
  • trailMaskBase64: 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.

Read-only HTTP observations

  • GET /healthz — process and room health
  • GET /api — protocol and rules metadata
  • GET /api/rooms — public lobby list
  • GET /api/rooms/:code/observation — public state plus run-length encoded territory, connectivity, trail owner, and trail masks
  • GET /api/replays — recent replay summaries
  • GET /api/replays/:id — a complete public replay record
  • GET /api/replays/:id/verify — reconstruct the match and compare its final checksum with the stored replay

HTTP observations do not authorize game commands.

TroubleMaker MCP tools

The included MCP bridge exposes:

  • connect, create_match, join_match, add_bot, and ready
  • observe and event-friendly wait_for_change
  • inspect_region, returning bounded run-length encoded board windows
  • choose_start and set_vector
  • record_episode, persisting replay-linked evidence, a supported lesson, and the next controlled experiment
  • learning_report, measuring first-to-latest score-delta improvement from the local learning ledger
  • disconnect

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 completion

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.