Skip to content

Game actions

Game actions manage shared game state and the built-in loop state. They are still ActionRegistry entries; “network” and “persistence” operations are Engine APIs, not action types.

Game state and lifecycle

Type Payload Result / effect
game:start none Marks the game started and returns game state
game:end { winner?, reason? } Marks the game ended
game:pause none Marks the game paused
game:resume none Resumes and updates pause duration
game:nextPhase { phase } Sets phase and increments turn
game:setProperty { key, value } Sets one gameState property
game:mergeState { state } Assigns fields into gameState
game:setState { key, value?, replace?, patches? } Writes game-specific top-level state
game:getState none Returns materialized game state

game:setState accepts either value or patches, never both. A patch is { path: string[], value }; missing intermediate objects are created. Values are sanitized with JSON serialization, so undefined, functions, class instances, and other non-JSON values are not a supported state format.

await engine.dispatch("game:setState", {
  key: "cuttle",
  value: { phase: "recruit", score: { red: 0, blue: 0 } },
});

await engine.dispatch("game:setState", {
  key: "cuttle",
  patches: [{ path: ["score", "red"], value: 1 }],
});

Game loop

These seven actual types manage doc.gameLoop and are normally used by GameLoop:

game:loopInit, game:loopStart, game:loopStop, game:nextTurn, game:setPhase, game:setMaxTurns, game:setActiveAgent.

Payloads are respectively { maxTurns? }, none, { phase? }, { agentCount? }, { phase }, { maxTurns }, and { index }.

Auxiliary actions

rule:initRules initializes doc.rules.fired; rule:markFired accepts { name, timestamp? } and returns whether this dispatch claimed a previously unfired rule. debug:log accepts any payload, returns it, and logs only when engine.debug is enabled. These are registry entries, not Engine network or storage operations.