-
Notifications
You must be signed in to change notification settings - Fork 1
/
parse_fen.go
183 lines (174 loc) · 3.49 KB
/
parse_fen.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package main
import (
"errors"
"log"
"strconv"
"unicode/utf8"
)
// ParseFEN parses FEN notation
func ParseFEN(fen string, pos *Board) error {
if len(fen) <= 0 || pos == nil {
log.Fatalln("FEN or board structure is invalid")
}
rank := Rank8
file := FileA
piece := 0
pos.Reset()
// Parsing position of pieces in FEN notation
for (rank >= Rank1) && (len(fen) > 0) {
count := 1
switch string(fen[0]) {
case "p":
piece = Bp
break
case "r":
piece = Br
break
case "n":
piece = Bn
break
case "b":
piece = Bb
break
case "k":
piece = Bk
break
case "q":
piece = Bq
break
case "P":
piece = Wp
break
case "R":
piece = Wr
break
case "N":
piece = Wn
break
case "B":
piece = Wb
break
case "K":
piece = Wk
break
case "Q":
piece = Wq
break
case "1":
fallthrough
case "2":
fallthrough
case "3":
fallthrough
case "4":
fallthrough
case "5":
fallthrough
case "6":
fallthrough
case "7":
fallthrough
case "8":
piece = Empty
count, _ = strconv.Atoi(string(fen[0]))
break
case "/":
fallthrough
case " ":
rank--
file = FileA
fen = fen[1:len(fen)]
continue
default:
log.Println("Error in parsing FEN")
pos.Reset()
return errors.New("Error in parsing FEN")
}
for i := 0; i < count; i++ {
sq64 := (rank * 8) + file
var sq120 int
if sq64 >= 0 && sq64 < 64 {
sq120 = SQ120(sq64)
} else {
log.Println("Error in parsing FEN")
pos.Reset()
return errors.New("Error in parsing FEN")
}
if piece != Empty {
pos.Pieces[sq120] = piece
}
file++
}
fen = fen[1:len(fen)]
}
// Parsing side to play in FEN notation
if len(fen) <= 0 {
log.Println("Missing side in FEN notation")
pos.Reset()
return errors.New("Missing side in FEN notation")
}
if !((string(fen[0]) == "w") || (string(fen[0]) == "b")) {
log.Println("Error in parsing FEN, side should be w or b in FEN notation")
return errors.New("Error in parsing FEN, side should be w or b in FEN notation")
}
if string(fen[0]) == "w" {
pos.Side = White
} else {
pos.Side = Black
}
fen = fen[2:len(fen)]
// Parsing castling in FEN notation
if len(fen) <= 0 {
log.Println("Missing castling permissions in FEN notation")
pos.Reset()
return errors.New("Missing castling permissions in FEN notation")
}
for i := 0; i < 4; i++ {
if string(fen[0]) == " " {
break
}
switch string(fen[0]) {
case "K":
pos.CastlePerm |= Wkca
break
case "Q":
pos.CastlePerm |= Wqca
break
case "k":
pos.CastlePerm |= Bkca
break
case "q":
pos.CastlePerm |= Bqca
break
default:
break
}
fen = fen[1:len(fen)]
}
fen = fen[1:len(fen)]
// Parsing enPas in FEN notation
if len(fen) <= 0 {
log.Println("Missing enPas in FEN notation")
pos.Reset()
return errors.New("Missing enPas in FEN notation")
}
if string(fen[0]) != "-" {
fileRune, _ := utf8.DecodeRuneInString(string(fen[0]))
file = int(fileRune) - 97
rankConvert, _ := strconv.Atoi(string(fen[1]))
rank = rankConvert - 1
if file < FileA || file > FileH {
log.Println("Error in parsing enPas in FEN notation")
return errors.New("Error in parsing enPas in FEN notation")
}
if rank < Rank1 || rank > Rank8 {
log.Println("Error in parsing enPas in FEN notation")
return errors.New("Error in parsing enPas in FEN notation")
}
pos.EnPas = FR2SQ(file, rank)
}
// Generating PosKey of board structure
pos.PosKey = GeneratePosKey(pos)
pos.UpdateListsMaterial()
return nil
}