max2201111

great OK 1 figura

Jul 21st, 2025
259
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 30.50 KB | Science | 0 0
  1. import time
  2. import copy
  3. from typing import List, Tuple, Optional, Dict, Set
  4.  
  5. class ChessEngine:
  6.     def __init__(self):
  7.         # Základní nastavení
  8.         self.board = [['' for _ in range(8)] for _ in range(8)]
  9.         self.white_to_move = True
  10.         self.castling_rights = {'K': True, 'Q': True, 'k': True, 'q': True}
  11.         self.en_passant = None
  12.         self.halfmove_clock = 0
  13.         self.fullmove_number = 1
  14.        
  15.         # Hodnoty figur pro evaluaci
  16.         self.piece_values = {
  17.             'P': 100, 'N': 320, 'B': 330, 'R': 500, 'Q': 900, 'K': 20000,
  18.             'p': -100, 'n': -320, 'b': -330, 'r': -500, 'q': -900, 'k': -20000,
  19.             'A': 1200, 'a': -1200,  # Amazonka (kůň + dáma)
  20.             'C': 800, 'c': -800,    # Cyril (kůň + věž)
  21.             'E': 650, 'e': -650     # Eve (kůň + střelec)
  22.         }
  23.        
  24.         # Historie tahů pro výpis cesty
  25.         self.move_history = []
  26.         self.position_history = []
  27.        
  28.     def load_fen(self, fen: str):
  29.         """Načte pozici z FEN stringu"""
  30.         # Nejdříve vymaž šachovnici
  31.         self.board = [['' for _ in range(8)] for _ in range(8)]
  32.        
  33.         parts = fen.split()
  34.        
  35.         # Parsování pozice
  36.         rows = parts[0].split('/')
  37.         for row_idx, row in enumerate(rows):
  38.             if row_idx >= 8:  # Ochrana proti příliš mnoha řádkům
  39.                 break
  40.             col_idx = 0
  41.             for char in row:
  42.                 if col_idx >= 8:  # Ochrana proti překročení sloupců
  43.                     break
  44.                 if char.isdigit():
  45.                     # Prázdná pole
  46.                     empty_squares = int(char)
  47.                     for _ in range(empty_squares):
  48.                         if col_idx < 8:
  49.                             self.board[row_idx][col_idx] = ''
  50.                             col_idx += 1
  51.                 else:
  52.                     self.board[row_idx][col_idx] = char
  53.                     col_idx += 1
  54.        
  55.         # Na tahu
  56.         self.white_to_move = parts[1] == 'w'
  57.        
  58.         # Rošáda
  59.         castling = parts[2] if len(parts) > 2 else '-'
  60.         self.castling_rights = {
  61.             'K': 'K' in castling,
  62.             'Q': 'Q' in castling,
  63.             'k': 'k' in castling,
  64.             'q': 'q' in castling
  65.         }
  66.        
  67.         # En passant
  68.         self.en_passant = parts[3] if len(parts) > 3 and parts[3] != '-' else None
  69.        
  70.         # Počet tahů
  71.         self.halfmove_clock = int(parts[4]) if len(parts) > 4 else 0
  72.         self.fullmove_number = int(parts[5]) if len(parts) > 5 else 1
  73.        
  74.     def to_fen(self) -> str:
  75.         """Převede aktuální pozici na FEN string"""
  76.         # Pozice
  77.         fen_rows = []
  78.         for row in self.board:
  79.             fen_row = ''
  80.             empty_count = 0
  81.             for cell in row:
  82.                 if cell == '':
  83.                     empty_count += 1
  84.                 else:
  85.                     if empty_count > 0:
  86.                         fen_row += str(empty_count)
  87.                         empty_count = 0
  88.                     fen_row += cell
  89.             if empty_count > 0:
  90.                 fen_row += str(empty_count)
  91.             fen_rows.append(fen_row)
  92.        
  93.         board_fen = '/'.join(fen_rows)
  94.        
  95.         # Na tahu
  96.         active_color = 'w' if self.white_to_move else 'b'
  97.        
  98.         # Rošáda
  99.         castling = ''
  100.         if self.castling_rights['K']: castling += 'K'
  101.         if self.castling_rights['Q']: castling += 'Q'
  102.         if self.castling_rights['k']: castling += 'k'
  103.         if self.castling_rights['q']: castling += 'q'
  104.         if not castling: castling = '-'
  105.        
  106.         # En passant
  107.         en_passant = self.en_passant if self.en_passant else '-'
  108.        
  109.         return f"{board_fen} {active_color} {castling} {en_passant} {self.halfmove_clock} {self.fullmove_number}"
  110.    
  111.     def print_board(self):
  112.         """Vypíše šachovnici v ASCII formátu"""
  113.         print("  a b c d e f g h")
  114.         for i in range(8):
  115.             print(f"{8-i} ", end="")
  116.             for j in range(8):
  117.                 piece = self.board[i][j]
  118.                 if piece == '':
  119.                     piece = '.'
  120.                 print(f"{piece} ", end="")
  121.             print(f"{8-i}")
  122.         print("  a b c d e f g h")
  123.         print()
  124.    
  125.     def is_white_piece(self, piece: str) -> bool:
  126.         """Zjistí, zda je figura bílá"""
  127.         return piece.isupper()
  128.    
  129.     def get_piece_moves(self, row: int, col: int, check_castling: bool = True) -> List[Tuple[int, int]]:
  130.         """Získá všechny možné tahy pro figuru na dané pozici"""
  131.         piece = self.board[row][col]
  132.         if piece == '':
  133.             return []
  134.        
  135.         piece_type = piece.lower()
  136.         is_white = self.is_white_piece(piece)
  137.         moves = []
  138.        
  139.         if piece_type == 'p':
  140.             # Pěšec
  141.             direction = -1 if is_white else 1
  142.             start_row = 6 if is_white else 1
  143.            
  144.             # Tah dopředu
  145.             if 0 <= row + direction < 8 and self.board[row + direction][col] == '':
  146.                 moves.append((row + direction, col))
  147.                 # Dvojitý tah z počáteční pozice
  148.                 if row == start_row and self.board[row + 2 * direction][col] == '':
  149.                     moves.append((row + 2 * direction, col))
  150.            
  151.             # Braní úhlopříčně
  152.             for dc in [-1, 1]:
  153.                 new_row, new_col = row + direction, col + dc
  154.                 if 0 <= new_row < 8 and 0 <= new_col < 8:
  155.                     target = self.board[new_row][new_col]
  156.                     if target != '' and self.is_white_piece(target) != is_white:
  157.                         moves.append((new_row, new_col))
  158.                     # En passant
  159.                     elif self.en_passant and self.en_passant == f"{chr(ord('a') + new_col)}{8 - new_row}":
  160.                         moves.append((new_row, new_col))
  161.        
  162.         elif piece_type == 'r':
  163.             # Věž
  164.             directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
  165.             for dr, dc in directions:
  166.                 for i in range(1, 8):
  167.                     new_row, new_col = row + i * dr, col + i * dc
  168.                     if not (0 <= new_row < 8 and 0 <= new_col < 8):
  169.                         break
  170.                     target = self.board[new_row][new_col]
  171.                     if target == '':
  172.                         moves.append((new_row, new_col))
  173.                     else:
  174.                         if self.is_white_piece(target) != is_white:
  175.                             moves.append((new_row, new_col))
  176.                         break
  177.        
  178.         elif piece_type == 'n':
  179.             # Kůň
  180.             knight_moves = [(2, 1), (2, -1), (-2, 1), (-2, -1), (1, 2), (1, -2), (-1, 2), (-1, -2)]
  181.             for dr, dc in knight_moves:
  182.                 new_row, new_col = row + dr, col + dc
  183.                 if 0 <= new_row < 8 and 0 <= new_col < 8:
  184.                     target = self.board[new_row][new_col]
  185.                     if target == '' or self.is_white_piece(target) != is_white:
  186.                         moves.append((new_row, new_col))
  187.        
  188.         elif piece_type == 'b':
  189.             # Střelec
  190.             directions = [(1, 1), (1, -1), (-1, 1), (-1, -1)]
  191.             for dr, dc in directions:
  192.                 for i in range(1, 8):
  193.                     new_row, new_col = row + i * dr, col + i * dc
  194.                     if not (0 <= new_row < 8 and 0 <= new_col < 8):
  195.                         break
  196.                     target = self.board[new_row][new_col]
  197.                     if target == '':
  198.                         moves.append((new_row, new_col))
  199.                     else:
  200.                         if self.is_white_piece(target) != is_white:
  201.                             moves.append((new_row, new_col))
  202.                         break
  203.        
  204.         elif piece_type == 'q':
  205.             # Dáma
  206.             directions = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)]
  207.             for dr, dc in directions:
  208.                 for i in range(1, 8):
  209.                     new_row, new_col = row + i * dr, col + i * dc
  210.                     if not (0 <= new_row < 8 and 0 <= new_col < 8):
  211.                         break
  212.                     target = self.board[new_row][new_col]
  213.                     if target == '':
  214.                         moves.append((new_row, new_col))
  215.                     else:
  216.                         if self.is_white_piece(target) != is_white:
  217.                             moves.append((new_row, new_col))
  218.                         break
  219.        
  220.         elif piece_type == 'k':
  221.             # Král
  222.             king_moves = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)]
  223.             for dr, dc in king_moves:
  224.                 new_row, new_col = row + dr, col + dc
  225.                 if 0 <= new_row < 8 and 0 <= new_col < 8:
  226.                     target = self.board[new_row][new_col]
  227.                     if target == '' or self.is_white_piece(target) != is_white:
  228.                         moves.append((new_row, new_col))
  229.            
  230.             # Rošáda - pouze pokud je povoleno kontrolovat (vyhneme se rekurzi)
  231.             if check_castling and not self.is_in_check(is_white):
  232.                 # Krátká rošáda
  233.                 castling_key = 'K' if is_white else 'k'
  234.                 if self.castling_rights[castling_key]:
  235.                     if (self.board[row][col + 1] == '' and self.board[row][col + 2] == '' and
  236.                         not self.is_square_attacked(row, col + 1, not is_white) and
  237.                         not self.is_square_attacked(row, col + 2, not is_white)):
  238.                         moves.append((row, col + 2))
  239.                
  240.                 # Dlouhá rošáda
  241.                 castling_key = 'Q' if is_white else 'q'
  242.                 if self.castling_rights[castling_key]:
  243.                     if (self.board[row][col - 1] == '' and self.board[row][col - 2] == '' and
  244.                         self.board[row][col - 3] == '' and
  245.                         not self.is_square_attacked(row, col - 1, not is_white) and
  246.                         not self.is_square_attacked(row, col - 2, not is_white)):
  247.                         moves.append((row, col - 2))
  248.        
  249.         elif piece_type == 'a':  # Amazonka (kůň + dáma)
  250.             # Tahy dámy
  251.             directions = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)]
  252.             for dr, dc in directions:
  253.                 for i in range(1, 8):
  254.                     new_row, new_col = row + i * dr, col + i * dc
  255.                     if not (0 <= new_row < 8 and 0 <= new_col < 8):
  256.                         break
  257.                     target = self.board[new_row][new_col]
  258.                     if target == '':
  259.                         moves.append((new_row, new_col))
  260.                     else:
  261.                         if self.is_white_piece(target) != is_white:
  262.                             moves.append((new_row, new_col))
  263.                         break
  264.             # Tahy koně
  265.             knight_moves = [(2, 1), (2, -1), (-2, 1), (-2, -1), (1, 2), (1, -2), (-1, 2), (-1, -2)]
  266.             for dr, dc in knight_moves:
  267.                 new_row, new_col = row + dr, col + dc
  268.                 if 0 <= new_row < 8 and 0 <= new_col < 8:
  269.                     target = self.board[new_row][new_col]
  270.                     if target == '' or self.is_white_piece(target) != is_white:
  271.                         moves.append((new_row, new_col))
  272.        
  273.         elif piece_type == 'c':  # Cyril (kůň + věž)
  274.             # Tahy věže
  275.             directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
  276.             for dr, dc in directions:
  277.                 for i in range(1, 8):
  278.                     new_row, new_col = row + i * dr, col + i * dc
  279.                     if not (0 <= new_row < 8 and 0 <= new_col < 8):
  280.                         break
  281.                     target = self.board[new_row][new_col]
  282.                     if target == '':
  283.                         moves.append((new_row, new_col))
  284.                     else:
  285.                         if self.is_white_piece(target) != is_white:
  286.                             moves.append((new_row, new_col))
  287.                         break
  288.             # Tahy koně
  289.             knight_moves = [(2, 1), (2, -1), (-2, 1), (-2, -1), (1, 2), (1, -2), (-1, 2), (-1, -2)]
  290.             for dr, dc in knight_moves:
  291.                 new_row, new_col = row + dr, col + dc
  292.                 if 0 <= new_row < 8 and 0 <= new_col < 8:
  293.                     target = self.board[new_row][new_col]
  294.                     if target == '' or self.is_white_piece(target) != is_white:
  295.                         moves.append((new_row, new_col))
  296.        
  297.         elif piece_type == 'e':  # Eve (kůň + střelec)
  298.             # Tahy střelce
  299.             directions = [(1, 1), (1, -1), (-1, 1), (-1, -1)]
  300.             for dr, dc in directions:
  301.                 for i in range(1, 8):
  302.                     new_row, new_col = row + i * dr, col + i * dc
  303.                     if not (0 <= new_row < 8 and 0 <= new_col < 8):
  304.                         break
  305.                     target = self.board[new_row][new_col]
  306.                     if target == '':
  307.                         moves.append((new_row, new_col))
  308.                     else:
  309.                         if self.is_white_piece(target) != is_white:
  310.                             moves.append((new_row, new_col))
  311.                         break
  312.             # Tahy koně
  313.             knight_moves = [(2, 1), (2, -1), (-2, 1), (-2, -1), (1, 2), (1, -2), (-1, 2), (-1, -2)]
  314.             for dr, dc in knight_moves:
  315.                 new_row, new_col = row + dr, col + dc
  316.                 if 0 <= new_row < 8 and 0 <= new_col < 8:
  317.                     target = self.board[new_row][new_col]
  318.                     if target == '' or self.is_white_piece(target) != is_white:
  319.                         moves.append((new_row, new_col))
  320.        
  321.         return moves
  322.    
  323.     def is_square_attacked(self, row: int, col: int, by_white: bool) -> bool:
  324.         """Zjistí, zda je pole napadené danou barvou"""
  325.         for r in range(8):
  326.             for c in range(8):
  327.                 piece = self.board[r][c]
  328.                 if piece != '' and self.is_white_piece(piece) == by_white:
  329.                     # Nekontroluji rošádu při detekci napadení (vyhneme se rekurzi)
  330.                     moves = self.get_piece_moves(r, c, check_castling=False)
  331.                     if (row, col) in moves:
  332.                         return True
  333.         return False
  334.    
  335.     def find_king(self, is_white: bool) -> Tuple[int, int]:
  336.         """Najde krále dané barvy"""
  337.         king = 'K' if is_white else 'k'
  338.         for r in range(8):
  339.             for c in range(8):
  340.                 if self.board[r][c] == king:
  341.                     return (r, c)
  342.         return (-1, -1)  # Král nenalezen
  343.    
  344.     def is_in_check(self, is_white: bool) -> bool:
  345.         """Zjistí, zda je král v šachu"""
  346.         king_pos = self.find_king(is_white)
  347.         if king_pos == (-1, -1):
  348.             return False
  349.         return self.is_square_attacked(king_pos[0], king_pos[1], not is_white)
  350.    
  351.     def make_move(self, from_pos: Tuple[int, int], to_pos: Tuple[int, int]) -> bool:
  352.         """Provede tah a vrátí True, pokud je legální"""
  353.         from_row, from_col = from_pos
  354.         to_row, to_col = to_pos
  355.        
  356.         piece = self.board[from_row][from_col]
  357.         if piece == '':
  358.             return False
  359.        
  360.         is_white = self.is_white_piece(piece)
  361.         if is_white != self.white_to_move:
  362.             return False
  363.        
  364.         # Zkontroluj, zda je tah v seznamu možných tahů
  365.         possible_moves = self.get_piece_moves(from_row, from_col)
  366.         if (to_row, to_col) not in possible_moves:
  367.             return False
  368.        
  369.         # Ulož původní stav
  370.         original_board = copy.deepcopy(self.board)
  371.         original_castling = copy.deepcopy(self.castling_rights)
  372.         original_en_passant = self.en_passant
  373.        
  374.         # Proveď tah
  375.         captured_piece = self.board[to_row][to_col]
  376.         self.board[to_row][to_col] = piece
  377.         self.board[from_row][from_col] = ''
  378.        
  379.         # Speciální tahy
  380.         piece_type = piece.lower()
  381.        
  382.         # En passant
  383.         if piece_type == 'p' and self.en_passant and f"{chr(ord('a') + to_col)}{8 - to_row}" == self.en_passant:
  384.             if is_white:
  385.                 self.board[to_row + 1][to_col] = ''
  386.             else:
  387.                 self.board[to_row - 1][to_col] = ''
  388.        
  389.         # Rošáda
  390.         if piece_type == 'k' and abs(to_col - from_col) == 2:
  391.             if to_col > from_col:  # Krátká rošáda
  392.                 self.board[from_row][7] = ''
  393.                 self.board[from_row][5] = 'R' if is_white else 'r'
  394.             else:  # Dlouhá rošáda
  395.                 self.board[from_row][0] = ''
  396.                 self.board[from_row][3] = 'R' if is_white else 'r'
  397.        
  398.         # Aktualizace en passant
  399.         if piece_type == 'p' and abs(to_row - from_row) == 2:
  400.             self.en_passant = f"{chr(ord('a') + from_col)}{8 - (from_row + to_row) // 2}"
  401.         else:
  402.             self.en_passant = None
  403.        
  404.         # Aktualizace rošádových práv
  405.         if piece_type == 'k':
  406.             if is_white:
  407.                 self.castling_rights['K'] = False
  408.                 self.castling_rights['Q'] = False
  409.             else:
  410.                 self.castling_rights['k'] = False
  411.                 self.castling_rights['q'] = False
  412.         elif piece_type == 'r':
  413.             if from_row == 0 or from_row == 7:
  414.                 if from_col == 0:
  415.                     key = 'Q' if from_row == 7 else 'q'
  416.                     self.castling_rights[key] = False
  417.                 elif from_col == 7:
  418.                     key = 'K' if from_row == 7 else 'k'
  419.                     self.castling_rights[key] = False
  420.        
  421.         # Zkontroluj, zda vlastní král není v šachu
  422.         if self.is_in_check(is_white):
  423.             # Vrať původní stav
  424.             self.board = original_board
  425.             self.castling_rights = original_castling
  426.             self.en_passant = original_en_passant
  427.             return False
  428.        
  429.         # Tah je legální
  430.         self.white_to_move = not self.white_to_move
  431.         if not self.white_to_move:
  432.             self.fullmove_number += 1
  433.        
  434.         if captured_piece or piece_type == 'p':
  435.             self.halfmove_clock = 0
  436.         else:
  437.             self.halfmove_clock += 1
  438.        
  439.         return True
  440.    
  441.     def undo_move(self, from_pos: Tuple[int, int], to_pos: Tuple[int, int],
  442.                   captured_piece: str, old_castling: dict, old_en_passant: str,
  443.                   old_halfmove: int, old_fullmove: int, was_white_to_move: bool):
  444.         """Vrátí tah zpět"""
  445.         from_row, from_col = from_pos
  446.         to_row, to_col = to_pos
  447.        
  448.         piece = self.board[to_row][to_col]
  449.         self.board[from_row][from_col] = piece
  450.         self.board[to_row][to_col] = captured_piece
  451.        
  452.         # Vrácení speciálních tahů
  453.         piece_type = piece.lower()
  454.        
  455.         # Rošáda
  456.         if piece_type == 'k' and abs(to_col - from_col) == 2:
  457.             if to_col > from_col:  # Krátká rošáda
  458.                 self.board[from_row][7] = 'R' if self.is_white_piece(piece) else 'r'
  459.                 self.board[from_row][5] = ''
  460.             else:  # Dlouhá rošáda
  461.                 self.board[from_row][0] = 'R' if self.is_white_piece(piece) else 'r'
  462.                 self.board[from_row][3] = ''
  463.        
  464.         # En passant
  465.         if piece_type == 'p' and old_en_passant and f"{chr(ord('a') + to_col)}{8 - to_row}" == old_en_passant:
  466.             if self.is_white_piece(piece):
  467.                 self.board[to_row + 1][to_col] = 'p'
  468.             else:
  469.                 self.board[to_row - 1][to_col] = 'P'
  470.        
  471.         self.castling_rights = old_castling
  472.         self.en_passant = old_en_passant
  473.         self.halfmove_clock = old_halfmove
  474.         self.fullmove_number = old_fullmove
  475.         self.white_to_move = was_white_to_move
  476.    
  477.     def get_all_legal_moves(self) -> List[Tuple[Tuple[int, int], Tuple[int, int]]]:
  478.         """Získá všechny legální tahy pro aktuálního hráče"""
  479.         legal_moves = []
  480.        
  481.         for row in range(8):
  482.             for col in range(8):
  483.                 piece = self.board[row][col]
  484.                 if piece != '' and self.is_white_piece(piece) == self.white_to_move:
  485.                     moves = self.get_piece_moves(row, col)
  486.                     for to_row, to_col in moves:
  487.                         # Zkopíruj stav
  488.                         original_state = self.save_state()
  489.                        
  490.                         # Zkus tah
  491.                         if self.make_move((row, col), (to_row, to_col)):
  492.                             legal_moves.append(((row, col), (to_row, to_col)))
  493.                        
  494.                         # Vrať stav
  495.                         self.restore_state(original_state)
  496.        
  497.         return legal_moves
  498.    
  499.     def save_state(self):
  500.         """Uloží aktuální stav hry"""
  501.         return {
  502.             'board': copy.deepcopy(self.board),
  503.             'white_to_move': self.white_to_move,
  504.             'castling_rights': copy.deepcopy(self.castling_rights),
  505.             'en_passant': self.en_passant,
  506.             'halfmove_clock': self.halfmove_clock,
  507.             'fullmove_number': self.fullmove_number
  508.         }
  509.    
  510.     def restore_state(self, state):
  511.         """Obnoví uložený stav hry"""
  512.         self.board = state['board']
  513.         self.white_to_move = state['white_to_move']
  514.         self.castling_rights = state['castling_rights']
  515.         self.en_passant = state['en_passant']
  516.         self.halfmove_clock = state['halfmove_clock']
  517.         self.fullmove_number = state['fullmove_number']
  518.    
  519.     def evaluate_position(self) -> int:
  520.         """Ohodnotí pozici (pozitivní hodnoty pro bílého, negativní pro černého)"""
  521.         score = 0
  522.        
  523.         for row in range(8):
  524.             for col in range(8):
  525.                 piece = self.board[row][col]
  526.                 if piece != '':
  527.                     score += self.piece_values.get(piece, 0)
  528.        
  529.         return score
  530.    
  531.     def is_checkmate(self) -> bool:
  532.         """Zjistí, zda je mat"""
  533.         if not self.is_in_check(self.white_to_move):
  534.             return False
  535.        
  536.         legal_moves = self.get_all_legal_moves()
  537.         return len(legal_moves) == 0
  538.    
  539.     def is_stalemate(self) -> bool:
  540.         """Zjistí, zda je pat"""
  541.         if self.is_in_check(self.white_to_move):
  542.             return False
  543.        
  544.         legal_moves = self.get_all_legal_moves()
  545.         return len(legal_moves) == 0
  546.    
  547.     def is_game_over(self) -> Tuple[bool, str]:
  548.         """Zjistí, zda je hra u konce"""
  549.         if self.is_checkmate():
  550.             winner = "Černý" if self.white_to_move else "Bílý"
  551.             return True, f"Mat! Vyhrál {winner}."
  552.         elif self.is_stalemate():
  553.             return True, "Pat! Remíza."
  554.         elif self.halfmove_clock >= 100:
  555.             return True, "Remíza podle pravidla 50 tahů."
  556.        
  557.         return False, ""
  558.    
  559.     def minimax(self, depth: int, alpha: int, beta: int, maximizing: bool,
  560.                 path: List[str]) -> Tuple[int, List[str]]:
  561.         """Minimax algoritmus s alfa-beta pruningem"""
  562.         game_over, result = self.is_game_over()
  563.        
  564.         if game_over:
  565.             if "Mat" in result:
  566.                 if "Bílý" in result:
  567.                     return (999999 - len(path), path)
  568.                 else:
  569.                     return (-999999 + len(path), path)
  570.             else:  # Pat nebo remíza
  571.                 return (0, path)
  572.        
  573.         if depth == 0:
  574.             return (self.evaluate_position(), path)
  575.        
  576.         legal_moves = self.get_all_legal_moves()
  577.        
  578.         if maximizing:
  579.             max_eval = float('-inf')
  580.             best_path = path
  581.            
  582.             for move in legal_moves:
  583.                 # Ulož stav
  584.                 original_state = self.save_state()
  585.                
  586.                 # Proveď tah
  587.                 self.make_move(move[0], move[1])
  588.                 move_notation = f"{chr(ord('a') + move[0][1])}{8 - move[0][0]}-{chr(ord('a') + move[1][1])}{8 - move[1][0]}"
  589.                 new_path = path + [move_notation]
  590.                
  591.                 eval_score, eval_path = self.minimax(depth - 1, alpha, beta, False, new_path)
  592.                
  593.                 if eval_score > max_eval:
  594.                     max_eval = eval_score
  595.                     best_path = eval_path
  596.                
  597.                 # Vrať stav
  598.                 self.restore_state(original_state)
  599.                
  600.                 alpha = max(alpha, eval_score)
  601.                 if beta <= alpha:
  602.                     break
  603.            
  604.             return (max_eval, best_path)
  605.        
  606.         else:
  607.             min_eval = float('inf')
  608.             best_path = path
  609.            
  610.             for move in legal_moves:
  611.                 # Ulož stav
  612.                 original_state = self.save_state()
  613.                
  614.                 # Proveď tah
  615.                 self.make_move(move[0], move[1])
  616.                 move_notation = f"{chr(ord('a') + move[0][1])}{8 - move[0][0]}-{chr(ord('a') + move[1][1])}{8 - move[1][0]}"
  617.                 new_path = path + [move_notation]
  618.                
  619.                 eval_score, eval_path = self.minimax(depth - 1, alpha, beta, True, new_path)
  620.                
  621.                 if eval_score < min_eval:
  622.                     min_eval = eval_score
  623.                     best_path = eval_path
  624.                
  625.                 # Vrať stav
  626.                 self.restore_state(original_state)
  627.                
  628.                 beta = min(beta, eval_score)
  629.                 if beta <= alpha:
  630.                     break
  631.            
  632.             return (min_eval, best_path)
  633.    
  634.     def find_best_move(self, max_depth: int = 10) -> Optional[List[str]]:
  635.         """Najde nejlepší tah pomocí iterativního prohloubení"""
  636.         print(f"Hledání nejlepšího tahu (maximální hloubka: {max_depth})...")
  637.         print(f"Na tahu: {'Bílý' if self.white_to_move else 'Černý'}")
  638.         print()
  639.        
  640.         best_path = None
  641.        
  642.         for depth in range(1, max_depth + 1):
  643.             start_time = time.time()
  644.            
  645.             score, path = self.minimax(depth, float('-inf'), float('inf'), True, [])
  646.            
  647.             end_time = time.time()
  648.             elapsed = end_time - start_time
  649.            
  650.             print(f"Hloubka {depth}: skóre {score}, čas {elapsed:.3f}s")
  651.            
  652.             best_path = path
  653.            
  654.             # Pokud byl nalezen mat, skonči
  655.             if abs(score) > 900000:
  656.                 print(f"Nalezen mat v {len(path)} tazích!")
  657.                 break
  658.        
  659.         return best_path
  660.    
  661.     def play_game(self, initial_fen: str = None, max_depth: int = 6):
  662.         """Spustí hru s automatickým hraním"""
  663.         if initial_fen:
  664.             self.load_fen(initial_fen)
  665.         else:
  666.             # Standardní počáteční pozice
  667.             self.load_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
  668.        
  669.         print("=== ŠACHOVÝ ENGINE S NESTANDARDNÍMI FIGURAMI ===")
  670.         print("Legenda figur:")
  671.         print("A/a = Amazonka (Kůň + Dáma)")
  672.         print("C/c = Cyril (Kůň + Věž)")
  673.         print("E/e = Eve (Kůň + Střelec)")
  674.         print()
  675.        
  676.         print("Počáteční pozice:")
  677.         print(f"FEN: {self.to_fen()}")
  678.         self.print_board()
  679.        
  680.         move_count = 0
  681.        
  682.         while True:
  683.             game_over, result = self.is_game_over()
  684.             if game_over:
  685.                 print(result)
  686.                 break
  687.            
  688.             move_count += 1
  689.             print(f"\n=== TAH {move_count} ===")
  690.            
  691.             best_path = self.find_best_move(max_depth)
  692.            
  693.             if not best_path:
  694.                 print("Žádný tah nenalezen!")
  695.                 break
  696.            
  697.             # Simuluj celou cestu k matu
  698.             print(f"\nNalezená cesta k matu ({len(best_path)} tahů):")
  699.            
  700.             current_engine = ChessEngine()
  701.             current_engine.restore_state(self.save_state())
  702.            
  703.             # Vypíš počáteční pozici
  704.             print(f"\nPočáteční pozice:")
  705.             print(f"FEN: {current_engine.to_fen()}")
  706.             current_engine.print_board()
  707.            
  708.             for i, move_notation in enumerate(best_path):
  709.                 # Parsuj a proveď tah
  710.                 from_pos = (8 - int(move_notation[1]), ord(move_notation[0]) - ord('a'))
  711.                 to_pos = (8 - int(move_notation[4]), ord(move_notation[3]) - ord('a'))
  712.                
  713.                 if not current_engine.make_move(from_pos, to_pos):
  714.                     print("Chyba při provádění tahu!")
  715.                     break
  716.                
  717.                 # Teď vypíš pozici PO provedení tahu
  718.                 print(f"\nTah {i + 1}: {move_notation}")
  719.                 print(f"FEN: {current_engine.to_fen()}")
  720.                 current_engine.print_board()
  721.                
  722.                 game_over, result = current_engine.is_game_over()
  723.                 if game_over:
  724.                     print(f"{result}")
  725.                     return
  726.            
  727.             # Proveď první tah z nalezené cesty
  728.             if best_path:
  729.                 first_move = best_path[0]
  730.                 from_pos = (8 - int(first_move[1]), ord(first_move[0]) - ord('a'))
  731.                 to_pos = (8 - int(first_move[4]), ord(first_move[3]) - ord('a'))
  732.                
  733.                 if self.make_move(from_pos, to_pos):
  734.                     print(f"\nProveden tah: {first_move}")
  735.                 else:
  736.                     print("Chyba při provádění prvního tahu!")
  737.                     break
  738.             else:
  739.                 break
  740.  
  741. # Spuštění enginu
  742. if __name__ == "__main__":
  743.     engine = ChessEngine()
  744.    
  745.     # Testovací pozice - zajímavější matový problém
  746.     # Černý král v rohu, bílá Amazonka a král pro demonstraci síly Amazonky
  747.     test_fen = "k7/8/2A5/8/8/8/8/K7 w - - 0 1"
  748.     test_fen = "7A/8/8/8/8/8/6k1/1K6 w - - 0 1"
  749.  
  750.  
  751.     test_fen = "8/8/8/8/8/5BN1/5K1k/8 b - - 0 1"
  752.    
  753.     print(f"Používám testovací pozici s Amazonkou: {test_fen}")
  754.     print("Pozice: Černý král na a8, Bílá Amazonka na c6, Bílý král na a1")
  755.     engine.play_game(test_fen, max_depth=14)
Advertisement
Add Comment
Please, Sign In to add comment