Advertisement
max2201111

odladena posledni verze Amazonka, Cyryl a Eve (pro Petra) opraveny strelec

Jul 10th, 2024
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 20.86 KB | Science | 0 0
  1. import chess
  2. from typing import Iterator, Optional
  3. from chess import Move, BB_ALL, Bitboard, PieceType, Color
  4.  
  5. # Definice nových figur
  6. AMAZON = 7
  7. CYRIL = 8
  8. EVE = 9
  9.  
  10. # Rozšíření seznamu PIECE_SYMBOLS
  11. chess.PIECE_SYMBOLS.append('a')
  12. chess.PIECE_SYMBOLS.append('c')
  13. chess.PIECE_SYMBOLS.append('e')
  14.  
  15. class CustomBoard(chess.Board):
  16.     def __init__(self, fen=None):
  17.         self.amazons_white = chess.BB_EMPTY
  18.         self.amazons_black = chess.BB_EMPTY
  19.         self.cyrils_white = chess.BB_EMPTY
  20.         self.cyrils_black = chess.BB_EMPTY
  21.         self.eves_white = chess.BB_EMPTY
  22.         self.eves_black = chess.BB_EMPTY
  23.         super().__init__(None)
  24.         if fen:
  25.             self.set_custom_fen(fen)
  26.         print("Šachovnice inicializována")
  27.         self.debug_amazons()
  28.         self.debug_cyrils()
  29.         self.debug_eves()
  30.  
  31.     def set_custom_fen(self, fen):
  32.         parts = fen.split()
  33.         board_part = parts[0]
  34.  
  35.         self.clear()
  36.         self.amazons_white = chess.BB_EMPTY
  37.         self.amazons_black = chess.BB_EMPTY
  38.         self.cyrils_white = chess.BB_EMPTY
  39.         self.cyrils_black = chess.BB_EMPTY
  40.         self.eves_white = chess.BB_EMPTY
  41.         self.eves_black = chess.BB_EMPTY
  42.  
  43.         square = 56
  44.         for c in board_part:
  45.             if c == '/':
  46.                 square -= 16
  47.             elif c.isdigit():
  48.                 square += int(c)
  49.             else:
  50.                 color = chess.WHITE if c.isupper() else chess.BLACK
  51.                 if c.upper() == 'A':
  52.                     if color == chess.WHITE:
  53.                         self.amazons_white |= chess.BB_SQUARES[square]
  54.                     else:
  55.                         self.amazons_black |= chess.BB_SQUARES[square]
  56.                     piece_type = AMAZON
  57.                 elif c.upper() == 'C':
  58.                     if color == chess.WHITE:
  59.                         self.cyrils_white |= chess.BB_SQUARES[square]
  60.                     else:
  61.                         self.cyrils_black |= chess.BB_SQUARES[square]
  62.                     piece_type = CYRIL
  63.                 elif c.upper() == 'E':
  64.                     if color == chess.WHITE:
  65.                         self.eves_white |= chess.BB_SQUARES[square]
  66.                     else:
  67.                         self.eves_black |= chess.BB_SQUARES[square]
  68.                     piece_type = EVE
  69.                 else:
  70.                     piece_type = chess.PIECE_SYMBOLS.index(c.lower())
  71.                 self._set_piece_at(square, piece_type, color)
  72.                 square += 1
  73.  
  74.         self.turn = chess.WHITE if parts[1] == 'w' else chess.BLACK
  75.         self.castling_rights = chess.BB_EMPTY
  76.         if '-' not in parts[2]:
  77.             if 'K' in parts[2]: self.castling_rights |= chess.BB_H1
  78.             if 'Q' in parts[2]: self.castling_rights |= chess.BB_A1
  79.             if 'k' in parts[2]: self.castling_rights |= chess.BB_H8
  80.             if 'q' in parts[2]: self.castling_rights |= chess.BB_A8
  81.         self.ep_square = chess.parse_square(parts[3]) if parts[3] != '-' else None
  82.         self.halfmove_clock = int(parts[4])
  83.         self.fullmove_number = int(parts[5])
  84.  
  85.     def _set_piece_at(self, square: chess.Square, piece_type: PieceType, color: Color) -> None:
  86.         super()._set_piece_at(square, piece_type, color)
  87.         if piece_type == AMAZON:
  88.             if color == chess.WHITE:
  89.                 self.amazons_white |= chess.BB_SQUARES[square]
  90.             else:
  91.                 self.amazons_black |= chess.BB_SQUARES[square]
  92.         elif piece_type == CYRIL:
  93.             if color == chess.WHITE:
  94.                 self.cyrils_white |= chess.BB_SQUARES[square]
  95.             else:
  96.                 self.cyrils_black |= chess.BB_SQUARES[square]
  97.         elif piece_type == EVE:
  98.             if color == chess.WHITE:
  99.                 self.eves_white |= chess.BB_SQUARES[square]
  100.             else:
  101.                 self.eves_black |= chess.BB_SQUARES[square]
  102.         else:
  103.             self.amazons_white &= ~chess.BB_SQUARES[square]
  104.             self.amazons_black &= ~chess.BB_SQUARES[square]
  105.             self.cyrils_white &= ~chess.BB_SQUARES[square]
  106.             self.cyrils_black &= ~chess.BB_SQUARES[square]
  107.             self.eves_white &= ~chess.BB_SQUARES[square]
  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.             if self.piece_type_at(move.from_square) not in [AMAZON, CYRIL, EVE]:
  156.                 yield move
  157.  
  158.     def amazon_attacks(self, square):
  159.         return self.queen_attacks(square) | chess.BB_KNIGHT_ATTACKS[square]
  160.  
  161.     def cyril_attacks(self, square):
  162.         return self.rook_attacks(square) | chess.BB_KNIGHT_ATTACKS[square]
  163.  
  164.     def eve_attacks(self, square):
  165.         return self.bishop_attacks(square) | chess.BB_KNIGHT_ATTACKS[square]
  166.  
  167.     def queen_attacks(self, square):
  168.         return self.bishop_attacks(square) | self.rook_attacks(square)
  169.  
  170.     def bishop_attacks(self, square):
  171.         return chess.BB_DIAG_ATTACKS[square][self.occupied & chess.BB_DIAG_MASKS[square]]
  172.  
  173.     def rook_attacks(self, square):
  174.         return (chess.BB_RANK_ATTACKS[square][self.occupied & chess.BB_RANK_MASKS[square]] |
  175.                 chess.BB_FILE_ATTACKS[square][self.occupied & chess.BB_FILE_MASKS[square]])
  176.  
  177.     def is_pseudo_legal(self, move):
  178.         from_square = move.from_square
  179.         to_square = move.to_square
  180.         piece = self.piece_at(from_square)
  181.        
  182.         if not piece or piece.color != self.turn:
  183.             return False
  184.  
  185.         if self.occupied_co[self.turn] & chess.BB_SQUARES[to_square]:
  186.             return False
  187.  
  188.         if self.is_castling(move):
  189.             return True
  190.  
  191.         if piece.piece_type == AMAZON:
  192.             return bool(self.amazon_attacks(from_square) & chess.BB_SQUARES[to_square])
  193.         elif piece.piece_type == CYRIL:
  194.             return bool(self.cyril_attacks(from_square) & chess.BB_SQUARES[to_square])
  195.         elif piece.piece_type == EVE:
  196.             return bool(self.eve_attacks(from_square) & chess.BB_SQUARES[to_square])
  197.         else:
  198.             return super().is_pseudo_legal(move)
  199.  
  200.     def is_legal(self, move):
  201.         print(f"Kontrola legality tahu: {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._remove_piece_at(from_square)
  211.         self._set_piece_at(to_square, piece.piece_type, piece.color)
  212.  
  213.         king_square = to_square if piece.piece_type == chess.KING else self.king(self.turn)
  214.         is_check, attacker_square = self._is_attacked_by(not self.turn, king_square)
  215.  
  216.         self._remove_piece_at(to_square)
  217.         self._set_piece_at(from_square, piece.piece_type, piece.color)
  218.         if captured_piece:
  219.             self._set_piece_at(to_square, captured_piece.piece_type, captured_piece.color)
  220.  
  221.         if is_check:
  222.             attacking_piece = self.piece_at(attacker_square)
  223.             attacker_color = "bílá" if attacking_piece.color == chess.WHITE else "černá"
  224.             print(f"Tah {move} staví vlastního krále do šachu od figury {self.piece_symbol(attacking_piece)} ({attacker_color}) na {chess.SQUARE_NAMES[attacker_square]}")
  225.         return not is_check
  226.  
  227.     def _is_attacked_by(self, color, square):
  228.         print(f"Kontrola útoku na pole {chess.SQUARE_NAMES[square]} od barvy {'bílé' if color == chess.WHITE else 'černé'}")
  229.         attackers = self.attackers(color, square)
  230.         if attackers:
  231.             for attacker_square in chess.scan_forward(attackers):
  232.                 piece = self.piece_at(attacker_square)
  233.                 attacker_color = "bílá" if piece.color == chess.WHITE else "černá"
  234.                 print(f"Figura {self.piece_symbol(piece)} ({attacker_color}) na {chess.SQUARE_NAMES[attacker_square]} útočí na {chess.SQUARE_NAMES[square]}")
  235.                 return True, attacker_square
  236.         print(f"Žádný útok na pole {chess.SQUARE_NAMES[square]} nebyl nalezen")
  237.         return False, None
  238.  
  239.     def attackers(self, color, square):
  240.         attackers = chess.BB_EMPTY
  241.        
  242.         knights = self.knights & self.occupied_co[color]
  243.         attackers |= knights & chess.BB_KNIGHT_ATTACKS[square]
  244.        
  245.         king = self.kings & self.occupied_co[color]
  246.         attackers |= king & chess.BB_KING_ATTACKS[square]
  247.        
  248.         pawns = self.pawns & self.occupied_co[color]
  249.         if color == chess.WHITE:
  250.             attackers |= pawns & chess.BB_PAWN_ATTACKS[chess.BLACK][square]
  251.         else:
  252.             attackers |= pawns & chess.BB_PAWN_ATTACKS[chess.WHITE][square]
  253.        
  254.         queens = self.queens & self.occupied_co[color]
  255.         bishops = (self.bishops | queens) & self.occupied_co[color]
  256.         rooks = (self.rooks | queens) & self.occupied_co[color]
  257.        
  258.         attackers |= chess.BB_DIAG_ATTACKS[square][self.occupied & chess.BB_DIAG_MASKS[square]] & bishops
  259.         attackers |= (chess.BB_RANK_ATTACKS[square][self.occupied & chess.BB_RANK_MASKS[square]] |
  260.                       chess.BB_FILE_ATTACKS[square][self.occupied & chess.BB_FILE_MASKS[square]]) & rooks
  261.        
  262.         # Kontrola útoků amazonek, cyrilů a eves
  263.         amazons = self.amazons_white if color == chess.WHITE else self.amazons_black
  264.         for amazon_square in chess.scan_forward(amazons):
  265.             if self.amazon_attacks(amazon_square) & chess.BB_SQUARES[square]:
  266.                 attackers |= chess.BB_SQUARES[amazon_square]
  267.  
  268.         cyrils = self.cyrils_white if color == chess.WHITE else self.cyrils_black
  269.         for cyril_square in chess.scan_forward(cyrils):
  270.             if self.cyril_attacks(cyril_square) & chess.BB_SQUARES[square]:
  271.                 attackers |= chess.BB_SQUARES[cyril_square]
  272.  
  273.         eves = self.eves_white if color == chess.WHITE else self.eves_black
  274.         for eve_square in chess.scan_forward(eves):
  275.             if self.eve_attacks(eve_square) & chess.BB_SQUARES[square]:
  276.                 attackers |= chess.BB_SQUARES[eve_square]
  277.  
  278.         return attackers
  279.  
  280.     def push(self, move):
  281.         if not self.is_legal(move):
  282.             raise ValueError(f"Move {move} is not legal in position {self.fen()}")
  283.  
  284.         piece = self.piece_at(move.from_square)
  285.         captured_piece = self.piece_at(move.to_square)
  286.  
  287.         self._remove_piece_at(move.from_square)
  288.         self._set_piece_at(move.to_square, piece.piece_type, piece.color)
  289.  
  290.         if piece.piece_type == AMAZON:
  291.             if piece.color == chess.WHITE:
  292.                 self.amazons_white &= ~chess.BB_SQUARES[move.from_square]
  293.                 self.amazons_white |= chess.BB_SQUARES[move.to_square]
  294.             else:
  295.                 self.amazons_black &= ~chess.BB_SQUARES[move.from_square]
  296.                 self.amazons_black |= chess.BB_SQUARES[move.to_square]
  297.         elif piece.piece_type == CYRIL:
  298.             if piece.color == chess.WHITE:
  299.                 self.cyrils_white &= ~chess.BB_SQUARES[move.from_square]
  300.                 self.cyrils_white |= chess.BB_SQUARES[move.to_square]
  301.             else:
  302.                 self.cyrils_black &= ~chess.BB_SQUARES[move.from_square]
  303.                 self.cyrils_black |= chess.BB_SQUARES[move.to_square]
  304.         elif piece.piece_type == EVE:
  305.             if piece.color == chess.WHITE:
  306.                 self.eves_white &= ~chess.BB_SQUARES[move.from_square]
  307.                 self.eves_white |= chess.BB_SQUARES[move.to_square]
  308.             else:
  309.                 self.eves_black &= ~chess.BB_SQUARES[move.from_square]
  310.                 self.eves_black |= chess.BB_SQUARES[move.to_square]
  311.  
  312.         self.turn = not self.turn
  313.         self.fullmove_number += 1 if self.turn == chess.WHITE else 0
  314.         self.halfmove_clock += 1
  315.  
  316.         if captured_piece or piece.piece_type == chess.PAWN:
  317.             self.halfmove_clock = 0
  318.  
  319.         self.move_stack.append(move)
  320.  
  321.     def pop(self):
  322.         if not self.move_stack:
  323.             return None
  324.  
  325.         move = self.move_stack.pop()
  326.  
  327.         piece = self.piece_at(move.to_square)
  328.         self._remove_piece_at(move.to_square)
  329.         self._set_piece_at(move.from_square, piece.piece_type, piece.color)
  330.  
  331.         if piece.piece_type == AMAZON:
  332.             if piece.color == chess.WHITE:
  333.                 self.amazons_white &= ~chess.BB_SQUARES[move.to_square]
  334.                 self.amazons_white |= chess.BB_SQUARES[move.from_square]
  335.             else:
  336.                 self.amazons_black &= ~chess.BB_SQUARES[move.to_square]
  337.                 self.amazons_black |= chess.BB_SQUARES[move.from_square]
  338.         elif piece.piece_type == CYRIL:
  339.             if piece.color == chess.WHITE:
  340.                 self.cyrils_white &= ~chess.BB_SQUARES[move.to_square]
  341.                 self.cyrils_white |= chess.BB_SQUARES[move.from_square]
  342.             else:
  343.                 self.cyrils_black &= ~chess.BB_SQUARES[move.to_square]
  344.                 self.cyrils_black |= chess.BB_SQUARES[move.from_square]
  345.         elif piece.piece_type == EVE:
  346.             if piece.color == chess.WHITE:
  347.                 self.eves_white &= ~chess.BB_SQUARES[move.to_square]
  348.                 self.eves_white |= chess.BB_SQUARES[move.from_square]
  349.             else:
  350.                 self.eves_black &= ~chess.BB_SQUARES[move.to_square]
  351.                 self.eves_black |= chess.BB_SQUARES[move.from_square]
  352.  
  353.         captured_piece = self.piece_at(move.to_square)
  354.         if captured_piece:
  355.             self._set_piece_at(move.to_square, captured_piece.piece_type, captured_piece.color)
  356.  
  357.         self.turn = not self.turn
  358.         self.fullmove_number -= 1 if self.turn == chess.BLACK else 0
  359.  
  360.         return move
  361.  
  362.     def is_check(self):
  363.         king_square = self.king(self.turn)
  364.         if king_square is None:
  365.             return False
  366.         return self._is_attacked_by(not self.turn, king_square)[0]
  367.  
  368.     def debug_amazons(self):
  369.         print(f"Bitboard bílých amazonek: {format(self.amazons_white, '064b')}")
  370.         print(f"Bitboard černých amazonek: {format(self.amazons_black, '064b')}")
  371.         for square in chess.SQUARES:
  372.             if self.amazons_white & chess.BB_SQUARES[square]:
  373.                 print(f"Bílá amazonka na {chess.SQUARE_NAMES[square]}")
  374.             if self.amazons_black & chess.BB_SQUARES[square]:
  375.                 print(f"Černá amazonka na {chess.SQUARE_NAMES[square]}")
  376.  
  377.     def debug_cyrils(self):
  378.         print(f"Bitboard bílých Cyrils: {format(self.cyrils_white, '064b')}")
  379.         print(f"Bitboard černých Cyrils: {format(self.cyrils_black, '064b')}")
  380.         for square in chess.SQUARES:
  381.             if self.cyrils_white & chess.BB_SQUARES[square]:
  382.                 print(f"Bílý Cyril na {chess.SQUARE_NAMES[square]}")
  383.             if self.cyrils_black & chess.BB_SQUARES[square]:
  384.                 print(f"Černý Cyril na {chess.SQUARE_NAMES[square]}")
  385.  
  386.     def debug_eves(self):
  387.         print(f"Bitboard bílých Eves: {format(self.eves_white, '064b')}")
  388.         print(f"Bitboard černých Eves: {format(self.eves_black, '064b')}")
  389.         for square in chess.SQUARES:
  390.             if self.eves_white & chess.BB_SQUARES[square]:
  391.                 print(f"Bílá Eve na {chess.SQUARE_NAMES[square]}")
  392.             if self.eves_black & chess.BB_SQUARES[square]:
  393.                 print(f"Černá Eve na {chess.SQUARE_NAMES[square]}")
  394.  
  395.     def piece_symbol(self, piece):
  396.         if piece is None:
  397.             return '.'
  398.         if piece.piece_type == AMAZON:
  399.             return 'A' if piece.color == chess.WHITE else 'a'
  400.         if piece.piece_type == CYRIL:
  401.             return 'C' if piece.color == chess.WHITE else 'c'
  402.         if piece.piece_type == EVE:
  403.             return 'E' if piece.color == chess.WHITE else 'e'
  404.         return piece.symbol()
  405.  
  406.     def piece_type_at(self, square):
  407.         if (self.amazons_white | self.amazons_black) & chess.BB_SQUARES[square]:
  408.             return AMAZON
  409.         if (self.cyrils_white | self.cyrils_black) & chess.BB_SQUARES[square]:
  410.             return CYRIL
  411.         if (self.eves_white | self.eves_black) & chess.BB_SQUARES[square]:
  412.             return EVE
  413.         return super().piece_type_at(square)
  414.  
  415.     def color_at(self, square):
  416.         if self.amazons_white & chess.BB_SQUARES[square]:
  417.             return chess.WHITE
  418.         if self.amazons_black & chess.BB_SQUARES[square]:
  419.             return chess.BLACK
  420.         if self.cyrils_white & chess.BB_SQUARES[square]:
  421.             return chess.WHITE
  422.         if self.cyrils_black & chess.BB_SQUARES[square]:
  423.             return chess.BLACK
  424.         if self.eves_white & chess.BB_SQUARES[square]:
  425.             return chess.WHITE
  426.         if self.eves_black & chess.BB_SQUARES[square]:
  427.             return chess.BLACK
  428.         return super().color_at(square)
  429.  
  430.     @property
  431.     def legal_moves(self):
  432.         return [move for move in self.generate_pseudo_legal_moves() if self.is_legal(move)]
  433.  
  434.     def __str__(self):
  435.         builder = []
  436.         for square in chess.SQUARES_180:
  437.             piece = self.piece_at(square)
  438.             symbol = self.piece_symbol(piece) if piece else '.'
  439.             builder.append(symbol)
  440.             if chess.square_file(square) == 7:
  441.                 if square != chess.H1:
  442.                     builder.append('\n')
  443.         return ''.join(builder)
  444.  
  445. if __name__ == "__main__":
  446.     start_fen = "a7/3k4/A7/8/1B6/8/A7/6K1 b - - 0 1"
  447.     start_fen = "8/3k4/8/8/1E6/8/A7/6K1 w - - 0 1"
  448.  
  449.     print(f"Vytváření šachovnice s FEN: {start_fen}")
  450.     board = CustomBoard(start_fen)
  451.  
  452.     print("Současná pozice:")
  453.     print(board)
  454.  
  455.     print("Generování legálních tahů pro počáteční pozici...")
  456.     legal_moves = list(board.legal_moves)
  457.     print(f"Počet legálních tahů: {len(legal_moves)}")
  458.  
  459.     print("Legální tahy:")
  460.     for move in legal_moves:
  461.         from_square = chess.SQUARE_NAMES[move.from_square]
  462.         to_square = chess.SQUARE_NAMES[move.to_square]
  463.         piece = board.piece_at(move.from_square)
  464.         print(f"{board.piece_symbol(piece)}: {from_square}-{to_square}")
  465.  
  466.     # Test tahu bílého krále z G1 na H1
  467.     test_move = chess.Move.from_uci("g1h1")
  468.     is_legal = board.is_legal(test_move)
  469.     print(f"Je tah g1h1 legální? {'Ano' if is_legal else 'Ne'}")
  470.  
  471.     for square in [chess.H1, chess.G2]:
  472.         attackers = board.attackers(chess.BLACK, square)
  473.         if attackers:
  474.             for attacker_square in chess.scan_forward(attackers):
  475.                 piece = board.piece_at(attacker_square)
  476.                 attacker_color = "bílá" if piece.color == chess.WHITE else "černá"
  477.                 print(f"Pole {chess.SQUARE_NAMES[square]} je napadeno figurou {board.piece_symbol(piece)} ({attacker_color}) z pole {chess.SQUARE_NAMES[attacker_square]}")
  478.         else:
  479.             print(f"Pole {chess.SQUARE_NAMES[square]} není napadeno žádnou černou figurou")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement