Ejemplo n.º 1
0
def deflection(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2][1:]:
        capture = node.parent.board().piece_at(node.move.to_square)
        if capture or node.move.promotion:
            piece = util.moved_piece_type(node)
            if capture and piece != KING and util.values[
                    capture.piece_type] > util.values[piece]:
                continue
            square = node.move.to_square
            prev_op_move = node.parent.move
            prev_player_move = node.parent.parent.move
            prev_player_capture = node.parent.parent.parent.board().piece_at(
                prev_player_move.to_square)
            if ((not prev_player_capture
                 or util.values[prev_player_capture.piece_type] <
                 util.moved_piece_type(node.parent.parent))
                    and (square != prev_op_move.to_square
                         and square != prev_player_move.to_square)
                    and (prev_op_move.to_square == prev_player_move.to_square)
                    and (square in node.parent.parent.board().attacks(
                        prev_op_move.from_square))
                    and (not square in node.parent.board().attacks(
                        prev_op_move.to_square))):
                return True
    return False
Ejemplo n.º 2
0
def deflection(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2][1:]:
        captured_piece = node.parent.board().piece_at(node.move.to_square)
        if captured_piece or node.move.promotion:
            capturing_piece = util.moved_piece_type(node)
            if captured_piece and util.king_values[
                    captured_piece.
                    piece_type] > util.king_values[capturing_piece]:
                continue
            square = node.move.to_square
            prev_op_move = node.parent.move
            assert (prev_op_move)
            grandpa = node.parent.parent
            assert isinstance(grandpa, ChildNode)
            prev_player_move = grandpa.move
            prev_player_capture = grandpa.parent.board().piece_at(
                prev_player_move.to_square)
            if ((not prev_player_capture
                 or util.values[prev_player_capture.piece_type] <
                 util.moved_piece_type(grandpa))
                    and square != prev_op_move.to_square
                    and square != prev_player_move.to_square
                    and (prev_op_move.to_square == prev_player_move.to_square
                         or grandpa.board().is_check()) and
                (square in grandpa.board().attacks(prev_op_move.from_square)
                 or node.move.promotion and square_file(node.move.to_square)
                 == square_file(prev_op_move.from_square)
                 and node.move.from_square in grandpa.board().attacks(
                     prev_op_move.from_square))
                    and (not square in node.parent.board().attacks(
                        prev_op_move.to_square))):
                return True
    return False
Ejemplo n.º 3
0
def en_passant(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2]:
        if (util.moved_piece_type(node) == PAWN and square_file(
                node.move.from_square) != square_file(node.move.to_square)
                and not node.parent.board().piece_at(node.move.to_square)):
            return True
    return False
Ejemplo n.º 4
0
def clearance(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2][1:]:
        board = node.board()
        if not node.parent.board().piece_at(node.move.to_square):
            piece = board.piece_at(node.move.to_square)
            if piece and piece.piece_type in util.ray_piece_types:
                prev = node.parent.parent
                assert prev
                prev_move = prev.move
                assert prev_move
                assert isinstance(node.parent, ChildNode)
                if (not prev_move.promotion
                        and prev_move.to_square != node.move.from_square
                        and prev_move.to_square != node.move.to_square
                        and not node.parent.board().is_check()
                        and (not board.is_check()
                             or util.moved_piece_type(node.parent) != KING)):
                    if (prev_move.from_square == node.move.to_square
                            or prev_move.from_square in SquareSet.between(
                                node.move.from_square, node.move.to_square)):
                        if prev.parent and not prev.parent.board().piece_at(
                                prev_move.to_square) or util.is_in_bad_spot(
                                    prev.board(), prev_move.to_square):
                            return True
    return False
Ejemplo n.º 5
0
def attraction(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1:]:
        if node.turn() == puzzle.pov:
            continue
        # 1. player moves to a square
        first_move_to = node.move.to_square
        opponent_reply = util.next_node(node)
        # 2. opponent captures on that square
        if opponent_reply and opponent_reply.move.to_square == first_move_to:
            attracted_piece = util.moved_piece_type(opponent_reply)
            if attracted_piece in [KING, QUEEN, ROOK]:
                attracted_to_square = opponent_reply.move.to_square
                next_node = util.next_node(opponent_reply)
                if next_node:
                    attackers = next_node.board().attackers(
                        puzzle.pov, attracted_to_square)
                    # 3. player attacks that square
                    if next_node.move.to_square in attackers:
                        # 4. player checks on that square
                        if attracted_piece == KING:
                            return True
                        n3 = util.next_next_node(next_node)
                        # 4. or player later captures on that square
                        if n3 and n3.move.to_square == attracted_to_square:
                            return True
    return False
Ejemplo n.º 6
0
def dovetail_mate(puzzle: Puzzle) -> bool:
    node = puzzle.game.end()
    board = node.board()
    king = board.king(not puzzle.pov)
    assert king is not None
    assert isinstance(node, ChildNode)
    if square_file(king) in [0, 7] or square_rank(king) in [0, 7]:
        return False
    queen_square = node.move.to_square
    if (util.moved_piece_type(node) != QUEEN
            or square_file(queen_square) == square_file(king)
            or square_rank(queen_square) == square_rank(king)
            or square_distance(queen_square, king) > 1):
        return False
    for square in [
            s for s in SquareSet(chess.BB_ALL) if square_distance(s, king) == 1
    ]:
        if square == queen_square:
            continue
        attackers = list(board.attackers(puzzle.pov, square))
        if attackers == [queen_square]:
            if board.piece_at(square):
                return False
        elif attackers:
            return False
    return True
Ejemplo n.º 7
0
def fork(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2][:-1]:
        if util.moved_piece_type(node) is not KING:
            board = node.board()
            if board.is_checkmate():
                return False
            nb = 0
            for (piece, square) in util.attacked_opponent_squares(
                    board, node.move.to_square, puzzle.pov):
                if piece.piece_type == PAWN:
                    continue
                if (piece.piece_type == KING or util.values[piece.piece_type] >
                        util.values[util.moved_piece_type(node)]
                        or util.is_hanging(board, piece, square)):
                    nb += 1
            if nb > 1:
                return True
    return False
Ejemplo n.º 8
0
def capturing_defender(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2][1:]:
        board = node.board()
        capture = node.parent.board().piece_at(node.move.to_square)
        if board.is_checkmate() or (
                capture and util.moved_piece_type(node) != KING
                and util.values[capture.piece_type] <=
                util.values[util.moved_piece_type(node)] and util.is_hanging(
                    node.parent.board(), capture, node.move.to_square)):
            prev = node.parent.parent
            if not prev.board().is_check(
            ) and prev.move.to_square != node.move.from_square:
                init_board = node.parent.parent.parent.board()
                defender_square = prev.move.to_square
                defender = init_board.piece_at(defender_square)
                if (defender and defender_square in init_board.attackers(
                        defender.color, node.move.to_square)
                        and not init_board.is_check()):
                    return True
Ejemplo n.º 9
0
def skewer(puzzle: Puzzle) -> bool:
    def value(pt: PieceType):
        return 10 if pt == KING else util.values[pt]

    for node in puzzle.mainline[1::2][1:]:
        prev = node.parent
        capture = prev.board().piece_at(node.move.to_square)
        if capture and util.moved_piece_type(
                node
        ) in util.ray_piece_types and not node.board().is_checkmate():
            between = SquareSet.between(node.move.from_square,
                                        node.move.to_square)
            op_move = prev.move
            if (op_move.to_square == node.move.to_square
                    or not op_move.from_square in between):
                continue
            if value(util.moved_piece_type(prev)) > value(capture.piece_type):
                return True
    return False
Ejemplo n.º 10
0
def skewer(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2][1:]:
        prev = node.parent
        assert isinstance(prev, ChildNode)
        capture = prev.board().piece_at(node.move.to_square)
        if capture and util.moved_piece_type(
                node
        ) in util.ray_piece_types and not node.board().is_checkmate():
            between = SquareSet.between(node.move.from_square,
                                        node.move.to_square)
            op_move = prev.move
            assert op_move
            if (op_move.to_square == node.move.to_square
                    or not op_move.from_square in between):
                continue
            if (util.king_values[util.moved_piece_type(prev)] >
                    util.king_values[capture.piece_type] and
                    util.is_in_bad_spot(prev.board(), node.move.to_square)):
                return True
    return False
