Advertisement
max2201111

NL well done kaK

Apr 1st, 2025
596
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 31.17 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. # Konstanty pro pohyby jezdce
  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 čas a historii tahů
  11. running = False
  12. start_time = 0
  13. move_stack = []
  14.  
  15. def time_reporter():
  16.     """Funkce pro výpis času každou sekundu na stejném řádku."""
  17.     global running, start_time
  18.     while running:
  19.         elapsed = time.time() - start_time
  20.         hrs = int(elapsed // 3600)
  21.         mins = int((elapsed % 3600) // 60)
  22.         secs = int(elapsed % 60)
  23.         sys.stdout.write(f"\r[INFO] Uplynulý čas: {hrs:02d}h {mins:02d}m {secs:02d}s")
  24.         sys.stdout.flush()
  25.         time.sleep(1)
  26.  
  27. class Board:
  28.     def __init__(self, fen=None):
  29.         """Inicializace šachovnice."""
  30.         self.grid = [[' ' for _ in range(8)] for _ in range(8)]
  31.         self.to_move = 'w'
  32.         self.castling_rights = set()
  33.         self.en_passant = None
  34.         self.halfmove_clock = 0
  35.         self.fullmove_number = 1
  36.         if fen:
  37.             self.set_fen(fen)
  38.    
  39.     def set_fen(self, fen):
  40.         """Nastaví šachovnici podle FEN řetězce."""
  41.         parts = fen.split()
  42.         while len(parts) < 6:
  43.             parts.append('0')
  44.         board_part, turn_part = parts[0], parts[1]
  45.         castling_part = parts[2] if len(parts) > 2 else '-'
  46.         en_passant_part = parts[3] if len(parts) > 3 else '-'
  47.         halfmove = parts[4] if len(parts) > 4 else '0'
  48.         fullmove = parts[5] if len(parts) > 5 else '1'
  49.        
  50.         self.grid = [['.' for _ in range(8)] for _ in range(8)]
  51.         ranks = board_part.split('/')
  52.        
  53.         for rank_idx, rank_str in enumerate(ranks):
  54.             file_idx = 0
  55.             for ch in rank_str:
  56.                 if ch.isdigit():
  57.                     file_idx += int(ch)
  58.                 else:
  59.                     self.grid[rank_idx][file_idx] = ch
  60.                     file_idx += 1
  61.        
  62.         self.to_move = 'w' if turn_part == 'w' else 'b'
  63.         self.castling_rights = set() if castling_part == '-' else set(castling_part)
  64.         self.en_passant = None
  65.        
  66.         if en_passant_part != '-' and en_passant_part != '':
  67.             file = ord(en_passant_part[0]) - ord('a')
  68.             rank = int(en_passant_part[1])
  69.             ri = 8 - rank
  70.             fi = file
  71.             if 0 <= ri < 8 and 0 <= fi < 8:
  72.                 self.en_passant = (ri, fi)
  73.        
  74.         try:
  75.             self.halfmove_clock = int(halfmove)
  76.         except:
  77.             self.halfmove_clock = 0
  78.        
  79.         try:
  80.             self.fullmove_number = int(fullmove)
  81.         except:
  82.             self.fullmove_number = 1
  83.    
  84.     def copy(self):
  85.         """Vytvoří hlubokou kopii šachovnice."""
  86.         new_board = Board()
  87.         new_board.grid = [row.copy() for row in self.grid]
  88.         new_board.to_move = self.to_move
  89.         new_board.castling_rights = set(self.castling_rights)
  90.         new_board.en_passant = None if self.en_passant is None else (self.en_passant[0], self.en_passant[1])
  91.         new_board.halfmove_clock = self.halfmove_clock
  92.         new_board.fullmove_number = self.fullmove_number
  93.         return new_board
  94.  
  95.     def display(self):
  96.         """Vrátí textovou reprezentaci šachovnice."""
  97.         lines = []
  98.         for ri in range(8):
  99.             line = ""
  100.             for fi in range(8):
  101.                 line += self.grid[ri][fi] + " "
  102.             lines.append(line)
  103.         return "\n".join(lines)
  104.  
  105. # Základní funkce pro šach
  106. def find_king(board, side):
  107.     """Najde pozici krále pro stranu 'w' nebo 'b'."""
  108.     target = 'K' if side=='w' else 'k'
  109.     for r in range(8):
  110.         for c in range(8):
  111.             if board.grid[r][c] == target:
  112.                 return (r, c)
  113.     return None
  114.  
  115. def is_square_attacked(board, r, c, by_side):
  116.     """Zjistí, zda je pole (r,c) napadeno stranou by_side."""
  117.     # Útoky pěšcem
  118.     if by_side == 'b':
  119.         if r+1 < 8 and c-1 >= 0 and board.grid[r+1][c-1] == 'p': return True
  120.         if r+1 < 8 and c+1 < 8 and board.grid[r+1][c+1] == 'p': return True
  121.     else:
  122.         if r-1 >= 0 and c-1 >= 0 and board.grid[r-1][c-1] == 'P': return True
  123.         if r-1 >= 0 and c+1 < 8 and board.grid[r-1][c+1] == 'P': return True
  124.    
  125.     # Útoky jezdcem a dalšími s jezdcovým pohybem (N, A, C, E)
  126.     enemy_knights = ['n','a','c','e'] if by_side=='b' else ['N','A','C','E']
  127.     for dr, dc in knight_moves:
  128.         nr, nc = r+dr, c+dc
  129.         if 0<=nr<8 and 0<=nc<8 and board.grid[nr][nc] in enemy_knights:
  130.             return True
  131.    
  132.     # Útoky po řadách/sloupcích (R, Q, E, A)
  133.     enemy_rook_like = ['r','q','e','a'] if by_side=='b' else ['R','Q','E','A']
  134.     for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:
  135.         nr, nc = r+dr, c+dc
  136.         while 0<=nr<8 and 0<=nc<8:
  137.             if board.grid[nr][nc] != '.':
  138.                 if board.grid[nr][nc] in enemy_rook_like:
  139.                     return True
  140.                 break
  141.             nr += dr; nc += dc
  142.    
  143.     # Útoky diagonálně (B, Q, C, A)
  144.     enemy_bishop_like = ['b','q','c','a'] if by_side=='b' else ['B','Q','C','A']
  145.     for dr, dc in [(1,1),(1,-1),(-1,1),(-1,-1)]:
  146.         nr, nc = r+dr, c+dc
  147.         while 0<=nr<8 and 0<=nc<8:
  148.             if board.grid[nr][nc] != '.':
  149.                 if board.grid[nr][nc] in enemy_bishop_like:
  150.                     return True
  151.                 break
  152.             nr += dr; nc += dc
  153.    
  154.     # Sousední král
  155.     enemy_king = 'k' if by_side=='b' else 'K'
  156.     for dr in [-1,0,1]:
  157.         for dc in [-1,0,1]:
  158.             if dr==0 and dc==0: continue
  159.             nr, nc = r+dr, c+dc
  160.             if 0<=nr<8 and 0<=nc<8 and board.grid[nr][nc] == enemy_king:
  161.                 return True
  162.    
  163.     return False
  164.  
  165. def is_in_check(board, side):
  166.     """Zjistí, zda je král strany side ('w' nebo 'b') v šachu."""
  167.     king_pos = find_king(board, side)
  168.     if not king_pos:
  169.         return False
  170.     kr, kc = king_pos
  171.     enemy_side = 'b' if side=='w' else 'w'
  172.     return is_square_attacked(board, kr, kc, enemy_side)
  173.  
  174. def generate_pseudo_moves(board, side):
  175.     """Generuje všechny pseudolegální tahy pro stranu side ('w' nebo 'b')."""
  176.     moves = []
  177.     is_white = (side=='w')
  178.     pawn_dir = -1 if is_white else 1
  179.     start_rank = 6 if is_white else 1
  180.     promote_rank = 0 if is_white else 7
  181.    
  182.     for r in range(8):
  183.         for c in range(8):
  184.             piece = board.grid[r][c]
  185.             if piece == '.': continue
  186.             if is_white and not piece.isupper(): continue
  187.             if not is_white and not piece.islower(): continue
  188.            
  189.             pt = piece.upper()
  190.             if pt == 'P':
  191.                 nr = r + pawn_dir
  192.                 if 0<=nr<8 and board.grid[nr][c]=='.':
  193.                     if nr==promote_rank:
  194.                         for promo in ['Q','R','B','N','A','E','C']:
  195.                             moves.append((r, c, nr, c, promo if is_white else promo.lower(), None))
  196.                     else:
  197.                         moves.append((r, c, nr, c, None, None))
  198.                     if r==start_rank and board.grid[r+pawn_dir*2][c]=='.' and board.grid[r+pawn_dir][c]=='.':
  199.                         moves.append((r, c, r+pawn_dir*2, c, None, 'double'))
  200.                 for dc in [-1,1]:
  201.                     nc = c + dc
  202.                     if 0<=nc<8 and 0<=nr<8:
  203.                         if board.grid[nr][nc] != '.' and ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
  204.                             if nr==promote_rank:
  205.                                 for promo in ['Q','R','B','N','A','E','C']:
  206.                                     moves.append((r, c, nr, nc, promo if is_white else promo.lower(), None))
  207.                             else:
  208.                                 moves.append((r, c, nr, nc, None, None))
  209.                         if board.en_passant == (nr, nc):
  210.                             moves.append((r, c, nr, nc, None, 'enpassant'))
  211.             elif pt == 'K':
  212.                 for dr in [-1,0,1]:
  213.                     for dc in [-1,0,1]:
  214.                         if dr==0 and dc==0: continue
  215.                         nr, nc = r+dr, c+dc
  216.                         if 0<=nr<8 and 0<=nc<8:
  217.                             if board.grid[nr][nc]=='.' or ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
  218.                                 moves.append((r, c, nr, nc, None, None))
  219.                 # Rošády
  220.                 if is_white and r==7 and c==4:
  221.                     if 'K' in board.castling_rights and board.grid[7][5]=='.' and board.grid[7][6]=='.':
  222.                         moves.append((7,4,7,6,None,'castle'))
  223.                     if 'Q' in board.castling_rights and board.grid[7][3]=='.' and board.grid[7][2]=='.' and board.grid[7][1]=='.':
  224.                         moves.append((7,4,7,2,None,'castle'))
  225.                 if not is_white and r==0 and c==4:
  226.                     if 'k' in board.castling_rights and board.grid[0][5]=='.' and board.grid[0][6]=='.':
  227.                         moves.append((0,4,0,6,None,'castle'))
  228.                     if 'q' in board.castling_rights and board.grid[0][3]=='.' and board.grid[0][2]=='.' and board.grid[0][1]=='.':
  229.                         moves.append((0,4,0,2,None,'castle'))
  230.             else:
  231.                 # Tahy pro figury s jezdcovým pohybem (N, A, C, E)
  232.                 if pt in ['N','A','C','E']:
  233.                     for dr, dc in knight_moves:
  234.                         nr, nc = r+dr, c+dc
  235.                         if 0<=nr<8 and 0<=nc<8:
  236.                             if board.grid[nr][nc]=='.' or ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
  237.                                 moves.append((r, c, nr, nc, None, None))
  238.                
  239.                 # Klouzavé tahy – pro R, Q, E, A
  240.                 if pt in ['R','Q','E','A']:
  241.                     for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:
  242.                         nr, nc = r+dr, c+dc
  243.                         while 0<=nr<8 and 0<=nc<8:
  244.                             if board.grid[nr][nc]=='.':
  245.                                 moves.append((r, c, nr, nc, None, None))
  246.                             else:
  247.                                 if ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
  248.                                     moves.append((r, c, nr, nc, None, None))
  249.                                 break
  250.                             nr += dr; nc += dc
  251.                
  252.                 # Diagonální tahy – pro B, Q, C, A
  253.                 if pt in ['B','Q','C','A']:
  254.                     for dr, dc in [(1,1),(1,-1),(-1,1),(-1,-1)]:
  255.                         nr, nc = r+dr, c+dc
  256.                         while 0<=nr<8 and 0<=nc<8:
  257.                             if board.grid[nr][nc]=='.':
  258.                                 moves.append((r, c, nr, nc, None, None))
  259.                             else:
  260.                                 if ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
  261.                                     moves.append((r, c, nr, nc, None, None))
  262.                                 break
  263.                             nr += dr; nc += dc
  264.    
  265.     return moves
  266.  
  267. def get_legal_moves(board, side):
  268.     """Vrátí seznam legálních tahů pro danou stranu."""
  269.     moves = generate_pseudo_moves(board, side)
  270.     legal_moves = []
  271.     for move in moves:
  272.         make_move(move, board)
  273.         if not is_in_check(board, side):
  274.             legal_moves.append(move)
  275.         undo_move(board)
  276.     return legal_moves
  277.  
  278. def make_move(move, board):
  279.     """Provede tah na šachovnici a uloží stav pro možnost undo."""
  280.     r1, c1, r2, c2, promo, special = move
  281.     piece = board.grid[r1][c1]
  282.     captured = board.grid[r2][c2] if special != 'enpassant' else ('p' if piece=='P' else 'P')
  283.     prev_state = (set(board.castling_rights), board.en_passant, board.halfmove_clock, board.fullmove_number)
  284.     move_stack.append((r1, c1, r2, c2, promo, special, piece, captured, prev_state))
  285.    
  286.     # Aktualizace půltahových hodin a čísla tahu
  287.     if piece.upper() == 'P' or captured != '.':
  288.         board.halfmove_clock = 0
  289.     else:
  290.         board.halfmove_clock += 1
  291.    
  292.     if board.to_move == 'b':
  293.         board.fullmove_number += 1
  294.    
  295.     board.grid[r1][c1] = '.'
  296.    
  297.     if special == 'castle':
  298.         board.grid[r2][c2] = piece
  299.         if piece == 'K':
  300.             if c2 == 6:
  301.                 board.grid[7][5] = 'R'; board.grid[7][7] = '.'
  302.             else:
  303.                 board.grid[7][3] = 'R'; board.grid[7][0] = '.'
  304.         else:
  305.             if c2 == 6:
  306.                 board.grid[0][5] = 'r'; board.grid[0][7] = '.'
  307.             else:
  308.                 board.grid[0][3] = 'r'; board.grid[0][0] = '.'
  309.     elif special == 'enpassant':
  310.         board.grid[r2][c2] = piece
  311.         if piece == 'P':
  312.             board.grid[r2+1][c2] = '.'
  313.         else:
  314.             board.grid[r2-1][c2] = '.'
  315.     else:
  316.         board.grid[r2][c2] = promo if promo else piece
  317.    
  318.     # Aktualizace rošádových práv
  319.     if piece == 'K':
  320.         board.castling_rights.discard('K'); board.castling_rights.discard('Q')
  321.     if piece == 'k':
  322.         board.castling_rights.discard('k'); board.castling_rights.discard('q')
  323.     if piece == 'R' and (r1, c1)==(7,7):
  324.         board.castling_rights.discard('K')
  325.     if piece == 'R' and (r1, c1)==(7,0):
  326.         board.castling_rights.discard('Q')
  327.     if piece == 'r' and (r1, c1)==(0,7):
  328.         board.castling_rights.discard('k')
  329.     if piece == 'r' and (r1, c1)==(0,0):
  330.         board.castling_rights.discard('q')
  331.    
  332.     # En passant
  333.     if special == 'double':
  334.         board.en_passant = (r1 + (-1 if board.to_move=='w' else 1), c1)
  335.     else:
  336.         board.en_passant = None
  337.    
  338.     board.to_move = 'b' if board.to_move=='w' else 'w'
  339.  
  340. def undo_move(board):
  341.     """Vrátí poslední provedený tah."""
  342.     if not move_stack:
  343.         print("Chyba: Žádný tah k vrácení!")
  344.         return
  345.    
  346.     r1, c1, r2, c2, promo, special, piece, captured, prev_state = move_stack.pop()
  347.     castling_rights, en_passant, halfmove_clock, fullmove_number = prev_state
  348.    
  349.     board.grid[r1][c1] = piece
  350.    
  351.     if special == 'castle':
  352.         board.grid[r2][c2] = '.'
  353.         if piece == 'K':
  354.             if c2 == 6:
  355.                 board.grid[7][7] = 'R'; board.grid[7][5] = '.'
  356.             else:
  357.                 board.grid[7][0] = 'R'; board.grid[7][3] = '.'
  358.         else:
  359.             if c2 == 6:
  360.                 board.grid[0][7] = 'r'; board.grid[0][5] = '.'
  361.             else:
  362.                 board.grid[0][0] = 'r'; board.grid[0][3] = '.'
  363.     elif special == 'enpassant':
  364.         board.grid[r2][c2] = '.'
  365.         if piece == 'P':
  366.             board.grid[r2+1][c2] = 'p'
  367.         else:
  368.             board.grid[r2-1][c2] = 'P'
  369.     else:
  370.         board.grid[r2][c2] = captured
  371.    
  372.     board.castling_rights = castling_rights
  373.     board.en_passant = en_passant
  374.     board.halfmove_clock = halfmove_clock
  375.     board.fullmove_number = fullmove_number
  376.     board.to_move = 'b' if board.to_move=='w' else 'w'
  377.  
  378. def move_to_notation(move, board):
  379.     """Převede tah na standardní šachovou notaci."""
  380.     cols = "abcdefgh"
  381.     r1, c1, r2, c2, promo, special = move
  382.    
  383.     if special == 'castle':
  384.         return "O-O" if c2 > c1 else "O-O-O"
  385.    
  386.     piece = board.grid[r1][c1].upper()
  387.     is_pawn = piece == 'P'
  388.    
  389.     # Pro pěšce nezačínáme označením figury
  390.     prefix = '' if is_pawn else piece
  391.    
  392.     # Pole
  393.     from_square = cols[c1] + str(8 - r1)
  394.     to_square = cols[c2] + str(8 - r2)
  395.    
  396.     # Proměna
  397.     promotion = '=' + promo.upper() if promo else ''
  398.    
  399.     # En passant
  400.     ep = " e.p." if special == 'enpassant' else ''
  401.    
  402.     return prefix + from_square + '-' + to_square + promotion + ep
  403.  
  404. def is_mate_in_n_plies(board, depth):
  405.     """Zjistí, zda je v pozici mat v přesně 'depth' půltazích."""
  406.     if depth == 0:
  407.         # Je teď mat?
  408.         side_to_move = board.to_move
  409.         return is_in_check(board, side_to_move) and not get_legal_moves(board, side_to_move), None
  410.    
  411.     side_to_move = board.to_move
  412.     legal_moves = get_legal_moves(board, side_to_move)
  413.    
  414.     # Pokud nemá tahy
  415.     if not legal_moves:
  416.         # Pokud je to mat nyní, není to mat v hloubce depth (musí být přesně)
  417.         if is_in_check(board, side_to_move):
  418.             return False, None
  419.         # Pat - nemůže dát mat
  420.         return False, None
  421.    
  422.     # Určení, zda je strana, která mate, na tahu
  423.     mating_color = 'w'  # Předpokládejme, že bílý dává mat
  424.     if depth % 2 == 0:
  425.         # Pokud je sudý počet půltahů, pak je na tahu matovaná strana
  426.         mating_color = 'b' if board.to_move == 'w' else 'w'
  427.     else:
  428.         # Pokud je lichý počet půltahů, pak je na tahu matující strana
  429.         mating_color = board.to_move
  430.    
  431.     # Je matující strana na tahu?
  432.     is_mating_side_to_move = (board.to_move == mating_color)
  433.    
  434.     if is_mating_side_to_move:
  435.         # Matující strana hledá tah, který vede k matu
  436.         for move in legal_moves:
  437.             make_move(move, board)
  438.             is_mate, _ = is_mate_in_n_plies(board, depth - 1)
  439.             undo_move(board)
  440.            
  441.             if is_mate:
  442.                 return True, move
  443.        
  444.         # Nenašli jsme žádnou matující sekvenci
  445.         return False, None
  446.     else:
  447.         # Bránící se strana hledá nejlepší obranu
  448.         all_lead_to_mate = True
  449.         best_defensive_move = None
  450.        
  451.         # Zkusíme najít tah, který oddálí mat
  452.         for move in legal_moves:
  453.             make_move(move, board)
  454.             is_mate, _ = is_mate_in_n_plies(board, depth - 1)
  455.             undo_move(board)
  456.            
  457.             if not is_mate:
  458.                 # Našli jsme únikový tah, který vyvrací mat v daném počtu půltahů
  459.                 all_lead_to_mate = False
  460.                 best_defensive_move = move
  461.                 break
  462.        
  463.         # Pokud všechny tahy vedou k matu, alespoň vybereme ten, který dává nejlepší šanci na obranu
  464.         if all_lead_to_mate and legal_moves:
  465.             # Tady bychom ideálně měli vybrat tah, který maximalizuje počet tahů do matu
  466.             # Pro jednoduchost vybereme první tah, ale v reálném enginu bychom zde
  467.             # implementovali důkladnější analýzu
  468.             best_defensive_move = legal_moves[0]
  469.            
  470.             # Pokusíme se najít tah, který oddálí mat (pokud všechny vedou k matu)
  471.             max_depth_to_mate = -1
  472.             for move in legal_moves:
  473.                 make_move(move, board)
  474.                
  475.                 # Zkusíme najít mat ve všech možných hloubkách menších než aktuální
  476.                 for d in range(1, depth):
  477.                     mate_found, _ = is_mate_in_n_plies(board, d)
  478.                     if mate_found:
  479.                         if d > max_depth_to_mate:
  480.                             max_depth_to_mate = d
  481.                             best_defensive_move = move
  482.                         break
  483.                
  484.                 undo_move(board)
  485.            
  486.         return all_lead_to_mate, best_defensive_move
  487.  
  488. def find_best_defensive_move(board, legal_moves):
  489.     """Najde nejlepší obranný tah pro stranu na tahu."""
  490.     if not legal_moves:
  491.         return None
  492.    
  493.     # Pro krále se snažíme maximalizovat vzdálenost k soupeřovu králi
  494.     side = board.to_move
  495.     king_pos = find_king(board, side)
  496.     enemy_king_pos = find_king(board, 'b' if side == 'w' else 'w')
  497.    
  498.     if king_pos and enemy_king_pos:
  499.         kr, kc = king_pos
  500.         ekr, ekc = enemy_king_pos
  501.        
  502.         # Pro krále hledáme tah, který maximalizuje vzdálenost mezi králi
  503.         best_move = legal_moves[0]
  504.         max_distance = -1
  505.        
  506.         for move in legal_moves:
  507.             r1, c1, r2, c2, _, _ = move
  508.            
  509.             # Pokud pohybujeme králem
  510.             if board.grid[r1][c1].upper() == 'K' and (r1, c1) == king_pos:
  511.                 # Spočítejme vzdálenost po tahu
  512.                 distance = max(abs(r2 - ekr), abs(c2 - ekc))
  513.                
  514.                 if distance > max_distance:
  515.                     max_distance = distance
  516.                     best_move = move
  517.        
  518.         return best_move
  519.    
  520.     # Pokud nemáme krále nebo jiný případ, vrátíme první legální tah
  521.     return legal_moves[0]
  522.  
  523. def find_mate_sequence(board, max_plies=20):
  524.     """Najde a vypíše posloupnost tahů vedoucí k matu."""
  525.     global running, start_time, move_stack
  526.    
  527.     # Vyčistit zásobník
  528.     move_stack = []
  529.    
  530.     # Spustit časovač
  531.     running = True
  532.     start_time = time.time()
  533.     timer_thread = threading.Thread(target=time_reporter)
  534.     timer_thread.daemon = True
  535.     timer_thread.start()
  536.    
  537.     try:
  538.         # Nejprve kontrola, zda je již mat
  539.         side_to_move = board.to_move
  540.         legal_moves = get_legal_moves(board, side_to_move)
  541.        
  542.         if not legal_moves:
  543.             if is_in_check(board, side_to_move):
  544.                 print("\nPoziční analýza: Mat - " +
  545.                       ("černý vyhrává" if side_to_move == 'w' else "bílý vyhrává"))
  546.                 return
  547.             else:
  548.                 print("\nPoziční analýza: Pat - remíza")
  549.                 return
  550.        
  551.         # Zkusíme najít mat v několika tazích
  552.         print("\nHledám posloupnost tahů k matu...")
  553.         print("\nProhledávám jednotlivé hloubky:")
  554.        
  555.         for plies in range(1, max_plies + 1):
  556.             print(f"\n--- Hloubka {plies} půltahů ---")
  557.            
  558.             # Zkusíme najít mat v této hloubce
  559.             is_mate, best_move = is_mate_in_n_plies(board, plies)
  560.            
  561.             if is_mate:
  562.                 print(f"\nNalezen mat v {plies} půltazích!")
  563.                
  564.                 # Rekonstruujeme a vypisujeme sekvenci tahů k matu
  565.                 print("\nPosloupnost tahů k matu (s optimální obranou):")
  566.                 variant_board = board.copy()
  567.                
  568.                 # Vypíšeme počáteční pozici
  569.                 print("\nVýchozí pozice:")
  570.                 print(variant_board.display())
  571.                 print(f"Na tahu je {'bílý' if variant_board.to_move == 'w' else 'černý'}")
  572.                 print("-" * 30)
  573.                
  574.                 # Proveďme první tah
  575.                 move_notation = move_to_notation(best_move, variant_board)
  576.                 make_move(best_move, variant_board)
  577.                 print(f"1. {move_notation}")
  578.                 print(variant_board.display())
  579.                 print(f"Na tahu je {'bílý' if variant_board.to_move == 'w' else 'černý'}")
  580.                 print("-" * 30)
  581.                
  582.                 # Pokud je již mat, končíme
  583.                 if not get_legal_moves(variant_board, variant_board.to_move) and is_in_check(variant_board, variant_board.to_move):
  584.                     print("Mat!")
  585.                     return
  586.                
  587.                 # Nyní pokračujeme v rekonstrukci sekvence tahů
  588.                 curr_depth = plies - 1
  589.                 move_num = 2
  590.                
  591.                 while curr_depth > 0:
  592.                     # Najdeme nejlepší odpověď pro aktuální stranu na tahu
  593.                     is_mat, next_move = is_mate_in_n_plies(variant_board, curr_depth)
  594.                    
  595.                     if next_move:
  596.                         move_notation = move_to_notation(next_move, variant_board)
  597.                         make_move(next_move, variant_board)
  598.                         print(f"{move_num}. {move_notation}")
  599.                         print(variant_board.display())
  600.                         print(f"Na tahu je {'bílý' if variant_board.to_move == 'w' else 'černý'}")
  601.                         print("-" * 30)
  602.                        
  603.                         # Kontrola, zda je již mat
  604.                         if not get_legal_moves(variant_board, variant_board.to_move) and is_in_check(variant_board, variant_board.to_move):
  605.                             print("Mat!")
  606.                             return
  607.                        
  608.                         move_num += 1
  609.                         curr_depth -= 1
  610.                     else:
  611.                         # Pokud nemáme další tah v sekvenci, najdeme nejlepší tah pro aktuální stranu
  612.                         legal_moves = get_legal_moves(variant_board, variant_board.to_move)
  613.                         if legal_moves:
  614.                             # Vybereme nejlepší obranný tah
  615.                             next_move = find_best_defensive_move(variant_board, legal_moves)
  616.                             move_notation = move_to_notation(next_move, variant_board)
  617.                             make_move(next_move, variant_board)
  618.                             print(f"{move_num}. {move_notation}")
  619.                             print(variant_board.display())
  620.                             print(f"Na tahu je {'bílý' if variant_board.to_move == 'w' else 'černý'}")
  621.                             print("-" * 30)
  622.                            
  623.                             move_num += 1
  624.                             curr_depth -= 1
  625.                         else:
  626.                             break
  627.                
  628.                 return
  629.             else:
  630.                 # Pokud jsme nenašli mat v této hloubce, ukážeme posun hloubky simulací tahů
  631.                 # Vytvoříme kopii šachovnice pro simulaci
  632.                 sim_board = board.copy()
  633.                 # Pro sudé hloubky simulujeme tahy, abychom ukázali jinou pozici
  634.                 if plies > 1 and plies <= len(get_legal_moves(board, board.to_move)):
  635.                     # Provedeme jeden tah pro ilustraci
  636.                     sim_move = get_legal_moves(sim_board, sim_board.to_move)[0]
  637.                     make_move(sim_move, sim_board)
  638.                     print("Ukázka pozice po jednom tahu:")
  639.                     print(sim_board.display())
  640.                     print(f"Na tahu je {'bílý' if sim_board.to_move == 'w' else 'černý'}")
  641.                 else:
  642.                     # Pokud nemůžeme simulovat, aspoň zobrazíme aktuální pozici
  643.                     print("Aktuální pozice pro tuto hloubku:")
  644.                     print(board.display())
  645.                     print(f"Na tahu je {'bílý' if board.to_move == 'w' else 'černý'}")
  646.        
  647.         # Pokud nenajdeme mat, vypíšeme posloupnost tahů s nejlepšími tahy pro obě strany
  648.         print("\nMat nebyl nalezen v hloubce do", max_plies, "půltahů.")
  649.         print("\nPosloupnost nejlepších tahů (bez zaručeného matu):")
  650.        
  651.         legal_moves = get_legal_moves(board, board.to_move)
  652.        
  653.         if legal_moves:
  654.             variant_board = board.copy()
  655.            
  656.             # Vypíšeme počáteční pozici
  657.             print("\nVýchozí pozice:")
  658.             print(variant_board.display())
  659.             print(f"Na tahu je {'bílý' if variant_board.to_move == 'w' else 'černý'}")
  660.             print("-" * 30)
  661.            
  662.             # Jednoduché vyhledávání: pokusit se najít tahy vedoucí k matu nebo materiálnímu zisku
  663.             for i in range(10):  # Max 10 tahů
  664.                 legal_moves = get_legal_moves(variant_board, variant_board.to_move)
  665.                 if not legal_moves:
  666.                     if is_in_check(variant_board, variant_board.to_move):
  667.                         print("Mat!")
  668.                     else:
  669.                         print("Pat - remíza!")
  670.                     break
  671.                
  672.                 # Zkusíme najít mat v 1
  673.                 best_move = None
  674.                 for move in legal_moves:
  675.                     make_move(move, variant_board)
  676.                     if not get_legal_moves(variant_board, variant_board.to_move) and is_in_check(variant_board, variant_board.to_move):
  677.                         best_move = move
  678.                         break
  679.                     undo_move(variant_board)
  680.                
  681.                 if best_move:
  682.                     print(f"{i+1}. {move_to_notation(best_move, board)} (mat)")
  683.                     print(variant_board.display())
  684.                     print(f"Na tahu je {'bílý' if variant_board.to_move == 'w' else 'černý'}")
  685.                     print("-" * 30)
  686.                     print("Mat!")
  687.                     break
  688.                
  689.                 # Nemáme mat, zkusíme najít braní figury
  690.                 best_move = None
  691.                 for move in legal_moves:
  692.                     r1, c1, r2, c2, _, _ = move
  693.                     if variant_board.grid[r2][c2] != '.':
  694.                         best_move = move
  695.                         make_move(move, variant_board)
  696.                         print(f"{i+1}. {move_to_notation(move, board)} (braní)")
  697.                         print(variant_board.display())
  698.                         print(f"Na tahu je {'bílý' if variant_board.to_move == 'w' else 'černý'}")
  699.                         print("-" * 30)
  700.                         break
  701.                
  702.                 if best_move:
  703.                     continue
  704.                
  705.                 # Žádné braní, vybereme tah, který maximalizuje vzdálenost králů
  706.                 best_move = find_best_defensive_move(variant_board, legal_moves)
  707.                 make_move(best_move, variant_board)
  708.                 print(f"{i+1}. {move_to_notation(best_move, board)}")
  709.                 print(variant_board.display())
  710.                 print(f"Na tahu je {'bílý' if variant_board.to_move == 'w' else 'černý'}")
  711.                 print("-" * 30)
  712.    
  713.     finally:
  714.         # Ukončit časovač
  715.         running = False
  716.         if timer_thread.is_alive():
  717.             timer_thread.join(timeout=1.0)
  718.         print("")  # Nový řádek po časovém výpisu
  719.  
  720. def main():
  721.     """Hlavní funkce programu."""
  722.     # Několik zajímavých pozic pro testování
  723.     standard_fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"  # Základní pozice
  724.    
  725.     # Pozice s Amazonkou (A/a) - kombinuje tahy dámy a jezdce
  726.     amazon_fen = "8/6A1/8/8/8/k7/8/K7 w - - 0 1"  # Bílá Amazonka
  727.    
  728.     # Pozice s Cyrilo (C/c) - kombinuje tahy jezdce a střelce
  729.     cyrilo_fen = "8/8/8/8/8/kq2K3/6C1/8 w - - 0 1"
  730.    
  731.     # Pozice s Eve (E/e) - kombinuje tahy jezdce a věže
  732.     eve_fen = "8/8/8/8/8/k2E4/8/K7 w - - 0 1"
  733.    
  734.     # Mat Amazonkou v jednom tahu
  735.     amazon_mate_fen = "k7/8/1K6/8/8/8/8/A7 w - - 0 1"
  736.    
  737.     # Bílý dá mat v 2
  738.     mate_in_2_fen = "3k4/8/3K4/8/8/8/8/R7 w - - 0 1"
  739.    
  740.     # Pozice pro testování (můžete změnit na jinou z výše uvedených)
  741.     test_fen = amazon_mate_fen
  742.    
  743.     test_fen = "6k1/8/5a2/3K4/8/8/8/3B4 w - - 0 1"
  744.    
  745.     test_fen = "5k2/8/8/8/8/1KQ5/8/8 w - - 0 1"
  746.    
  747.     print("Šachový engine pro hledání matových sekvencí")
  748.     print("============================================")
  749.    
  750.     # Načtení pozice
  751.     board = Board(test_fen)
  752.     print("\nPočáteční pozice:")
  753.     print(board.display())
  754.     print(f"Na tahu je {'bílý' if board.to_move == 'w' else 'černý'}")
  755.    
  756.     # Najít sekvenci tahů k matu
  757.     find_mate_sequence(board, max_plies=10)
  758.  
  759. if __name__ == "__main__":
  760.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement