WebSocket JSON Protocol

Endpoints

  • Game: /ws
  • Debug: /ws/debug

The frontend picks minimax vs alphazero by settings.ai and connects to one of:

  • Local: ws://localhost:{PORT}/ws
  • Production: wss://sungyongcho.com/minimax/ws or wss://sungyongcho.com/alphazero/ws

Compatibility Notes

The protocol is frontend-compatible across minimax and AlphaZero, but not byte-identical between backends.

  • Shared core request fields (both backends): type, nextPlayer, board, scores.
  • evaluate requests require lastPlay.coordinate (for both backends).
  • Minimax requires difficulty for move/test.
  • AlphaZero currently ignores difficulty, goal, enableCapture, and enableDoubleThreeRestriction in request payloads.
  • move response shape differs by backend: AlphaZero includes scores and evalScores; minimax omits both.

Request Messages

1) move, evaluate, test

The frontend sends one common superset payload shape:

      {
  "type": "move",
  "difficulty": "easy | medium | hard",
  // minimax: required for move/test
  // alphazero: currently ignored
  "nextPlayer": "X | O",
  "goal": 5,
  // currently ignored by alphazero server
  "enableCapture": true,
  // currently ignored by alphazero server
  "enableDoubleThreeRestriction": true,
  "lastPlay": {
    "coordinate": { "x": 9, "y": 10 },
    "stone": "X"
  },
  // `lastPlay.coordinate` is required for `evaluate`.
  "board": [[".", ".", "..."]],
  // Full board state is sent every request (board-state stateless handling; minimax TT/difficulty are per-connection state).
  "scores": [
    { "player": "X", "score": 3 },
    { "player": "O", "score": 1 }
  ],
  // `scores` is capture score by player (used by both backends).
  // `test` is used by `front/pages/test.vue` (minimax-focused check path).
}

    
json

lastPlay semantics differ by request type:

  • move: lastPlay is the actual last move played. It can be omitted for the first AI move request.
  • evaluate: lastPlay.coordinate is required and specifies the position to evaluate (not the actual last move played).
  • Frontend behavior: right-click evaluate is enabled only in minimax mode; it is disabled in alphazero mode.
  • test: same semantics as move.

test note: in the minimax backend, difficulty is currently ignored and the handler always uses the hard PVS path.

2) reset

      { "type": "reset" }

    
json

Response Messages

1) move (also used for test)

      {
  "type": "move",
  "status": "success",
  "lastPlay": {
    "coordinate": { "x": 9, "y": 10 },
    "stone": "O"
  },
  "board": [[".", ".", "..."]],
  "capturedStones": [
    { "x": 1, "y": 1, "stone": "X" }
  ],
  "executionTime": { "s": 0.12, "ms": 120.0, "ns": 120000000 },
  // Optional by backend: `scores`, `evalScores`
}

    
json

lastPlay.stone is the stone that was just placed for this move (not the next player to move). For move/test responses: AlphaZero includes scores and evalScores; minimax omits both fields.

2) evaluate

      {
  "type": "evaluate",
  "evalScores": [
    // NOTE: the inner field shares the name "evalScores" with the outer array — a naming quirk retained for backward compatibility.
    { "player": "O", "evalScores": 0.13, "percentage": 43.5 },
    { "player": "X", "evalScores": -0.13, "percentage": 56.5 }
  ],
  // Frontend mainly uses `player` + `percentage`.
}

    
json

evalScores type differs by backend:

  • Minimax: raw integer heuristic score.
  • AlphaZero: model value as a float.

percentage is a normalized 0-100 evaluation intended for cross-backend UI display (frontend primarily uses this field).

3) error

      {
  "type": "error",
  "error": "Unknown type"
}

    
json