Advertisement
max2201111

bishops amazons BB good OK

Jul 4th, 2024
924
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 15.75 KB | Science | 0 0
  1. import chess
  2. import time
  3. from functools import lru_cache
  4. import traceback
  5. from typing import Iterator
  6. from chess import Move, BB_ALL, Bitboard, scan_reversed
  7.  
  8. # Definice nových figurek
  9. AMAZON = 7
  10.  
  11. class CustomBoard(chess.Board):
  12.     def __init__(self, fen=None):
  13.         self.amazons = chess.BB_EMPTY
  14.         self.custom_bishops = chess.BB_EMPTY
  15.         super().__init__(None)  # Initialize with empty board
  16.         if fen:
  17.             self.set_custom_fen(fen)
  18.  
  19.     def set_custom_fen(self, fen):
  20.         parts = fen.split()
  21.         board_part = parts[0]
  22.         self.clear()
  23.         self.amazons = chess.BB_EMPTY
  24.         self.custom_bishops = chess.BB_EMPTY
  25.         square = 0
  26.         for c in board_part:
  27.             if c == '/':
  28.                 continue
  29.             elif c.isdigit():
  30.                 square += int(c)
  31.             else:
  32.                 color = chess.WHITE if c.isupper() else chess.BLACK
  33.                 piece_type = chess.PIECE_SYMBOLS.index(c.lower()) if c.lower() not in ['a', 'b'] else (AMAZON if c.lower() == 'a' else chess.BISHOP)
  34.                 self._set_piece_at(square, chess.Piece(piece_type, color))
  35.                 square += 1
  36.        
  37.         self.turn = chess.WHITE if parts[1] == 'w' else chess.BLACK
  38.         self.set_castling_fen(parts[2])
  39.         self.ep_square = chess.parse_square(parts[3]) if parts[3] != '-' else None
  40.         self.halfmove_clock = int(parts[4]) if len(parts) > 4 else 0
  41.         self.fullmove_number = int(parts[5]) if len(parts) > 5 else 1
  42.         print(f"After setting FEN, amazons bitboard: {self.amazons:064b}")
  43.         print(f"After setting FEN, custom bishops bitboard: {self.custom_bishops:064b}")
  44.  
  45.     def _set_piece_at(self, square, piece, promoted=False):
  46.         super()._set_piece_at(square, piece, promoted)
  47.         if piece:
  48.             if piece.piece_type == AMAZON:
  49.                 self.amazons |= chess.BB_SQUARES[square]
  50.             elif piece.piece_type == chess.BISHOP:
  51.                 self.custom_bishops |= chess.BB_SQUARES[square]
  52.         else:
  53.             self.amazons &= ~chess.BB_SQUARES[square]
  54.             self.custom_bishops &= ~chess.BB_SQUARES[square]
  55.         print(f"After _set_piece_at, amazons bitboard: {self.amazons:064b}")
  56.         print(f"After _set_piece_at, custom bishops bitboard: {self.custom_bishops:064b}")
  57.  
  58.     def piece_type_at(self, square):
  59.         if self.amazons & chess.BB_SQUARES[square]:
  60.             return AMAZON
  61.         if self.custom_bishops & chess.BB_SQUARES[square]:
  62.             return chess.BISHOP
  63.         return super().piece_type_at(square)
  64.  
  65.     def piece_at(self, square):
  66.         if self.amazons & chess.BB_SQUARES[square]:
  67.             color = bool(self.occupied_co[chess.WHITE] & chess.BB_SQUARES[square])
  68.             return chess.Piece(AMAZON, color)
  69.         if self.custom_bishops & chess.BB_SQUARES[square]:
  70.             color = bool(self.occupied_co[chess.WHITE] & chess.BB_SQUARES[square])
  71.             return chess.Piece(chess.BISHOP, color)
  72.         return super().piece_at(square)
  73.  
  74.     def generate_pseudo_legal_moves(self, from_mask: Bitboard = BB_ALL, to_mask: Bitboard = BB_ALL) -> Iterator[Move]:
  75.         print("Generating pseudo-legal moves...")
  76.         print(f"Current amazons bitboard: {self.amazons:064b}")
  77.         print(f"Current custom bishops bitboard: {self.custom_bishops:064b}")
  78.         print(f"Current turn: {'White' if self.turn == chess.WHITE else 'Black'}")
  79.  
  80.         # Generate standard moves
  81.         for move in super().generate_pseudo_legal_moves(from_mask, to_mask):
  82.             print(f"Standard pseudo-legal move: {move}")
  83.             yield move
  84.  
  85.         # Generate amazon moves
  86.         our_amazons = self.amazons & self.occupied_co[self.turn] & from_mask
  87.         print(f"Our amazons: {our_amazons:064b}")
  88.         for from_square in chess.scan_forward(our_amazons):
  89.             attacks = self.amazon_attacks(from_square)
  90.             print(f"Amazon at {chess.SQUARE_NAMES[from_square]}, attacks: {attacks:064b}")
  91.             for to_square in chess.scan_forward(attacks & ~self.occupied & to_mask):
  92.                 move = Move(from_square, to_square)
  93.                 print(f"Amazon pseudo-legal move: {move}")
  94.                 yield move
  95.  
  96.         # Generate custom bishop moves
  97.         our_bishops = self.custom_bishops & self.occupied_co[self.turn] & from_mask
  98.         print(f"Our custom bishops: {our_bishops:064b}")
  99.         for from_square in chess.scan_forward(our_bishops):
  100.             attacks = self.bishop_attacks(from_square)
  101.             print(f"Custom bishop at {chess.SQUARE_NAMES[from_square]}, attacks: {attacks:064b}")
  102.             for to_square in chess.scan_forward(attacks & ~self.occupied & to_mask):
  103.                 move = Move(from_square, to_square)
  104.                 print(f"Custom bishop pseudo-legal move: {move}")
  105.                 yield move
  106.  
  107.     def amazon_attacks(self, square):
  108.         queen_attacks = self.attacks_mask(chess.QUEEN, square, self.occupied)
  109.         knight_attacks = self.attacks_mask(chess.KNIGHT, square, self.occupied)
  110.         print(f"Amazon at {chess.SQUARE_NAMES[square]}:")
  111.         print(f"  Queen attacks: {queen_attacks:064b}")
  112.         print(f"  Knight attacks: {knight_attacks:064b}")
  113.         return queen_attacks | knight_attacks
  114.  
  115.     def bishop_attacks(self, square):
  116.         return self.attacks_mask(chess.BISHOP, square, self.occupied)
  117.  
  118.     def is_check(self):
  119.         king = self.king(self.turn)
  120.         if king is None:
  121.             return False
  122.  
  123.         if super().is_check():
  124.             return True
  125.  
  126.         opponent_amazons = self.amazons & self.occupied_co[not self.turn]
  127.         for amazon_square in chess.scan_forward(opponent_amazons):
  128.             if self.amazon_attacks(amazon_square) & chess.BB_SQUARES[king]:
  129.                 return True
  130.  
  131.         return False
  132.  
  133.     def is_legal(self, move: Move) -> bool:
  134.         print(f"Checking legality of move: {move}")
  135.         if not self.is_pseudo_legal(move):
  136.             print("Move is not pseudo-legal")
  137.             return False
  138.        
  139.         self.push(move)
  140.         legal = not self.is_check()
  141.         self.pop()
  142.        
  143.         if legal:
  144.             print("Move is legal")
  145.         else:
  146.             print("Move is illegal (leaves king in check)")
  147.         return legal
  148.  
  149.     def push(self, move):
  150.         piece = self.piece_at(move.from_square)
  151.         super().push(move)
  152.         if piece:
  153.             if piece.piece_type == AMAZON:
  154.                 self.amazons &= ~chess.BB_SQUARES[move.from_square]
  155.                 self.amazons |= chess.BB_SQUARES[move.to_square]
  156.             elif piece.piece_type == chess.BISHOP:
  157.                 self.custom_bishops &= ~chess.BB_SQUARES[move.from_square]
  158.                 self.custom_bishops |= chess.BB_SQUARES[move.to_square]
  159.  
  160.     def pop(self):
  161.         move = self.move_stack[-1]
  162.         piece = self.piece_at(move.to_square)
  163.         result = super().pop()
  164.         if piece:
  165.             if piece.piece_type == AMAZON:
  166.                 self.amazons &= ~chess.BB_SQUARES[move.to_square]
  167.                 self.amazons |= chess.BB_SQUARES[move.from_square]
  168.             elif piece.piece_type == chess.BISHOP:
  169.                 self.custom_bishops &= ~chess.BB_SQUARES[move.to_square]
  170.                 self.custom_bishops |= chess.BB_SQUARES[move.from_square]
  171.         return result
  172.  
  173.     def piece_symbol(self, piece):
  174.         if piece is None:
  175.             return '.'
  176.         if piece.piece_type == AMAZON:
  177.             return 'A' if piece.color == chess.WHITE else 'a'
  178.         if piece.piece_type == chess.BISHOP:
  179.             return 'B' if piece.color == chess.WHITE else 'b'
  180.         return piece.symbol()
  181.  
  182.     def fen(self):
  183.         fen = []
  184.         empty = 0
  185.  
  186.         for square in chess.SQUARES_180:
  187.             piece = self.piece_at(square)
  188.  
  189.             if not piece:
  190.                 empty += 1
  191.             else:
  192.                 if empty:
  193.                     fen.append(str(empty))
  194.                     empty = 0
  195.                 fen.append(self.piece_symbol(piece))
  196.  
  197.             if chess.BB_SQUARES[square] & chess.BB_FILE_H:
  198.                 if empty:
  199.                     fen.append(str(empty))
  200.                     empty = 0
  201.  
  202.                 if square != chess.H1:
  203.                     fen.append("/")
  204.  
  205.         return " ".join([
  206.             "".join(fen),
  207.             "w" if self.turn == chess.WHITE else "b",
  208.             self.castling_xfen(),
  209.             chess.SQUARE_NAMES[self.ep_square] if self.ep_square is not None else "-",
  210.             str(self.halfmove_clock),
  211.             str(self.fullmove_number)
  212.         ])
  213.  
  214. @lru_cache(maxsize=None)
  215. def simplify_fen_string(fen):
  216.     parts = fen.split(' ')
  217.     return ' '.join(parts[:4])
  218.  
  219. def format_time(seconds):
  220.     hours, remainder = divmod(seconds, 3600)
  221.     minutes, seconds = divmod(remainder, 60)
  222.     return f"{int(hours):02d}h {int(minutes):02d}m {int(seconds):02d}s"
  223.  
  224. def analyze_positions(start_fen, min_depth=5):
  225.     POZ = {1: start_fen}
  226.     AR = {simplify_fen_string(start_fen): {'depth': 0, 'value': None}}
  227.     N = 1
  228.  
  229.     start_time = time.time()
  230.     total_time = 0
  231.  
  232.     while True:
  233.         new_positions = False
  234.         for i in range(1, N + 1):
  235.             current_fen = POZ[i]
  236.             board = CustomBoard(current_fen)
  237.             simplified_fen = simplify_fen_string(current_fen)
  238.            
  239.             if AR[simplified_fen]['depth'] == 0:
  240.                 AR[simplified_fen]['depth'] = 1
  241.                 legal_moves = list(board.legal_moves)
  242.                 print(f"Pozice {i}: {simplified_fen}, Počet legálních tahů: {len(legal_moves)}")
  243.                 for move in legal_moves:
  244.                     board.push(move)
  245.                     new_fen = board.fen()
  246.                     simplified_new_fen = simplify_fen_string(new_fen)
  247.                     if simplified_new_fen not in AR:
  248.                         N += 1
  249.                         POZ[N] = new_fen
  250.                         AR[simplified_new_fen] = {'depth': 0, 'value': None}
  251.                         new_positions = True
  252.                     board.pop()
  253.        
  254.         if not new_positions:
  255.             break
  256.        
  257.     print(f"Celkový počet pozic: {N}")
  258.  
  259.     # Inicializace koncových pozic
  260.     terminal_positions = 0
  261.     for i in range(1, N + 1):
  262.         current_fen = POZ[i]
  263.         board = CustomBoard(current_fen)
  264.         simplified_fen = simplify_fen_string(current_fen)
  265.  
  266.         if board.is_checkmate():
  267.             AR[simplified_fen]['value'] = -1000 if board.turn == chess.WHITE else 1000
  268.             AR[simplified_fen]['depth'] = min_depth
  269.             terminal_positions += 1
  270.         elif board.is_stalemate() or board.is_insufficient_material() or board.is_seventyfive_moves() or board.is_fivefold_repetition():
  271.             AR[simplified_fen]['value'] = 0
  272.             AR[simplified_fen]['depth'] = min_depth
  273.             terminal_positions += 1
  274.  
  275.     print(f"Počet koncových pozic: {terminal_positions}")
  276.  
  277.     max_depth = 0
  278.     while max_depth < min_depth:
  279.         max_depth += 1
  280.         level_start_time = time.time()
  281.        
  282.         changes = False
  283.         positions_evaluated = 0
  284.         for i in range(1, N + 1):
  285.             current_fen = POZ[i]
  286.             board = CustomBoard(current_fen)
  287.             simplified_fen = simplify_fen_string(current_fen)
  288.             if AR[simplified_fen]['depth'] < max_depth and AR[simplified_fen]['value'] is None:
  289.                 positions_evaluated += 1
  290.                 best_value = -2000 if board.turn == chess.WHITE else 2000
  291.                 all_moves_evaluated = True
  292.                 legal_moves = list(board.legal_moves)
  293.                 for move in legal_moves:
  294.                     board.push(move)
  295.                     next_fen = board.fen()
  296.                     simplified_next_fen = simplify_fen_string(next_fen)
  297.                     if simplified_next_fen not in AR:
  298.                         all_moves_evaluated = False
  299.                         break
  300.                     next_value = AR[simplified_next_fen]['value']
  301.                     if next_value is None:
  302.                         all_moves_evaluated = False
  303.                         break
  304.                     if board.turn == chess.WHITE:
  305.                         best_value = max(best_value, -next_value)
  306.                     else:
  307.                         best_value = min(best_value, -next_value)
  308.                     board.pop()
  309.                
  310.                 if all_moves_evaluated:
  311.                     AR[simplified_fen]['value'] = best_value
  312.                     AR[simplified_fen]['depth'] = max_depth
  313.                     changes = True
  314.  
  315.         level_end_time = time.time()
  316.         level_elapsed_time = level_end_time - level_start_time
  317.         total_time += level_elapsed_time
  318.        
  319.         formatted_total_time = format_time(total_time)
  320.         formatted_level_time = format_time(level_elapsed_time)
  321.        
  322.         print(f"Hloubka {max_depth} dokončena")
  323.         print(f"Pozice vyhodnoceny: {positions_evaluated}")
  324.         print(f"Změny provedeny: {'Ano' if changes else 'Ne'}")
  325.         print(f"Čas: {formatted_total_time} / {formatted_level_time}")
  326.  
  327.     print(f"Analýza dokončena do hloubky {max_depth}")
  328.     print(f"Celkový čas: {format_time(total_time)}")
  329.  
  330.     current_fen = start_fen
  331.     optimal_moves = []
  332.     while True:
  333.         board = CustomBoard(current_fen)
  334.         simplified_fen = simplify_fen_string(current_fen)
  335.         if simplified_fen not in AR:
  336.             break
  337.         current_value = AR[simplified_fen]['value']
  338.        
  339.         if current_value in [-1000, 0, 1000] or current_value is None:
  340.             break
  341.        
  342.         best_move = None
  343.         for move in board.legal_moves:
  344.             board.push(move)
  345.             next_fen = board.fen()
  346.             simplified_next_fen = simplify_fen_string(next_fen)
  347.             if simplified_next_fen not in AR:
  348.                 continue
  349.             next_value = AR[simplified_next_fen]['value']
  350.             if next_value is not None and next_value == -current_value:
  351.                 best_move = move
  352.                 break
  353.             board.pop()
  354.        
  355.         if best_move is None:
  356.             break
  357.        
  358.         optimal_moves.append((current_fen, best_move))
  359.         board.push(best_move)
  360.         current_fen = board.fen()
  361.  
  362.     print("\nOptimální tahy:")
  363.     for fen, move in optimal_moves:
  364.         board = CustomBoard(fen)
  365.         print(f"{board.fullmove_number}. {'Bílý' if board.turn == chess.WHITE else 'Černý'}: {move}")
  366.  
  367.     print("\nKonečná pozice:")
  368.     print(f"FEN: {current_fen}")
  369.  
  370. if __name__ == "__main__":
  371.     start_fen = "1b6/3k4/8/8/8/8/8/6K1 b - - 0 1"
  372.    
  373.     try:
  374.         print(f"Creating board with FEN: {start_fen}")
  375.         initial_board = CustomBoard(start_fen)
  376.        
  377.         print("Debugging amazons...")
  378.         print(f"Amazons bitboard: {initial_board.amazons:064b}")
  379.         print(f"Bishops bitboard: {initial_board.bishops:064b}")
  380.        
  381.        
  382.         print("Piece positions:")
  383.         for square in chess.SQUARES:
  384.             piece = initial_board.piece_at(square)
  385.             if piece:
  386.                 print(f"{chess.SQUARE_NAMES[square]}: {initial_board.piece_symbol(piece)}")
  387.        
  388.         print("Generating legal moves for initial position...")
  389.         legal_moves = list(initial_board.legal_moves)
  390.         print(f"Number of legal moves: {len(legal_moves)}")
  391.        
  392.         print("Legal moves:")
  393.         for move in legal_moves:
  394.             from_square = chess.SQUARE_NAMES[move.from_square]
  395.             to_square = chess.SQUARE_NAMES[move.to_square]
  396.             piece = initial_board.piece_at(move.from_square)
  397.             print(f"{initial_board.piece_symbol(piece)}: {from_square}-{to_square}")
  398.        
  399.         analyze_positions(start_fen, min_depth=5)
  400.     except Exception as e:
  401.         print(f"An error occurred: {str(e)}")
  402.         traceback.print_exc()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement