Exemple #1
0
def pin_prevents_escape(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2]:
        board = node.board()
        for pinned_square, pinned_piece in board.piece_map().items():
            if pinned_piece.color == puzzle.pov:
                continue
            pin_dir = board.pin(pinned_piece.color, pinned_square)
            if pin_dir == chess.BB_ALL:
                continue
            for attacker_square in board.attackers(puzzle.pov, pinned_square):
                if attacker_square in pin_dir:
                    attacker = board.piece_at(attacker_square)
                    assert (attacker)
                    if util.values[pinned_piece.piece_type] > util.values[
                            attacker.piece_type]:
                        return True
                    if (util.is_hanging(board, pinned_piece, pinned_square)
                            and pinned_square not in board.attackers(
                                not puzzle.pov, attacker_square) and [
                                    m for m in board.pseudo_legal_moves
                                    if m.from_square == pinned_square
                                    and m.to_square not in pin_dir
                                ]):
                        return True
    return False
Exemple #2
0
def hanging_piece(puzzle: Puzzle) -> bool:
    if util.is_capture(
            puzzle.mainline[0]) or puzzle.mainline[0].board().is_check():
        return False
    to = puzzle.mainline[1].move.to_square
    captured = puzzle.mainline[0].board().piece_at(to)
    if captured and captured.piece_type != PAWN:
        if util.is_hanging(puzzle.mainline[0].board(), captured, to):
            if len(puzzle.mainline) < 3:
                return True
            if material_diff(puzzle.mainline[3].board(),
                             puzzle.pov) >= material_diff(
                                 puzzle.mainline[1].board(), puzzle.pov):
                return True
    return False
Exemple #3
0
def pin(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2][:-1]:
        board = node.board()
        for square, piece in board.piece_map().items():
            if piece.color == puzzle.pov:
                continue
            pin_dir = board.pin(piece.color, square)
            if pin_dir == chess.BB_ALL:
                continue
            for attack in board.attacks(square):
                attacked = board.piece_at(attack)
                if attacked and attacked.color == puzzle.pov and not attack in pin_dir and (
                        util.values[attacked.piece_type] >
                        util.values[piece.piece_type]
                        or util.is_hanging(board, attacked, attack)):
                    return True
Exemple #4
0
def self_interference(puzzle: Puzzle) -> bool:
    # intereference by opponent piece
    for node in puzzle.mainline[1::2][1:]:
        prev_board = node.parent.board()
        square = node.move.to_square
        capture = prev_board.piece_at(square)
        if capture and util.is_hanging(prev_board, capture, square):
            init_board = node.parent.parent.board()
            defenders = init_board.attackers(capture.color, square)
            defender = defenders.pop() if defenders else None
            if defender and init_board.piece_at(
                    defender).piece_type in util.ray_piece_types:
                if node.parent.move.to_square in SquareSet.between(
                        square, defender):
                    return True
    return False
Exemple #5
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
Exemple #6
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
Exemple #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 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
Exemple #8
0
def hanging_piece(puzzle: Puzzle) -> bool:
    to = puzzle.mainline[1].move.to_square
    captured = puzzle.mainline[0].board().piece_at(to)
    if puzzle.mainline[0].board().is_check() and (not captured or
                                                  captured.piece_type == PAWN):
        return False
    if captured and captured.piece_type != PAWN:
        if util.is_hanging(puzzle.mainline[0].board(), captured, to):
            op_move = puzzle.mainline[0].move
            op_capture = puzzle.game.board().piece_at(op_move.to_square)
            if op_capture and util.values[
                    op_capture.piece_type] >= util.values[
                        captured.piece_type] and op_move.to_square == to:
                return False
            if len(puzzle.mainline) < 3:
                return True
            if material_diff(puzzle.mainline[3].board(),
                             puzzle.pov) >= material_diff(
                                 puzzle.mainline[1].board(), puzzle.pov):
                return True
    return False
Exemple #9
0
def interference(puzzle: Puzzle) -> bool:
    # intereference by player piece
    for node in puzzle.mainline[1::2][1:]:
        prev_board = node.parent.board()
        square = node.move.to_square
        capture = prev_board.piece_at(square)
        assert node.parent.move
        if capture and square != node.parent.move.to_square and util.is_hanging(
                prev_board, capture, square):
            assert node.parent
            assert node.parent.parent
            assert node.parent.parent.parent
            init_board = node.parent.parent.parent.board()
            defenders = init_board.attackers(capture.color, square)
            defender = defenders.pop() if defenders else None
            defender_piece = init_board.piece_at(
                defender) if defender else None
            if defender and defender_piece and defender_piece.piece_type in util.ray_piece_types:
                interfering = node.parent.parent
                if interfering.move and interfering.move.to_square in SquareSet.between(
                        square, defender):
                    return True
    return False