Documentation
¶
Overview ¶
Package pgn provides PGN parsing and chess position handling using bitboards.
The core types are:
- GameState: bitboard-based position representation
- Mv: compact move encoding
- PGNScanner: streaming PGN parser
- ParsePGNParallel: high-performance parallel parser
Index ¶
- Constants
- func AppendCheckpointCSV(filename string, index uint64, fen string) error
- func ApplyMove(pos *GameState, m Mv) error
- func PackedFENFromFEN(fen string) (string, error)
- func PackedPositionFromFEN(fen string) (string, error)
- func Perft(pos *GameState, depth int) int64
- func UnmakeMove(pos *GameState, m Mv, undo UndoInfo)
- func ValidateParentMove(parent *GameState, move Mv) bool
- func ValidateParentMoveQuick(parent *GameState, move Mv) bool
- func WithLegalMoves(pos *GameState, fn func([]Mv))
- type Bitboard
- type CheckpointDFS
- type Color
- type Game
- type GameParser
- type GameState
- func (gs *GameState) BoardEquals(other *GameState) bool
- func (p *GameState) Copy() *GameState
- func (gs *GameState) Equals(other *GameState) bool
- func (p *GameState) IsCheckmate() bool
- func (p *GameState) IsInCheck() bool
- func (p *GameState) IsSquareAttacked(sq Square, byColor Color) bool
- func (p *GameState) IsStalemate() bool
- func (p *GameState) KingSquare(color Color) Square
- func (gs *GameState) Pack() PackedPosition
- func (gs *GameState) PackFEN() PackedFEN
- func (p *GameState) PieceAt(sq Square) byte
- func (p *GameState) String() string
- func (p *GameState) ToFEN() string
- type Mv
- type PGNScanner
- type PackedFEN
- func (pf PackedFEN) AppendString(dst []byte) []byte
- func (pf PackedFEN) CastlingRights() byte
- func (pf PackedFEN) EPFile() int
- func (pf PackedFEN) EPSquare() Square
- func (pf PackedFEN) Fullmove() int
- func (pf PackedFEN) Halfmove() int
- func (pf PackedFEN) Occupancy() uint64
- func (pf PackedFEN) PieceAt(sq Square) byte
- func (pf PackedFEN) PieceCount() int
- func (pf *PackedFEN) SetCastlingRights(castle byte)
- func (pf *PackedFEN) SetEPFile(file int)
- func (pf *PackedFEN) SetFullmove(fm int)
- func (pf *PackedFEN) SetHalfmove(hm int)
- func (pf *PackedFEN) SetSideToMove(c Color)
- func (pf PackedFEN) SideToMove() Color
- func (pf PackedFEN) String() string
- func (pf PackedFEN) ToFEN() string
- func (pf PackedFEN) ToPackedPosition() PackedPosition
- func (pf PackedFEN) Unpack() *GameState
- func (pf PackedFEN) UnpackInto(gs *GameState)
- type PackedPosition
- func (pp PackedPosition) AppendString(dst []byte) []byte
- func (pp PackedPosition) CastlingRights() byte
- func (pp PackedPosition) EPFile() int
- func (pp PackedPosition) EPSquare() Square
- func (pp PackedPosition) Occupancy() uint64
- func (pp PackedPosition) PieceAt(sq Square) byte
- func (pp PackedPosition) PieceCount() int
- func (pp PackedPosition) Pieces(fn func(sq Square, piece byte))
- func (pp *PackedPosition) SetCastlingRights(castle byte)
- func (pp *PackedPosition) SetEPFile(file int)
- func (pp *PackedPosition) SetSideToMove(c Color)
- func (pp PackedPosition) SideToMove() Color
- func (pp PackedPosition) String() string
- func (pp PackedPosition) ToFEN() string
- func (pp PackedPosition) Unpack() *GameState
- func (pp PackedPosition) UnpackInto(gs *GameState)
- type ParentCandidate
- type PositionEnumeratorDFS
- func (e *PositionEnumeratorDFS) ContinueFromCheckpoint(ckptIdx int, maxDepth int, callback func(uint64, *GameState, int) bool) error
- func (e *PositionEnumeratorDFS) CurrentIndexDFS() uint64
- func (e *PositionEnumeratorDFS) EnumerateDFS(maxDepth int, callback func(index uint64, pos *GameState, depth int) bool)
- func (e *PositionEnumeratorDFS) EnumerateDFSParallel(maxDepth int, callback func(index uint64, pos *GameState, depth int) bool)
- func (e *PositionEnumeratorDFS) GetCheckpointForIndexDFS(targetIdx uint64) *CheckpointDFS
- func (e *PositionEnumeratorDFS) GetCheckpointsDFS() []*CheckpointDFS
- func (e *PositionEnumeratorDFS) IndexOfBoardDFS(target *GameState, maxDepth int) (uint64, bool)
- func (e *PositionEnumeratorDFS) IndexOfPositionDFS(target *GameState, maxDepth int) (uint64, bool)
- func (e *PositionEnumeratorDFS) LoadCheckpointsCSV(filename string) (int, error)
- func (e *PositionEnumeratorDFS) PositionAtIndexDFS(targetIdx uint64, maxDepth int) (*GameState, bool)
- func (e *PositionEnumeratorDFS) SaveCheckpointsCSV(filename string, maxDepth int) error
- type PromoPiece
- type Square
- type UndoInfo
Constants ¶
const ( CheckpointIntervalDFS = 1 << 20 // 1,048,576 // Max depth for terminal detection (prevent infinite loops) MaxDepthDFS = 500 // ~250 moves, well beyond normal games )
Variables ¶
This section is empty.
Functions ¶
func AppendCheckpointCSV ¶
AppendCheckpointCSV appends a single checkpoint to a CSV file. This is useful for incremental saves during long enumerations.
func ApplyMove ¶
ApplyMove applies a move to the position without undo capability. This is simpler but slower than MakeMove/UnmakeMove for search.
func PackedFENFromFEN ¶
PackedFENFromFEN is a convenience function to get a base64 string from FEN. Returns the full FEN encoding (with metadata).
func PackedPositionFromFEN ¶
PackedPositionFromFEN is a convenience function to get a base64 string from FEN. Returns just the board encoding (no metadata).
func Perft ¶
Perft counts all legal move sequences to a given depth from a position. It uses parallel processing and pooled allocations for best performance. Returns the number of leaf nodes (positions) at the given depth.
func UnmakeMove ¶
UnmakeMove reverses a move using the undo info from MakeMove.
func ValidateParentMove ¶ added in v3.2.0
ValidateParentMove checks if the forward move from parent to current is legal. Use this after looking up a parent position in your store.
func ValidateParentMoveQuick ¶ added in v3.2.0
ValidateParentMoveQuick is like ValidateParentMove but only checks from/to/promo. This is sufficient for most cases since flags are mainly internal.
func WithLegalMoves ¶
WithLegalMoves generates legal moves using pooled slices and calls fn with them. The moves slice is automatically released after fn returns. This is more efficient than GenerateLegalMoves for repeated calls.
Types ¶
type Bitboard ¶
type Bitboard uint64
Bitboard represents a set of squares as a 64-bit integer where each bit corresponds to a square (bit 0 = a1, bit 63 = h8).
type CheckpointDFS ¶
type CheckpointDFS struct {
Index uint64 // Position index
Depth int // Current ply depth
State GameState // Position state (for quick restart)
Stack []Mv // Move stack to reach this position (enables DFS resumption)
}
CheckpointDFS stores minimal info for DFS restart.
type GameParser ¶
type GameParser struct {
// Games yields parsed games. Closed when parsing completes.
Games <-chan *Game
// contains filtered or unexported fields
}
GameParser streams parsed games from a PGN source.
func Games ¶
func Games(path string, workers ...int) *GameParser
Games returns a parser that yields games from a PGN file. Handles .zst compressed files automatically.
Workers defaults to NumCPU-1 (leaving one core for decompression).
Example:
for game := range pgn.Games("huge.pgn.zst").Games {
fmt.Println(game.Tags["Event"])
}
func GamesFromReader ¶
func GamesFromReader(r io.Reader, workers ...int) *GameParser
GamesFromReader returns a channel that yields parsed games from a reader. Workers defaults to NumCPU-1 (leaving one core for I/O).
func (*GameParser) Err ¶
func (gp *GameParser) Err() error
Err returns any error that occurred during parsing. Only valid after Games channel is closed.
func (*GameParser) Stop ¶
func (gp *GameParser) Stop()
Stop cancels parsing early. Safe to call multiple times.
type GameState ¶
type GameState struct {
SideToMove Color
Castle uint8
EP Square
Halfmove int
Fullmove int
FEN string
// contains filtered or unexported fields
}
GameState represents a chess position using bitboards.
func NewStartingPosition ¶
func NewStartingPosition() *GameState
NewStartingPosition creates a new game at the standard starting position.
func (*GameState) BoardEquals ¶
BoardEquals compares board state (ignores halfmove/fullmove counters). Returns true if piece positions, side to move, castling rights, and EP square match.
func (*GameState) Equals ¶
Equals compares positions exactly (including halfmove/fullmove counters).
func (*GameState) IsCheckmate ¶
IsCheckmate returns true if the side to move is in checkmate.
func (*GameState) IsSquareAttacked ¶
IsSquareAttacked returns true if the given square is attacked by the specified color.
func (*GameState) IsStalemate ¶
IsStalemate returns true if the side to move is in stalemate (not in check but has no legal moves).
func (*GameState) KingSquare ¶
KingSquare returns the square of the king for the given color. Returns -1 if no king is found.
func (*GameState) Pack ¶
func (gs *GameState) Pack() PackedPosition
Pack encodes a GameState into a PackedPosition (26 bytes with metadata).
func (*GameState) PackFEN ¶
PackFEN encodes a GameState into a PackedFEN (29 bytes with all metadata).
func (*GameState) PieceAt ¶
PieceAt returns the piece character at the given square. Returns 0 for empty, uppercase for white, lowercase for black.
type Mv ¶
type Mv struct {
From Square
To Square
Promo PromoPiece
Flags uint16
}
Mv represents a chess move with from/to squares and optional promotion.
func GenerateLegalMoves ¶
GenerateLegalMoves returns all legal moves from the position.
func ParseSANBytes ¶
ParseSANBytes parses a SAN move from a byte slice without allocations.
type PGNScanner ¶
type PGNScanner struct {
// contains filtered or unexported fields
}
PGNScanner scans PGN games from a reader one at a time.
func NewPGNScanner ¶
func NewPGNScanner(r io.Reader) *PGNScanner
NewPGNScanner creates a new PGN scanner that reads from r.
func (*PGNScanner) Next ¶
func (ps *PGNScanner) Next() bool
Next returns true if there are more games to scan.
func (*PGNScanner) Scan ¶
func (ps *PGNScanner) Scan() (*Game, error)
Scan parses and returns the next game, or an error if parsing fails.
type PackedFEN ¶
type PackedFEN [29]byte
PackedFEN is a compact 29-byte representation containing all FEN fields. Layout:
- Bytes 0-25: PackedPosition (board + metadata)
- Byte 26: Halfmove clock (0-255)
- Bytes 27-28: Fullmove number (little-endian, 1-65535)
func ParsePackedFEN ¶
ParsePackedFEN decodes a base64 URL-safe encoded packed FEN.
func ParsePackedFENBytes ¶ added in v3.1.0
ParsePackedFENBytes decodes a base64 URL-safe encoded packed FEN from bytes. This can avoid allocation when the input is already a byte slice.
func (PackedFEN) AppendString ¶ added in v3.1.0
AppendString appends the base64 URL-safe encoding to dst and returns the extended buffer. This is the zero-allocation version of String() when dst has sufficient capacity.
func (PackedFEN) CastlingRights ¶
CastlingRights returns the castling rights byte. Bit 0: White kingside, Bit 1: White queenside, Bit 2: Black kingside, Bit 3: Black queenside.
func (PackedFEN) PieceCount ¶
PieceCount returns the number of pieces on the board.
func (*PackedFEN) SetCastlingRights ¶
SetCastlingRights sets the castling rights.
func (*PackedFEN) SetFullmove ¶
SetFullmove sets the fullmove number (capped at 65535, minimum 1).
func (*PackedFEN) SetHalfmove ¶
SetHalfmove sets the halfmove clock (capped at 255).
func (*PackedFEN) SetSideToMove ¶
SetSideToMove sets the side to move.
func (PackedFEN) SideToMove ¶
SideToMove returns the side to move (White or Black).
func (PackedFEN) ToPackedPosition ¶
func (pf PackedFEN) ToPackedPosition() PackedPosition
ToPackedPosition extracts the position (without move counters).
func (PackedFEN) UnpackInto ¶ added in v3.1.0
UnpackInto decodes a PackedFEN into an existing GameState (zero allocation). The GameState is fully reset before unpacking.
type PackedPosition ¶
type PackedPosition [26]byte
PackedPosition is a compact 26-byte representation of a chess position. Layout:
- Bytes 0-7: Occupancy bitmap (bit i set means square i has a piece)
- Bytes 8-23: Piece codes (4 bits each, up to 32 pieces, in occupancy bit order)
- Byte 24: Flags (side to move, castling rights)
- Byte 25: EP file (0-7, or 0xFF for none)
func ParsePackedPosition ¶
func ParsePackedPosition(s string) (PackedPosition, error)
ParsePackedPosition decodes a base64 URL-safe encoded packed position.
func ParsePackedPositionBytes ¶ added in v3.1.0
func ParsePackedPositionBytes(src []byte) (PackedPosition, error)
ParsePackedPositionBytes decodes a base64 URL-safe encoded packed position from bytes. This can avoid allocation when the input is already a byte slice.
func (PackedPosition) AppendString ¶ added in v3.1.0
func (pp PackedPosition) AppendString(dst []byte) []byte
AppendString appends the base64 URL-safe encoding to dst and returns the extended buffer. This is the zero-allocation version of String() when dst has sufficient capacity.
func (PackedPosition) CastlingRights ¶
func (pp PackedPosition) CastlingRights() byte
CastlingRights returns the castling rights byte. Bit 0: White kingside, Bit 1: White queenside, Bit 2: Black kingside, Bit 3: Black queenside.
func (PackedPosition) EPFile ¶
func (pp PackedPosition) EPFile() int
EPFile returns the en passant file (0-7), or -1 if none.
func (PackedPosition) EPSquare ¶
func (pp PackedPosition) EPSquare() Square
EPSquare returns the en passant target square, or -1 if none.
func (PackedPosition) Occupancy ¶
func (pp PackedPosition) Occupancy() uint64
Occupancy returns the 64-bit bitmap of occupied squares.
func (PackedPosition) PieceAt ¶
func (pp PackedPosition) PieceAt(sq Square) byte
PieceAt returns the piece at the given square, or 0 if empty. Returns piece character: P, N, B, R, Q, K (white) or p, n, b, r, q, k (black).
func (PackedPosition) PieceCount ¶
func (pp PackedPosition) PieceCount() int
PieceCount returns the number of pieces on the board.
func (PackedPosition) Pieces ¶
func (pp PackedPosition) Pieces(fn func(sq Square, piece byte))
Pieces iterates over all pieces on the board. Calls fn with (square, piece character) for each piece.
func (*PackedPosition) SetCastlingRights ¶
func (pp *PackedPosition) SetCastlingRights(castle byte)
SetCastlingRights sets the castling rights.
func (*PackedPosition) SetEPFile ¶
func (pp *PackedPosition) SetEPFile(file int)
SetEPFile sets the en passant file (0-7), or -1 for none.
func (*PackedPosition) SetSideToMove ¶
func (pp *PackedPosition) SetSideToMove(c Color)
SetSideToMove sets the side to move.
func (PackedPosition) SideToMove ¶
func (pp PackedPosition) SideToMove() Color
SideToMove returns the side to move (White or Black).
func (PackedPosition) String ¶
func (pp PackedPosition) String() string
String returns the base64 URL-safe encoding of the packed position.
func (PackedPosition) ToFEN ¶
func (pp PackedPosition) ToFEN() string
ToFEN converts the packed position to a FEN string (with default metadata).
func (PackedPosition) Unpack ¶
func (pp PackedPosition) Unpack() *GameState
Unpack decodes a PackedPosition into a GameState.
func (PackedPosition) UnpackInto ¶ added in v3.1.0
func (pp PackedPosition) UnpackInto(gs *GameState)
UnpackInto decodes a PackedPosition into an existing GameState (zero allocation). The GameState is fully reset before unpacking.
type ParentCandidate ¶ added in v3.2.0
type ParentCandidate struct {
Position PackedPosition
Move Mv // The forward move from parent to current position
}
ParentCandidate represents a candidate parent position with the connecting move.
func GenerateParentPositions ¶ added in v3.2.0
func GenerateParentPositions(pos *GameState) []ParentCandidate
GenerateParentPositions generates all candidate parent positions. For each candidate, Move indicates the forward move from parent to current position.
This generates pseudo-legal retro-moves and should be validated by: 1. Looking up Position in your store 2. If found, verifying Move is in GenerateLegalMoves(parent)
type PositionEnumeratorDFS ¶
type PositionEnumeratorDFS struct {
// contains filtered or unexported fields
}
PositionEnumeratorDFS performs depth-first enumeration.
func NewPositionEnumeratorDFS ¶
func NewPositionEnumeratorDFS(startPos *GameState) *PositionEnumeratorDFS
NewPositionEnumeratorDFS creates a DFS enumerator.
func (*PositionEnumeratorDFS) ContinueFromCheckpoint ¶
func (e *PositionEnumeratorDFS) ContinueFromCheckpoint( ckptIdx int, maxDepth int, callback func(uint64, *GameState, int) bool, ) error
ContinueFromCheckpoint continues enumeration from a checkpoint. This allows extending enumeration depth or resuming after interruption.
func (*PositionEnumeratorDFS) CurrentIndexDFS ¶
func (e *PositionEnumeratorDFS) CurrentIndexDFS() uint64
CurrentIndexDFS returns the current enumeration index.
func (*PositionEnumeratorDFS) EnumerateDFS ¶
func (e *PositionEnumeratorDFS) EnumerateDFS( maxDepth int, callback func(index uint64, pos *GameState, depth int) bool, )
EnumerateDFS performs depth-first enumeration with make/unmake. This is MUCH more memory efficient than BFS - only O(depth) memory.
The enumeration order is deterministic based on move generation order. Terminal conditions:
- Checkmate/Stalemate (no legal moves)
- 50-move rule (halfmove >= 100)
- Threefold repetition (same position 3x on path)
- Max depth reached (safety limit)
- Callback returns false (early stop)
The callback should return true to continue, false to stop enumeration.
func (*PositionEnumeratorDFS) EnumerateDFSParallel ¶
func (e *PositionEnumeratorDFS) EnumerateDFSParallel( maxDepth int, callback func(index uint64, pos *GameState, depth int) bool, )
EnumerateDFSParallel performs two-pass parallel enumeration with deterministic ordering.
Pass 1: Count subtree sizes for each root move (parallel) Pass 2: Enumerate each subtree with correct index offsets (parallel)
This maintains deterministic position-to-index mapping while using all CPU cores.
func (*PositionEnumeratorDFS) GetCheckpointForIndexDFS ¶
func (e *PositionEnumeratorDFS) GetCheckpointForIndexDFS(targetIdx uint64) *CheckpointDFS
GetCheckpointForIndexDFS finds the checkpoint at or before the given index.
func (*PositionEnumeratorDFS) GetCheckpointsDFS ¶
func (e *PositionEnumeratorDFS) GetCheckpointsDFS() []*CheckpointDFS
GetCheckpointsDFS returns all stored checkpoints.
func (*PositionEnumeratorDFS) IndexOfBoardDFS ¶
func (e *PositionEnumeratorDFS) IndexOfBoardDFS(target *GameState, maxDepth int) (uint64, bool)
IndexOfBoardDFS searches for a board state (ignoring move counters) and returns its first index. This is faster than IndexOfPositionDFS when you only care about the board configuration.
func (*PositionEnumeratorDFS) IndexOfPositionDFS ¶
func (e *PositionEnumeratorDFS) IndexOfPositionDFS(target *GameState, maxDepth int) (uint64, bool)
IndexOfPositionDFS searches for a position and returns its index. Requires exact match including halfmove and fullmove counters.
func (*PositionEnumeratorDFS) LoadCheckpointsCSV ¶
func (e *PositionEnumeratorDFS) LoadCheckpointsCSV(filename string) (int, error)
LoadCheckpointsCSV loads checkpoints from a CSV file. Returns the number of checkpoints loaded. If filename ends with .zstd or .zst, the input is decompressed.
func (*PositionEnumeratorDFS) PositionAtIndexDFS ¶
func (e *PositionEnumeratorDFS) PositionAtIndexDFS(targetIdx uint64, maxDepth int) (*GameState, bool)
PositionAtIndexDFS returns the position at a specific index. This replays the DFS from the start until reaching the target index.
func (*PositionEnumeratorDFS) SaveCheckpointsCSV ¶
func (e *PositionEnumeratorDFS) SaveCheckpointsCSV(filename string, maxDepth int) error
SaveCheckpointsCSV writes checkpoints to a CSV file with metadata. Format: index,depth,fen,stack with maxDepth metadata header. The stack field contains comma-separated UCI moves. If filename ends with .zstd or .zst, the output is compressed.
type PromoPiece ¶
type PromoPiece int
PromoPiece represents the piece type for pawn promotion.
const ( NoPromo PromoPiece = iota PromoQueen PromoRook PromoBishop PromoKnight )
type Square ¶
type Square int
Square is a board square index from 0-63, where a1=0, b1=1, ..., h8=63.
const ( SqA1 Square = iota SqB1 SqC1 SqD1 SqE1 SqF1 SqG1 SqH1 SqA2 SqB2 SqC2 SqD2 SqE2 SqF2 SqG2 SqH2 SqA3 SqB3 SqC3 SqD3 SqE3 SqF3 SqG3 SqH3 SqA4 SqB4 SqC4 SqD4 SqE4 SqF4 SqG4 SqH4 SqA5 SqB5 SqC5 SqD5 SqE5 SqF5 SqG5 SqH5 SqA6 SqB6 SqC6 SqD6 SqE6 SqF6 SqG6 SqH6 SqA7 SqB7 SqC7 SqD7 SqE7 SqF7 SqG7 SqH7 SqA8 SqB8 SqC8 SqD8 SqE8 SqF8 SqG8 SqH8 SqNone Square = -1 )
Square constants for convenient reference.
func MakeSquare ¶
MakeSquare creates a Square from file (0-7) and rank (0-7).
func ParseSquare ¶
ParseSquare parses algebraic notation (e.g., "e4") to a Square.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
build_checkpoints
command
build_checkpoints is a tool for building position index checkpoint files.
|
build_checkpoints is a tool for building position index checkpoint files. |
|
zsttest
command
|