Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
950 views72 pages

Python Chess

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
950 views72 pages

Python Chess

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 72

python-chess

Release 0.18.0

Apr 20, 2017


Contents

1 Introduction 1

2 Documentation 3

3 Features 5

4 Installing 11

5 Selected use cases 13

6 License 15

7 Contents 17
7.1 Core . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
7.2 PGN parsing and writing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
7.3 Polyglot opening book reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
7.4 Gaviota endgame tablebase probing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
7.5 Syzygy endgame tablebase probing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
7.6 UCI engine communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
7.7 SVG rendering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
7.8 Variants (experimental) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
7.9 Changelog for python-chess . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

8 Indices and tables 63

i
ii
CHAPTER 1

Introduction

python-chess is a pure Python chess library with move generation and validation and handling of common formats.
This is the scholars mate in python-chess:

>>> import chess

>>> board = chess.Board()

>>> board.legal_moves
<LegalMoveGenerator at ... (Nh3, Nf3, Nc3, Na3, h3, g3, f3, e3, d3, c3, ...)>
>>> chess.Move.from_uci("a8a1") in board.legal_moves
False

>>> board.push_san("e4")
Move.from_uci('e2e4')
>>> board.push_san("e5")
Move.from_uci('e7e5')
>>> board.push_san("Qh5")
Move.from_uci('d1h5')
>>> board.push_san("Nc6")
Move.from_uci('b8c6')
>>> board.push_san("Bc4")
Move.from_uci('f1c4')
>>> board.push_san("Nf6")
Move.from_uci('g8f6')
>>> board.push_san("Qxf7")
Move.from_uci('h5f7')

>>> board.is_checkmate()
True

>>> board
Board('r1bqkb1r/pppp1Qpp/2n2n2/4p3/2B1P3/8/PPPP1PPP/RNB1K1NR b KQkq - 0 4')

1
python-chess, Release 0.18.0

2 Chapter 1. Introduction
CHAPTER 2

Documentation

https://python-chess.readthedocs.io/en/latest/
• Core
• PGN parsing and writing
• Polyglot opening book reading
• Gaviota endgame tablebase probing
• Syzygy endgame tablebase probing
• UCI engine communication
• Variants
• Changelog

3
python-chess, Release 0.18.0

4 Chapter 2. Documentation
CHAPTER 3

Features

• Supports Python 2.6+, Python 3.3+ and PyPy.


• IPython notebook integration. SVG rendering docs.

>>> board

• Chess variants: Standard, Chess960, Suicide, Giveaway, Atomic, King of the Hill, Racing Kings, Horde, Three-
check, Crazyhouse. Variant docs.
• Make and unmake moves.

>>> Nf3 = chess.Move.from_uci("g1f3")


>>> board.push(Nf3) # Make the move

>>> board.pop() # Unmake the last move


Move.from_uci('g1f3')

• Show a simple ASCII board.

