Files
Ilia Denisov 15c7959d96 Implement Scrabble move generator (DAWG) with English and Russian rules
A Go library that returns every legal play ranked by score and scores or
validates plays, using the Appel-Jacobson DAWG algorithm over
github.com/iliadenisov/dafsa v1.1.0.

- DAWG move generation (across / down / both), full tournament scoring with a
  per-tile breakdown; public Solver: GenerateMoves (ranked), ScorePlay,
  ValidatePlay.
- Rulesets: English Scrabble, Russian Scrabble, Эрудит (parameterizable Ruleset).
- cmd/builddict (build the DAWG from the dictionaries submodule), cmd/stress
  (self-play benchmark), selfplay engine; brute-force test oracle.
- A GADDAG was implemented, benchmarked and removed (the DAWG was smaller and
  faster for a scoring solver); see RESULTS.md and ALGORITHM.md.
2026-06-01 16:07:32 +02:00

62 lines
1.5 KiB
Go

package rules
import "testing"
func sumCounts(c []int) int {
s := 0
for _, v := range c {
s += v
}
return s
}
func TestRussianScrabble(t *testing.T) {
rs := RussianScrabble()
if err := rs.Validate(); err != nil {
t.Fatal(err)
}
if rs.Size() != 33 {
t.Errorf("alphabet size %d, want 33", rs.Size())
}
if n := sumCounts(rs.Counts); n != 102 || n+rs.Blanks != 104 {
t.Errorf("bag = %d letters + %d blanks, want 102+2=104", n, rs.Blanks)
}
if rs.Bingo != 50 {
t.Errorf("bonus %d, want 50", rs.Bingo)
}
if rs.Premium(7, 7) != DW {
t.Errorf("centre premium %d, want DW", rs.Premium(7, 7))
}
if rs.Values[6] != 3 || rs.Counts[6] != 1 { // ё
t.Errorf("ё = value %d count %d, want 3/1", rs.Values[6], rs.Counts[6])
}
}
func TestErudit(t *testing.T) {
rs := Erudit()
if err := rs.Validate(); err != nil {
t.Fatal(err)
}
if rs.Size() != 33 {
t.Errorf("alphabet size %d, want 33", rs.Size())
}
if n := sumCounts(rs.Counts); n != 128 || n+rs.Blanks != 131 {
t.Errorf("bag = %d letters + %d blanks, want 128+3=131", n, rs.Blanks)
}
if rs.Bingo != 15 {
t.Errorf("bonus %d, want 15", rs.Bingo)
}
if rs.Center != 7*15+7 {
t.Errorf("centre index %d, want %d", rs.Center, 7*15+7)
}
if rs.Premium(7, 7) != None {
t.Errorf("centre premium %d, want None (Эрудит centre does not double)", rs.Premium(7, 7))
}
if rs.Counts[6] != 0 { // ё has no tile
t.Errorf("ё count %d, want 0", rs.Counts[6])
}
if rs.Premium(0, 0) != TW {
t.Errorf("corner premium %d, want TW (board otherwise standard)", rs.Premium(0, 0))
}
}