I have detected where roughly is a problem. It is in this function which gets processed for node "1" only, see the output section below: (I'm trying to put the node 6109 into A[1]['sequence'] but I cannot) Can someone help to me fix this function def evaluate_and_partition(A, node_id=1):
END OF THE WRONG FUNCTION, the code follows
The output is like this, the node 6109 below is my target to be included to A[1]['sequence']
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
def evaluate_and_partition(A, node_id = 1 ): node = A[node_id] # Debugging line to track the function calls print ( f "Evaluating Node ID: {node_id}" ) # Return previously calculated result if this node has been processed if node[ 'processed' ]: print ( f "Returning processed Node ID: {node_id} with result: {node['result']}, moves to mate: {node['moves_to_mate']}" ) return node[ 'result' ], node[ 'moves_to_mate' ] # Initialize variables to store the best result and path found so far optimal_result = - float ( 'inf' ) # Assume worst case scenario optimal_moves_to_mate = None # Initialize as None, to be updated optimal_child_id = None # Keep track of which child leads to the optimal result # Iterate through each child of the current node for child_id in node[ 'children' ]: print (child_id) # Recursively evaluate each child child_result, child_moves_to_mate = evaluate_and_partition(A, child_id) # Check if the current child's result improves upon the best result found so far if child_result is not None and ( child_result > optimal_result or (child_result = = optimal_result and optimal_moves_to_mate is not None and child_moves_to_mate is not None and child_moves_to_mate < optimal_moves_to_mate)): # Update optimal values based on the current child's results optimal_result = child_result optimal_moves_to_mate = child_moves_to_mate optimal_child_id = child_id # After evaluating all children, update the current node with the best result and path found node[ 'result' ] = optimal_result if optimal_moves_to_mate is not None : # If a path to victory or draw is found, increment moves to mate as we move up the tree node[ 'moves_to_mate' ] = optimal_moves_to_mate + 1 else : # If no path improves the position, moves to mate remains None node[ 'moves_to_mate' ] = None node[ 'sequence' ] = [optimal_child_id] if optimal_child_id is not None else [] node[ 'processed' ] = True # Mark the node as processed # Return the best result and path found for the current node return node[ 'result' ], node[ 'moves_to_mate' ] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
import chess def initialize_game_tree(initial_fen): """Initializes the game tree with the root node based on the initial FEN.""" return { 1 : { 'fen' : initial_fen, 'moves_to_mate' : None , 'parent' : None , 'color' : chess.WHITE if initial_fen.split( ' ' )[ 1 ] = = 'w' else chess.BLACK, 'result' : None , 'processed' : False , 'sequence' : [], 'children' : [] } } def add_descendants(node_id, depth, A): """Recursively adds descendant nodes to the game tree up to a specified depth.""" if depth = = 0 : return board = chess.Board(A[node_id][ 'fen' ]) for move in board.legal_moves: board.push(move) new_node_id = len (A) + 1 A[new_node_id] = { 'fen' : board.fen(), 'moves_to_mate' : None , 'parent' : node_id, 'color' : chess.WHITE if board.turn else chess.BLACK, 'result' : None , 'processed' : False , 'sequence' : [], 'children' : [] } A[node_id][ 'children' ].append(new_node_id) add_descendants(new_node_id, depth - 1 , A) board.pop() def evaluate_and_partition(A, node_id = 1 ): node = A[node_id] # Debugging line to track the function calls print ( f "Evaluating Node ID: {node_id}" ) # Return previously calculated result if this node has been processed if node[ 'processed' ]: print ( f "Returning processed Node ID: {node_id} with result: {node['result']}, moves to mate: {node['moves_to_mate']}" ) return node[ 'result' ], node[ 'moves_to_mate' ] # Initialize variables to store the best result and path found so far optimal_result = - float ( 'inf' ) # Assume worst case scenario optimal_moves_to_mate = None # Initialize as None, to be updated optimal_child_id = None # Keep track of which child leads to the optimal result # Iterate through each child of the current node for child_id in node[ 'children' ]: print (child_id) # Recursively evaluate each child child_result, child_moves_to_mate = evaluate_and_partition(A, child_id) # Check if the current child's result improves upon the best result found so far if child_result is not None and ( child_result > optimal_result or (child_result = = optimal_result and optimal_moves_to_mate is not None and child_moves_to_mate is not None and child_moves_to_mate < optimal_moves_to_mate)): # Update optimal values based on the current child's results optimal_result = child_result optimal_moves_to_mate = child_moves_to_mate optimal_child_id = child_id # After evaluating all children, update the current node with the best result and path found node[ 'result' ] = optimal_result if optimal_moves_to_mate is not None : # If a path to victory or draw is found, increment moves to mate as we move up the tree node[ 'moves_to_mate' ] = optimal_moves_to_mate + 1 else : # If no path improves the position, moves to mate remains None node[ 'moves_to_mate' ] = None node[ 'sequence' ] = [optimal_child_id] if optimal_child_id is not None else [] node[ 'processed' ] = True # Mark the node as processed # Return the best result and path found for the current node return node[ 'result' ], node[ 'moves_to_mate' ] # Main execution block initial_fen = "4k3/8/8/3K2Q1/8/8/8/8 w - - 6 4" A = initialize_game_tree(initial_fen) add_descendants( 1 , 5 , A) # Adjust the depth as needed evaluate_terminal_positions(A) evaluate_and_partition(A, 1 ) # Print the root node to see the analysis result print (A[ 1 ]) # Function to print boards for children of a given node def print_boards_for_children(A, parent_key): children_keys = A[parent_key].get( 'children' , []) for key in children_keys: if key in A: fen = A[key][ 'fen' ] board = chess.Board(fen) print ( f "Board for child {key}:\n{board}\n" ) # Display the initial board and boards for first-level children print (chess.Board(initial_fen)) print_boards_for_children(A, 1 ) |
Output:Evaluating Node ID: 1
Returning processed Node ID: 1 with result: None, moves to mate: None
{'fen': '4k3/8/8/3K2Q1/8/8/8/8 w - - 6 4', 'moves_to_mate': None, 'parent': None, 'color': True, 'result': None, 'processed': True, 'sequence': [], 'children': [2, 3697, 6109, 8685, 9041, 20864, 32046, 34967, 44777, 50093, 60983, 70685, 83639, 94018, 111578, 126490, 142939, 161014, 178208, 196205, 197783, 202648, 209235, 216611, 225572, 236906, 248111]}
. . . . k . . .
. . . . . . . .
. . . . . . . .
. . . K . . Q .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
Board for child 2:
. . . . k . Q .
. . . . . . . .
. . . . . . . .
. . . K . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
Board for child 3697:
. . . Q k . . .
. . . . . . . .
. . . . . . . .
. . . K . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
Board for child 6109:
. . . . k . . .
. . . . . . Q .
. . . . . . . .
. . . K . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .