Advertisement
max2201111

aktualizace hodnot OK??

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