Untitled
unknown
python
a year ago
3.2 kB
12
Indexable
import chess
def a_star_search(board: chess.Board, goal_position: chess.Square):
"""
Implements the A* search algorithm to find the final path for the Knight's quest.
Parameters:
- board: The chess board that the knight is moving upon.
- goal_position: The target square where the knight needs to move (H8).
Returns:
A list containing the final path from start to goal, represented by square IDs.
"""
# Priority queue: stores (f(n), g(n), current_square, path_to_current_square)
priority_queue = []
# g_score: cost to reach a square from the start
g_score = {i: float('inf') for i in range(64)} # Initialize with infinity
g_score[0] = 0 # The knight starts at A1 (square 0)
# Start position and push it to the list with initial f(n) = g(n) + h(n)
start_position = 0
priority_queue.append((0 + chess.square_knight_distance(start_position, goal_position), 0, start_position, [start_position]))
# Set to track visited nodes
visited = set()
while priority_queue:
# Sort the queue manually by f(n) to always pick the best option
priority_queue.sort(key=lambda x: x[0]) # Sort by f(n)
f_current, g_current, current_square, path_to_current = priority_queue.pop(0)
# If the current square is the goal, return the path
if current_square == goal_position:
return path_to_current
# If we've already visited this node, skip it
if current_square in visited:
continue
# Mark this node as visited
visited.add(current_square)
# Place the knight at the current square
board.clear() # Clear the board
board.set_piece_at(current_square, chess.Piece(chess.KNIGHT, chess.WHITE)) # Place the knight
# Get all legal moves for the knight from the current square
legal_moves = list(board.legal_moves)
# Prepare the list of possible moves sorted by f(n)
for move in legal_moves:
next_square = move.to_square
# Skip already visited squares
if next_square in visited:
continue
# Calculate g(n): the cost to reach next_square
tentative_g_score = g_current + 1
# Only proceed if this new g(n) is better (shorter path) than what we have for the next square
if tentative_g_score < g_score[next_square]:
# Update g(n) for next_square
g_score[next_square] = tentative_g_score
# Calculate h(n): heuristic cost to the goal
h_score = chess.square_knight_distance(next_square, goal_position)
# Calculate f(n) = g(n) + h(n)
f_score = tentative_g_score + h_score
# Add the move to the priority queue
priority_queue.append((f_score, tentative_g_score, next_square, path_to_current + [next_square]))
# If we exhaust the priority queue without finding the goal, return an empty list (shouldn't happen)
return []
Editor is loading...
Leave a Comment