- Rename module to gitea.iliadenisov.ru/developer/scrabble-solver so it can be consumed as a versioned dependency (no go.work replace / CI clone). - De-internalize wordlist and dictdawg as public packages. - Remove cmd/builddict, dictprep/, the dictionaries submodule and the dawg Makefile: the word-list parsing and DAWG build now live in the separate scrabble-dictionary repository, which publishes the DAWG set as a release artifact. - internal/dict loads the committed dawg/en_sowpods.dawg fixture for cmd/stress. - Update README/CLAUDE docs accordingly.
2.8 KiB
scrabble-solver — project guide
A Go library that, given a dictionary, a board position and a rack, returns every legal
play ranked by score, and scores/validates arbitrary plays. The move generator is the
DAWG algorithm (Appel & Jacobson) over github.com/iliadenisov/dafsa — a bit-packed,
minimised DAWG with a compact ≤63-symbol alphabet. A GADDAG generator was also built,
measured by self-play, and removed: DAWG won for this scoring-solver workload
(~7× smaller, comparable speed) — see RESULTS.md.
Module scrabble-solver, Go 1.26. Rulesets: English Scrabble, Russian Scrabble, and
Russian Эрудит (rules package); Эрудит has no Ё tile and folds Ё→Е in its dictionary.
Layout
scrabble/— the public API:Solver(NewSolver,GenerateMoves,ScorePlay,ValidatePlay), theMove/Placement/Wordtypes, the DAWG generator and scoring.board/,rack/,rules/— board grid (+ transpose), rack as per-letter counts, and rulesets (geometry, premium layout, tile values/counts, alphabet, bonus):rules.English(),rules.RussianScrabble(),rules.Erudit().dictdawg/,wordlist/— public helpers:dictdawg(build/load/serialise DAWGs over dafsa),wordlist(encode/filter/sort/dedupe +FoldYo). Imported by the separatescrabble-dictionaryrepo that builds and publishes the DAWG set.internal/—encoding,graph,dict(loads the committeddawg/en_sowpods.dawgforcmd/stress).cmd/stress,selfplay/— the self-play stress harness behindRESULTS.md.dawg/— committed dictionaries:en_sowpods.dawg,ru_scrabble.dawg,ru_erudit.dawg(Ё→Е folded). The word-list sources and build pipeline live in the separatescrabble-dictionaryrepo (which publishes the DAWG set as a release artifact); these committed copies are test fixtures.
Build & test
go test ./... # all packages green; also run go vet ./... and gofmt
Scoring and move generation are validated against real tournament games in GCG format
(scrabble/gcg_test.go + scrabble/testdata/*.gcg, including the 700+ club): for every
move the test checks the score, the running total, and that the generator actually
produces the played move with that score — canonical play, not invented cases.
Key facts
- Compact byte encoding: low 6 bits = alphabet index;
0x80= blank/wildcard (board, rack and output bytes only — never inside the graph). The public API is byte-indexed. - DAWG is the production generator; the GADDAG was removed after measurement.
- Detailed docs:
ALGORITHM.md(the algorithm — single source of truth),PLAN.md(design and decisions),RESULTS.md(DAWG-vs-GADDAG). The RU word-list pipeline and the DAWG build now live in thescrabble-dictionaryrepo.