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) < 4: return True if material_diff(puzzle.mainline[3].board(), puzzle.pov) >= material_diff(puzzle.mainline[1].board(), puzzle.pov): return True return False
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): grandpa = node.parent.parent assert grandpa init_board = grandpa.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: if node.parent.move and 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 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 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) assert isinstance(node.parent, ChildNode) 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) and node.parent.move.to_square != node.move.to_square ): prev = node.parent.parent assert isinstance(prev, ChildNode) if not prev.board().is_check() and prev.move.to_square != node.move.from_square: assert prev.parent init_board = prev.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 return False
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 pin_prevents_attack(puzzle: Puzzle) -> bool: for node in puzzle.mainline[1::2]: 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 return False