Advertisement
max2201111

excellent 4 figury OK rychle korektni

Jul 1st, 2025
419
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 17.80 KB | Science | 0 0
  1. import chess
  2. import math
  3. import time
  4. from copy import deepcopy
  5.  
  6. def knight_moves():
  7.     return [(2, 1), (1, 2), (-1, 2), (-2, 1),
  8.             (-2, -1), (-1, -2), (1, -2), (2, -1)]
  9.  
  10. def rook_moves():
  11.     moves = []
  12.     for i in range(1, 8):
  13.         moves.extend([(i, 0), (-i, 0), (0, i), (0, -i)])
  14.     return moves
  15.  
  16. def bishop_moves():
  17.     moves = []
  18.     for i in range(1, 8):
  19.         moves.extend([(i, i), (i, -i), (-i, i), (-i, -i)])
  20.     return moves
  21.  
  22. def queen_moves():
  23.     return rook_moves() + bishop_moves()
  24.  
  25. def amazon_moves():
  26.     return queen_moves() + knight_moves()
  27.  
  28. def cyril_moves():
  29.     return rook_moves() + knight_moves()
  30.  
  31. def eve_moves():
  32.     return bishop_moves() + knight_moves()
  33.  
  34. def print_board(board):
  35.     print("  a b c d e f g h")
  36.     for i in range(8):
  37.         print(f"{8-i} ", end="")
  38.         for j in range(8):
  39.             print(f"{board[i][j]} ", end="")
  40.         print(f"{8-i}")
  41.     print("  a b c d e f g h")
  42.     print()
  43.  
  44. def generate_moves(board, piece, row, col):
  45.     size = 8
  46.     moves = []
  47.    
  48.     if piece.upper() == 'A':
  49.         directions = amazon_moves()
  50.     elif piece.upper() == 'C':
  51.         directions = cyril_moves()
  52.     elif piece.upper() == 'E':
  53.         directions = eve_moves()
  54.     elif piece.upper() == 'K':
  55.         directions = [(-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)]
  56.     else:
  57.         return moves
  58.    
  59.     for dx, dy in directions:
  60.         new_row, new_col = row + dx, col + dy
  61.        
  62.         if 0 <= new_row < size and 0 <= new_col < size:
  63.             target = board[new_row][new_col]
  64.            
  65.             if piece.upper() == 'K' and target.upper() == 'K':
  66.                 continue
  67.            
  68.             if piece.upper() in ['A', 'C', 'E'] and (dx, dy) not in knight_moves():
  69.                 blocked = False
  70.                 step_x = 1 if dx > 0 else (-1 if dx < 0 else 0)
  71.                 step_y = 1 if dy > 0 else (-1 if dy < 0 else 0)
  72.                
  73.                 check_x, check_y = row + step_x, col + step_y
  74.                 while (check_x, check_y) != (new_row, new_col):
  75.                     if board[check_x][check_y] != '.':
  76.                         blocked = True
  77.                         break
  78.                     check_x += step_x
  79.                     check_y += step_y
  80.                
  81.                 if blocked:
  82.                     continue
  83.            
  84.             if target == '.':
  85.                 moves.append((new_row, new_col))
  86.             elif target.islower() != piece.islower():
  87.                 moves.append((new_row, new_col))
  88.    
  89.     return moves
  90.  
  91. def board_to_fen(board):
  92.     fen_rows = []
  93.     for row in board:
  94.         fen_row = ""
  95.         empty_count = 0
  96.         for cell in row:
  97.             if cell == '.':
  98.                 empty_count += 1
  99.             else:
  100.                 if empty_count > 0:
  101.                     fen_row += str(empty_count)
  102.                     empty_count = 0
  103.                 fen_row += cell
  104.         if empty_count > 0:
  105.             fen_row += str(empty_count)
  106.         fen_rows.append(fen_row)
  107.    
  108.     return "/".join(fen_rows) + " w - - 0 1"
  109.  
  110. def fen_to_board(fen):
  111.     fen_board = fen.split()[0]
  112.     board = []
  113.    
  114.     for row_fen in fen_board.split('/'):
  115.         row = []
  116.         for char in row_fen:
  117.             if char.isdigit():
  118.                 row.extend(['.'] * int(char))
  119.             else:
  120.                 row.append(char)
  121.         board.append(row)
  122.    
  123.     return board
  124.  
  125. def is_under_attack(board, row, col, by_white):
  126.     for i in range(8):
  127.         for j in range(8):
  128.             piece = board[i][j]
  129.             if piece == '.' or piece.isupper() != by_white:
  130.                 continue
  131.                
  132.             if piece.upper() in ['A', 'C', 'E']:
  133.                 moves = generate_moves(board, piece, i, j)
  134.                 if (row, col) in moves:
  135.                     return True
  136.             elif piece.upper() == 'K':
  137.                 if abs(i - row) <= 1 and abs(j - col) <= 1 and (i != row or j != col):
  138.                     return True
  139.                    
  140.     return False
  141.  
  142. def get_all_legal_moves(board, white_to_move):
  143.     legal_moves = []
  144.    
  145.     for i in range(8):
  146.         for j in range(8):
  147.             piece = board[i][j]
  148.             if piece == '.' or piece.isupper() != white_to_move:
  149.                 continue
  150.                
  151.             if piece.upper() in ['A', 'C', 'E', 'K']:
  152.                 possible_moves = generate_moves(board, piece, i, j)
  153.                 for new_row, new_col in possible_moves:
  154.                     test_board = deepcopy(board)
  155.                     test_board[new_row][new_col] = piece
  156.                     test_board[i][j] = '.'
  157.                    
  158.                     king_pos = None
  159.                     for ki in range(8):
  160.                         for kj in range(8):
  161.                             if test_board[ki][kj] == ('K' if white_to_move else 'k'):
  162.                                 king_pos = (ki, kj)
  163.                                 break
  164.                         if king_pos:
  165.                             break
  166.                    
  167.                     if king_pos and not is_under_attack(test_board, king_pos[0], king_pos[1], not white_to_move):
  168.                         legal_moves.append(((i, j), (new_row, new_col)))
  169.    
  170.     return legal_moves
  171.  
  172. def is_check_or_mate(fen, white_to_move=True):
  173.     try:
  174.         board = fen_to_board(fen)
  175.        
  176.         white_king = None
  177.         black_king = None
  178.        
  179.         for i in range(8):
  180.             for j in range(8):
  181.                 if board[i][j] == 'K':
  182.                     white_king = (i, j)
  183.                 elif board[i][j] == 'k':
  184.                     black_king = (i, j)
  185.        
  186.         if not white_king or not black_king:
  187.             return {
  188.                 'checkmate': False,
  189.                 'stalemate': False,
  190.                 'insufficient_material': False,
  191.                 'seventyfive_moves': False,
  192.                 'check': False,
  193.                 'winner': None
  194.             }
  195.        
  196.         current_king = white_king if white_to_move else black_king
  197.         in_check = is_under_attack(board, current_king[0], current_king[1], not white_to_move)
  198.         legal_moves = get_all_legal_moves(board, white_to_move)
  199.        
  200.         if not legal_moves:
  201.             if in_check:
  202.                 winner = 'black' if white_to_move else 'white'
  203.                 return {
  204.                     'checkmate': True,
  205.                     'stalemate': False,
  206.                     'insufficient_material': False,
  207.                     'seventyfive_moves': False,
  208.                     'check': True,
  209.                     'winner': winner
  210.                 }
  211.             else:
  212.                 return {
  213.                     'checkmate': False,
  214.                     'stalemate': True,
  215.                     'insufficient_material': False,
  216.                     'seventyfive_moves': False,
  217.                     'check': False,
  218.                     'winner': None
  219.                 }
  220.        
  221.         return {
  222.             'checkmate': False,
  223.             'stalemate': False,
  224.             'insufficient_material': False,
  225.             'seventyfive_moves': False,
  226.             'check': in_check,
  227.             'winner': None
  228.         }
  229.        
  230.     except Exception:
  231.         return {
  232.             'checkmate': False,
  233.             'stalemate': False,
  234.             'insufficient_material': False,
  235.             'seventyfive_moves': False,
  236.             'check': False,
  237.             'winner': None
  238.         }
  239.  
  240. def create_successors(index, state, all_states, seen_fens):
  241.     board = state['board']
  242.     new_states = []
  243.     new_outputs = []
  244.    
  245.     current_player_white = index % 2 == 0
  246.     legal_moves = get_all_legal_moves(board, current_player_white)
  247.    
  248.     for ((from_row, from_col), (to_row, to_col)) in legal_moves:
  249.         piece = board[from_row][from_col]
  250.        
  251.         new_board = deepcopy(board)
  252.         new_board[to_row][to_col] = piece
  253.         new_board[from_row][from_col] = '.'
  254.        
  255.         fen = board_to_fen(new_board)
  256.        
  257.         if fen not in seen_fens:
  258.             seen_fens.add(fen)
  259.             new_state = {
  260.                 'radek': len(all_states),
  261.                 'N': [],
  262.                 'P': [index],
  263.                 'FEN': fen,
  264.                 'board': new_board,
  265.                 'to_mate': None,
  266.                 'to_end': None
  267.             }
  268.             all_states.append(new_state)
  269.             new_states.append(new_state['radek'])
  270.             new_outputs.append(f"{new_state['radek']}({state['radek']})")
  271.         else:
  272.             for s in all_states:
  273.                 if s['FEN'] == fen:
  274.                     if index not in s['P']:
  275.                         s['P'].append(index)
  276.                     new_states.append(s['radek'])
  277.                     break
  278.    
  279.     if new_outputs:
  280.         max_radek = max(new_states) if new_states else index
  281.         print(f"\rDepth={index} max={max_radek} : {' '.join(new_outputs[:5])}" +
  282.               (f" ...({len(new_outputs)-5} more)" if len(new_outputs) > 5 else ""),
  283.               end='', flush=True)
  284.    
  285.     return new_states
  286.  
  287. def create_initial_board():
  288.     board = [['.' for _ in range(8)] for _ in range(8)]
  289.     board[4][0] = 'A'  # Bílá amazonka na a1
  290.     board[5][4] = 'c'
  291.     board[6][5] = 'K'  # Bílý král na h1  
  292.     board[5][6] = 'k'  # Černý král na e8
  293.     return board
  294.  
  295. def propagate_values(L):
  296.     print("\nPropaguji hodnoty s minimax logikou...")
  297.     start_time = time.time()
  298.     round_num = 0
  299.     max_rounds = 100
  300.    
  301.     # Nejdřív označ stavy bez následníků jako koncové
  302.     for state in L:
  303.         if not state['N'] and state['to_end'] is None:
  304.             state['to_mate'] = math.inf
  305.             state['to_end'] = 0
  306.    
  307.     while round_num < max_rounds:
  308.         round_num += 1
  309.         changed = False
  310.        
  311.         # Projdi všechny stavy zpětně
  312.         for state in reversed(L):
  313.             if state['to_mate'] is None or state['to_end'] is None:
  314.                 if state['N']:  # Má následníky
  315.                     # Získej hodnoty následníků
  316.                     succ_mate_vals = []
  317.                     succ_end_vals = []
  318.                    
  319.                     for idx in state['N']:
  320.                         if idx < len(L):
  321.                             succ = L[idx]
  322.                             if succ['to_mate'] is not None:
  323.                                 succ_mate_vals.append(succ['to_mate'])
  324.                             if succ['to_end'] is not None:
  325.                                 succ_end_vals.append(succ['to_end'])
  326.                    
  327.                     # KLÍČOVÁ OPRAVA: Minimax logika podle toho, kdo je na tahu
  328.                     if succ_mate_vals and state['to_mate'] is None:
  329.                         white_to_move = state['radek'] % 2 == 0
  330.                        
  331.                         if white_to_move:  # Bílý na tahu - hledá minimum (nejrychlejší mat)
  332.                             if all(val == math.inf for val in succ_mate_vals):
  333.                                 new_mate_val = math.inf
  334.                             else:
  335.                                 finite_vals = [val for val in succ_mate_vals if val != math.inf]
  336.                                 if finite_vals:
  337.                                     new_mate_val = 1 + min(finite_vals)
  338.                                 else:
  339.                                     new_mate_val = math.inf
  340.                         else:  # Černý na tahu - hledá maximum (nejpomalejší mat)
  341.                             finite_vals = [val for val in succ_mate_vals if val != math.inf]
  342.                             if finite_vals:
  343.                                 new_mate_val = 1 + max(finite_vals)  # Maximum z konečných hodnot
  344.                             else:
  345.                                 new_mate_val = math.inf  # Jen pokud jsou všechny inf
  346.                        
  347.                         state['to_mate'] = new_mate_val
  348.                         changed = True
  349.                    
  350.                     # to_end vždy minimum (nejkratší cesta k jakémukoli konci)
  351.                     if succ_end_vals and state['to_end'] is None:
  352.                         new_end_val = 1 + min(succ_end_vals)
  353.                         state['to_end'] = new_end_val
  354.                         changed = True
  355.        
  356.         elapsed = int(time.time() - start_time)
  357.         hh, rem = divmod(elapsed, 3600)
  358.         mm, ss = divmod(rem, 60)
  359.         states_with_mate = sum(1 for s in L if s['to_mate'] is not None)
  360.         states_with_end = sum(1 for s in L if s['to_end'] is not None)
  361.         print(f"\rPrůchod {round_num}: čas {hh:02d}h{mm:02d}m{ss:02d}s, "
  362.               f"změněno: {changed}, stavů s to_mate: {states_with_mate}/{len(L)}, "
  363.               f"stavů s to_end: {states_with_end}/{len(L)}", end='', flush=True)
  364.        
  365.         if not changed:
  366.             print("\nŽádné další změny - ukončuji propagaci")
  367.             break
  368.        
  369.         if all(s['to_mate'] is not None and s['to_end'] is not None for s in L):
  370.             print(f"\nVšechny stavy vyhodnocené po {round_num} průchodech")
  371.             break
  372.    
  373.     print()
  374.  
  375. def find_optimal_path(L):
  376.     print("\n--- Hledání optimální cesty k matu ---")
  377.    
  378.     if L[0]['to_mate'] is None or L[0]['to_mate'] == math.inf:
  379.         print(f"L[0] nemá cestu k matu (to_mate = {L[0]['to_mate']})")
  380.         return []
  381.    
  382.     path = []
  383.     current_index = 0
  384.     move_number = 0
  385.    
  386.     print(f"L[0] má to_mate = {L[0]['to_mate']}, hledám cestu...")
  387.    
  388.     while True:
  389.         current_state = L[current_index]
  390.         path.append(current_index)
  391.        
  392.         print(f"\nTah {move_number}: L[{current_index}]")
  393.         print(f"to_mate: {current_state['to_mate']}, to_end: {current_state['to_end']}")
  394.         print_board(current_state['board'])
  395.        
  396.         if current_state['to_mate'] == 0:
  397.             print("Mat dosažen!")
  398.             break
  399.        
  400.         if not current_state['N']:
  401.             print("Žádní následníci - konec")
  402.             break
  403.        
  404.         # OPRAVENÁ LOGIKA: Najdi následníka s hodnotou o 1 menší
  405.         target_value = current_state['to_mate'] - 1
  406.         best_successor = None
  407.        
  408.         print(f"Hledám následníka s to_mate = {target_value}")
  409.        
  410.         for succ_idx in current_state['N']:
  411.             succ_state = L[succ_idx]
  412.             print(f"  L[{succ_idx}]: to_mate = {succ_state['to_mate']}")
  413.            
  414.             if succ_state['to_mate'] == target_value:
  415.                 best_successor = succ_idx
  416.                 break
  417.        
  418.         if best_successor is None:
  419.             print("CHYBA: Nelze najít následníka s očekávanou hodnotou!")
  420.             print("Dostupní následníci:")
  421.             for succ_idx in current_state['N']:
  422.                 succ_state = L[succ_idx]
  423.                 print(f"  L[{succ_idx}]: to_mate = {succ_state['to_mate']}")
  424.             break
  425.        
  426.         player = "bílý" if move_number % 2 == 0 else "černý"
  427.         print(f"{player} vybírá L[{best_successor}] s to_mate={target_value}")
  428.        
  429.         current_index = best_successor
  430.         move_number += 1
  431.        
  432.         if move_number > 20:
  433.             print("Příliš mnoho tahů - přerušuji")
  434.             break
  435.    
  436.     return path
  437.  
  438. def main():
  439.     print("=== Chess Endgame Analyzer ===")
  440.     print("Figury: A=Amazonka(Q+N), C=Cyril(R+N), E=Eve(B+N), K=Král")
  441.     print("Mat = král v šachu + žádné legální tahy\n")
  442.    
  443.     board = create_initial_board()
  444.     start_fen = board_to_fen(board)
  445.    
  446.     print("Počáteční pozice:")
  447.     print_board(board)
  448.     print(f"Start FEN: {start_fen}\n")
  449.    
  450.     L = []
  451.     seen_fens = set()
  452.     seen_fens.add(start_fen)
  453.    
  454.     L.append({
  455.         'radek': 0,
  456.         'N': [],
  457.         'P': [],
  458.         'FEN': start_fen,
  459.         'board': board,
  460.         'to_mate': None,
  461.         'to_end': None
  462.     })
  463.    
  464.     print("Generuji následníky...")
  465.     start_generation = time.time()
  466.    
  467.     i = 0
  468.     max_states = 3000
  469.    
  470.     while i < len(L) and len(L) < max_states:
  471.         L[i]['N'] = create_successors(i, L[i], L, seen_fens)
  472.         i += 1
  473.        
  474.         if i % 200 == 0:
  475.             elapsed = time.time() - start_generation
  476.             print(f"\nZpracováno {i} stavů, celkem {len(L)} stavů, čas: {elapsed:.1f}s")
  477.    
  478.     generation_time = time.time() - start_generation
  479.     print(f"\nVygenerováno {len(L)} stavů za {generation_time:.1f}s")
  480.    
  481.     print("\nHledám koncové stavy...")
  482.     end_states_found = 0
  483.    
  484.     for state in L:
  485.         white_to_move = state['radek'] % 2 == 0
  486.         check_result = is_check_or_mate(state['FEN'], white_to_move)
  487.        
  488.         if check_result['checkmate']:
  489.             state['to_mate'] = 0
  490.             state['to_end'] = 0
  491.             end_states_found += 1
  492.             winner = check_result.get('winner', 'neznámý')
  493.             player_on_move = "bílý" if white_to_move else "černý"
  494.             print(f"Mat nalezen ve stavu L[{state['radek']}] - {player_on_move} je matován, vyhrál {winner}")
  495.         elif (check_result['stalemate'] or
  496.               check_result['insufficient_material'] or
  497.               check_result['seventyfive_moves']):
  498.             state['to_mate'] = math.inf
  499.             state['to_end'] = 0
  500.             end_states_found += 1
  501.    
  502.     print(f"Nalezeno {end_states_found} koncových stavů")
  503.    
  504.     propagate_values(L)
  505.    
  506.     print(f"\n=== VÝSLEDKY ===")
  507.     print(f"Počáteční stav L[0]:")
  508.     print(f"  to_mate: {L[0]['to_mate']}")
  509.     print(f"  to_end: {L[0]['to_end']}")
  510.     print(f"  Počet následníků: {len(L[0]['N'])}")
  511.    
  512.     path = find_optimal_path(L)
  513.     if path:
  514.         print(f"\nOptimální cesta: {' -> '.join(map(str, path))}")
  515.    
  516.     if len(L) > 22:
  517.         print(f"\nL[22] = {L[22]}")
  518.  
  519. if __name__ == "__main__":
  520.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement