Changes:
- Drop support for Python 3.7, which has reached its end of life.
chess.engine.EventLoopPolicy
is no longer needed and now merely an alias for the default event loop policy.- If available and requested via
setpgrp
, useprocess_group
support from Python 3.11 for engine processes. - No longer eagerly reject 8 piece positions in
chess.syzygy
, so that some 8 piece positions with decisive captures can be probed successfully. - The string wrapper returned by
chess.svg
functions now also implements_repr_html_
. - Significant changes to
chess.engine
internals:chess.engine.BaseCommand
methods other than the constructor no longer receiveengine: Protocol
. - Significant changes to board state internals: Subclasses of
chess.Board
can no longer hook into board state recording/restoration and need to override relevant methods instead (clear_stack
,copy
,root
,push
,pop
).
New features:
- Add
chess.pgn.Game.time_control()
and related data models. - Add model
sf16.1
forchess.engine.Score.wdl()
, the new default.
Bugfixes:
- Fix unsolicited engine output may cause assertion errors with regard to command states.
- Fix handling of whitespace in UCI engine communication.
- For
chess.Board.epd()
andchess.Board.set_epd()
, require that EPD opcodes start with a letter.
New features:
- Use
chess.engine.Opponent
to send opponent information to engines. - Inform engines about the game result using
chess.engine.Protocol.send_game_result()
. - Add
chess.engine.Limit.clock_id
. - Add
chess.svg.board(..., borders=True)
. - Avoid rendering background behind SVG boards to better support transparency.
- Add
chess.pgn.BaseVisitor.begin_parse_san()
. - Introduce new distance metrics
chess.square_manhattan_distance()
andchess.square_knight_distance()
.
Bugfixes:
- Fix
chess.pgn.GameNode.eval()
sometimes off by one centipawn. - Fix handling of additional spaces between UCI option tokens.
- Handle implicit XBoard engine resignation via output like
0-1 {White resigns}
.
Changes:
- Add model
sf16
forchess.engine.Score.wdl()
, the new default. - Update
lichess
WDL model. - Keep PGN headers that do not belong to the Seven Tag Roster in insertion order.
- Halve the number of open file descriptors maintained by tablebases and opening books.
- Reduce verbosity of logged
chess.pgn
errors.
Bugfixes:
- Fix
PovScore.wdl()
ignoredmodel
andply
parameters. chess.syzygy
: Check that board matches tablebase variant.
New features:
- Add model
sf15.1
forchess.engine.Score.wdl()
. - Raise more specific exceptions:
chess.IllegalMoveError
,chess.AmbiguousMoveError
, andchess.InvalidMoveError
.
Bugfixes:
- Fix some valid characters were not accepted in PGN tag names.
Changes:
- Skip over syntactically invalid PGN tags.
- Detect Antichess insufficient material with two opposing knights.
New features:
- Add
chess.Board.unicode(..., orientation=chess.WHITE)
.
Bugfixes:
- Fix recursive Crazyhouse move generation sometimes failing with
with
RuntimeError
. - Fix rendering of black pawn SVG on dark background.
New features:
- Add
chess.engine.AnalysisResult.would_block()
.
Bugfixes:
- Reject pawn capture SAN if the original file is not specified, e.g.,
d5
will no longer matchcxd5
.
Changes:
- Tweak handling of whitespace in PGN comments: When parsing, any leading and trailing whitespace (beyond one space) is preserved. When joining multiple PGN comments, they are now separated with a space instead of a newline character. When removing annotations from comments, leftover whitespace is avoided.
New features:
- Add model
sf15
forchess.engine.Score.wdl()
.
Bugfixes:
- Expand position validation to detect check conflicting with en passant square.
New features:
- Add
chess.svg.board(..., fill=...)
. - Let
chess.svg.board()
add ASCII board as description of SVG. - Add hint when engine process dies due to illegal instruction.
Bugfixes:
- Fix
SquareSet.issuperset()
andSquareSet.issubset()
by swapping their respective implementations.
New features:
- Read and write PGN comments like
[%emt 0:05:21]
.
New features:
- Add new models for
chess.engine.Score.wdl()
:sf
(the new default) andsf14
. - Add
chess.Board.piece_map()
.
Bugfixes:
chess.pgn
: Fix skipping with nested variations.chess.svg
: Make check gradient compatible with QtSvg.
Bugfixes:
- Make
chess.engine.SimpleEngine.play(..., draw_offered=True)
available. Previously only added forchess.engine.Protocol
.
New features:
- Allow offering a draw to XBoard engines using
chess.engine.Protocol.play(..., draw_offered=True)
. - Now detects insufficient material in Horde. Thanks @stevepapazis!
Changes:
chess.engine.popen_engine(..., setpgrp=True)
on Windows now mergesCREATE_NEW_PROCESS_GROUP
intocreationflags
instead of overriding. On Unix it now usesstart_new_session
instead of callingsetpgrp
inpreexec_fn
.- Declare that
chess.svg
produces SVG Tiny 1.2, and prepare SVG 2 forwards compatibility.
Bugfixes:
- Fix slightly off-center pawns in
chess.svg
. - Fix typing error in Python 3.10 (due to added
int.bit_count
).
Bugfixes:
- Fixed typing of
chess.pgn.Mainline.__reversed__()
. It is now a generator, andchess.pgn.ReverseMainline
has been removed. This is a breaking change but a required bugfix. - Implement UCI ponderhit for consecutive calls to
chess.engine.Protocol.play(..., ponder=True)
. Previously, the pondering search was always stopped and restarted. - Provide the full move stack, not just the position, for UCI pondering.
- Fixed XBoard level in sudden death games.
- Ignore trailing space after ponder move sent by UCI engine. Previously, such a move would be rejected.
- Prevent cancelling engine commands after they have already been cancelled or
completed. Some internals (
chess.engine.BaseCommand
) have been changed to accomplish this.
New features:
- Added
chess.Board.outcome()
. - Implement and accept usermove feature for XBoard engines.
Special thanks to @MarkZH for many of the engine related changes in this release!
New features:
- Let
chess.pgn.GameNode.eval()
accept PGN comments like[%eval 2.5,11]
, meaning 250 centipawns at depth 11. Usechess.pgn.GameNode.eval_depth()
andchess.pgn.GameNode.set_eval(..., depth)
to get and set the depth. - Read and write PGN comments with millisecond precision like
[%clk 1:23:45.678]
.
Changes:
- Recover from invalid UTF-8 sent by an UCI engine, by ignoring that (and only that) line.
Bugfixes:
- Fixed unintended collisions and optimized
chess.Piece.__hash__()
. - Fixed false-positive
chess.STATUS_IMPOSSIBLE_CHECK
if checkers are aligned with other king.
Changes:
- Also detect
chess.STATUS_IMPOSSIBLE_CHECK
if checker is aligned with en passant square and king.
New features:
- Implemented Lichess winning chance model for
chess.engine.Score
:score.wdl(model="lichess")
.
Bugfixes:
- Added a new reason for
board.status()
to be invalid:chess.STATUS_IMPOSSIBLE_CHECK
. This detects positions where two sliding pieces are giving check while also being aligned with the king on the same rank, file, or diagonal. Such positions are impossible to reach, break Stockfish, and maybe other engines.
Bugfixes:
chess.pgn.read_game()
now properly detects variant games with Chess960 castling rights (as well as mislabeled Standard Chess960 games). Previously, all castling moves in such games were rejected.
Changes:
Introduced
chess.pgn.ChildNode
, a subclass ofchess.pgn.GameNode
for all nodes other than the root node, and convertedchess.pgn.GameNode
to an abstract base class. This improves ergonomics in typed code.The change is backwards compatible if using only documented features. However, a notable undocumented feature is the ability to create dangling nodes. This is no longer possible. If you have been using this for subclassing, override
GameNode.add_variation()
instead ofGameNode.dangling_node()
. It is now the only method that creates child nodes.
Bugfixes:
- Removed broken
weakref
-based caching inchess.pgn.GameNode.board()
.
New features:
- Added
chess.pgn.GameNode.next()
.
Bugfixes:
- Fixed regression where releases were uploaded without the
py.typed
marker.
Changes:
The primary location for the published package is now https://pypi.org/project/chess/. Thanks to Kristian Glass for transferring the namespace.
The old https://pypi.org/project/python-chess/ will remain an alias that installs the package from the new location as a dependency (as recommended by PEP423).
ModuleNotFoundError: No module named 'chess'
after upgrading from previous versions? Runpip install --force-reinstall chess
(due to #680).
New features:
- Added
chess.Board.ply()
. - Added
chess.pgn.GameNode.ply()
andchess.pgn.GameNode.turn()
. - Added
chess.engine.PovWdl
,chess.engine.Wdl
, and conversions from scores:chess.engine.PovScore.wdl()
,chess.engine.Score.wdl()
. - Added
chess.engine.Score.score(*, mate_score: int) -> int
overload.
Changes:
- The
PovScore
returned bychess.pgn.GameNode.eval()
is now always relative to the side to move. The ambiguity around[%eval #0]
has been resolved toMate(-0)
. This makes sense, given that the authors of the specification probably had standard chess in mind (where a game-ending move is always a loss for the opponent). Previously, this would be parsed asNone
. - Typed
chess.engine.InfoDict["wdl"]
as the newchess.engine.PovWdl
, rather thanTuple[int, int, int]
. The new type is backwards compatible, but it is recommended to use its documented fields and methods instead. - Removed
chess.engine.PovScore.__str__()
. String representation falls back to__repr__
. - The
en_passant
parameter ofchess.Board.fen()
andchess.Board.epd()
is now typed asLiteral["legal", "fen", "xfen"]
rather thanstr
.
New features:
- Added
chess.svg.board(..., orientation)
. This is a more idiomatic way to set the board orientation thanflipped
. - Added
chess.svg.Arrow.pgn()
andchess.svg.Arrow.from_pgn()
.
Changes:
- Further relaxed
chess.Board.parse_san()
. Now accepts fully specified moves likee2e4
, even if that is not a pawn move, castling notation with zeros, null moves in UCI notation, and null moves in XBoard notation.
Bugfixes:
chess.svg
: Restored SVG Tiny compatibility by splitting colors like#rrggbbaa
into a solid color and opacity.
See CHANGELOG-OLD.rst
for changes up to v1.0.0.