예제 #1
0
 def _parse_game(game: Game) -> List[str]:
     positions: List[str] = []
     board = game.board()
     for move in game.mainline_moves():
         board.push(move)
         positions.append(board.fen())
     return positions
예제 #2
0
def pgn_game_to_serializable_game(pgn_game: pgn.Game) -> SerializableGame:
    current_index = 1
    all_positions: List[SerializablePosition] = []

    def parse_position(pgn_position: pgn.ChildNode,
                       is_mainline: bool) -> SerializablePosition:
        nonlocal current_index
        nonlocal all_positions
        index = current_index
        current_index += 1
        next_pos_index = None
        if pgn_position.variations:
            next_pos_index = parse_position(pgn_position.variations[0],
                                            True).index
        variations_indexes = []
        if len(pgn_position.variations) > 1:
            variations_indexes = [
                parse_position(p, False).index
                for i, p in enumerate(pgn_position.variations) if i > 0
            ]
        position = SerializablePosition(
            index=index,
            next_position_index=next_pos_index,
            variations_indexes=variations_indexes,
            nags=list(pgn_position.nags),
            fen=pgn_position.board().fen(),
            comment=pgn_position.comment,
            commentBefore=pgn_position.starting_comment,
            san=pgn_position.san(),
            is_mainline=is_mainline,
            move=Move(from_square=square_name(pgn_position.move.from_square),
                      to=square_name(pgn_position.move.to_square),
                      promotion=pgn_position.move.promotion))
        all_positions.insert(0, position)
        return position

    first_pos = SerializablePosition(index=0,
                                     fen=pgn_game.board().fen(),
                                     is_mainline=True,
                                     nags=[],
                                     san="",
                                     variations_indexes=[],
                                     next_position_index=1)
    all_positions.append(first_pos)
    for i, position in enumerate(pgn_game.variations):
        if i != 0:
            first_pos.variations_indexes.append(current_index)
        parse_position(position, i == 0)
    headers: Dict[str, str] = {}
    for key in pgn_game.headers.keys():
        headers[key] = pgn_game.headers[key]
    game = SerializableGame(
        headers=headers,
        comment=pgn_game.starting_comment,
        positions=all_positions,
    )
    return game
예제 #3
0
    def analyze_game(self, game: Game, tier: int) -> Optional[Puzzle]:

        logger.debug(f'Analyzing tier {tier} {game.headers.get("Site")}...')

        prev_score: Score = Cp(20)
        seen_epds: Set[str] = set()
        board = game.board()
        skip_until_irreversible = False

        for node in game.mainline():
            if skip_until_irreversible:
                if board.is_irreversible(node.move):
                    skip_until_irreversible = False
                    seen_epds.clear()
                else:
                    board.push(node.move)
                    continue

            current_eval = node.eval()

            if not current_eval:
                logger.debug("Skipping game without eval on ply {}".format(
                    node.ply()))
                return None

            board.push(node.move)
            epd = board.epd()
            if epd in seen_epds:
                skip_until_irreversible = True
                continue
            seen_epds.add(epd)

            if board.castling_rights != maximum_castling_rights(board):
                continue

            result = self.analyze_position(node, prev_score, current_eval,
                                           tier)

            if isinstance(result, Puzzle):
                return result

            prev_score = -result

        logger.debug("Found nothing from {}".format(game.headers.get("Site")))

        return None