#chess-engine #polyglot #chess #opening-book-format

polyglot-book-rs

A Rust library for reading and using Polyglot opening book format for chess engines

1 unstable release

0.1.0 Nov 13, 2025

#750 in Parser implementations


Used in lunar-chess

MIT/Apache

54KB
770 lines

polyglot-book-rs

A Rust library for reading and using Polyglot opening book format for chess engines.

Crates.io Documentation License

Features

  • Load Polyglot books: Read .bin format opening book files
  • FEN support: Query moves directly from FEN strings
  • Generic board interface: Integrate with any chess engine via the BoardPosition trait
  • Complete move data: Access move weights, algebraic notation, and position hashes
  • Correct hash implementation: Uses the official Polyglot specification with verified hash values

Quick Start

Add this to your Cargo.toml:

[dependencies]
polyglot-book-rs = "0.1.0"

Basic Usage

use polyglot_book_rs::PolyglotBook;

// Load a book file
let book = PolyglotBook::load("Perfect2023.bin")?;

// Query by FEN string
let starting_position = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
if let Some(entry) = book.get_best_move_from_fen(starting_position) {
    println!("Best move: {} (weight: {})", entry.move_string, entry.weight);
}

// Get all moves for a position
let all_moves = book.get_all_moves_from_fen(starting_position);
for entry in all_moves {
    println!("Move: {} (weight: {})", entry.move_string, entry.weight);
}

Integration with Custom Chess Engines

Implement the BoardPosition trait for your board representation:

use polyglot_book_rs::{BoardPosition, Piece, PolyglotBook};

struct MyBoard {
    // Your board representation
}

impl BoardPosition for MyBoard {
    fn piece_at(&self, square: u8) -> Piece {
        // Return the piece at the given square (0-63, a1=0, h8=63)
        // Your implementation here
    }
    
    fn is_white_to_move(&self) -> bool {
        // Return true if it's white's turn
        // Your implementation here
    }
    
    fn castling_rights(&self) -> u8 {
        // Return castling rights as bitmask:
        // Bit 0: White kingside, Bit 1: White queenside
        // Bit 2: Black kingside, Bit 3: Black queenside
        // Your implementation here
    }
    
    fn en_passant_file(&self) -> Option<u8> {
        // Return en passant file (0-7 for a-h) or None
        // Your implementation here
    }
}

// Now you can use your board with the book
let book = PolyglotBook::load("book.bin")?;
let my_board = MyBoard::new();
if let Some(entry) = book.get_best_move(&my_board) {
    println!("Best move: {}", entry.move_string);
}

Hash Computation

You can also compute Polyglot hashes directly:

use polyglot_book_rs::hash::polyglot_hash_from_fen;

let fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
let hash = polyglot_hash_from_fen(fen)?;
println!("Position hash: 0x{:016X}", hash);
// Output: Position hash: 0x463B96181691FC9C

API Reference

PolyglotBook

  • load(path: &str) - Load a book from file
  • get_best_move_from_fen(fen: &str) - Get best move from FEN
  • get_all_moves_from_fen(fen: &str) - Get all moves from FEN
  • get_best_move<B: BoardPosition>(board: &B) - Get best move from custom board
  • get_all_moves<B: BoardPosition>(board: &B) - Get all moves from custom board
  • has_position_fen(fen: &str) - Check if position exists in book
  • entry_count() - Get number of entries in book

PolyglotEntry

  • chess_move: PolyglotMove - The chess move
  • move_string: String - Move in algebraic notation (e.g., "e2e4")
  • weight: u16 - Move weight/frequency
  • position_hash: u64 - Polyglot hash of the position

PolyglotMove

  • from: u8 - Source square (0-63)
  • to: u8 - Target square (0-63)
  • promotion: Option<Piece> - Promotion piece if any
  • to_algebraic() - Convert to algebraic notation

Polyglot Format

This library implements the official Polyglot opening book format:

  • Hash Algorithm: Uses the standard 781-entry random number table
  • Piece Encoding: 0=black pawn, 1=white pawn, 2=black knight, etc.
  • Square Encoding: a1=0, b1=1, ..., h8=63
  • Castling Rights: Indices 768-771 in random table
  • En Passant: Indices 772-779 (one per file)
  • Turn: Index 780 (XOR if white to move)

The starting position hash is verified to be 0x463B96181691FC9C.

Examples

See the examples/ directory for more usage examples:

  • basic_usage.rs - Simple book querying
  • custom_board.rs - Integration with custom board representation
  • hash_computation.rs - Direct hash computation

Testing

Run the test suite:

cargo test

The tests include verification of:

  • Correct hash computation for known positions
  • FEN parsing and conversion
  • Move encoding/decoding
  • Book loading and querying

License

Licensed under either of

at your option.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

No runtime deps