Files
battleship/docs/GAME_DECISIONS.md
T

4.3 KiB
Raw Blame History

Production decisions

This document is the binding implementation contract for the MVP. It resolves the choices left open in MVP.md; future code must not widen these limits without updating this document and RESOURCE_BUDGET.md.

Platform and ownership

  • Target: ESP32-C6FH4 (4 MB flash, no PSRAM assumed), custom 2 MiB app and 1,984 KiB LittleFS partitions.
  • Stack: PlatformIO Core 6.1.19, espressif32 7.0.1, ESP-IDF 6.0.1, built-in esp_http_server WebSocket support, and esp_littlefs 1.20.4.
  • The ESP32 is authoritative. HTTP and WebSocket callbacks only validate and enqueue commands; one application task owns game, session, and statistics mutation.
  • Internal coordinates are unsigned x and y in [0, 9]. The browser renders Russian column labels; it never sends them.

Fixed game rules

  • Board size is 10 by 10. Each side has ships of lengths 4, 3, 3, 2, 2, 2, 1, 1, 1, 1, placed randomly by the server without touching, including diagonally.
  • A hit retains the turn. A miss changes it. Sinking a ship marks its surrounding cells as misses. A repeated shot is rejected without state change. First turn and each fleet are independently random.
  • Modes are HUMAN_VS_HUMAN and HUMAN_VS_BOT. The bot is ESP32; it uses only previously visible shot results and acts after a bounded 500900 ms server timer.
  • Phases are LOBBY, PREPARING, IN_PROGRESS, FINISHED, and REMATCH_WAIT. Every accepted state change increments version.

Sessions and capacity

  • Roles are PLAYER_1, PLAYER_2, and SPECTATOR; capacity is two players and eight spectators. New clients become spectators when player slots are occupied, subject to the spectator limit.
  • Display names are 120 Unicode scalar values after removing controls and markup. The server stores a bounded UTF-8 encoding of at most 80 bytes and escapes it before HTML rendering.
  • A session token is 16 cryptographically random bytes, transported as 32 lowercase hexadecimal characters. It is opaque, never logged, and remains valid only until board reboot or explicit slot release.
  • Active player sessions survive disconnects. Spectator disconnects free their slot immediately. A player may resume only with the same token; a resumed session receives a complete role-safe snapshot.

Lifecycle

  1. join assigns player 1 if vacant and requested, then player 2 only in the two-player mode; otherwise it assigns spectator. resume never changes a role.
  2. Player 1 may configure a mode only in LOBBY. Switching to bot reserves player 2 as ESP32; switching back requires no human player 2 conflict.
  3. Player 1 may start only when player 2 is present in human mode, or bot mode is selected. PREPARING is internal and advances atomically to IN_PROGRESS after both fleets validate.
  4. A player disconnect does not abort a game. The game waits for that player; the bot continues only when it is the bot's turn. Player 1 may issue the explicit abort command while a human opponent is disconnected, returning to LOBBY and incrementing version.
  5. Destroying all ten opponent ships transitions to FINISHED, records match and cumulative statistics, reveals both boards, and rejects shots.
  6. In FINISHED, a player may confirm rematch. Human mode requires both player confirmations; bot mode requires player 1 only. The server enters REMATCH_WAIT until the required confirmations exist, then creates a new game ID and returns to PREPARING. Names, roles, and cumulative statistics remain; per-match statistics reset.
  7. Board reboot clears sessions, game, and all statistics. Wi-Fi loss does not mutate them; clients use HTTP polling while WebSocket reconnects.

Visibility and transport

  • Player 1 receives its complete board and only known opponent shot results; player 2 is symmetric. Spectators see known shot results from both boards. Unhit ships are replaced by 0 in every unauthorized view.
  • FINISHED is the sole phase that exposes full boards to every role.
  • HTTP commands include the token in the JSON body. WebSocket authentication is the first hello message; the token is never placed in a URL or log.
  • WebSocket reconnect delay is 1, 2, 5, then 10 seconds. HTTP polls a complete snapshot every two seconds only while WebSocket is unavailable. Any skipped version triggers a full snapshot request.