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"
  }
]
chess/gamehoster-instance/gamehoster-instance-schema.json

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")
chess/gamehoster-instance/gamehoster-instance-update-backend.js