Stage 2: engine package over scrabble-solver (registry, bag, Game, replay)
Tests · Go / test (push) Successful in 6s
Tests · Integration / integration (push) Successful in 7s

backend/internal/engine wraps the sibling scrabble-solver library in-process:

- Registry: versioned DAWG load via dafsa.Load, keyed by (variant, dict_version),
  latest-per-variant; English / Russian / Эрудит handled uniformly.
- Bag: own deterministic, seeded tile bag with Draw + Return (for exchanges),
  since the solver's self-play bag cannot return tiles.
- Game: pure rules engine — deal, play/pass/exchange/resign, refill, per-move
  scoring, turn order, and end-condition detection (empty bag + empty rack, six
  scoreless turns, resignation) with end-game rack adjustment.
- decode/ReplayBoard: dictionary-independent MoveRecords and board replay via
  scrabble.Apply (no internal/encoding), realising ARCHITECTURE §9.1.

Wiring: go.work gains "replace scrabble-solver => ../scrabble-solver"; backend
requires scrabble-solver (placeholder) and github.com/iliadenisov/dafsa directly.
Both Go CI workflows clone the public solver sibling (master HEAD, no token) and
set BACKEND_DICT_DIR.

Docs: ARCHITECTURE §5/§14, TESTING engine layer, backend README, and PLAN
refinements + deferred TODOs (publish/version solver; split engine vs dictionary
generator).
This commit is contained in:
Ilia Denisov
2026-06-02 15:10:08 +02:00
parent 7bd461bfc7
commit 6d0dd4fb14
19 changed files with 1590 additions and 19 deletions
+11 -4
View File
@@ -15,10 +15,17 @@ tests or touching CI.
by a separate CI workflow (`integration.yaml`; Ryuk disabled, serial). Slow.
- **UI** *(introduced with the UI in Stage 7)* — Vitest (unit) + Playwright
(e2e), mirroring the chosen plain-Svelte + Vite toolchain.
- **Engine** — correctness of scoring and move generation is owned by
`scrabble-solver`'s own GCG-backed tests. The backend adds regression tests
for end-conditions, the 24-hour timeout / auto-resign, robot balance and
margin targeting, and **dictionary-independent history replay**.
- **Engine** *(Stage 2+)* — correctness of scoring and move generation is owned
by `scrabble-solver`'s own GCG-backed tests. `backend/internal/engine` adds, on
top of the embedded solver: per-variant smoke tests (load all three committed
DAWGs and validate a known word, including Эрудит), bag draw/return determinism
and exchange accounting, the `Game` end-conditions (empty bag with an empty
rack, and six scoreless turns) with end-game rack scoring, and
**dictionary-independent history replay** (`ReplayBoard` reproduces a full
greedy game's final board from decoded records alone). The engine tests read
the DAWGs from `BACKEND_DICT_DIR` (or the sibling `scrabble-solver` checkout)
and fail loudly when it is absent. The 24-hour timeout / auto-resign and robot
balance/margin regression tests arrive with those stages.
## Principles