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