Advertisement
max2201111

ultimate very good amazonka 2 not exact

Jun 30th, 2024
542
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.86 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 a QUEENa
  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]]:
  170.     moves = []
  171.     occupied = white_pieces | black_pieces
  172.     if piece_type == 'A':
  173.         attacks = BB_AMAZON_ATTACKS
  174.     elif piece_type == 'C':
  175.         attacks = BB_CYRIL_ATTACKS
  176.     elif piece_type == 'E':
  177.         attacks = BB_EVA_ATTACKS
  178.     elif piece_type == 'K':
  179.         attacks = BB_KING_ATTACKS
  180.     elif piece_type == 'Q':
  181.         attacks = BB_QUEEN_ATTACKS
  182.     else:
  183.         return moves
  184.  
  185.     for square in piece_squares:
  186.         piece_attacks = attacks[square]
  187.         for move in SQUARES:
  188.             if piece_attacks & BB_SQUARES[move]:
  189.                 if turn == 'w' and not (occupied & BB_SQUARES[move] and white_pieces & BB_SQUARES[move]):
  190.                     moves.append((square, move))
  191.                 elif turn == 'b' and not (occupied & BB_SQUARES[move] and black_pieces & BB_SQUARES[move]):
  192.                     moves.append((square, move))
  193.     return moves
  194.  
  195. # Funkce pro generování SAN notace
  196. def generate_san_notation(square: Square, move_square: Square, is_white: bool, piece_type: str) -> str:
  197.     file_from = chr((square % 8) + ord('a'))
  198.     rank_from = str(8 - (square // 8))
  199.     file_to = chr((move_square % 8) + ord('a'))
  200.     rank_to = str(8 - (move_square // 8))
  201.     piece = piece_type if is_white else piece_type.lower()
  202.     return f"{piece}{file_from}{rank_from}-{file_to}{rank_to}"
  203.  
  204. # Funkce pro aktualizaci FEN stringu s novou pozicí figurky
  205. def update_fen_with_piece(fen: str, square: Square, move_square: Square, is_white: bool, piece_type: str) -> str:
  206.     parts = fen.split()
  207.     board_part = parts[0]
  208.     rows = board_part.split('/')
  209.     new_rows = []
  210.  
  211.     for rank in range(8):
  212.         row = rows[rank]
  213.         new_row = ''
  214.         file = 0
  215.         for char in row:
  216.             if char.isdigit():
  217.                 empty_squares = int(char)
  218.                 for _ in range(empty_squares):
  219.                     new_row += '1'
  220.                     file += 1
  221.             else:
  222.                 if (7 - rank) * 8 + file == square:
  223.                     new_row += '1'
  224.                 else:
  225.                     new_row += char
  226.                 file += 1
  227.         new_rows.append(new_row)
  228.  
  229.     new_board_part = '/'.join(new_rows)
  230.     new_fen = f"{new_board_part} w - - 0 1"
  231.     new_fen = re.sub(r'1{8}', '8', new_fen)
  232.     new_fen = re.sub(r'1{7}', '7', new_fen)
  233.     new_fen = re.sub(r'1{6}', '6', new_fen)
  234.     new_fen = re.sub(r'1{5}', '5', new_fen)
  235.     new_fen = re.sub(r'1{4}', '4', new_fen)
  236.     new_fen = re.sub(r'1{3}', '3', new_fen)
  237.     new_fen = re.sub(r'1{2}', '2', new_fen)
  238.     new_fen = re.sub(r'1', '', new_fen)
  239.     new_rows = new_fen.split('/')
  240.  
  241.     # Update the piece position in the new FEN
  242.     for rank in range(8):
  243.         new_row = ''
  244.         file = 0
  245.         for char in new_rows[rank]:
  246.             if char.isdigit():
  247.                 empty_squares = int(char)
  248.                 for _ in range(empty_squares):
  249.                     if (7 - rank) * 8 + file == move_square:
  250.                         piece = piece_type if is_white else piece_type.lower()
  251.                         new_row += piece
  252.                     else:
  253.                         new_row += '1'
  254.                     file += 1
  255.             else:
  256.                 if (7 - rank) * 8 + file == move_square:
  257.                     piece = piece_type if is_white else piece_type.lower()
  258.                     new_row += piece
  259.                 else:
  260.                     new_row += char
  261.                 file += 1
  262.         new_rows[rank] = new_row
  263.  
  264.     new_fen = '/'.join(new_rows)
  265.     new_fen = re.sub(r'1{8}', '8', new_fen)
  266.     new_fen = re.sub(r'1{7}', '7', new_fen)
  267.     new_fen = re.sub(r'1{6}', '6', new_fen)
  268.     new_fen = re.sub(r'1{5}', '5', new_fen)
  269.     new_fen = re.sub(r'1{4}', '4', new_fen)
  270.     new_fen = re.sub(r'1{3}', '3', new_fen)
  271.     new_fen = re.sub(r'1{2}', '2', new_fen)
  272.     new_fen = re.sub(r'1', '', new_fen)
  273.  
  274.     return new_fen
  275.  
  276. # Parsování FEN stringu
  277. fen_string = "1a6/2k5/8/8/3A4/8/8/6K1 b - - 0 1"
  278. 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)
  279.  
  280. # Výpis šachovnic pro všechny možné tahy figurky z výchozí pozice
  281. print("Inicialní šachovnice:")
  282. print_board_with_fen(fen_string)
  283. print()
  284.  
  285. piece_types = ['A', 'C', 'E', 'K', 'Q']
  286. all_moves = []
  287.  
  288. for piece_type in piece_types:
  289.     if piece_type == 'A':
  290.         amazons = white_amazons if turn == 'w' else black_amazons
  291.         moves = generate_moves(amazons, white_pieces, black_pieces, turn, piece_type)
  292.     elif piece_type == 'C':
  293.         cyrils = white_cyrils if turn == 'w' else black_cyrils
  294.         moves = generate_moves(cyrils, white_pieces, black_pieces, turn, piece_type)
  295.     elif piece_type == 'E':
  296.         evas = white_evas if turn == 'w' else black_evas
  297.         moves = generate_moves(evas, white_pieces, black_pieces, turn, piece_type)
  298.     elif piece_type == 'K':
  299.         kings = white_kings if turn == 'w' else black_kings
  300.         moves = generate_moves(kings, white_pieces, black_pieces, turn, piece_type)
  301.     elif piece_type == 'Q':
  302.         queens = white_queens if turn == 'w' else black_queens
  303.         moves = generate_moves(queens, white_pieces, black_pieces, turn, piece_type)
  304.    
  305.     all_moves.extend([(piece_type, move) for move in moves])
  306.  
  307. for piece_type, (square, move) in all_moves:
  308.     new_fen = update_fen_with_piece(fen_string, square, move, turn == 'w', piece_type)
  309.     san_notation = generate_san_notation(square, move, turn == 'w', piece_type)
  310.     print(f"SAN: {san_notation}")
  311.     print(f"FEN: {new_fen}")
  312.     print_board_with_fen(new_fen)
  313.     print()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement