Advertisement
max2201111

ladeni

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