Variants

python-chess supports several chess variants.

>>> import chess.variant
>>>
>>> board = chess.variant.GiveawayBoard()
>>> # General information about the variants.
>>> type(board).uci_variant
'giveaway'
>>> type(board).xboard_variant
'giveaway'
>>> type(board).starting_fen
'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w - - 0 1'

Variant

Board class

UCI/XBoard

Syzygy

Standard

chess.Board

chess/normal

.rtbw, .rtbz

Suicide

chess.variant.SuicideBoard

suicide

.stbw, .stbz

Giveaway

chess.variant.GiveawayBoard

giveaway

.gtbw, .gtbz

Antichess

chess.variant.AntichessBoard

antichess

.gtbw, .gtbz

Atomic

chess.variant.AtomicBoard

atomic

.atbw, .atbz

King of the Hill

chess.variant.KingOfTheHillBoard

kingofthehill

Racing Kings

chess.variant.RacingKingsBoard

racingkings

Horde

chess.variant.HordeBoard

horde

Three-check

chess.variant.ThreeCheckBoard

3check

Crazyhouse

chess.variant.CrazyhouseBoard

crazyhouse

chess.variant.find_variant(name: str) Type[Board][source]

Looks for a variant board class by variant name. Supports many common aliases.

Game end

See chess.Board.is_variant_end(), is_variant_win(), is_variant_draw(), or is_variant_loss() for special variant end conditions and results.

Note that if all of them return False, the game may still be over and decided by standard conditions like is_checkmate(), is_stalemate(), is_insufficient_material(), move counters, repetitions, and legitimate claims.

Chess960

Chess960 is orthogonal to all other variants.

>>> chess.Board(chess960=True)
Board('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1', chess960=True)

See chess.BaseBoard.set_chess960_pos(), chess960_pos(), and from_chess960_pos() for dealing with Chess960 starting positions.

Crazyhouse

class chess.variant.CrazyhousePocket(symbols: Iterable[str] = '')[source]

A Crazyhouse pocket with a counter for each piece type.

reset() None[source]

Clears the pocket.

add(piece_type: int) None[source]

Adds a piece of the given type to this pocket.

remove(piece_type: int) None[source]

Removes a piece of the given type from this pocket.

count(piece_type: int) int[source]

Returns the number of pieces of the given type in the pocket.

copy() CrazyhousePocketT[source]

Returns a copy of this pocket.

class chess.variant.CrazyhouseBoard(fen: str | None = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR[] w KQkq - 0 1', chess960: bool = False)[source]
pockets = [chess.variant.CrazyhousePocket(), chess.variant.CrazyhousePocket()]

Pockets for each color. For example, board.pockets[chess.WHITE] are the pocket pieces available to White.

legal_drop_squares() SquareSet[source]

Gets the squares where the side to move could legally drop a piece. Does not check whether they actually have a suitable piece in their pocket.

It is legal to drop a checkmate.

Returns a set of squares.

Three-check

class chess.variant.ThreeCheckBoard(fen: str | None = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 3+3 0 1', chess960: bool = False)[source]
remaining_checks = [3, 3]

Remaining checks until victory for each color. For example, board.remaining_checks[chess.WHITE] == 0 implies that White has won.

UCI/XBoard

Multi-Variant Stockfish and other engines have an UCI_Variant option. XBoard engines may declare support for variants. This is automatically managed.

>>> import chess.engine
>>>
>>> engine = chess.engine.SimpleEngine.popen_uci("stockfish-mv")
>>>
>>> board = chess.variant.RacingKingsBoard()
>>> result = engine.play(board, chess.engine.Limit(time=1.0))

Syzygy

Syzygy tablebases are available for suicide, giveaway and atomic chess.

>>> import chess.syzygy
>>> import chess.variant
>>>
>>> tables = chess.syzygy.open_tablebase("data/syzygy", VariantBoard=chess.variant.AtomicBoard)