Advertisement
max2201111

ultimate very good amazonka

Jun 30th, 2024
484
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.15 KB | Science | 0 0
  1. from typing import List, Iterable, Tuple
  2.  
  3. # Definice bitboardu a dalších typů
  4. Bitboard = int
  5. Square = int
  6.  
  7. # Konstanty
  8. BB_EMPTY = 0
  9. BB_ALL = (1 << 64) - 1
  10. SQUARES = list(range(64))
  11. BB_SQUARES = [1 << sq for sq in SQUARES]
  12.  
  13. # Pomocné funkce
  14. def square_distance(sq1: Square, sq2: Square) -> int:
  15.     file1, rank1 = sq1 % 8, sq1 // 8
  16.     file2, rank2 = sq2 % 8, sq2 // 8
  17.     return max(abs(file1 - file2), abs(rank1 - rank2))
  18.  
  19. # Funkce pro generování útoků
  20. def _sliding_attacks(square: Square, occupied: Bitboard, deltas: Iterable[int]) -> Bitboard:
  21.     attacks = BB_EMPTY
  22.  
  23.     for delta in deltas:
  24.         sq = square
  25.  
  26.         while True:
  27.             sq += delta
  28.             if not (0 <= sq < 64) or square_distance(sq, sq - delta) > 2:
  29.                 break
  30.  
  31.             attacks |= BB_SQUARES[sq]
  32.  
  33.             if occupied & BB_SQUARES[sq]:
  34.                 break
  35.  
  36.     return attacks
  37.  
  38. def _step_attacks(square: Square, deltas: Iterable[int]) -> Bitboard:
  39.     attacks = BB_EMPTY
  40.     for delta in deltas:
  41.         sq = square + delta
  42.         if 0 <= sq < 64 and square_distance(sq, square) <= 2:
  43.             attacks |= BB_SQUARES[sq]
  44.     return attacks
  45.  
  46. # Funkce pro generování tabulek útoků
  47. def _attack_table(deltas: List[int]) -> Tuple[List[Bitboard], List[Bitboard]]:
  48.     masks = []
  49.     attacks = []
  50.  
  51.     for sq in SQUARES:
  52.         mask = 0
  53.         attack = _sliding_attacks(sq, BB_EMPTY, deltas)
  54.         for i in range(64):
  55.             if attack & BB_SQUARES[i]:
  56.                 mask |= BB_SQUARES[i]
  57.         masks.append(mask)
  58.         attacks.append(attack)
  59.  
  60.     return masks, attacks
  61.  
  62. # Útoky pro KNIGHTa a BISHOPa
  63. KNIGHT_DELTAS = [-17, -15, -10, -6, 6, 10, 15, 17]
  64. BISHOP_DELTAS = [-9, -7, 7, 9]
  65.  
  66. # Získání masky a útoků pro KNIGHTa a BISHOPa
  67. BB_KNIGHT_MASKS, BB_KNIGHT_ATTACKS = _attack_table(KNIGHT_DELTAS)
  68. BB_BISHOP_MASKS, BB_BISHOP_ATTACKS = _attack_table(BISHOP_DELTAS)
  69.  
  70. # Kombinované útoky pro figurku AMAZON
  71. BB_AMAZON_ATTACKS = [knight | bishop for knight, bishop in zip(BB_KNIGHT_ATTACKS, BB_BISHOP_ATTACKS)]
  72.  
  73. # Funkce pro tisk šachovnice v ASCII formátu s FEN stringem
  74. def print_board_with_fen(fen: str) -> None:
  75.     parts = fen.split()
  76.     board_part = parts[0]
  77.     rows = board_part.split('/')
  78.     for row in rows:
  79.         row_str = ''
  80.         for char in row:
  81.             if char.isdigit():
  82.                 row_str += '.' * int(char)
  83.             else:
  84.                 row_str += char
  85.         print(row_str)
  86.  
  87. # Funkce pro parsování FEN stringu a získání pozice Amazonky
  88. def parse_fen(fen: str) -> Tuple[List[Square], List[Square], str, Bitboard, Bitboard]:
  89.     parts = fen.split()
  90.     board_part = parts[0]
  91.     turn = parts[1]
  92.     rows = board_part.split('/')
  93.     white_amazons = []
  94.     black_amazons = []
  95.     white_pieces = BB_EMPTY
  96.     black_pieces = BB_EMPTY
  97.     for rank in range(8):
  98.         row = rows[rank]
  99.         file = 0
  100.         for char in row:
  101.             if char.isdigit():
  102.                 file += int(char)
  103.             elif char == 'A':
  104.                 white_amazons.append((7 - rank) * 8 + file)
  105.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  106.                 file += 1
  107.             elif char == 'a':
  108.                 black_amazons.append((7 - rank) * 8 + file)
  109.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  110.                 file += 1
  111.             elif char.isupper():
  112.                 white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  113.                 file += 1
  114.             elif char.islower():
  115.                 black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
  116.                 file += 1
  117.     return white_amazons, black_amazons, turn, white_pieces, black_pieces
  118.  
  119. # Funkce pro generování možných tahů Amazonky
  120. def generate_amazon_moves(amazon_squares: List[Square], white_pieces: Bitboard, black_pieces: Bitboard, turn: str) -> List[Tuple[Square, Square]]:
  121.     moves = []
  122.     occupied = white_pieces | black_pieces
  123.     for amazon_square in amazon_squares:
  124.         attacks = BB_AMAZON_ATTACKS[amazon_square]
  125.         for move in SQUARES:
  126.             if attacks & BB_SQUARES[move]:
  127.                 if turn == 'w':
  128.                     if not (occupied & BB_SQUARES[move] and (white_pieces & BB_SQUARES[move])):
  129.                         moves.append((amazon_square, move))
  130.                 else:
  131.                     if not (occupied & BB_SQUARES[move] and (black_pieces & BB_SQUARES[move])):
  132.                         moves.append((amazon_square, move))
  133.     return moves
  134.  
  135. # Funkce pro generování SAN notace
  136. def generate_san_notation(amazon_square: Square, move_square: Square, is_white: bool) -> str:
  137.     file_from = chr((amazon_square % 8) + ord('a'))
  138.     rank_from = str(8 - (amazon_square // 8))
  139.     file_to = chr((move_square % 8) + ord('a'))
  140.     rank_to = str(8 - (move_square // 8))
  141.     piece = 'A' if is_white else 'a'
  142.     return f"{piece}{file_from}{rank_from}-{file_to}{rank_to}"
  143.  
  144. # Funkce pro aktualizaci FEN stringu s novou pozicí Amazonky
  145. def update_fen_with_amazon(fen: str, amazon_square: Square, move_square: Square, is_white: bool) -> str:
  146.     parts = fen.split()
  147.     board_part = parts[0]
  148.     rows = board_part.split('/')
  149.     new_rows = []
  150.  
  151.     for rank in range(8):
  152.         row = rows[rank]
  153.         new_row = ''
  154.         file = 0
  155.         for char in row:
  156.             if char.isdigit():
  157.                 empty_squares = int(char)
  158.                 for _ in range(empty_squares):
  159.                     new_row += '1'
  160.                     file += 1
  161.             else:
  162.                 if (7 - rank) * 8 + file == amazon_square:
  163.                     new_row += '1'
  164.                 else:
  165.                     new_row += char
  166.                 file += 1
  167.         new_rows.append(new_row)
  168.  
  169.     new_board_part = '/'.join(new_rows)
  170.     new_fen = f"{new_board_part} {'b' if is_white else 'w'} - - 0 1"
  171.  
  172.     # Použití regulárních výrazů pro zkrácení sekvencí '1'
  173.     new_fen = re.sub(r'1{8}', '8', new_fen)
  174.     new_fen = re.sub(r'1{7}', '7', new_fen)
  175.     new_fen = re.sub(r'1{6}', '6', new_fen)
  176.     new_fen = re.sub(r'1{5}', '5', new_fen)
  177.     new_fen = re.sub(r'1{4}', '4', new_fen)
  178.     new_fen = re.sub(r'1{3}', '3', new_fen)
  179.     new_fen = re.sub(r'1{2}', '2', new_fen)
  180.     new_fen = re.sub(r'1', '', new_fen)
  181.  
  182.     # Update the Amazon position in the new FEN
  183.     new_rows = new_fen.split('/')
  184.  
  185.     for rank in range(8):
  186.         new_row = ''
  187.         file = 0
  188.         for char in new_rows[rank]:
  189.             if char.isdigit():
  190.                 empty_squares = int(char)
  191.                 for _ in range(empty_squares):
  192.                     if (7 - rank) * 8 + file == move_square:
  193.                         new_row += 'A' if is_white else 'a'
  194.                     else:
  195.                         new_row += '1'
  196.                     file += 1
  197.             else:
  198.                 if (7 - rank) * 8 + file == move_square:
  199.                     new_row += 'A' if is_white else 'a'
  200.                 else:
  201.                     new_row += char
  202.                 file += 1
  203.         new_rows[rank] = new_row
  204.  
  205.     new_fen = '/'.join(new_rows)
  206.     new_fen = re.sub(r'1{8}', '8', new_fen)
  207.     new_fen = re.sub(r'1{7}', '7', new_fen)
  208.     new_fen = re.sub(r'1{6}', '6', new_fen)
  209.     new_fen = re.sub(r'1{5}', '5', new_fen)
  210.     new_fen = re.sub(r'1{4}', '4', new_fen)
  211.     new_fen = re.sub(r'1{3}', '3', new_fen)
  212.     new_fen = re.sub(r'1{2}', '2', new_fen)
  213.     new_fen = re.sub(r'1', '', new_fen)
  214.  
  215.     return new_fen
  216.  
  217. # Parsování FEN stringu
  218. fen_string = "1a6/2k5/8/8/3A4/8/8/6K1 b - - 0 1"
  219. white_amazons, black_amazons, turn, white_pieces, black_pieces = parse_fen(fen_string)
  220. amazons = white_amazons if turn == 'w' else black_amazons
  221.  
  222. # Výpis šachovnic pro všechny možné tahy Amazonky z výchozí pozice
  223. print("Inicialní šachovnice:")
  224. print_board_with_fen(fen_string)
  225. print()
  226. moves = generate_amazon_moves(amazons, white_pieces, black_pieces, turn)
  227. for amazon_square, move in moves:
  228.     new_fen = update_fen_with_amazon(fen_string, amazon_square, move, turn == 'w')
  229.     san_notation = generate_san_notation(amazon_square, move, turn == 'w')
  230.     print(f"SAN: {san_notation}")
  231.     print(f"FEN: {new_fen}")
  232.     print_board_with_fen(new_fen)
  233.     print()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement