-
Notifications
You must be signed in to change notification settings - Fork 9
/
board_utils.go
124 lines (113 loc) · 3.08 KB
/
board_utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package board
import (
"log"
"regexp"
"github.com/domino14/macondo/alphabet"
)
type TilesInPlay struct {
OnBoard []alphabet.MachineLetter
Rack1 []alphabet.MachineLetter
Rack2 []alphabet.MachineLetter
}
var boardPlaintextRegex = regexp.MustCompile(`\|([[:print:]]+)\|`)
var userRackRegex = regexp.MustCompile(`(?U)[[:print:]]+\s+([A-Z\?]*)\s+-?[0-9]+`)
func (g *GameBoard) ToDisplayText(alph *alphabet.Alphabet) string {
var str string
n := g.Dim()
for i := 0; i < n; i++ {
row := ""
for j := 0; j < n; j++ {
row = row + g.squares[i][j].DisplayString(alph) + " "
}
str = str + row + "\n"
}
return "\n" + str
}
// SetFromPlaintext sets the board from the given plaintext board.
// It returns a list of all played machine letters (tiles) so that the
// caller can reconcile the tile bag appropriately.
func (g *GameBoard) SetFromPlaintext(qText string,
alph *alphabet.Alphabet) *TilesInPlay {
tilesInPlay := &TilesInPlay{}
// Take a Quackle Plaintext Board and turn it into an internal structure.
// (Another alternative later is to implement GCG)
playedTiles := []alphabet.MachineLetter(nil)
result := boardPlaintextRegex.FindAllStringSubmatch(qText, -1)
if len(result) != 15 {
panic("Wrongly implemented")
}
g.tilesPlayed = 0
var err error
var letter alphabet.MachineLetter
for i := range result {
// result[i][1] has the string
for j, ch := range result[i][1] {
if j%2 != 0 {
continue
}
letter, err = alph.Val(ch)
if err != nil {
// Ignore the error; we are passing in a space or another
// board marker.
g.squares[i][j/2].letter = alphabet.EmptySquareMarker
} else {
g.squares[i][j/2].letter = letter
g.tilesPlayed++
playedTiles = append(playedTiles, letter)
}
}
}
userRacks := userRackRegex.FindAllStringSubmatch(qText, -1)
for i := range userRacks {
if i > 1 { // only the first two lines that match
break
}
rack := userRacks[i][1]
rackTiles := []alphabet.MachineLetter{}
for _, ch := range rack {
letter, err = alph.Val(ch)
if err != nil {
panic(err)
}
rackTiles = append(rackTiles, letter)
}
if i == 0 {
tilesInPlay.Rack1 = rackTiles
} else if i == 1 {
tilesInPlay.Rack2 = rackTiles
}
}
tilesInPlay.OnBoard = playedTiles
return tilesInPlay
}
func (b *GameBoard) SetRow(rowNum int, letters string, alph *alphabet.Alphabet) {
// Set the row in board to the passed in letters array.
for idx := 0; idx < b.Dim(); idx++ {
b.SetLetter(int(rowNum), idx, alphabet.EmptySquareMarker)
}
for idx, r := range letters {
if r != ' ' {
letter, err := alph.Val(r)
if err != nil {
log.Fatalf(err.Error())
}
b.SetLetter(int(rowNum), idx, letter)
}
}
}
// Two boards are equal if all the squares are equal. This includes anchors,
// letters, and cross-sets.
func (b *GameBoard) equals(b2 *GameBoard) bool {
if b.Dim() != b2.Dim() {
return false
}
for row := 0; row < b.Dim(); row++ {
for col := 0; col < b.Dim(); col++ {
if !b.GetSquare(row, col).equals(b2.GetSquare(row, col)) {
log.Printf("> Not equal, row %v col %v", row, col)
return false
}
}
}
return true
}