Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from typing import List, Iterable, Tuple
- import re
- # Definice bitboardu a dalších typů
- Bitboard = int
- Square = int
- # Konstanty
- BB_EMPTY = 0
- BB_ALL = (1 << 64) - 1
- SQUARES = list(range(64))
- BB_SQUARES = [1 << sq for sq in SQUARES]
- # Pomocné funkce
- def square_distance(sq1: Square, sq2: Square) -> int:
- file1, rank1 = sq1 % 8, sq1 // 8
- file2, rank2 = sq2 % 8, sq2 // 8
- return max(abs(file1 - file2), abs(rank1 - rank2))
- # Funkce pro generování útoků
- def _sliding_attacks(square: Square, occupied: Bitboard, deltas: Iterable[int]) -> Bitboard:
- attacks = BB_EMPTY
- for delta in deltas:
- sq = square
- while True:
- sq += delta
- if not (0 <= sq < 64) or square_distance(sq, sq - delta) > 2:
- break
- attacks |= BB_SQUARES[sq]
- if occupied & BB_SQUARES[sq]:
- break
- return attacks
- def _step_attacks(square: Square, deltas: Iterable[int]) -> Bitboard:
- attacks = BB_EMPTY
- for delta in deltas:
- sq = square + delta
- if 0 <= sq < 64 and square_distance(sq, square) <= 2:
- attacks |= BB_SQUARES[sq]
- return attacks
- # Funkce pro generování tabulek útoků
- def _attack_table(deltas: List[int]) -> Tuple[List[Bitboard], List[Bitboard]]:
- masks = []
- attacks = []
- for sq in SQUARES:
- mask = 0
- attack = _sliding_attacks(sq, BB_EMPTY, deltas)
- for i in range(64):
- if attack & BB_SQUARES[i]:
- mask |= BB_SQUARES[i]
- masks.append(mask)
- attacks.append(attack)
- return masks, attacks
- # Útoky pro KNIGHTa, BISHOPa, ROOKa, QUEENa a KINGa
- KNIGHT_DELTAS = [-17, -15, -10, -6, 6, 10, 15, 17]
- BISHOP_DELTAS = [-9, -7, 7, 9]
- ROOK_DELTAS = [-8, -1, 1, 8]
- QUEEN_DELTAS = BISHOP_DELTAS + ROOK_DELTAS
- KING_DELTAS = [-9, -8, -7, -1, 1, 7, 8, 9]
- # Získání masky a útoků pro KNIGHTa, BISHOPa, ROOKa, QUEENa a KINGa
- BB_KNIGHT_MASKS, BB_KNIGHT_ATTACKS = _attack_table(KNIGHT_DELTAS)
- BB_BISHOP_MASKS, BB_BISHOP_ATTACKS = _attack_table(BISHOP_DELTAS)
- BB_ROOK_MASKS, BB_ROOK_ATTACKS = _attack_table(ROOK_DELTAS)
- BB_QUEEN_MASKS, BB_QUEEN_ATTACKS = _attack_table(QUEEN_DELTAS)
- BB_KING_MASKS, BB_KING_ATTACKS = _attack_table(KING_DELTAS)
- # Kombinované útoky pro figurky AMAZON, CYRIL a EVA
- BB_AMAZON_ATTACKS = [knight | bishop for knight, bishop in zip(BB_KNIGHT_ATTACKS, BB_BISHOP_ATTACKS)]
- BB_CYRIL_ATTACKS = [knight | rook for knight, rook in zip(BB_KNIGHT_ATTACKS, BB_ROOK_ATTACKS)]
- BB_EVA_ATTACKS = [knight | queen for knight, queen in zip(BB_KNIGHT_ATTACKS, BB_QUEEN_ATTACKS)]
- # Funkce pro tisk šachovnice v ASCII formátu s FEN stringem
- def print_board_with_fen(fen: str) -> None:
- parts = fen.split()
- board_part = parts[0]
- rows = board_part.split('/')
- for row in rows:
- row_str = ''
- for char in row:
- if char.isdigit():
- row_str += '.' * int(char)
- else:
- row_str += char
- print(row_str)
- # Funkce pro parsování FEN stringu a získání pozic figurek
- 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]:
- parts = fen.split()
- board_part = parts[0]
- turn = parts[1]
- rows = board_part.split('/')
- white_amazons = []
- black_amazons = []
- white_cyrils = []
- black_cyrils = []
- white_evas = []
- black_evas = []
- white_kings = []
- black_kings = []
- white_queens = []
- black_queens = []
- white_bishops = []
- black_bishops = []
- white_pieces = BB_EMPTY
- black_pieces = BB_EMPTY
- for rank in range(8):
- row = rows[rank]
- file = 0
- for char in row:
- if char.isdigit():
- file += int(char)
- elif char == 'A':
- white_amazons.append((7 - rank) * 8 + file)
- white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- elif char == 'a':
- black_amazons.append((7 - rank) * 8 + file)
- black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- elif char == 'C':
- white_cyrils.append((7 - rank) * 8 + file)
- white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- elif char == 'c':
- black_cyrils.append((7 - rank) * 8 + file)
- black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- elif char == 'E':
- white_evas.append((7 - rank) * 8 + file)
- white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- elif char == 'e':
- black_evas.append((7 - rank) * 8 + file)
- black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- elif char == 'K':
- white_kings.append((7 - rank) * 8 + file)
- white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- elif char == 'k':
- black_kings.append((7 - rank) * 8 + file)
- black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- elif char == 'Q':
- white_queens.append((7 - rank) * 8 + file)
- white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- elif char == 'q':
- black_queens.append((7 - rank) * 8 + file)
- black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- elif char == 'B':
- white_bishops.append((7 - rank) * 8 + file)
- white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- elif char == 'b':
- black_bishops.append((7 - rank) * 8 + file)
- black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- elif char.isupper():
- white_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- elif char.islower():
- black_pieces |= BB_SQUARES[(7 - rank) * 8 + file]
- file += 1
- 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
- # Funkce pro generování možných tahů figurek
- def generate_moves(piece_squares: List[Square], white_pieces: Bitboard, black_pieces: Bitboard, turn: str, piece_type: str) -> List[Tuple[Square, Square, str]]:
- moves = []
- occupied = white_pieces | black_pieces
- if piece_type == 'A':
- attacks = BB_AMAZON_ATTACKS
- move_types = {"Bishop": BISHOP_DELTAS, "Knight": KNIGHT_DELTAS}
- elif piece_type == 'C':
- attacks = BB_CYRIL_ATTACKS
- move_types = {"Rook": ROOK_DELTAS, "Knight": KNIGHT_DELTAS}
- elif piece_type == 'E':
- attacks = BB_EVA_ATTACKS
- move_types = {"Queen": QUEEN_DELTAS, "Knight": KNIGHT_DELTAS}
- elif piece_type == 'K':
- attacks = BB_KING_ATTACKS
- move_types = {"King": KING_DELTAS}
- elif piece_type == 'Q':
- attacks = BB_QUEEN_ATTACKS
- move_types = {"Queen": QUEEN_DELTAS}
- elif piece_type == 'B':
- attacks = BB_BISHOP_ATTACKS
- move_types = {"Bishop": BISHOP_DELTAS}
- for square in piece_squares:
- piece_attacks = attacks[square]
- for move in SQUARES:
- if piece_attacks & BB_SQUARES[move]:
- if turn == 'w' and not (occupied & BB_SQUARES[move] and white_pieces & BB_SQUARES[move]):
- for move_type, deltas in move_types.items():
- if _sliding_attacks(square, occupied, deltas) & BB_SQUARES[move]:
- moves.append((square, move, move_type))
- break
- elif turn == 'b' and not (occupied & BB_SQUARES[move] and black_pieces & BB_SQUARES[move]):
- for move_type, deltas in move_types.items():
- if _sliding_attacks(square, occupied, deltas) & BB_SQUARES[move]:
- moves.append((square, move, move_type))
- break
- return moves
- # Funkce pro generování SAN notace
- def generate_san_notation(square: Square, move_square: Square, is_white: bool, piece_type: str, move_type: str) -> str:
- file_from = chr((square % 8) + ord('a'))
- rank_from = str(8 - (square // 8))
- file_to = chr((move_square % 8) + ord('a'))
- rank_to = str(8 - (move_square // 8))
- piece = piece_type if is_white else piece_type.lower()
- move_prefix = move_type[0].lower() if move_type in ["Knight", "Bishop", "Rook"] else ""
- return f"{piece}{file_from}{rank_from}-{move_prefix}{file_to}{rank_to}, {piece}"
- # Funkce pro aktualizaci FEN stringu s novou pozicí figurky
- def update_fen_with_piece(fen: str, square: Square, move_square: Square, is_white: bool, piece_type: str) -> str:
- parts = fen.split()
- board_part = parts[0]
- rows = board_part.split('/')
- new_rows = []
- for rank in range(8):
- row = rows[rank]
- new_row = ''
- file = 0
- for char in row:
- if char.isdigit():
- empty_squares = int(char)
- for _ in range(empty_squares):
- new_row += '1'
- file += 1
- else:
- if (7 - rank) * 8 + file == square:
- new_row += '1'
- else:
- new_row += char
- file += 1
- while len(new_row) < 8:
- new_row += '1'
- new_rows.append(new_row)
- new_board_part = '/'.join(new_rows)
- new_fen = f"{new_board_part} w - - 0 1"
- new_fen = re.sub(r'1{8}', '8', new_fen)
- new_fen = re.sub(r'1{7}', '7', new_fen)
- new_fen = re.sub(r'1{6}', '6', new_fen)
- new_fen = re.sub(r'1{5}', '5', new_fen)
- new_fen = re.sub(r'1{4}', '4', new_fen)
- new_fen = re.sub(r'1{3}', '3', new_fen)
- new_fen = re.sub(r'1{2}', '2', new_fen)
- new_rows = new_fen.split('/')
- # Update the piece position in the new FEN
- for rank in range(8):
- new_row = ''
- file = 0
- for char in new_rows[rank]:
- if char.isdigit():
- empty_squares = int(char)
- for _ in range(empty_squares):
- if (7 - rank) * 8 + file == move_square:
- piece = piece_type if is_white else piece_type.lower()
- new_row += piece
- else:
- new_row += '1'
- file += 1
- else:
- if (7 - rank) * 8 + file == move_square:
- piece = piece_type if is_white else piece_type.lower()
- new_row += piece
- else:
- new_row += char
- file += 1
- while len(new_row) < 8:
- new_row += '1'
- new_rows[rank] = new_row
- new_fen = '/'.join(new_rows)
- new_fen = re.sub(r'1{8}', '8', new_fen)
- new_fen = re.sub(r'1{7}', '7', new_fen)
- new_fen = re.sub(r'1{6}', '6', new_fen)
- new_fen = re.sub(r'1{5}', '5', new_fen)
- new_fen = re.sub(r'1{4}', '4', new_fen)
- new_fen = re.sub(r'1{3}', '3', new_fen)
- new_fen = re.sub(r'1{2}', '2', new_fen)
- return new_fen
- # Parsování FEN stringu
- fen_string = "1a6/3k4/8/8/4b3/8/8/6K1 b - - 0 1"
- 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)
- # Výpis šachovnic pro všechny možné tahy figurek z výchozí pozice
- print("Inicialní šachovnice:")
- print_board_with_fen(fen_string)
- print()
- piece_types = ['A', 'C', 'E', 'K', 'Q', 'B']
- all_moves = []
- for piece_type in piece_types:
- if piece_type == 'A':
- amazons = white_amazons if turn == 'w' else black_amazons
- moves = generate_moves(amazons, white_pieces, black_pieces, turn, piece_type)
- elif piece_type == 'C':
- cyrils = white_cyrils if turn == 'w' else black_cyrils
- moves = generate_moves(cyrils, white_pieces, black_pieces, turn, piece_type)
- elif piece_type == 'E':
- evas = white_evas if turn == 'w' else black_evas
- moves = generate_moves(evas, white_pieces, black_pieces, turn, piece_type)
- elif piece_type == 'K':
- kings = white_kings if turn == 'w' else black_kings
- moves = generate_moves(kings, white_pieces, black_pieces, turn, piece_type)
- elif piece_type == 'Q':
- queens = white_queens if turn == 'w' else black_queens
- moves = generate_moves(queens, white_pieces, black_pieces, turn, piece_type)
- elif piece_type == 'B':
- bishops = white_bishops if turn == 'w' else black_bishops
- moves = generate_moves(bishops, white_pieces, black_pieces, turn, piece_type)
- all_moves.extend([(piece_type, move) for move in moves])
- for piece_type, (square, move, move_type) in all_moves:
- new_fen = update_fen_with_piece(fen_string, square, move, turn == 'w', piece_type)
- san_notation = generate_san_notation(square, move, turn == 'w', piece_type, move_type)
- print(f"SAN: {san_notation} ({move_type})")
- print(f"FEN: {new_fen}")
- print_board_with_fen(new_fen)
- print()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement