-
Notifications
You must be signed in to change notification settings - Fork 17
Board
The chess package uses a sophisticated board representation that combines bitboards with convenient lookup maps for optimal performance and ease of use. Each board state is represented by the Board struct, which maintains separate bitboards for each piece type and color, along with additional convenience bitboards for quick position analysis.
The Board struct maintains the following state:
type Board struct {
// Piece bitboards
bbWhiteKing bitboard
bbWhiteQueen bitboard
bbWhiteRook bitboard
bbWhiteBishop bitboard
bbWhiteKnight bitboard
bbWhitePawn bitboard
bbBlackKing bitboard
bbBlackQueen bitboard
bbBlackRook bitboard
bbBlackBishop bitboard
bbBlackKnight bitboard
bbBlackPawn bitboard
// Convenience bitboards
whiteSqs bitboard
blackSqs bitboard
emptySqs bitboard
// King square trackers
whiteKingSq Square
blackKingSq Square
}Each piece type (King, Queen, Rook, Bishop, Knight, Pawn) for each color (White, Black) has its own dedicated bitboard. This allows for:
- Quick piece location lookups
- Efficient move generation
- Fast position evaluation
The board maintains three additional bitboards for optimization:
-
whiteSqs: All squares occupied by white pieces -
blackSqs: All squares occupied by black pieces -
emptySqs: All empty squares
These convenience bitboards are automatically updated whenever the board state changes and provide O(1) lookup for:
- Square occupation checks
- Color-based position analysis
- Move validation
The position of both kings is tracked separately using whiteKingSq and blackKingSq. This provides:
- Instant king location lookup
- Efficient check detection
- Quick castling validation
// Create a new board from a square-piece mapping
func NewBoard(m map[Square]Piece) *BoardExample:
squares := map[Square]Piece{
NewSquare(FileE, Rank1): WhiteKing,
NewSquare(FileE, Rank8): BlackKing,
}
board := NewBoard(squares)// Get current board state as a square-piece mapping
func (b *Board) SquareMap() map[Square]Piece
// Get piece at specific square
func (b *Board) Piece(sq Square) Piece
// Check if square is occupied
func (b *Board) isOccupied(sq Square) boolThe board supports several transformation operations:
// Rotate board 90 degrees clockwise
func (b *Board) Rotate() *Board
// Flip board vertically or horizontally
func (b *Board) Flip(fd FlipDirection) *Board
// Transpose board over A8-H1 diagonal
func (b *Board) Transpose() *BoardThe board state is updated through the update method, which handles:
- Basic piece moves
- Captures
- Special moves:
- En passant captures
- Castling
- Pawn promotions
The board supports multiple serialization formats:
// FEN string representation
func (b *Board) String() string
func (b *Board) MarshalText() ([]byte, error)
func (b *Board) UnmarshalText(text []byte) error
// Binary representation
func (b *Board) MarshalBinary() ([]byte, error)
func (b *Board) UnmarshalBinary(data []byte) errorThe board can analyze positions for sufficient material:
func (b *Board) hasSufficientMaterial() boolThis method checks for:
- Presence of major pieces (Queen, Rook)
- Pawn existence
- Minor piece combinations
- Same-colored bishop scenarios
The board provides visualization methods for debugging:
// ASCII representation of the board
func (b *Board) Draw() stringExample output:
A B C D E F G H
8 r n b q k b n r
7 p p p p p p p p
6 - - - - - - - -
5 - - - - - - - -
4 - - - - - - - -
3 - - - - - - - -
2 P P P P P P P P
1 R N B Q K B N R
- Bitboard Operations: Most operations use bitwise operations, which are extremely fast on modern CPUs.
- Memory Usage: Each board instance uses 12 bitboards (64 bits each) plus convenience fields.
-
Copy Operations: The
copy()method performs a shallow copy, suitable for move generation and position analysis. - Cached Information: King positions and convenience bitboards are maintained to avoid recalculation.
The board itself is not thread-safe and should be copied when used across goroutines.
- The board representation does not store:
- Move history
- Castling rights
- En passant target squares
- These must be tracked separately by the game state manager.
- Use
SquareMap()for iteration over pieces - Use bitboard operations for move generation
- Use convenience bitboards for quick occupation checks
- Copy the board when exploring multiple variations
- Use
Draw()for debugging complex positions