Advertisement
max2201111

Amazon Bob Cyryl

Jun 28th, 2024
584
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.85 KB | Science | 0 0
  1. import chess
  2. import time
  3. from functools import lru_cache
  4.  
  5. class CustomPiece(chess.Piece):
  6.     def __init__(self, piece_type, color):
  7.         super().__init__(piece_type, color)
  8.  
  9. class Amazon(CustomPiece):
  10.     def __init__(self, color):
  11.         super().__init__(chess.BISHOP, color)  # BISHOP is a placeholder
  12.  
  13.     def symbol(self):
  14.         return 'A' if self.color == chess.WHITE else 'a'
  15.  
  16. class Bob(CustomPiece):
  17.     def __init__(self, color):
  18.         super().__init__(chess.ROOK, color)
  19.  
  20.     def symbol(self):
  21.         return 'B' if self.color == chess.WHITE else 'b'
  22.  
  23. class Cyryl(CustomPiece):
  24.     def __init__(self, color):
  25.         super().__init__(chess.QUEEN, color)
  26.  
  27.     def symbol(self):
  28.         return 'C' if self.color == chess.WHITE else 'c'
  29.  
  30. class CustomBoard(chess.Board):
  31.     def __init__(self, fen=None):
  32.         self.custom_pieces = {
  33.             'A': Amazon(chess.WHITE), 'a': Amazon(chess.BLACK),
  34.             'B': Bob(chess.WHITE), 'b': Bob(chess.BLACK),
  35.             'C': Cyryl(chess.WHITE), 'c': Cyryl(chess.BLACK)
  36.         }
  37.         super().__init__(fen)
  38.  
  39.     def set_fen(self, fen):
  40.         parts = fen.split(' ')
  41.         while len(parts) < 6:
  42.             parts.append("0")
  43.         board_part = parts[0]
  44.         turn_part = parts[1]
  45.         castling_part = parts[2]
  46.         en_passant_part = parts[3]
  47.         halfmove_clock = parts[4]
  48.         fullmove_number = parts[5]
  49.  
  50.         self.set_board_fen(board_part)
  51.         self.turn = chess.WHITE if turn_part == 'w' else chess.BLACK
  52.         self.castling_rights = chess.BB_EMPTY if castling_part == '-' else chess.SquareSet.from_square(chess.parse_square(castling_part))
  53.         self.ep_square = None if en_passant_part == '-' else chess.parse_square(en_passant_part)
  54.         self.halfmove_clock = int(halfmove_clock)
  55.         self.fullmove_number = int(fullmove_number)
  56.  
  57.     def set_board_fen(self, fen):
  58.         self.clear()
  59.         rows = fen.split('/')
  60.         for rank, row in enumerate(rows):
  61.             file = 0
  62.             for char in row:
  63.                 if char.isdigit():
  64.                     file += int(char)
  65.                 else:
  66.                     square = chess.square(file, 7 - rank)
  67.                     if char in self.custom_pieces:
  68.                         self.set_piece_at(square, self.custom_pieces[char])
  69.                     else:
  70.                         self.set_piece_at(square, chess.Piece.from_symbol(char))
  71.                     file += 1
  72.  
  73.     def piece_symbol(self, piece):
  74.         if piece is None:
  75.             return '.'
  76.         if isinstance(piece, Amazon):
  77.             return 'A'
  78.         if isinstance(piece, Bob):
  79.             return 'B'
  80.         if isinstance(piece, Cyryl):
  81.             return 'C'
  82.         return piece.symbol()
  83.  
  84.     def generate_legal_moves(self, from_mask=chess.BB_ALL, to_mask=chess.BB_ALL):
  85.         for move in super().generate_legal_moves(from_mask, to_mask):
  86.             yield move
  87.        
  88.         for square in self.piece_map():
  89.             piece = self.piece_at(square)
  90.             if piece.symbol().lower() in ['a', 'b', 'c']:
  91.                 yield from self.generate_custom_piece_moves(square, piece)
  92.  
  93.     def generate_custom_piece_moves(self, square, piece):
  94.         knight_moves = [
  95.             (2, 1), (2, -1), (-2, 1), (-2, -1),
  96.             (1, 2), (1, -2), (-1, 2), (-1, -2)
  97.         ]
  98.        
  99.         directions = []
  100.         if piece.symbol().lower() == 'a':  # Amazon: Bishop + Knight moves
  101.             directions = [(1, 1), (1, -1), (-1, 1), (-1, -1)]
  102.             moves = self.generate_sliding_moves(square, directions) + self.generate_knight_moves(square, knight_moves)
  103.         elif piece.symbol().lower() == 'b':  # Bob: Rook + Knight moves
  104.             directions = [(1, 0), (0, 1), (-1, 0), (0, -1)]
  105.             moves = self.generate_sliding_moves(square, directions) + self.generate_knight_moves(square, knight_moves)
  106.         elif piece.symbol().lower() == 'c':  # Cyryl: Queen + Knight moves
  107.             directions = [(1, 1), (1, -1), (-1, 1), (-1, -1), (1, 0), (0, 1), (-1, 0), (0, -1)]
  108.             moves = self.generate_sliding_moves(square, directions) + self.generate_knight_moves(square, knight_moves)
  109.        
  110.         for move in moves:
  111.             if self.is_pseudo_legal(move):
  112.                 yield move
  113.  
  114.     def generate_sliding_moves(self, square, directions):
  115.         moves = []
  116.         for dx, dy in directions:
  117.             x, y = chess.square_file(square), chess.square_rank(square)
  118.             while True:
  119.                 x, y = x + dx, y + dy
  120.                 if 0 <= x < 8 and 0 <= y < 8:
  121.                     dest_square = chess.square(x, y)
  122.                     move = chess.Move(square, dest_square)
  123.                     moves.append(move)
  124.                     if self.piece_at(dest_square):
  125.                         break
  126.                 else:
  127.                     break
  128.         return moves
  129.  
  130.     def generate_knight_moves(self, square, knight_moves):
  131.         moves = []
  132.         for dx, dy in knight_moves:
  133.             file = chess.square_file(square) + dx
  134.             rank = chess.square_rank(square) + dy
  135.             if 0 <= file < 8 and 0 <= rank < 8:
  136.                 dest_square = chess.square(file, rank)
  137.                 move = chess.Move(square, dest_square)
  138.                 moves.append(move)
  139.         return moves
  140.  
  141. @lru_cache(maxsize=None)
  142. def simplify_fen_string(fen):
  143.     parts = fen.split(' ')
  144.     simplified_fen = ' '.join(parts[:4])  # Zachováváme pouze informace o pozici
  145.     if len(parts) < 6:
  146.         simplified_fen += " 0 1"
  147.     return simplified_fen
  148.  
  149. def print_custom_board(fen):
  150.     board = CustomBoard(fen)
  151.     for rank in range(7, -1, -1):
  152.         line = []
  153.         for file in range(8):
  154.             piece = board.piece_at(chess.square(file, rank))
  155.             symbol = board.piece_symbol(piece)
  156.             line.append(symbol)
  157.         print(' '.join(line))
  158.  
  159. # Startovní pozice
  160. start_fen = "8/6A1/8/8/8/k1K5/8/8 w - - 0 1"
  161. print_custom_board(start_fen)  # Tisk ASCII šachovnice pro startovní pozici
  162. simplified_POZ2 = simplify_fen_string(start_fen)
  163. POZ = {1: simplified_POZ2}
  164.  
  165. AR = {simplified_POZ2: {'used': 0, 'to_end': 0}}
  166. N = 1
  167. M = 0
  168.  
  169. start_time = time.time()
  170.  
  171. def format_elapsed_time(elapsed_time):
  172.     hours, remainder = divmod(elapsed_time, 3600)
  173.     minutes, seconds = divmod(remainder, 60)
  174.     return f"{int(hours)}h {int(minutes)}m {int(seconds)}s"
  175.  
  176. def print_elapsed_time(total_time, level_time):
  177.     print(f"{format_elapsed_time(total_time)} / {format_elapsed_time(level_time)}")
  178.  
  179. while M < N:
  180.     M += 1
  181.     current_fen = POZ[M]
  182.     board = CustomBoard(current_fen)
  183.     simplified_current_fen = simplify_fen_string(current_fen)
  184.  
  185.     if simplified_current_fen not in AR:
  186.         AR[simplified_current_fen] = {'used': 0, 'to_end': 0}
  187.  
  188.     if AR[simplified_current_fen]['used'] == 0:
  189.         AR[simplified_current_fen]['used'] = 1
  190.         for move in board.generate_legal_moves():
  191.             # Check if the move is a promotion
  192.             if move.promotion:
  193.                 move.promotion = chess.QUEEN  # Set promotion to queen only
  194.  
  195.             board.push(move)
  196.             POZ2 = board.fen()
  197.             simplified_POZ2 = simplify_fen_string(POZ2)
  198.  
  199.             if simplified_POZ2 not in AR:
  200.                 AR[simplified_POZ2] = {'used': None, 'to_end': 0}
  201.  
  202.             if AR[simplified_POZ2]['used'] is None:
  203.                 N += 1
  204.                 POZ[N] = simplified_POZ2
  205.                 AR[simplified_POZ2] = {'used': 0, 'to_end': 0}
  206.  
  207.             board.pop()  # Vrátíme tah zpět
  208.  
  209. print(f"Počet pozic je {N}")
  210.  
  211. # Přidání kontroly pro mat, remízu a výchozí hodnotu
  212. F = 0
  213. for i in range(1, N + 1):
  214.     current_fen = POZ[i]
  215.     board = CustomBoard(current_fen)
  216.     simplified_current_fen = simplify_fen_string(current_fen)
  217.  
  218.     if simplified_current_fen not in AR:
  219.         AR[simplified_current_fen] = {'used': 0, 'to_end': 0}
  220.  
  221.     if board.is_checkmate():
  222.         AR[simplified_current_fen]['to_end'] = -1000
  223.         F += 1
  224.     elif board.is_stalemate() or board.is_insufficient_material() or board.is_seventyfive_moves() or board.is_fivefold_repetition():
  225.         AR[simplified_current_fen]['to_end'] = 0
  226.     else:
  227.         AR[simplified_current_fen]['to_end'] = 0
  228.  
  229. print(f"Počet pozic v matu je {F}")
  230.  
  231. uroven = 0
  232. while F > 0:
  233.     uroven += 1
  234.     level_start_time = time.time()
  235.     print(f"Výpočet v úrovni {uroven}")
  236.    
  237.     F = 0
  238.     current_level_positions = 0
  239.     for i in range(1, N + 1):
  240.         current_fen = POZ[i]
  241.         board = CustomBoard(current_fen)
  242.         simplified_current_fen = simplify_fen_string(current_fen)
  243.         if AR[simplified_current_fen]['to_end'] == 0:
  244.             hod = -2000
  245.             for move in board.generate_legal_moves():
  246.                 # Check if the move is a promotion
  247.                 if move.promotion:
  248.                     move.promotion = chess.QUEEN  # Set promotion to queen only
  249.  
  250.                 board.push(move)
  251.                 POZ2 = board.fen()
  252.                 simplified_POZ2 = simplify_fen_string(POZ2)
  253.                 if simplified_POZ2 not in AR or AR[simplified_POZ2]['to_end'] is None:
  254.                     hod2 = 0
  255.                 else:
  256.                     hod2 = -AR[simplified_POZ2]['to_end']
  257.                 if hod2 > hod:
  258.                     hod = hod2
  259.                 board.pop()  # Vrátíme tah zpět
  260.             if hod == 1001 - uroven:
  261.                 AR[simplified_current_fen]['to_end'] = 1000 - uroven
  262.                 F += 1
  263.                 current_level_positions += 1
  264.             if hod == -1001 + uroven:
  265.                 AR[simplified_current_fen]['to_end'] = -1000 + uroven
  266.                 F += 1
  267.                 current_level_positions += 1
  268.     level_end_time = time.time()
  269.     total_elapsed_time = level_end_time - start_time
  270.     level_elapsed_time = level_end_time - level_start_time
  271.     print(f"Nalezeno {current_level_positions} pozic v úrovni {uroven}")
  272.     print_elapsed_time(total_elapsed_time, level_elapsed_time)
  273.  
  274. print(f"Nalezeno {F} pozic celkem")
  275.  
  276. # Výpis všech pozic s to_end == 17
  277. print("Pozice s to_end == 17:")
  278. for fen, data in AR.items():
  279.     if data['to_end'] is not None and data['to_end'] < 983 and data['to_end'] > 0:
  280.         print(f"{fen} -> to_end: {data['to_end']}")
  281.  
  282. print("*****")
  283.  
  284. print("Pozice s to_end == -20:")
  285. for fen, data in AR.items():
  286.     if data['to_end'] is not None and data['to_end'] > -981 and data['to_end'] < 0:
  287.         print(f"{fen} -> to_end: {data['to_end']}")
  288.  
  289. current_fen = POZ[1]
  290. board = CustomBoard(current_fen)
  291. simplified_current_fen = simplify_fen_string(current_fen)
  292. hod = AR[simplified_current_fen]['to_end']
  293. print(f"Hodnocení počáteční pozice je {hod}")
  294.  
  295. # Závěrečný kód pro procházení nejlepších tahů
  296. current_fen = start_fen
  297. simplified_current_fen = simplify_fen_string(current_fen)
  298.  
  299. optimal_moves = []
  300. while AR[simplified_current_fen]['to_end'] is not None and AR[simplified_current_fen]['to_end'] > -1000:
  301.     board = CustomBoard(current_fen)
  302.     simplified_current_fen = simplify_fen_string(current_fen)
  303.     hod = -2000
  304.     for move in board.generate_legal_moves():
  305.         # Check if the move is a promotion
  306.         if move.promotion:
  307.             move.promotion = chess.QUEEN  # Set promotion to queen only
  308.  
  309.         board.push(move)
  310.         POZ2 = board.fen()
  311.         simplified_POZ2 = simplify_fen_string(POZ2)
  312.         if simplified_POZ2 not in AR or AR[simplified_POZ2]['to_end'] is None:
  313.             hod2 = 0
  314.         else:
  315.             hod2 = -AR[simplified_POZ2]['to_end']
  316.         if hod2 > hod:
  317.             hod = hod2
  318.             best_fen = simplified_POZ2
  319.         board.pop()  # Vrátíme tah zpět
  320.  
  321.     optimal_moves.append(best_fen)
  322.     current_fen = best_fen
  323.     simplified_current_fen = simplify_fen_string(current_fen)
  324.  
  325. # Tisk šachovnic v opačném pořadí
  326. for fen in reversed(optimal_moves):
  327.     print_custom_board(fen)
  328.     print("\n")
  329.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement