python · c extension · by peargentlabs

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.

$ pip install fastchess
board.push_uci("e2e4")

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.

C-backed core
Move generation and board logic run as native C - no Python overhead in the hot path.
ML-ready tensors
Export any position as an (18, 8, 8) NumPy float32 tensor in one call.
Full UCI & SAN
Push moves in either notation. Castling, en passant, and promotions all handled.

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.

Featurefastchesspython-chess
Core languageC extensionPure Python
Move generationNative C - zero Python overheadPython loops
ML tensor exportBuilt-in to_tensor()Manual encoding required
UCI/SAN parsingC-level parsingPython string operations
Target use caseData pipelines, ML trainingGeneral purpose
LicenseMITGPL-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:

PlanesContent
0–5White's pieces (P, N, B, R, Q, K) - pre-mirrored to side-to-move when canonical=True
6–11Black's pieces (P, N, B, R, Q, K) - pre-mirrored to opponent when canonical=True
12–15Castling rights (WK, WQ, BK, BQ)
16En passant target square
17Side 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

SignatureDescription
Board()Create board at the starting position
Board(fen)Create board from a FEN string

Methods

MethodReturnsDescription
fen()strCurrent 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)strApply a move given in SAN; returns the UCI string
is_check()boolTrue if the side to move is in check
has_legal_en_passant()boolTrue if a legal en passant capture is available
has_kingside_castling_rights(color)boolPass fastchess.WHITE (0) for White, fastchess.BLACK (1) for Black
has_queenside_castling_rights(color)boolPass fastchess.WHITE (0) for White, fastchess.BLACK (1) for Black
piece_at(sq)(int, int) | NonePiece type and color at square index 0–63, or None
to_tensor(canonical=True)ndarrayBoard as (18, 8, 8) float32 NumPy array
copy()BoardIndependent copy of the board
mirror()BoardVertically mirrored board with colors swapped

Properties

PropertyTypeDescription
turnint0 = White, 1 = Black
castlingintCastling rights bitmask (15 = all four rights)
ep_squareintEn passant target square index, or -1
halfmoveintHalf-move clock (50-move rule counter)
fullmoveintFull-move number

Constants

Piece types and colors exposed at the module level:

fastchess.WHITE fastchess.BLACK fastchess.PAWN fastchess.KNIGHT fastchess.BISHOP fastchess.ROOK fastchess.QUEEN fastchess.KING

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.