Advertisement
max2201111

snad funguje kqK

Apr 1st, 2025
629
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 30.38 KB | Science | 0 0
  1. #!/usr/bin/env python3
  2. import time
  3. import threading
  4. import sys
  5. from math import inf
  6.  
  7. # Globální konstanty – pohyby jezdce (relativní souřadnice)
  8. knight_moves = [(2,1),(2,-1),(-2,1),(-2,-1),(1,2),(1,-2),(-1,2),(-1,-2)]
  9.  
  10. # Globální proměnné pro sledování času
  11. running = False
  12. start_time = 0
  13.  
  14. ###############################################################################
  15. # Funkce pro výpis času v samostatném vlákně
  16. ###############################################################################
  17.  
  18. def time_reporter():
  19.     """Funkce pro výpis aktuálního času každou sekundu na stejném řádku."""
  20.     global running, start_time
  21.     while running:
  22.         elapsed = time.time() - start_time
  23.         hrs = int(elapsed // 3600)
  24.         mins = int((elapsed % 3600) // 60)
  25.         secs = int(elapsed % 60)
  26.        
  27.         # Použijeme \r pro návrat na začátek řádku a přepsání předchozího výpisu
  28.         sys.stdout.write(f"\r[INFO] Uplynulý čas: {hrs:02d}h {mins:02d}m {secs:02d}s")
  29.         sys.stdout.flush()
  30.        
  31.         time.sleep(1)
  32.  
  33. ###############################################################################
  34. # Třída Board – reprezentuje šachovnici a umí ji inicializovat z FEN řetězce.
  35. ###############################################################################
  36.  
  37. class Board:
  38.     def __init__(self, fen=None):
  39.         """Inicializace šachovnice; pokud je zadán FEN, nastaví pozici podle něj."""
  40.         self.grid = [[' ' for _ in range(8)] for _ in range(8)]
  41.         self.to_move = 'w'
  42.         self.castling_rights = set()  # např. {'K','Q','k','q'}
  43.         self.en_passant = None       # (row, col) nebo None
  44.         self.halfmove_clock = 0
  45.         self.fullmove_number = 1
  46.         if fen:
  47.             self.set_fen(fen)
  48.    
  49.     def set_fen(self, fen):
  50.         """Nastaví šachovnici podle FEN řetězce."""
  51.         parts = fen.split()
  52.         while len(parts) < 6:
  53.             parts.append('0')
  54.         board_part, turn_part = parts[0], parts[1]
  55.         castling_part = parts[2] if len(parts) > 2 else '-'
  56.         en_passant_part = parts[3] if len(parts) > 3 else '-'
  57.         halfmove = parts[4] if len(parts) > 4 else '0'
  58.         fullmove = parts[5] if len(parts) > 5 else '1'
  59.         self.grid = [['.' for _ in range(8)] for _ in range(8)]
  60.         ranks = board_part.split('/')
  61.         # FEN řady začínají od horní (8.) a jdou dolů
  62.         for rank_idx, rank_str in enumerate(ranks):
  63.             file_idx = 0
  64.             for ch in rank_str:
  65.                 if ch.isdigit():
  66.                     file_idx += int(ch)
  67.                 else:
  68.                     self.grid[rank_idx][file_idx] = ch
  69.                     file_idx += 1
  70.         self.to_move = 'w' if turn_part == 'w' else 'b'
  71.         self.castling_rights = set() if castling_part == '-' else set(castling_part)
  72.         self.en_passant = None
  73.         if en_passant_part != '-' and en_passant_part != '':
  74.             file = ord(en_passant_part[0]) - ord('a')
  75.             rank = int(en_passant_part[1])
  76.             ri = 8 - rank
  77.             fi = file
  78.             if 0 <= ri < 8 and 0 <= fi < 8:
  79.                 self.en_passant = (ri, fi)
  80.         try:
  81.             self.halfmove_clock = int(halfmove)
  82.         except:
  83.             self.halfmove_clock = 0
  84.         try:
  85.             self.fullmove_number = int(fullmove)
  86.         except:
  87.             self.fullmove_number = 1
  88.    
  89.     def copy(self):
  90.         """Vytvoří hlubokou kopii šachovnice."""
  91.         new_board = Board()
  92.         new_board.grid = [row.copy() for row in self.grid]
  93.         new_board.to_move = self.to_move
  94.         new_board.castling_rights = set(self.castling_rights)
  95.         new_board.en_passant = None if self.en_passant is None else (self.en_passant[0], self.en_passant[1])
  96.         new_board.halfmove_clock = self.halfmove_clock
  97.         new_board.fullmove_number = self.fullmove_number
  98.         return new_board
  99.  
  100.     def display(self):
  101.         """Vrátí textovou reprezentaci šachovnice."""
  102.         lines = []
  103.         for ri in range(8):
  104.             line = ""
  105.             for fi in range(8):
  106.                 line += self.grid[ri][fi] + " "
  107.             lines.append(line)
  108.         return "\n".join(lines)
  109.  
  110. ###############################################################################
  111. # Funkce pro detekci šachu, generování tahů a jejich provádění
  112. ###############################################################################
  113.  
  114. def find_king(board, side):
  115.     """Najde pozici krále pro stranu 'w' nebo 'b'."""
  116.     target = 'K' if side=='w' else 'k'
  117.     for r in range(8):
  118.         for c in range(8):
  119.             if board.grid[r][c] == target:
  120.                 return (r, c)
  121.     return None
  122.  
  123. def is_square_attacked(board, r, c, by_side):
  124.     """Zjistí, zda je pole (r,c) napadeno stranou by_side."""
  125.     # Útoky pěšcem
  126.     if by_side == 'b':
  127.         if r+1 < 8 and c-1 >= 0 and board.grid[r+1][c-1] == 'p': return True
  128.         if r+1 < 8 and c+1 < 8 and board.grid[r+1][c+1] == 'p': return True
  129.     else:
  130.         if r-1 >= 0 and c-1 >= 0 and board.grid[r-1][c-1] == 'P': return True
  131.         if r-1 >= 0 and c+1 < 8 and board.grid[r-1][c+1] == 'P': return True
  132.    
  133.     # Útoky jezdcem a dalšími s jezdcovým pohybem (N, A, C, E)
  134.     enemy_knights = ['n','a','c','e'] if by_side=='b' else ['N','A','C','E']
  135.     for dr, dc in knight_moves:
  136.         nr, nc = r+dr, c+dc
  137.         if 0<=nr<8 and 0<=nc<8 and board.grid[nr][nc] in enemy_knights:
  138.             return True
  139.    
  140.     # Útoky po řadách/sloupcích (R, Q, E, A)
  141.     enemy_rook_like = ['r','q','e','a'] if by_side=='b' else ['R','Q','E','A']
  142.     for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:
  143.         nr, nc = r+dr, c+dc
  144.         while 0<=nr<8 and 0<=nc<8:
  145.             if board.grid[nr][nc] != '.':
  146.                 if board.grid[nr][nc] in enemy_rook_like:
  147.                     return True
  148.                 break
  149.             nr += dr; nc += dc
  150.    
  151.     # Útoky diagonálně (B, Q, C, A)
  152.     enemy_bishop_like = ['b','q','c','a'] if by_side=='b' else ['B','Q','C','A']
  153.     for dr, dc in [(1,1),(1,-1),(-1,1),(-1,-1)]:
  154.         nr, nc = r+dr, c+dc
  155.         while 0<=nr<8 and 0<=nc<8:
  156.             if board.grid[nr][nc] != '.':
  157.                 if board.grid[nr][nc] in enemy_bishop_like:
  158.                     return True
  159.                 break
  160.             nr += dr; nc += dc
  161.    
  162.     # Sousední král
  163.     enemy_king = 'k' if by_side=='b' else 'K'
  164.     for dr in [-1,0,1]:
  165.         for dc in [-1,0,1]:
  166.             if dr==0 and dc==0: continue
  167.             nr, nc = r+dr, c+dc
  168.             if 0<=nr<8 and 0<=nc<8 and board.grid[nr][nc] == enemy_king:
  169.                 return True
  170.    
  171.     return False
  172.  
  173. def is_in_check(board, side):
  174.     """Zjistí, zda je král strany side ('w' nebo 'b') v šachu."""
  175.     king_pos = find_king(board, side)
  176.     if not king_pos:
  177.         return False
  178.     kr, kc = king_pos
  179.     enemy_side = 'b' if side=='w' else 'w'
  180.     return is_square_attacked(board, kr, kc, enemy_side)
  181.  
  182. def generate_pseudo_moves(board, side):
  183.     """Generuje všechny pseudolegální tahy pro stranu side ('w' nebo 'b')."""
  184.     moves = []
  185.     enemy = 'b' if side=='w' else 'w'
  186.     is_white = (side=='w')
  187.     pawn_dir = -1 if is_white else 1
  188.     start_rank = 6 if is_white else 1
  189.     promote_rank = 0 if is_white else 7
  190.     for r in range(8):
  191.         for c in range(8):
  192.             piece = board.grid[r][c]
  193.             if piece == '.': continue
  194.             if is_white and not piece.isupper(): continue
  195.             if not is_white and not piece.islower(): continue
  196.             pt = piece.upper()
  197.             if pt == 'P':
  198.                 nr = r + pawn_dir
  199.                 if 0<=nr<8 and board.grid[nr][c]=='.':
  200.                     if nr==promote_rank:
  201.                         for promo in ['Q','R','B','N','A','E','C']:
  202.                             moves.append((r, c, nr, c, promo if is_white else promo.lower(), None))
  203.                     else:
  204.                         moves.append((r, c, nr, c, None, None))
  205.                     if r==start_rank and board.grid[r+pawn_dir*2][c]=='.' and board.grid[r+pawn_dir][c]=='.':
  206.                         moves.append((r, c, r+pawn_dir*2, c, None, 'double'))
  207.                 for dc in [-1,1]:
  208.                     nc = c + dc
  209.                     if 0<=nc<8 and 0<=nr<8:
  210.                         if board.grid[nr][nc] != '.' and ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
  211.                             if nr==promote_rank:
  212.                                 for promo in ['Q','R','B','N','A','E','C']:
  213.                                     moves.append((r, c, nr, nc, promo if is_white else promo.lower(), None))
  214.                             else:
  215.                                 moves.append((r, c, nr, nc, None, None))
  216.                         if board.en_passant == (nr, nc):
  217.                             moves.append((r, c, nr, nc, None, 'enpassant'))
  218.             elif pt == 'K':
  219.                 for dr in [-1,0,1]:
  220.                     for dc in [-1,0,1]:
  221.                         if dr==0 and dc==0: continue
  222.                         nr, nc = r+dr, c+dc
  223.                         if 0<=nr<8 and 0<=nc<8:
  224.                             if board.grid[nr][nc]=='.' or ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
  225.                                 moves.append((r, c, nr, nc, None, None))
  226.                 # Rošády (základní verze)
  227.                 if is_white and r==7 and c==4:
  228.                     if 'K' in board.castling_rights and board.grid[7][5]=='.' and board.grid[7][6]=='.':
  229.                         moves.append((7,4,7,6,None,'castle'))
  230.                     if 'Q' in board.castling_rights and board.grid[7][3]=='.' and board.grid[7][2]=='.' and board.grid[7][1]=='.':
  231.                         moves.append((7,4,7,2,None,'castle'))
  232.                 if not is_white and r==0 and c==4:
  233.                     if 'k' in board.castling_rights and board.grid[0][5]=='.' and board.grid[0][6]=='.':
  234.                         moves.append((0,4,0,6,None,'castle'))
  235.                     if 'q' in board.castling_rights and board.grid[0][3]=='.' and board.grid[0][2]=='.' and board.grid[0][1]=='.':
  236.                         moves.append((0,4,0,2,None,'castle'))
  237.             else:
  238.                 # Tahy pro figury s jezdcovým pohybem (N, A, C, E)
  239.                 if pt in ['N','A','C','E']:
  240.                     for dr, dc in knight_moves:
  241.                         nr, nc = r+dr, c+dc
  242.                         if 0<=nr<8 and 0<=nc<8:
  243.                             if board.grid[nr][nc]=='.' or ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
  244.                                 moves.append((r, c, nr, nc, None, None))
  245.                 # Klouzavé tahy – pro R, Q, E, A
  246.                 if pt in ['R','Q','E','A']:
  247.                     for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:
  248.                         nr, nc = r+dr, c+dc
  249.                         while 0<=nr<8 and 0<=nc<8:
  250.                             if board.grid[nr][nc]=='.':
  251.                                 moves.append((r, c, nr, nc, None, None))
  252.                             else:
  253.                                 if ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
  254.                                     moves.append((r, c, nr, nc, None, None))
  255.                                 break
  256.                             nr += dr; nc += dc
  257.                 if pt in ['B','Q','C','A']:
  258.                     for dr, dc in [(1,1),(1,-1),(-1,1),(-1,-1)]:
  259.                         nr, nc = r+dr, c+dc
  260.                         while 0<=nr<8 and 0<=nc<8:
  261.                             if board.grid[nr][nc]=='.':
  262.                                 moves.append((r, c, nr, nc, None, None))
  263.                             else:
  264.                                 if ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
  265.                                     moves.append((r, c, nr, nc, None, None))
  266.                                 break
  267.                             nr += dr; nc += dc
  268.     return moves
  269.  
  270. def get_legal_moves(board, side):
  271.     """Vrátí seznam legálních tahů pro danou stranu."""
  272.     moves = generate_pseudo_moves(board, side)
  273.     legal_moves = []
  274.     for move in moves:
  275.         make_move(move, board)
  276.         if not is_in_check(board, side):
  277.             legal_moves.append(move)
  278.         undo_move(board)
  279.     return legal_moves
  280.  
  281. # Zásobník pro tahy (pro undo)
  282. move_stack = []
  283.  
  284. def make_move(move, board):
  285.     """Provede tah na šachovnici a uloží stav pro možnost undo.
  286.       move: (r1, c1, r2, c2, promo, special)"""
  287.     r1, c1, r2, c2, promo, special = move
  288.     piece = board.grid[r1][c1]
  289.     captured = board.grid[r2][c2] if special != 'enpassant' else ('p' if piece=='P' else 'P')
  290.     prev_state = (set(board.castling_rights), board.en_passant)
  291.     move_stack.append((r1, c1, r2, c2, promo, special, piece, captured, prev_state))
  292.     board.grid[r1][c1] = '.'
  293.     if special == 'castle':
  294.         board.grid[r2][c2] = piece
  295.         if piece == 'K':
  296.             if c2 == 6:
  297.                 board.grid[7][5] = 'R'; board.grid[7][7] = '.'
  298.             else:
  299.                 board.grid[7][3] = 'R'; board.grid[7][0] = '.'
  300.         else:
  301.             if c2 == 6:
  302.                 board.grid[0][5] = 'r'; board.grid[0][7] = '.'
  303.             else:
  304.                 board.grid[0][3] = 'r'; board.grid[0][0] = '.'
  305.     elif special == 'enpassant':
  306.         board.grid[r2][c2] = piece
  307.         if piece == 'P':
  308.             board.grid[r2+1][c2] = '.'
  309.         else:
  310.             board.grid[r2-1][c2] = '.'
  311.     else:
  312.         board.grid[r2][c2] = promo if promo else piece
  313.     if piece == 'K':
  314.         board.castling_rights.discard('K'); board.castling_rights.discard('Q')
  315.     if piece == 'k':
  316.         board.castling_rights.discard('k'); board.castling_rights.discard('q')
  317.     if piece == 'R' and (r1, c1)==(7,7):
  318.         board.castling_rights.discard('K')
  319.     if piece == 'R' and (r1, c1)==(7,0):
  320.         board.castling_rights.discard('Q')
  321.     if piece == 'r' and (r1, c1)==(0,7):
  322.         board.castling_rights.discard('k')
  323.     if piece == 'r' and (r1, c1)==(0,0):
  324.         board.castling_rights.discard('q')
  325.     if special == 'double':
  326.         board.en_passant = (r1 + (-1 if board.to_move=='w' else 1), c1)
  327.     else:
  328.         board.en_passant = None
  329.     board.to_move = 'b' if board.to_move=='w' else 'w'
  330.  
  331. def undo_move(board):
  332.     """Vrátí poslední provedený tah."""
  333.     r1, c1, r2, c2, promo, special, piece, captured, prev_state = move_stack.pop()
  334.     board.grid[r1][c1] = piece
  335.     if special == 'castle':
  336.         board.grid[r2][c2] = '.'
  337.         if piece == 'K':
  338.             if c2 == 6:
  339.                 board.grid[7][7] = 'R'; board.grid[7][5] = '.'
  340.             else:
  341.                 board.grid[7][0] = 'R'; board.grid[7][3] = '.'
  342.         else:
  343.             if c2 == 6:
  344.                 board.grid[0][7] = 'r'; board.grid[0][5] = '.'
  345.             else:
  346.                 board.grid[0][0] = 'r'; board.grid[0][3] = '.'
  347.     elif special == 'enpassant':
  348.         board.grid[r2][c2] = '.'
  349.         if piece == 'P':
  350.             board.grid[r2+1][c2] = 'p'
  351.         else:
  352.             board.grid[r2-1][c2] = 'P'
  353.     else:
  354.         board.grid[r2][c2] = captured
  355.     board.castling_rights, board.en_passant = prev_state
  356.     board.to_move = 'b' if board.to_move=='w' else 'w'
  357.  
  358. ###############################################################################
  359. # Jednoduchá funkce pro zjištění, zda je mat v určité hloubce
  360. # (pro pomoc s detekcí matů za určitý počet tahů)
  361. ###############################################################################
  362.  
  363. def is_mate_in_n(board, side, depth):
  364.     """Zkontroluje, zda je pozice mat (pro stranu side) v zadané hloubce."""
  365.     if depth == 0:
  366.         # Kontrola matu
  367.         legal_moves = get_legal_moves(board, side)
  368.         return not legal_moves and is_in_check(board, side)
  369.    
  370.     # Rekurzivní kontrola pro stranu side (zda má vynucený mat)
  371.     legal_moves = get_legal_moves(board, side)
  372.    
  373.     if not legal_moves:
  374.         return False  # Nemáme tahy, nemůžeme dát mat
  375.    
  376.     # Zkontrolujeme všechny tahy, musí existovat alespoň jeden, který vede k matu
  377.     opponent = 'b' if side=='w' else 'w'
  378.     for move in legal_moves:
  379.         make_move(move, board)
  380.         # Pro všechny odpovědi protivníka musí být mat
  381.         opponent_can_avoid_mate = False
  382.         opponent_legal_moves = get_legal_moves(board, opponent)
  383.        
  384.         if not opponent_legal_moves:
  385.             # Protivník nemá tahy - buď je to mat nebo pat
  386.             if is_in_check(board, opponent):
  387.                 undo_move(board)
  388.                 return True  # Již nyní máme mat
  389.             # Jinak je to pat a to není výhra
  390.        
  391.         # Pokud má protivník tahy, musíme prověřit všechny
  392.         for op_move in opponent_legal_moves:
  393.             make_move(op_move, board)
  394.             if not is_mate_in_n(board, side, depth-1):
  395.                 opponent_can_avoid_mate = True
  396.             undo_move(board)
  397.             if opponent_can_avoid_mate:
  398.                 break
  399.        
  400.         undo_move(board)
  401.        
  402.         # Pokud protivník nemůže vyhnout matu, máme mat za 'depth' tahů
  403.         if not opponent_can_avoid_mate:
  404.             return True
  405.    
  406.     return False
  407.  
  408. ###############################################################################
  409. # Negamax s alfa-beta ořezáváním pro hledání nejlepší sekvence
  410. ###############################################################################
  411.  
  412. def negamax(board, depth, alpha, beta, side):
  413.     """Negamax s alfa-beta ořezáváním.
  414.       side: 1 pro bílého, -1 pro černého.
  415.       Vrací (hodnota, tahová sekvence)."""
  416.     # Koncové podmínky - mat (nebo pat když depth=0)
  417.     curr_color = 'w' if side == 1 else 'b'
  418.     legal_moves = get_legal_moves(board, curr_color)
  419.    
  420.     # Kontrola na mat nebo pat (terminální stavy)
  421.     if not legal_moves:
  422.         if is_in_check(board, curr_color):
  423.             return -inf, []  # Mat
  424.         return 0, []  # Pat
  425.    
  426.     # Dosáhli jsme maximální hloubky - základní ohodnocení
  427.     if depth == 0:
  428.         # Kontrola, zda máme mat v nejbližších tazích
  429.         enemy_color = 'b' if curr_color == 'w' else 'w'
  430.         for move in legal_moves:
  431.             make_move(move, board)
  432.             enemy_legal_moves = get_legal_moves(board, enemy_color)
  433.                
  434.             if not enemy_legal_moves and is_in_check(board, enemy_color):
  435.                 undo_move(board)
  436.                 return inf, [move]  # Našli jsme mat
  437.             undo_move(board)
  438.        
  439.         # Pro jednoduchost zde neohodnocujeme materiál, pozici atd.
  440.         # V reálném šachovém enginu bychom zde vraceli pozici na základě materiálu, struktury pěšců atd.
  441.         return 0, []
  442.    
  443.     best_val = -inf
  444.     best_line = []
  445.    
  446.     # Seřazení tahů pro alfa-beta
  447.     legal_moves.sort(key=lambda m: 1 if board.grid[m[2]][m[3]] != '.' else 0, reverse=True)
  448.    
  449.     for move in legal_moves:
  450.         make_move(move, board)
  451.         val, line = negamax(board, depth-1, -beta, -alpha, -side)
  452.         val = -val
  453.         undo_move(board)
  454.        
  455.         if val > best_val:
  456.             best_val = val
  457.             best_line = [move] + line
  458.        
  459.         alpha = max(alpha, best_val)
  460.         if alpha >= beta:
  461.             break
  462.    
  463.     return best_val, best_line
  464.  
  465. ###############################################################################
  466. # Iterativní prohlubování – hledáme do maximální hloubky a vypisujeme uplynulý čas
  467. ###############################################################################
  468.  
  469. def iterative_deepening(board, max_depth=50, time_limit=300):
  470.     """Iterativní prohlubování s časovým limitem (výchozí 5 minut)."""
  471.     global running, start_time
  472.    
  473.     # Spuštění časovacího vlákna
  474.     running = True
  475.     start_time = time.time()
  476.     timer_thread = threading.Thread(target=time_reporter)
  477.     timer_thread.daemon = True
  478.     timer_thread.start()
  479.    
  480.     best_line = []
  481.     best_val = 0
  482.    
  483.     try:
  484.         # Nejdříve zkontrolujeme, zda máme vůbec nějaké legální tahy
  485.         curr_side = board.to_move
  486.         enemy_side = 'b' if curr_side=='w' else 'w'
  487.        
  488.         legal_moves = get_legal_moves(board, curr_side)
  489.        
  490.         # Pokud nemáme žádné legální tahy, je to pat nebo mat
  491.         if not legal_moves:
  492.             total_elapsed = time.time() - start_time
  493.             running = False
  494.             if is_in_check(board, curr_side):
  495.                 return -inf, [], total_elapsed  # Mat
  496.             return 0, [], total_elapsed  # Pat
  497.        
  498.         # Zkontrolujeme, zda máme mat v jednom tahu
  499.         for move in legal_moves:
  500.             make_move(move, board)
  501.             enemy_legal = get_legal_moves(board, enemy_side)
  502.            
  503.             if not enemy_legal and is_in_check(board, enemy_side):
  504.                 # Našli jsme mat v jednom tahu
  505.                 undo_move(board)
  506.                 running = False
  507.                 return inf, [move], 0.1
  508.             undo_move(board)
  509.        
  510.         # Pokud máme jen jeden legální tah, vrátíme ho bez dalšího počítání
  511.         if len(legal_moves) == 1:
  512.             running = False
  513.             return 0, legal_moves, 0.1
  514.        
  515.         # Nyní začněme iterativní prohlubování
  516.         for depth in range(1, max_depth+1):
  517.             t0 = time.time()
  518.             val, line = negamax(board, depth, -inf, inf, 1 if board.to_move=='w' else -1)
  519.             t1 = time.time()
  520.             elapsed = time.time() - start_time
  521.            
  522.             # Výpis času po dosažení každé hloubky
  523.             hrs = int(elapsed // 3600)
  524.             mins = int((elapsed % 3600) // 60)
  525.             secs = int(elapsed % 60)
  526.            
  527.             # Po výpisu každé hloubky přejdeme na nový řádek
  528.             move_time = t1 - t0
  529.             sys.stdout.write("\n")  # Nový řádek po časovém informačním řádku
  530.             print(f"Hloubka {depth:2d} – uplynulý čas: {hrs:02d}h {mins:02d}m {secs:02d}s (poslední krok: {move_time:.2f}s)")
  531.            
  532.             # Zobrazení aktuální nejlepší pozice pro tuto hloubku
  533.             if line:
  534.                 print(f"\nNejlepší sekvence v hloubce {depth}:")
  535.                 variant_board = board.copy()
  536.                
  537.                 # Oprava: Použijeme celou sekvenci tahů, ne jen první tah
  538.                 for i, move in enumerate(line):
  539.                     make_move(move, variant_board)
  540.                     move_notation = move_to_notation(move)
  541.                     print(f"Tah {i+1}: {move_notation}")
  542.                
  543.                 print(variant_board.display())
  544.                 print("-" * 40)
  545.             else:
  546.                 print("\nŽádná nalezená sekvence v této hloubce.")
  547.            
  548.             # Aktualizujeme nejlepší nalezenou sekvenci
  549.             best_val = val
  550.             best_line = line
  551.            
  552.             # Pokud jsme našli vynucený mat nebo pat, končíme
  553.             if abs(val) == inf or time.time() - start_time > time_limit:
  554.                 if time.time() - start_time > time_limit:
  555.                     print(f"Časový limit vypršel po {time_limit} sekundách")
  556.                 break
  557.        
  558.         # Ověření, že když máme tahy, tak vrátíme nejlepší z nich (i když je remíza)
  559.         if not best_line and legal_moves:
  560.             best_line = [legal_moves[0]]
  561.                
  562.         total_elapsed = time.time() - start_time
  563.         return best_val, best_line, total_elapsed
  564.    
  565.     finally:
  566.         # Zajistíme ukončení časovacího vlákna
  567.         running = False
  568.         timer_thread.join(timeout=1.0)
  569.         # Přejdeme na nový řádek po posledním časovém výpisu
  570.         sys.stdout.write("\n")
  571.         sys.stdout.flush()
  572.  
  573. ###############################################################################
  574. # Testovací funkce pro kontrolu, zda jsou tahy e4 správně generovány
  575. ###############################################################################
  576.  
  577. def debug_king_moves(fen="8/8/8/8/8/kq2K3/8/8 w - - 0 1"):
  578.     """Testovací funkce pro zobrazení generovaných tahů krále."""
  579.     board = Board(fen)
  580.     print("Pozice:")
  581.     print(board.display())
  582.    
  583.     side = board.to_move
  584.     king_pos = find_king(board, side)
  585.     if not king_pos:
  586.         print("Král nenalezen!")
  587.         return
  588.    
  589.     kr, kc = king_pos
  590.     print(f"Král na pozici: {'abcdefgh'[kc]}{8-kr} ({kr},{kc})")
  591.    
  592.     # Generujeme tahy krále
  593.     king_moves = []
  594.     for dr in [-1, 0, 1]:
  595.         for dc in [-1, 0, 1]:
  596.             if dr == 0 and dc == 0:
  597.                 continue
  598.             nr, nc = kr + dr, kc + dc
  599.             if 0 <= nr < 8 and 0 <= nc < 8:
  600.                 king_moves.append((nr, nc))
  601.    
  602.     print("Možné tahy krále:")
  603.     for nr, nc in king_moves:
  604.         # Zjistíme, zda je tam vlastní figura
  605.         piece = board.grid[nr][nc]
  606.         enemy_side = 'b' if side == 'w' else 'w'
  607.         attacked = is_square_attacked(board, nr, nc, enemy_side)
  608.        
  609.         status = ""
  610.         if piece != '.':
  611.             is_own = (side == 'w' and piece.isupper()) or (side == 'b' and piece.islower())
  612.             if is_own:
  613.                 status = "vlastní figura"
  614.             else:
  615.                 status = f"soupeřova figura {piece}"
  616.        
  617.         if attacked:
  618.             status += " (napadeno)"
  619.        
  620.         if not status:
  621.             status = "volné pole"
  622.        
  623.         print(f"  {'abcdefgh'[nc]}{8-nr} ({nr},{nc}): {status}")
  624.    
  625.     # Generování legálních tahů pomocí generate_pseudo_moves
  626.     print("\nLegální tahy podle generate_pseudo_moves:")
  627.     moves = generate_pseudo_moves(board, side)
  628.     king_moves = []
  629.     for move in moves:
  630.         r1, c1, r2, c2, _, _ = move
  631.         if r1 == kr and c1 == kc:
  632.             king_moves.append(move)
  633.    
  634.     for move in king_moves:
  635.         r1, c1, r2, c2, _, _ = move
  636.         make_move(move, board)
  637.         in_check = is_in_check(board, side)
  638.         undo_move(board)
  639.        
  640.         print(f"  {'abcdefgh'[c1]}{8-r1} -> {'abcdefgh'[c2]}{8-r2}: {'nelegální (šach)' if in_check else 'legální'}")
  641.  
  642. ###############################################################################
  643. # Převod tahu do šachové notace
  644. ###############################################################################
  645.  
  646. def move_to_notation(move):
  647.     cols = "abcdefgh"
  648.     r1, c1, r2, c2, promo, special = move
  649.     if special == 'castle':
  650.         return "O-O" if c2 > c1 else "O-O-O"
  651.     s = cols[c1] + str(8 - r1) + cols[c2] + str(8 - r2)
  652.     if promo:
  653.         s += "=" + promo.upper()
  654.     if special == 'enpassant':
  655.         s += " e.p."
  656.     return s
  657.  
  658. ###############################################################################
  659. # Analýza pozice pro určení výsledku
  660. ###############################################################################
  661.  
  662. def analyze_position(board):
  663.     """Analyzuje pozici a vrací výsledek."""
  664.     # Zjistíme stranu na tahu
  665.     side_to_move = board.to_move
  666.    
  667.     # Zjistíme, zda má strana na tahu legální tahy
  668.     legal_moves = get_legal_moves(board, side_to_move)
  669.    
  670.     # Kontrola na mat nebo pat
  671.     if not legal_moves:
  672.         if is_in_check(board, side_to_move):
  673.             if side_to_move == 'w':
  674.                 return "Mat – černý vyhrává"
  675.             else:
  676.                 return "Mat – bílý vyhrává"
  677.         else:
  678.             return "Pat (remíza)"
  679.    
  680.     # Zjistíme, zda po provedení tahu bude mat
  681.     for move in legal_moves:
  682.         make_move(move, board)
  683.         opponent = 'b' if side_to_move == 'w' else 'w'
  684.         opponent_legal_moves = get_legal_moves(board, opponent)
  685.        
  686.         if not opponent_legal_moves and is_in_check(board, opponent):
  687.             undo_move(board)
  688.             if side_to_move == 'w':
  689.                 return "Mat v příštím tahu – bílý vyhrává"
  690.             else:
  691.                 return "Mat v příštím tahu – černý vyhrává"
  692.         undo_move(board)
  693.    
  694.     # Pokud nemáme ani mat ani pat, pozice je otevřená
  695.     return "Pozice není rozhodnuta"
  696.  
  697. ###############################################################################
  698. # Hlavní program – inicializace z FEN a výpis optimální tahové sekvence
  699. ###############################################################################
  700.  
  701. def main():
  702.     # Nastavíme pozici ze zadaného FEN
  703.     fen = "8/6A1/8/8/8/k1K5/8/8 w - - 0 1"
  704.     fen = "8/8/8/8/8/kq2K3/8/8 w - - 0 1"
  705.  
  706.     # Další příklad pozice
  707.     #fen = "8/8/8/8/8/kq2K3/6A1/8 w - - 0 1"
  708.    
  709.     # Nejprve spustíme debug pro ověření tahů krále
  710.     print("DEBUG TAHŮ KRÁLE:")
  711.     print("-" * 40)
  712.     debug_king_moves(fen)
  713.     print("-" * 40)
  714.    
  715.     board_obj = Board(fen)
  716.     board = board_obj.copy()
  717.    
  718.     print("Počáteční pozice:")
  719.     print(board.display())
  720.     print("\nVyhledávání optimální tahové sekvence – iterativní prohlubování...\n")
  721.    
  722.     # Nastavíme časový limit na 5 minut (300 sekund)
  723.     best_val, best_line, total_elapsed = iterative_deepening(board, max_depth=500, time_limit=inf)
  724.     hrs = int(total_elapsed // 3600)
  725.     mins = int((total_elapsed % 3600) // 60)
  726.     secs = int(total_elapsed % 60)
  727.    
  728.     variant_board = board.copy()
  729.     moves_notation = []
  730.     print("Postup tahů:")
  731.     print("-"*40)
  732.     print("Start:")
  733.     print(variant_board.display())
  734.     print("-"*40)
  735.    
  736.     # Vykonání sekvence tahů a zobrazení průběhu
  737.     for move in best_line:
  738.         s = move_to_notation(move)
  739.         moves_notation.append(s)
  740.         make_move(move, variant_board)
  741.         print("Tah:", s)
  742.         print(variant_board.display())
  743.         print("-"*40)
  744.    
  745.     # Vyhodnocení výsledné pozice
  746.     if best_val == inf:
  747.         result_text = "Mat – bílý vyhrává"
  748.     elif best_val == -inf:
  749.         result_text = "Mat – černý vyhrává"
  750.     else:
  751.         # Pokud engine nenašel jednoznačný výsledek, analyzujeme pozici znovu
  752.         result_text = analyze_position(variant_board)
  753.    
  754.     print("Optimální tahová sekvence:", " ".join(moves_notation) if moves_notation else "(žádný tah)")
  755.     print("Výsledek:", result_text)
  756.     print(f"Celkový uplynulý čas: {hrs:02d}h {mins:02d}m {secs:02d}s")
  757.  
  758. if __name__ == '__main__':
  759.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement