Advertisement
max2201111

posledni vereze se spravnymi remizamy 4

Aug 31st, 2024
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 30.07 KB | Science | 0 0
  1. import chess
  2. from typing import Iterator, Optional, Dict, Tuple
  3. from chess import Move, BB_ALL, Bitboard, PieceType, Color
  4. import time
  5. from collections import deque
  6. import threading
  7. from collections import defaultdict
  8.  
  9. # Definice nových figur
  10. AMAZON = 7
  11. CYRIL = 8
  12. EVE = 9
  13.  
  14. # Rozšíření seznamu PIECE_SYMBOLS
  15. chess.PIECE_SYMBOLS.append('a')
  16. chess.PIECE_SYMBOLS.append('c')
  17. chess.PIECE_SYMBOLS.append('e')
  18.  
  19. class CustomBoard(chess.Board):
  20.     def __init__(self, fen=None):
  21.         self.amazons_white = chess.BB_EMPTY
  22.         self.amazons_black = chess.BB_EMPTY
  23.         self.cyrils_white = chess.BB_EMPTY
  24.         self.cyrils_black = chess.BB_EMPTY
  25.         self.eves_white = chess.BB_EMPTY
  26.         self.eves_black = chess.BB_EMPTY
  27.         super().__init__(None)
  28.         if fen:
  29.             self.set_custom_fen(fen)
  30.         self.debug_amazons()
  31.         self.debug_cyrils()
  32.         self.debug_eves()
  33.  
  34.     def clear_square(self, square):
  35.         super()._remove_piece_at(square)
  36.         self.amazons_white &= ~chess.BB_SQUARES[square]
  37.         self.amazons_black &= ~chess.BB_SQUARES[square]
  38.         self.cyrils_white &= ~chess.BB_SQUARES[square]
  39.         self.cyrils_black &= ~chess.BB_SQUARES[square]
  40.         self.eves_white &= ~chess.BB_SQUARES[square]
  41.         self.eves_black &= ~chess.BB_SQUARES[square]
  42.  
  43.     def set_custom_fen(self, fen):
  44.         parts = fen.split()
  45.         board_part = parts[0]
  46.    
  47.         self.clear()
  48.         self.amazons_white = chess.BB_EMPTY
  49.         self.amazons_black = chess.BB_EMPTY
  50.         self.cyrils_white = chess.BB_EMPTY
  51.         self.cyrils_black = chess.BB_EMPTY
  52.         self.eves_white = chess.BB_EMPTY
  53.         self.eves_black = chess.BB_EMPTY
  54.    
  55.         square = 56
  56.         for c in board_part:
  57.             if c == '/':
  58.                 square -= 16
  59.             elif c.isdigit():
  60.                 square += int(c)
  61.             else:
  62.                 color = chess.WHITE if c.isupper() else chess.BLACK
  63.                 if c.upper() == 'A':
  64.                     if color == chess.WHITE:
  65.                         self.amazons_white |= chess.BB_SQUARES[square]
  66.                     else:
  67.                         self.amazons_black |= chess.BB_SQUARES[square]
  68.                     piece_type = AMAZON
  69.                 elif c.upper() == 'C':
  70.                     if color == chess.WHITE:
  71.                         self.cyrils_white |= chess.BB_SQUARES[square]
  72.                     else:
  73.                         self.cyrils_black |= chess.BB_SQUARES[square]
  74.                     piece_type = CYRIL
  75.                 elif c.upper() == 'E':
  76.                     if color == chess.WHITE:
  77.                         self.eves_white |= chess.BB_SQUARES[square]
  78.                     else:
  79.                         self.eves_black |= chess.BB_SQUARES[square]
  80.                     piece_type = EVE
  81.                 elif c == 'P' and chess.square_rank(square) == 7:
  82.                     piece_type = chess.QUEEN
  83.                     color = chess.WHITE
  84.                 elif c == 'p' and chess.square_rank(square) == 0:
  85.                     piece_type = chess.QUEEN
  86.                     color = chess.BLACK
  87.                 else:
  88.                     piece_type = chess.PIECE_SYMBOLS.index(c.lower())
  89.                
  90.                 self._set_piece_at(square, piece_type, color)
  91.                 square += 1
  92.    
  93.         self.turn = chess.WHITE if parts[1] == 'w' else chess.BLACK
  94.         self.castling_rights = chess.BB_EMPTY
  95.         if '-' not in parts[2]:
  96.             if 'K' in parts[2]: self.castling_rights |= chess.BB_H1
  97.             if 'Q' in parts[2]: self.castling_rights |= chess.BB_A1
  98.             if 'k' in parts[2]: self.castling_rights |= chess.BB_H8
  99.             if 'q' in parts[2]: self.castling_rights |= chess.BB_A8
  100.         self.ep_square = chess.parse_square(parts[3]) if parts[3] != '-' else None
  101.            
  102.  
  103.     def _set_piece_at(self, square: chess.Square, piece_type: PieceType, color: Color) -> None:
  104.         self.clear_square(square)
  105.         super()._set_piece_at(square, piece_type, color)
  106.         if piece_type == AMAZON:
  107.             if color == chess.WHITE:
  108.                 self.amazons_white |= chess.BB_SQUARES[square]
  109.             else:
  110.                 self.amazons_black |= chess.BB_SQUARES[square]
  111.         elif piece_type == CYRIL:
  112.             if color == chess.WHITE:
  113.                 self.cyrils_white |= chess.BB_SQUARES[square]
  114.             else:
  115.                 self.cyrils_black |= chess.BB_SQUARES[square]
  116.         elif piece_type == EVE:
  117.             if color == chess.WHITE:
  118.                 self.eves_white |= chess.BB_SQUARES[square]
  119.             else:
  120.                 self.eves_black |= chess.BB_SQUARES[square]
  121.  
  122.     def piece_at(self, square: chess.Square) -> Optional[chess.Piece]:
  123.         if self.amazons_white & chess.BB_SQUARES[square]:
  124.             return chess.Piece(AMAZON, chess.WHITE)
  125.         elif self.amazons_black & chess.BB_SQUARES[square]:
  126.             return chess.Piece(AMAZON, chess.BLACK)
  127.         elif self.cyrils_white & chess.BB_SQUARES[square]:
  128.             return chess.Piece(CYRIL, chess.WHITE)
  129.         elif self.cyrils_black & chess.BB_SQUARES[square]:
  130.             return chess.Piece(CYRIL, chess.BLACK)
  131.         elif self.eves_white & chess.BB_SQUARES[square]:
  132.             return chess.Piece(EVE, chess.WHITE)
  133.         elif self.eves_black & chess.BB_SQUARES[square]:
  134.             return chess.Piece(EVE, chess.BLACK)
  135.         return super().piece_at(square)
  136.  
  137.     def generate_pseudo_legal_moves(self, from_mask: Bitboard = BB_ALL, to_mask: Bitboard = BB_ALL) -> Iterator[Move]:
  138.         our_pieces = self.occupied_co[self.turn]
  139.         if self.turn == chess.WHITE:
  140.             our_amazons = self.amazons_white
  141.             our_cyrils = self.cyrils_white
  142.             our_eves = self.eves_white
  143.         else:
  144.             our_amazons = self.amazons_black
  145.             our_cyrils = self.cyrils_black
  146.             our_eves = self.eves_black
  147.    
  148.         # Generování tahů pro amazonky
  149.         for from_square in chess.scan_forward(our_amazons & from_mask):
  150.             attacks = self.amazon_attacks(from_square)
  151.             valid_moves = attacks & ~our_pieces & to_mask
  152.             for to_square in chess.scan_forward(valid_moves):
  153.                 yield Move(from_square, to_square)
  154.    
  155.         # Generování tahů pro Cyrily
  156.         for from_square in chess.scan_forward(our_cyrils & from_mask):
  157.             attacks = self.cyril_attacks(from_square)
  158.             valid_moves = attacks & ~our_pieces & to_mask
  159.             for to_square in chess.scan_forward(valid_moves):
  160.                 yield Move(from_square, to_square)
  161.    
  162.         # Generování tahů pro Evy
  163.         for from_square in chess.scan_forward(our_eves & from_mask):
  164.             attacks = self.eve_attacks(from_square)
  165.             valid_moves = attacks & ~our_pieces & to_mask
  166.             for to_square in chess.scan_forward(valid_moves):
  167.                 yield Move(from_square, to_square)
  168.    
  169.         # Generování tahů pro standardní figury
  170.         for move in super().generate_pseudo_legal_moves(from_mask, to_mask):
  171.             piece = self.piece_at(move.from_square)
  172.             if piece and piece.piece_type not in [AMAZON, CYRIL, EVE]:
  173.                 yield move
  174.  
  175.     def queen_attacks(self, square):
  176.         return self.bishop_attacks(square) | self.rook_attacks(square)
  177.  
  178.     def bishop_attacks(self, square):
  179.         return chess.BB_DIAG_ATTACKS[square][self.occupied & chess.BB_DIAG_MASKS[square]]
  180.  
  181.     def rook_attacks(self, square):
  182.         return (chess.BB_RANK_ATTACKS[square][self.occupied & chess.BB_RANK_MASKS[square]] |
  183.                 chess.BB_FILE_ATTACKS[square][self.occupied & chess.BB_FILE_MASKS[square]])
  184.  
  185.     def amazon_attacks(self, square):
  186.         return self.queen_attacks(square) | chess.BB_KNIGHT_ATTACKS[square]
  187.  
  188.     def cyril_attacks(self, square):
  189.         return self.rook_attacks(square) | chess.BB_KNIGHT_ATTACKS[quare]
  190.  
  191.     def eve_attacks(self, square):
  192.         return self.bishop_attacks(square) | chess.BB_KNIGHT_ATTACKS[square]
  193.  
  194.     def is_pseudo_legal(self, move):
  195.         from_square = move.from_square
  196.         to_square = move.to_square
  197.         piece = self.piece_at(from_square)
  198.    
  199.         if not piece or piece.color != self.turn:
  200.             return False
  201.    
  202.         if self.occupied_co[self.turn] & chess.BB_SQUARES[to_square]:
  203.             return False
  204.    
  205.         if self.is_castling(move):
  206.             return True
  207.    
  208.         if piece.piece_type == AMAZON:
  209.             return bool(self.amazon_attacks(from_square) & chess.BB_SQUARES[to_square])
  210.         elif piece.piece_type == CYRIL:
  211.             return bool(self.cyril_attacks(from_square) & chess.BB_SQUARES[to_square])
  212.         elif piece.piece_type == EVE:
  213.             return bool(self.eve_attacks(from_square) & chess.BB_SQUARES[to_square])
  214.         else:
  215.             return super().is_pseudo_legal(move)
  216.  
  217.     def is_legal(self, move):
  218.         if not self.is_pseudo_legal(move):
  219.             return False
  220.    
  221.         from_square = move.from_square
  222.         to_square = move.to_square
  223.         piece = self.piece_at(from_square)
  224.         captured_piece = self.piece_at(to_square)
  225.    
  226.         # Kontrola pro všechny figury: nelze brát figuru stejné barvy
  227.         if captured_piece and captured_piece.color == piece.color:
  228.             return False
  229.    
  230.         # Dočasně provést tah
  231.         self.clear_square(from_square)
  232.         self._set_piece_at(to_square, piece.piece_type, piece.color)
  233.    
  234.         # Najít pozici krále
  235.         king_square = to_square if piece.piece_type == chess.KING else self.king(self.turn)
  236.    
  237.         # Kontrola, zda je král v šachu po tahu
  238.         is_check = self._is_attacked_by(not self.turn, king_square) if king_square is not None else False
  239.    
  240.         # Vrátit pozici do původního stavu
  241.         self.clear_square(to_square)
  242.         self._set_piece_at(from_square, piece.piece_type, piece.color)
  243.         if captured_piece:
  244.             self._set_piece_at(to_square, captured_piece.piece_type, captured_piece.color)
  245.    
  246.         return not is_check
  247.        
  248.  
  249.     def _is_attacked_by(self, color, square):
  250.         attackers = self.attackers(color, square)
  251.         return bool(attackers)
  252.  
  253.     def attackers(self, color: Color, square: chess.Square) -> Bitboard:
  254.         if square is None:
  255.             return chess.BB_EMPTY
  256.    
  257.         attackers = chess.BB_EMPTY
  258.         occupied = self.occupied
  259.         occupied_co = self.occupied_co[color]
  260.    
  261.         # Jezdci
  262.         attackers |= chess.BB_KNIGHT_ATTACKS[square] & self.knights & occupied_co
  263.    
  264.         # Král
  265.         attackers |= chess.BB_KING_ATTACKS[square] & self.kings & occupied_co
  266.    
  267.         # Pěšci
  268.         if color == chess.WHITE:
  269.             attackers |= chess.BB_PAWN_ATTACKS[chess.BLACK][square] & self.pawns & occupied_co
  270.         else:
  271.             attackers |= chess.BB_PAWN_ATTACKS[chess.WHITE][square] & self.pawns & occupied_co
  272.    
  273.         # Střelcové útoky (včetně dam a amazonek)
  274.         bishop_attacks = chess.BB_DIAG_ATTACKS[square][occupied & chess.BB_DIAG_MASKS[square]]
  275.         attackers |= bishop_attacks & ((self.bishops | self.queens) & occupied_co)
  276.    
  277.         # Věžové útoky (včetně dam, amazonek a cyrilů)
  278.         rook_attacks = (
  279.             chess.BB_RANK_ATTACKS[square][occupied & chess.BB_RANK_MASKS[square]] |
  280.             chess.BB_FILE_ATTACKS[square][occupied & chess.BB_FILE_MASKS[square]]
  281.         )
  282.         attackers |= rook_attacks & ((self.rooks | self.queens) & occupied_co)
  283.    
  284.         # Amazonky (Dáma + Jezdec)
  285.         amazons = self.amazons_white if color == chess.WHITE else self.amazons_black
  286.         amazon_attacks = bishop_attacks | rook_attacks | chess.BB_KNIGHT_ATTACKS[square]
  287.         attackers |= amazon_attacks & amazons
  288.    
  289.         # Cyrilové (Věž + Jezdec)
  290.         cyrils = self.cyrils_white if color == chess.WHITE else self.cyrils_black
  291.         cyril_attacks = rook_attacks | chess.BB_KNIGHT_ATTACKS[square]
  292.         attackers |= cyril_attacks & cyrils
  293.    
  294.         # Evy (Střelec + Jezdec)
  295.         eves = self.eves_white if color == chess.WHITE else self.eves_black
  296.         eve_attacks = bishop_attacks | chess.BB_KNIGHT_ATTACKS[square]
  297.         attackers |= eve_attacks & eves
  298.    
  299.         return attackers
  300.        
  301.     def push(self, move):
  302.         if not self.is_legal(move):
  303.             raise ValueError(f"Move {move} is not legal in position {self.fen()}")
  304.  
  305.         piece = self.piece_at(move.from_square)
  306.         captured_piece = self.piece_at(move.to_square)
  307.  
  308.         self.clear_square(move.from_square)
  309.         self.clear_square(move.to_square)
  310.         self._set_piece_at(move.to_square, piece.piece_type, piece.color)
  311.  
  312.         self.turn = not self.turn
  313.  
  314.         self.move_stack.append((move, captured_piece))
  315.  
  316.     def pop(self):
  317.         if not self.move_stack:
  318.             return None
  319.  
  320.         move, captured_piece = self.move_stack.pop()
  321.  
  322.         piece = self.piece_at(move.to_square)
  323.        
  324.         self.clear_square(move.from_square)
  325.         self.clear_square(move.to_square)
  326.  
  327.         self._set_piece_at(move.from_square, piece.piece_type, piece.color)
  328.  
  329.         if captured_piece:
  330.             self._set_piece_at(move.to_square, captured_piece.piece_type, captured_piece.color)
  331.  
  332.         self.turn = not self.turn
  333.  
  334.         return move
  335.  
  336.     def is_check(self):
  337.         king_square = self.king(self.turn)
  338.         if king_square is None:
  339.             return False
  340.         is_check = self._is_attacked_by(not self.turn, king_square)
  341.         return is_check
  342.  
  343.     def is_checkmate(self):
  344.         if not self.is_check():
  345.             return False
  346.         legal_moves = list(self.generate_legal_moves())
  347.         return len(legal_moves) == 0
  348.  
  349.     def is_game_over(self):
  350.         return self.is_checkmate() or self.is_stalemate() or self.is_insufficient_material()
  351.  
  352.     def is_stalemate(self):
  353.         if self.is_check():
  354.             return False
  355.         legal_moves = list(self.generate_legal_moves())
  356.         return len(legal_moves) == 0
  357.    
  358.     def is_insufficient_material(self):
  359.         return (self.pawns | self.rooks | self.queens | self.amazons_white | self.amazons_black |
  360.                 self.cyrils_white | self.cyrils_black | self.eves_white | self.eves_black) == 0 and (
  361.             chess.popcount(self.occupied) <= 3
  362.         )
  363.  
  364.     def generate_legal_moves(self, from_mask=chess.BB_ALL, to_mask=chess.BB_ALL):
  365.         for move in self.generate_pseudo_legal_moves(from_mask, to_mask):
  366.             if self.is_legal(move):
  367.                 yield move
  368.  
  369.     def debug_amazons(self):
  370.         pass
  371.  
  372.     def debug_cyrils(self):
  373.         pass
  374.  
  375.     def debug_eves(self):
  376.         pass
  377.  
  378.     def piece_symbol(self, piece):
  379.         if piece is None:
  380.             return '.'
  381.         if piece.piece_type == AMAZON:
  382.             return 'A' if piece.color == chess.WHITE else 'a'
  383.         if piece.piece_type == CYRIL:
  384.             return 'C' if piece.color == chess.WHITE else 'c'
  385.         if piece.piece_type == EVE:
  386.             return 'E' if piece.color == chess.WHITE else 'e'
  387.         return piece.symbol()
  388.  
  389.     def piece_type_at(self, square):
  390.         if (self.amazons_white | self.amazons_black) & chess.BB_SQUARES[square]:
  391.             return AMAZON
  392.         if (self.cyrils_white | self.cyrils_black) & chess.BB_SQUARES[square]:
  393.             return CYRIL
  394.         if (self.eves_white | self.eves_black) & chess.BB_SQUARES[square]:
  395.             return EVE
  396.         return super().piece_type_at(square)
  397.  
  398.     def color_at(self, square):
  399.         if self.amazons_white & chess.BB_SQUARES[square]:
  400.             return chess.WHITE
  401.         if self.amazons_black & chess.BB_SQUARES[square]:
  402.             return chess.BLACK
  403.         if self.cyrils_white & chess.BB_SQUARES[square]:
  404.             return chess.WHITE
  405.         if self.cyrils_black & chess.BB_SQUARES[square]:
  406.             return chess.BLACK
  407.         if self.eves_white & chess.BB_SQUARES[square]:
  408.             return chess.WHITE
  409.         if self.eves_black & chess.BB_SQUARES[square]:
  410.             return chess.BLACK
  411.         return super().color_at(square)
  412.  
  413.     @property
  414.     def legal_moves(self):
  415.         return list(self.generate_legal_moves())
  416.  
  417.     def __str__(self):
  418.         builder = []
  419.         for square in chess.SQUARES_180:
  420.             piece = self.piece_at(square)
  421.             symbol = self.piece_symbol(piece) if piece else '.'
  422.             builder.append(symbol)
  423.             if chess.square_file(square) == 7:
  424.                 if square != chess.H1:
  425.                     builder.append('\n')
  426.         return ''.join(builder)
  427.  
  428. def format_time(seconds):
  429.     hours, remainder = divmod(seconds, 3600)
  430.     minutes, seconds = divmod(remainder, 60)
  431.     return f"{int(hours):02d}h {int(minutes):02d}m {int(seconds):02d}s"
  432.  
  433. def print_elapsed_time(stop_event, start_time):
  434.     while not stop_event.is_set():
  435.         elapsed_time = time.time() - start_time
  436.         print(f"\rUplynulý čas: {format_time(elapsed_time)}", end="", flush=True)
  437.         time.sleep(1)
  438.  
  439. def print_board(fen):
  440.     board = chess.Board(fen)
  441.     print(board)
  442.  
  443. def simplify_fen(fen):
  444.     return ' '.join(fen.split()[:4])
  445.  
  446. class CustomBoard(chess.Board):
  447.     def is_valid(self):
  448.         return self.status() == chess.STATUS_VALID
  449.  
  450.     def set_custom_fen(self, fen):
  451.         self.set_fen(fen)
  452.  
  453. def format_time(seconds):
  454.     hours, remainder = divmod(seconds, 3600)
  455.     minutes, seconds = divmod(remainder, 60)
  456.     return f"{int(hours):02d}h {int(minutes):02d}m {int(seconds):02d}s"
  457.  
  458. def print_elapsed_time(stop_event, start_time):
  459.     while not stop_event.is_set():
  460.         elapsed_time = time.time() - start_time
  461.         print(f"\rUplynulý čas: {format_time(elapsed_time)}", end="", flush=True)
  462.         time.sleep(1)
  463.  
  464. def print_board(fen):
  465.     board = chess.Board(fen)
  466.     print(board)
  467.  
  468. def calculate_optimal_moves(start_fen: str) -> Tuple[Dict[str, Tuple[int, str]], int, str]:
  469.     print(f"Počáteční FEN: {start_fen}")
  470.     board = CustomBoard(start_fen)
  471.     if not board.is_valid():
  472.         raise ValueError("Neplatný FEN")
  473.  
  474.     POZ = {1: start_fen}
  475.     AR = defaultdict(lambda: {'used': False, 'to_end': None, 'depth': 0, 'type': 'normal', 'position_count': defaultdict(int)})
  476.     AR[board.epd()]['position_count'][board.epd()] = 1
  477.     N = 1
  478.     M = 0
  479.  
  480.     unique_positions: Set[str] = set()
  481.     unique_positions.add(board.epd())
  482.  
  483.     start_time = time.time()
  484.     current_depth = 0
  485.     positions_at_depth = defaultdict(int)
  486.     depth_start_time = start_time
  487.  
  488.     stop_event = threading.Event()
  489.     timer_thread = threading.Thread(target=print_elapsed_time, args=(stop_event, start_time))
  490.     timer_thread.start()
  491.  
  492.     last_depth_position = None
  493.  
  494.     try:
  495.         print("Začínám generovat pozice...")
  496.         print("Počáteční pozice:")
  497.         print_board(start_fen)
  498.  
  499.         # Generate all positions
  500.         while M < N:
  501.             M += 1
  502.             current_fen = POZ[M]
  503.             board.set_custom_fen(current_fen)
  504.             current_depth = AR[board.epd()]['depth']
  505.  
  506.             if positions_at_depth[current_depth] == 0 and current_depth > 0:
  507.                 depth_time = time.time() - depth_start_time
  508.                 total_time = time.time() - start_time
  509.                 print(f"\nHloubka {current_depth - 1}: {positions_at_depth[current_depth - 1]} pozic, "
  510.                       f"Čas hloubky: {format_time(depth_time)} / Celkový čas: {format_time(total_time)}")
  511.                 depth_start_time = time.time()
  512.  
  513.             positions_at_depth[current_depth] += 1
  514.             last_depth_position = board.epd()
  515.  
  516.             if not AR[board.epd()]['used']:
  517.                 AR[board.epd()]['used'] = True
  518.                 for move in board.legal_moves:
  519.                     board.push(move)
  520.                     new_epd = board.epd()
  521.                     AR[new_epd]['position_count'][new_epd] += 1
  522.                     if new_epd not in unique_positions:
  523.                         N += 1
  524.                         POZ[N] = board.fen()
  525.                         AR[new_epd]['depth'] = current_depth + 1
  526.                         unique_positions.add(new_epd)
  527.                     board.pop()
  528.  
  529.             if stop_event.is_set():
  530.                 print("Výpočet byl přerušen uživatelem.")
  531.                 return {}, 0, None
  532.  
  533.         # Print last depth and example position
  534.         depth_time = time.time() - depth_start_time
  535.         total_time = time.time() - start_time
  536.         print(f"\nHloubka {current_depth}: {positions_at_depth[current_depth]} pozic, "
  537.               f"Čas hloubky: {format_time(depth_time)} / Celkový čas: {format_time(total_time)}")
  538.  
  539.         print(f"Generování pozic dokončeno. Celkový počet unikátních pozic: {len(unique_positions)}")
  540.  
  541.         if last_depth_position:
  542.             print("\nPříklad pozice v poslední hloubce:")
  543.             print(f"EPD: {last_depth_position}")
  544.             print_board(chess.Board(last_depth_position).fen())
  545.  
  546.         # Initial evaluation
  547.         print("\nZačínám počáteční ohodnocení...")
  548.         F_checkmate = F_stalemate = F_drawing = F_check = F_normal = 0
  549.         for epd in unique_positions:
  550.             board.set_fen(epd)
  551.             if board.is_checkmate():
  552.                 AR[epd]['to_end'] = -1000 if board.turn == chess.WHITE else 1000
  553.                 AR[epd]['type'] = 'checkmate'
  554.                 F_checkmate += 1
  555.             elif board.is_stalemate():
  556.                 AR[epd]['to_end'] = 0
  557.                 AR[epd]['type'] = 'stalemate'
  558.                 F_stalemate += 1
  559.             elif board.is_insufficient_material():
  560.                 AR[epd]['to_end'] = 0
  561.                 AR[epd]['type'] = 'insufficient_material'
  562.                 F_drawing += 1
  563.             elif max(AR[epd]['position_count'].values()) >= 3:
  564.                 AR[epd]['to_end'] = 0
  565.                 AR[epd]['type'] = 'threefold_repetition'
  566.                 F_drawing += 1
  567.             elif board.halfmove_clock >= 100:
  568.                 AR[epd]['to_end'] = 0
  569.                 AR[epd]['type'] = 'fifty_move_rule'
  570.                 F_drawing += 1
  571.             elif board.is_check():
  572.                 AR[epd]['to_end'] = None
  573.                 AR[epd]['type'] = 'check'
  574.                 F_check += 1
  575.             else:
  576.                 AR[epd]['to_end'] = None
  577.                 AR[epd]['type'] = 'normal'
  578.                 F_normal += 1
  579.  
  580.         print(f"Počet pozic v matu je {F_checkmate}")
  581.         print(f"Počet pozic v patu je {F_stalemate}")
  582.         print(f"Počet pozic v remíze je {F_drawing}")
  583.         print(f"Počet pozic v šachu je {F_check}")
  584.         print(f"Počet normálních pozic je {F_normal}")
  585.  
  586.         print("\nZačínám iterativní ohodnocení...")
  587.         uroven = 0
  588.         while True:
  589.             uroven += 1
  590.             level_start_time = time.time()
  591.             print(f"Výpočet v úrovni {uroven}")
  592.  
  593.             changed = False
  594.             current_level_positions = 0
  595.             for epd in unique_positions:
  596.                 if AR[epd]['to_end'] is None or (AR[epd]['to_end'] == 0 and AR[epd]['type'] == 'normal'):
  597.                     board.set_fen(epd)
  598.                     hod = float('-inf') if board.turn == chess.WHITE else float('inf')
  599.                     all_moves_evaluated = True
  600.                     all_moves_draw = True
  601.                     for move in board.legal_moves:
  602.                         board.push(move)
  603.                         new_epd = board.epd()
  604.                         if AR[new_epd]['to_end'] is not None:
  605.                             hod2 = -AR[new_epd]['to_end']
  606.                         else:
  607.                             all_moves_evaluated = False
  608.                             board.pop()
  609.                             continue
  610.                         if hod2 != 0:
  611.                             all_moves_draw = False
  612.                         if board.turn == chess.WHITE:
  613.                             hod = max(hod, hod2)
  614.                         else:
  615.                             hod = min(hod, hod2)
  616.                         board.pop()
  617.  
  618.                     if not all_moves_evaluated:
  619.                         continue
  620.  
  621.                     if all_moves_draw:
  622.                         new_to_end = 0
  623.                         new_type = 'drawing'
  624.                     elif hod == 1001 - uroven:
  625.                         new_to_end = 1000 - uroven
  626.                         new_type = 'winning'
  627.                     elif hod == -1001 + uroven:
  628.                         new_to_end = -1000 + uroven
  629.                         new_type = 'losing'
  630.                     elif hod == 0:
  631.                         new_to_end = 0
  632.                         new_type = 'drawing'
  633.                     else:
  634.                         new_to_end = hod
  635.                         new_type = 'normal'
  636.  
  637.                     if AR[epd]['to_end'] != new_to_end or AR[epd]['type'] != new_type:
  638.                         AR[epd]['to_end'] = new_to_end
  639.                         AR[epd]['type'] = new_type
  640.                         changed = True
  641.                         current_level_positions += 1
  642.  
  643.             level_end_time = time.time()
  644.             total_elapsed_time = level_end_time - start_time
  645.             level_elapsed_time = level_end_time - level_start_time
  646.             print(f"Nalezeno {current_level_positions} pozic v úrovni {uroven}")
  647.             print(f"Čas úrovně: {format_time(level_elapsed_time)} / Celkový čas: {format_time(total_elapsed_time)}")
  648.  
  649.             if not changed:
  650.                 print("Hodnocení ukončeno - žádné další změny.")
  651.                 break
  652.  
  653.             if stop_event.is_set():
  654.                 print("Výpočet byl přerušen uživatelem.")
  655.                 return {}, 0, None
  656.  
  657.         total_positions = len(unique_positions)
  658.         evaluated_positions = sum(1 for data in AR.values() if data['to_end'] is not None)
  659.         unknown_positions = total_positions - evaluated_positions
  660.  
  661.         print(f"Celkový počet unikátních pozic: {total_positions}")
  662.         print(f"Celkem nalezeno {evaluated_positions} ohodnocených pozic")
  663.         print(f"Počet neohodnocených pozic: {unknown_positions}")
  664.  
  665.         print("\nVýpočet dokončen.")
  666.         return {epd: (data['to_end'], data['type']) for epd, data in AR.items() if data['to_end'] is not None}, total_positions, last_depth_position
  667.  
  668.     finally:
  669.         stop_event.set()
  670.         timer_thread.join()
  671.  
  672. def find_min_positive_value(AR):
  673.     min_positive_value = float('inf')
  674.     min_epd = None
  675.  
  676.     for epd, (value, type_pozice) in AR.items():
  677.         if value is not None and value > 0 and value < min_positive_value:
  678.             min_positive_value = value
  679.             min_epd = epd
  680.  
  681.     if min_positive_value == float('inf'):
  682.         print("Žádná kladná hodnota nebyla nalezena.")
  683.     else:
  684.         print(f"Nejmenší kladná hodnota: {min_positive_value}, EPD: {min_epd}")
  685.  
  686. if __name__ == "__main__":
  687.     start_fen = "7K/8/k7/8/8/8/8/8 w - - 0 1"
  688.  
  689.     try:
  690.         AR, total_positions, last_depth_position = calculate_optimal_moves(start_fen)
  691.     except KeyboardInterrupt:
  692.         print("\nVýpočet byl přerušen uživatelem.")
  693.         exit()
  694.  
  695.     find_min_positive_value(AR)
  696.  
  697.     start_epd = chess.Board(start_fen).epd()
  698.     if start_epd in AR:
  699.         value, position_type = AR[start_epd]
  700.         print(f"Počáteční pozice: Hodnota = {value}, Typ = {position_type}")
  701.         if value == 0:
  702.             print("Pozice je vyhodnocena jako remíza.")
  703.         elif value > 0:
  704.             print("Bílý má výhodu.")
  705.         else:
  706.             print("Černý má výhodu.")
  707.     else:
  708.         print("Počáteční pozice nebyla vyhodnocena.")
  709.  
  710.     print(f"\nCelkový počet unikátních pozic: {total_positions}")
  711.     print(f"Počet ohodnocených pozic: {len(AR)}")
  712.     print(f"Počet neohodnocených pozic: {total_positions - len(AR)}")
  713.  
  714.     if last_depth_position:
  715.         print("\nPříklad pozice v poslední hloubce:")
  716.         print(f"EPD: {last_depth_position}")
  717.         print_board(chess.Board(last_depth_position).fen())
  718.         if last_depth_position in AR:
  719.             value, position_type = AR[last_depth_position]
  720.             print(f"Hodnota: {value}, Typ: {position_type}")
  721.         else:
  722.             print("Tato pozice nebyla ohodnocena.")
  723.  
  724.     current_epd = start_epd
  725.     optimal_moves = []
  726.  
  727.     while True:
  728.         board = CustomBoard(chess.Board(current_epd).fen())
  729.         if board.is_game_over():
  730.             break
  731.  
  732.         if current_epd not in AR:
  733.             print(f"Pozice {current_epd} není v AR.")
  734.             break
  735.  
  736.         current_value, current_type = AR[current_epd]
  737.  
  738.         best_move = None
  739.         best_value = float('-inf') if board.turn == chess.WHITE else float('inf')
  740.         for move in board.legal_moves:
  741.             board.push(move)
  742.             new_epd = board.epd()
  743.             board.pop()
  744.             if new_epd in AR:
  745.                 move_value = AR[new_epd][0]
  746.                 if (board.turn == chess.WHITE and move_value > best_value) or (board.turn == chess.BLACK and move_value < best_value):
  747.                     best_value = move_value
  748.                     best_move = move
  749.  
  750.         if best_move is None:
  751.             print("Žádný další tah nebyl nalezen.")
  752.             break
  753.  
  754.         board.push(best_move)
  755.         optimal_moves.append((current_epd, best_move, board.epd()))
  756.         current_epd = board.epd()
  757.  
  758.     print("\nOptimální tahy:")
  759.     print("Počáteční pozice:")
  760.     print_board(start_fen)
  761.     hodnota, typ_pozice = AR[start_epd]
  762.     print(f"Hodnota: {hodnota}, Typ: {typ_pozice}")
  763.     print(start_epd)
  764.     print("\n")
  765.  
  766.  
  767.     for from_epd, move, to_epd in optimal_moves:
  768.         print_board(chess.Board(from_epd).fen())
  769.         print(f"Tah: {move}")
  770.         hodnota, typ_pozice = AR[to_epd]
  771.         print(f"Hodnota: {hodnota}, Typ: {typ_pozice}")
  772.         print(to_epd)
  773.         print("\n")
  774.  
  775.     if optimal_moves:
  776.         print("Konečná pozice:")
  777.         final_epd = optimal_moves[-1][2]  # Poslední 'to_epd'
  778.         print_board(chess.Board(final_epd).fen())
  779.         hodnota, typ_pozice = AR[final_epd]
  780.         print(f"Hodnota: {hodnota}, Typ: {typ_pozice}")
  781.         print(final_epd)
  782.         print("\n")
  783.     else:
  784.         print("Žádné optimální tahy nebyly nalezeny.")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement