Advertisement
max2201111

excellent 3 table base

Jul 1st, 2025
393
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 17.77 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[7][0] = 'A'  # Bílá amazonka na a1
  290.     board[7][7] = 'K'  # Bílý král na h1  
  291.     board[0][4] = 'k'  # Černý král na e8
  292.     return board
  293.  
  294. def propagate_values(L):
  295.     print("\nPropaguji hodnoty s minimax logikou...")
  296.     start_time = time.time()
  297.     round_num = 0
  298.     max_rounds = 100
  299.    
  300.     # Nejdřív označ stavy bez následníků jako koncové
  301.     for state in L:
  302.         if not state['N'] and state['to_end'] is None:
  303.             state['to_mate'] = math.inf
  304.             state['to_end'] = 0
  305.    
  306.     while round_num < max_rounds:
  307.         round_num += 1
  308.         changed = False
  309.        
  310.         # Projdi všechny stavy zpětně
  311.         for state in reversed(L):
  312.             if state['to_mate'] is None or state['to_end'] is None:
  313.                 if state['N']:  # Má následníky
  314.                     # Získej hodnoty následníků
  315.                     succ_mate_vals = []
  316.                     succ_end_vals = []
  317.                    
  318.                     for idx in state['N']:
  319.                         if idx < len(L):
  320.                             succ = L[idx]
  321.                             if succ['to_mate'] is not None:
  322.                                 succ_mate_vals.append(succ['to_mate'])
  323.                             if succ['to_end'] is not None:
  324.                                 succ_end_vals.append(succ['to_end'])
  325.                    
  326.                     # KLÍČOVÁ OPRAVA: Minimax logika podle toho, kdo je na tahu
  327.                     if succ_mate_vals and state['to_mate'] is None:
  328.                         white_to_move = state['radek'] % 2 == 0
  329.                        
  330.                         if white_to_move:  # Bílý na tahu - hledá minimum (nejrychlejší mat)
  331.                             if all(val == math.inf for val in succ_mate_vals):
  332.                                 new_mate_val = math.inf
  333.                             else:
  334.                                 finite_vals = [val for val in succ_mate_vals if val != math.inf]
  335.                                 if finite_vals:
  336.                                     new_mate_val = 1 + min(finite_vals)
  337.                                 else:
  338.                                     new_mate_val = math.inf
  339.                         else:  # Černý na tahu - hledá maximum (nejpomalejší mat)
  340.                             finite_vals = [val for val in succ_mate_vals if val != math.inf]
  341.                             if finite_vals:
  342.                                 new_mate_val = 1 + max(finite_vals)  # Maximum z konečných hodnot
  343.                             else:
  344.                                 new_mate_val = math.inf  # Jen pokud jsou všechny inf
  345.                        
  346.                         state['to_mate'] = new_mate_val
  347.                         changed = True
  348.                    
  349.                     # to_end vždy minimum (nejkratší cesta k jakémukoli konci)
  350.                     if succ_end_vals and state['to_end'] is None:
  351.                         new_end_val = 1 + min(succ_end_vals)
  352.                         state['to_end'] = new_end_val
  353.                         changed = True
  354.        
  355.         elapsed = int(time.time() - start_time)
  356.         hh, rem = divmod(elapsed, 3600)
  357.         mm, ss = divmod(rem, 60)
  358.         states_with_mate = sum(1 for s in L if s['to_mate'] is not None)
  359.         states_with_end = sum(1 for s in L if s['to_end'] is not None)
  360.         print(f"\rPrůchod {round_num}: čas {hh:02d}h{mm:02d}m{ss:02d}s, "
  361.               f"změněno: {changed}, stavů s to_mate: {states_with_mate}/{len(L)}, "
  362.               f"stavů s to_end: {states_with_end}/{len(L)}", end='', flush=True)
  363.        
  364.         if not changed:
  365.             print("\nŽádné další změny - ukončuji propagaci")
  366.             break
  367.        
  368.         if all(s['to_mate'] is not None and s['to_end'] is not None for s in L):
  369.             print(f"\nVšechny stavy vyhodnocené po {round_num} průchodech")
  370.             break
  371.    
  372.     print()
  373.  
  374. def find_optimal_path(L):
  375.     print("\n--- Hledání optimální cesty k matu ---")
  376.    
  377.     if L[0]['to_mate'] is None or L[0]['to_mate'] == math.inf:
  378.         print(f"L[0] nemá cestu k matu (to_mate = {L[0]['to_mate']})")
  379.         return []
  380.    
  381.     path = []
  382.     current_index = 0
  383.     move_number = 0
  384.    
  385.     print(f"L[0] má to_mate = {L[0]['to_mate']}, hledám cestu...")
  386.    
  387.     while True:
  388.         current_state = L[current_index]
  389.         path.append(current_index)
  390.        
  391.         print(f"\nTah {move_number}: L[{current_index}]")
  392.         print(f"to_mate: {current_state['to_mate']}, to_end: {current_state['to_end']}")
  393.         print_board(current_state['board'])
  394.        
  395.         if current_state['to_mate'] == 0:
  396.             print("Mat dosažen!")
  397.             break
  398.        
  399.         if not current_state['N']:
  400.             print("Žádní následníci - konec")
  401.             break
  402.        
  403.         # OPRAVENÁ LOGIKA: Najdi následníka s hodnotou o 1 menší
  404.         target_value = current_state['to_mate'] - 1
  405.         best_successor = None
  406.        
  407.         print(f"Hledám následníka s to_mate = {target_value}")
  408.        
  409.         for succ_idx in current_state['N']:
  410.             succ_state = L[succ_idx]
  411.             print(f"  L[{succ_idx}]: to_mate = {succ_state['to_mate']}")
  412.            
  413.             if succ_state['to_mate'] == target_value:
  414.                 best_successor = succ_idx
  415.                 break
  416.        
  417.         if best_successor is None:
  418.             print("CHYBA: Nelze najít následníka s očekávanou hodnotou!")
  419.             print("Dostupní následníci:")
  420.             for succ_idx in current_state['N']:
  421.                 succ_state = L[succ_idx]
  422.                 print(f"  L[{succ_idx}]: to_mate = {succ_state['to_mate']}")
  423.             break
  424.        
  425.         player = "bílý" if move_number % 2 == 0 else "černý"
  426.         print(f"{player} vybírá L[{best_successor}] s to_mate={target_value}")
  427.        
  428.         current_index = best_successor
  429.         move_number += 1
  430.        
  431.         if move_number > 20:
  432.             print("Příliš mnoho tahů - přerušuji")
  433.             break
  434.    
  435.     return path
  436.  
  437. def main():
  438.     print("=== Chess Endgame Analyzer ===")
  439.     print("Figury: A=Amazonka(Q+N), C=Cyril(R+N), E=Eve(B+N), K=Král")
  440.     print("Mat = král v šachu + žádné legální tahy\n")
  441.    
  442.     board = create_initial_board()
  443.     start_fen = board_to_fen(board)
  444.    
  445.     print("Počáteční pozice:")
  446.     print_board(board)
  447.     print(f"Start FEN: {start_fen}\n")
  448.    
  449.     L = []
  450.     seen_fens = set()
  451.     seen_fens.add(start_fen)
  452.    
  453.     L.append({
  454.         'radek': 0,
  455.         'N': [],
  456.         'P': [],
  457.         'FEN': start_fen,
  458.         'board': board,
  459.         'to_mate': None,
  460.         'to_end': None
  461.     })
  462.    
  463.     print("Generuji následníky...")
  464.     start_generation = time.time()
  465.    
  466.     i = 0
  467.     max_states = 3000
  468.    
  469.     while i < len(L) and len(L) < max_states:
  470.         L[i]['N'] = create_successors(i, L[i], L, seen_fens)
  471.         i += 1
  472.        
  473.         if i % 200 == 0:
  474.             elapsed = time.time() - start_generation
  475.             print(f"\nZpracováno {i} stavů, celkem {len(L)} stavů, čas: {elapsed:.1f}s")
  476.    
  477.     generation_time = time.time() - start_generation
  478.     print(f"\nVygenerováno {len(L)} stavů za {generation_time:.1f}s")
  479.    
  480.     print("\nHledám koncové stavy...")
  481.     end_states_found = 0
  482.    
  483.     for state in L:
  484.         white_to_move = state['radek'] % 2 == 0
  485.         check_result = is_check_or_mate(state['FEN'], white_to_move)
  486.        
  487.         if check_result['checkmate']:
  488.             state['to_mate'] = 0
  489.             state['to_end'] = 0
  490.             end_states_found += 1
  491.             winner = check_result.get('winner', 'neznámý')
  492.             player_on_move = "bílý" if white_to_move else "černý"
  493.             print(f"Mat nalezen ve stavu L[{state['radek']}] - {player_on_move} je matován, vyhrál {winner}")
  494.         elif (check_result['stalemate'] or
  495.               check_result['insufficient_material'] or
  496.               check_result['seventyfive_moves']):
  497.             state['to_mate'] = math.inf
  498.             state['to_end'] = 0
  499.             end_states_found += 1
  500.    
  501.     print(f"Nalezeno {end_states_found} koncových stavů")
  502.    
  503.     propagate_values(L)
  504.    
  505.     print(f"\n=== VÝSLEDKY ===")
  506.     print(f"Počáteční stav L[0]:")
  507.     print(f"  to_mate: {L[0]['to_mate']}")
  508.     print(f"  to_end: {L[0]['to_end']}")
  509.     print(f"  Počet následníků: {len(L[0]['N'])}")
  510.    
  511.     path = find_optimal_path(L)
  512.     if path:
  513.         print(f"\nOptimální cesta: {' -> '.join(map(str, path))}")
  514.    
  515.     if len(L) > 22:
  516.         print(f"\nL[22] = {L[22]}")
  517.  
  518. if __name__ == "__main__":
  519.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement