Source code for lczerolens.play.game

"""Preproces functions for chess games."""

from dataclasses import dataclass
from typing import Any, Dict, List, Optional, Union

from datasets import Features, Value, Sequence

from lczerolens.board import LczeroBoard

[docs] GAME_DATASET_FEATURES = Features( { "gameid": Value("string"), "moves": Value("string"), } )
[docs] BOARD_DATASET_FEATURES = Features( { "gameid": Value("string"), "moves": Sequence(Value("string")), "fen": Value("string"), } )
@dataclass
[docs] class Game:
[docs] gameid: str
[docs] moves: List[str]
[docs] book_exit: Optional[int] = None
@classmethod
[docs] def from_dict(cls, obj: Dict[str, str]) -> "Game": if "moves" not in obj: ValueError("The dict should contain `moves`.") if "gameid" not in obj: ValueError("The dict should contain `gameid`.") *pre, post = obj["moves"].split("{ Book exit }") if pre: if len(pre) > 1: raise ValueError("More than one book exit") (pre,) = pre parsed_pre_moves = [m for m in pre.split() if not m.endswith(".")] book_exit = len(parsed_pre_moves) else: parsed_pre_moves = [] book_exit = None parsed_moves = parsed_pre_moves + [m for m in post.split() if not m.endswith(".")] return cls( gameid=obj["gameid"], moves=parsed_moves, book_exit=book_exit, )
[docs] def to_boards( self, n_history: int = 0, skip_book_exit: bool = False, skip_first_n: int = 0, output_dict=True, ) -> List[Union[Dict[str, Any], LczeroBoard]]: working_board = LczeroBoard() if skip_first_n > 0 or (skip_book_exit and (self.book_exit is not None)): boards = [] else: if output_dict: boards = [ { "fen": working_board.fen(), "moves": [], "gameid": self.gameid, } ] else: boards = [working_board.copy(stack=n_history)] for i, move in enumerate(self.moves[:-1]): # skip the last move as it can be over working_board.push_san(move) if (i < skip_first_n) or (skip_book_exit and (self.book_exit is not None) and (i < self.book_exit)): continue if output_dict: save_board = working_board.copy(stack=n_history) boards.append( { "fen": save_board.root().fen(), "moves": [move.uci() for move in save_board.move_stack], "gameid": self.gameid, } ) else: boards.append(working_board.copy(stack=n_history)) return boards
@staticmethod
[docs] def board_collate_fn(batch): boards = [] for element in batch: board = LczeroBoard(element["fen"]) for move in element["moves"]: board.push_san(move) boards.append(board) return boards, {}