Skip to main content
A command is an action a player can send from the frontend. Every command has an ID, an input schema, validation, and execution.

Define a command

Create one factory for your game state and event registry:
The stage containing advance still controls whose turn it is. .isAvailable() adds a rule for when the active player should see the command.

Availability and validation

Use the two checks for different questions:
  • .isAvailable() answers “should this command be offered now?” It powers getAvailableCommands() in the client.
  • .validate() answers “is this exact attempt legal?” It returns a stable rejection reason that the frontend can handle.
Always repeat critical legality checks in .validate(). Availability can change between rendering a button and submitting the command. Validation can also return structured metadata:

Execute the change

.execute() receives mutable game, the validated command, deterministic rng, and typed emitEvent when your factory has an event registry. Use rng for random outcomes:
An accepted command runs against a cloned working state. The executor returns the next state only after the command and following stage transitions finish successfully.

Guide the frontend with discovery

Discovery lets the UI ask the engine for legal choices before it sends a command. This is useful when options depend on hidden or changing state.
Call the same step again with the chosen option’s nextInput. The completed input must match the command schema.

Put commands in stages

Control when and by whom commands can run.