package scrabble import ( "testing" "gitea.iliadenisov.ru/developer/scrabble-solver/board" "gitea.iliadenisov.ru/developer/scrabble-solver/internal/encoding" "gitea.iliadenisov.ru/developer/scrabble-solver/rules" ) const plain7 = `....... ....... ....... ...+... ....... ....... .......` // plainRules is a 7x7 board with no premiums and English tile values, for isolating // word-assembly and cross-word logic from premium multipliers. func plainRules(t *testing.T) *rules.Ruleset { t.Helper() eng := rules.English() rs, err := rules.FromTemplate("plain7", eng.Alphabet, eng.Values, eng.Counts, 2, 7, 50, plain7) if err != nil { t.Fatal(err) } return rs } // indices: a=0 c=2 o=14 t=19 x=23 func TestEvaluateSimpleWord(t *testing.T) { rs := plainRules(t) b := board.New(7, 7) m, err := Evaluate(b, rs, Horizontal, []Placement{ {Row: 3, Col: 1, Letter: 2}, {Row: 3, Col: 2, Letter: 0}, {Row: 3, Col: 3, Letter: 19}, }) if err != nil { t.Fatal(err) } if m.Main.Score != 5 || m.Score != 5 { t.Errorf("cat: main=%d total=%d, want 5/5", m.Main.Score, m.Score) } if len(m.Cross) != 0 || m.Bonus != 0 { t.Errorf("cat: cross=%d bonus=%d, want 0/0", len(m.Cross), m.Bonus) } } func TestEvaluateCrossWord(t *testing.T) { rs := plainRules(t) b := board.New(7, 7) b.Set(2, 3, encoding.Cell(14, false)) // o b.Set(3, 3, encoding.Cell(23, false)) // x // Play "at" horizontally on row 4; the 'a' on col 3 forms the cross word "oxa". m, err := Evaluate(b, rs, Horizontal, []Placement{ {Row: 4, Col: 3, Letter: 0}, {Row: 4, Col: 4, Letter: 19}, }) if err != nil { t.Fatal(err) } if m.Main.Score != 2 { t.Errorf("main 'at' = %d, want 2", m.Main.Score) } if len(m.Cross) != 1 || m.Cross[0].Score != 10 { t.Errorf("cross = %+v, want one word scoring 10 (oxa)", m.Cross) } if m.Score != 12 { t.Errorf("total = %d, want 12", m.Score) } } func TestEvaluatePremiums(t *testing.T) { rs := rules.English() // (0,3) is a double-letter square: c(3)*2 + a(1) + t(1) = 8. b := board.New(15, 15) m, err := Evaluate(b, rs, Horizontal, []Placement{ {Row: 0, Col: 3, Letter: 2}, {Row: 0, Col: 4, Letter: 0}, {Row: 0, Col: 5, Letter: 19}, }) if err != nil { t.Fatal(err) } if m.Score != 8 { t.Errorf("DL cat = %d, want 8", m.Score) } // (1,1) is a double-word square: (c(3) + a(1)) * 2 = 8. b2 := board.New(15, 15) m2, err := Evaluate(b2, rs, Horizontal, []Placement{ {Row: 1, Col: 1, Letter: 2}, {Row: 1, Col: 2, Letter: 0}, }) if err != nil { t.Fatal(err) } if m2.Score != 8 { t.Errorf("DW ca = %d, want 8", m2.Score) } } func TestEvaluateBingo(t *testing.T) { rs := plainRules(t) b := board.New(7, 7) tiles := make([]Placement, 7) for c := range 7 { tiles[c] = Placement{Row: 0, Col: c, Letter: 0} // seven a's } m, err := Evaluate(b, rs, Horizontal, tiles) if err != nil { t.Fatal(err) } if m.Bonus != 50 || m.Score != 7+50 { t.Errorf("bingo: bonus=%d total=%d, want 50/57", m.Bonus, m.Score) } } func TestEvaluateErrors(t *testing.T) { rs := plainRules(t) b := board.New(7, 7) b.Set(2, 3, encoding.Cell(14, false)) if _, err := Evaluate(b, rs, Horizontal, nil); err == nil { t.Error("empty play: want error") } if _, err := Evaluate(b, rs, Horizontal, []Placement{{Row: 2, Col: 3, Letter: 0}}); err == nil { t.Error("occupied square: want error") } if _, err := Evaluate(b, rs, Horizontal, []Placement{ {Row: 3, Col: 1, Letter: 0}, {Row: 4, Col: 2, Letter: 0}, }); err == nil { t.Error("non-collinear: want error") } if _, err := Evaluate(b, rs, Horizontal, []Placement{ {Row: 5, Col: 1, Letter: 0}, {Row: 5, Col: 3, Letter: 0}, }); err == nil { t.Error("gap: want error") } }