Utilities

Provides functionality to:

  • Check whether a PGN has [%eval ...] tags for every half move

  • Generate analysis and decorate a PGN with [%eval ...] tags

game = chess.pgn.read_game(io.StringIO(pgn_string))

# If analysis is not present, add it
if not PGN(game).has_analysis():
      with chess.engine.SimpleEngine.popen_uci("/path/to/stockfish") as engine:
         game = PGN(game).add_analysis(engine, chess.engine.Limit(depth=18))

# Optionally store the new PGN to avoid having to generate analysis again
pgn_with_analysis = game.export()
with open("analysis.pgn", "w") as text_file:
   text_file.write(pgn_with_analysis)

Warning

Engine analysis is a CPU intensive operation, ensure that an appropriate limit is applied.

A depth limit of 18 provides a reasonable trade-off between accuracy and compute time.

Note

Once you have finished with the chess.engine.SimpleEngine instance it should be closed using the close() method, or alternatively use a with statement. Otherwise your program will not exit as expected.

class gifpgn.utils.PGN(pgn: Game)[source]

Bases: object

Class for working with [%eval ...] annotations

Parameters:

pgn (chess.pgn.Game) – An instance of chess.pgn.Game containing the PGN for analysis

acpl(max_eval: int = 1000) Dict[bool, int][source]

Calculate the average centipawn loss for each player.

Parameters:

max_eval (int) – The maximum evaluation to consider when calculating the ACPL, defaults to 1000

Raises:

MissingAnalysisError – PGN is not decorated with [%eval ...] annotations

Return Dict[chess.Color, int]:

Dictionary containing the ACPL for each player

add_analysis(engine: SimpleEngine, engine_limit: Limit) Game[source]

Calculates and adds [%eval ...] annotations to each half move in the PGN

Parameters:
export() str[source]

Output the current PGN

Return str:

has_analysis() bool[source]

Checks that every half move in the PGN has [%eval ...] annotations

Return bool:

True if every half move has [%eval ...] annotations, False otherwise