rpdelaney-archive / python-chess-annotator

Reads chess games in PGN format and adds annotations using an engine
GNU General Public License v3.0
62 stars 29 forks source link

Intermittent TypeError in var_end_comment() on board = node.board() #3

Closed rpdelaney closed 8 years ago

rpdelaney commented 8 years ago

Intermittently, annotator.py will throw an exception at board = node.board() when using stockfish at very low time budgets. Example stacktrace:

Traceback (most recent call last):
  File "./annotator.py", line 640, in <module>
    main()
  File "./annotator.py", line 634, in main
    analyzed_game = analyze_game(game, args.time, args.engine)
  File "./annotator.py", line 575, in analyze_game
    add_annotation(node, judgment)
  File "./annotator.py", line 251, in add_annotation
    var_node.comment = var_end_comment(var_node, judgment["bestcomment"])
  File "./annotator.py", line 213, in var_end_comment
    board = node.board()
  File "/home/ryan/.local/lib/python3.5/site-packages/chess/pgn.py", line 116, in board
    board = self.parent.board(_cache=False)
  File "/home/ryan/.local/lib/python3.5/site-packages/chess/pgn.py", line 116, in board
    board = self.parent.board(_cache=False)
  File "/home/ryan/.local/lib/python3.5/site-packages/chess/pgn.py", line 116, in board
    board = self.parent.board(_cache=False)
  File "/home/ryan/.local/lib/python3.5/site-packages/chess/pgn.py", line 116, in board
    board = self.parent.board(_cache=False)
  File "/home/ryan/.local/lib/python3.5/site-packages/chess/pgn.py", line 116, in board
    board = self.parent.board(_cache=False)
  File "/home/ryan/.local/lib/python3.5/site-packages/chess/pgn.py", line 116, in board
    board = self.parent.board(_cache=False)
  File "/home/ryan/.local/lib/python3.5/site-packages/chess/pgn.py", line 116, in board
    board = self.parent.board(_cache=False)
  File "/home/ryan/.local/lib/python3.5/site-packages/chess/pgn.py", line 117, in board
    board.push(self.move)
  File "/home/ryan/.local/lib/python3.5/site-packages/chess/__init__.py", line 2088, in push
    self._set_piece_at(move.to_square, piece_type, self.turn)
  File "/home/ryan/.local/lib/python3.5/site-packages/chess/__init__.py", line 975, in _set_piece_at
    piece_index = (piece_type - 1) * 2
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'

The behavior is not exhibited with other engines tested (Toga II and senpai).

This bug seems to be indirectly caused by a bug in stockfish described here[1], where the UCI bestmove is sometimes different from the pv's first move. This can cause annotator.py to attempt to add illegal moves as an annotation, corrupting the working GameNode object and ultimately preventing python-chess from rendering a board on assignment.

rpdelaney commented 8 years ago

This issue raises the general concern that with any engine we can't guarantee that the UCI bestmove is == to the pv root move, although it should be. Furthermore, we always use the pv (not the bestmove) when adding annotations, and so that is what we should rely on. Therefore, we should fill judgment["bestmove"] with the pv root move instead of the engine bestmove.