Ejemplo n.º 11
0
def fork(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2][:-1]:
        if util.moved_piece_type(node) is not KING:
            board = node.board()
            if util.is_in_bad_spot(board, node.move.to_square):
                continue
            nb = 0
            for (piece, square) in util.attacked_opponent_squares(
                    board, node.move.to_square, puzzle.pov):
                if piece.piece_type == PAWN:
                    continue
                if (util.king_values[piece.piece_type] >
                        util.king_values[util.moved_piece_type(node)]
                        or (util.is_hanging(board, piece, square)
                            and square not in board.attackers(
                                not puzzle.pov, node.move.to_square))):
                    nb += 1
            if nb > 1:
                return True
    return False
Ejemplo n.º 12
0
def quiet_move(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline:
        if (
                # on player move, not the last move of the puzzle
                node.turn() != puzzle.pov and not node.is_end() and
                # no check given or escaped
                not node.board().is_check()
                and not node.parent.board().is_check() and
                # no capture made or threatened
                not util.is_capture(node)
                and not util.attacked_opponent_pieces(
                    node.board(), node.move.to_square, puzzle.pov) and
                # no advanced pawn push
                not util.is_advanced_pawn_move(node)
                and util.moved_piece_type(node) != KING):
            return True
    return False
Ejemplo n.º 13
0
def x_ray(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2][1:]:
        if not util.is_capture(node):
            continue
        prev_op_node = node.parent
        assert isinstance(prev_op_node, ChildNode)
        if prev_op_node.move.to_square != node.move.to_square or util.moved_piece_type(
                prev_op_node) == KING:
            continue
        prev_pl_node = prev_op_node.parent
        assert isinstance(prev_pl_node, ChildNode)
        if prev_pl_node.move.to_square != prev_op_node.move.to_square:
            continue
        if prev_op_node.move.from_square in SquareSet.between(
                node.move.from_square, node.move.to_square):
            return True

    return False
Ejemplo n.º 14
0
def arabian_mate(puzzle: Puzzle) -> bool:
    node = puzzle.game.end()
    board = node.board()
    king = board.king(not puzzle.pov)
    assert king is not None
    assert isinstance(node, ChildNode)
    if square_file(king) in [0, 7] and square_rank(king) in [
            0, 7
    ] and util.moved_piece_type(node) == ROOK and square_distance(
            node.move.to_square, king) == 1:
        for knight_square in board.attackers(puzzle.pov, node.move.to_square):
            knight = board.piece_at(knight_square)
            if knight and knight.piece_type == KNIGHT and (
                    abs(square_rank(knight_square) - square_rank(king)) == 2
                    and abs(square_file(knight_square) - square_file(king))
                    == 2):
                return True
    return False
Ejemplo n.º 15
0
def hook_mate(puzzle: Puzzle) -> bool:
    node = puzzle.game.end()
    board = node.board()
    king = board.king(not puzzle.pov)
    assert king is not None
    assert isinstance(node, ChildNode)
    if util.moved_piece_type(node) == ROOK and square_distance(
            node.move.to_square, king) == 1:
        for rook_defender_square in board.attackers(puzzle.pov,
                                                    node.move.to_square):
            defender = board.piece_at(rook_defender_square)
            if defender and defender.piece_type == KNIGHT and square_distance(
                    rook_defender_square, king) == 1:
                for knight_defender_square in board.attackers(
                        puzzle.pov, rook_defender_square):
                    pawn = board.piece_at(knight_defender_square)
                    if pawn and pawn.piece_type == PAWN:
                        return True
    return False
Ejemplo n.º 16
0
def anastasia_mate(puzzle: Puzzle) -> bool:
    node = puzzle.game.end()
    board = node.board()
    king = board.king(not puzzle.pov)
    assert king is not None
    assert isinstance(node, ChildNode)
    if square_file(king) in [0, 7] and square_rank(king) not in [0, 7]:
        if square_file(node.move.to_square) == square_file(
                king) and util.moved_piece_type(node) in [QUEEN, ROOK]:
            if square_file(king) != 0:
                board.apply_transform(chess.flip_horizontal)
            king = board.king(not puzzle.pov)
            assert king is not None
            blocker = board.piece_at(king + 1)
            if blocker is not None and blocker.color != puzzle.pov:
                knight = board.piece_at(king + 3)
                if knight is not None and knight.color == puzzle.pov and knight.piece_type == KNIGHT:
                    return True
    return False