Advertisement
max2201111

snad opraveno

Jul 3rd, 2025
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 29.97 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.        
  117.         # Na tahu
  118.         turn = 'w' if self.turn else 'b'
  119.        
  120.         # Rošáda
  121.         castling = ''
  122.         for right in ['K', 'Q', 'k', 'q']:
  123.             if self.castling_rights[right]:
  124.                 castling += right
  125.         if not castling:
  126.             castling = '-'
  127.        
  128.         # En passant
  129.         en_passant = self.en_passant if self.en_passant else '-'
  130.        
  131.         return f"{position} {turn} {castling} {en_passant} {self.halfmove_clock} {self.fullmove_number}"
  132.    
  133.     def copy(self):
  134.         """Vytvoří kopii šachovnice"""
  135.         new_board = ChessBoard()
  136.         new_board.board = [row[:] for row in self.board]
  137.         new_board.turn = self.turn
  138.         new_board.castling_rights = self.castling_rights.copy()
  139.         new_board.en_passant = self.en_passant
  140.         new_board.halfmove_clock = self.halfmove_clock
  141.         new_board.fullmove_number = self.fullmove_number
  142.         return new_board
  143.    
  144.     def make_move(self, from_pos, to_pos):
  145.         """Provede tah"""
  146.         from_rank, from_file = from_pos
  147.         to_rank, to_file = to_pos
  148.        
  149.         piece = self.board[from_rank][from_file]
  150.         self.board[to_rank][to_file] = piece
  151.         self.board[from_rank][from_file] = None
  152.        
  153.         # Změnit hráče na tahu
  154.         self.turn = not self.turn
  155.        
  156.         # Inkrementovat počítadla
  157.         if self.turn:
  158.             self.fullmove_number += 1
  159.         self.halfmove_clock += 1
  160.    
  161.     def find_king(self, color):
  162.         """Najde krále dané barvy"""
  163.         for rank in range(8):
  164.             for file in range(8):
  165.                 piece = self.board[rank][file]
  166.                 if piece and piece[0] == color and piece[1] == 'K':
  167.                     return (rank, file)
  168.         return None
  169.    
  170.     def is_check(self, color):
  171.         """Kontroluje zda je král v šachu"""
  172.         king_pos = self.find_king(color)
  173.         if not king_pos:
  174.             return False
  175.        
  176.         enemy_color = 'b' if color == 'w' else 'w'
  177.        
  178.         for rank in range(8):
  179.             for file in range(8):
  180.                 piece = self.board[rank][file]
  181.                 if piece and piece[0] == enemy_color:
  182.                     if self.attacks_square((rank, file), king_pos):
  183.                         return True
  184.         return False
  185.    
  186.     def attacks_square(self, from_pos, to_pos):
  187.         """Kontroluje zda figura útočí na dané pole"""
  188.         rank, file = from_pos
  189.         piece = self.board[rank][file]
  190.        
  191.         if not piece:
  192.             return False
  193.        
  194.         color, piece_type = piece
  195.        
  196.         if piece_type == 'P':
  197.             return self.pawn_attacks(from_pos, to_pos, color)
  198.         elif piece_type == 'R':
  199.             return self.rook_attacks(from_pos, to_pos)
  200.         elif piece_type == 'N':
  201.             return self.knight_attacks(from_pos, to_pos)
  202.         elif piece_type == 'B':
  203.             return self.bishop_attacks(from_pos, to_pos)
  204.         elif piece_type == 'Q':
  205.             return self.queen_attacks(from_pos, to_pos)
  206.         elif piece_type == 'K':
  207.             return self.king_attacks(from_pos, to_pos)
  208.         elif piece_type == 'A':  # Amazonka (Q+N)
  209.             return self.queen_attacks(from_pos, to_pos) or self.knight_attacks(from_pos, to_pos)
  210.         elif piece_type == 'C':  # Cyril (R+N)
  211.             return self.rook_attacks(from_pos, to_pos) or self.knight_attacks(from_pos, to_pos)
  212.         elif piece_type == 'E':  # Eve (B+N)
  213.             return self.bishop_attacks(from_pos, to_pos) or self.knight_attacks(from_pos, to_pos)
  214.        
  215.         return False
  216.    
  217.     def pawn_attacks(self, from_pos, to_pos, color):
  218.         """Kontroluje útok pěšce"""
  219.         from_rank, from_file = from_pos
  220.         to_rank, to_file = to_pos
  221.        
  222.         direction = 1 if color == 'w' else -1
  223.        
  224.         return (abs(from_file - to_file) == 1 and
  225.                 to_rank - from_rank == direction)
  226.    
  227.     def knight_attacks(self, from_pos, to_pos):
  228.         """Kontroluje útok jezdce"""
  229.         from_rank, from_file = from_pos
  230.         to_rank, to_file = to_pos
  231.        
  232.         dr = abs(from_rank - to_rank)
  233.         df = abs(from_file - to_file)
  234.        
  235.         return (dr == 2 and df == 1) or (dr == 1 and df == 2)
  236.    
  237.     def rook_attacks(self, from_pos, to_pos):
  238.         """Kontroluje útok věže"""
  239.         from_rank, from_file = from_pos
  240.         to_rank, to_file = to_pos
  241.        
  242.         if from_rank != to_rank and from_file != to_file:
  243.             return False
  244.        
  245.         if from_rank == to_rank:  # Horizontální
  246.             start = min(from_file, to_file) + 1
  247.             end = max(from_file, to_file)
  248.             for f in range(start, end):
  249.                 if self.board[from_rank][f] is not None:
  250.                     return False
  251.         else:  # Vertikální
  252.             start = min(from_rank, to_rank) + 1
  253.             end = max(from_rank, to_rank)
  254.             for r in range(start, end):
  255.                 if self.board[r][from_file] is not None:
  256.                     return False
  257.        
  258.         return True
  259.    
  260.     def bishop_attacks(self, from_pos, to_pos):
  261.         """Kontroluje útok střelce"""
  262.         from_rank, from_file = from_pos
  263.         to_rank, to_file = to_pos
  264.        
  265.         dr = to_rank - from_rank
  266.         df = to_file - from_file
  267.        
  268.         if abs(dr) != abs(df) or dr == 0:
  269.             return False
  270.        
  271.         step_r = 1 if dr > 0 else -1
  272.         step_f = 1 if df > 0 else -1
  273.        
  274.         steps = abs(dr)
  275.         for i in range(1, steps):
  276.             check_rank = from_rank + i * step_r
  277.             check_file = from_file + i * step_f
  278.             if self.board[check_rank][check_file] is not None:
  279.                 return False
  280.        
  281.         return True
  282.    
  283.     def queen_attacks(self, from_pos, to_pos):
  284.         """Kontroluje útok dámy"""
  285.         return self.rook_attacks(from_pos, to_pos) or self.bishop_attacks(from_pos, to_pos)
  286.    
  287.     def king_attacks(self, from_pos, to_pos):
  288.         """Kontroluje útok krále"""
  289.         from_rank, from_file = from_pos
  290.         to_rank, to_file = to_pos
  291.        
  292.         return (abs(from_rank - to_rank) <= 1 and
  293.                 abs(from_file - to_file) <= 1 and
  294.                 from_pos != to_pos)
  295.  
  296. class FairyChessAnalyzer:
  297.     def __init__(self, start_fen):
  298.         self.start_fen = start_fen
  299.         self.L = []
  300.         self.fen_to_index = {}
  301.         self.iteration_count = 0
  302.         # Konstanty pro hodnocení
  303.         self.WHITE_MATE = -1000
  304.         self.BLACK_MATE = 1000
  305.         self.DRAW = 0
  306.        
  307.     def print_time(self, message=""):
  308.         """Vypíše čas ve formátu %hh%mm%ss"""
  309.         now = datetime.now()
  310.         time_str = now.strftime("%H:%M:%S")
  311.         print(f"[{time_str}] Průchod {self.iteration_count}: {message}")
  312.    
  313.     def generate_moves(self, board, from_pos):
  314.         """Generuje všechny možné tahy z dané pozice"""
  315.         rank, file = from_pos
  316.         piece = board.board[rank][file]
  317.        
  318.         if not piece:
  319.             return []
  320.        
  321.         color, piece_type = piece
  322.         moves = []
  323.        
  324.         # Kontrola zda je figura na tahu
  325.         if (color == 'w') != board.turn:
  326.             return []
  327.        
  328.         if piece_type == 'P':
  329.             moves = self.generate_pawn_moves(board, from_pos)
  330.         elif piece_type == 'R':
  331.             moves = self.generate_rook_moves(board, from_pos)
  332.         elif piece_type == 'N':
  333.             moves = self.generate_knight_moves(board, from_pos)
  334.         elif piece_type == 'B':
  335.             moves = self.generate_bishop_moves(board, from_pos)
  336.         elif piece_type == 'Q':
  337.             moves = self.generate_queen_moves(board, from_pos)
  338.         elif piece_type == 'K':
  339.             moves = self.generate_king_moves(board, from_pos)
  340.         elif piece_type == 'A':  # Amazonka (Q+N)
  341.             moves = self.generate_queen_moves(board, from_pos) + self.generate_knight_moves(board, from_pos)
  342.         elif piece_type == 'C':  # Cyril (R+N)
  343.             moves = self.generate_rook_moves(board, from_pos) + self.generate_knight_moves(board, from_pos)
  344.         elif piece_type == 'E':  # Eve (B+N)
  345.             moves = self.generate_bishop_moves(board, from_pos) + self.generate_knight_moves(board, from_pos)
  346.        
  347.         # Filtrovat legální tahy
  348.         legal_moves = []
  349.         for move in moves:
  350.             if self.is_move_legal(board, from_pos, move):
  351.                 legal_moves.append(move)
  352.        
  353.         return legal_moves
  354.    
  355.     def generate_pawn_moves(self, board, from_pos):
  356.         """Generuje tahy pěšce"""
  357.         rank, file = from_pos
  358.         piece = board.board[rank][file]
  359.         color = piece[0]
  360.         moves = []
  361.        
  362.         direction = 1 if color == 'w' else -1
  363.         start_rank = 1 if color == 'w' else 6
  364.        
  365.         # Tah dopředu
  366.         new_rank = rank + direction
  367.         if 0 <= new_rank <= 7 and board.board[new_rank][file] is None:
  368.             moves.append((new_rank, file))
  369.            
  370.             # Dvojitý tah z výchozí pozice
  371.             if rank == start_rank and board.board[new_rank + direction][file] is None:
  372.                 moves.append((new_rank + direction, file))
  373.        
  374.         # Braní
  375.         for df in [-1, 1]:
  376.             new_file = file + df
  377.             if 0 <= new_file <= 7 and 0 <= new_rank <= 7:
  378.                 target = board.board[new_rank][new_file]
  379.                 if target and target[0] != color:
  380.                     moves.append((new_rank, new_file))
  381.        
  382.         return moves
  383.    
  384.     def generate_knight_moves(self, board, from_pos):
  385.         """Generuje tahy jezdce"""
  386.         rank, file = from_pos
  387.         piece = board.board[rank][file]
  388.         color = piece[0]
  389.         moves = []
  390.        
  391.         knight_moves = [(2,1), (2,-1), (-2,1), (-2,-1), (1,2), (1,-2), (-1,2), (-1,-2)]
  392.        
  393.         for dr, df in knight_moves:
  394.             new_rank = rank + dr
  395.             new_file = file + df
  396.            
  397.             if 0 <= new_rank <= 7 and 0 <= new_file <= 7:
  398.                 target = board.board[new_rank][new_file]
  399.                 if not target or target[0] != color:
  400.                     moves.append((new_rank, new_file))
  401.        
  402.         return moves
  403.    
  404.     def generate_sliding_moves(self, board, from_pos, directions):
  405.         """Generuje tahy pro posuvné figury"""
  406.         rank, file = from_pos
  407.         piece = board.board[rank][file]
  408.         color = piece[0]
  409.         moves = []
  410.        
  411.         for dr, df in directions:
  412.             for distance in range(1, 8):
  413.                 new_rank = rank + dr * distance
  414.                 new_file = file + df * distance
  415.                
  416.                 if not (0 <= new_rank <= 7 and 0 <= new_file <= 7):
  417.                     break
  418.                
  419.                 target = board.board[new_rank][new_file]
  420.                
  421.                 if not target:
  422.                     moves.append((new_rank, new_file))
  423.                 elif target[0] != color:
  424.                     moves.append((new_rank, new_file))
  425.                     break
  426.                 else:
  427.                     break
  428.        
  429.         return moves
  430.    
  431.     def generate_rook_moves(self, board, from_pos):
  432.         """Generuje tahy věže"""
  433.         directions = [(0,1), (0,-1), (1,0), (-1,0)]
  434.         return self.generate_sliding_moves(board, from_pos, directions)
  435.    
  436.     def generate_bishop_moves(self, board, from_pos):
  437.         """Generuje tahy střelce"""
  438.         directions = [(1,1), (1,-1), (-1,1), (-1,-1)]
  439.         return self.generate_sliding_moves(board, from_pos, directions)
  440.    
  441.     def generate_queen_moves(self, board, from_pos):
  442.         """Generuje tahy dámy"""
  443.         directions = [(0,1), (0,-1), (1,0), (-1,0), (1,1), (1,-1), (-1,1), (-1,-1)]
  444.         return self.generate_sliding_moves(board, from_pos, directions)
  445.    
  446.     def generate_king_moves(self, board, from_pos):
  447.         """Generuje tahy krále"""
  448.         rank, file = from_pos
  449.         piece = board.board[rank][file]
  450.         color = piece[0]
  451.         moves = []
  452.        
  453.         for dr in [-1, 0, 1]:
  454.             for df in [-1, 0, 1]:
  455.                 if dr == 0 and df == 0:
  456.                     continue
  457.                
  458.                 new_rank = rank + dr
  459.                 new_file = file + df
  460.                
  461.                 if 0 <= new_rank <= 7 and 0 <= new_file <= 7:
  462.                     target = board.board[new_rank][new_file]
  463.                     if not target or target[0] != color:
  464.                         moves.append((new_rank, new_file))
  465.        
  466.         return moves
  467.    
  468.     def is_move_legal(self, board, from_pos, to_pos):
  469.         """Kontroluje zda je tah legální"""
  470.         temp_board = board.copy()
  471.         temp_board.make_move(from_pos, to_pos)
  472.        
  473.         # Kontrola zda vlastní král není v šachu
  474.         color = 'w' if board.turn else 'b'
  475.         return not temp_board.is_check(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 evaluate_position(self, board):
  494.         """Evaluuje pozici - vrací hodnotu z pohledu bílého"""
  495.         # Získat všechny legální tahy
  496.         legal_moves = self.get_all_legal_moves(board)
  497.        
  498.         # Kontrola koncových pozic
  499.         if len(legal_moves) == 0:
  500.             current_color = 'w' if board.turn else 'b'
  501.             if board.is_check(current_color):
  502.                 # Mat - pokud je na tahu bílý a je mat, černý vyhrál
  503.                 return self.WHITE_MATE if board.turn else self.BLACK_MATE
  504.             else:
  505.                 # Pat
  506.                 return self.DRAW
  507.        
  508.         # Pozice není koncová
  509.         return None
  510.    
  511.     def create_position_dict(self, fen, depth):
  512.         """Vytvoří slovník pro pozici"""
  513.         board = ChessBoard(fen)
  514.         evaluation = self.evaluate_position(board)
  515.        
  516.         return {
  517.             'depth': depth,
  518.             'N': [],  # Následníci
  519.             'P': [],  # Předchůdci
  520.             'FEN': board.get_fen(),
  521.             'board': board,
  522.             'evaluation': evaluation,
  523.             'minimax_value': evaluation
  524.         }
  525.    
  526.     def build_position_tree(self, max_depth=5):
  527.         """Postaví strom pozic pomocí BFS"""
  528.         self.iteration_count += 1
  529.         self.print_time("Začátek generování stromu pozic")
  530.        
  531.         # Inicializace
  532.         start_dict = self.create_position_dict(self.start_fen, 0)
  533.         self.L.append(start_dict)
  534.         self.fen_to_index[start_dict['FEN']] = 0
  535.        
  536.         queue = deque([0])
  537.        
  538.         for depth in range(max_depth):
  539.             self.iteration_count += 1
  540.            
  541.             if not queue:
  542.                 break
  543.            
  544.             level_size = len(queue)
  545.             self.print_time(f"Hloubka {depth}, pozic: {level_size}")
  546.            
  547.             for _ in range(level_size):
  548.                 if not queue:
  549.                     break
  550.                
  551.                 current_index = queue.popleft()
  552.                 current_pos = self.L[current_index]
  553.                
  554.                 # Přeskočit koncové pozice
  555.                 if current_pos['evaluation'] is not None:
  556.                     continue
  557.                
  558.                 try:
  559.                     # Získat všechny legální tahy
  560.                     legal_moves = self.get_all_legal_moves(current_pos['board'])
  561.                    
  562.                     for move in legal_moves:
  563.                         from_rank, from_file, to_rank, to_file = move
  564.                        
  565.                         # Vytvořit novou pozici
  566.                         temp_board = current_pos['board'].copy()
  567.                         temp_board.make_move((from_rank, from_file), (to_rank, to_file))
  568.                         new_fen = temp_board.get_fen()
  569.                        
  570.                         if new_fen not in self.fen_to_index:
  571.                             # Nová pozice
  572.                             new_dict = self.create_position_dict(new_fen, depth + 1)
  573.                             new_index = len(self.L)
  574.                             self.L.append(new_dict)
  575.                             self.fen_to_index[new_fen] = new_index
  576.                             queue.append(new_index)
  577.                         else:
  578.                             new_index = self.fen_to_index[new_fen]
  579.                        
  580.                         # Přidat vazby
  581.                         if new_index not in current_pos['N']:
  582.                             current_pos['N'].append(new_index)
  583.                         if current_index not in self.L[new_index]['P']:
  584.                             self.L[new_index]['P'].append(current_index)
  585.                            
  586.                 except Exception as e:
  587.                     self.print_time(f"Chyba při generování tahů: {e}")
  588.                     continue
  589.        
  590.         self.print_time(f"Strom postaven, celkem pozic: {len(self.L)}")
  591.    
  592.     def minimax_evaluation(self):
  593.         """Provede minimax evaluaci pozic"""
  594.         self.iteration_count += 1
  595.         self.print_time("Začátek minimax evaluace")
  596.        
  597.         changed = True
  598.         iterations = 0
  599.        
  600.         while changed and iterations < 100:
  601.             changed = False
  602.             iterations += 1
  603.            
  604.             if iterations % 10 == 0:
  605.                 self.print_time(f"Iterace minimax {iterations}")
  606.            
  607.             # Procházet od nejhlubších pozic
  608.             for i in reversed(range(len(self.L))):
  609.                 pos = self.L[i]
  610.                
  611.                 # Přeskočit už vyhodnocené pozice
  612.                 if pos['minimax_value'] is not None:
  613.                     continue
  614.                
  615.                 # Pokud nemá následníky, už je vyhodnocena
  616.                 if not pos['N']:
  617.                     continue
  618.                
  619.                 # Zkontrolovat zda jsou všichni následníci vyhodnoceni
  620.                 successor_values = []
  621.                 all_evaluated = True
  622.                
  623.                 for succ_idx in pos['N']:
  624.                     if succ_idx < len(self.L):
  625.                         succ_value = self.L[succ_idx]['minimax_value']
  626.                         if succ_value is not None:
  627.                             successor_values.append(succ_value)
  628.                         else:
  629.                             all_evaluated = False
  630.                             break
  631.                
  632.                 if all_evaluated and successor_values:
  633.                     # Aplikovat minimax
  634.                     if pos['board'].turn:  # Bílý na tahu - minimalizuje
  635.                         pos['minimax_value'] = min(successor_values)
  636.                     else:  # Černý na tahu - maximalizuje
  637.                         pos['minimax_value'] = max(successor_values)
  638.                    
  639.                     # Přidat penalizaci za vzdálenost (pokud je to matová pozice)
  640.                     if pos['minimax_value'] == self.WHITE_MATE:
  641.                         pos['minimax_value'] = self.WHITE_MATE + pos['depth']
  642.                     elif pos['minimax_value'] == self.BLACK_MATE:
  643.                         pos['minimax_value'] = self.BLACK_MATE - pos['depth']
  644.                    
  645.                     changed = True
  646.        
  647.         self.print_time(f"Minimax evaluace dokončena po {iterations} iteracích")
  648.    
  649.     def find_best_move_sequence(self, start_index=0):
  650.         """Najde nejlepší sekvenci tahů"""
  651.         sequence = []
  652.         current_idx = start_index
  653.         visited = set()
  654.        
  655.         while current_idx not in visited and current_idx < len(self.L):
  656.             visited.add(current_idx)
  657.             current_pos = self.L[current_idx]
  658.             sequence.append(current_idx)
  659.            
  660.             # Pokud nemá následníky, konec
  661.             if not current_pos['N']:
  662.                 break
  663.            
  664.             # Najít nejlepší tah
  665.             best_idx = None
  666.             best_value = None
  667.            
  668.             for succ_idx in current_pos['N']:
  669.                 if succ_idx < len(self.L):
  670.                     succ_value = self.L[succ_idx]['minimax_value']
  671.                    
  672.                     if succ_value is not None:
  673.                         if best_value is None:
  674.                             best_value = succ_value
  675.                             best_idx = succ_idx
  676.                         else:
  677.                             # Vybrat tah podle minimax
  678.                             if current_pos['board'].turn:  # Bílý minimalizuje
  679.                                 if succ_value < best_value:
  680.                                     best_value = succ_value
  681.                                     best_idx = succ_idx
  682.                             else:  # Černý maximalizuje
  683.                                 if succ_value > best_value:
  684.                                     best_value = succ_value
  685.                                     best_idx = succ_idx
  686.            
  687.             if best_idx is None:
  688.                 break
  689.            
  690.             current_idx = best_idx
  691.        
  692.         return sequence
  693.    
  694.     def analyze(self, max_depth=6):
  695.         """Hlavní analýza"""
  696.         start_time = time.time()
  697.         self.iteration_count += 1
  698.         self.print_time("Začátek analýzy")
  699.        
  700.         try:
  701.             # Postavit strom
  702.             self.build_position_tree(max_depth)
  703.            
  704.             # Provést minimax evaluaci
  705.             self.minimax_evaluation()
  706.            
  707.             # Najít nejlepší sekvenci
  708.             best_sequence = self.find_best_move_sequence()
  709.            
  710.             end_time = time.time()
  711.             self.iteration_count += 1
  712.             self.print_time(f"Analýza dokončena za {end_time - start_time:.2f} sekund")
  713.            
  714.             # Výsledky
  715.             print(f"\nCelkem pozic: {len(self.L)}")
  716.             print(f"Nejlepší sekvence má {len(best_sequence)} tahů")
  717.            
  718.             if self.L:
  719.                 start_value = self.L[0]['minimax_value']
  720.                 print(f"Hodnota počáteční pozice: {start_value}")
  721.                
  722.                 if start_value == self.WHITE_MATE:
  723.                     print("Bílý je v matu!")
  724.                 elif start_value == self.BLACK_MATE:
  725.                     print("Černý je v matu!")
  726.                 elif start_value == self.DRAW:
  727.                     print("Pozice je remíza")
  728.                 elif start_value is not None:
  729.                     if start_value > 0:
  730.                         print(f"Černý má výhodu ({start_value})")
  731.                     else:
  732.                         print(f"Bílý má výhodu ({start_value})")
  733.            
  734.             print(f"\nNejlepší sekvence (prvních 10 tahů):")
  735.             for i, pos_idx in enumerate(best_sequence[:10]):
  736.                 if pos_idx < len(self.L):
  737.                     pos = self.L[pos_idx]
  738.                     turn = "Bílý" if pos['board'].turn else "Černý"
  739.                     value = pos['minimax_value']
  740.                     print(f"Tah {i} ({turn}): hodnota={value}")
  741.                     print_board(pos['board'])
  742.                     print()
  743.            
  744.             return best_sequence
  745.            
  746.         except Exception as e:
  747.             self.iteration_count += 1
  748.             self.print_time(f"Chyba při analýze: {e}")
  749.             import traceback
  750.             traceback.print_exc()
  751.             return []
  752.  
  753. def print_board2(fen):
  754.     """Pomocná funkce pro tisk pozice z FEN"""
  755.     rows = fen.split()[0].split("/")
  756.     print("  +-----------------+")
  757.     for i, row in enumerate(rows):
  758.         line = ""
  759.         for char in row:
  760.             if char.isdigit():
  761.                 line += "." * int(char)
  762.             else:
  763.                 line += char
  764.         print(f"{8 - i} | {' '.join(line)} |")
  765.     print("  +-----------------+")
  766.     print("    a b c d e f g h")
  767.  
  768. # Testování
  769. if __name__ == "__main__":
  770.     # Testovací pozice
  771.     simple_mate = "8/8/8/8/A7/4c1k1/8/6K1 w - - 0 1"
  772.  
  773.     simple_mate = "8/8/8/8/A7/4c1k1/8/6K1 w - - 0 1"
  774.    
  775.     print("TESTOVÁNÍ KOREKTNÍHO ŠACHOVÉHO ANALYZÁTORU")
  776.     print("=" * 60)
  777.    
  778.     print("Výchozí pozice:")
  779.     print_board2(simple_mate)
  780.    
  781.     print(f"\nAnalýza pozice: {simple_mate}")
  782.     print("Pohádkové figury: A=Amazonka(Q+N), C=Cyril(R+N), E=Eve(B+N)")
  783.     print("="*60)
  784.    
  785.     analyzer = FairyChessAnalyzer(simple_mate)
  786.     best_sequence = analyzer.analyze(max_depth=8)
  787.    
  788.     print(f"\nFINÁLNÍ VÝSLEDEK:")
  789.     print(f"Pozic: {len(analyzer.L)}")
  790.     print(f"Nejlepší sekvence: {len(best_sequence)} tahů")
  791.    
  792.     # Detailní analýza prvních tahů
  793.     if len(best_sequence) > 1:
  794.         print("\nDetailní analýza prvních tahů:")
  795.         for i in range(min(3, len(best_sequence) - 1)):
  796.             current_pos = analyzer.L[best_sequence[i]]
  797.             next_pos = analyzer.L[best_sequence[i + 1]]
  798.            
  799.             turn = "Bílý" if current_pos['board'].turn else "Černý"
  800.             value = next_pos['minimax_value']
  801.            
  802.             print(f"\nTah {i + 1} ({turn}): hodnota po tahu = {value}")
  803.             print("Po tahu:")
  804.             print_board(next_pos['board'])
  805.            
  806.             # Zkontrolovat všechny možné následující tahy
  807.             legal_moves = analyzer.get_all_legal_moves(next_pos['board'])
  808.             print(f"Možných tahů pro {('Černý' if next_pos['board'].turn else 'Bílý')}: {len(legal_moves)}")
  809.            
  810.             if len(legal_moves) == 0:
  811.                 if next_pos['board'].is_check('w' if next_pos['board'].turn else 'b'):
  812.                     print("*** POZICE JE MAT! ***")
  813.                 else:
  814.                     print("*** POZICE JE PAT! ***")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement