Advertisement
max2201111

ultimate very good amazonka 4 exact

Jul 1st, 2024
497
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.71 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], 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_pieces = BB_EMPTY
  113.     black_pieces = BB_EMPTY
  114.     for rank in range(8):
  115.         row = rows[rank]
  116.         file = 0
  117.         for char in row:
  118.             if char.isdigit():
  119.                 file += int(char)
  120.             elif char == 'A':
  121.                 white_amazons.append((7 - rank) * 8 + file)
  122.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  123.                 file += 1
  124.             elif char == 'a':
  125.                 black_amazons.append((7 - rank) * 8 + file)
  126.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  127.                 file += 1
  128.             elif char == 'C':
  129.                 white_cyrils.append((7 - rank) * 8 + file)
  130.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  131.                 file += 1
  132.             elif char == 'c':
  133.                 black_cyrils.append((7 - rank) * 8 + file)
  134.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  135.                 file += 1
  136.             elif char == 'E':
  137.                 white_evas.append((7 - rank) * 8 + file)
  138.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  139.                 file += 1
  140.             elif char == 'e':
  141.                 black_evas.append((7 - rank) * 8 + file)
  142.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  143.                 file += 1
  144.             elif char == 'K':
  145.                 white_kings.append((7 - rank) * 8 + file)
  146.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  147.                 file += 1
  148.             elif char == 'k':
  149.                 black_kings.append((7 - rank) * 8 + file)
  150.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  151.                 file += 1
  152.             elif char == 'Q':
  153.                 white_queens.append((7 - rank) * 8 + file)
  154.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  155.                 file += 1
  156.             elif char == 'q':
  157.                 black_queens.append((7 - rank) * 8 + file)
  158.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  159.                 file += 1
  160.             elif char.isupper():
  161.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  162.                 file += 1
  163.             elif char.islower():
  164.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  165.                 file += 1
  166.     return white_amazons, black_amazons, white_cyrils, black_cyrils, white_evas, black_evas, white_kings, black_kings, white_queens, black_queens, turn, white_pieces, black_pieces
  167.  
  168. # Funkce pro generování možných tahů figurek
  169. def generate_moves(piece_squares: List[Square], white_pieces: Bitboard, black_pieces: Bitboard, turn: str, piece_type: str) -> List[Tuple[Square, Square, str]]:
  170.     moves = []
  171.     occupied = white_pieces | black_pieces
  172.     if piece_type == 'A':
  173.         attacks = BB_AMAZON_ATTACKS
  174.         move_types = {"Bishop": BISHOP_DELTAS, "Knight": KNIGHT_DELTAS}
  175.     elif piece_type == 'C':
  176.         attacks = BB_CYRIL_ATTACKS
  177.         move_types = {"Rook": ROOK_DELTAS, "Knight": KNIGHT_DELTAS}
  178.     elif piece_type == 'E':
  179.         attacks = BB_EVA_ATTACKS
  180.         move_types = {"Queen": QUEEN_DELTAS, "Knight": KNIGHT_DELTAS}
  181.     elif piece_type == 'K':
  182.         attacks = BB_KING_ATTACKS
  183.         move_types = {"King": KING_DELTAS}
  184.     elif piece_type == 'Q':
  185.         attacks = BB_QUEEN_ATTACKS
  186.         move_types = {"Queen": QUEEN_DELTAS}
  187.  
  188.     for square in piece_squares:
  189.         piece_attacks = attacks[square]
  190.         for move in SQUARES:
  191.             if piece_attacks & BB_SQUARES[move]:
  192.                 if turn == 'w' and not (occupied & BB_SQUARES[move] and white_pieces & BB_SQUARES[move]):
  193.                     for move_type, deltas in move_types.items():
  194.                         if _step_attacks(square, deltas) & BB_SQUARES[move]:
  195.                             moves.append((square, move, move_type))
  196.                             break
  197.                 elif turn == 'b' and not (occupied & BB_SQUARES[move] and black_pieces & BB_SQUARES[move]):
  198.                     for move_type, deltas in move_types.items():
  199.                         if _step_attacks(square, deltas) & BB_SQUARES[move]:
  200.                             moves.append((square, move, move_type))
  201.                             break
  202.     return moves
  203.  
  204. # Funkce pro generování SAN notace
  205. def generate_san_notation(square: Square, move_square: Square, is_white: bool, piece_type: str, move_type: str) -> str:
  206.     file_from = chr((square % 8) + ord('a'))
  207.     rank_from = str(8 - (square // 8))
  208.     file_to = chr((move_square % 8) + ord('a'))
  209.     rank_to = str(8 - (move_square // 8))
  210.     piece = piece_type if is_white else piece_type.lower()
  211.     move_prefix = move_type[0].lower() if move_type in ["Knight", "Bishop", "Rook"] else ""
  212.     return f"{piece}{file_from}{rank_from}-{move_prefix}{file_to}{rank_to}"
  213.  
  214. # Funkce pro aktualizaci FEN stringu s novou pozicí figurky
  215. def update_fen_with_piece(fen: str, square: Square, move_square: Square, is_white: bool, piece_type: str) -> str:
  216.     parts = fen.split()
  217.     board_part = parts[0]
  218.     rows = board_part.split('/')
  219.     new_rows = []
  220.  
  221.     for rank in range(8):
  222.         row = rows[rank]
  223.         new_row = ''
  224.         file = 0
  225.         for char in row:
  226.             if char.isdigit():
  227.                 empty_squares = int(char)
  228.                 for _ in range(empty_squares):
  229.                     new_row += '1'
  230.                     file += 1
  231.             else:
  232.                 if (7 - rank) * 8 + file == square:
  233.                     new_row += '1'
  234.                 else:
  235.                     new_row += char
  236.                 file += 1
  237.         while len(new_row) < 8:
  238.             new_row += '1'
  239.         new_rows.append(new_row)
  240.  
  241.     new_board_part = '/'.join(new_rows)
  242.     new_fen = f"{new_board_part} w - - 0 1"
  243.     new_fen = re.sub(r'1{8}', '8', new_fen)
  244.     new_fen = re.sub(r'1{7}', '7', new_fen)
  245.     new_fen = re.sub(r'1{6}', '6', new_fen)
  246.     new_fen = re.sub(r'1{5}', '5', new_fen)
  247.     new_fen = re.sub(r'1{4}', '4', new_fen)
  248.     new_fen = re.sub(r'1{3}', '3', new_fen)
  249.     new_fen = re.sub(r'1{2}', '2', new_fen)
  250.     new_rows = new_fen.split('/')
  251.  
  252.     # Update the piece position in the new FEN
  253.     for rank in range(8):
  254.         new_row = ''
  255.         file = 0
  256.         for char in new_rows[rank]:
  257.             if char.isdigit():
  258.                 empty_squares = int(char)
  259.                 for _ in range(empty_squares):
  260.                     if (7 - rank) * 8 + file == move_square:
  261.                         piece = piece_type if is_white else piece_type.lower()
  262.                         new_row += piece
  263.                     else:
  264.                         new_row += '1'
  265.                     file += 1
  266.             else:
  267.                 if (7 - rank) * 8 + file == move_square:
  268.                     piece = piece_type if is_white else piece_type.lower()
  269.                     new_row += piece
  270.                 else:
  271.                     new_row += char
  272.                 file += 1
  273.         while len(new_row) < 8:
  274.             new_row += '1'
  275.         new_rows[rank] = new_row
  276.  
  277.     new_fen = '/'.join(new_rows)
  278.     new_fen = re.sub(r'1{8}', '8', new_fen)
  279.     new_fen = re.sub(r'1{7}', '7', new_fen)
  280.     new_fen = re.sub(r'1{6}', '6', new_fen)
  281.     new_fen = re.sub(r'1{5}', '5', new_fen)
  282.     new_fen = re.sub(r'1{4}', '4', new_fen)
  283.     new_fen = re.sub(r'1{3}', '3', new_fen)
  284.     new_fen = re.sub(r'1{2}', '2', new_fen)
  285.  
  286.     return new_fen
  287.  
  288. # Parsování FEN stringu
  289. fen_string = "1a6/2k5/8/8/3A4/8/8/6K1 b - - 0 1"
  290. white_amazons, black_amazons, white_cyrils, black_cyrils, white_evas, black_evas, white_kings, black_kings, white_queens, black_queens, turn, white_pieces, black_pieces = parse_fen(fen_string)
  291.  
  292. # Výpis šachovnic pro všechny možné tahy figurek z výchozí pozice
  293. print("Inicialní šachovnice:")
  294. print_board_with_fen(fen_string)
  295. print()
  296.  
  297. piece_types = ['A', 'C', 'E', 'K', 'Q']
  298. all_moves = []
  299.  
  300. for piece_type in piece_types:
  301.     if piece_type == 'A':
  302.         amazons = white_amazons if turn == 'w' else black_amazons
  303.         moves = generate_moves(amazons, white_pieces, black_pieces, turn, piece_type)
  304.     elif piece_type == 'C':
  305.         cyrils = white_cyrils if turn == 'w' else black_cyrils
  306.         moves = generate_moves(cyrils, white_pieces, black_pieces, turn, piece_type)
  307.     elif piece_type == 'E':
  308.         evas = white_evas if turn == 'w' else black_evas
  309.         moves = generate_moves(evas, white_pieces, black_pieces, turn, piece_type)
  310.     elif piece_type == 'K':
  311.         kings = white_kings if turn == 'w' else black_kings
  312.         moves = generate_moves(kings, white_pieces, black_pieces, turn, piece_type)
  313.     elif piece_type == 'Q':
  314.         queens = white_queens if turn == 'w' else black_queens
  315.         moves = generate_moves(queens, white_pieces, black_pieces, turn, piece_type)
  316.    
  317.     all_moves.extend([(piece_type, move) for move in moves])
  318.  
  319. for piece_type, (square, move, move_type) in all_moves:
  320.     new_fen = update_fen_with_piece(fen_string, square, move, turn == 'w', piece_type)
  321.     san_notation = generate_san_notation(square, move, turn == 'w', piece_type, move_type)
  322.     print(f"SAN: {san_notation} ({move_type})")
  323.     print(f"FEN: {new_fen}")
  324.     print_board_with_fen(new_fen)
  325.     print()
  326.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement