Advertisement
max2201111

quite good moves_to_mate 14 but is 10

Mar 16th, 2024
538
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.83 KB | Science | 0 0
  1. import chess
  2.  
  3. def simplify_fen(fen):
  4.     """Simplifies a FEN string to include only position, turn, castling availability, and en passant target."""
  5.     return ' '.join(fen.split(' ')[:4])
  6.  
  7. def initialize_game_tree(initial_fen):
  8.     """Initializes the game tree with the root node based on the initial FEN."""
  9.     simplified_fen = simplify_fen(initial_fen)
  10.     game_tree = {1: {'fen': simplified_fen, 'parent': None, 'color': chess.WHITE if 'w' in initial_fen else chess.BLACK, 'children': [], 'moves_to_mate': None}}
  11.     fen_to_node_id = {simplified_fen: 1}
  12.     return game_tree, fen_to_node_id
  13.  
  14. def add_descendants_iteratively(game_tree, fen_to_node_id):
  15.     """Expands the game tree by iteratively adding legal move descendants of each game state."""
  16.     queue = [(1, 0)]
  17.     while queue:
  18.         node_id, _ = queue.pop(0)
  19.         board = chess.Board(game_tree[node_id]['fen'] + " 0 1")
  20.         for move in board.legal_moves:
  21.             board.push(move)
  22.             simplified_fen = simplify_fen(board.fen())
  23.             if simplified_fen not in fen_to_node_id:
  24.                 new_node_id = len(game_tree) + 1
  25.                 game_tree[new_node_id] = {'fen': simplified_fen, 'parent': node_id, 'color': chess.WHITE if board.turn else chess.BLACK, 'children': [], 'moves_to_mate': None}
  26.                 fen_to_node_id[simplified_fen] = new_node_id
  27.                 game_tree[node_id]['children'].append(new_node_id)
  28.                 queue.append((new_node_id, 0))
  29.             board.pop()
  30.  
  31. def update_game_outcomes(game_tree):
  32.     """Updates game outcomes focusing only on checkmates."""
  33.     for node_id, node in game_tree.items():
  34.         board = chess.Board(node['fen'] + " 0 1")
  35.         if board.is_checkmate():
  36.             node['result'] = 1 if board.turn == chess.BLACK else -1  # Black's turn but checkmate means White wins, and vice versa
  37.             node['moves_to_mate'] = 0  # Checkmate is immediate, no more moves required.
  38.         elif board.is_game_over():
  39.             node['result'] = 0  # For draws or stalemates, we consider the result as 0 (this will be ignored in propagation)
  40.  
  41. # def update_parent_preferences(game_tree):
  42. #     """Propagates the best outcome for each node up the game tree, prioritizing checkmates and updating moves to mate."""
  43. #     def recurse(node_id):
  44. #         node = game_tree[node_id]
  45. #         if 'result' in node and node['result'] in [-1, 1]:  # Checkmate detected
  46. #             return node['result'], [node_id], 0 if 'moves_to_mate' in node else None
  47.  
  48. #         best_result = None
  49. #         best_path = []
  50. #         best_moves_to_mate = None
  51. #         for child_id in node['children']:
  52. #             child_result, child_path, child_moves_to_mate = recurse(child_id)
  53.            
  54. #             if child_moves_to_mate is not None:
  55. #                 child_moves_to_mate += 1  # Increment moves to mate since we move up the tree
  56.                
  57. #                 if best_moves_to_mate is None or (node['color'] == chess.WHITE and child_result == 1 and child_moves_to_mate < best_moves_to_mate) or (node['color'] == chess.BLACK and child_result == -1 and child_moves_to_mate > best_moves_to_mate):
  58. #                     best_result, best_path, best_moves_to_mate = child_result, child_path, child_moves_to_mate
  59.  
  60. #         if best_result in [-1, 1]:
  61. #             node['result'] = best_result
  62. #             node['moves_to_mate'] = best_moves_to_mate
  63. #         else:
  64. #             node['result'] = 0  # Default to draw if no win/loss is found
  65.  
  66. #         return node.get('result', 0), [node_id] + best_path, node.get('moves_to_mate', None)
  67.  
  68. #     result, path, moves_to_mate = recurse(1)  # Start the recursion from the root node.
  69. #     return path
  70.  
  71. def update_parent_preferences(game_tree):
  72.     """Updates the parent preferences for each node up the game tree, prioritizing checkmates."""
  73.     def recurse(node_id):
  74.         node = game_tree[node_id]
  75.         if 'result' in node and node['result'] in [-1, 1]:  # Direct checkmate detected
  76.             return node['result'], [node_id], 0
  77.  
  78.         best_result = None
  79.         best_path = []
  80.         # Initialize moves_to_mate with a large number for comparison
  81.         best_moves_to_mate = float('inf') if node['color'] == chess.WHITE else -float('inf')
  82.  
  83.         for child_id in node['children']:
  84.             child_result, child_path, child_moves_to_mate = recurse(child_id)
  85.  
  86.             # Update for WHITE (minimizing moves to mate) or BLACK (maximizing moves to mate)
  87.             if child_moves_to_mate is not None:
  88.                 updated = False
  89.                 if node['color'] == chess.WHITE and child_result == 1:
  90.                     if best_moves_to_mate > child_moves_to_mate:
  91.                         best_moves_to_mate = child_moves_to_mate
  92.                         updated = True
  93.                 elif node['color'] == chess.BLACK and child_result == -1:
  94.                     if best_moves_to_mate < child_moves_to_mate:
  95.                         best_moves_to_mate = child_moves_to_mate
  96.                         updated = True
  97.  
  98.                 if updated:
  99.                     best_result = child_result
  100.                     best_path = child_path
  101.  
  102.         # If no checkmate path was found, revert moves_to_mate to None and set result to draw
  103.         if best_moves_to_mate == float('inf') or best_moves_to_mate == -float('inf'):
  104.             best_moves_to_mate = None
  105.             best_result = 0
  106.  
  107.         if best_result in [-1, 1]:
  108.             node['moves_to_mate'] = best_moves_to_mate + 1 if best_moves_to_mate is not None else None
  109.         else:
  110.             node['result'] = 0  # Default to draw if no win/loss is found
  111.             node['moves_to_mate'] = None
  112.  
  113.         return best_result, [node_id] + best_path, node.get('moves_to_mate')
  114.  
  115.     # Execute the recursive function starting from the root node.
  116.     result, path, moves_to_mate = recurse(1)
  117.     return path
  118.  
  119. # Ensure you call this function in your main to see the corrected output.
  120.  
  121.  
  122. def print_path(game_tree, path):
  123.     """Prints the board positions along the path."""
  124.     for node_id in path:
  125.         node = game_tree[node_id]
  126.         board = chess.Board(node['fen'] + " 0 1")
  127.         moves_to_mate = "N/A" if node.get('moves_to_mate') is None else node.get('moves_to_mate')
  128.         print(f"Node ID: {node_id}, Result: {node.get('result', 'N/A')}, Moves to Mate: {moves_to_mate}")
  129.         print(board)
  130.         print("---")
  131.  
  132. def main():
  133.     initial_fen = "8/8/8/3k4/8/8/2K2Q2/8 w - - 0 1"  # Example FEN
  134.     initial_fen = "8/8/8/3k4/8/2K5/5q2/8 w - - 0 1"
  135.  
  136.     game_tree, fen_to_node_id = initialize_game_tree(initial_fen)
  137.     add_descendants_iteratively(game_tree, fen_to_node_id)
  138.     update_game_outcomes(game_tree)
  139.     path = update_parent_preferences(game_tree)
  140.     print(game_tree[1])
  141.     print("Path to the outcome:")
  142.     print_path(game_tree, path)
  143.  
  144. if __name__ == "__main__":
  145.     main()
  146.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement