diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 6e7731f..20c138e 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1,6 +1,6 @@ # Architecture -> Last Updated: 2026-04-02T18:12:18.000Z +> Last Updated: 2026-04-02T19:05:00.000Z ## Overview @@ -27,7 +27,10 @@ scopone-phaser/ | | |- types.ts | | |- engine.ts | | |- card-tracker.ts -| | `- ai.ts +| | |- ai.ts +| | |- ai-worker-protocol.ts +| | |- ai-worker-client.ts +| | `- ai.worker.ts | `- scenes/ | |- BootScene.ts | |- MenuScene.ts @@ -64,8 +67,9 @@ Observed architectural patterns in the current codebase: | Scene-based flow | `BootScene -> MenuScene -> GameScene` via Phaser scene registration | | Functional core / imperative shell | `src/game/` stays free of Phaser imports, while `src/scenes/` owns rendering and input | | Clone-before-mutate state transitions | `applyMove()` clones `GameState` before applying move effects | +| Worker offload with fallback | `AIWorkerClient` runs heavy AI inside `ai.worker.ts` and falls back to in-thread `chooseMove()` if worker startup or messaging fails | | Determinization search | Master AI samples hidden hands before alpha-beta evaluation | -| Callback-driven progress reporting | `chooseMove()` reports `AIDecisionProgress` to `GameScene` for the think bar | +| Message-based progress reporting | Worker and main thread exchange typed request/result/progress messages through `ai-worker-protocol.ts` | ## Key Components @@ -94,7 +98,7 @@ Observed architectural patterns in the current codebase: - Computes unseen cards from `played + myHand + table`. - Supplies probability helpers used by the AI for value-based inference. -### `src/game/ai.ts` (1210 lines) +### `src/game/ai.ts` - Exposes `chooseMove()` as an async entry point. - Implements three difficulty levels: @@ -103,22 +107,38 @@ Observed architectural patterns in the current codebase: - `master`: determinization plus alpha-beta search with dynamic time budgets, batching, and progress callbacks. - Uses `yieldToBrowser()` between master-search batches so Phaser can repaint the think bar. -### `src/scenes/BootScene.ts` (47 lines) +### `src/game/ai-worker-protocol.ts` + +- Defines the typed message contract between the main thread and the worker. +- Serializes requests around `GameState`, `Difficulty`, `PlayerIndex`, tracker snapshots, progress, results, and worker-safe errors. + +### `src/game/ai-worker-client.ts` + +- Wraps the worker lifecycle behind the same `chooseMove()` API the scene needs. +- Creates module workers with `new Worker(new URL('./ai.worker.ts', import.meta.url), { type: 'module' })`. +- Streams progress callbacks back into `GameScene` and degrades to direct `chooseMove()` execution when workers are unavailable. + +### `src/game/ai.worker.ts` + +- Rehydrates `CardTracker` from a snapshot, delegates move selection to `chooseMove()`, and posts progress/result/error messages back to the scene thread. +- Keeps the expensive `master` search off the main rendering thread when worker support is available. + +### `src/scenes/BootScene.ts` - Loads the card atlas and card-back texture. - Shows a simple progress bar and transitions into the menu. -### `src/scenes/MenuScene.ts` (103 lines) +### `src/scenes/MenuScene.ts` - Renders the title screen and rules summary. - Lets the player choose `beginner`, `advanced`, or `master` difficulty. - Starts `GameScene` with the selected difficulty in scene data. -### `src/scenes/GameScene.ts` (1446 lines) +### `src/scenes/GameScene.ts` - Owns the match loop, HUD, think bar, card interaction, animation, FX, audio, and round transitions. - Uses `CardTracker` to record played and captured cards after each move. -- Bridges async AI progress into a visible top-of-screen think bar. +- Instantiates `AIWorkerClient`, bridges async AI progress into a visible top-of-screen think bar, and disposes worker resources on scene shutdown. - Handles end-of-round overlays and full-match restart flow. ### `android/app/src/main/java/com/phaser/scopa/MainActivity.java` @@ -166,6 +186,10 @@ main.ts -> GameScene -> engine.ts -> ai.ts + -> ai-worker-client.ts + -> ai-worker-protocol.ts + -> ai.worker.ts + -> ai.ts -> card-tracker.ts -> types.ts ``` @@ -184,10 +208,12 @@ Dependencies are one-directional at the application level: 4. `GameScene.create()` initializes a new `CardTracker`, creates the initial `GameState`, and animates the opening deal. 5. On each turn: - Human turns use click-driven selection and capture highlighting. - - AI turns call `chooseMove(state, playerIdx, difficulty, tracker, onProgress)`. -6. `chooseMove()` either returns immediately for heuristic tiers or performs batched master search while reporting `AIDecisionProgress`. -7. `GameScene.executeMove()` applies the move, updates the tracker, animates the result, refreshes the HUD, and advances the round. -8. When all hands are empty, `engine.ts` finalizes scoring and `GameScene` displays the round summary or final match screen. + - AI turns call `AIWorkerClient.chooseMove(state, playerIdx, difficulty, tracker, onProgress)`. +6. `AIWorkerClient` posts a typed request into `ai.worker.ts`; if worker setup fails, it falls back to in-thread `chooseMove()`. +7. `chooseMove()` either returns immediately for heuristic tiers or performs batched master search while reporting `AIDecisionProgress`. +8. Worker progress messages drive `GameScene.updateThinkBar()` until a result is posted back. +9. `GameScene.executeMove()` applies the move, updates the tracker, animates the result, refreshes the HUD, and advances the round. +10. When all hands are empty, `engine.ts` finalizes scoring and `GameScene` displays the round summary or final match screen. ## Build System diff --git a/docs/FINDINGS.md b/docs/FINDINGS.md index f10db46..d14c099 100644 --- a/docs/FINDINGS.md +++ b/docs/FINDINGS.md @@ -1,20 +1,22 @@ # Findings -> Last Updated: 2026-04-02T18:12:18.000Z +> Last Updated: 2026-04-02T19:05:00.000Z ## Summary -Initializer refresh for the current Scopone Scientifico codebase. The existing findings were stale relative to the latest AI and tracker implementation, so the observations below reflect the current source tree. +Initializer refresh for the current Scopone Scientifico codebase. The existing findings were stale relative to the current worker-backed AI execution path, so the observations below reflect the live source tree. ## Codebase Observations - Primary gameplay code lives in 8 TypeScript source files under `src/`; the Android wrapper adds 3 Java files. -- The largest modules are `src/scenes/GameScene.ts` (1446 lines) and `src/game/ai.ts` (1210 lines). +- The gameplay runtime now includes three AI transport files in addition to the rules engine: `ai-worker-protocol.ts`, `ai-worker-client.ts`, and `ai.worker.ts`. +- The largest concentration of logic still sits in `src/scenes/GameScene.ts` and `src/game/ai.ts`. - `src/game/` remains framework-independent and contains the rules engine, score calculation, card tracker, and AI logic. - The AI now has three distinct difficulty levels: `beginner`, `advanced`, and `master`. - The `advanced` and `master` tiers use `CardTracker` to reason about unseen cards instead of reading hidden hands directly. -- The `master` tier performs determinization plus alpha-beta search and reports progress back to the scene. -- `GameScene` displays AI progress through a top think bar and updates it from the `AIDecisionProgress` callback. +- The `master` tier performs determinization plus alpha-beta search and reports progress back through `AIDecisionProgress`. +- `GameScene` displays AI progress through a top think bar and updates it from worker-forwarded progress messages. +- `AIWorkerClient` degrades cleanly to in-thread `chooseMove()` execution when workers are unavailable or fail. - Audio remains fully procedural via Web Audio; no audio asset pipeline is present. - No ESLint or Prettier config is present. - The only repository-wide verification command supplied is `npx tsc --noEmit`. @@ -23,6 +25,7 @@ Initializer refresh for the current Scopone Scientifico codebase. The existing f - `GameScene.ts` still centralizes scene layout, input, effects, audio, HUD, and round transitions in one file, which raises maintenance cost. - `ai.ts` mixes heuristic tiers, inference helpers, determinization, and alpha-beta evaluation in one module. +- Worker message types and fallback behavior are separated cleanly, but the UI still knows about AI progress presentation details directly. - The `master` profile allows up to 9800 ms of search budget, which may be expensive on slower devices even with batch yielding. - There is still no dedicated automated test suite for rules or AI behavior beyond type-checking. - Formatting rules are enforced socially rather than by a linter/formatter toolchain. @@ -43,6 +46,14 @@ Initializer refresh for the current Scopone Scientifico codebase. The existing f - `master` orders legal moves with a quick evaluator, samples hidden hands, then scores moves with alpha-beta search under a deadline. - `masterMove()` yields back to the browser between batches so Phaser can repaint the progress UI. +### Worker execution snapshot + +- `GameScene` creates a fresh `AIWorkerClient` on scene creation and disposes it on shutdown. +- `AIWorkerClient` serializes a tracker snapshot instead of sending a live `CardTracker` instance across the worker boundary. +- `ai.worker.ts` reconstructs tracker state with `CardTracker.fromSnapshot()` before calling `chooseMove()`. +- Progress, results, and serialized worker errors all travel through `ai-worker-protocol.ts`. +- If worker initialization, posting, or message deserialization fails, pending requests are rerun with the in-thread AI path. + ### Scene / UI implementation snapshot - `MenuScene` exposes difficulty selection before match start.