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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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