Example #1
0
 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
Example #2
0
def cook_mate(engine: SimpleEngine, node: ChildNode, winner: Color) -> Optional[List[Move]]:
    
    board = node.board()

    if board.is_game_over():
        return []

    if board.turn == winner:
        pair = get_next_pair(engine, node, winner)
        if not pair:
            return None
        if pair.best.score < mate_soon:
            logger.debug("Best move is not a mate, we're probably not searching deep enough")
            return None
        move = pair.best.move
    else:
        next = get_next_move(engine, node, mate_defense_limit)
        if not next:
            return None
        move = next

    follow_up = cook_mate(engine, node.add_main_variation(move), winner)

    if follow_up is None:
        return None

    return [move] + follow_up
Example #3
0
def cook_mate(engine: SimpleEngine, node: ChildNode,
              winner: Color) -> Optional[List[Move]]:

    if node.board().is_game_over():
        return []

    pair = get_next_move(engine, node, winner)

    if not pair:
        return None

    next = pair.best

    if next.score < mate_soon:
        logger.debug(
            "Best move is not a mate, we're probably not searching deep enough"
        )
        return None

    follow_up = cook_mate(engine, node.add_main_variation(next.move), winner)

    if follow_up is None:
        return None

    return [next.move] + follow_up
Example #4
0
def cook_advantage(engine: SimpleEngine, node: ChildNode,
                   winner: Color) -> Optional[List[NextMovePair]]:

    if node.board().is_repetition(2):
        logger.debug("Found repetition, canceling")
        return None

    next = get_next_move(engine, node, winner)

    if not next:
        logger.debug("No next move")
        return []

    if next.best.score.is_mate():
        logger.debug("Expected advantage, got mate?!")
        return None

    if next.best.score < Cp(200):
        logger.debug("Not winning enough, aborting")
        return None

    follow_up = cook_advantage(engine, node.add_main_variation(next.best.move),
                               winner)

    if follow_up is None:
        return None

    return [next] + follow_up
Example #5
0
def analyze_position(server: Server, engine: SimpleEngine, node: ChildNode, prev_score: Score, current_eval: PovScore, tier: int) -> Union[Puzzle, Score]:

    board = node.board()
    winner = board.turn
    score = current_eval.pov(winner)

    if board.legal_moves.count() < 2:
        return score

    game_url = node.game().headers.get("Site")

    logger.debug("{} {} to {}".format(node.ply(), node.move.uci() if node.move else None, score))

    if prev_score > Cp(300) and score < mate_soon:
        logger.debug("{} Too much of a winning position to start with {} -> {}".format(node.ply(), prev_score, score))
        return score
    if is_up_in_material(board, winner):
        logger.debug("{} already up in material {} {} {}".format(node.ply(), winner, material_count(board, winner), material_count(board, not winner)))
        return score
    elif score >= Mate(1) and tier < 3:
        logger.debug("{} mate in one".format(node.ply()))
        return score
    elif score > mate_soon:
        logger.debug("Mate {}#{} Probing...".format(game_url, node.ply()))
        if server.is_seen_pos(node):
            logger.debug("Skip duplicate position")
            return score
        mate_solution = cook_mate(engine, copy.deepcopy(node), winner)
        if mate_solution is None or (tier == 1 and len(mate_solution) == 3):
            return score
        return Puzzle(node, mate_solution, 999999999)
    elif score >= Cp(200) and win_chances(score) > win_chances(prev_score) + 0.6:
        if score < Cp(400) and material_diff(board, winner) > -1:
            logger.debug("Not clearly winning and not from being down in material, aborting")
            return score
        logger.debug("Advantage {}#{} {} -> {}. Probing...".format(game_url, node.ply(), prev_score, score))
        if server.is_seen_pos(node):
            logger.debug("Skip duplicate position")
            return score
        puzzle_node = copy.deepcopy(node)
        solution : Optional[List[NextMovePair]] = cook_advantage(engine, puzzle_node, winner)
        server.set_seen(node.game())
        if not solution:
            return score
        while len(solution) % 2 == 0 or not solution[-1].second:
            if not solution[-1].second:
                logger.debug("Remove final only-move")
            solution = solution[:-1]
        if not solution or len(solution) == 1 :
            logger.debug("Discard one-mover")
            return score
        if tier < 3 and len(solution) == 3:
            logger.debug("Discard two-mover")
            return score
        cp = solution[len(solution) - 1].best.score.score()
        return Puzzle(node, [p.best.move for p in solution], 999999998 if cp is None else cp)
    else:
        return score
Example #6
0
def is_advanced_pawn_move(node: ChildNode) -> bool:
    if node.move.promotion:
        return True
    if moved_piece_type(node) != chess.PAWN:
        return False
    to_rank = square_rank(node.move.to_square)
    return to_rank < 3 if node.turn() else to_rank > 4
Example #7
0
def get_next_pair(engine: SimpleEngine, node: ChildNode,
                  winner: Color) -> Optional[NextMovePair]:
    pair = get_next_move_pair(engine, node, winner, pair_limit)
    if node.board().turn == winner and not is_valid_attack(pair, engine):
        logger.debug("No valid attack {}".format(pair))
        return None
    return pair
Example #8
0
def cook_advantage(engine: SimpleEngine, node: ChildNode, winner: Color) -> Optional[List[NextMovePair]]:
    
    board = node.board()

    if board.is_repetition(2):
        logger.debug("Found repetition, canceling")
        return None

    pair = get_next_pair(engine, node, winner)
    if not pair:
        return []
    if pair.best.score < Cp(200):
        logger.debug("Not winning enough, aborting")
        return None

    follow_up = cook_advantage(engine, node.add_main_variation(pair.best.move), winner)

    if follow_up is None:
        return None

    return [pair] + follow_up
Example #9
0
def get_next_move(engine: SimpleEngine, node: ChildNode,
                  winner: Color) -> Optional[NextMovePair]:
    board = node.board()
    pair = get_next_move_pair(engine, node, winner, get_move_limit)
    logger.debug("{} {} {}".format(
        "attack" if board.turn == winner else "defense", pair.best,
        pair.second))
    if board.turn == winner and not is_valid_attack(pair, engine):
        logger.debug("No valid attack {}".format(pair))
        return None
    if board.turn != winner and not is_valid_defense(pair):
        logger.debug("No valid defense {}".format(pair))
        return None
    return pair
Example #10
0
def get_next_move(engine: SimpleEngine, node: ChildNode, limit: chess.engine.Limit) -> Optional[Move]:
    result = engine.play(node.board(), limit = limit)
    return result.move if result else None
Example #11
0
def moved_piece_type(node: ChildNode) -> chess.PieceType:
    pt = node.board().piece_type_at(node.move.to_square)
    assert pt
    return pt
Example #12
0
def is_very_advanced_pawn_move(node: ChildNode) -> bool:
    if not is_advanced_pawn_move(node):
        return False
    to_rank = square_rank(node.move.to_square)
    return to_rank < 2 if node.turn() else to_rank > 5