Advertisement
max2201111

ultimate very good amazonka 5 exact

Jul 1st, 2024
538
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.54 KB | Science | 0 0
  1. from typing import List, Iterable, Tuple
  2. import re
  3.  
  4. # Definice bitboardu a dalších typů
  5. Bitboard = int
  6. Square = int
  7.  
  8. # Konstanty
  9. BB_EMPTY = 0
  10. BB_ALL = (1 << 64) - 1
  11. SQUARES = list(range(64))
  12. BB_SQUARES = [1 << sq for sq in SQUARES]
  13.  
  14. # Pomocné funkce
  15. def square_distance(sq1: Square, sq2: Square) -> int:
  16.     file1, rank1 = sq1 % 8, sq1 // 8
  17.     file2, rank2 = sq2 % 8, sq2 // 8
  18.     return max(abs(file1 - file2), abs(rank1 - rank2))
  19.  
  20. # Funkce pro generování útoků
  21. def _sliding_attacks(square: Square, occupied: Bitboard, deltas: Iterable[int]) -> Bitboard:
  22.     attacks = BB_EMPTY
  23.  
  24.     for delta in deltas:
  25.         sq = square
  26.  
  27.         while True:
  28.             sq += delta
  29.             if not (0 <= sq < 64) or square_distance(sq, sq - delta) > 2:
  30.                 break
  31.  
  32.             attacks |= BB_SQUARES[sq]
  33.  
  34.             if occupied & BB_SQUARES[sq]:
  35.                 break
  36.  
  37.     return attacks
  38.  
  39. def _step_attacks(square: Square, deltas: Iterable[int]) -> Bitboard:
  40.     attacks = BB_EMPTY
  41.     for delta in deltas:
  42.         sq = square + delta
  43.         if 0 <= sq < 64 and square_distance(sq, square) <= 2:
  44.             attacks |= BB_SQUARES[sq]
  45.     return attacks
  46.  
  47. # Funkce pro generování tabulek útoků
  48. def _attack_table(deltas: List[int]) -> Tuple[List[Bitboard], List[Bitboard]]:
  49.     masks = []
  50.     attacks = []
  51.  
  52.     for sq in SQUARES:
  53.         mask = 0
  54.         attack = _sliding_attacks(sq, BB_EMPTY, deltas)
  55.         for i in range(64):
  56.             if attack & BB_SQUARES[i]:
  57.                 mask |= BB_SQUARES[i]
  58.         masks.append(mask)
  59.         attacks.append(attack)
  60.  
  61.     return masks, attacks
  62.  
  63. # Útoky pro KNIGHTa, BISHOPa, ROOKa, QUEENa a KINGa
  64. KNIGHT_DELTAS = [-17, -15, -10, -6, 6, 10, 15, 17]
  65. BISHOP_DELTAS = [-9, -7, 7, 9]
  66. ROOK_DELTAS = [-8, -1, 1, 8]
  67. QUEEN_DELTAS = BISHOP_DELTAS + ROOK_DELTAS
  68. KING_DELTAS = [-9, -8, -7, -1, 1, 7, 8, 9]
  69.  
  70. # Získání masky a útoků pro KNIGHTa, BISHOPa, ROOKa, QUEENa a KINGa
  71. BB_KNIGHT_MASKS, BB_KNIGHT_ATTACKS = _attack_table(KNIGHT_DELTAS)
  72. BB_BISHOP_MASKS, BB_BISHOP_ATTACKS = _attack_table(BISHOP_DELTAS)
  73. BB_ROOK_MASKS, BB_ROOK_ATTACKS = _attack_table(ROOK_DELTAS)
  74. BB_QUEEN_MASKS, BB_QUEEN_ATTACKS = _attack_table(QUEEN_DELTAS)
  75. BB_KING_MASKS, BB_KING_ATTACKS = _attack_table(KING_DELTAS)
  76.  
  77. # Kombinované útoky pro figurky AMAZON, CYRIL a EVA
  78. BB_AMAZON_ATTACKS = [knight | bishop for knight, bishop in zip(BB_KNIGHT_ATTACKS, BB_BISHOP_ATTACKS)]
  79. BB_CYRIL_ATTACKS = [knight | rook for knight, rook in zip(BB_KNIGHT_ATTACKS, BB_ROOK_ATTACKS)]
  80. BB_EVA_ATTACKS = [knight | queen for knight, queen in zip(BB_KNIGHT_ATTACKS, BB_QUEEN_ATTACKS)]
  81.  
  82. # Funkce pro tisk šachovnice v ASCII formátu s FEN stringem
  83. def print_board_with_fen(fen: str) -> None:
  84.     parts = fen.split()
  85.     board_part = parts[0]
  86.     rows = board_part.split('/')
  87.     for row in rows:
  88.         row_str = ''
  89.         for char in row:
  90.             if char.isdigit():
  91.                 row_str += '.' * int(char)
  92.             else:
  93.                 row_str += char
  94.         print(row_str)
  95.  
  96. # Funkce pro parsování FEN stringu a získání pozic figurek
  97. def parse_fen(fen: str) -> Tuple[List[Square], List[Square], List[Square], List[Square], List[Square], List[Square], List[Square], List[Square], List[Square], List[Square], List[Square], List[Square], str, Bitboard, Bitboard]:
  98.     parts = fen.split()
  99.     board_part = parts[0]
  100.     turn = parts[1]
  101.     rows = board_part.split('/')
  102.     white_amazons = []
  103.     black_amazons = []
  104.     white_cyrils = []
  105.     black_cyrils = []
  106.     white_evas = []
  107.     black_evas = []
  108.     white_kings = []
  109.     black_kings = []
  110.     white_queens = []
  111.     black_queens = []
  112.     white_bishops = []
  113.     black_bishops = []
  114.     white_pieces = BB_EMPTY
  115.     black_pieces = BB_EMPTY
  116.     for rank in range(8):
  117.         row = rows[rank]
  118.         file = 0
  119.         for char in row:
  120.             if char.isdigit():
  121.                 file += int(char)
  122.             elif char == 'A':
  123.                 white_amazons.append((7 - rank) * 8 + file)
  124.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  125.                 file += 1
  126.             elif char == 'a':
  127.                 black_amazons.append((7 - rank) * 8 + file)
  128.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  129.                 file += 1
  130.             elif char == 'C':
  131.                 white_cyrils.append((7 - rank) * 8 + file)
  132.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  133.                 file += 1
  134.             elif char == 'c':
  135.                 black_cyrils.append((7 - rank) * 8 + file)
  136.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  137.                 file += 1
  138.             elif char == 'E':
  139.                 white_evas.append((7 - rank) * 8 + file)
  140.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  141.                 file += 1
  142.             elif char == 'e':
  143.                 black_evas.append((7 - rank) * 8 + file)
  144.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  145.                 file += 1
  146.             elif char == 'K':
  147.                 white_kings.append((7 - rank) * 8 + file)
  148.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  149.                 file += 1
  150.             elif char == 'k':
  151.                 black_kings.append((7 - rank) * 8 + file)
  152.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  153.                 file += 1
  154.             elif char == 'Q':
  155.                 white_queens.append((7 - rank) * 8 + file)
  156.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  157.                 file += 1
  158.             elif char == 'q':
  159.                 black_queens.append((7 - rank) * 8 + file)
  160.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  161.                 file += 1
  162.             elif char == 'B':
  163.                 white_bishops.append((7 - rank) * 8 + file)
  164.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  165.                 file += 1
  166.             elif char == 'b':
  167.                 black_bishops.append((7 - rank) * 8 + file)
  168.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  169.                 file += 1
  170.             elif char.isupper():
  171.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  172.                 file += 1
  173.             elif char.islower():
  174.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  175.                 file += 1
  176.     return white_amazons, black_amazons, white_cyrils, black_cyrils, white_evas, black_evas, white_kings, black_kings, white_queens, black_queens, white_bishops, black_bishops, turn, white_pieces, black_pieces
  177.  
  178. # Funkce pro generování možných tahů figurek
  179. def generate_moves(piece_squares: List[Square], white_pieces: Bitboard, black_pieces: Bitboard, turn: str, piece_type: str) -> List[Tuple[Square, Square, str]]:
  180.     moves = []
  181.     occupied = white_pieces | black_pieces
  182.     if piece_type == 'A':
  183.         attacks = BB_AMAZON_ATTACKS
  184.         move_types = {"Bishop": BISHOP_DELTAS, "Knight": KNIGHT_DELTAS}
  185.     elif piece_type == 'C':
  186.         attacks = BB_CYRIL_ATTACKS
  187.         move_types = {"Rook": ROOK_DELTAS, "Knight": KNIGHT_DELTAS}
  188.     elif piece_type == 'E':
  189.         attacks = BB_EVA_ATTACKS
  190.         move_types = {"Queen": QUEEN_DELTAS, "Knight": KNIGHT_DELTAS}
  191.     elif piece_type == 'K':
  192.         attacks = BB_KING_ATTACKS
  193.         move_types = {"King": KING_DELTAS}
  194.     elif piece_type == 'Q':
  195.         attacks = BB_QUEEN_ATTACKS
  196.         move_types = {"Queen": QUEEN_DELTAS}
  197.     elif piece_type == 'B':
  198.         attacks = BB_BISHOP_ATTACKS
  199.         move_types = {"Bishop": BISHOP_DELTAS}
  200.  
  201.     for square in piece_squares:
  202.         piece_attacks = attacks[square]
  203.         for move in SQUARES:
  204.             if piece_attacks & BB_SQUARES[move]:
  205.                 if turn == 'w' and not (occupied & BB_SQUARES[move] and white_pieces & BB_SQUARES[move]):
  206.                     for move_type, deltas in move_types.items():
  207.                         if _sliding_attacks(square, occupied, deltas) & BB_SQUARES[move]:
  208.                             moves.append((square, move, move_type))
  209.                             break
  210.                 elif turn == 'b' and not (occupied & BB_SQUARES[move] and black_pieces & BB_SQUARES[move]):
  211.                     for move_type, deltas in move_types.items():
  212.                         if _sliding_attacks(square, occupied, deltas) & BB_SQUARES[move]:
  213.                             moves.append((square, move, move_type))
  214.                             break
  215.     return moves
  216.  
  217. # Funkce pro generování SAN notace
  218. def generate_san_notation(square: Square, move_square: Square, is_white: bool, piece_type: str, move_type: str) -> str:
  219.     file_from = chr((square % 8) + ord('a'))
  220.     rank_from = str(8 - (square // 8))
  221.     file_to = chr((move_square % 8) + ord('a'))
  222.     rank_to = str(8 - (move_square // 8))
  223.     piece = piece_type if is_white else piece_type.lower()
  224.     move_prefix = move_type[0].lower() if move_type in ["Knight", "Bishop", "Rook"] else ""
  225.     return f"{piece}{file_from}{rank_from}-{move_prefix}{file_to}{rank_to}, {piece}"
  226.  
  227. # Funkce pro aktualizaci FEN stringu s novou pozicí figurky
  228. def update_fen_with_piece(fen: str, square: Square, move_square: Square, is_white: bool, piece_type: str) -> str:
  229.     parts = fen.split()
  230.     board_part = parts[0]
  231.     rows = board_part.split('/')
  232.     new_rows = []
  233.  
  234.     for rank in range(8):
  235.         row = rows[rank]
  236.         new_row = ''
  237.         file = 0
  238.         for char in row:
  239.             if char.isdigit():
  240.                 empty_squares = int(char)
  241.                 for _ in range(empty_squares):
  242.                     new_row += '1'
  243.                     file += 1
  244.             else:
  245.                 if (7 - rank) * 8 + file == square:
  246.                     new_row += '1'
  247.                 else:
  248.                     new_row += char
  249.                 file += 1
  250.         while len(new_row) < 8:
  251.             new_row += '1'
  252.         new_rows.append(new_row)
  253.  
  254.     new_board_part = '/'.join(new_rows)
  255.     new_fen = f"{new_board_part} w - - 0 1"
  256.     new_fen = re.sub(r'1{8}', '8', new_fen)
  257.     new_fen = re.sub(r'1{7}', '7', new_fen)
  258.     new_fen = re.sub(r'1{6}', '6', new_fen)
  259.     new_fen = re.sub(r'1{5}', '5', new_fen)
  260.     new_fen = re.sub(r'1{4}', '4', new_fen)
  261.     new_fen = re.sub(r'1{3}', '3', new_fen)
  262.     new_fen = re.sub(r'1{2}', '2', new_fen)
  263.     new_rows = new_fen.split('/')
  264.  
  265.     # Update the piece position in the new FEN
  266.     for rank in range(8):
  267.         new_row = ''
  268.         file = 0
  269.         for char in new_rows[rank]:
  270.             if char.isdigit():
  271.                 empty_squares = int(char)
  272.                 for _ in range(empty_squares):
  273.                     if (7 - rank) * 8 + file == move_square:
  274.                         piece = piece_type if is_white else piece_type.lower()
  275.                         new_row += piece
  276.                     else:
  277.                         new_row += '1'
  278.                     file += 1
  279.             else:
  280.                 if (7 - rank) * 8 + file == move_square:
  281.                     piece = piece_type if is_white else piece_type.lower()
  282.                     new_row += piece
  283.                 else:
  284.                     new_row += char
  285.                 file += 1
  286.         while len(new_row) < 8:
  287.             new_row += '1'
  288.         new_rows[rank] = new_row
  289.  
  290.     new_fen = '/'.join(new_rows)
  291.     new_fen = re.sub(r'1{8}', '8', new_fen)
  292.     new_fen = re.sub(r'1{7}', '7', new_fen)
  293.     new_fen = re.sub(r'1{6}', '6', new_fen)
  294.     new_fen = re.sub(r'1{5}', '5', new_fen)
  295.     new_fen = re.sub(r'1{4}', '4', new_fen)
  296.     new_fen = re.sub(r'1{3}', '3', new_fen)
  297.     new_fen = re.sub(r'1{2}', '2', new_fen)
  298.  
  299.     return new_fen
  300.  
  301. # Parsování FEN stringu
  302. fen_string = "1a6/3k4/8/8/4b3/8/8/6K1 b - - 0 1"
  303. white_amazons, black_amazons, white_cyrils, black_cyrils, white_evas, black_evas, white_kings, black_kings, white_queens, black_queens, white_bishops, black_bishops, turn, white_pieces, black_pieces = parse_fen(fen_string)
  304.  
  305. # Výpis šachovnic pro všechny možné tahy figurek z výchozí pozice
  306. print("Inicialní šachovnice:")
  307. print_board_with_fen(fen_string)
  308. print()
  309.  
  310. piece_types = ['A', 'C', 'E', 'K', 'Q', 'B']
  311. all_moves = []
  312.  
  313. for piece_type in piece_types:
  314.     if piece_type == 'A':
  315.         amazons = white_amazons if turn == 'w' else black_amazons
  316.         moves = generate_moves(amazons, white_pieces, black_pieces, turn, piece_type)
  317.     elif piece_type == 'C':
  318.         cyrils = white_cyrils if turn == 'w' else black_cyrils
  319.         moves = generate_moves(cyrils, white_pieces, black_pieces, turn, piece_type)
  320.     elif piece_type == 'E':
  321.         evas = white_evas if turn == 'w' else black_evas
  322.         moves = generate_moves(evas, white_pieces, black_pieces, turn, piece_type)
  323.     elif piece_type == 'K':
  324.         kings = white_kings if turn == 'w' else black_kings
  325.         moves = generate_moves(kings, white_pieces, black_pieces, turn, piece_type)
  326.     elif piece_type == 'Q':
  327.         queens = white_queens if turn == 'w' else black_queens
  328.         moves = generate_moves(queens, white_pieces, black_pieces, turn, piece_type)
  329.     elif piece_type == 'B':
  330.         bishops = white_bishops if turn == 'w' else black_bishops
  331.         moves = generate_moves(bishops, white_pieces, black_pieces, turn, piece_type)
  332.    
  333.     all_moves.extend([(piece_type, move) for move in moves])
  334.  
  335. for piece_type, (square, move, move_type) in all_moves:
  336.     new_fen = update_fen_with_piece(fen_string, square, move, turn == 'w', piece_type)
  337.     san_notation = generate_san_notation(square, move, turn == 'w', piece_type, move_type)
  338.     print(f"SAN: {san_notation} ({move_type})")
  339.     print(f"FEN: {new_fen}")
  340.     print_board_with_fen(new_fen)
  341.     print()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement