Score4 — Project Overview

Goal

Coordinate the communication between a C++ engine and game state manager, and a Go Server handling connections and concurrency

Architecture Summary

Separation of concerns:

  • C++: game rules + game intelligence. Pure, stateless functions over a given bitboard state. No persistence, no networking, no concept of “players” or “sessions.”
  • Go: game state (source of truth for every active game), connections (matchmaking, reconnects), orchestration (calls out to C++ for validation/AI moves).

Why C++ is stateless

Keeping C++ as state in → move/result out makes it trivially testable, easy to reason about, and safe to call concurrently (no shared mutable state inside the engine). Go is the only thing that persists anything.

flowchart LR
    subgraph Client
        FE[JS Frontend]
    end
    subgraph Go Server
        WS[Connection Handling]
        MM[Matchmaking]
        GS[Game State Store]
    end
    subgraph CPP Engine
        VAL[Move Validation]
        AI[Alpha-Beta Search]
    end

    FE <-->|WebSocket/HTTP| WS
    WS --> MM
    WS --> GS
    GS <-->|IPC: state in, move/result out| VAL
    GS <-->|IPC: state in, move out| AI

Components

PartOwnerResponsibility
1. Engine coreC++Compact game state repr, bitmask win detection, move generation
2. AI engineC++Alpha-beta pruning, move ordering, eval function
3. ServerGoConnection handling, matchmaking, game state, calls to C++
4. DeploymentAWS EC2Hosting, live demo

See individual specs: Score4-Engine, Score4-AI, Score4-Server
IPC Specs: Score4-IPC

Open Question: Move Validation Frequency

Does Go duplicate simple win/valid-move checks itself, or does every move round-trip through C++ (even non-AI moves)?

  • Round-trip everything → C++ is the single source of truth for rules, no logic duplication/drift risk. But higher call volume — matters more once transport is subprocess (process spawn cost) vs gRPC (cheap, persistent connection).
  • Go duplicates simple checks → fewer round-trips, but now rules logic exists in two languages and could drift.

Leaning toward round-trip everything through C++ — keeps rules logic in exactly one place, and it’s a more interesting scaling problem for part 3 (frequent small IPC calls). Revisit once Score4-Server concurrency model is drafted.

IPC Strategy: Subprocess → gRPC Migration

Plan: build v1 with subprocess spawning (fast to ship, simple to debug), then refactor to gRPC once the core system works end-to-end. The data contract (what a “state” and a “move” look like) is designed once, up front, so the transport swap doesn’t touch game logic — only the Go-side call site and a new C++ entrypoint (server loop instead of main() reading stdin).

Done Criteria (project-level)

  • Two players can connect via frontend and play a full game against each other
  • A player can play against the AI engine
  • Server correctly handles disconnects/reconnects without corrupting game state
  • Deployed and playable live on EC2
  • (Stretch) IPC layer refactored from subprocess to gRPC