Advertisement
max2201111

excellent 44

Jul 3rd, 2025
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 29.45 KB | Science | 0 0
  1. import time
  2. from datetime import datetime
  3. from collections import deque
  4. import copy
  5.  
  6. def print_board(board):
  7.     print(str(board))
  8.  
  9. class ChessBoard:
  10.     """Vlastní implementace šachovnice pro pohádkové figury"""
  11.    
  12.     def __init__(self, fen=None):
  13.         self.board = [[None for _ in range(8)] for _ in range(8)]
  14.         self.turn = True  # True = bílý, False = černý
  15.         self.castling_rights = {'K': True, 'Q': True, 'k': True, 'q': True}
  16.         self.en_passant = None
  17.         self.halfmove_clock = 0
  18.         self.fullmove_number = 1
  19.        
  20.         if fen:
  21.             self.set_fen(fen)
  22.         else:
  23.             self.setup_initial_position()
  24.  
  25.     def __str__(self):
  26.         rows = []
  27.         for i, row in enumerate(self.board[::-1], 1):
  28.             safe_row = []
  29.             for piece in row:
  30.                 if piece is None:
  31.                     safe_row.append('.')
  32.                 elif isinstance(piece, tuple):
  33.                     # Opraveno: tuple je (color, piece_type)
  34.                     color, symbol = piece
  35.                     safe_row.append(symbol.upper() if color == 'w' else symbol.lower())
  36.                 else:
  37.                     # už je string, rovnou přidej
  38.                     safe_row.append(str(piece))
  39.             rows.append(f"{8 - i + 1} " + " ".join(safe_row))
  40.         rows.append("  a b c d e f g h")
  41.         return "\n".join(rows)
  42.  
  43.     def setup_initial_position(self):
  44.         """Nastaví základní pozici"""
  45.         # Bílé figury
  46.         pieces = ['R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R']
  47.         for i, piece in enumerate(pieces):
  48.             self.board[0][i] = ('w', piece)
  49.         for i in range(8):
  50.             self.board[1][i] = ('w', 'P')
  51.        
  52.         # Černé figury - opraveno
  53.         pieces = ['R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R']
  54.         for i, piece in enumerate(pieces):
  55.             self.board[7][i] = ('b', piece)
  56.         for i in range(8):
  57.             self.board[6][i] = ('b', 'P')
  58.    
  59.     def set_fen(self, fen_string):
  60.         """Nastaví pozici z FEN stringu"""
  61.         parts = fen_string.split()
  62.        
  63.         # Pozice figur
  64.         rows = parts[0].split('/')
  65.         for rank, row in enumerate(rows):
  66.             file_idx = 0
  67.             for char in row:
  68.                 if char.isdigit():
  69.                     # Prázdná pole
  70.                     for _ in range(int(char)):
  71.                         self.board[7-rank][file_idx] = None
  72.                         file_idx += 1
  73.                 else:
  74.                     # Figura
  75.                     color = 'w' if char.isupper() else 'b'
  76.                     self.board[7-rank][file_idx] = (color, char.upper())
  77.                     file_idx += 1
  78.        
  79.         # Na tahu
  80.         self.turn = parts[1] == 'w'
  81.        
  82.         # Rošáda
  83.         castling = parts[2] if len(parts) > 2 else '-'
  84.         self.castling_rights = {
  85.             'K': 'K' in castling,
  86.             'Q': 'Q' in castling,
  87.             'k': 'k' in castling,
  88.             'q': 'q' in castling
  89.         }
  90.        
  91.         # En passant
  92.         self.en_passant = parts[3] if len(parts) > 3 and parts[3] != '-' else None
  93.        
  94.         # Počítadla tahů
  95.         self.halfmove_clock = int(parts[4]) if len(parts) > 4 else 0
  96.         self.fullmove_number = int(parts[5]) if len(parts) > 5 else 1
  97.    
  98.     def get_fen(self):
  99.         """Vrátí FEN string pozice"""
  100.         # Pozice figur
  101.         fen_parts = []
  102.         for rank in range(7, -1, -1):
  103.             row_fen = ""
  104.             empty_count = 0
  105.            
  106.             for file in range(8):
  107.                 piece = self.board[rank][file]
  108.                 if piece is None:
  109.                     empty_count += 1
  110.                 else:
  111.                     if empty_count > 0:
  112.                         row_fen += str(empty_count)
  113.                         empty_count = 0
  114.                     color, piece_type = piece
  115.                     row_fen += piece_type if color == 'w' else piece_type.lower()
  116.            
  117.             if empty_count > 0:
  118.                 row_fen += str(empty_count)
  119.            
  120.             fen_parts.append(row_fen)
  121.        
  122.         position = '/'.join(fen_parts)
  123.        
  124.         # Na tahu
  125.         turn = 'w' if self.turn else 'b'
  126.        
  127.         # Rošáda
  128.         castling = ''
  129.         for right in ['K', 'Q', 'k', 'q']:
  130.             if self.castling_rights[right]:
  131.                 castling += right
  132.         if not castling:
  133.             castling = '-'
  134.        
  135.         # En passant
  136.         en_passant = self.en_passant if self.en_passant else '-'
  137.        
  138.         return f"{position} {turn} {castling} {en_passant} {self.halfmove_clock} {self.fullmove_number}"
  139.    
  140.     def copy(self):
  141.         """Vytvoří kopii šachovnice"""
  142.         new_board = ChessBoard()
  143.         new_board.board = [row[:] for row in self.board]
  144.         new_board.turn = self.turn
  145.         new_board.castling_rights = self.castling_rights.copy()
  146.         new_board.en_passant = self.en_passant
  147.         new_board.halfmove_clock = self.halfmove_clock
  148.         new_board.fullmove_number = self.fullmove_number
  149.         return new_board
  150.    
  151.     def make_move(self, from_pos, to_pos):
  152.         """Provede tah"""
  153.         from_rank, from_file = from_pos
  154.         to_rank, to_file = to_pos
  155.        
  156.         piece = self.board[from_rank][from_file]
  157.         self.board[to_rank][to_file] = piece
  158.         self.board[from_rank][from_file] = None
  159.        
  160.         # Změnit hráče na tahu
  161.         self.turn = not self.turn
  162.        
  163.         # Inkrementovat počítadla
  164.         if self.turn:  # Pokud je nyní na tahu bílý, znamená to že černý právě táhl
  165.             self.fullmove_number += 1
  166.         self.halfmove_clock += 1
  167.    
  168.     def find_king(self, color):
  169.         """Najde krále dané barvy"""
  170.         for rank in range(8):
  171.             for file in range(8):
  172.                 piece = self.board[rank][file]
  173.                 if piece and piece[0] == color and piece[1] == 'K':
  174.                     return (rank, file)
  175.         return None
  176.    
  177.     def is_check(self, color):
  178.         """Kontroluje zda je král v šachu"""
  179.         king_pos = self.find_king(color)
  180.         if not king_pos:
  181.             return False
  182.        
  183.         # Kontrola útoku od protivníka
  184.         enemy_color = 'b' if color == 'w' else 'w'
  185.        
  186.         for rank in range(8):
  187.             for file in range(8):
  188.                 piece = self.board[rank][file]
  189.                 if piece and piece[0] == enemy_color:
  190.                     if self.attacks_square((rank, file), king_pos):
  191.                         return True
  192.         return False
  193.    
  194.     def attacks_square(self, from_pos, to_pos):
  195.         """Kontroluje zda figura útočí na dané pole"""
  196.         rank, file = from_pos
  197.         piece = self.board[rank][file]
  198.        
  199.         if not piece:
  200.             return False
  201.        
  202.         color, piece_type = piece
  203.        
  204.         # Získat možné útoky podle typu figury
  205.         if piece_type == 'P':
  206.             return self.pawn_attacks(from_pos, to_pos, color)
  207.         elif piece_type == 'R':
  208.             return self.rook_attacks(from_pos, to_pos)
  209.         elif piece_type == 'N':
  210.             return self.knight_attacks(from_pos, to_pos)
  211.         elif piece_type == 'B':
  212.             return self.bishop_attacks(from_pos, to_pos)
  213.         elif piece_type == 'Q':
  214.             return self.queen_attacks(from_pos, to_pos)
  215.         elif piece_type == 'K':
  216.             return self.king_attacks(from_pos, to_pos)
  217.         elif piece_type == 'A':  # Amazonka (Q+N)
  218.             return self.queen_attacks(from_pos, to_pos) or self.knight_attacks(from_pos, to_pos)
  219.         elif piece_type == 'C':  # Cyril (R+N)
  220.             return self.rook_attacks(from_pos, to_pos) or self.knight_attacks(from_pos, to_pos)
  221.         elif piece_type == 'E':  # Eve (B+N)
  222.             return self.bishop_attacks(from_pos, to_pos) or self.knight_attacks(from_pos, to_pos)
  223.        
  224.         return False
  225.    
  226.     def pawn_attacks(self, from_pos, to_pos, color):
  227.         """Kontroluje útok pěšce"""
  228.         from_rank, from_file = from_pos
  229.         to_rank, to_file = to_pos
  230.        
  231.         direction = 1 if color == 'w' else -1
  232.        
  233.         return (abs(from_file - to_file) == 1 and
  234.                 to_rank - from_rank == direction)
  235.    
  236.     def knight_attacks(self, from_pos, to_pos):
  237.         """Kontroluje útok jezdce"""
  238.         from_rank, from_file = from_pos
  239.         to_rank, to_file = to_pos
  240.        
  241.         dr = abs(from_rank - to_rank)
  242.         df = abs(from_file - to_file)
  243.        
  244.         return (dr == 2 and df == 1) or (dr == 1 and df == 2)
  245.    
  246.     def rook_attacks(self, from_pos, to_pos):
  247.         """Kontroluje útok věže"""
  248.         from_rank, from_file = from_pos
  249.         to_rank, to_file = to_pos
  250.        
  251.         if from_rank != to_rank and from_file != to_file:
  252.             return False
  253.        
  254.         # Kontrola zda není blokováno
  255.         if from_rank == to_rank:  # Horizontální
  256.             start = min(from_file, to_file) + 1
  257.             end = max(from_file, to_file)
  258.             for f in range(start, end):
  259.                 if self.board[from_rank][f] is not None:
  260.                     return False
  261.         else:  # Vertikální
  262.             start = min(from_rank, to_rank) + 1
  263.             end = max(from_rank, to_rank)
  264.             for r in range(start, end):
  265.                 if self.board[r][from_file] is not None:
  266.                     return False
  267.        
  268.         return True
  269.    
  270.     def bishop_attacks(self, from_pos, to_pos):
  271.         """Kontroluje útok střelce"""
  272.         from_rank, from_file = from_pos
  273.         to_rank, to_file = to_pos
  274.        
  275.         dr = to_rank - from_rank
  276.         df = to_file - from_file
  277.        
  278.         if abs(dr) != abs(df) or dr == 0:
  279.             return False
  280.        
  281.         # Kontrola zda není blokováno
  282.         step_r = 1 if dr > 0 else -1
  283.         step_f = 1 if df > 0 else -1
  284.        
  285.         steps = abs(dr)
  286.         for i in range(1, steps):
  287.             check_rank = from_rank + i * step_r
  288.             check_file = from_file + i * step_f
  289.             if self.board[check_rank][check_file] is not None:
  290.                 return False
  291.        
  292.         return True
  293.    
  294.     def queen_attacks(self, from_pos, to_pos):
  295.         """Kontroluje útok dámy"""
  296.         return self.rook_attacks(from_pos, to_pos) or self.bishop_attacks(from_pos, to_pos)
  297.    
  298.     def king_attacks(self, from_pos, to_pos):
  299.         """Kontroluje útok krále"""
  300.         from_rank, from_file = from_pos
  301.         to_rank, to_file = to_pos
  302.        
  303.         return (abs(from_rank - to_rank) <= 1 and
  304.                 abs(from_file - to_file) <= 1 and
  305.                 from_pos != to_pos)
  306.  
  307. class FairyChessAnalyzer:
  308.     def __init__(self, start_fen):
  309.         self.start_fen = start_fen
  310.         self.L = []
  311.         self.fen_to_index = {}
  312.         self.iteration_count = 0
  313.        
  314.     def print_time(self, message=""):
  315.         """Vypíše čas ve formátu %hh%mm%ss"""
  316.         now = datetime.now()
  317.         time_str = now.strftime("%H:%M:%S")
  318.         print(f"[{time_str}] Průchod {self.iteration_count}: {message}")
  319.    
  320.     def is_fairy_piece(self, piece_type):
  321.         """Kontroluje zda je figura pohádková"""
  322.         return piece_type in ['A', 'C', 'E']
  323.    
  324.     def generate_moves(self, board, from_pos):
  325.         """Generuje všechny možné tahy z dané pozice"""
  326.         rank, file = from_pos
  327.         piece = board.board[rank][file]
  328.        
  329.         if not piece:
  330.             return []
  331.        
  332.         color, piece_type = piece
  333.         moves = []
  334.        
  335.         # Kontrola zda je figura na tahu
  336.         if (color == 'w') != board.turn:
  337.             return []
  338.        
  339.         if piece_type == 'P':
  340.             moves = self.generate_pawn_moves(board, from_pos)
  341.         elif piece_type == 'R':
  342.             moves = self.generate_rook_moves(board, from_pos)
  343.         elif piece_type == 'N':
  344.             moves = self.generate_knight_moves(board, from_pos)
  345.         elif piece_type == 'B':
  346.             moves = self.generate_bishop_moves(board, from_pos)
  347.         elif piece_type == 'Q':
  348.             moves = self.generate_queen_moves(board, from_pos)
  349.         elif piece_type == 'K':
  350.             moves = self.generate_king_moves(board, from_pos)
  351.         elif piece_type == 'A':  # Amazonka (Q+N)
  352.             moves = self.generate_queen_moves(board, from_pos) + self.generate_knight_moves(board, from_pos)
  353.         elif piece_type == 'C':  # Cyril (R+N)
  354.             moves = self.generate_rook_moves(board, from_pos) + self.generate_knight_moves(board, from_pos)
  355.         elif piece_type == 'E':  # Eve (B+N)
  356.             moves = self.generate_bishop_moves(board, from_pos) + self.generate_knight_moves(board, from_pos)
  357.        
  358.         # Filtrovat legální tahy (král nesmí být v šachu)
  359.         legal_moves = []
  360.         for move in moves:
  361.             if self.is_move_legal(board, from_pos, move):
  362.                 legal_moves.append(move)
  363.        
  364.         return legal_moves
  365.    
  366.     def generate_pawn_moves(self, board, from_pos):
  367.         """Generuje tahy pěšce"""
  368.         rank, file = from_pos
  369.         piece = board.board[rank][file]
  370.         color = piece[0]
  371.         moves = []
  372.        
  373.         direction = 1 if color == 'w' else -1
  374.         start_rank = 1 if color == 'w' else 6
  375.        
  376.         # Tah dopředu
  377.         new_rank = rank + direction
  378.         if 0 <= new_rank <= 7 and board.board[new_rank][file] is None:
  379.             moves.append((new_rank, file))
  380.            
  381.             # Dvojitý tah z výchozí pozice
  382.             if rank == start_rank and board.board[new_rank + direction][file] is None:
  383.                 moves.append((new_rank + direction, file))
  384.        
  385.         # Braní
  386.         for df in [-1, 1]:
  387.             new_file = file + df
  388.             if 0 <= new_file <= 7 and 0 <= new_rank <= 7:
  389.                 target = board.board[new_rank][new_file]
  390.                 if target and target[0] != color:
  391.                     moves.append((new_rank, new_file))
  392.        
  393.         return moves
  394.    
  395.     def generate_knight_moves(self, board, from_pos):
  396.         """Generuje tahy jezdce"""
  397.         rank, file = from_pos
  398.         piece = board.board[rank][file]
  399.         color = piece[0]
  400.         moves = []
  401.        
  402.         knight_moves = [(2,1), (2,-1), (-2,1), (-2,-1), (1,2), (1,-2), (-1,2), (-1,-2)]
  403.        
  404.         for dr, df in knight_moves:
  405.             new_rank = rank + dr
  406.             new_file = file + df
  407.            
  408.             if 0 <= new_rank <= 7 and 0 <= new_file <= 7:
  409.                 target = board.board[new_rank][new_file]
  410.                 if not target or target[0] != color:
  411.                     moves.append((new_rank, new_file))
  412.        
  413.         return moves
  414.    
  415.     def generate_sliding_moves(self, board, from_pos, directions):
  416.         """Generuje tahy pro posuvné figury"""
  417.         rank, file = from_pos
  418.         piece = board.board[rank][file]
  419.         color = piece[0]
  420.         moves = []
  421.        
  422.         for dr, df in directions:
  423.             for distance in range(1, 8):
  424.                 new_rank = rank + dr * distance
  425.                 new_file = file + df * distance
  426.                
  427.                 if not (0 <= new_rank <= 7 and 0 <= new_file <= 7):
  428.                     break
  429.                
  430.                 target = board.board[new_rank][new_file]
  431.                
  432.                 if not target:
  433.                     moves.append((new_rank, new_file))
  434.                 elif target[0] != color:
  435.                     moves.append((new_rank, new_file))
  436.                     break
  437.                 else:
  438.                     break
  439.        
  440.         return moves
  441.    
  442.     def generate_rook_moves(self, board, from_pos):
  443.         """Generuje tahy věže"""
  444.         directions = [(0,1), (0,-1), (1,0), (-1,0)]
  445.         return self.generate_sliding_moves(board, from_pos, directions)
  446.    
  447.     def generate_bishop_moves(self, board, from_pos):
  448.         """Generuje tahy střelce"""
  449.         directions = [(1,1), (1,-1), (-1,1), (-1,-1)]
  450.         return self.generate_sliding_moves(board, from_pos, directions)
  451.    
  452.     def generate_queen_moves(self, board, from_pos):
  453.         """Generuje tahy dámy"""
  454.         directions = [(0,1), (0,-1), (1,0), (-1,0), (1,1), (1,-1), (-1,1), (-1,-1)]
  455.         return self.generate_sliding_moves(board, from_pos, directions)
  456.    
  457.     def generate_king_moves(self, board, from_pos):
  458.         """Generuje tahy krále"""
  459.         rank, file = from_pos
  460.         piece = board.board[rank][file]
  461.         color = piece[0]
  462.         moves = []
  463.        
  464.         for dr in [-1, 0, 1]:
  465.             for df in [-1, 0, 1]:
  466.                 if dr == 0 and df == 0:
  467.                     continue
  468.                
  469.                 new_rank = rank + dr
  470.                 new_file = file + df
  471.                
  472.                 if 0 <= new_rank <= 7 and 0 <= new_file <= 7:
  473.                     target = board.board[new_rank][new_file]
  474.                     if not target or target[0] != color:
  475.                         moves.append((new_rank, new_file))
  476.        
  477.         return moves
  478.    
  479.     def generate_pawn_attacks(self, board, from_pos):
  480.         """Generuje útoky pěšce (bez pohybu dopředu)"""
  481.         rank, file = from_pos
  482.         piece = board.board[rank][file]
  483.         color = piece[0]
  484.         moves = []
  485.        
  486.         direction = 1 if color == 'w' else -1
  487.         new_rank = rank + direction
  488.        
  489.         for df in [-1, 1]:
  490.             new_file = file + df
  491.             if 0 <= new_file <= 7 and 0 <= new_rank <= 7:
  492.                 moves.append((new_rank, new_file))
  493.        
  494.         return moves
  495.    
  496.     def is_move_legal(self, board, from_pos, to_pos):
  497.         """Kontroluje zda je tah legální"""
  498.         # Simulace tahu
  499.         temp_board = board.copy()
  500.         temp_board.make_move(from_pos, to_pos)
  501.        
  502.         # Kontrola zda vlastní král není v šachu
  503.         color = 'w' if board.turn else 'b'
  504.         return not temp_board.is_check(color)
  505.    
  506.     def get_all_legal_moves(self, board):
  507.         """Získá všechny legální tahy"""
  508.         moves = []
  509.        
  510.         for rank in range(8):
  511.             for file in range(8):
  512.                 piece = board.board[rank][file]
  513.                 if piece:
  514.                     color = piece[0]
  515.                     if (color == 'w') == board.turn:
  516.                         piece_moves = self.generate_moves(board, (rank, file))
  517.                         for to_pos in piece_moves:
  518.                             moves.append((rank, file, to_pos[0], to_pos[1]))
  519.        
  520.         return moves
  521.    
  522.     def create_position_dict(self, fen, radek):
  523.         """Vytvoří slovník pro pozici"""
  524.         board = ChessBoard(fen)
  525.        
  526.         to_mate = None
  527.         to_end = None
  528.        
  529.         # Získat všechny legální tahy
  530.         legal_moves = self.get_all_legal_moves(board)
  531.        
  532.         # Kontrola koncových pozic
  533.         if len(legal_moves) == 0:
  534.             color = 'w' if board.turn else 'b'
  535.             if board.is_check(color):
  536.                 # Mat
  537.                 to_mate = 0
  538.                 to_end = 0
  539.             else:
  540.                 # Pat
  541.                 to_mate = None
  542.                 to_end = 0
  543.        
  544.         return {
  545.             'radek': radek,
  546.             'N': [],
  547.             'P': [],
  548.             'FEN': board.get_fen(),
  549.             'board': board,
  550.             'to_mate': to_mate,
  551.             'to_end': to_end
  552.         }
  553.    
  554.     def build_position_tree(self, max_depth=5):
  555.         """Postaví strom pozic pomocí BFS"""
  556.         self.iteration_count += 1
  557.         self.print_time("Začátek generování stromu pozic")
  558.        
  559.         # Inicializace
  560.         start_dict = self.create_position_dict(self.start_fen, 0)
  561.         self.L.append(start_dict)
  562.         self.fen_to_index[start_dict['FEN']] = 0
  563.        
  564.         queue = deque([0])
  565.        
  566.         for depth in range(max_depth):
  567.             self.iteration_count += 1
  568.            
  569.             if not queue:
  570.                 break
  571.            
  572.             level_size = len(queue)
  573.             self.print_time(f"Hloubka {depth}, pozic: {level_size}")
  574.            
  575.             for _ in range(level_size):
  576.                 if not queue:
  577.                     break
  578.                
  579.                 current_index = queue.popleft()
  580.                 current_pos = self.L[current_index]
  581.                
  582.                 # Přeskočit koncové pozice
  583.                 if current_pos['to_end'] is not None:
  584.                     continue
  585.                
  586.                 try:
  587.                     # Získat všechny legální tahy
  588.                     legal_moves = self.get_all_legal_moves(current_pos['board'])
  589.                    
  590.                     for move in legal_moves:
  591.                         from_rank, from_file, to_rank, to_file = move
  592.                        
  593.                         # Vytvořit novou pozici
  594.                         temp_board = current_pos['board'].copy()
  595.                         temp_board.make_move((from_rank, from_file), (to_rank, to_file))
  596.                         new_fen = temp_board.get_fen()
  597.                        
  598.                         if new_fen not in self.fen_to_index:
  599.                             # Nová pozice
  600.                             new_dict = self.create_position_dict(new_fen, depth + 1)
  601.                             new_index = len(self.L)
  602.                             self.L.append(new_dict)
  603.                             self.fen_to_index[new_fen] = new_index
  604.                             queue.append(new_index)
  605.                         else:
  606.                             new_index = self.fen_to_index[new_fen]
  607.                        
  608.                         # Přidat vazby
  609.                         if new_index not in current_pos['N']:
  610.                             current_pos['N'].append(new_index)
  611.                         if current_index not in self.L[new_index]['P']:
  612.                             self.L[new_index]['P'].append(current_index)
  613.                            
  614.                 except Exception as e:
  615.                     self.print_time(f"Chyba při generování tahů: {e}")
  616.                     continue
  617.        
  618.         self.print_time(f"Strom postaven, celkem pozic: {len(self.L)}")
  619.    
  620.     def evaluate_positions(self):
  621.         """Ohodnotí všechny pozice pomocí minimax"""
  622.         self.iteration_count += 1
  623.         self.print_time("Začátek ohodnocování pozic")
  624.        
  625.         for iteration in range(50):
  626.             self.iteration_count += 1
  627.            
  628.             if iteration % 10 == 0:
  629.                 self.print_time(f"Iterace ohodnocování {iteration}")
  630.            
  631.             changed = False
  632.            
  633.             # Procházet od nejhlubších pozic
  634.             for i in reversed(range(len(self.L))):
  635.                 pos = self.L[i]
  636.                
  637.                 # Přeskočit už ohodnocené
  638.                 if pos['to_mate'] is not None:
  639.                     continue
  640.                
  641.                 # Koncové pozice bez tahů
  642.                 if not pos['N']:
  643.                     pos['to_mate'] = None
  644.                     pos['to_end'] = 0
  645.                     changed = True
  646.                     continue
  647.                
  648.                 # Kontrola zda jsou všichni následníci ohodnoceni
  649.                 successor_values = []
  650.                 all_evaluated = True
  651.                
  652.                 for succ_idx in pos['N']:
  653.                     if succ_idx < len(self.L):
  654.                         succ = self.L[succ_idx]
  655.                         if succ['to_mate'] is not None:
  656.                             successor_values.append(succ['to_mate'])
  657.                         elif succ['to_end'] == 0:
  658.                             successor_values.append(None)
  659.                         else:
  660.                             all_evaluated = False
  661.                             break
  662.                
  663.                 if all_evaluated and successor_values:
  664.                     # Minimax
  665.                     numeric_values = [v for v in successor_values if v is not None]
  666.                    
  667.                     if not numeric_values:
  668.                         pos['to_mate'] = None
  669.                     else:
  670.                         if pos['board'].turn:  # Bílý minimalizuje
  671.                             pos['to_mate'] = 1 + min(numeric_values)
  672.                         else:  # Černý maximalizuje
  673.                             pos['to_mate'] = 1 + max(numeric_values)
  674.                    
  675.                     pos['to_end'] = pos['to_mate'] if pos['to_mate'] is not None else 0
  676.                     changed = True
  677.            
  678.             if not changed:
  679.                 break
  680.        
  681.         self.print_time("Ohodnocování dokončeno")
  682.    
  683.     def find_optimal_path(self, start_index=0):
  684.         """Najde optimální cestu z dané pozice"""
  685.         path = []
  686.         current_idx = start_index
  687.         visited = set()
  688.        
  689.         while current_idx not in visited and current_idx < len(self.L):
  690.             visited.add(current_idx)
  691.             current_pos = self.L[current_idx]
  692.             path.append(current_idx)
  693.            
  694.             if not current_pos['N'] or current_pos['to_end'] == 0:
  695.                 break
  696.            
  697.             # Najít nejlepší tah
  698.             best_idx = None
  699.             best_value = None
  700.            
  701.             for succ_idx in current_pos['N']:
  702.                 if succ_idx < len(self.L):
  703.                     succ = self.L[succ_idx]
  704.                     value = succ['to_mate']
  705.                    
  706.                     if value is not None:
  707.                         if best_value is None:
  708.                             best_value = value
  709.                             best_idx = succ_idx
  710.                         else:
  711.                             if current_pos['board'].turn:  # Bílý minimalizuje
  712.                                 if value < best_value:
  713.                                     best_value = value
  714.                                     best_idx = succ_idx
  715.                             else:  # Černý maximalizuje
  716.                                 if value > best_value:
  717.                                     best_value = value
  718.                                     best_idx = succ_idx
  719.            
  720.             if best_idx is None:
  721.                 break
  722.            
  723.             current_idx = best_idx
  724.        
  725.         return path
  726.    
  727.     def analyze(self, max_depth=4):
  728.         """Hlavní analýza"""
  729.         start_time = time.time()
  730.         self.iteration_count += 1
  731.         self.print_time("Začátek analýzy")
  732.        
  733.         try:
  734.             # Postavit strom
  735.             self.build_position_tree(max_depth)
  736.            
  737.             # Ohodnotit pozice
  738.             self.evaluate_positions()
  739.            
  740.             # Najít optimální cestu
  741.             optimal_path = self.find_optimal_path()
  742.            
  743.             end_time = time.time()
  744.             self.iteration_count += 1
  745.             self.print_time(f"Analýza dokončena za {end_time - start_time:.2f} sekund")
  746.            
  747.             # Výsledky
  748.             print(f"\nCelkem pozic: {len(self.L)}")
  749.             print(f"Optimální cesta má {len(optimal_path)} tahů")
  750.            
  751.             if len(self.L) > 22:
  752.                 pos_22 = self.L[22]
  753.                 print(f"\nL[22]: {pos_22}")
  754.            
  755.             print(f"\nOptimální cesta (prvních 10 tahů):")
  756.             for i, pos_idx in enumerate(optimal_path[:10]):
  757.                 if pos_idx < len(self.L):
  758.                     pos = self.L[pos_idx]
  759.                     turn = "Bílý" if pos['board'].turn else "Černý"
  760.                     print(f"Tah {i} ({turn}): to_mate={pos['to_mate']}, FEN={pos['FEN'][:50]}...")
  761.                     print_board(pos['board'])
  762.            
  763.             return optimal_path
  764.            
  765.         except Exception as e:
  766.             self.iteration_count += 1
  767.             self.print_time(f"Chyba při analýze: {e}")
  768.             import traceback
  769.             traceback.print_exc()
  770.             return []
  771.  
  772. # Testování
  773. if __name__ == "__main__":
  774.     # Testovací pozice
  775.    
  776.     # 1. Jednoduchá matová pozice (mat v 1 tahu)
  777.     simple_mate = "7k/4A3/8/7K/8/8/8/8 w - - 0 1"
  778.    
  779.     # 2. Pozice s delším matem
  780.     longer_mate = "8/6K1/3b4/4n1k1/8/8/8/8 w - - 0 1"
  781.  
  782.     # 3. Weak Amazon
  783.     weak_amaz = "8/6k1/1A6/8/3K4/8/8/8 w - - 0 1"
  784.    
  785.     # Výběr pozice pro testování
  786.     test_positions = {
  787.         1: ("Jednoduchý mat", simple_mate),
  788.         2: ("Delší mat", longer_mate),
  789.         3: ("Weak Amazon", weak_amaz)
  790.     }
  791.    
  792.     print("Dostupné testovací pozice:")
  793.     for num, (name, fen) in test_positions.items():
  794.         print(f"{num}. {name}: {fen}")
  795.    
  796.     # Použijeme pozici 1 (jednoduchý mat) pro analýzu
  797.     selected_pos = 1
  798.     name, start_fen = test_positions[selected_pos]
  799.    
  800.     print(f"\nTestování šachové analýzy s pohádkovými figurami...")
  801.     print(f"Vybraná pozice: {name}")
  802.     print(f"FEN: {start_fen}")
  803.     print("Pohádkové figury: A=Amazonka(Q+N), C=Cyril(R+N), E=Eve(B+N)")
  804.     print("="*60)
  805.    
  806.     analyzer = FairyChessAnalyzer(start_fen)
  807.     optimal_path = analyzer.analyze(max_depth=12)
  808.    
  809.     print(f"\nFINÁLNÍ VÝSLEDEK:")
  810.     print(f"Pozic: {len(analyzer.L)}")
  811.     print(f"Optimální cesta: {len(optimal_path)} tahů")
  812.    
  813.     if len(optimal_path) > 1:
  814.         start_pos = analyzer.L[0]
  815.         if start_pos['to_mate'] is not None:
  816.             print(f"Mat v {start_pos['to_mate']} tazích")
  817.         else:
  818.             print("Pozice vede k remíze")
  819.     else:
  820.         print("Koncová pozice nebo chyba v analýze")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement