Advertisement
max2201111

posledniii v

Jul 25th, 2024
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 33.83 KB | Science | 0 0
  1. # Import knihovny chess a dalších potřebných modulů
  2. import chess
  3. from typing import Iterator, Optional, Dict, Tuple
  4. from chess import Move, BB_ALL, Bitboard, PieceType, Color
  5. import time
  6. from collections import deque
  7. import threading
  8.  
  9. # Definice nových figur
  10. AMAZON = 7
  11. CYRIL = 8
  12. EVE = 9
  13.  
  14. # Rozšíření seznamu PIECE_SYMBOLS
  15. chess.PIECE_SYMBOLS.append('a')
  16. chess.PIECE_SYMBOLS.append('c')
  17. chess.PIECE_SYMBOLS.append('e')
  18.  
  19. class CustomBoard(chess.Board):
  20.     def __init__(self, fen=None):
  21.         self.amazons_white = chess.BB_EMPTY
  22.         self.amazons_black = chess.BB_EMPTY
  23.         self.cyrils_white = chess.BB_EMPTY
  24.         self.cyrils_black = chess.BB_EMPTY
  25.         self.eves_white = chess.BB_EMPTY
  26.         self.eves_black = chess.BB_EMPTY
  27.         super().__init__(None)
  28.         if fen:
  29.             self.set_custom_fen(fen)
  30.     #    print("Šachovnice inicializována")
  31.         self.debug_amazons()
  32.         self.debug_cyrils()
  33.         self.debug_eves()
  34.  
  35.     def clear_square(self, square):
  36.         super()._remove_piece_at(square)
  37.         self.amazons_white &= ~chess.BB_SQUARES[square]
  38.         self.amazons_black &= ~chess.BB_SQUARES[square]
  39.         self.cyrils_white &= ~chess.BB_SQUARES[square]
  40.         self.cyrils_black &= ~chess.BB_SQUARES[square]
  41.         self.eves_white &= ~chess.BB_SQUARES[square]
  42.         self.eves_black &= ~chess.BB_SQUARES[square]
  43.  
  44.     def set_custom_fen(self, fen):
  45.         parts = fen.split()
  46.         board_part = parts[0]
  47.  
  48.         self.clear()
  49.         self.amazons_white = chess.BB_EMPTY
  50.         self.amazons_black = chess.BB_EMPTY
  51.         self.cyrils_white = chess.BB_EMPTY
  52.         self.cyrils_black = chess.BB_EMPTY
  53.         self.eves_white = chess.BB_EMPTY
  54.         self.eves_black = chess.BB_EMPTY
  55.  
  56.         square = 56
  57.         for c in board_part:
  58.             if c == '/':
  59.                 square -= 16
  60.             elif c.isdigit():
  61.                 square += int(c)
  62.             else:
  63.                 color = chess.WHITE if c.isupper() else chess.BLACK
  64.                 if c.upper() == 'A':
  65.                     if color == chess.WHITE:
  66.                         self.amazons_white |= chess.BB_SQUARES[square]
  67.                     else:
  68.                         self.amazons_black |= chess.BB_SQUARES[square]
  69.                     piece_type = AMAZON
  70.                 elif c.upper() == 'C':
  71.                     if color == chess.WHITE:
  72.                         self.cyrils_white |= chess.BB_SQUARES[square]
  73.                     else:
  74.                         self.cyrils_black |= chess.BB_SQUARES[square]
  75.                     piece_type = CYRIL
  76.                 elif c.upper() == 'E':
  77.                     if color == chess.WHITE:
  78.                         self.eves_white |= chess.BB_SQUARES[square]
  79.                     else:
  80.                         self.eves_black |= chess.BB_SQUARES[square]
  81.                     piece_type = EVE
  82.                 else:
  83.                     piece_type = chess.PIECE_SYMBOLS.index(c.lower())
  84.                 self._set_piece_at(square, piece_type, color)
  85.                 square += 1
  86.  
  87.         self.turn = chess.WHITE if parts[1] == 'w' else chess.BLACK
  88.         self.castling_rights = chess.BB_EMPTY
  89.         if '-' not in parts[2]:
  90.             if 'K' in parts[2]: self.castling_rights |= chess.BB_H1
  91.             if 'Q' in parts[2]: self.castling_rights |= chess.BB_A1
  92.             if 'k' in parts[2]: self.castling_rights |= chess.BB_H8
  93.             if 'q' in parts[2]: self.castling_rights |= chess.BB_A8
  94.         self.ep_square = chess.parse_square(parts[3]) if parts[3] != '-' else None
  95.  
  96.     def _set_piece_at(self, square: chess.Square, piece_type: PieceType, color: Color) -> None:
  97.         self.clear_square(square)
  98.         super()._set_piece_at(square, piece_type, color)
  99.         if piece_type == AMAZON:
  100.             if color == chess.WHITE:
  101.                 self.amazons_white |= chess.BB_SQUARES[square]
  102.             else:
  103.                 self.amazons_black |= chess.BB_SQUARES[square]
  104.         elif piece_type == CYRIL:
  105.             if color == chess.WHITE:
  106.                 self.cyrils_white |= chess.BB_SQUARES[square]
  107.             else:
  108.                 self.cyrils_black |= chess.BB_SQUARES[square]
  109.         elif piece_type == EVE:
  110.             if color == chess.WHITE:
  111.                 self.eves_white |= chess.BB_SQUARES[square]
  112.             else:
  113.                 self.eves_black |= chess.BB_SQUARES[square]
  114.  
  115.     def piece_at(self, square: chess.Square) -> Optional[chess.Piece]:
  116.         if self.amazons_white & chess.BB_SQUARES[square]:
  117.             return chess.Piece(AMAZON, chess.WHITE)
  118.         elif self.amazons_black & chess.BB_SQUARES[square]:
  119.             return chess.Piece(AMAZON, chess.BLACK)
  120.         elif self.cyrils_white & chess.BB_SQUARES[square]:
  121.             return chess.Piece(CYRIL, chess.WHITE)
  122.         elif self.cyrils_black & chess.BB_SQUARES[square]:
  123.             return chess.Piece(CYRIL, chess.BLACK)
  124.         elif self.eves_white & chess.BB_SQUARES[square]:
  125.             return chess.Piece(EVE, chess.WHITE)
  126.         elif self.eves_black & chess.BB_SQUARES[square]:
  127.             return chess.Piece(EVE, chess.BLACK)
  128.         return super().piece_at(square)
  129.  
  130.     def generate_pseudo_legal_moves(self, from_mask: Bitboard = BB_ALL, to_mask: Bitboard = BB_ALL) -> Iterator[Move]:
  131.         our_pieces = self.occupied_co[self.turn]
  132.         if self.turn == chess.WHITE:
  133.             our_amazons = self.amazons_white
  134.             our_cyrils = self.cyrils_white
  135.             our_eves = self.eves_white
  136.         else:
  137.             our_amazons = self.amazons_black
  138.             our_cyrils = self.cyrils_black
  139.             our_eves = self.eves_black
  140.    
  141.         # Generování tahů pro amazonky
  142.         for from_square in chess.scan_forward(our_amazons & from_mask):
  143.             attacks = self.amazon_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.         # Generování tahů pro Cyrily
  149.         for from_square in chess.scan_forward(our_cyrils & from_mask):
  150.             attacks = self.cyril_attacks(from_square)
  151.             valid_moves = attacks & ~our_pieces & to_mask
  152.             for to_square in chess.scan_forward(valid_moves):
  153.                 yield Move(from_square, to_square)
  154.    
  155.         # Generování tahů pro Evy
  156.         for from_square in chess.scan_forward(our_eves & from_mask):
  157.             attacks = self.eve_attacks(from_square)
  158.             valid_moves = attacks & ~our_pieces & to_mask
  159.             for to_square in chess.scan_forward(valid_moves):
  160.                 yield Move(from_square, to_square)
  161.    
  162.         # Generování tahů pro standardní figury
  163.         for move in super().generate_pseudo_legal_moves(from_mask, to_mask):
  164.             piece = self.piece_at(move.from_square)
  165.             if piece and piece.piece_type not in [AMAZON, CYRIL, EVE]:
  166.                 yield move
  167.  
  168.     def queen_attacks(self, square):
  169.         return self.bishop_attacks(square) | self.rook_attacks(square)
  170.  
  171.     def bishop_attacks(self, square):
  172.         return chess.BB_DIAG_ATTACKS[square][self.occupied & chess.BB_DIAG_MASKS[square]]
  173.  
  174.     def rook_attacks(self, square):
  175.         return (chess.BB_RANK_ATTACKS[square][self.occupied & chess.BB_RANK_MASKS[square]] |
  176.                 chess.BB_FILE_ATTACKS[square][self.occupied & chess.BB_FILE_MASKS[square]])
  177.  
  178.     def amazon_attacks(self, square):
  179.         return self.queen_attacks(square) | chess.BB_KNIGHT_ATTACKS[square]
  180.  
  181.     def cyril_attacks(self, square):
  182.         return self.rook_attacks(square) | chess.BB_KNIGHT_ATTACKS(square)
  183.  
  184.     def eve_attacks(self, square):
  185.         return self.bishop_attacks(square) | chess.BB_KNIGHT_ATTACKS(square)
  186.  
  187.     def is_pseudo_legal(self, move):
  188.         from_square = move.from_square
  189.         to_square = move.to_square
  190.         piece = self.piece_at(from_square)
  191.    
  192.         if not piece or piece.color != self.turn:
  193.             return False
  194.    
  195.         if self.occupied_co[self.turn] & chess.BB_SQUARES[to_square]:
  196.             return False
  197.    
  198.         if self.is_castling(move):
  199.             return True
  200.    
  201.         if piece.piece_type == AMAZON:
  202.             return bool(self.amazon_attacks(from_square) & chess.BB_SQUARES[to_square])
  203.         elif piece.piece_type == CYRIL:
  204.             return bool(self.cyril_attacks(from_square) & chess.BB_SQUARES[to_square])
  205.         elif piece.piece_type == EVE:
  206.             return bool(self.eve_attacks(from_square) & chess.BB_SQUARES[to_square])
  207.         else:
  208.             return super().is_pseudo_legal(move)
  209.  
  210.     # def is_legal(self, move):
  211.     #     if not self.is_pseudo_legal(move):
  212.     #         return False
  213.  
  214.     #     from_square = move.from_square
  215.     #     to_square = move.to_square
  216.     #     piece = self.piece_at(from_square)
  217.     #     captured_piece = self.piece_at(to_square)
  218.  
  219.     #     self.clear_square(from_square)
  220.     #     self.clear_square(to_square)
  221.     #     self._set_piece_at(to_square, piece.piece_type, piece.color)
  222.  
  223.     #     king_square = to_square if piece.piece_type == chess.KING else self.king(self.turn)
  224.     #     is_check = self._is_attacked_by(not self.turn, king_square)
  225.  
  226.     #     self.clear_square(to_square)
  227.     #     self._set_piece_at(from_square, piece.piece_type, piece.color)
  228.     #     if captured_piece:
  229.     #         self._set_piece_at(to_square, captured_piece.piece_type, captured_piece.color)
  230.  
  231.     #     if is_check:
  232.     #         attackers = self.attackers(not self.turn, king_square)
  233.     # #        print(f"[DEBUG] King at {chess.SQUARE_NAMES[king_square]} is attacked by pieces at: {[chess.SQUARE_NAMES[sq] for sq in chess.scan_forward(attackers)]}")
  234.  
  235.     #     return not is_check
  236.  
  237.     def _is_attacked_by(self, color, square):
  238.         attackers = self.attackers(color, square)
  239.         return bool(attackers)
  240.  
  241.     def attackers(self, color, square):
  242.         if square is None:
  243.             return chess.BB_EMPTY
  244.        
  245.         attackers = chess.BB_EMPTY
  246.        
  247.         # Knights
  248.         knights = self.knights & self.occupied_co[color]
  249.         if chess.BB_KNIGHT_ATTACKS[square] & knights:
  250.             attackers |= knights & chess.BB_KNIGHT_ATTACKS[square]
  251.        
  252.         # King
  253.         king = self.kings & self.occupied_co[color]
  254.         if chess.BB_KING_ATTACKS[square] & king:
  255.             attackers |= king
  256.        
  257.         # Pawns
  258.         pawns = self.pawns & self.occupied_co[color]
  259.         pawn_attacks = chess.BB_PAWN_ATTACKS[not color][square]
  260.         if pawn_attacks & pawns:
  261.             attackers |= pawns & pawn_attacks
  262.        
  263.         # Queens
  264.         queens = self.queens & self.occupied_co[color]
  265.         queen_attacks = (
  266.             chess.BB_DIAG_ATTACKS[square][self.occupied & chess.BB_DIAG_MASKS[square]] |
  267.             chess.BB_RANK_ATTACKS[square][self.occupied & chess.BB_RANK_MASKS[square]] |
  268.             chess.BB_FILE_ATTACKS[square][self.occupied & chess.BB_FILE_MASKS[square]]
  269.         )
  270.         if queen_attacks & queens:
  271.             attackers |= queens & queen_attacks
  272.        
  273.         # Bishops
  274.         bishops = self.bishops & self.occupied_co[color]
  275.         bishop_attacks = chess.BB_DIAG_ATTACKS[square][self.occupied & chess.BB_DIAG_MASKS[square]]
  276.         if bishop_attacks & bishops:
  277.             attackers |= bishops & bishop_attacks
  278.        
  279.         # Rooks
  280.         rooks = self.rooks & self.occupied_co[color]
  281.         rook_attacks = (
  282.             chess.BB_RANK_ATTACKS[square][self.occupied & chess.BB_RANK_MASKS[square]] |
  283.             chess.BB_FILE_ATTACKS[square][self.occupied & chess.BB_FILE_MASKS[square]]
  284.         )
  285.         if rook_attacks & rooks:
  286.             attackers |= rooks & rook_attacks
  287.        
  288.         # Amazons (Queen + Knight)
  289.         amazons = self.amazons_white if color == chess.WHITE else self.amazons_black
  290.         for amazon_square in chess.scan_forward(amazons):
  291.             amazon_attacks = (
  292.                 chess.BB_DIAG_ATTACKS[amazon_square][self.occupied & chess.BB_DIAG_MASKS[amazon_square]] |
  293.                 chess.BB_RANK_ATTACKS[amazon_square][self.occupied & chess.BB_RANK_MASKS[amazon_square]] |
  294.                 chess.BB_FILE_ATTACKS[amazon_square][self.occupied & chess.BB_FILE_MASKS[amazon_square]] |
  295.                 chess.BB_KNIGHT_ATTACKS[amazon_square]
  296.             )
  297.             if amazon_attacks & chess.BB_SQUARES[square]:
  298.                 attackers |= chess.BB_SQUARES[amazon_square]
  299.        
  300.         # Cyrils (Rook + Knight)
  301.         cyrils = self.cyrils_white if color == chess.WHITE else self.cyrils_black
  302.         for cyril_square in chess.scan_forward(cyrils):
  303.             cyril_attacks = (
  304.                 chess.BB_RANK_ATTACKS[cyril_square][self.occupied & chess.BB_RANK_MASKS[cyril_square]] |
  305.                 chess.BB_FILE_ATTACKS[cyril_square][self.occupied & chess.BB_FILE_MASKS[cyril_square]] |
  306.                 chess.BB_KNIGHT_ATTACKS[cyril_square]
  307.             )
  308.             if cyril_attacks & chess.BB_SQUARES[square]:
  309.                 attackers |= chess.BB_SQUARES[cyril_square]
  310.        
  311.         # Eves (Bishop + Knight)
  312.         eves = self.eves_white if color == chess.WHITE else self.eves_black
  313.         for eve_square in chess.scan_forward(eves):
  314.             eve_attacks = (
  315.                 chess.BB_DIAG_ATTACKS[eve_square][self.occupied & chess.BB_DIAG_MASKS[eve_square]] |
  316.                 chess.BB_KNIGHT_ATTACKS[eve_square]
  317.             )
  318.             if eve_attacks & chess.BB_SQUARES[square]:
  319.                 attackers |= chess.BB_SQUARES[eve_square]
  320.        
  321.         return attackers
  322.  
  323.     def is_legal(self, move):
  324.         if not self.is_pseudo_legal(move):
  325.             return False
  326.  
  327.         from_square = move.from_square
  328.         to_square = move.to_square
  329.         piece = self.piece_at(from_square)
  330.         captured_piece = self.piece_at(to_square)
  331.  
  332.         self.clear_square(from_square)
  333.         self.clear_square(to_square)
  334.         self._set_piece_at(to_square, piece.piece_type, piece.color)
  335.  
  336.         king_square = to_square if piece.piece_type == chess.KING else self.king(self.turn)
  337.         is_check = False
  338.         if king_square is not None:
  339.             is_check = self._is_attacked_by(not self.turn, king_square)
  340.  
  341.         self.clear_square(to_square)
  342.         self._set_piece_at(from_square, piece.piece_type, piece.color)
  343.         if captured_piece:
  344.             self._set_piece_at(to_square, captured_piece.piece_type, captured_piece.color)
  345.  
  346.         return not is_check        
  347.  
  348.     def push(self, move):
  349.         if not self.is_legal(move):
  350.             raise ValueError(f"Move {move} is not legal in position {self.fen()}")
  351.  
  352.         piece = self.piece_at(move.from_square)
  353.         captured_piece = self.piece_at(move.to_square)
  354.  
  355.         self.clear_square(move.from_square)
  356.         self.clear_square(move.to_square)
  357.         self._set_piece_at(move.to_square, piece.piece_type, piece.color)
  358.  
  359.         self.turn = not self.turn
  360.  
  361.         self.move_stack.append((move, captured_piece))
  362.  
  363.     def pop(self):
  364.         if not self.move_stack:
  365.             return None
  366.  
  367.         move, captured_piece = self.move_stack.pop()
  368.  
  369.         piece = self.piece_at(move.to_square)
  370.        
  371.         self.clear_square(move.from_square)
  372.         self.clear_square(move.to_square)
  373.  
  374.         self._set_piece_at(move.from_square, piece.piece_type, piece.color)
  375.  
  376.         if captured_piece:
  377.             self._set_piece_at(move.to_square, captured_piece.piece_type, captured_piece.color)
  378.  
  379.         self.turn = not self.turn
  380.  
  381.         return move
  382.  
  383.     def is_check(self):
  384.         king_square = self.king(self.turn)
  385.         if king_square is None:
  386.             return False
  387.         is_check = self._is_attacked_by(not self.turn, king_square)
  388.   #      print(f"[DEBUG] Checking if position is check: FEN: {self.fen()}, King at {chess.SQUARE_NAMES[king_square]}, is_check: {is_check}")
  389.         return is_check
  390.  
  391.     def is_checkmate(self):
  392.         if not self.is_check():
  393.   #          print(f"[DEBUG] Position is not check, hence not checkmate: FEN: {self.fen()}")
  394.             return False
  395.         legal_moves = list(self.generate_legal_moves())
  396.  #       print(f"[DEBUG] Checking if position is checkmate: FEN: {self.fen()}, Legal moves: {legal_moves}")
  397.         return len(legal_moves) == 0
  398.  
  399.     def is_game_over(self):
  400.         return self.is_checkmate() or self.is_stalemate() or self.is_insufficient_material()
  401.  
  402.     def is_stalemate(self):
  403.         if self.is_check():
  404.             return False
  405.         legal_moves = list(self.generate_legal_moves())
  406.   #      print(f"[DEBUG] Checking if position is stalemate: FEN: {self.fen()}, Legal moves: {legal_moves}")
  407.         return len(legal_moves) == 0
  408.    
  409.     def is_insufficient_material(self):
  410.         return (self.pawns | self.rooks | self.queens | self.amazons_white | self.amazons_black |
  411.                 self.cyrils_white | self.cyrils_black | self.eves_white | self.eves_black) == 0 and (
  412.             chess.popcount(self.occupied) <= 3
  413.         )
  414.  
  415.     def generate_legal_moves(self, from_mask=chess.BB_ALL, to_mask=chess.BB_ALL):
  416.         for move in self.generate_pseudo_legal_moves(from_mask, to_mask):
  417.             if self.is_legal(move):
  418.       #          print(f"[DEBUG] Legal move: {move}")
  419.                 yield move
  420.        #     else:
  421.         #        print(f"[DEBUG] Illegal move: {move}")
  422.  
  423.     def debug_amazons(self):
  424.         pass
  425.       #  print(f"Bitboard bílých amazonek: {format(self.amazons_white, '064b')}")
  426.     #   print(f"Bitboard černých amazonek: {format(self.amazons_black, '064b')}")
  427.         for square in chess.SQUARES:
  428.             pass
  429.        #     if self.amazons_white & chess.BB_SQUARES[square]:
  430.        #         print(f"Bílá amazonka na {chess.SQUARE_NAMES[square]}")
  431.      #       if self.amazons_black & chess.BB_SQUARES[square]:
  432.        #         print(f"Černá amazonka na {chess.SQUARE_NAMES[square]}")
  433.  
  434.     def debug_cyrils(self):
  435.         pass
  436.        # print(f"Bitboard bílých Cyrils: {format(self.cyrils_white, '064b')}")
  437.        # print(f"Bitboard černých Cyrils: {format(self.cyrils_black, '064b')}")
  438.        # for square in chess.SQUARES:
  439.        #     if self.cyrils_white & chess.BB_SQUARES[square]:
  440.       #          print(f"Bílý Cyril na {chess.SQUARE_NAMES[square]}")
  441.      #       if self.cyrils_black & chess.BB_SQUARES[square]:
  442.     #            print(f"Černý Cyril na {chess.SQUARE_NAMES[square]}")
  443.  
  444.     def debug_eves(self):
  445.         pass
  446.     #    print(f"Bitboard bílých Eves: {format(self.eves_white, '064b')}")
  447.      #   print(f"Bitboard černých Eves: {format(self.eves_black, '064b')}")
  448.       #  for square in chess.SQUARES:
  449.       #      if self.eves_white & chess.BB_SQUARES[square]:
  450.           #      print(f"Bílá Eve na {chess.SQUARE_NAMES[square]}")
  451.        #     if self.eves_black & chess.BB_SQUARES[square]:
  452.        #         print(f"Černá Eve na {chess.SQUARE_NAMES[square]}")
  453.  
  454.     def piece_symbol(self, piece):
  455.         if piece is None:
  456.             return '.'
  457.         if piece.piece_type == AMAZON:
  458.             return 'A' if piece.color == chess.WHITE else 'a'
  459.         if piece.piece_type == CYRIL:
  460.             return 'C' if piece.color == chess.WHITE else 'c'
  461.         if piece.piece_type == EVE:
  462.             return 'E' if piece.color == chess.WHITE else 'e'
  463.         return piece.symbol()
  464.  
  465.     def piece_type_at(self, square):
  466.         if (self.amazons_white | self.amazons_black) & chess.BB_SQUARES[square]:
  467.             return AMAZON
  468.         if (self.cyrils_white | self.cyrils_black) & chess.BB_SQUARES[square]:
  469.             return CYRIL
  470.         if (self.eves_white | self.eves_black) & chess.BB_SQUARES[square]:
  471.             return EVE
  472.         return super().piece_type_at(square)
  473.  
  474.     def color_at(self, square):
  475.         if self.amazons_white & chess.BB_SQUARES[square]:
  476.             return chess.WHITE
  477.         if self.amazons_black & chess.BB_SQUARES[square]:
  478.             return chess.BLACK
  479.         if self.cyrils_white & chess.BB_SQUARES[square]:
  480.             return chess.WHITE
  481.         if self.cyrils_black & chess.BB_SQUARES[square]:
  482.             return chess.BLACK
  483.         if self.eves_white & chess.BB_SQUARES[square]:
  484.             return chess.WHITE
  485.         if self.eves_black & chess.BB_SQUARES[square]:
  486.             return chess.BLACK
  487.         return super().color_at(square)
  488.  
  489.     @property
  490.     def legal_moves(self):
  491.         return list(self.generate_legal_moves())
  492.  
  493.     def __str__(self):
  494.         builder = []
  495.         for square in chess.SQUARES_180:
  496.             piece = self.piece_at(square)
  497.             symbol = self.piece_symbol(piece) if piece else '.'
  498.             builder.append(symbol)
  499.             if chess.square_file(square) == 7:
  500.                 if square != chess.H1:
  501.                     builder.append('\n')
  502.         return ''.join(builder)
  503.  
  504.     def print_all_possible_moves(self):
  505.         pass
  506.     #    print(f"[DEBUG] All possible moves for FEN: {self.fen()}")
  507.   #      for move in self.generate_pseudo_legal_moves():
  508.    #         print(f"Move: {move}, Is legal: {self.is_legal(move)}")
  509.  
  510.  
  511. def format_time(seconds):
  512.     hours, remainder = divmod(seconds, 3600)
  513.     minutes, seconds = divmod(remainder, 60)
  514.     return f"{int(hours):02d}h {int(minutes):02d}m {int(seconds):02d}s"
  515.  
  516. def print_elapsed_time(stop_event, start_time):
  517.     while not stop_event.is_set():
  518.         elapsed_time = time.time() - start_time
  519.         print(f"\rUplynulý čas: {format_time(elapsed_time)}", end="", flush=True)
  520.         time.sleep(1)
  521.  
  522. def simplify_fen(fen):
  523.     return ' '.join(fen.split()[:4])
  524.  
  525.  
  526. def calculate_optimal_moves(start_fen: str) -> Dict[str, Tuple[int, str]]:
  527.     print("Funkce calculate_optimal_moves byla zavolána")
  528.     print(f"Počáteční FEN: {start_fen}")
  529.    
  530.     board = CustomBoard(start_fen)
  531.     POZ = {1: simplify_fen_string(start_fen)}
  532.     AR = {simplify_fen_string(start_fen): {'used': 0, 'to_end': None, 'depth': 0, 'type': 'normal'}}
  533.     N = 1
  534.     M = 0
  535.  
  536.     start_time = time.time()
  537.     current_depth = 0
  538.     positions_at_depth = {0: 0}
  539.     depth_start_time = start_time
  540.  
  541.     stop_event = threading.Event()
  542.     timer_thread = threading.Thread(target=print_elapsed_time, args=(stop_event, start_time))
  543.     timer_thread.start()
  544.  
  545.     try:
  546.         print("Začínám generovat pozice...")
  547.         print("Počáteční pozice:")
  548.         print_board(start_fen)
  549.        
  550.         depth_1_positions = []  # Seznam pro ukládání pozic v hloubce 1
  551.  
  552.         # Generování všech pozic
  553.         while M < N:
  554.             M += 1
  555.             current_fen = POZ[M]
  556.             board.set_custom_fen(current_fen)
  557.             simplified_current_fen = simplify_fen_string(current_fen)
  558.             current_depth = AR[simplified_current_fen]['depth']
  559.  
  560.             if current_depth not in positions_at_depth:
  561.                 positions_at_depth[current_depth] = 0
  562.                 if current_depth > 0:
  563.                     depth_time = time.time() - depth_start_time
  564.                     total_time = time.time() - start_time
  565.                     print(f"\nHloubka {current_depth - 1}: {positions_at_depth[current_depth - 1]} pozic, "
  566.                           f"Čas hloubky: {format_time(depth_time)} / Celkový čas: {format_time(total_time)}")
  567.                    
  568.                     if current_depth == 1:
  569.                         print("Všechny pozice v hloubce 1:")
  570.                         for pos in depth_1_positions:
  571.                             print_board(pos)
  572.                             print(pos)
  573.                             print()
  574.                
  575.                 depth_start_time = time.time()
  576.  
  577.             positions_at_depth[current_depth] += 1
  578.  
  579.             if current_depth == 1:
  580.                 depth_1_positions.append(current_fen)
  581.  
  582.             if AR[simplified_current_fen]['used'] == 0:
  583.                 AR[simplified_current_fen]['used'] = 1
  584.                 legal_moves = list(board.legal_moves)
  585.             for move in legal_moves:
  586.                 board.push(move)
  587.                 # Kontrola promoce
  588.                 if move.promotion == chess.QUEEN:
  589.                     # Aktualizujeme FEN, aby obsahoval dámu místo pěšce
  590.                     fen_parts = board.fen().split()
  591.                     board_rows = fen_parts[0].split('/')
  592.                     promotion_row = 0 if board.turn == chess.BLACK else 7
  593.                     promotion_file = chess.square_file(move.to_square)
  594.            
  595.                     # Určíme, zda promovaný pěšec je bílý nebo černý
  596.                     if board.turn == chess.BLACK:
  597.                         # Proměníme na malou 'q', protože tah černého pěšce končí na 1. řadě
  598.                         board_rows[promotion_row] = (board_rows[promotion_row][:promotion_file] +
  599.                                                      'q' +
  600.                                                      board_rows[promotion_row][promotion_file + 1:])
  601.                         # Odstraníme černého pěšce z původní pozice
  602.                         start_row = 7 - chess.square_rank(move.from_square)
  603.                         start_file = chess.square_file(move.from_square)
  604.                         board_rows[start_row] = (board_rows[start_row][:start_file] +
  605.                                                  board_rows[start_row][start_file + 1:])
  606.                     else:
  607.                         # Proměníme na velkou 'Q', protože tah bílého pěšce končí na 8. řadě
  608.                         board_rows[promotion_row] = (board_rows[promotion_row][:promotion_file] +
  609.                                                      'Q' +
  610.                                                      board_rows[promotion_row][promotion_file + 1:])
  611.                         # Odstraníme bílého pěšce z původní pozice
  612.                         start_row = 7 - chess.square_rank(move.from_square)
  613.                         start_file = chess.square_file(move.from_square)
  614.                         board_rows[start_row] = (board_rows[start_row][:start_file] +
  615.                                                  board_rows[start_row][start_file + 1:])
  616.            
  617.                     fen_parts[0] = '/'.join(board_rows)
  618.                     POZ2 = ' '.join(fen_parts)
  619.                 else:
  620.                     POZ2 = board.fen()
  621.                 simplified_POZ2 = simplify_fen_string(POZ2)
  622.                 if simplified_POZ2 not in AR:
  623.                     N += 1
  624.                     POZ[N] = simplified_POZ2
  625.                     AR[simplified_POZ2] = {'used': 0, 'to_end': None, 'depth': current_depth + 1, 'type': 'normal'}
  626.                 board.pop()
  627.    
  628.         # Tisk poslední hloubky
  629.         depth_time = time.time() - depth_start_time
  630.         total_time = time.time() - start_time
  631.         print(f"\nHloubka {current_depth}: {positions_at_depth[current_depth]} pozic, "
  632.               f"Čas hloubky: {format_time(depth_time)} / Celkový čas: {format_time(total_time)}")
  633.         print(f"Příklad pozice v hloubce {current_depth}:")
  634.         print_board(current_fen)
  635.  
  636.         print(f"Generování pozic dokončeno. Celkový počet pozic: {N}")
  637.  
  638.         # Počáteční ohodnocení
  639.         print("\nZačínám počáteční ohodnocení...")
  640.         F = 0
  641.         for i in range(1, N + 1):
  642.             current_fen = POZ[i]
  643.             board.set_custom_fen(current_fen)
  644.             simplified_current_fen = simplify_fen_string(current_fen)
  645.             if board.is_checkmate():
  646.                 AR[simplified_current_fen]['to_end'] = -1000 if board.turn == chess.WHITE else 1000
  647.                 AR[simplified_current_fen]['type'] = 'checkmate'
  648.                 F += 1
  649.             elif board.is_stalemate():
  650.                 AR[simplified_current_fen]['to_end'] = 0
  651.                 AR[simplified_current_fen]['type'] = 'stalemate'
  652.             elif board.is_insufficient_material():
  653.                 AR[simplified_current_fen]['to_end'] = 0
  654.                 AR[simplified_current_fen]['type'] = 'insufficient_material'
  655.             else:
  656.                 AR[simplified_current_fen]['type'] = 'check' if board.is_check() else 'normal'
  657.                 # 'to_end' není nastaveno pro pozice v šachu a normální pozice
  658.  
  659.         print(f"Počet pozic v matu je {F}")
  660.         print(f"Počet pozic v patu je {sum(1 for data in AR.values() if data['type'] == 'stalemate')}")
  661.         print(f"Počet pozic s nedostatečným materiálem je {sum(1 for data in AR.values() if data['type'] == 'insufficient_material')}")
  662.         print(f"Počet pozic v šachu je {sum(1 for data in AR.values() if data['type'] == 'check')}")
  663.         print(f"Počet normálních pozic je {sum(1 for data in AR.values() if data['type'] == 'normal')}")
  664.  
  665.         # Iterativní ohodnocení
  666.         print("\nZačínám iterativní ohodnocení...")
  667.         uroven = 0
  668.         while F > 0:
  669.             uroven += 1
  670.             level_start_time = time.time()
  671.             print(f"Výpočet v úrovni {uroven}")
  672.            
  673.             F = 0
  674.             current_level_positions = 0
  675.             for i in range(1, N + 1):
  676.                 current_fen = POZ[i]
  677.                 board.set_custom_fen(current_fen)
  678.                 simplified_current_fen = simplify_fen_string(current_fen)
  679.                 if AR[simplified_current_fen].get('to_end') is None:
  680.                     hod = -2000
  681.                     for move in board.legal_moves:
  682.                         board.push(move)
  683.                         POZ2 = board.fen()
  684.                         simplified_POZ2 = simplify_fen_string(POZ2)
  685.                         if simplified_POZ2 in AR:
  686.                             ar_entry = AR[simplified_POZ2]
  687.                             if ar_entry is not None and 'to_end' in ar_entry:
  688.                                 hod2 = -ar_entry['to_end'] if ar_entry['to_end'] is not None else 0
  689.                             else:
  690.                                 hod2 = 0
  691.                         else:
  692.                             hod2 = 0
  693.                         if hod2 > hod:
  694.                             hod = hod2
  695.                         board.pop()
  696.                     if hod == 1001 - uroven:
  697.                         AR[simplified_current_fen]['to_end'] = 1000 - uroven
  698.                         F += 1
  699.                         current_level_positions += 1
  700.                     elif hod == -1001 + uroven:
  701.                         AR[simplified_current_fen]['to_end'] = -1000 + uroven
  702.                         F += 1
  703.                         current_level_positions += 1
  704.             level_end_time = time.time()
  705.             total_elapsed_time = level_end_time - start_time
  706.             level_elapsed_time = level_end_time - level_start_time
  707.             print(f"Nalezeno {current_level_positions} pozic v úrovni {uroven}")
  708.             print(f"Čas úrovně: {format_time(level_elapsed_time)} / Celkový čas: {format_time(total_elapsed_time)}")
  709.  
  710.         print(f"Nalezeno {F} pozic celkem")
  711.        
  712.         print("\nVýpočet dokončen.")
  713.         return {fen: (data['to_end'], data['type']) for fen, data in AR.items() if data['to_end'] is not None}
  714.  
  715.     finally:
  716.         stop_event.set()
  717.         timer_thread.join()
  718.        
  719. # Pomocná funkce pro tisk šachovnice
  720. def print_board(fen):
  721.     board = CustomBoard(fen)
  722.     print(board)
  723.  
  724. # Najděte nejmenší kladnou hodnotu to_end ve všech FEN záznamech v AR
  725. def find_min_positive_value(AR):
  726.     min_positive_value = float('inf')
  727.     min_fen = None
  728.    
  729.     for fen, (value, type_pozice) in AR.items():
  730.         if value is not None and value > 0 and value < min_positive_value:
  731.             min_positive_value = value
  732.             min_fen = fen
  733.    
  734.     if min_positive_value == float('inf'):
  735.         print("Žádná kladná hodnota nebyla nalezena.")
  736.     else:
  737.         print(f"Nejmenší kladná hodnota: {min_positive_value}, FEN: {min_fen}")
  738.  
  739. # Hlavní provedení
  740. if __name__ == "__main__":
  741.     start_fen = "8/8/2P5/4K3/8/8/k7/8 w - - 0 1"
  742.    
  743.     AR = calculate_optimal_moves(start_fen)
  744.  
  745.     find_min_positive_value(AR)
  746.  
  747.     print("\nVýsledky:")
  748.     for fen, (hodnota, typ_pozice) in AR.items():
  749.         if hodnota == 984 or hodnota == -980:
  750.             print(f"FEN: {fen}")
  751.             print(f"Hodnota: {hodnota}")
  752.             print(f"Typ pozice: {typ_pozice}")
  753.            
  754.             temp_board = CustomBoard(fen)
  755.            
  756.             if temp_board.is_checkmate():
  757.                 print("Stav: Mat")
  758.             elif temp_board.is_stalemate():
  759.                 print("Stav: Pat")
  760.             elif temp_board.is_insufficient_material():
  761.                 print("Stav: Nedostatečný materiál")
  762.             elif temp_board.is_check():
  763.                 print("Stav: Šach")
  764.             else:
  765.                 print("Stav: Normální pozice")
  766.  
  767.             print_board(fen)
  768.            
  769.             print()
  770.  
  771.     # Tisk optimálních tahů
  772.     current_fen = start_fen
  773.     simplified_current_fen = simplify_fen_string(current_fen)
  774.     simplified_current_fen1 = simplify_fen_string(current_fen)
  775.     optimal_moves = []
  776.  
  777.     while True:
  778.         board = CustomBoard(current_fen)
  779.         if board.is_game_over():
  780.             break
  781.  
  782.         hod = -2000
  783.         best_fen = None
  784.         for move in board.legal_moves:
  785.             board.push(move)
  786.             POZ2 = board.fen()
  787.             simplified_POZ2 = simplify_fen_string(POZ2)
  788.             if simplified_POZ2 in AR:
  789.                 hod2 = -AR[simplified_POZ2][0] if AR[simplified_POZ2][0] is not None else 0
  790.                 if hod2 > hod:
  791.                     hod = hod2
  792.                     best_fen = simplified_POZ2
  793.             board.pop()
  794.  
  795.         if best_fen is None:
  796.             break
  797.  
  798.         optimal_moves.append(best_fen)
  799.         current_fen = best_fen
  800.         simplified_current_fen = simplify_fen_string(current_fen)
  801.  
  802.     print("\nOptimální tahy:")
  803.     for fen in reversed(optimal_moves):
  804.         print_board(fen)
  805.         print(AR[fen])
  806.         print(fen)
  807.         print("\n")
  808.  
  809.     print_board(simplified_current_fen1)
  810.     print(AR[simplified_current_fen1])
  811.     print(simplified_current_fen1)
  812.     print("\n")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement