Instance
An instance is one game of Chess: the lobby the two players meet in and
the board they then play on, one and the same room, told apart by its phase. Its
state tracks the phase, whose turn it is, and the winner, and it runs
a server-side backend update each tick that drives the lobby into
play. Everything visible is server-authoritative, so there is no separate frontend update.
gamehoster-instance-schema.json
The instance's shared state, all sent to both clients:
phase (lobby, then playing, then over),
turn (white or black), and winner once the game is
decided.
[
{
"gamehoster-instance-schema-name": "phase",
"gamehoster-instance-schema-type": "string",
"gamehoster-instance-schema-default": "lobby",
"gamehoster-instance-schema-sync": "sent",
"gamehoster-instance-schema-audience": "all"
},
{
"gamehoster-instance-schema-name": "turn",
"gamehoster-instance-schema-type": "string",
"gamehoster-instance-schema-default": "white",
"gamehoster-instance-schema-sync": "sent",
"gamehoster-instance-schema-audience": "all"
},
{
"gamehoster-instance-schema-name": "winner",
"gamehoster-instance-schema-type": "string",
"gamehoster-instance-schema-default": "none",
"gamehoster-instance-schema-sync": "sent",
"gamehoster-instance-schema-audience": "all"
}
]
gamehoster-instance-update-backend.js
The whole-room authoritative pass, run each tick on the server. It is only a phase machine: while in the
lobby it waits for two ready players, then assigns colours by join order, spawns the 32 starting pieces,
and flips the phase to playing. Once play begins it does nothing more, all in-game logic
lives in the move and resign commands.
// The instance's backend update: the whole-room, authoritative pass (step 3).
// For chess this is purely the phase machine: while in the lobby, wait for two
// ready players, then assign colours, set up the board and begin play. All the
// in-game logic lives in the `move`/`resign` commands, so once we are "playing"
// there is nothing for the per-tick instance update to do. There are no arenas:
// the lobby and the game are the same instance, distinguished by `phase`.
const here = Gamehoster.Context.instanceId
if (Gamehoster.Instance.State.Get(here, "phase") !== "lobby") return
const players = Gamehoster.Player.List()
if (players.length !== 2) return
if (!players.every(id => Gamehoster.Player.State.Get(id, "ready"))) return
// assign colours: white to the first by join order, black to the second
Gamehoster.Player.State.Set(players[0], "color", "white")
Gamehoster.Player.State.Set(players[1], "color", "black")
// spawn the 32 starting pieces. rank/file are 0-based (a1 = file 0, rank 0);
// white occupies ranks 0-1, black ranks 6-7.
const back = ["rook", "knight", "bishop", "queen", "king", "bishop", "knight", "rook"]
for (let f = 0; f < 8; f++) {
Gamehoster.Entity.Spawn("piece", { kind: back[f], color: "white", file: f, rank: 0, moved: false })
Gamehoster.Entity.Spawn("piece", { kind: "pawn", color: "white", file: f, rank: 1, moved: false })
Gamehoster.Entity.Spawn("piece", { kind: "pawn", color: "black", file: f, rank: 6, moved: false })
Gamehoster.Entity.Spawn("piece", { kind: back[f], color: "black", file: f, rank: 7, moved: false })
}
Gamehoster.Instance.State.Set(here, "turn", "white")
Gamehoster.Instance.State.Set(here, "phase", "playing")