-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboard.go
148 lines (129 loc) · 3.4 KB
/
board.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
package chess
import (
"strconv"
"strings"
"unicode"
)
// Board represents a 8x8 matrix, that consists of rows
// of Pieces.
//
// Note: If you intend in creating a new Board, use NewBoard()
// function, or else the created board's piece's position will
// be (0, 0) by default.
type Board [8][8]Piece
// PieceAtSquare returns a copy of the Piece placed in the
// board.
//
// If there is no piece at that position, it's Kind and Color
// will be none (Kind_None and Color_None).
//
// Note: It assumes that the square is correct. If you create a Square
// instance without the NewSquare, make sure it's valid.
func (b Board) PieceAtSquare(square Square) Piece {
return b[square.I][square.J]
}
// PieceAtSquareAlgebraic returns a copy of the Piece placed in the
// board.
//
// If the algebraic position is invalid, it will return an empty Piece and it's error.
//
// Examples:
//
// PieceAtSquareAlgebraic("d2") // returns Piece{Kind:Kind_Pawn, Color:Color_White, ...}, nil
// PieceAtSquareAlgebraic("aa") // returns Piece{}, error
func (b Board) PieceAtSquareAlgebraic(algebraic string) (Piece, error) {
square, err := NewSquareFromAlgebraic(algebraic)
if err != nil {
return Piece{}, err
}
return b.PieceAtSquare(square), nil
}
// Fen returns a string of the board's piece placement
// in Forsyth–Edwards Notation.
//
// For example, for a starting chess game would return:
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR
//
// Note: This Fen() function returns solely the FEN information
// related to the board's piece placement. You should use
// the Position type's Fen() function if you intend to
// get the turn, halfmove clock, etc.
func (b *Board) Fen() string {
var sb strings.Builder
spaceAccum := 0
for i := 0; i < 8; i++ {
for j := 0; j < 8; j++ {
if b[i][j].Kind == Kind_None {
spaceAccum++
} else {
if spaceAccum > 0 {
sb.WriteString(strconv.Itoa(spaceAccum))
spaceAccum = 0
}
kindRune := b[i][j].Kind.Rune()
if b[i][j].Color == Color_White {
kindRune = unicode.ToUpper(kindRune)
}
sb.WriteRune(kindRune)
}
}
if spaceAccum > 0 {
sb.WriteString(strconv.Itoa(spaceAccum))
spaceAccum = 0
}
if i != 7 {
sb.WriteRune('/')
}
}
return sb.String()
}
// Unicode returns the unicode representation of the board, with
// ranks, files and pieces.
func (b Board) Unicode() string {
s := ""
for i := 0; i < 8; i++ {
s += strconv.Itoa(i) + " "
for j := 0; j < 8; j++ {
s += string([]rune{b[i][j].Unicode(), ' '})
}
s += "\n"
}
return s + " a b c d e f g h"
}
func newBoardEmpty() Board {
var board Board
for i := uint8(0); i < 8; i++ {
for j := uint8(0); j < 8; j++ {
board[i][j].Square = newSquare(i, j)
board[i][j].Color = Color_None
board[i][j].Kind = Kind_None
}
}
return board
}
func newBoardFromFen(placementFenData [8]string) Board {
board := newBoardEmpty()
col := uint8(0)
row := uint8(0)
for _, rowData := range placementFenData {
for _, colData := range rowData {
if unicode.IsNumber(colData) {
colsToJump, _ := strconv.Atoi(string(colData))
col += uint8(colsToJump) - 1 // Subtract current
} else {
kind, color := KindAndColorFromRune(colData)
board.createPieceAt(color, kind, row, col)
}
col++
if col >= 8 {
col = 0
}
}
row++
col = 0
}
return board
}
func (b *Board) createPieceAt(color Color, kind Kind, i, j uint8) {
b[i][j] = newPiece(color, kind, newSquare(i, j))
}