>>> board = chess.Board("r1bqkb1r/pppp1Qpp/2n2n2/4p3/2B1P3/8/PPPP1PPP/RNB1K1NR b


˓→KQkq - 0 4")

>>> print(board)
r . b q k b . r
p p p p . Q p p
. . n . . n . .
. . . . p . . .
. . B . P . . .
. . . . . . . .
P P P P . P P P
R N B . K . N R

• Detects checkmates, stalemates and draws by insufficient material.

>>> board.is_stalemate()
False

5
python-chess, Release 0.18.0

>>> board.is_insufficient_material()
False
>>> board.is_game_over()
True

• Detects repetitions. Has a half move clock.


>>> board.can_claim_threefold_repetition()
False
>>> board.halfmove_clock
0
>>> board.can_claim_fifty_moves()
False
>>> board.can_claim_draw()
False

With the new rules from July 2014 a game ends drawn (even without a claim) once a fivefold repetition occurs
or if there are 75 moves without a pawn push or capture. Other ways of ending a game take precedence.
>>> board.is_fivefold_repetition()
False
>>> board.is_seventyfive_moves()
False

• Detects checks and attacks.


>>> board.is_check()
True
>>> board.is_attacked_by(chess.WHITE, chess.E8)
True

>>> attackers = board.attackers(chess.WHITE, chess.F3)


>>> attackers
SquareSet(0b0000000000000000000000000000000000000000000000000100000001000000)
>>> chess.G2 in attackers
True
>>> print(attackers)
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . 1 .
. . . . . . 1 .

• Parses and creates SAN representation of moves.


>>> board = chess.Board()
>>> board.san(chess.Move(chess.E2, chess.E4))
'e4'
>>> board.parse_san('Nf3')
Move.from_uci('g1f3')
>>> board.variation_san([chess.Move.from_uci(m) for m in ["e2e4", "e7e5", "g1f3
˓→"]])

'1. e4 e5 2. Nf3'

• Parses and creates FENs, extended FENs and Shredder FENs.

6 Chapter 3. Features
python-chess, Release 0.18.0

>>> board.fen()
'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
>>> board.shredder_fen()
'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w HAha - 0 1'
>>> board = chess.Board("8/8/8/2k5/4K3/8/8/8 w - - 4 45")
>>> board.piece_at(chess.C5)
Piece.from_symbol('k')

• Parses and creates EPDs.

>>> board = chess.Board()


>>> board.epd(bm=board.parse_uci("d2d4"))
'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - bm d4;'

>>> ops = board.set_epd("1k1r4/pp1b1R2/3q2pp/4p3/2B5/4Q3/PPP2B2/2K5 b - - bm Qd1+;


˓→ id \"BK.01\";")

>>> ops == {'bm': [chess.Move.from_uci('d6d1')], 'id': 'BK.01'}


True

• Detects absolute pins and their directions.


• Read Polyglot opening books. Docs.

>>> import chess.polyglot

>>> book = chess.polyglot.open_reader("data/polyglot/performance.bin")

>>> board = chess.Board()


>>> main_entry = book.find(board)
>>> main_entry.move()
Move.from_uci('e2e4')
>>> main_entry.weight
1
>>> main_entry.learn
0

>>> book.close()

• Read and write PGNs. Supports headers, comments, NAGs and a tree of variations. Docs.

>>> import chess.pgn

>>> pgn = open("data/pgn/molinari-bordais-1979.pgn")


>>> first_game = chess.pgn.read_game(pgn)
>>> pgn.close()

>>> first_game.headers["White"]
'Molinari'
>>> first_game.headers["Black"]
'Bordais'

>>> # Get the mainline as a list of moves.


>>> moves = first_game.main_line()
>>> first_game.board().variation_san(moves)
'1. e4 c5 2. c4 Nc6 3. Ne2 Nf6 4. Nbc3 Nb4 5. g3 Nd3#'

>>> # Iterate through the mainline of this embarrasingly short game.


>>> node = first_game

7
python-chess, Release 0.18.0

>>> while not node.is_end():


... next_node = node.variation(0)
... print(node.board().san(next_node.move))
... node = next_node
e4
c5
c4
Nc6
Ne2
Nf6
Nbc3
Nb4
g3
Nd3#

>>> first_game.headers["Result"]
'0-1'

• Probe Gaviota endgame tablebases (DTM, WDL). Docs.


• Probe Syzygy endgame tablebases (DTZ, WDL). Docs.

>>> import chess.syzygy

>>> tablebases = chess.syzygy.open_tablebases("data/syzygy/regular")

>>> # Black to move is losing in 53 half moves (distance to zero) in this


>>> # KNBvK endgame.
>>> board = chess.Board("8/2K5/4B3/3N4/8/8/4k3/8 b - - 0 1")
>>> tablebases.probe_dtz(board)
-53

>>> tablebases.close()

• Communicate with an UCI engine. Docs.

>>> import chess.uci

>>> engine = chess.uci.popen_engine("stockfish")


>>> engine.uci()
>>> engine.author
'Tord Romstad, Marco Costalba and Joona Kiiski'

>>> # Synchronous mode.


>>> board = chess.Board("1k1r4/pp1b1R2/3q2pp/4p3/2B5/4Q3/PPP2B2/2K5 b - - 0 1")
>>> engine.position(board)
>>> engine.go(movetime=2000) # Gets tuple of bestmove and ponder move.
BestMove(bestmove=Move.from_uci('d6d1'), ponder=Move.from_uci('c1d1'))

>>> # Asynchronous mode.


>>> def callback(command):
... bestmove, ponder = command.result()
... assert bestmove == chess.Move.from_uci('d6d1')
...
>>> command = engine.go(movetime=2000, async_callback=callback)
>>> command.done()
False
>>> command.result()

8 Chapter 3. Features
python-chess, Release 0.18.0

BestMove(bestmove=Move.from_uci('d6d1'), ponder=Move.from_uci('c1d1'))
>>> command.done()
True

>>> # Quit.
>>> engine.quit()
0

9
python-chess, Release 0.18.0

10 Chapter 3. Features
CHAPTER 4

Installing

Download and install the latest release:

pip install python-chess[uci,gaviota]

11
python-chess, Release 0.18.0

12 Chapter 4. Installing
CHAPTER 5

Selected use cases

If you like, let me know if you are creating something intresting with python-chess, for example:
• a stand alone chess computer based on DGT board - http://www.picochess.org/
• a website to probe Syzygy endgame tablebases - https://syzygy-tables.info/
• a GUI to play against UCI chess engines - http://johncheetham.com/projects/jcchess/
• an HTTP microservice to render board images - https://github.com/niklasf/web-boardimage
• a bot to play chess on Telegram - https://github.com/cxjdavin/tgchessbot
• connecting Stockfish to the Novag Citrine - http://empiricalrabbit.blogspot.de/2016/05/
integrating-with-python-chess-module.html
• a tool to build Anki decks from a PGN opening repertoire - https://github.com/asdfjkl/pgn2anki

13
python-chess, Release 0.18.0

14 Chapter 5. Selected use cases


CHAPTER 6

License

python-chess is licensed under the GPL3. See the LICENSE file for the full copyright and license information.
Thanks to the Stockfish authors. Thanks to Sam Tannous for publishing his approach to avoid rotated bitboards with
direct lookup (pdf) alongside his GPL2+ engine Shatranj. Some move generation ideas are taken from these sources.
Thanks to Ronald de Man for his Syzygy endgame tablebases (https://github.com/syzygy1/tb). The probing code in
python-chess is very directly ported from his C probing code.
Thanks to Miguel A. Ballicora for his Gaviota tablebases (https://github.com/michiguel/Gaviota-Tablebases).

15
python-chess, Release 0.18.0

16 Chapter 6. License
CHAPTER 7

Contents

Core

Colors

Constants for the side to move or the color of a piece.


chess.WHITE = True
chess.BLACK = False
You can get the opposite color using not color.

Piece types

chess.PAWN = 1
chess.KNIGHT = 2
chess.BISHOP = 3
chess.ROOK = 4
chess.QUEEN = 5
chess.KING = 6

Squares

chess.A1 = 0
chess.B1 = 1
and so on to
chess.G8 = 62

17
python-chess, Release 0.18.0

chess.H8 = 63
chess.SQUARES = [chess.A1, chess.B1, ..., chess.G8, chess.H8]
chess.SQUARE_NAMES = [’a1’, ‘b1’, ..., ‘g8’, ‘h8’]
chess.FILE_NAMES = [’a’, ‘b’, ..., ‘g’, ‘h’]
chess.RANK_NAMES = [‘1’, ‘2’, ..., ‘7’, ‘8’]
chess.square(file_index, rank_index)
Gets a square number by file and rank index.
chess.square_file(square)
Gets the file index of the square where 0 is the a file.
chess.square_rank(square)
Gets the rank index of the square where 0 is the first rank.
chess.square_distance(a, b)
Gets the distance (i.e. the number of king steps) from square a to b.
chess.square_mirror(square)
Mirrors the square vertically.

Pieces

class chess.Piece(piece_type, color)


A piece with type and color.
piece_type
The piece type.
color
The piece color.
symbol()
Gets the symbol P, N, B, R, Q or K for white pieces or the lower-case variants for the black pieces.
unicode_symbol(invert_color=False)
Gets the unicode character for the piece.
classmethod from_symbol(symbol)
Creates a piece instance from a piece symbol.
Raises ValueError if the symbol is invalid.

Moves

class chess.Move(from_square, to_square, promotion=None, drop=None)


Represents a move from a square to a square and possibly the promotion piece type.
Drops and null moves are supported.
from_square
The source square.
to_square
The target square.
promotion
The promotion piece type.

18 Chapter 7. Contents
python-chess, Release 0.18.0

uci()
Gets an UCI string for the move.
For example a move from A7 to A8 would be a7a8 or a7a8q if it is a promotion to a queen.
The UCI representatin of null moves is 0000.
classmethod from_uci(uci)
Parses an UCI string.
Raises ValueError if the UCI string is invalid.
classmethod null()
Gets a null move.
A null move just passes the turn to the other side (and possibly forfeits en passant capturing). Null moves
evaluate to False in boolean contexts.

>>> bool(chess.Move.null())
False

Board

chess.STARTING_FEN = ‘rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1’


The FEN of the standard chess starting position.
chess.STARTING_BOARD_FEN = ‘rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR’
The board part of the FEN of the standard chess starting position.
class chess.Board(fen=’rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1’,
chess960=False)
A BaseBoard and additional information representing a chess position.
Provides move generation, validation, parsing, attack generation, game end detection, move counters and the
capability to make and unmake moves.
The board is initialized to the standard chess starting position, unless otherwise specified in the optional fen
argument. If fen is None an empty board is created.
Optionally supports chess960. In Chess960 castling moves are encoded by a king move to the corresponding
rook square. Use chess.Board.from_chess960_pos() to create a board with one of the Chess960
starting positions.
turn
The side to move.
castling_rights
Bitmask of the rooks with castling rights.

>>> white_castle_kingside = board.castling_rights & chess.BB_H1

Also see has_castling_rights(), has_kingside_castling_rights(),


has_queenside_castling_rights(), has_chess960_castling_rights(),
clean_castling_rights() and set_castling_fen().
ep_square
The potential en passant square on the third or sixth rank or None.
Use has_legal_en_passant() to test if en passant capturing would actually be possible on the next
move.

7.1. Core 19
python-chess, Release 0.18.0

fullmove_number
Counts move pairs. Starts at 1 and is incremented after every move of the black side.
halfmove_clock
The number of half moves since the last capture or pawn move.
chess960
Whether the board is in Chess960 mode. In Chess960 castling moves are represented as king moves to the
corresponding rook square.
legal_moves = LegalMoveGenerator(self)
A dynamic list of legal moves.
The following operations do not just generate everything but map to more efficient methods.

>>> len(board.legal_moves)
20

>>> bool(board.legal_moves)
True

>>> move in board.legal_moves


True

Wraps generate_legal_moves() and is_legal().


pseudo_legal_moves = PseudoLegalMoveGenerator(self)
A dynamic list of pseudo legal moves, much like the legal move list.
Pseudo legal moves might leave or put the king in check, but are otherwise valid. Null moves are not
pseudo legal. Castling moves are only included if they are completely legal.
Wraps generate_pseudo_legal_moves() and is_pseudo_legal().
move_stack
The move stack. Use Board.push(), Board.pop(), Board.peek() and Board.
clear_stack() for manipulation.
reset()
Restores the starting position.
clear()
Clears the board.
Resets move stacks and move counters. The side to move is white. There are no rooks or kings, so castling
rights are removed.
In order to be in a valid status() at least kings need to be put on the board.
clear_stack()
Clears the move stack.
is_attacked_by(color, square)
Checks if the given side attacks the given square.
Pinned pieces still count as attackers. Pawns that can be captured en passant are not considered attacked.
attackers(color, square)
Gets a set of attackers of the given color for the given square.
Pinned pieces still count as attackers.
Returns a set of squares.

20 Chapter 7. Contents
python-chess, Release 0.18.0

attacks(square)
Gets a set of attacked squares from a given square.
There will be no attacks if the square is empty. Pinned pieces are still attacking other squares.
Returns a set of squares.
pin(color, square)
Detects an absolute pin (and its direction) of the given square to the king of the given color.

>>> board = chess.Board("rnb1k2r/ppp2ppp/5n2/3q4/1b1P4/2N5/PP3PPP/R1BQKBNR w


˓→KQkq - 3 7")

>>> board.is_pinned(chess.WHITE, chess.C3)


True
>>> direction = board.pin(chess.WHITE, chess.C3)
>>> direction
SquareSet(0b0000000000000000000000000000000100000010000001000000100000010000)
>>> print(direction)
. . . . . . . .
. . . . . . . .
. . . . . . . .
1 . . . . . . .
. 1 . . . . . .
. . 1 . . . . .
. . . 1 . . . .
. . . . 1 . . .

Returns a set of squares that mask the rank, file or diagonal of the pin. If there is no pin, then a
mask of the entire board is returned.
is_pinned(color, square)
Detects if the given square is pinned to the king of the given color.
is_check()
Returns if the current side to move is in check.
is_into_check(move)
Checks if the given move would leave the king in check or put it into check. The move must be at least
pseudo legal.
was_into_check()
Checks if the king of the other side is attacked. Such a position is not valid and could only be reached by
an illegal move.
is_variant_end()
Checks if the game is over due to a special variant end condition.
Note for example that stalemate is not considered a variant-specific end condition (this method will
return False), yet it can have a special result in suicide chess (any of is_variant_loss(),
is_variant_win(), is_variant_draw() might return True).
is_variant_loss()
Checks if a special variant-specific loss condition is fulfilled.
is_variant_win()
Checks if a special variant-specific win condition is fulfilled.
is_variant_draw()
Checks if a special variant-specific drawing condition is fulfilled.

7.1. Core 21
python-chess, Release 0.18.0

is_game_over(claim_draw=False)
Checks if the game is over due to checkmate, stalemate, insufficient material, the
seventyfive-move rule, fivefold repetition or a variant end condition.
The game is not considered to be over by threefold repetition or the fifty-move rule,
unless claim_draw is given.
result(claim_draw=False)
Gets the game result.
1-0, 0-1 or 1/2-1/2 if the game is over. Otherwise the result is undetermined: *.
is_checkmate()
Checks if the current position is a checkmate.
is_stalemate()
Checks if the current position is a stalemate.
is_insufficient_material()
Checks for a draw due to insufficient mating material.
is_seventyfive_moves()
Since the first of July 2014 a game is automatically drawn (without a claim by one of the players) if the
half move clock since a capture or pawn move is equal to or grather than 150. Other means to end a game
take precedence.
is_fivefold_repetition()
Since the first of July 2014 a game is automatically drawn (without a claim by one of the players) if a
position occurs for the fifth time on consecutive alternating moves.
can_claim_draw()
Checks if the side to move can claim a draw by the fifty-move rule or by threefold repetition.
can_claim_fifty_moves()
Draw by the fifty-move rule can be claimed once the clock of halfmoves since the last capture or pawn
move becomes equal or greater to 100 and the side to move still has a legal move they can make.
can_claim_threefold_repetition()
Draw by threefold repetition can be claimed if the position on the board occured for the third time or if
such a repetition is reached with one of the possible legal moves.
push(move)
Updates the position with the given move and puts it onto the move stack.

>>> Nf3 = chess.Move.from_uci("g1f3")


>>> board.push(Nf3) # Make the move

>>> board.pop() # Unmake the last move


Move.from_uci('g1f3')

Null moves just increment the move counters, switch turns and forfeit en passant capturing.
Warning Moves are not checked for legality.
pop()
Restores the previous position and returns the last move from the stack.
peek()
Gets the last move from the move stack.
has_legal_en_passant()
Checks if there is a legal en passant capture.

22 Chapter 7. Contents
python-chess, Release 0.18.0

fen(promoted=False)
Gets the FEN representation of the position.
A FEN string (e.g. rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1)
consists of the position part (board_fen()), the turn, the castling part (castling_xfen()), a rele-
vant en passant square (ep_square, has_legal_en_passant()), the halfmove clock and the full-
move number.
Optionally designates promoted pieces with a ~ before their symbol.
shredder_fen(promoted=False)
Gets the Shredder FEN representation of the position.
Castling rights are encoded by the file of the rook. The starting castling rights in normal chess are HAha.
Use castling_shredder_fen() to get just the castling part.
Optionally designates promoted pieces with a ~ before their symbol.
set_fen(fen)
Parses a FEN and sets the position from it.
Raises ValueError if the FEN string is invalid.
set_castling_fen(castling_fen)
Sets castling rights from a string in FEN notation like Qqk.
chess960_pos(ignore_turn=False, ignore_castling=False, ignore_counters=True)
Gets the Chess960 starting position index between 0 and 956 or None if the current position is not a
Chess960 starting position.
By default white to move (ignore_turn) and full castling rights (ignore_castling) are required, but move
counters (ignore_counters) are ignored.
epd(shredder_fen=False, promoted=False, **operations)
Gets an EPD representation of the current position.
EPD operations can be given as keyword arguments. Supported operands are strings, integers, floats and
moves and lists of moves and None. All other operands are converted to strings.
A list of moves for pv will be interpreted as a variation. All other move lists are interpreted as a set of
moves in the current position.
hmvc and fmvc are not included by default. You can use:

>>> board.epd(hmvc=board.halfmove_clock, fmvc=board.fullmove_number)


'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - hmvc 0; fmvc 1;'

set_epd(epd)
Parses the given EPD string and uses it to set the position.
If present the hmvc and the fmvn are used to set the half move clock and the fullmove number. Otherwise
0 and 1 are used.
Returns a dictionary of parsed operations. Values can be strings, integers, floats or move objects.
Raises ValueError if the EPD string is invalid.
san(move)
Gets the standard algebraic notation of the given move in the context of the current position.
There is no validation. It is only guaranteed to work if the move is legal or a null move.

7.1. Core 23
python-chess, Release 0.18.0

variation_san(variation)
Given a sequence of moves, return a string representing the sequence in standard algebraic notation (e.g.
“1. e4 e5 2. Nf3 Nc6” or “37...Bg6 38. fxg6”).
ValueError will be thrown if any moves in the sequence are illegal.
This board will not be modified as a result of calling this.
parse_san(san)
Uses the current position as the context to parse a move in standard algebraic notation and return the
corresponding move object.
The returned move is guaranteed to be either legal or a null move.
Raises ValueError if the SAN is invalid or ambiguous.
push_san(san)
Parses a move in standard algebraic notation, makes the move and puts it on the the move stack.
Returns the move.
Raises ValueError if neither legal nor a null move.
uci(move, chess960=None)
Gets the UCI notation of the move.
chess960 defaults to the mode of the board. Pass True to force UCI_Chess960 mode.
parse_uci(uci)
Parses the given move in UCI notation.
Supports both UCI_Chess960 and standard UCI notation.
The returned move is guaranteed to be either legal or a null move.
Raises ValueError if the move is invalid or illegal in the current position (but not a null
move).
push_uci(uci)
Parses a move in UCI notation and puts it on the move stack.
Returns the move.
Raises ValueError if the move is invalid or illegal in the current position (but not a null
move).
is_en_passant(move)
Checks if the given pseudo-legal move is an en passant capture.
is_capture(move)
Checks if the given pseudo-legal move is a capture.
is_zeroing(move)
Checks if the given pseudo-legal move is a capture or pawn move.
is_castling(move)
Checks if the given pseudo-legal move is a castling move.
is_kingside_castling(move)
Checks if the given pseudo-legal move is a kingside castling move.
is_queenside_castling(move)
Checks if the given pseudo-legal move is a queenside castling move.
clean_castling_rights()
Returns valid castling rights filtered from castling_rights.

24 Chapter 7. Contents
python-chess, Release 0.18.0

has_castling_rights(color)
Checks if the given side has castling rights.
has_kingside_castling_rights(color)
Checks if the given side has kingside (that is h-side in Chess960) castling rights.
has_queenside_castling_rights(color)
Checks if the given side has queenside (that is a-side in Chess960) castling rights.
has_chess960_castling_rights()
Checks if there are castling rights that are only possible in Chess960.
status()
Gets a bitmask of possible problems with the position.
Move making, generation and validation are only guaranteed to work on a completely valid board.
STATUS_VALID for a completely valid board.
Otherwise bitwise combinations of: STATUS_NO_WHITE_KING, STATUS_NO_BLACK_KING,
STATUS_TOO_MANY_KINGS, STATUS_TOO_MANY_WHITE_PAWNS,
STATUS_TOO_MANY_BLACK_PAWNS, STATUS_PAWNS_ON_BACKRANK,
STATUS_TOO_MANY_WHITE_PIECES, STATUS_TOO_MANY_BLACK_PIECES,
STATUS_BAD_CASTLING_RIGHTS, STATUS_INVALID_EP_SQUARE,
STATUS_OPPOSITE_CHECK, STATUS_EMPTY, STATUS_RACE_CHECK, STATUS_RACE_OVER,
STATUS_RACE_MATERIAL.
is_valid()
Checks if the board is valid.
Move making, generation and validation are only guaranteed to work on a completely valid board.
See status() for details.
zobrist_hash(array=None)
Returns a Zobrist hash of the current position.
A zobrist hash is an exclusive or of pseudo random values picked from an array. Which values are picked
is decided by features of the position, such as piece positions, castling rights and en passant squares. For
this implementation an array of 781 values is required.
The default behaviour is to use values from POLYGLOT_RANDOM_ARRAY, which makes for hashes com-
patible with polyglot opening books.
classmethod empty(chess960=False)
Creates a new empty board. Also see clear().
classmethod from_epd(epd, chess960=False)
Creates a new board from an EPD string. See set_epd().
Returns the board and the dictionary of parsed operations as a tuple.
class chess.BaseBoard(board_fen=’rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR’)
A board representing the position of chess pieces. See Board for a full board with move generation.
The board is initialized to the standard chess starting position, unless otherwise specified in the optional
board_fen argument. If board_fen is None an empty board is created.
clear_board()
Clears the board.
pieces(piece_type, color)
Gets pieces of the given type and color.

7.1. Core 25
python-chess, Release 0.18.0

Returns a set of squares.


piece_at(square)
Gets the piece at the given square.
piece_type_at(square)
Gets the piece type at the given square.
king(color)
Finds the king square of the given side. Returns None if there is no king of that color.
In variants with king promotions only non-promoted kings are considered.
remove_piece_at(square)
Removes the piece from the given square. Returns the Piece or None if the square was already empty.
set_piece_at(square, piece, promoted=False)
Sets a piece at the given square.
An existing piece is replaced. Setting piece to None is equivalent to remove_piece_at().
board_fen(promoted=False)
Gets the board FEN.
set_board_fen(fen)
Parses a FEN and sets the board from it.
Raises ValueError if the FEN string is invalid.
set_chess960_pos(sharnagl)
Sets up a Chess960 starting position given its index between 0 and 959.
>>> board.set_chess960_pos(random.randint(0, 959))

chess960_pos()
Gets the Chess960 starting position index between 0 and 959 or None.
copy()
Creates a copy of the board.
classmethod empty()
Creates a new empty board. Also see clear_board().
classmethod from_chess960_pos(sharnagl)
Creates a new board, initialized to a Chess960 starting position. Also see set_chess960_pos().

Square sets

class chess.SquareSet(mask=0)
A set of squares.
>>> squares = chess.SquareSet(chess.BB_B1 | chess.BB_G1)
>>> squares
SquareSet(0b0000000000000000000000000000000000000000000000000000000001000010)

>>> print(squares)
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .

26 Chapter 7. Contents
python-chess, Release 0.18.0

. . . . . . . .
. . . . . . . .
. 1 . . . . 1 .

>>> len(squares)
2

>>> bool(squares)
True

>>> chess.B1 in squares


True

>>> for square in squares:


... # 1 -- chess.B1
... # 6 -- chess.G1
... print(square)
...
1
6

>>> list(squares)
[1, 6]

Square sets are internally represented by 64 bit integer masks of the included squares. Bitwise operations can
be used to compute unions, intersections and shifts.
>>> int(squares)
66

Also supports common set operations like issubset(), issuperset(), union(),


intersection(), difference(), symmetric_difference() and copy() as well as update(),
intersection_update(), difference_update(), symmetric_difference_update() and
clear().
Warning Square sets can be used as dictionary keys, but do not modify them when doing this.
add(square)
Add a square to the set.
remove(square)
Remove a square from the set.
Raises KeyError if the given square was not in the set.
discard(square)
Discards a square from the set.
pop()
Removes a square from the set and returns it.
Raises KeyError on an empty set.
classmethod from_square(square)
Creates a SquareSet from a single square.
>>> chess.SquareSet.from_square(chess.A1) == chess.BB_A1:
True

7.1. Core 27
python-chess, Release 0.18.0

Common integer masks are:


chess.BB_VOID = 0
chess.BB_ALL
Single squares:
chess.BB_SQUARES = [chess.BB_A1, chess.BB_B1, ..., chess.BB_G8, chess.BB_H8]
Ranks and files:
chess.BB_RANKS = [chess.BB_RANK_1, ..., chess.BB_RANK_8]
chess.BB_FILES = [chess.BB_FILE_A, ..., chess.BB_FILE_H]
Other masks:
chess.BB_LIGHT_SQUARES
chess.BB_DARK_SQUARES
chess.BB_BACKRANKS = chess.BB_RANK_1 | chess.BB_RANK_8

PGN parsing and writing

Game model

Games are represented as a tree of moves. Each GameNode can have extra information such as comments. The root
node of a game (Game extends GameNode) also holds general information, such as game headers.
class chess.pgn.Game
The root node of a game with extra information such as headers and the starting position.
By default the following 7 headers are provided in an ordered dictionary:

>>> game = chess.pgn.Game()


>>> game.headers["Event"]
'?'
>>> game.headers["Site"]
'?'
>>> game.headers["Date"]
'????.??.??'
>>> game.headers["Round"]
'?'
>>> game.headers["White"]
'?'
>>> game.headers["Black"]
'?'
>>> game.headers["Result"]
'*'

Also has all the other properties and methods of GameNode.


headers
A collections.OrderedDict() of game headers.
errors
A list of illegal or ambiguous move errors encountered while parsing the game.

28 Chapter 7. Contents
python-chess, Release 0.18.0

board(_cache=False)
Gets the starting position of the game.
Unless the SetUp and FEN header tags are set this is the default starting position.
setup(board)
Setup a specific starting position. This sets (or resets) the SetUp, FEN and Variant header tags.
accept(visitor)
Traverses the game in PGN order using the given visitor. Returns the visitor result.
classmethod from_board(board)
Creates a game from the move stack of a Board().
class chess.pgn.GameNode

parent
The parent node or None if this is the root node of the game.
move
The move leading to this node or None if this is the root node of the game.
nags = set()
A set of NAGs as integers. NAGs always go behind a move, so the root node of the game can have none.
comment = ‘’
A comment that goes behind the move leading to this node. Comments that occur before any move are
assigned to the root node.
starting_comment = ‘’
A comment for the start of a variation. Only nodes that actually start a variation (starts_variation()) can
have a starting comment. The root node can not have a starting comment.
variations
A list of child nodes.
board(_cache=True)
Gets a board with the position of the node.
It’s a copy, so modifying the board will not alter the game.
san()
Gets the standard algebraic notation of the move leading to this node.
Do not call this on the root node.
root()
Gets the root node, i.e. the game.
end()
Follows the main variation to the end and returns the last node.
is_end()
Checks if this node is the last node in the current variation.
starts_variation()
Checks if this node starts a variation (and can thus have a starting comment). The root node does not start
a variation and can have no starting comment.
is_main_line()
Checks if the node is in the main line of the game.

7.2. PGN parsing and writing 29


python-chess, Release 0.18.0

is_main_variation()
Checks if this node is the first variation from the point of view of its parent. The root node also is in the
main variation.
variation(move)
Gets a child node by move or index.
has_variation(move)
Checks if the given move appears as a variation.
promote_to_main(move)
Promotes the given move to the main variation.
promote(move)
Moves the given variation one up in the list of variations.
demote(move)
Moves the given variation one down in the list of variations.
remove_variation(move)
Removes a variation by move.
add_variation(move, comment=’‘, starting_comment=’‘, nags=())
Creates a child node with the given attributes.
add_main_variation(move, comment=’‘)
Creates a child node with the given attributes and promotes it to the main variation.
main_line()
Yields the moves of the main line starting in this node.
add_line(moves, comment=’‘, starting_comment=’‘, nags=())
Creates a sequence of child nodes for the given list of moves. Adds comment and nags to the last node of
the line and returns it.
accept(visitor, _board=None)
Traverse game nodes in PGN order using the given visitor. Returns the visitor result.

Parsing

chess.pgn.read_game(handle, Visitor=<class ‘chess.pgn.GameModelCreator’>)


Reads a game from a file opened in text mode.

>>> pgn = open("data/pgn/kasparov-deep-blue-1997.pgn")


>>> first_game = chess.pgn.read_game(pgn)
>>> second_game = chess.pgn.read_game(pgn)
>>>
>>> first_game.headers["Event"]
'IBM Man-Machine, New York USA'

By using text mode the parser does not need to handle encodings. It is the callers responsibility to open the file
with the correct encoding. PGN files are ASCII or UTF-8 most of the time. So the following should cover most
relevant cases (ASCII, UTF-8 without BOM, UTF-8 with BOM, UTF-8 with encoding errors).

>>> pgn = open("data/pgn/kasparov-deep-blue-1997.pgn", encoding="utf-8-sig",


˓→errors="surrogateescape")

Use StringIO to parse games from a string.

30 Chapter 7. Contents
python-chess, Release 0.18.0

>>> pgn_string = "1. e4 e5 2. Nf3 *"


>>>
>>> try:
>>> from StringIO import StringIO # Python 2
>>> except ImportError:
>>> from io import StringIO # Python 3
>>>
>>> pgn = StringIO(pgn_string)
>>> game = chess.pgn.read_game(pgn)

The end of a game is determined by a completely blank line or the end of the file. (Of course blank lines in
comments are possible.)
According to the standard at least the usual 7 header tags are required for a valid game. This parser also handles
games without any headers just fine.
The parser is relatively forgiving when it comes to errors. It skips over tokens it can not parse. Any exceptions
are logged.
Returns the parsed game or None if the EOF is reached.
chess.pgn.scan_headers(handle)
Scan a PGN file opened in text mode for game offsets and headers.
Yields a tuple for each game. The first element is the offset. The second element is an ordered dictionary of
game headers.
Since actually parsing many games from a big file is relatively expensive, this is a better way to look only for
specific games and seek and parse them later.
This example scans for the first game with Kasparov as the white player.

>>> pgn = open("mega.pgn")


>>> for offset, headers in chess.pgn.scan_headers(pgn):
... if "Kasparov" in headers["White"]:
... kasparov_offset = offset
... break

Then it can later be seeked an parsed.

>>> pgn.seek(kasparov_offset)
>>> game = chess.pgn.read_game(pgn)

This also works nicely with generators, scanning lazily only when the next offset is required.

>>> white_win_offsets = (offset for offset, headers in chess.pgn.scan_headers(pgn)


... if headers["Result"] == "1-0")
>>> first_white_win = next(white_win_offsets)
>>> second_white_win = next(white_win_offsets)

Warning Be careful when seeking a game in the file while more offsets are being generated.

chess.pgn.scan_offsets(handle)
Scan a PGN file opened in text mode for game offsets.
Yields the starting offsets of all the games, so that they can be seeked later. This is just like scan_headers()
but more efficient if you do not actually need the header information.
The PGN standard requires each game to start with an Event-tag. So does this scanner.

7.2. PGN parsing and writing 31


python-chess, Release 0.18.0

Writing

If you want to export your game game with all headers, comments and variations you can use:

>>> print(game)
[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "*"]

1. e4 e5 { Comment } *

Remember that games in files should be separated with extra blank lines.

>>> print(game, file=handle, end="\n\n")

Use the StringExporter() or FileExporter() visitors if you need more control.

Visitors

Visitors are an advanced concept for game tree traversal.


class chess.pgn.BaseVisitor
Base class for visitors.
Use with chess.pgn.Game.accept() or chess.pgn.GameNode.accept().
Methods are called in PGN order.
begin_game()
Called at the start of a game.
begin_headers()
Called at the start of the game headers.
visit_header(tagname, tagvalue)
Called for each game header.
end_headers()
Called at the end of the game headers.
visit_move(board, move)
Called for each move.
board is the board state before the move. The board state must be restored before the traversal continues.
visit_comment(comment)
Called for each comment.
visit_nag(nag)
Called for each NAG.
begin_variation()
Called at the start of a new variation. It is not called for the mainline of the game.
end_variation()
Concludes a variation.

32 Chapter 7. Contents
python-chess, Release 0.18.0

visit_result(result)
Called at the end of the game with the Result-header.
end_game()
Called at the end of a game.
result()
Called to get the result of the visitor. Defaults to True.
handle_error(error)
Called for errors encountered. Defaults to raising an exception.
The following visitors are readily available.
class chess.pgn.GameModelCreator
Creates a game model. Default visitor for read_game().
handle_error(error)
Populates chess.pgn.Game.errors with encountered errors and logs them.
result()
Returns the visited Game().
class chess.pgn.StringExporter(columns=80, headers=True, comments=True, variations=True)
Allows exporting a game as a string.

>>> exporter = chess.pgn.StringExporter(headers=True, variations=True,


˓→comments=True)

>>> pgn_string = game.accept(exporter)

Only columns characters are written per line. If columns is None then the entire movetext will be on a single
line. This does not affect header tags and comments.
There will be no newlines at the end of the string.
class chess.pgn.FileExporter(handle, columns=80, headers=True, comments=True, varia-
tions=True)
Like a StringExporter, but games are written directly to a text file.
There will always be a blank line after each game. Handling encodings is up to the caller.

>>> new_pgn = open("new.pgn", "w", encoding="utf-8")


>>> exporter = chess.pgn.FileExporter(new_pgn)
>>> game.accept(exporter)

NAGs

Numeric anotation glyphs describe moves and positions using standardized codes that are understood by many chess
programs. During PGN parsing, annotations like !, ?, !!, etc. are also converted to NAGs.
chess.pgn.NAG_GOOD_MOVE = 1
A good move. Can also be indicated by ! in PGN notation.
chess.pgn.NAG_MISTAKE = 2
A mistake. Can also be indicated by ? in PGN notation.
chess.pgn.NAG_BRILLIANT_MOVE = 3
A brilliant move. Can also be indicated by !! in PGN notation.
chess.pgn.NAG_BLUNDER = 4
A blunder. Can also be indicated by ?? in PGN notation.

7.2. PGN parsing and writing 33


python-chess, Release 0.18.0

chess.pgn.NAG_SPECULATIVE_MOVE = 5
A speculative move. Can also be indicated by !? in PGN notation.
chess.pgn.NAG_DUBIOUS_MOVE = 6
A dubious move. Can also be indicated by ?! in PGN notation.

Polyglot opening book reading

chess.polyglot.open_reader(path)
Creates a reader for the file at the given path.

>>> with open_reader("data/polyglot/performance.bin") as reader:


... for entry in reader.find_all(board):
... print(entry.move(), entry.weight, entry.learn)
e2e4 1 0
d2d4 1 0
c2c4 1 0

class chess.polyglot.Entry
An entry from a polyglot opening book.
key
The Zobrist hash of the position.
raw_move
The raw binary representation of the move. Use the move() method to extract a move object from this.
weight
An integer value that can be used as the weight for this entry.
learn
Another integer value that can be used for extra information.
move(chess960=False)
Gets the move (as a Move object).
class chess.polyglot.MemoryMappedReader(filename)
Maps a polyglot opening book to memory.
close()
Closes the reader.
find_all(board, minimum_weight=1, exclude_moves=())
Seeks a specific position and yields corresponding entries.
find(board, minimum_weight=1, exclude_moves=())
Finds the main entry for the given position or zobrist hash.
The main entry is the first entry with the highest weight.
By default entries with weight 0 are excluded. This is a common way to delete entries from an opening
book without compacting it. Pass minimum_weight 0 to select all entries.
Raises IndexError if no entries are found.
choice(board, minimum_weight=1, exclude_moves=(), random=<module ‘ran-
dom’ from ‘/home/docs/checkouts/readthedocs.org/user_builds/python-
chess/envs/v0.18.0/lib/python3.5/random.py’>)
Uniformly selects a random entry for the given position.
Raises IndexError if no entries are found.

34 Chapter 7. Contents
python-chess, Release 0.18.0

weighted_choice(board, exclude_moves=(), random=<module ‘random’ from


‘/home/docs/checkouts/readthedocs.org/user_builds/python-
chess/envs/v0.18.0/lib/python3.5/random.py’>)
Selects a random entry for the given position, distributed by the weights of the entries.
Raises IndexError if no entries are found.
chess.POLYGLOT_RANDOM_ARRAY = [0x9D39247E33776D41, ..., 0xF8D626AAAF278509]
Array of 781 polyglot compatible pseudo random values for Zobrist hashing.

Gaviota endgame tablebase probing

Gaviota tablebases provide WDL (win/draw/loss) and DTM (depth to mate) information for all endgame positions
with up to 5 pieces. Positions with castling rights are not included.
chess.gaviota.open_tablebases(directory=None, libgtb=None, Library-
Loader=<ctypes.LibraryLoader object>)
Opens a collection of tablebases for probing.
First native access via the shared library libgtb is tried. You can optionally provide a specific library name or a
library loader. The shared library has global state and caches, so only one instance can be open at a time.
Second pure Python probing code is tried.
class chess.gaviota.PythonTablebases(directory, lzma)
Provides access to Gaviota tablebases using pure Python code.
open_directory(directory)
Loads .gtb.cp4 tables from a directory.
probe_dtm(board)
Probes for depth to mate information.
The absolute value is the number of half moves until forced mate (or 0 in drawn positions). The value is
positive if the side to move is winning, otherwise it is negative.
In the example position white to move will get mated in 10 half moves:

>>> with chess.gaviota.open_tablebases("data/gaviota") as tablebases:


... tablebases.probe_dtm(chess.Board("8/8/8/8/8/8/8/K2kr3 w - - 0 1"))
...
-10

Raises KeyError (or specifically chess.gaviota.MissingTableError) if the probe


fails. Use get_dtm() if you prefer to get None instead of an exception.

probe_wdl(board)
Probes for win/draw/loss-information.
Returns 1 if the side to move is winning, 0 if it is a draw, and -1 if the side to move is losing.

>>> with chess.gaviota.open_tablebases("data/gaviota") as tablebases:


... tablebases.probe_wdl(chess.Board("8/4k3/8/B7/8/8/8/4K3 w - - 0 1"))
...
0

Raises KeyError (or specifically chess.gaviota.MissingTableError) if the probe


fails. Use get_wdl() if you prefer to get None instead of an exception.

7.4. Gaviota endgame tablebase probing 35


python-chess, Release 0.18.0

close()
Closes all loaded tables.

backports.lzma

For Python versions before 3.3 you have to install backports.lzma in order to use the pure Python probing code.

sudo apt-get install liblzma-dev libpython2.7-dev


pip install backports.lzma

libgtb

For faster access you can build and install a shared library. Otherwise the pure Python probing code is used.

git clone https://github.com/michiguel/Gaviota-Tablebases.git


cd Gaviota-Tablebases
make
sudo make install

chess.gaviota.open_tablebases_native(directory, libgtb=None, Library-


Loader=<ctypes.LibraryLoader object>)
Opens a collection of tablebases for probing using libgtb.
In most cases open_tablebases() should be used. Use this function only if you do not want to downgrade
to pure Python tablebase probing.
Raises RuntimeError or OSError when libgtb can not be used.
class chess.gaviota.NativeTablebases(directory, libgtb)
Provides access to Gaviota tablebases via the shared library libgtb. Has the same interface as
PythonTablebases.

Syzygy endgame tablebase probing

Syzygy tablebases provide WDL (win/draw/loss) and DTZ (distance to zero) information for all endgame positions
with up to 6 pieces. Positions with castling rights are not included.
chess.syzygy.open_tablebases(directory=None, load_wdl=True, load_dtz=True, max_fds=128,
VariantBoard=<class ‘chess.Board’>)
Opens a collection of tablebases for probing. See Tablebases.

Note: Generally probing requires tablebase files for the specific material composition, as well as tablebase files
with less pieces. This is important because 6-piece and 5-piece files are often distributed seperately, but are both
required for 6-piece positions. Use open_directory() to load tablebases from additional directories.

class chess.syzygy.Tablebases(directory=None, load_wdl=True, load_dtz=True, max_fds=128,


VariantBoard=<class ‘chess.Board’>)
Manages a collection of tablebase files for probing.
Syzygy tables come in files like KQvKN.rtbw or KRBvK.rtbz, one WDL (.rtbw) and DTZ (.rtbz) file for each
material composition.
Directly loads tables from directory. See open_directory().

36 Chapter 7. Contents
python-chess, Release 0.18.0

If max_fds is not None, will at most use max_fds open file descriptors at any given time. The least recently used
tables are closed, if nescessary.
open_directory(directory, load_wdl=True, load_dtz=True)
Loads tables from a directory.
By default all available tables with the correct file names (e.g. KQvKN.rtbw or KRBvK.rtbz) are loaded.
Returns the number of successfully openened and loaded tablebase files.
probe_wdl(board)
Probes WDL tables for win/draw/loss-information.
Probing is thread-safe when done with different board objects and if board objects are not modified during
probing.
Returns 2 if the side to move is winning, 0 if the position is a draw and -2 if the side to move is losing.
Returns 1 in case of a cursed win and -1 in case of a blessed loss. Mate can be forced but the position can
be drawn due to the fifty-move rule.

>>> with chess.syzygy.open_tablebases("data/syzygy/regular") as tablebases:


... tablebases.probe_wdl(chess.Board("8/2K5/4B3/3N4/8/8/4k3/8 b - - 0 1"))
...
-2

Raises KeyError (or specifically chess.syzygy.MissingTableError) if the probe


fails. Use get_wdl() if you prefer to get None instead of an exception.

probe_dtz(board)
Probes DTZ tables for distance to zero information.
Both DTZ and WDL tables are required in order to probe for DTZ.
Returns a positive value if the side to move is winning, 0 if the position is a draw and a negative value if
the side to move is losing. More precisely:
WDL DTZ
-2 -100 <= Unconditional loss (assuming 50-move counter is zero), where a zeroing move can
n < -1 be forced in -n plies.
-1 n< Loss, but draw under the 50-move rule. A zeroing move can be forced in -n plies or
-100 -n - 100 plies (if a later phase is responsible for the blessed loss).
0 0 Draw.
1 100 < n Win, but draw under the 50-move rule. A zeroing move can be forced in n plies or n
- 100 plies (if a later phase is responsible for the cursed win).
2 1<n Unconditional win (assuming 50-move counter is zero), where a zeroing move can
<= 100 be forced in n plies.
The return value can be off by one: a return value -n can mean a loss in n + 1 plies and a return value +n
can mean a win in n + 1 plies. This is guaranteed not to happen for positions exactly on the edge of the
50-move rule, so that this never impacts results of practical play.
Minmaxing the DTZ values guarantees winning a won position (and drawing a drawn position), because it
makes progress keeping the win in hand. However the lines are not always the most straightforward ways
to win. Engines like Stockfish calculate themselves, checking with DTZ, but only play according to DTZ
if they can not manage on their own.

>>> with chess.syzygy.open_tablebases("data/syzygy/regular") as tablebases:


... tablebases.probe_dtz(chess.Board("8/2K5/4B3/3N4/8/8/4k3/8 b - - 0 1"))

7.5. Syzygy endgame tablebase probing 37


python-chess, Release 0.18.0

...
-53

Probing is thread-safe when done with different board objects and if board objects are not modified during
probing.
Raises KeyError (or specifically chess.syzygy.MissingTableError) if the probe
fails. Use get_dtz() if you prefer to get None instead of an exception.
close()
Closes all loaded tables.

UCI engine communication

The Universal Chess Interface is a protocol for communicating with engines.


chess.uci.popen_engine(command, engine_cls=<class ‘chess.uci.Engine’>, setpgrp=False,
_popen_lock=<unlocked _thread.lock object>)
Opens a local chess engine process.
No initialization commands are sent, so do not forget to send the mandatory uci command.

>>> engine = chess.uci.popen_engine("/usr/games/stockfish")


>>> engine.uci()
>>> engine.name
'Stockfish 230814 64'
>>> engine.author
'Tord Romstad, Marco Costalba and Joona Kiiski'

Parameters setpgrp – Open the engine process in a new process group. This will stop signals
(such as keyboards interrupts) from propagating from the parent process. Defaults to False.

chess.uci.spur_spawn_engine(shell, command, engine_cls=<class ‘chess.uci.Engine’>)


Spawns a remote engine using a Spur shell.

>>> import spur


>>> shell = spur.SshShell(hostname="localhost", username="username", password="pw
˓→")

>>> engine = chess.uci.spur_spawn_engine(shell, ["/usr/games/stockfish"])


>>> engine.uci()

class chess.uci.Engine(Executor=<class ‘concurrent.futures.thread.ThreadPoolExecutor’>)

process
The underlying operating system process.
name
The name of the engine. Conforming engines should send this as id name when they receive the initial uci
command.
author
The author, as sent via id author. Just like the name.
options
A case insensitive dictionary of Options. The engine should send available options when it receives the
initial uci command.

38 Chapter 7. Contents
python-chess, Release 0.18.0

uciok
threading.Event() that will be set as soon as uciok was received. By then name, author and
options should be available.
return_code
The return code of the operating system process.
terminated
threading.Event() that will be set as soon as the underyling operating system process is terminated
and the return_code is available.
terminate(async_callback=None)
Terminate the engine.
This is not an UCI command. It instead tries to terminate the engine on operating system level, for example
by sending SIGTERM on Unix systems. If possible, first try the quit command.
Returns The return code of the engine process (or a Future).
kill(async_callback=None)
Kill the engine.
Forcefully kill the engine process, for example by sending SIGKILL.
Returns The return code of the engine process (or a Future).
is_alive()
Poll the engine process to check if it is alive.

UCI commands

class chess.uci.Engine(Executor=<class ‘concurrent.futures.thread.ThreadPoolExecutor’>)

uci(async_callback=None)
Tells the engine to use the UCI interface.
This is mandatory before any other command. A conforming engine will send its name, authors and
available options.
Returns Nothing
debug(on, async_callback=None)
Switch the debug mode on or off.
In debug mode the engine should send additional infos to the GUI to help debugging. This mode should
be switched off by default.
Parameters on – bool
Returns Nothing
isready(async_callback=None)
Command used to synchronize with the engine.
The engine will respond as soon as it has handled all other queued commands.
Returns Nothing
setoption(options, async_callback=None)
Set values for the engines available options.
Parameters options – A dictionary with option names as keys.

7.6. UCI engine communication 39


python-chess, Release 0.18.0

Returns Nothing
ucinewgame(async_callback=None)
Tell the engine that the next search will be from a different game.
This can be a new game the engine should play or if the engine should analyse a position from a different
game. Using this command is recommended but not required.
Returns Nothing
position(board, async_callback=None)
Set up a given position.
Instead of just the final FEN, the initial FEN and all moves leading up to the position will be sent, so that
the engine can detect repetitions.
If the position is from a new game it is recommended to use the ucinewgame command before the position
command.
Parameters board – A chess.Board.
Returns Nothing
Raises EngineStateException if the engine is still calculating.
go(searchmoves=None, ponder=False, wtime=None, btime=None, winc=None, binc=None,
movestogo=None, depth=None, nodes=None, mate=None, movetime=None, infinite=False,
async_callback=None)
Start calculating on the current position.
All parameters are optional, but there should be at least one of depth, nodes, mate, infinite or some time
control settings, so that the engine knows how long to calculate.
Note that when using infinite or ponder the engine will not stop until it is told to.
Parameters
• searchmoves – Restrict search to moves in this list.
• ponder – Bool to enable pondering mode. The engine will not stop pondering in the
background until a stop command is received.
• wtime – Integer of milliseconds white has left on the clock.
• btime – Integer of milliseconds black has left on the clock.
• winc – Integer of white Fisher increment.
• binc – Integer of black Fisher increment.
• movestogo – Number of moves to the next time control. If this is not set, but wtime or
btime are, then it is sudden death.
• depth – Search depth ply only.
• nodes – Search so many nodes only.
• mate – Search for a mate in mate moves.
• movetime – Integer. Search exactly movetime milliseconds.
• infinite – Search in the background until a stop command is received.
Returns A tuple of two elements. The first is the best move according to the engine. The second
is the ponder move. This is the reply as sent by the engine. Either of the elements may be
None.
Raises EngineStateException if the engine is already calculating.

40 Chapter 7. Contents
python-chess, Release 0.18.0

stop(async_callback=None)
Stop calculating as soon as possible.
Returns Nothing.
ponderhit(async_callback=None)
May be sent if the expected ponder move has been played.
The engine should continue searching but should switch from pondering to normal search.
Returns Nothing.
Raises EngineStateException if the engine is not currently searching in ponder mode.
quit(async_callback=None)
Quit the engine as soon as possible.
Returns The return code of the engine process.
EngineTerminatedException is raised if the engine process is no longer alive.

Asynchronous communication

By default all operations are executed synchronously and their result is returned. For example

>>> engine.go(movetime=2000)
BestMove(bestmove=Move.from_uci('e2e4'), ponder=None)

will take about 2000 milliseconds. All UCI commands have an optional async_callback argument. They will then
immediately return a Future and continue.

>>> command = engine.go(movetime=2000, async_callback=True)


>>> command.done()
False
>>> command.result() # Synchronously wait for the command to finish
BestMove(bestmove=Move.from_uci('e2e4'), ponder=None)
>>> command.done()
True

Instead of just passing async_callback=True a callback function may be passed. It will be invoked possibly on a
different thread as soon as the command is completed. It takes the command future as a single argument.

>>> def on_go_finished(command):


... # Will likely be executed on a different thread.
... bestmove, ponder = command.result()
...
>>> command = engine.go(movetime=2000, async_callback=on_go_finished)

Note about castling moves

There are different ways castling moves may be encoded. The normal way to do it is e1g1 for short castling. The
same move would be e1h1 in UCI_Chess960 mode.
This is abstracted away by the UCI module, but if the engine supports it, it is recommended to enable enable
UCI_Chess960 mode.

>>> engine.setoption({"UCI_Chess960": True})

7.6. UCI engine communication 41


python-chess, Release 0.18.0

Info handler

class chess.uci.Score
A centipawns or mate score sent by an UCI engine.
cp
Evaluation in centipawns or None.
mate
Mate in x or None. Negative if the engine thinks it is going to be mated.
lowerbound
If the score is not exact but only a lowerbound.
upperbound
If the score is only an upperbound.
class chess.uci.InfoHandler
Chess engines may send information about their calculations with the info command. Info handlers can be used
to aggregate or react to this information.
>>> # Register a standard info handler.
>>> info_handler = chess.uci.InfoHandler()
>>> engine.info_handlers.append(info_handler)

>>> # Start a search.


>>> engine.position(board)
>>> engine.go(movetime=1000)
BestMove(bestmove=Move.from_uci('e2e4'), ponder=Move.from_uci('e7e6'))
>>>
>>> # Retrieve the score of the mainline (PV 1) after search is completed.
>>> # Note that the score is relative to the side to move.
>>> info_handler.info["score"][1]
Score(cp=34, mate=None, lowerbound=False, upperbound=False)

See info for a way to access this dictionary in a thread-safe way during search.
If you want to be notified whenever new information is available you would usually subclass the InfoHandler
class:
>>> class MyHandler(chess.uci.InfoHandler):
... def post_info(self):
... # Called whenever a complete *info* line has been processed.
... super(MyHandler, self).post_info()
... print(self.info)

info
The default implementation stores all received information in this dictionary. To get a consistent snapshot
use the object as if it were a threading.Lock().
>>> # Start thinking.
>>> engine.go(infinite=True, async_callback=True)

>>> # Wait a moment, then access a consistent snapshot.


>>> time.sleep(3)
>>> with info_handler:
... if 1 in info_handler.info["score"]:
... print("Score: ", info_handler.info["score"][1].cp)
... print("Mate: ", info_handler.info["score"][1].mate)

42 Chapter 7. Contents
python-chess, Release 0.18.0

Score: 34
Mate: None

depth(x)
Received search depth in plies.
seldepth(x)
Received selective search depth in plies.
time(x)
Received new time searched in milliseconds.
nodes(x)
Received number of nodes searched.
pv(moves)
Received the principal variation as a list of moves.
In MultiPV mode this is related to the most recent multipv number sent by the engine.
multipv(num)
Received a new multipv number, starting at 1.
If multipv occurs in an info line, this is guaranteed to be called before score or pv.
score(cp, mate, lowerbound, upperbound)
Received a new evaluation in centipawns or a mate score.
cp may be None if no score in centipawns is available.
mate may be None if no forced mate has been found. A negative numbers means the engine thinks it will
get mated.
lowerbound and upperbound are usually False. If True, the sent score are just a lowerbound or upperbound.
In MultiPV mode this is related to the most recent multipv number sent by the engine.
currmove(move)
Received a move the engine is currently thinking about.
These moves come directly from the engine. So the castling move representation depends on the
UCI_Chess960 option of the engine.
currmovenumber(x)
Received a new currmovenumber.
hashfull(x)
Received new information about the hashtable.
The hashtable is x permill full.
nps(x)
Received new nodes per second statistic.
tbhits(x)
Received new information about the number of table base hits.
cpuload(x)
Received new cpuload information in permill.
string(string)
Received a string the engine wants to display.

7.6. UCI engine communication 43


python-chess, Release 0.18.0

refutation(move, refuted_by)
Received a new refutation of a move.
refuted_by may be a list of moves representing the mainline of the refutation or None if no refutation has
been found.
Engines should only send refutations if the UCI_ShowRefutations option has been enabled.
currline(cpunr, moves)
Received a new snapshot of a line a specific CPU is calculating.
cpunr is an integer representing a specific CPU. moves is a list of moves.
pre_info(line)
Received a new info line about to be processed.
When subclassing remember to call this method of the parent class in order to keep the locking in tact.
post_info()
Processing of a new info line has been finished.
When subclassing remember to call this method of the parent class in order to keep the locking in tact.
on_bestmove(bestmove, ponder)
A new bestmove and pondermove have been received.
on_go()
A go command is being sent.
Since information about the previous search is invalidated the dictionary with the current information will
be cleared.

Options

class chess.uci.Option
Information about an available option for an UCI engine.
name
The name of the option.
type
The type of the option.
Officially documented types are check for a boolean value, spin for an integer value between a min-
imum and a maximum, combo for an enumeration of predefined string values (one of which can be
selected), button for an action and string for a textfield.
default
The default value of the option.
There is no need to send a setoption command with the defaut value.
min
The minimum integer value of a spin option.
max
The maximum integer value of a spin option.
var
A list of allows string values for a combo option.

44 Chapter 7. Contents
python-chess, Release 0.18.0

SVG rendering

This module renders SVGs (mostly for IPython integration). Pieces images are copyright Colin M.L. Burnett and
licensed under GFDL & BSD & GPL.
chess.svg.piece(piece, size=None)
Renders the given chess.Piece as an SVG.

>>> chess.svg.piece(chess.Piece.from_symbol("R"))

chess.svg.board(board=None, squares=None, flipped=False, coordinates=True, lastmove=None,


check=None, arrows=(), size=None, style=None)
Renders a board with pieces and/or selected squares as an SVG.
Parameters
• board – A chess.BaseBoard with pieces or None.
• squares – A chess.SquareSet with selected squares.
• flipped – Pass True to flip the board.
• coordinates – Pass False to disable coordinates in the margin.
• lastmove – A chess.Move to be highlighted.
• check – A square to be marked as check.
• arrows – A list of Arrow objects or tuples like (chess.E2, chess.E4).
• size – Limit the SVG size by setting width and height of the image.
• style – CSS to use instead of the default stylesheet.

>>> board = chess.Board("8/8/8/8/4N3/8/8/8 w - - 0 1")


>>> squares = board.attacks(chess.E4)
>>> chess.svg.board(board=board, squares=squares)

Variants (experimental)

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).starting_fen
'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w - - 0 1'

See chess.Board.is_variant_end(), is_variant_win() is_variant_draw()


is_variant_loss() for special variant end conditions and results.

7.7. SVG rendering 45


python-chess, Release 0.18.0

Variant Board class UCI Syzygy


Standard chess.Board chess .rtbw, .rtbz
Suicide chess.variant.SuicideBoard suicide .stbw, .stbz
Giveaway chess.variant.GiveawayBoard giveaway .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 threecheck
Crazyhouse chess.variant.CrazyhouseBoard crazyhouse
chess.variant.find_variant(name)
Looks for a variant board class by variant name.

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)

UCI

Stockfish and other engines allow you to switch variants by setting the UCI_Variant option.

>>> board = chess.variant.RacingKingsBoard()


>>> engine.setoption({
... "UCI_Variant": type(board).uci_variant,
... "UCI_Chess960": board.chess960
... })
>>> engine.position(board)

Syzygy

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

>>> tables = chess.syzygy.open_tablebases("data/syzygy", VariantBoard=chess.variant.


˓→AtomicBoard)

Changelog for python-chess

At the current stage of this project it is more important to get things right than to be consistent with previous versions.
Use this changelog to see what changed in a new release, because this might include API breaking changes.

New in v0.18.0

Bugfixes:
• Fixed Board.parse_uci() for crazyhouse drops. Thanks to Ryan Delaney.

46 Chapter 7. Contents
python-chess, Release 0.18.0

• Fixed AtomicBoard.is_insufficient_material().
• Fixed signature of SuicideBoard.was_into_check().
• Explicitly close input and output streams when a chess.uci.PopenProcess terminates.
• The documentation of Board.attackers() was wrongly stating that en passant capturable pawns are considered
attacked.
Changes:
• chess.SquareSet is no longer hashable (since it is mutable).
• Removed functions and constants deprecated in v0.17.0.
• Dropped gmpy2 and gmpy as optional dependencies. They were no longer improving performance.
• Various tweaks and optimizations for 5% improvement in PGN parsing and perft speed. (Signature of _is_safe
and _ep_skewered changed).
• Rewritten chess.svg.board() using xml.etree. No longer supports pre and post. Use an XML parser if you need
to modify the SVG. Now only inserts actually used piece defintions.
• Untangled UCI process and engine instanciation, changing signatures of constructors and allowing arbitrary
arguments to subprocess.Popen.
• Coding style and documentation improvements.
New features:
• chess.svg.board() now supports arrows. Thanks to @rheber for implementing this feature.
• Let chess.uci.PopenEngine consistently handle Ctrl+C across platforms and Python versions.
chess.uci.popen_engine() now supports a setpgrp keyword argument to start the engine process in a new
process group. Thanks to @dubiousjim.
• Added board.king(color) to find the (royal) king of a given side.
• SVGs now have viewBox and chess.svg.board(size=None) supports and defaults to None (i.e. scaling to the size
of the container).

New in v0.17.0

Changes:
• Rewritten move generator, various performance tweaks, code simplications (500 lines removed) amounting to
doubled PGN parsing and perft speed.
• Removed board.generate_evasions() and board.generate_non_evasions().
• Removed board.transpositions. Transpositions are now counted on demand.
• file_index(), rank_index(), and pop_count() have been renamed to square_file(), square_rank() and popcount()
respectively. Aliases will be removed in some future release.
• STATUS_ILLEGAL_CHECK has been renamed to STATUS_RACE_CHECK. The alias will be removed in a
future release.
• Removed DIAG_ATTACKS_NE, DIAG_ATTACKS_NW, RANK_ATTACKS and FILE_ATTACKS as well as
the corresponding masks. New attack tables BB_DIAG_ATTACKS (combined both diagonal tables),
BB_RANK_ATTACKS and BB_FILE_ATTACKS are indexed by square instead of mask.
• board.push() no longer requires pseudo-legality.
• Documentation improvements.

7.9. Changelog for python-chess 47


python-chess, Release 0.18.0

Bugfixes:
• Positions in variant end are now guaranteed to have no legal moves. board.is_variant_end() has been added
to test for special variant end conditions. Thanks to salvador-dali.
• chess.svg: Fixed a typo in the class names of black queens. Fixed fill color for black rooks and queens. Added
SVG Tiny support. These combined changes fix display in a number of applications, including Jupyter Qt
Console. Thanks to Alexander Meshcheryakov.
• board.ep_square was not consistently None instead of 0.
• Detect invalid racing kings positions: STATUS_RACE_OVER, STATUS_RACE_MATERIAL.
• SAN_REGEX, FEN_CASTLING_REGEX and TAG_REGEX now try to match the entire string and no longer
accept newlines.
• Fixed Move.__hash__() for drops.
New features:
• board.remove_piece_at() now returns the removed piece.
• Added square_distance() and square_mirror().
• Added msb(), lsb(), scan_reversed() and scan_forward().
• Added BB_RAYS and BB_BETWEEN.

New in v0.16.2

Changes:
• board.move_stack now contains the exact move objects added with Board.push() (instead of normalized copies
for castling moves). This ensures they can be used with Board.variation_san() amongst others.
• board.ep_square is now None instead of 0 for no en passant square.
• chess.svg: Better vector graphics for knights. Thanks to ProgramFox.
• Documentation improvements.

New in v0.16.1

Bugfixes:
• Explosions in atomic chess were not destroying castling rights. Thanks to ProgramFOX for finding this issue.

New in v0.16.0

Bugfixes:
• pin_mask(), pin() and is_pinned() make more sense when already in check. Thanks to Ferdinand Mosca.
New features:
• Variant support: Suicide, Giveaway, Atomic, King of the Hill, Racing Kings, Horde, Three-check, Crazy-
house. chess.Move now supports drops.
• More fine grained dependencies. Use pip install python-chess[uci,gaviota] to install dependencies for the full
feature set.
• Added chess.STATUS_EMPTY and chess.STATUS_ILLEGAL_CHECK.

48 Chapter 7. Contents
python-chess, Release 0.18.0

• The board.promoted mask keeps track of promoted pieces.


• Optionally copy boards without the move stack: board.copy(stack=False).
• examples/bratko_kopec now supports avoid move (am), variants and displays fractional scores immidiately.
Thanks to Daniel Dugovic.
• perft.py rewritten with multi-threading support and moved to examples/perft.
• chess.syzygy.dependencies(), chess.syzygy.all_dependencies() to generate Syzygy tablebase dependencies.
Changes:
• Endgame tablebase probing (Syzygy, Gaviota): probe_wdl() , probe_dtz() and probe_dtm() now raise Key-
Error or MissingTableError instead of returning None. If you prefer getting None in case of an error use
get_wdl(), get_dtz() and get_dtm().
• chess.pgn.BaseVisitor.result() returns True by default and is no longer used by chess.pgn.read_game() if no
game was found.
• Non-fast-forward update of the Git repository to reduce size (old binary test assets removed).
• board.pop() now uses a boardstate stack to undo moves.
• uci.engine.position() will send the move history only until the latest zeroing move.
• Optimize board.clean_castling_rights() and micro-optimizations improving PGN parser performance by around
20%.
• Syzygy tables now directly use the endgame name as hash keys.
• Improve test performance (especially on Travis CI).
• Documentation updates and improvements.

New in v0.15.4

New features:
• Highlight last move and checks when rendering board SVGs.

New in v0.15.3

Bugfixes:
• pgn.Game.errors was not populated as documented. Thanks to Ryan Delaney for reporting.
New features:
• Added pgn.GameNode.add_line() and pgn.GameNode.main_line() which make it easier to work with lists of
moves as variations.

New in v0.15.2

Bugfixes:
• Fix a bug where shift_right() and shift_2_right() were producing integers larger than 64bit when shifting squares
off the board. This is very similar to the bug fixed in v0.15.1. Thanks to piccoloprogrammatore for reporting.

7.9. Changelog for python-chess 49


python-chess, Release 0.18.0

New in v0.15.1

Bugfixes:
• Fix a bug where shift_up_right() and shift_up_left() were producing integers larger than 64bit when shifting
squares off the board.
New features:
• Replaced __html__ with experimental SVG rendering for IPython.

New in v0.15.0

Changes:
• chess.uci.Score no longer has upperbound and lowerbound attributes. Previously these were always False.
• Significant improvements of move generation speed, around 2.3x faster PGN parsing. Removed the follow-
ing internal attributes and methods of the Board class: attacks_valid, attacks_to, attacks_from, _pinned(), at-
tacks_valid_stack, attacks_from_stack, attacks_to_stack, generate_attacks().
• UCI: Do not send isready directly after go. Though allowed by the UCI protocol specification it is just not
nescessary and many engines were having trouble with this.
• Polyglot: Use less memory for uniform random choices from big opening books (reservoir sampling).
• Documentation improvements.
Bugfixes:
• Allow underscores in PGN header tags. Found and fixed by Bajusz Tamás.
New features:
• Added Board.chess960_pos() to identify the Chess960 starting position number of positions.
• Added chess.BB_BACKRANKS and chess.BB_PAWN_ATTACKS.

New in v0.14.1

Bugfixes:
• Backport Bugfix for Syzygy DTZ related to en-passant. See official-stockfish/Stockfish@6e2ca97d93812b2.
Changes:
• Added optional argument max_fds=128 to chess.syzygy.open_tablebases(). An LRU cache is used to keep at
most max_fds files open. This allows using many tables without running out of file descriptors. Previously all
tables were opened at once.
• Syzygy and Gaviota now store absolute tablebase paths, in case you change the working directory of the process.
• The default implementation of chess.uci.InfoHandler.score() will no longer store score bounds in info[”score”],
only real scores.
• Added Board.set_chess960_pos().
• Documentation improvements.

50 Chapter 7. Contents
python-chess, Release 0.18.0

New in v0.14.0

Changes:
• Board.attacker_mask() has been renamed to Board.attackers_mask() for consistency.
• The signature of Board.generate_legal_moves() and Board.generate_pseudo_legal_moves() has been
changed. Previously it was possible to select piece types for selective move generation:
Board.generate_legal_moves(castling=True, pawns=True, knights=True, bishops=True, rooks=True,
queens=True, king=True)
Now it is possible to select arbitrary sets of origin and target squares. to_mask uses the corresponding rook
squares for castling moves.
Board.generate_legal_moves(from_mask=BB_ALL, to_mask=BB)
To generate all knight and queen moves do:
board.generate_legal_moves(board.knights | board.queens)
To generate only castling moves use:
Board.generate_castling_moves(from_mask=BB_ALL, to_mask=BB_ALL)
• Additional hardening has been added on top of the bugfix from v0.13.3. Diagonal skewers on the last double
pawn move are now handled correctly, even though such positions can not be reached with a sequence of legal
moves.
• chess.syzygy now uses the more efficient selective move generation.
New features:
• The following move generation methods have been added: Board.generate_pseudo_legal_ep(from_mask=BB_ALL,
to_mask=BB_ALL), Board.generate_legal_ep(from_mask=BB_ALL, to_mask=BB_ALL),
Board.generate_pseudo_legal_captures(from_mask=BB_ALL, to_mask=BB_ALL),
Board.generate_legal_captures(from_mask=BB_ALL, to_mask=BB_ALL).

New in v0.13.3

This is a bugfix release for a move generation bug. Other than the bugfix itself there are only minimal fully back-
wardscompatible changes. You should update immediately.
Bugfixes:
• When capturing en passant, both the capturer and the captured pawn disappear from the fourth or fifth rank. If
those pawns were covering a horizontal attack on the king, then capturing en passant should not have been legal.
Board.generate_legal_moves() and Board.is_into_check() have been fixed.
The same principle applies for diagonal skewers, but nothing has been done in this release: If the last double
pawn move covers a diagonal attack, then the king would have already been in check.
v0.14.0 adds additional hardening for all cases. It is recommended you upgrade to v0.14.0 as soon as you can
deal with the non-backwards compatible changes.
Changes:
• chess.uci now uses subprocess32 if applicable (and available). Additionally a lock is used to work around a race
condition in Python 2, that can occur when spawning engines from multiple threads at the same time.
• Consistently handle tabs in UCI engine output.

7.9. Changelog for python-chess 51


python-chess, Release 0.18.0

New in v0.13.2

Changes:
• chess.syzygy.open_tablebases() now raises if the given directory does not exist.
• Allow visitors to handle invalid FEN tags in PGNs.
• Gaviota tablebase probing fails faster for piece counts > 5.
Minor new features:
• Added chess.pgn.Game.from_board().

New in v0.13.1

Changes:
• Missing SetUp tags in PGNs are ignored.
• Incompatible comparisons on chess.Piece, chess.Move, chess.Board and chess.SquareSet now return NotImple-
mented instead of False.
Minor new features:
• Factored out basic board operations to chess.BaseBoard. This is inherited by chess.Board and extended with the
usual move generation features.
• Added optional claim_draw argument to chess.Base.is_game_over().
• Added chess.Board.result(claim_draw=False).
• Allow chess.Board.set_piece_at(square, None).
• Added chess.SquareSet.from_square(square).

New in v0.13.0

• chess.pgn.Game.export() and chess.pgn.GameNode.export() have been removed and replaced with a new visitor
concept.
• chess.pgn.read_game() no longer takes an error_handler argument. Errors are now logged. Use the new visitor
concept to change this behaviour.

New in v0.12.5

Bugfixes:
• Context manager support for pure Python Gaviota probing code. Various documentation fixes for Gaviota
probing. Thanks to Jürgen Précour for reporting.
• PGN variation start comments for variations on the very first move were assigned to the game. Thanks to Norbert
Räcke for reporting.

52 Chapter 7. Contents
python-chess, Release 0.18.0

New in v0.12.4

Bugfixes:
• Another en passant related Bugfix for pure Python Gaviota tablebase probing.
New features:
• Added pgn.GameNode.is_end().
Changes:
• Big speedup for pgn module. Boards are cached less agressively. Board move stacks are copied faster.
• Added tox.ini to specify test suite and flake8 options.

New in v0.12.3

Bugfixes:
• Some invalid castling rights were silently ignored by Board.set_fen(). Now it is ensured information is stored
for retrieval using Board.status().

New in v0.12.2

Bugfixes:
• Some Gaviota probe results were incorrect for positions where black could capture en passant.

New in v0.12.1

Changes:
• Robust handling of invalid castling rights. You can also use the new method Board.clean_castling_rights() to
get the subset of strictly valid castling rights.

New in v0.12.0

New features:
• Python 2.6 support. Patch by vdbergh.
• Pure Python Gaviota tablebase probing. Thanks to Jean-Noël Avila.

New in v0.11.1

Bugfixes:
• syzygy.Tablebases.probe_dtz() has was giving wrong results for some positions with possible en passant captur-
ing. This was found and fixed upstream: https://github.com/official-stockfish/Stockfish/issues/394.
• Ignore extra spaces in UCI info lines, as for example sent by the Hakkapeliitta engine. Thanks to Jürgen Précour
for reporting.

7.9. Changelog for python-chess 53


python-chess, Release 0.18.0

New in v0.11.0

Changes:
• Chess960 support and the representation of castling moves has been changed.
The constructor of board has a new chess960 argument, defaulting to False: Board(fen=STARTING_FEN,
chess960=False). That property is available as Board.chess960.
In Chess960 mode the behaviour is as in the previous release. Castling moves are represented as a king move to
the corresponding rook square.
In the default standard chess mode castling moves are represented with the standard UCI notation, e.g. e1g1 for
king-side castling.
Board.uci(move, chess960=None) creates UCI representations for moves. Unlike Move.uci() it can convert them
in the context of the current position.
Board.has_chess960_castling_rights() has been added to test for castling rights that are impossible in standard
chess.
The modules chess.polyglot, chess.pgn and chess.uci will transparently handle both modes.
• In a previous release Board.fen() has been changed to only display an en passant square if a legal en passant
move is indeed possible. This has now also been adapted for Board.shredder_fen() and Board.epd().
New features:
• Get individual FEN components: Board.board_fen(), Board.castling_xfen(), Board.castling_shredder_fen().
• Use Board.has_legal_en_passant() to test if a position has a legal en passant move.
• Make repr(board.legal_moves) human readable.

New in v0.10.1

Bugfixes:
• Fix use-after-free in Gaviota tablebase initialization.

New in v0.10.0

New dependencies:
• If you are using Python < 3.2 you have to install futures in order to use the chess.uci module.
Changes:
• There are big changes in the UCI module. Most notably in async mode multiple commands can be executed at
the same time (e.g. go infinite and then stop or go ponder and then ponderhit).
go infinite and go ponder will now wait for a result, i.e. you may have to call stop or ponderhit from a different
thread or run the commands asynchronously.
stop and ponderhit no longer have a result.
• The values of the color constants chess.WHITE and chess.BLACK have been changed. Previously WHITE was
0, BLACK was 1. Now WHITE is True, BLACK is False. The recommended way to invert color is using not
color.
• The pseudo piece type chess.NONE has been removed in favor of just using None.

54 Chapter 7. Contents
python-chess, Release 0.18.0

• Changed the Board(fen) constructor. If the optional fen argument is not given behavior did not change. However
if None is passed explicitly an empty board is created. Previously the starting position would have been set up.
• Board.fen() will now only show completely legal en passant squares.
• Board.set_piece_at() and Board.remove_piece_at() will now clear the move stack, because the old moves may
not be valid in the changed position.
• Board.parse_uci() and Board.push_uci() will now accept null moves.
• Changed shebangs from #!/usr/bin/python to #!/usr/bin/env python for better virtualenv support.
• Removed unused game data files from repository.
Bugfixes:
• PGN: Prefer the game result from the game termination marker over * in the header. These should be identical
in standard compliant PGNs. Thanks to Skyler Dawson for reporting this.
• Polyglot: minimum_weight for find(), find_all() and choice() was not respected.
• Polyglot: Negative indexing of opening books was raising IndexError.
• Various documentation fixes and improvements.
New features:
• Experimental probing of Gaviota tablebases via libgtb.
• New methods to construct boards:

>>> chess.Board.empty()
Board('8/8/8/8/8/8/8/8 w - - 0 1')

>>> board, ops = chess.Board.from_epd("4k3/8/8/8/8/8/8/4K3 b - - fmvn 17; hmvc 13


˓→")

>>> board
Board('4k3/8/8/8/8/8/8/4K3 b - - 13 17')
>>> ops
{'fmvn': 17, 'hmvc': 13}

• Added Board.copy() and hooks to let the copy module to the right thing.
• Added Board.has_castling_rights(color), Board.has_kingside_castling_rights(color) and
Board.has_queenside_castling_rights(color).
• Added Board.clear_stack().
• Support common set operations on chess.SquareSet().

New in v0.9.1

Bugfixes:
• UCI module could not handle castling ponder moves. Thanks to Marco Belli for reporting.
• The initial move number in PGNs was missing, if black was to move in the starting position. Thanks to Jürgen
Précour for reporting.
• Detect more impossible en passant squares in Board.status(). There already was a requirement for a pawn on
the fifth rank. Now the sixth and seventh rank must be empty, additionally. We do not do further retrograde
analysis, because these are the only cases affecting move generation.

7.9. Changelog for python-chess 55


python-chess, Release 0.18.0

New in v0.8.3

Bugfixes:
• The initial move number in PGNs was missing, if black was to move in the starting position. Thanks to Jürgen
Précour for reporting.
• Detect more impossible en passant squares in Board.status(). There already was a requirement for a pawn on
the fifth rank. Now the sixth and seventh rank must be empty, additionally. We do not do further retrograde
analysis, because these are the only cases affecting move generation.

New in v0.9.0

This is a big update with quite a few breaking changes. Carefully review the changes before upgrading. It’s no
problem if you can not update right now. The 0.8.x branch still gets bugfixes.
Incompatible changes:
• Removed castling right constants. Castling rights are now represented as a bitmask of the rook square. For
example:

>>> board = chess.Board()

>>> # Standard castling rights.


>>> board.castling_rights == chess.BB_A1 | chess.BB_H1 | chess.BB_A8 | chess.BB_H8
True

>>> # Check for the presence of a specific castling right.


>>> can_white_castle_queenside = chess.BB_A1 & board.castling_rights

Castling moves were previously encoded as the corresponding king movement in UCI, e.g. e1f1 for white king-
side castling. Now castling moves are encoded as a move to the corresponding rook square (UCI_Chess960-
style), e.g. e1a1.
You may use the new methods Board.uci(move, chess960=True), Board.parse_uci(uci) and Board.push_uci(uci)
to handle this transparently.
The uci module takes care of converting moves when communicating with an engine that is not in UCI_Chess960
mode.
• The get_entries_for_position(board) method of polyglot opening book readers has been changed to
find_all(board, minimum_weight=1). By default entries with weight 0 are excluded.
• The Board.pieces lookup list has been removed.
• In 0.8.1 the spelling of repetition (was repitition) was fixed. can_claim_threefold_repetition() and
is_fivefold_repetition() are the affected method names. Aliases are now removed.
• Board.set_epd() will now interpret bm, am as a list of moves for the current position and pv as a variation
(represented by a list of moves). Thanks to Jordan Bray for reporting this.
• Removed uci.InfoHandler.pre_bestmove() and uci.InfoHandler.post_bestmove().
• uci.InfoHandler().info[”score”] is now relative to multipv. Use

>>> with info_handler as info:


... if 1 in info["score"]:
... cp = info["score"][1].cp

where you were previously using

56 Chapter 7. Contents
python-chess, Release 0.18.0

>>> with info_handler as info:


... if "score" in info:
... cp = info["score"].cp

• Clear uci.InfoHandler() dictionary at the start of new searches (new on_go()), not at the end of searches.
• Renamed PseudoLegalMoveGenerator.bitboard and LegalMoveGenerator.bitboard to PseudoLegalMoveGen-
erator.board and LegalMoveGenerator.board, respectively.
• Scripts removed.
• Python 3.2 compability dropped. Use Python 3.3 or higher. Python 2.7 support is not affected.
New features:
• Introduced Chess960 support. Board(fen) and Board.set_fen(fen) now support X-FENs. Added
Board.shredder_fen(). Board.status(allow_chess960=True) has an optional argument allowing to insist on stan-
dard chess castling rules. Added Board.is_valid(allow_chess960=True).
• Improved move generation using Shatranj-style direct lookup. Removed rotated bitboards. Perft speed has
been more than doubled.
• Added choice(board) and weighted_choice(board) for polyglot opening book readers.
• Added Board.attacks(square) to determine attacks from a given square. There already was
Board.attackers(color, square) returning attacks to a square.
• Added Board.is_en_passant(move), Board.is_capture(move) and Board.is_castling(move).
• Added Board.pin(color, square) and Board.is_pinned(color, square).
• There is a new method Board.pieces(piece_type, color) to get a set of squares with the specified pieces.
• Do expensive Syzygy table initialization on demand.
• Allow promotions like e8Q (usually e8=Q) in Board.parse_san() and PGN files.
• Patch by Richard C. Gerkin: Added Board.__unicode__() just like Board.__str__() but with unicode pieces.
• Patch by Richard C. Gerkin: Added Board.__html__().

New in v0.8.2

Bugfixes:
• pgn.Game.setup() with the standard starting position was failing when the standard starting position was already
set. Thanks to Jordan Bray for reporting this.
Optimizations:
• Remove bswap() from Syzygy decompression hot path. Directly read integers with the correct endianness.

New in v0.8.1

• Fixed pondering mode in uci module. For example ponderhit() was blocking indefinitely. Thanks to Valeriy
Huz for reporting this.
• Patch by Richard C. Gerkin: Moved searchmoves to the end of the UCI go command, where it will not cause
other command parameters to be ignored.
• Added missing check or checkmate suffix to castling SANs, e.g. O-O-O#.

7.9. Changelog for python-chess 57


python-chess, Release 0.18.0

• Fixed off-by-one error in polyglot opening book binary search. This would not have caused problems for real
opening books.
• Fixed Python 3 support for reverse polyglot opening book iteration.
• Bestmoves may be literally (none) in UCI protocol, for example in checkmate positions. Fix parser and return
None as the bestmove in this case.
• Fixed spelling of repetition (was repitition). can_claim_threefold_repetition() and is_fivefold_repetition() are
the affected method names. Aliases are there for now, but will be removed in the next release. Thanks to Jimmy
Patrick for reporting this.
• Added SquareSet.__reversed__().
• Use containerized tests on Travis CI, test against Stockfish 6, improved test coverage amd various minor clean-
ups.

New in v0.8.0

• Implement Syzygy endgame tablebase probing. https://syzygy-tables.info is an example project that provides
a public API using the new features.
• The interface for aynchronous UCI command has changed to mimic concurrent.futures. is_done() is now just
done(). Callbacks will receive the command object as a single argument instead of the result. The result property
and wait() have been removed in favor of a synchronously waiting result() method.
• The result of the stop and go UCI commands are now named tuples (instead of just normal tuples).
• Add alias Board for Bitboard.
• Fixed race condition during UCI engine startup. Lines received during engine startup sometimes needed to be
processed before the Engine object was fully initialized.

New in v0.7.0

• Implement UCI engine communication.


• Patch by Matthew Lai: Add caching for gameNode.board().

New in v0.6.0

• If there are comments in a game before the first move, these are now assigned to Game.comment instead of
Game.starting_comment. Game.starting_comment is ignored from now on. Game.starts_variation() is no
longer true. The first child node of a game can no longer have a starting comment. It is possible to have a
game with Game.comment set, that is otherwise completely empty.
• Fix export of games with variations. Previously the moves were exported in an unusual (i.e. wrong) order.
• Install gmpy2 or gmpy if you want to use slightly faster binary operations.
• Ignore superfluous variation opening brackets in PGN files.
• Add GameNode.san().
• Remove sparse_pop_count(). Just use pop_count().
• Remove next_bit(). Now use bit_scan().

58 Chapter 7. Contents
python-chess, Release 0.18.0

New in v0.5.0

• PGN parsing is now more robust: read_game() ignores invalid tokens. Still exceptions are going to be thrown
on illegal or ambiguous moves, but this behaviour can be changed by passing an error_handler argument.

>>> # Raises ValueError:


>>> game = chess.pgn.read_game(file_with_illegal_moves)

>>> # Silently ignores errors and continues parsing:


>>> game = chess.pgn.read_game(file_with_illegal_moves, None)

>>> # Logs the error, continues parsing:


>>> game = chess.pgn.read_game(file_with_illegal_moves, logger.exception)

If there are too many closing brackets this is now ignored.


Castling moves like 0-0 (with zeros) are now accepted in PGNs. The Bitboard.parse_san() method remains
strict as always, though.
Previously the parser was strictly following the PGN spefification in that empty lines terminate a game. So a
game like

[Event "?"]

{ Starting comment block }

1. e4 e5 2. Nf3 Nf6 *

would have ended directly after the starting comment. To avoid this, the parser will now look ahead until it finds
at least one move or a termination marker like *, 1-0, 1/2-1/2 or 0-1.
• Introduce a new function scan_headers() to quickly scan a PGN file for headers without having to parse the full
games.
• Minor testcoverage improvements.

New in v0.4.2

• Fix bug where pawn_moves_from() and consequently is_legal() weren’t handling en passant correctly. Thanks
to Norbert Naskov for reporting.

New in v0.4.1

• Fix is_fivefold_repitition(): The new fivefold repetition rule requires the repetitions to occur on alternating
consecutive moves.
• Minor testing related improvements: Close PGN files, allow running via setuptools.
• Add recently introduced features to README.

New in v0.4.0

• Introduce can_claim_draw(), can_claim_fifty_moves() and can_claim_threefold_repitition().

7.9. Changelog for python-chess 59


python-chess, Release 0.18.0

• Since the first of July 2014 a game is also over (even without claim by one of the players) if there were 75
moves without a pawn move or capture or a fivefold repetition. Let is_game_over() respect that. Introduce
is_seventyfive_moves() and is_fivefold_repitition(). Other means of ending a game take precedence.
• Threefold repetition checking requires efficient hashing of positions to build the table. So performance improve-
ments were needed there. The default polyglot compatible zobrist hashes are now built incrementally.
• Fix low level rotation operations l90(), l45() and r45(). There was no problem in core because correct versions
of the functions were inlined.
• Fix equality and inequality operators for Bitboard, Move and Piece. Also make them robust against comparisons
with incompatible types.
• Provide equality and inequality operators for SquareSet and polyglot.Entry.
• Fix return values of incremental arithmetical operations for SquareSet.
• Make polyglot.Entry a collections.namedtuple.
• Determine and improve test coverage.
• Minor coding style fixes.

New in v0.3.1

• Bitboard.status() now correctly detects STATUS_INVALID_EP_SQUARE, instead of errors or false reports.


• Polyglot opening book reader now correctly handles knight underpromotions.
• Minor coding style fixes, including removal of unused imports.

New in v0.3.0

• Rename property half_moves of Bitboard to halfmove_clock.


• Rename property ply of Bitboard to fullmove_number.
• Let PGN parser handle symbols like !, ?, !? and so on by converting them to NAGs.
• Add a human readable string representation for Bitboards.

>>> print(chess.Bitboard())
r n b q k b n r
p p p p p p p p
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
P P P P P P P P
R N B Q K B N R

• Various documentation improvements.

New in v0.2.0

• Implement PGN parsing and writing.


• Hugely improve test coverage and use Travis CI for continuous integration and testing.
• Create an API documentation.

60 Chapter 7. Contents
python-chess, Release 0.18.0

• Improve Polyglot opening-book handling.

New in v0.1.0

Apply the lessons learned from the previous releases, redesign the API and implement it in pure Python.

New in v0.0.4

Implement the basics in C++ and provide bindings for Python. Obviously performance was a lot better - but at the
expense of having to compile code for the target platform.

Pre v0.0.4

First experiments with a way too slow pure Python API, creating way too many objects for basic operations.

7.9. Changelog for python-chess 61


python-chess, Release 0.18.0

62 Chapter 7. Contents
CHAPTER 8

Indices and tables

• genindex
• search

63
python-chess, Release 0.18.0

64 Chapter 8. Indices and tables


Index

A chess.BISHOP (built-in variable), 17


accept() (chess.pgn.Game method), 29 chess.BLACK (built-in variable), 17
accept() (chess.pgn.GameNode method), 30 chess.FILE_NAMES (built-in variable), 18
add() (chess.SquareSet method), 27 chess.G8 (built-in variable), 17
add_line() (chess.pgn.GameNode method), 30 chess.H8 (built-in variable), 17
add_main_variation() (chess.pgn.GameNode method), 30 chess.KING (built-in variable), 17
add_variation() (chess.pgn.GameNode method), 30 chess.KNIGHT (built-in variable), 17
attackers() (chess.Board method), 20 chess.PAWN (built-in variable), 17
attacks() (chess.Board method), 20 chess.POLYGLOT_RANDOM_ARRAY (built-in vari-
author (Engine attribute), 38 able), 35
chess.QUEEN (built-in variable), 17
B chess.RANK_NAMES (built-in variable), 18
chess.ROOK (built-in variable), 17
BaseBoard (class in chess), 25
chess.SQUARE_NAMES (built-in variable), 18
BaseVisitor (class in chess.pgn), 32
chess.SQUARES (built-in variable), 18
begin_game() (chess.pgn.BaseVisitor method), 32
chess.WHITE (built-in variable), 17
begin_headers() (chess.pgn.BaseVisitor method), 32
chess960 (Board attribute), 20
begin_variation() (chess.pgn.BaseVisitor method), 32
chess960_pos() (chess.BaseBoard method), 26
Board (class in chess), 19
chess960_pos() (chess.Board method), 23
board() (chess.pgn.Game method), 28
choice() (chess.polyglot.MemoryMappedReader
board() (chess.pgn.GameNode method), 29
method), 34
board() (in module chess.svg), 45
clean_castling_rights() (chess.Board method), 24
board_fen() (chess.BaseBoard method), 26
clear() (chess.Board method), 20
C clear_board() (chess.BaseBoard method), 25
clear_stack() (chess.Board method), 20
can_claim_draw() (chess.Board method), 22 close() (chess.gaviota.PythonTablebases method), 36
can_claim_fifty_moves() (chess.Board method), 22 close() (chess.polyglot.MemoryMappedReader method),
can_claim_threefold_repetition() (chess.Board method), 34
22 close() (chess.syzygy.Tablebases method), 38
castling_rights (Board attribute), 19 color (Piece attribute), 18
chess.A1 (built-in variable), 17 comment (GameNode attribute), 29
chess.B1 (built-in variable), 17 copy() (chess.BaseBoard method), 26
chess.BB_ALL (built-in variable), 28 cp (Score attribute), 42
chess.BB_BACKRANKS (built-in variable), 28 cpuload() (chess.uci.InfoHandler method), 43
chess.BB_DARK_SQUARES (built-in variable), 28 currline() (chess.uci.InfoHandler method), 44
chess.BB_FILES (built-in variable), 28 currmove() (chess.uci.InfoHandler method), 43
chess.BB_LIGHT_SQUARES (built-in variable), 28 currmovenumber() (chess.uci.InfoHandler method), 43
chess.BB_RANKS (built-in variable), 28
chess.BB_SQUARES (built-in variable), 28 D
chess.BB_VOID (built-in variable), 28
debug() (chess.uci.Engine method), 39

65
python-chess, Release 0.18.0

default (Option attribute), 44 has_variation() (chess.pgn.GameNode method), 30


demote() (chess.pgn.GameNode method), 30 hashfull() (chess.uci.InfoHandler method), 43
depth() (chess.uci.InfoHandler method), 43 headers (Game attribute), 28
discard() (chess.SquareSet method), 27
I
E info (InfoHandler attribute), 42
empty() (chess.BaseBoard class method), 26 InfoHandler (class in chess.uci), 42
empty() (chess.Board class method), 25 is_alive() (chess.uci.Engine method), 39
end() (chess.pgn.GameNode method), 29 is_attacked_by() (chess.Board method), 20
end_game() (chess.pgn.BaseVisitor method), 33 is_capture() (chess.Board method), 24
end_headers() (chess.pgn.BaseVisitor method), 32 is_castling() (chess.Board method), 24
end_variation() (chess.pgn.BaseVisitor method), 32 is_check() (chess.Board method), 21
Engine (class in chess.uci), 38, 39 is_checkmate() (chess.Board method), 22
Entry (class in chess.polyglot), 34 is_en_passant() (chess.Board method), 24
ep_square (Board attribute), 19 is_end() (chess.pgn.GameNode method), 29
epd() (chess.Board method), 23 is_fivefold_repetition() (chess.Board method), 22
errors (Game attribute), 28 is_game_over() (chess.Board method), 21
is_insufficient_material() (chess.Board method), 22
F is_into_check() (chess.Board method), 21
fen() (chess.Board method), 22 is_kingside_castling() (chess.Board method), 24
FileExporter (class in chess.pgn), 33 is_main_line() (chess.pgn.GameNode method), 29
find() (chess.polyglot.MemoryMappedReader method), is_main_variation() (chess.pgn.GameNode method), 29
34 is_pinned() (chess.Board method), 21
find_all() (chess.polyglot.MemoryMappedReader is_queenside_castling() (chess.Board method), 24
method), 34 is_seventyfive_moves() (chess.Board method), 22
find_variant() (in module chess.variant), 46 is_stalemate() (chess.Board method), 22
from_board() (chess.pgn.Game class method), 29 is_valid() (chess.Board method), 25
from_chess960_pos() (chess.BaseBoard class method), is_variant_draw() (chess.Board method), 21
26 is_variant_end() (chess.Board method), 21
from_epd() (chess.Board class method), 25 is_variant_loss() (chess.Board method), 21
from_square (Move attribute), 18 is_variant_win() (chess.Board method), 21
from_square() (chess.SquareSet class method), 27 is_zeroing() (chess.Board method), 24
from_symbol() (chess.Piece class method), 18 isready() (chess.uci.Engine method), 39
from_uci() (chess.Move class method), 19
fullmove_number (Board attribute), 19 K
key (Entry attribute), 34
G kill() (chess.uci.Engine method), 39
Game (class in chess.pgn), 28 king() (chess.BaseBoard method), 26
GameModelCreator (class in chess.pgn), 33
GameNode (class in chess.pgn), 29 L
go() (chess.uci.Engine method), 40 learn (Entry attribute), 34
legal_moves (Board attribute), 20
H lowerbound (Score attribute), 42
halfmove_clock (Board attribute), 20
handle_error() (chess.pgn.BaseVisitor method), 33 M
handle_error() (chess.pgn.GameModelCreator method), main_line() (chess.pgn.GameNode method), 30
33 mate (Score attribute), 42
has_castling_rights() (chess.Board method), 24 max (Option attribute), 44
has_chess960_castling_rights() (chess.Board method), 25 MemoryMappedReader (class in chess.polyglot), 34
has_kingside_castling_rights() (chess.Board method), 25 min (Option attribute), 44
has_legal_en_passant() (chess.Board method), 22 Move (class in chess), 18
has_queenside_castling_rights() (chess.Board method), move (GameNode attribute), 29
25 move() (chess.polyglot.Entry method), 34

66 Index
python-chess, Release 0.18.0

move_stack (Board attribute), 20 probe_wdl() (chess.gaviota.PythonTablebases method),


multipv() (chess.uci.InfoHandler method), 43 35
probe_wdl() (chess.syzygy.Tablebases method), 37
N process (Engine attribute), 38
NAG_BLUNDER (in module chess.pgn), 33 promote() (chess.pgn.GameNode method), 30
NAG_BRILLIANT_MOVE (in module chess.pgn), 33 promote_to_main() (chess.pgn.GameNode method), 30
NAG_DUBIOUS_MOVE (in module chess.pgn), 34 promotion (Move attribute), 18
NAG_GOOD_MOVE (in module chess.pgn), 33 pseudo_legal_moves (Board attribute), 20
NAG_MISTAKE (in module chess.pgn), 33 push() (chess.Board method), 22
NAG_SPECULATIVE_MOVE (in module chess.pgn), 33 push_san() (chess.Board method), 24
nags (GameNode attribute), 29 push_uci() (chess.Board method), 24
name (Engine attribute), 38 pv() (chess.uci.InfoHandler method), 43
name (Option attribute), 44 PythonTablebases (class in chess.gaviota), 35
NativeTablebases (class in chess.gaviota), 36
nodes() (chess.uci.InfoHandler method), 43 Q
nps() (chess.uci.InfoHandler method), 43 quit() (chess.uci.Engine method), 41
null() (chess.Move class method), 19
R
O raw_move (Entry attribute), 34
on_bestmove() (chess.uci.InfoHandler method), 44 read_game() (in module chess.pgn), 30
on_go() (chess.uci.InfoHandler method), 44 refutation() (chess.uci.InfoHandler method), 43
open_directory() (chess.gaviota.PythonTablebases remove() (chess.SquareSet method), 27
method), 35 remove_piece_at() (chess.BaseBoard method), 26
open_directory() (chess.syzygy.Tablebases method), 37 remove_variation() (chess.pgn.GameNode method), 30
open_reader() (in module chess.polyglot), 34 reset() (chess.Board method), 20
open_tablebases() (in module chess.gaviota), 35 result() (chess.Board method), 22
open_tablebases() (in module chess.syzygy), 36 result() (chess.pgn.BaseVisitor method), 33
open_tablebases_native() (in module chess.gaviota), 36 result() (chess.pgn.GameModelCreator method), 33
Option (class in chess.uci), 44 return_code (Engine attribute), 39
options (Engine attribute), 38 root() (chess.pgn.GameNode method), 29

P S
parent (GameNode attribute), 29 san() (chess.Board method), 23
parse_san() (chess.Board method), 24 san() (chess.pgn.GameNode method), 29
parse_uci() (chess.Board method), 24 scan_headers() (in module chess.pgn), 31
peek() (chess.Board method), 22 scan_offsets() (in module chess.pgn), 31
Piece (class in chess), 18 Score (class in chess.uci), 42
piece() (in module chess.svg), 45 score() (chess.uci.InfoHandler method), 43
piece_at() (chess.BaseBoard method), 26 seldepth() (chess.uci.InfoHandler method), 43
piece_type (Piece attribute), 18 set_board_fen() (chess.BaseBoard method), 26
piece_type_at() (chess.BaseBoard method), 26 set_castling_fen() (chess.Board method), 23
pieces() (chess.BaseBoard method), 25 set_chess960_pos() (chess.BaseBoard method), 26
pin() (chess.Board method), 21 set_epd() (chess.Board method), 23
ponderhit() (chess.uci.Engine method), 41 set_fen() (chess.Board method), 23
pop() (chess.Board method), 22 set_piece_at() (chess.BaseBoard method), 26
pop() (chess.SquareSet method), 27 setoption() (chess.uci.Engine method), 39
popen_engine() (in module chess.uci), 38 setup() (chess.pgn.Game method), 29
position() (chess.uci.Engine method), 40 shredder_fen() (chess.Board method), 23
post_info() (chess.uci.InfoHandler method), 44 spur_spawn_engine() (in module chess.uci), 38
pre_info() (chess.uci.InfoHandler method), 44 square() (in module chess), 18
probe_dtm() (chess.gaviota.PythonTablebases method), square_distance() (in module chess), 18
35 square_file() (in module chess), 18
probe_dtz() (chess.syzygy.Tablebases method), 37 square_mirror() (in module chess), 18

Index 67
python-chess, Release 0.18.0

square_rank() (in module chess), 18


SquareSet (class in chess), 26
STARTING_BOARD_FEN (in module chess), 19
starting_comment (GameNode attribute), 29
STARTING_FEN (in module chess), 19
starts_variation() (chess.pgn.GameNode method), 29
status() (chess.Board method), 25
stop() (chess.uci.Engine method), 41
string() (chess.uci.InfoHandler method), 43
StringExporter (class in chess.pgn), 33
symbol() (chess.Piece method), 18

T
Tablebases (class in chess.syzygy), 36
tbhits() (chess.uci.InfoHandler method), 43
terminate() (chess.uci.Engine method), 39
terminated (Engine attribute), 39
time() (chess.uci.InfoHandler method), 43
to_square (Move attribute), 18
turn (Board attribute), 19
type (Option attribute), 44

U
uci() (chess.Board method), 24
uci() (chess.Move method), 19
uci() (chess.uci.Engine method), 39
ucinewgame() (chess.uci.Engine method), 40
uciok (Engine attribute), 38
unicode_symbol() (chess.Piece method), 18
upperbound (Score attribute), 42

V
var (Option attribute), 44
variation() (chess.pgn.GameNode method), 30
variation_san() (chess.Board method), 23
variations (GameNode attribute), 29
visit_comment() (chess.pgn.BaseVisitor method), 32
visit_header() (chess.pgn.BaseVisitor method), 32
visit_move() (chess.pgn.BaseVisitor method), 32
visit_nag() (chess.pgn.BaseVisitor method), 32
visit_result() (chess.pgn.BaseVisitor method), 32

W
was_into_check() (chess.Board method), 21
weight (Entry attribute), 34
weighted_choice() (chess.polyglot.MemoryMappedReader
method), 34

Z
zobrist_hash() (chess.Board method), 25

68 Index

You might also like