Changelog for python-chess
==========================

This project is pretty young and maturing only slowly. At the current stage 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.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`.

* 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:

  .. code:: python

      >>> 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.

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:

  .. code:: python

      >>> 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 kingside 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

  .. code:: python

      >>> with info_handler as info:
      ...     if 1 in info["score"]:
      ...         cp = info["score"][1].cp

  where you were previously using

  .. code:: python

      >>> 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 `PseudoLegalMoveGenerator.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 standard chess castling rules.
  Added `Board.is_valid(allow_chess960=True)`.

* **Improved move generation using** `Shatranj-style direct lookup
  <http://arxiv.org/pdf/0704.3773.pdf>`_. **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#`.

* 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 <https://syzygy-tables.info/apidoc?fen=6N1/5KR1/2n5/8/8/8/2n5/1k6%20w%20-%20-%200%201>`_
  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()`.

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.

  .. code:: python

      >>> # Raises ValueError:
      >>> game = chess.pgn.read_game(file_with_illegal_moves)

  .. code:: python

      >>> # Silently ignores errors and continues parsing:
      >>> game = chess.pgn.read_game(file_with_illegal_moves, None)

  .. code:: python

      >>> # 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()`.

* 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 improvements 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.

  .. code:: python

      >>> 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.
* 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.
