Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import chess
- import time
- from functools import lru_cache
- import traceback
- from typing import Iterator
- from chess import Move, BB_ALL, Bitboard, scan_reversed
- # Definice nových figurek
- AMAZON = 7
- CYRIL = 8
- EVA = 9
- # Nová funkce attacks_mask
- def new_attacks_mask(self, piece_type, square, occupied):
- print("new_attacks_mask")
- bb_square = chess.BB_SQUARES[square]
- if piece_type == chess.PAWN:
- color = bool(bb_square & self.occupied_co[chess.WHITE])
- return chess.BB_PAWN_ATTACKS[color][square]
- elif piece_type == chess.KNIGHT:
- return chess.BB_KNIGHT_ATTACKS[square]
- elif piece_type == chess.KING:
- return chess.BB_KING_ATTACKS[square]
- else:
- attacks = 0
- if piece_type == chess.BISHOP or piece_type == chess.QUEEN:
- attacks = chess.BB_DIAG_ATTACKS[square][chess.BB_DIAG_MASKS[square] & occupied]
- if piece_type == chess.ROOK or piece_type == chess.QUEEN:
- attacks |= (chess.BB_RANK_ATTACKS[square][chess.BB_RANK_MASKS[square] & occupied] |
- chess.BB_FILE_ATTACKS[square][chess.BB_FILE_MASKS[square] & occupied])
- if piece_type == AMAZON:
- attacks = (chess.BB_KNIGHT_ATTACKS[square] |
- chess.BB_DIAG_ATTACKS[square][chess.BB_DIAG_MASKS[square] & occupied])
- elif piece_type == CYRIL:
- attacks = (chess.BB_KNIGHT_ATTACKS[square] |
- chess.BB_RANK_ATTACKS[square][chess.BB_RANK_MASKS[square] & occupied] |
- chess.BB_FILE_ATTACKS[square][chess.BB_FILE_MASKS[square] & occupied])
- elif piece_type == EVA:
- attacks = (chess.BB_KNIGHT_ATTACKS[square] |
- chess.BB_DIAG_ATTACKS[square][chess.BB_DIAG_MASKS[square] & occupied])
- return attacks
- # Přiřazení nové funkce
- chess.BaseBoard.attacks_mask = new_attacks_mask
- class CustomBoard(chess.Board):
- def __init__(self, fen=None):
- print("__init__")
- super().__init__(fen)
- self._custom_piece_map = self._parse_custom_fen(fen) if fen else self._custom_piece_map()
- def _parse_custom_fen(self, fen):
- print("_parse_custom_fen")
- piece_map = {}
- square = 0
- for char in fen.split()[0]:
- if char.isdigit():
- square += int(char)
- elif char == '/':
- continue
- else:
- color = chess.WHITE if char.isupper() else chess.BLACK
- piece_type = {
- 'A': AMAZON,
- 'C': CYRIL,
- 'E': EVA,
- 'P': chess.PAWN,
- 'N': chess.KNIGHT,
- 'B': chess.BISHOP,
- 'R': chess.ROOK,
- 'Q': chess.QUEEN,
- 'K': chess.KING
- }.get(char.upper(), None)
- if piece_type:
- piece = chess.Piece(piece_type, color)
- piece_map[square] = piece
- square += 1
- return piece_map
- def piece_symbol(self, piece):
- print("piece_symbol")
- if piece is None:
- return "."
- if piece.piece_type == AMAZON:
- return "A" if piece.color == chess.WHITE else "a"
- if piece.piece_type == CYRIL:
- return "C" if piece.color == chess.WHITE else "c"
- if piece.piece_type == EVA:
- return "E" if piece.color == chess.WHITE else "e"
- return chess.PIECE_SYMBOLS[piece.piece_type].upper() if piece.color == chess.WHITE else chess.PIECE_SYMBOLS[piece.piece_type]
- def board_fen(self):
- print("board_fen")
- empty_squares = 0
- fen = []
- for square in chess.SQUARES_180:
- piece = self._custom_piece_map.get(square)
- if piece:
- if empty_squares:
- fen.append(str(empty_squares))
- empty_squares = 0
- fen.append(self.piece_symbol(piece))
- else:
- empty_squares += 1
- if chess.square_file(square) == 7:
- if empty_squares:
- fen.append(str(empty_squares))
- empty_squares = 0
- if square != chess.H1:
- fen.append('/')
- return ''.join(fen)
- def _custom_piece_map(self):
- print("_custom_piece_map")
- piece_map = {}
- for square, piece in self.piece_map().items():
- piece_map[square] = piece
- return piece_map
- def to_string(self):
- print("to_string")
- builder = []
- for square in chess.SQUARES_180:
- piece = self._custom_piece_map.get(square)
- symbol = self.piece_symbol(piece)
- builder.append(symbol)
- if chess.square_file(square) == 7:
- if square != chess.H1:
- builder.append("\n")
- return "".join(builder)
- def generate_pseudo_legal_moves(self, from_mask: Bitboard = BB_ALL, to_mask: Bitboard = BB_ALL) -> Iterator[chess.Move]:
- print("generate_pseudo_legal_moves")
- our_pieces = self.occupied_co[self.turn]
- # Generate piece moves.
- non_pawns = our_pieces & ~self.pawns & from_mask
- for from_square in scan_reversed(non_pawns):
- piece_type = self.piece_type_at(from_square)
- moves = self.attacks_mask(piece_type, from_square, self.occupied) & ~our_pieces & to_mask
- for to_square in scan_reversed(moves):
- yield Move(from_square, to_square)
- # Generate castling moves.
- if from_mask & self.kings:
- yield from self.generate_castling_moves(from_mask, to_mask)
- # The remaining moves are all pawn moves.
- pawns = self.pawns & self.occupied_co[self.turn] & from_mask
- if not pawns:
- return
- # Generate pawn moves.
- yield from self.generate_pseudo_legal_pawn_moves(pawns, to_mask)
- # Generate pawn captures.
- capturers = pawns
- for from_square in scan_reversed(capturers):
- targets = (
- chess.BB_PAWN_ATTACKS[self.turn][from_square] &
- self.occupied_co[not self.turn] & to_mask)
- for to_square in scan_reversed(targets):
- if chess.square_rank(to_square) in [0, 7]:
- yield Move(from_square, to_square, chess.QUEEN)
- yield Move(from_square, to_square, chess.ROOK)
- yield Move(from_square, to_square, chess.BISHOP)
- yield Move(from_square, to_square, chess.KNIGHT)
- else:
- yield Move(from_square, to_square)
- def is_check(self):
- print("is_check")
- king_square = self.king(self.turn)
- if king_square is None:
- return False
- if super().is_check():
- return True
- opponent_color = not self.turn
- for square, piece in self._custom_piece_map.items():
- if piece.color == opponent_color:
- if piece.piece_type in [AMAZON, CYRIL, EVA]:
- if self._is_attacked_by_new_piece(king_square, square, piece.piece_type):
- return True
- return False
- def _is_attacked_by_new_piece(self, target_square, attacker_square, piece_type):
- print("_is_attacked_by_new_piece")
- if piece_type == AMAZON:
- return (self.attacks_knight(attacker_square) | self.attacks_bishop(attacker_square)) & chess.BB_SQUARES[target_square]
- elif piece_type == CYRIL:
- return (self.attacks_knight(attacker_square) | self.attacks_rook(attacker_square)) & chess.BB_SQUARES[target_square]
- elif piece_type == EVA:
- return (self.attacks_queen(attacker_square) | self.attacks_knight(attacker_square)) & chess.BB_SQUARES[target_square]
- return False
- def attacks_knight(self, square):
- return self.attacks_mask(chess.KNIGHT, square, self.occupied)
- def attacks_bishop(self, square):
- return self.attacks_mask(chess.BISHOP, square, self.occupied)
- def attacks_rook(self, square):
- return self.attacks_mask(chess.ROOK, square, self.occupied)
- def attacks_queen(self, square):
- return self.attacks_bishop(square) | self.attacks_rook(square)
- @property
- def legal_moves(self):
- print("legal_moves")
- return [move for move in self.generate_pseudo_legal_moves() if self.is_legal(move)]
- @lru_cache(maxsize=None)
- def simplify_fen_string(fen):
- print("simplify_fen_string")
- parts = fen.split(' ')
- simplified_fen = ' '.join(parts[:4] + ["0", "1"])
- return simplified_fen
- def print_board(fen):
- print("print_board")
- board = CustomBoard(fen)
- print(board.to_string())
- print() # Add an empty line after the board
- def format_time(seconds):
- print("format_time")
- hours, remainder = divmod(seconds, 3600)
- minutes, seconds = divmod(remainder, 60)
- return f"{int(hours):02d}h {int(minutes):02d}m {int(seconds):02d}s"
- def analyze_positions(start_fen):
- print("analyze_positions")
- print("Initializing analysis...")
- POZ = {1: start_fen}
- AR = {simplify_fen_string(start_fen): {'used': 0, 'to_end': None}}
- N = 1
- M = 0
- start_time = time.time()
- total_time = 0
- print("Generování pozic...")
- while M < N:
- M += 1
- current_fen = POZ[M]
- board = CustomBoard(current_fen)
- legal_moves = list(board.legal_moves)
- if AR[simplify_fen_string(current_fen)]['used'] == 0:
- AR[simplify_fen_string(current_fen)]['used'] = 1
- for move in legal_moves:
- board.push(move)
- POZ2 = board.fen()
- simplified_POZ2 = simplify_fen_string(POZ2)
- if simplified_POZ2 not in AR:
- N += 1
- POZ[N] = POZ2
- AR[simplified_POZ2] = {'used': 0, 'to_end': None}
- board.pop()
- if M % 100 == 0: # Průběžný výpis každých 100 pozic
- print(f"Zpracováno {M} pozic, celkem {N} pozic")
- print(f"Čas: {format_time(time.time() - start_time)}")
- print(f"Počet pozic je {N}")
- F = 0
- for i in range(1, N + 1):
- current_fen = POZ[i]
- board = CustomBoard(current_fen)
- simplified_fen = simplify_fen_string(current_fen)
- if board.is_checkmate():
- AR[simplified_fen]['to_end'] = -1000 if board.turn == chess.WHITE else 1000
- F += 1
- elif board.is_stalemate() or board.is_insufficient_material() or board.is_seventyfive_moves() or board.is_fivefold_repetition():
- AR[simplified_fen]['to_end'] = 0
- else:
- AR[simplified_fen]['to_end'] = 0
- print(f"Počet pozic v matu je {F}")
- uroven = 0
- while F > 0:
- uroven += 1
- level_start_time = time.time()
- print(f"Výpočet v úrovni {uroven}")
- F = 0
- current_level_positions = 0
- for i in range(1, N + 1):
- current_fen = POZ[i]
- board = CustomBoard(current_fen)
- simplified_fen = simplify_fen_string(current_fen)
- if AR[simplified_fen]['to_end'] == 0:
- hod = -2000 if board.turn == chess.WHITE else 2000
- for move in board.legal_moves:
- board.push(move)
- POZ2 = board.fen()
- simplified_POZ2 = simplify_fen_string(POZ2)
- hod2 = -AR[simplified_POZ2]['to_end']
- if board.turn == chess.WHITE:
- if hod2 > hod:
- hod = hod2
- else:
- if hod2 < hod:
- hod = hod2
- board.pop()
- if (board.turn == chess.WHITE and hod == 1001 - uroven) or (board.turn == chess.BLACK and hod == -1001 + uroven):
- AR[simplified_fen]['to_end'] = 1000 - uroven if board.turn == chess.WHITE else -1000 + uroven
- F += 1
- current_level_positions += 1
- level_end_time = time.time()
- level_elapsed_time = level_end_time - level_start_time
- total_time += level_elapsed_time
- formatted_total_time = format_time(total_time)
- formatted_level_time = format_time(level_elapsed_time)
- print(f"Nalezeno {current_level_positions} pozic v úrovni {uroven}")
- print(f"Čas: {formatted_total_time} / {formatted_level_time}")
- print(f"Nalezeno {F} pozic celkem")
- print(f"Celkový čas: {format_time(total_time)}")
- current_fen = POZ[1]
- hod = AR[simplify_fen_string(current_fen)]['to_end']
- print(f"Hodnocení počáteční pozice je {hod}")
- # Procházení nejlepších tahů
- current_fen = start_fen
- optimal_moves = []
- while AR[simplify_fen_string(current_fen)]['to_end'] is not None and AR[simplify_fen_string(current_fen)]['to_end'] != 1000 and AR[simplify_fen_string(current_fen)]['to_end'] != -1000:
- board = CustomBoard(current_fen)
- hod = -2000 if board.turn == chess.WHITE else 2000
- best_move = None
- for move in board.legal_moves:
- board.push(move)
- POZ2 = board.fen()
- simplified_POZ2 = simplify_fen_string(POZ2)
- if AR[simplified_POZ2]['to_end'] is not None:
- hod2 = -AR[simplified_POZ2]['to_end']
- if (board.turn == chess.WHITE and hod2 > hod) or (board.turn == chess.BLACK and hod2 < hod):
- hod = hod2
- best_move = move
- board.pop()
- if best_move is None:
- break
- board.push(best_move)
- optimal_moves.append((current_fen, best_move))
- current_fen = board.fen()
- # Tisk optimálních tahů
- print("\nOptimální tahy:")
- for fen, move in optimal_moves:
- board = CustomBoard(fen)
- print(f"{board.fullmove_number}. {'Bílý' if board.turn == chess.WHITE else 'Černý'}: {move}")
- print_board(fen)
- print("\n")
- print("Konečná pozice:")
- print_board(current_fen)
- if __name__ == "__main__":
- start_fen = "1a6/3k4/8/8/8/8/8/6K1 b - - 0 1"
- print("Starting analysis...")
- print("Initial position:")
- print_board(start_fen)
- try:
- print("Creating initial board...")
- initial_board = CustomBoard(start_fen)
- print("Initial board created successfully.")
- print("Piece map:")
- for square, piece in initial_board._custom_piece_map.items():
- print(f"Square {chess.SQUARE_NAMES[square]}: {initial_board.piece_symbol(piece)}")
- print("Generating legal moves for initial position...")
- legal_moves = list(initial_board.legal_moves)
- print(f"Number of legal moves: {len(legal_moves)}")
- for move in legal_moves:
- print(f"Move: {move}")
- print("Starting position analysis...")
- analyze_positions(start_fen)
- except Exception as e:
- print(f"An error occurred: {str(e)}")
- traceback.print_exc()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement