-
Notifications
You must be signed in to change notification settings - Fork 0
/
encoding.go
117 lines (96 loc) · 2.86 KB
/
encoding.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
package main
import (
"errors"
"strconv"
"strings"
"github.com/andrewbackes/chess/piece"
"github.com/andrewbackes/chess/position/move"
"github.com/andrewbackes/chess/position/square"
)
const encodePosAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
var encodePromotionCharToPiece map[byte]piece.Type = map[byte]piece.Type{
'@': piece.Rook,
'$': piece.Knight,
'^': piece.Bishop,
'*': piece.Queen,
}
var encodePieceToPromotionChar map[piece.Type]byte = func() map[piece.Type]byte {
res := map[piece.Type]byte{}
for b, p := range encodePromotionCharToPiece {
res[p] = b
}
return res
}()
func encodeMove(m move.Move) (string, error) {
res := ""
if int(m.Source) < 0 || int(m.Source) >= len(encodePosAlphabet) {
return "", errors.New("Source square integer out of bounds: " + strconv.Itoa(int(m.Source)))
}
res += string(encodePosAlphabet[int(m.Source)])
if int(m.Destination) < 0 || int(m.Destination) >= len(encodePosAlphabet) {
return "", errors.New("Destination square integer out of bounds: " + strconv.Itoa(int(m.Destination)))
}
res += string(encodePosAlphabet[int(m.Destination)])
if m.Promote != piece.None {
b, ok := encodePieceToPromotionChar[m.Promote]
if !ok {
return "", errors.New("Invalid promotion piece: " + m.Promote.String())
}
res += string(b)
}
return res, nil
}
func EncodeGame(g *ChessGame) (string, error) {
res := ""
for _, position := range g.game.Positions {
if position.LastMove != move.Null {
if m, err := encodeMove(position.LastMove); err != nil {
return "", err
} else {
res += m
}
}
}
return res, nil
}
func DecodeMoves(moves string) ([]move.Move, error) {
res := []move.Move{}
if moves == "" {
return res, nil
}
for moves != "" {
move := move.Move{}
fromInt := strings.Index(encodePosAlphabet, string(moves[0]))
if fromInt == -1 {
return nil, errors.New("Invalid move from position character: " + string(moves[0]))
}
moves = moves[1:]
fromSquare := square.Square(fromInt)
if fromSquare < 0 || fromSquare > square.LastSquare {
return nil, errors.New("Invalid move from square integer: " + strconv.Itoa(fromInt))
}
move.Source = fromSquare
if len(moves) == 0 {
return nil, errors.New("Missing move to position character")
}
toInt := strings.Index(encodePosAlphabet, string(moves[0]))
if toInt == -1 {
return nil, errors.New("Invalid move to position character: " + string(moves[0]))
}
moves = moves[1:]
toSquare := square.Square(toInt)
if toSquare < 0 || toSquare > square.LastSquare {
return nil, errors.New("Invalid move to square integer: " + strconv.Itoa(toInt))
}
move.Destination = toSquare
if len(moves) > 0 {
if piece, ok := encodePromotionCharToPiece[moves[0]]; ok {
// next char is promotion character
moves = moves[1:]
move.Promote = piece
}
}
res = append(res, move)
}
return res, nil
}