Advertisement
max2201111

zda se excellent 2

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