Advertisement
max2201111

nejlepsi ale s pass a8a7

Jul 11th, 2024
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 20.90 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.  
  8. # Definice nových figur
  9. AMAZON = 7
  10. CYRIL = 8
  11. EVE = 9
  12.  
  13. # Rozšíření seznamu PIECE_SYMBOLS
  14. chess.PIECE_SYMBOLS.append('a')
  15. chess.PIECE_SYMBOLS.append('c')
  16. chess.PIECE_SYMBOLS.append('e')
  17.  
  18. class CustomBoard(chess.Board):
  19.     def __init__(self, fen=None):
  20.         self.amazons_white = chess.BB_EMPTY
  21.         self.amazons_black = chess.BB_EMPTY
  22.         self.cyrils_white = chess.BB_EMPTY
  23.         self.cyrils_black = chess.BB_EMPTY
  24.         self.eves_white = chess.BB_EMPTY
  25.         self.eves_black = chess.BB_EMPTY
  26.         super().__init__(None)
  27.         if fen:
  28.             self.set_custom_fen(fen)
  29.         print("Šachovnice inicializována")
  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.                 else:
  82.                     piece_type = chess.PIECE_SYMBOLS.index(c.lower())
  83.                 self._set_piece_at(square, piece_type, color)
  84.                 square += 1
  85.  
  86.         self.turn = chess.WHITE if parts[1] == 'w' else chess.BLACK
  87.         self.castling_rights = chess.BB_EMPTY
  88.         if '-' not in parts[2]:
  89.             if 'K' in parts[2]: self.castling_rights |= chess.BB_H1
  90.             if 'Q' in parts[2]: self.castling_rights |= chess.BB_A1
  91.             if 'k' in parts[2]: self.castling_rights |= chess.BB_H8
  92.             if 'q' in parts[2]: self.castling_rights |= chess.BB_A8
  93.         self.ep_square = chess.parse_square(parts[3]) if parts[3] != '-' else None
  94.  
  95.     def _set_piece_at(self, square: chess.Square, piece_type: PieceType, color: Color) -> None:
  96.         self.clear_square(square)
  97.         super()._set_piece_at(square, piece_type, color)
  98.         if piece_type == AMAZON:
  99.             if color == chess.WHITE:
  100.                 self.amazons_white |= chess.BB_SQUARES[square]
  101.             else:
  102.                 self.amazons_black |= chess.BB_SQUARES[square]
  103.         elif piece_type == CYRIL:
  104.             if color == chess.WHITE:
  105.                 self.cyrils_white |= chess.BB_SQUARES[square]
  106.             else:
  107.                 self.cyrils_black |= chess.BB_SQUARES[square]
  108.         elif piece_type == EVE:
  109.             if color == chess.WHITE:
  110.                 self.eves_white |= chess.BB_SQUARES[square]
  111.             else:
  112.                 self.eves_black |= chess.BB_SQUARES[square]
  113.  
  114.     def piece_at(self, square: chess.Square) -> Optional[chess.Piece]:
  115.         if self.amazons_white & chess.BB_SQUARES[square]:
  116.             return chess.Piece(AMAZON, chess.WHITE)
  117.         elif self.amazons_black & chess.BB_SQUARES[square]:
  118.             return chess.Piece(AMAZON, chess.BLACK)
  119.         elif self.cyrils_white & chess.BB_SQUARES[square]:
  120.             return chess.Piece(CYRIL, chess.WHITE)
  121.         elif self.cyrils_black & chess.BB_SQUARES[square]:
  122.             return chess.Piece(CYRIL, chess.BLACK)
  123.         elif self.eves_white & chess.BB_SQUARES[square]:
  124.             return chess.Piece(EVE, chess.WHITE)
  125.         elif self.eves_black & chess.BB_SQUARES[square]:
  126.             return chess.Piece(EVE, chess.BLACK)
  127.         return super().piece_at(square)
  128.  
  129.     def generate_pseudo_legal_moves(self, from_mask: Bitboard = BB_ALL, to_mask: Bitboard = BB_ALL) -> Iterator[Move]:
  130.         our_pieces = self.occupied_co[self.turn]
  131.         if self.turn == chess.WHITE:
  132.             our_amazons = self.amazons_white
  133.             our_cyrils = self.cyrils_white
  134.             our_eves = self.eves_white
  135.         else:
  136.             our_amazons = self.amazons_black
  137.             our_cyrils = self.cyrils_black
  138.             our_eves = self.eves_black
  139.  
  140.         for from_square in chess.scan_forward(our_amazons & from_mask):
  141.             attacks = self.amazon_attacks(from_square)
  142.             valid_moves = attacks & ~our_pieces & to_mask
  143.             for to_square in chess.scan_forward(valid_moves):
  144.                 yield Move(from_square, to_square)
  145.  
  146.         for from_square in chess.scan_forward(our_cyrils & from_mask):
  147.             attacks = self.cyril_attacks(from_square)
  148.             valid_moves = attacks & ~our_pieces & to_mask
  149.             for to_square in chess.scan_forward(valid_moves):
  150.                 yield Move(from_square, to_square)
  151.  
  152.         for from_square in chess.scan_forward(our_eves & from_mask):
  153.             attacks = self.eve_attacks(from_square)
  154.             valid_moves = attacks & ~our_pieces & to_mask
  155.             for to_square in chess.scan_forward(valid_moves):
  156.                 yield Move(from_square, to_square)
  157.  
  158.         for move in super().generate_pseudo_legal_moves(from_mask, to_mask):
  159.             if self.piece_type_at(move.from_square) not in [AMAZON, CYRIL, EVE]:
  160.                 yield move
  161.  
  162.     def queen_attacks(self, square):
  163.         return self.bishop_attacks(square) | self.rook_attacks(square)
  164.  
  165.     def bishop_attacks(self, square):
  166.         return chess.BB_DIAG_ATTACKS[square][self.occupied & chess.BB_DIAG_MASKS[square]]
  167.  
  168.     def rook_attacks(self, square):
  169.         return (chess.BB_RANK_ATTACKS[square][self.occupied & chess.BB_RANK_MASKS[square]] |
  170.                 chess.BB_FILE_ATTACKS[square][self.occupied & chess.BB_FILE_MASKS[square]])
  171.  
  172.     def amazon_attacks(self, square):
  173.         return self.queen_attacks(square) | chess.BB_KNIGHT_ATTACKS[square]
  174.  
  175.     def cyril_attacks(self, square):
  176.         return self.rook_attacks(square) | chess.BB_KNIGHT_ATTACKS[square]
  177.  
  178.     def eve_attacks(self, square):
  179.         return self.bishop_attacks(square) | chess.BB_KNIGHT_ATTACKS[square]
  180.  
  181.     def is_pseudo_legal(self, move):
  182.         from_square = move.from_square
  183.         to_square = move.to_square
  184.         piece = self.piece_at(from_square)
  185.  
  186.         if not piece or piece.color != self.turn:
  187.             return False
  188.  
  189.         if self.occupied_co[self.turn] & chess.BB_SQUARES[to_square]:
  190.             return False
  191.  
  192.         if self.is_castling(move):
  193.             return True
  194.  
  195.         if piece.piece_type == AMAZON:
  196.             return bool(self.amazon_attacks(from_square) & chess.BB_SQUARES[to_square])
  197.         elif piece.piece_type == CYRIL:
  198.             return bool(self.cyril_attacks(from_square) & chess.BB_SQUARES[to_square])
  199.         elif piece.piece_type == EVE:
  200.             return bool(self.eve_attacks(from_square) & chess.BB_SQUARES[to_square])
  201.         else:
  202.             return super().is_pseudo_legal(move)
  203.  
  204.     def is_legal(self, move):
  205.         if not self.is_pseudo_legal(move):
  206.             return False
  207.  
  208.         from_square = move.from_square
  209.         to_square = move.to_square
  210.         piece = self.piece_at(from_square)
  211.         captured_piece = self.piece_at(to_square)
  212.  
  213.         self.clear_square(from_square)
  214.         self.clear_square(to_square)
  215.         self._set_piece_at(to_square, piece.piece_type, piece.color)
  216.  
  217.         king_square = to_square if piece.piece_type == chess.KING else self.king(self.turn)
  218.         is_check, attacker_square = self._is_attacked_by(not self.turn, king_square)
  219.  
  220.         self.clear_square(to_square)
  221.         self._set_piece_at(from_square, piece.piece_type, piece.color)
  222.         if captured_piece:
  223.             self._set_piece_at(to_square, captured_piece.piece_type, captured_piece.color)
  224.  
  225.         return not is_check
  226.  
  227.     def _is_attacked_by(self, color, square):
  228.         attackers = self.attackers(color, square)
  229.         if attackers:
  230.             for attacker_square in chess.scan_forward(attackers):
  231.                 return True, attacker_square
  232.         return False, None
  233.  
  234.     def attackers(self, color, square):
  235.         attackers = chess.BB_EMPTY
  236.  
  237.         knights = self.knights & self.occupied_co[color]
  238.         attackers |= knights & chess.BB_KNIGHT_ATTACKS[square]
  239.  
  240.         king = self.kings & self.occupied_co[color]
  241.         attackers |= king & chess.BB_KING_ATTACKS[square]
  242.  
  243.         pawns = self.pawns & self.occupied_co[color]
  244.         if color == chess.WHITE:
  245.             attackers |= pawns & chess.BB_PAWN_ATTACKS[chess.BLACK][square]
  246.         else:
  247.             attackers |= pawns & chess.BB_PAWN_ATTACKS[chess.WHITE][square]
  248.  
  249.         queens = self.queens & self.occupied_co[color]
  250.         bishops = (self.bishops | queens) & self.occupied_co[color]
  251.         rooks = (self.rooks | queens) & self.occupied_co[color]
  252.  
  253.         attackers |= chess.BB_DIAG_ATTACKS[square][self.occupied & chess.BB_DIAG_MASKS[square]] & bishops
  254.         attackers |= (chess.BB_RANK_ATTACKS[square][self.occupied & chess.BB_RANK_MASKS[square]] |
  255.                       chess.BB_FILE_ATTACKS[square][self.occupied & chess.BB_FILE_MASKS[square]]) & rooks
  256.  
  257.         amazons = self.amazons_white if color == chess.WHITE else self.amazons_black
  258.         for amazon_square in chess.scan_forward(amazons):
  259.             if self.amazon_attacks(amazon_square) & chess.BB_SQUARES[square]:
  260.                 attackers |= chess.BB_SQUARES[amazon_square]
  261.  
  262.         cyrils = self.cyrils_white if color == chess.WHITE else self.cyrils_black
  263.         for cyril_square in chess.scan_forward(cyrils):
  264.             if self.cyril_attacks(cyril_square) & chess.BB_SQUARES[square]:
  265.                 attackers |= chess.BB_SQUARES[cyril_square]
  266.  
  267.         eves = self.eves_white if color == chess.WHITE else self.eves_black
  268.         for eve_square in chess.scan_forward(eves):
  269.             if self.eve_attacks(eve_square) & chess.BB_SQUARES[square]:
  270.                 attackers |= chess.BB_SQUARES[eve_square]
  271.  
  272.         return attackers
  273.  
  274.     def push(self, move):
  275.         if not self.is_legal(move):
  276.             pass
  277.          #  raise ValueError(f"Move {move} is not legal in position {self.fen()}")
  278.  
  279.         piece = self.piece_at(move.from_square)
  280.         captured_piece = self.piece_at(move.to_square)
  281.  
  282.         self.clear_square(move.from_square)
  283.         self.clear_square(move.to_square)
  284.         self._set_piece_at(move.to_square, piece.piece_type, piece.color)
  285.  
  286.         self.turn = not self.turn
  287.  
  288.         self.move_stack.append((move, captured_piece))
  289.  
  290.     def pop(self):
  291.         if not self.move_stack:
  292.             return None
  293.  
  294.         move, captured_piece = self.move_stack.pop()
  295.  
  296.         piece = self.piece_at(move.to_square)
  297.        
  298.         self.clear_square(move.from_square)
  299.         self.clear_square(move.to_square)
  300.  
  301.         self._set_piece_at(move.from_square, piece.piece_type, piece.color)
  302.  
  303.         if captured_piece:
  304.             self._set_piece_at(move.to_square, captured_piece.piece_type, captured_piece.color)
  305.  
  306.         self.turn = not self.turn
  307.  
  308.         return move
  309.  
  310.     def is_check(self):
  311.         king_square = self.king(self.turn)
  312.         if king_square is None:
  313.             return False
  314.         return self._is_attacked_by(not self.turn, king_square)[0]
  315.  
  316.     def is_checkmate(self):
  317.         if not self.is_check():
  318.             return False
  319.         return not any(self.generate_legal_moves())
  320.  
  321.     def is_stalemate(self):
  322.         if self.is_check():
  323.             return False
  324.         return not any(self.generate_legal_moves())
  325.    
  326.     def is_insufficient_material(self):
  327.             return (self.pawns | self.rooks | self.queens | self.amazons_white | self.amazons_black |
  328.                     self.cyrils_white | self.cyrils_black | self.eves_white | self.eves_black) == 0 and (
  329.                 chess.popcount(self.occupied) <= 3
  330.             )
  331.  
  332.     def is_game_over(self):
  333.         return self.is_checkmate() or self.is_stalemate() or self.is_insufficient_material()
  334.  
  335.     def debug_amazons(self):
  336.         print(f"Bitboard bílých amazonek: {format(self.amazons_white, '064b')}")
  337.         print(f"Bitboard černých amazonek: {format(self.amazons_black, '064b')}")
  338.         for square in chess.SQUARES:
  339.             if self.amazons_white & chess.BB_SQUARES[square]:
  340.                 print(f"Bílá amazonka na {chess.SQUARE_NAMES[square]}")
  341.             if self.amazons_black & chess.BB_SQUARES[square]:
  342.                 print(f"Černá amazonka na {chess.SQUARE_NAMES[square]}")
  343.  
  344.     def debug_cyrils(self):
  345.         print(f"Bitboard bílých Cyrils: {format(self.cyrils_white, '064b')}")
  346.         print(f"Bitboard černých Cyrils: {format(self.cyrils_black, '064b')}")
  347.         for square in chess.SQUARES:
  348.             if self.cyrils_white & chess.BB_SQUARES[square]:
  349.                 print(f"Bílý Cyril na {chess.SQUARE_NAMES[square]}")
  350.             if self.cyrils_black & chess.BB_SQUARES[square]:
  351.                 print(f"Černý Cyril na {chess.SQUARE_NAMES[square]}")
  352.  
  353.     def debug_eves(self):
  354.         print(f"Bitboard bílých Eves: {format(self.eves_white, '064b')}")
  355.         print(f"Bitboard černých Eves: {format(self.eves_black, '064b')}")
  356.         for square in chess.SQUARES:
  357.             if self.eves_white & chess.BB_SQUARES[square]:
  358.                 print(f"Bílá Eve na {chess.SQUARE_NAMES[square]}")
  359.             if self.eves_black & chess.BB_SQUARES[square]:
  360.                 print(f"Černá Eve na {chess.SQUARE_NAMES[square]}")
  361.  
  362.     def piece_symbol(self, piece):
  363.         if piece is None:
  364.             return '.'
  365.         if piece.piece_type == AMAZON:
  366.             return 'A' if piece.color == chess.WHITE else 'a'
  367.         if piece.piece_type == CYRIL:
  368.             return 'C' if piece.color == chess.WHITE else 'c'
  369.         if piece.piece_type == EVE:
  370.             return 'E' if piece.color == chess.WHITE else 'e'
  371.         return piece.symbol()
  372.  
  373.     def piece_type_at(self, square):
  374.         if (self.amazons_white | self.amazons_black) & chess.BB_SQUARES[square]:
  375.             return AMAZON
  376.         if (self.cyrils_white | self.cyrils_black) & chess.BB_SQUARES[square]:
  377.             return CYRIL
  378.         if (self.eves_white | self.eves_black) & chess.BB_SQUARES[square]:
  379.             return EVE
  380.         return super().piece_type_at(square)
  381.  
  382.     def color_at(self, square):
  383.         if self.amazons_white & chess.BB_SQUARES[square]:
  384.             return chess.WHITE
  385.         if self.amazons_black & chess.BB_SQUARES[square]:
  386.             return chess.BLACK
  387.         if self.cyrils_white & chess.BB_SQUARES[square]:
  388.             return chess.WHITE
  389.         if self.cyrils_black & chess.BB_SQUARES[square]:
  390.             return chess.BLACK
  391.         if self.eves_white & chess.BB_SQUARES[square]:
  392.             return chess.WHITE
  393.         if self.eves_black & chess.BB_SQUARES[square]:
  394.             return chess.BLACK
  395.         return super().color_at(square)
  396.  
  397.     @property
  398.     def legal_moves(self):
  399.         return [move for move in self.generate_pseudo_legal_moves() if self.is_legal(move)]
  400.  
  401.     def __str__(self):
  402.         builder = []
  403.         for square in chess.SQUARES_180:
  404.             piece = self.piece_at(square)
  405.             symbol = self.piece_symbol(piece) if piece else '.'
  406.             builder.append(symbol)
  407.             if chess.square_file(square) == 7:
  408.                 if square != chess.H1:
  409.                     builder.append('\n')
  410.         return ''.join(builder)
  411.  
  412.     def simplify_fen_string(fen):
  413.         parts = fen.split(' ')
  414.         return ' '.join(parts[:4])  # Zachováváme pouze informace o pozici, barvě na tahu, rošádách a en passant
  415.    
  416.     def format_time(seconds):
  417.         hours, remainder = divmod(seconds, 3600)
  418.         minutes, seconds = divmod(remainder, 60)
  419.         return f"{int(hours):02d}h {int(minutes):02d}m {int(seconds):02d}s"
  420.    
  421.     def print_elapsed_time(stop_event):
  422.         start_time = time.time()
  423.         while not stop_event.is_set():
  424.             elapsed_time = time.time() - start_time
  425.             formatted_time = time.strftime("%H:%M:%S", time.gmtime(elapsed_time))
  426.             print(f"Uplynulý čas: {formatted_time}", end='\r')
  427.             time.sleep(1)
  428.    
  429.     def calculate_optimal_moves(start_fen: str) -> Dict[str, int]:
  430.         board = CustomBoard(start_fen)
  431.         AR = {simplify_fen_string(start_fen): 0}
  432.         queue = deque([(simplify_fen_string(start_fen), 0)])
  433.         visited = set()
  434.    
  435.         start_time = time.time()
  436.         current_level = 0
  437.         pozice_na_urovni = 0
  438.         level_start_time = start_time
  439.    
  440.         stop_event = threading.Event()
  441.         timer_thread = threading.Thread(target=print_elapsed_time, args=(stop_event,))
  442.         timer_thread.start()
  443.    
  444.         try:
  445.             while queue:
  446.                 fen, hloubka = queue.popleft()
  447.    
  448.                 if hloubka > current_level:
  449.                     level_time = time.time() - level_start_time
  450.                     print(f"\nHloubka {current_level}: {pozice_na_urovni} pozic, Čas: {format_time(level_time)}")
  451.                     current_level = hloubka
  452.                     pozice_na_urovni = 0
  453.                     level_start_time = time.time()
  454.    
  455.                 if fen in visited:
  456.                     continue
  457.    
  458.                 visited.add(fen)
  459.                 pozice_na_urovni += 1
  460.                 board.set_custom_fen(fen)
  461.    
  462.                 if board.is_checkmate():
  463.                     AR[fen] = -1000 + hloubka if board.turn == chess.WHITE else 1000 - hloubka
  464.                     continue
  465.                 elif board.is_stalemate() or board.is_insufficient_material():
  466.                     AR[fen] = 0
  467.                     continue
  468.    
  469.                 legal_moves = list(board.legal_moves)
  470.    
  471.                 for move in legal_moves:
  472.                     board.push(move)
  473.                     new_fen = simplify_fen_string(board.fen())
  474.                     if new_fen not in AR:
  475.                         AR[new_fen] = 0
  476.                         queue.append((new_fen, hloubka + 1))
  477.                     board.pop()
  478.    
  479.             level_time = time.time() - level_start_time
  480.             print(f"\nHloubka {current_level}: {pozice_na_urovni} pozic, Čas: {format_time(level_time)}")
  481.    
  482.             # Procházení a aktualizace hodnot
  483.             changed = True
  484.             while changed:
  485.                 changed = False
  486.                 for fen in AR:
  487.                     board.set_custom_fen(fen)
  488.                     if board.is_game_over():
  489.                         continue
  490.    
  491.                     legal_moves = list(board.legal_moves)
  492.                     if board.turn == chess.WHITE:
  493.                         best_value = max(AR[simplify_fen_string(board.fen())] for _ in [board.push(move), board.pop()] for move in legal_moves)
  494.                         if best_value > AR[fen]:
  495.                             AR[fen] = best_value
  496.                             changed = True
  497.                     else:
  498.                         best_value = min(AR[simplify_fen_string(board.fen())] for _ in [board.push(move), board.pop()] for move in legal_moves)
  499.                         if best_value < AR[fen]:
  500.                             AR[fen] = best_value
  501.                             changed = True
  502.    
  503.             celkovy_cas = time.time() - start_time
  504.             print(f"\nVýpočet dokončen za {format_time(celkovy_cas)}")
  505.    
  506.         finally:
  507.             stop_event.set()
  508.             timer_thread.join()
  509.    
  510.         return AR
  511.  
  512. if __name__ == "__main__":
  513.     start_fen = "8/3k4/8/8/8/8/A7/6K1 w - - 0 1"
  514.     AR = calculate_optimal_moves(start_fen)
  515.  
  516.     # Výpis výsledků
  517.     for fen, hodnota in AR.items():
  518.         print(f"FEN: {fen}")
  519.         print(f"Hodnota: {hodnota}")
  520.         print()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement