rust-chess is a Python package that acts as a bridge between the chess crate and Python. It aims to provide a high-performance chess library that is largely compatible with python-chess syntax.
This repository provides:
- A Python package
rust-chesscreated using Maturin. - A type stub (
rust_chess.pyi) providing hover documentation and examples in IDEs. - A micro-benchmark comparison against
python-chessin the filecompare.py.
This project is almost out of alpha/beta phase (pun intended). Expect some breaking changes, refactoring, and new features.
Quick usage example:
import rust_chess as rc
board = rc.Board() # Create a board
move = rc.Move.from_uci("e2e4") # Create move from UCI
# Check if the move is legal for the current board
if board.is_legal_move(move):
# Make a move on the current board
# Disable the legality check since we already know the move is legal
board.make_move(move, check_legality=False)
# Make move onto a new board
new_board = board.make_move_new(rc.Move("e7e5"))
# Get the FEN of the current board
print(board.get_fen())
# Generate the next move
move = board.generate_next_move()
# Create a list of all legal moves (exhausts the generator)
moves = list(board.generate_legal_moves())
# The generator saves state
assert move not in moves
# Reset the generator to be able to generate moves again
board.reset_move_generator()
# Generate legal captures
captures = list(board.generate_legal_captures())Use IDE completion or read the generated stub (rust_chess.pyi) for detailed function signatures and documentation. Actual documentation coming soon (TM).
Color:WHITE,BLACK,COLORSPieceType:PAWN,KNIGHT,BISHOP,ROOK,QUEEN,KING,PIECE_TYPESPiece:WHITE_PAWN...BLACK_KING,COLORED_PIECESSquare:A1..H8,SQUARESBitboard:BB_EMPTY,BB_FULL,BB_FILE_A...BB_FILE_H,BB_RANK_1...BB_RANK_8,BB_FILES,BB_RANKSMove: TODO: Add castling and null moves?PyRepetitionDetectionModeenum:.NONE,.PARTIAL,.FULL- Currently no difference between partial and full for now, but the plan is to have partial have a smaller history list
CastleRightsenum:.NO_RIGHTS,.QUEENSIDE,.KINGSIDE,.BOTHBoardStatusenum:.ONGOING,.FIVE_FOLD_REPETITION,.SEVENTY_FIVE_MOVES,.INSUFFICIENT_MATERIAL,.STALEMATE,.CHECKMATEBoard: No constants.
- Create a
Boardfrom an optional FEN string withboard = rc.Board(). - Get the FEN of a board by calling
get_fen()on a board object. - Iterate over every square using the
rc.SQUARESconstant or get an individual square by using the corresponding constant (ex.rc.E2). - Create a
Bitboardfrom an integer or square.- Supports bitwise operators, shift operators, popcnt, iteration, and conversion to and from a
Square.
- Supports bitwise operators, shift operators, popcnt, iteration, and conversion to and from a
- Get many different bitboards for the current board including
board.get_color_bitboard(rc.WHITE),board.get_piece_type_bitboard(rc.PAWN),board.get_checkers_bitboard(), and more. - Create a move from a source and destination square, with an optional promotion piece type using
move = rc.Move(rc.E2, rc.E4).- Can also create a move from a UCI string using
move = rc.Move("e2e4")ormove = rc.Move.from_uci("e2e4").
- Can also create a move from a UCI string using
- Check if a move is legal with
board.is_legal_move(move). - Generate all legal moves or captures for a board by iterating over
board.generate_legal_moves()andboard.generate_legal_captures().- The generator remembers state; make sure to reset it with
board.reset_move_generator()if you want to iterate over the moves again.
- The generator remembers state; make sure to reset it with
- Generate the next move for the generator with
board.generate_next_move(). - Generate moves for a specific bitboard mask by setting it with
board.set_move_generator_mask(mask_bitboard)and then callingboard.generate_moves(). - Apply a move to a board with
board.make_move(move, check_legality=[True]|False).check_legalitydefaults toTrue(can disable if you already know the move is legal for an extra performance boost).
- Apply a move to a new board with
new_board = board.make_move_new(move). - Check what piece, piece type, or color is on a square with the corresponding
get_piece_on,get_piece_type_on, andget_color_onfunctions. - Get the
BoardStatusenum of a board withboard.get_status().- Can also call individual status check functions like
board.is_checkmate(),board.is_insufficient_material(),board.is_fifty_moves(), and more.
- Can also call individual status check functions like
Requires Python 3.10+.
A pip package is available at: (https://pypi.org/project/rust-chess)[https://pypi.org/project/rust-chess]
- Set up a virtual environment:
python -m venv .venv
source .venv/bin/activate
# Or
uv venv
source .venv/bin/activate- Use the pip package:
pip install rust-chess
# Or
uv pip install rust-chess- Set up a virtual environment:
python -m venv .venv
source .venv/bin/activate
# Or
uv venv
source .venv/bin/activate- Clone the repository:
git clone https://github.com/nemeott/rust-chess.git
cd rust-chess- Build and install the Python package:
./build.sh
pip install target/wheels/rust_chess-0.3.2-cp313-cp313-linux_x86_64.whl
# Or
uv pip install target/wheels/rust_chess-0.3.2-cp313-cp313-linux_x86_64.whl
# Or build and install in current virtual environment
./develop.sh-
Color- Color constants
- Comparison between colors and booleans
-
PieceType- Piece type constants
- Get internal index representation
- Printing
- Basic characters
- Unicode characters
-
Piece- Piece constants
- Get internal piece type index representation
- Printing
- Basic characters
- Unicode characters
-
Square- Square constants
- Square creation and parsing
- Get the rank and file from a square
- Create a square from rank, file, or vice versa
- Get the color of a square
- Get the index of square
- Use a square as an index
- Rich comparison operators
- Flip a square vertically
- Bitboard conversion
- Get adjacent squares
- Get square forward/backward depending on color
- Printing
-
Bitboard- File and rank constants
- Creation from a square or integer
- Bitboard operations
- Between bitboards
- Between a bitboard and integer
- Count the number of bits
- Flip vertically
- Iterate over the squares in a bitboard
- Printing
- Flip printing direction by default?
-
Move- Move creation from data types or UCI
- Castling move constants
- Null move constant?
-
MoveGenerator- Generate the next move*, legal move, and legal capture
- Generate moves, legal moves, and legal captures
- Support iterating over the generator
- Specify the generator mask (bitboard of squares the generator will generate for)
- Remove a generator mask (bitboard of squares the generator will avoid)
- Remove a move from the generator
- Reset the generator
-
CastleRights- Get castle rights (No rights, queenside, kingside, both)
- Set castle rights? (use cases?)
- Rich comparison operators
-
BoardStatus- Game-ending conditions
- Checkmate
- Stalemate
- Insufficient material
- Fivefold repetition
- Potential draw conditions
- Threefold repetition
- Fifty moves
- Rich comparison operators
- Game-ending conditions
-
Board- FEN parsing and printing
- SAN move parsing
- Human readable printing
- Basic characters
- ASCII with colors?
- Unicode characters
- Get color, piece type, and piece on a square
- Get king square for a color
- Get the en passant square
- Check if move is zeroing
- Check if move is legal
- Quick legality detection for psuedo-legal moves
- Check if move is a capture
- Check if move is en passant
- Make moves on the current or new board
- Make null moves (make_null_move)
- Make null moves on new board
- Get bitboards
- Pinned pieces
- Checking pieces
- Color pieces
- Piece type
- Piece
- All pieces
- Zobrist hashing
- Comparison operators (using Zobrist hash)
- Move history
- Repetition detection
- Cache default board for faster creation?
- Piece-Square Table support?
- Miscellaneous
- PGN support (parsing and writing)
- UCI protocol basics
- Opening book support
- Improved Python ergonomics (e.g., more Pythonic wrappers where appropriate)
- Comprehensive test suite
- Docstring tests
- Other tests
- Working GitHub action (😢)
python-chess generates moves in reverse order (H8, H7, ...)* rust-chess generates moves in normal order (A1, A2, ...).
compare.py was used for a quick benchmark and comparison between the same operations for rust-chess and python-chess. The comparison script was run with large iteration counts (n = 100,000) and profiled using PySpy. The key observations from that analysis are as follows:
- Small/simple operations (e.g., some tiny getters, Python-exposed primitives) can be slightly slower because of Rust<->Python boundary costs.
- Complex and heavy operations are substantially faster in
rust-chess:- Creating moves from UCI.
- Board initialization.
- FEN parsing and printing.
- Generating legal moves and legal captures.
- Checking move legality and check.
More detailed analysis is documented inside the file, including time deltas per function.
- Bridge overhead: Small functions and data types are slower due to the bridge overhead, however heavy computations are much faster.
- No board history yet: Undo/pop are not available currently. Make moves onto a new board and pass it into a function instead for now.
- Reliability: The library has not been widely tested yet. It has somewhat detailed docstring tests but not every edge case is guaranteed to be covered.
MIT License.