Advertisement
max2201111

posledni very good the best jeste ASCII pridat

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