Chess that moves at C speed
fastchess is a high-performance Python chess library written in C. Fast legal move generation, SAN/UCI parsing, and NumPy tensor export - built for data pipelines and ML workflows. A fast alternative to python-chess by PeargentLabs.
Why fastchess?
fastchess gives you C-speed chess logic with a clean Python API. Whether you're building a chess engine, training an ML model, or processing millions of PGN games, fastchess handles the heavy lifting without Python overhead.
(18, 8, 8) NumPy float32 tensor in one call.fastchess vs python-chess
Looking for a faster alternative to python-chess? Here's how fastchess compares for data-intensive and machine learning use cases.
| Feature | fastchess | python-chess |
|---|---|---|
| Core language | C extension | Pure Python |
| Move generation | Native C - zero Python overhead | Python loops |
| ML tensor export | Built-in to_tensor() | Manual encoding required |
| UCI/SAN parsing | C-level parsing | Python string operations |
| Target use case | Data pipelines, ML training | General purpose |
| License | MIT | GPL-3.0 |
If you're processing millions of chess positions for machine learning, fastchess is designed to be a drop-in replacement that gives you the speed of C with the convenience of Python.
Quick Start
Requires Python 3.9+ and NumPy. Install the fastchess Python package with pip:
# install fastchess
pip install fastchess
Create a board & make moves
import fastchess
# Start from the initial position
board = fastchess.Board()
# Or load from a FEN string
board = fastchess.Board("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1")
# Push moves by UCI or SAN
board.push_uci("e2e4")
board.push_san("e5")
board.push_uci("g1f3")
# Get the current FEN
print(board.fen())
# rnbqkbnr/pppp1ppp/8/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2
List legal moves
moves = board.legal_moves_uci()
print(moves)
# ['a7a6', 'a7a5', 'b7b6', 'b7b5', ...]
# From the starting position there are always 20
start = fastchess.Board()
print(len(start.legal_moves_uci())) # 20
Board State
Query the current position without touching move generation.
board = fastchess.Board()
board.push_uci("e2e4")
board.push_uci("e7e5")
# Whose turn is it? fastchess.WHITE = 0, fastchess.BLACK = 1
print(board.turn) # 0 (fastchess.WHITE)
# Is the side to move in check?
print(board.is_check()) # False
# Move counters
print(board.halfmove) # half-move clock (for 50-move rule)
print(board.fullmove) # full-move number
# En passant
print(board.ep_square) # square index, or -1 if none
print(board.has_legal_en_passant()) # True/False
# Castling rights - pass fastchess.WHITE (0) or fastchess.BLACK (1)
print(board.castling) # bitmask (15 = all four)
print(board.has_kingside_castling_rights(fastchess.WHITE)) # True
print(board.has_queenside_castling_rights(fastchess.WHITE)) # True
print(board.has_kingside_castling_rights(fastchess.BLACK)) # True
# What piece is on a square? (0-indexed, a1=0 … h8=63)
piece = board.piece_at(4) # e1
print(piece) # (6, 0) → (KING, WHITE)
# Returns None if the square is empty
Copy & mirror
# Independent copy - mutations don't affect the original
clone = board.copy()
clone.push_uci("d2d4")
# Flip the board vertically and swap colors (useful for canonical ML input)
flipped = board.mirror()
print(flipped.turn) # opposite of board.turn
ML / Tensors
to_tensor() exports the board as a (18, 8, 8) NumPy float32 array,
ready to feed directly into PyTorch or TensorFlow. Perfect for chess machine learning
and neural network training pipelines.
import fastchess
import numpy as np
board = fastchess.Board()
board.push_uci("e2e4")
# canonical=True mirrors the board so the side-to-move is always "down"
tensor = board.to_tensor(canonical=True)
print(tensor.shape) # (18, 8, 8)
print(tensor.dtype) # float32
# Plug straight into PyTorch
import torch
x = torch.from_numpy(tensor).unsqueeze(0) # (1, 18, 8, 8) batch
Tensor plane layout
The 18 planes encode piece positions and board metadata:
| Planes | Content |
|---|---|
0–5 | White's pieces (P, N, B, R, Q, K) - pre-mirrored to side-to-move when canonical=True |
6–11 | Black's pieces (P, N, B, R, Q, K) - pre-mirrored to opponent when canonical=True |
12–15 | Castling rights (WK, WQ, BK, BQ) |
16 | En passant target square |
17 | Side to move (all 1s = White, all 0s = Black) |
API Reference
Everything lives on fastchess.Board. The fastchess Python API is designed to be familiar if you've used python-chess.
Constructor
| Signature | Description |
|---|---|
Board() | Create board at the starting position |
Board(fen) | Create board from a FEN string |
Methods
| Method | Returns | Description |
|---|---|---|
fen() | str | Current position as a FEN string |
legal_moves_uci() | list[str] | All legal moves in UCI format |
push_uci(uci) | - | Apply a move given as a UCI string (e.g. "e2e4") |
push_san(san) | str | Apply a move given in SAN; returns the UCI string |
is_check() | bool | True if the side to move is in check |
has_legal_en_passant() | bool | True if a legal en passant capture is available |
has_kingside_castling_rights(color) | bool | Pass fastchess.WHITE (0) for White, fastchess.BLACK (1) for Black |
has_queenside_castling_rights(color) | bool | Pass fastchess.WHITE (0) for White, fastchess.BLACK (1) for Black |
piece_at(sq) | (int, int) | None | Piece type and color at square index 0–63, or None |
to_tensor(canonical=True) | ndarray | Board as (18, 8, 8) float32 NumPy array |
copy() | Board | Independent copy of the board |
mirror() | Board | Vertically mirrored board with colors swapped |
Properties
| Property | Type | Description |
|---|---|---|
turn | int | 0 = White, 1 = Black |
castling | int | Castling rights bitmask (15 = all four rights) |
ep_square | int | En passant target square index, or -1 |
halfmove | int | Half-move clock (50-move rule counter) |
fullmove | int | Full-move number |
Constants
Piece types and colors exposed at the module level:
PeargentLabs Ecosystem
fastchess is part of the PeargentLabs chess tooling ecosystem - a collection of high-performance, open-source tools for chess programming, engine development, and machine learning research.