Python Forum
Endgame engine with non-standard figures doesn't behave correctly - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Endgame engine with non-standard figures doesn't behave correctly (/thread-43660.html)



Endgame engine with non-standard figures doesn't behave correctly - max248 - Dec-07-2024

I've created a code for chess endgame with non-standard figures Amazon/Eve/Cyril.
Amazon, say, is like Queen and Knight at one piece.
The code is here:

import chess from typing import Iterator, Optional, Dict, Tuple from chess import Move, BB_ALL, Bitboard, PieceType, Color import time from collections import deque import threading # Definice nových figur AMAZON = 7 CYRIL = 8 EVE = 9 # Rozšíření seznamu PIECE_SYMBOLS chess.PIECE_SYMBOLS.append('a') chess.PIECE_SYMBOLS.append('c') chess.PIECE_SYMBOLS.append('e') class CustomBoard(chess.Board): def __init__(self, fen=None): self.amazons_white = chess.BB_EMPTY self.amazons_black = chess.BB_EMPTY self.cyrils_white = chess.BB_EMPTY self.cyrils_black = chess.BB_EMPTY self.eves_white = chess.BB_EMPTY self.eves_black = chess.BB_EMPTY super().__init__(None) if fen: self.set_custom_fen(fen) self.debug_amazons() self.debug_cyrils() self.debug_eves() def clear_square(self, square): super()._remove_piece_at(square) self.amazons_white &= ~chess.BB_SQUARES[square] self.amazons_black &= ~chess.BB_SQUARES[square] self.cyrils_white &= ~chess.BB_SQUARES[square] self.cyrils_black &= ~chess.BB_SQUARES[square] self.eves_white &= ~chess.BB_SQUARES[square] self.eves_black &= ~chess.BB_SQUARES[square] def set_custom_fen(self, fen): parts = fen.split() board_part = parts[0] self.clear() self.amazons_white = chess.BB_EMPTY self.amazons_black = chess.BB_EMPTY self.cyrils_white = chess.BB_EMPTY self.cyrils_black = chess.BB_EMPTY self.eves_white = chess.BB_EMPTY self.eves_black = chess.BB_EMPTY square = 56 for c in board_part: if c == '/': square -= 16 elif c.isdigit(): square += int(c) else: color = chess.WHITE if c.isupper() else chess.BLACK if c.upper() == 'A': if color == chess.WHITE: self.amazons_white |= chess.BB_SQUARES[square] else: self.amazons_black |= chess.BB_SQUARES[square] piece_type = AMAZON elif c.upper() == 'C': if color == chess.WHITE: self.cyrils_white |= chess.BB_SQUARES[square] else: self.cyrils_black |= chess.BB_SQUARES[square] piece_type = CYRIL elif c.upper() == 'E': if color == chess.WHITE: self.eves_white |= chess.BB_SQUARES[square] else: self.eves_black |= chess.BB_SQUARES[square] piece_type = EVE elif c == 'P' and chess.square_rank(square) == 7: piece_type = AMAZON color = chess.WHITE elif c == 'p' and chess.square_rank(square) == 0: piece_type = AMAZON color = chess.BLACK else: piece_type = chess.PIECE_SYMBOLS.index(c.lower()) self._set_piece_at(square, piece_type, color) square += 1 self.turn = chess.WHITE if parts[1] == 'w' else chess.BLACK self.castling_rights = chess.BB_EMPTY if '-' not in parts[2]: if 'K' in parts[2]: self.castling_rights |= chess.BB_H1 if 'Q' in parts[2]: self.castling_rights |= chess.BB_A1 if 'k' in parts[2]: self.castling_rights |= chess.BB_H8 if 'q' in parts[2]: self.castling_rights |= chess.BB_A8 self.ep_square = chess.parse_square(parts[3]) if parts[3] != '-' else None def _set_piece_at(self, square: chess.Square, piece_type: PieceType, color: Color) -> None: self.clear_square(square) super()._set_piece_at(square, piece_type, color) if piece_type == AMAZON: if color == chess.WHITE: self.amazons_white |= chess.BB_SQUARES[square] else: self.amazons_black |= chess.BB_SQUARES[square] elif piece_type == CYRIL: if color == chess.WHITE: self.cyrils_white |= chess.BB_SQUARES[square] else: self.cyrils_black |= chess.BB_SQUARES[square] elif piece_type == EVE: if color == chess.WHITE: self.eves_white |= chess.BB_SQUARES[square] else: self.eves_black |= chess.BB_SQUARES[square] def piece_at(self, square: chess.Square) -> Optional[chess.Piece]: if self.amazons_white & chess.BB_SQUARES[square]: return chess.Piece(AMAZON, chess.WHITE) elif self.amazons_black & chess.BB_SQUARES[square]: return chess.Piece(AMAZON, chess.BLACK) elif self.cyrils_white & chess.BB_SQUARES[square]: return chess.Piece(CYRIL, chess.WHITE) elif self.cyrils_black & chess.BB_SQUARES[square]: return chess.Piece(CYRIL, chess.BLACK) elif self.eves_white & chess.BB_SQUARES[square]: return chess.Piece(EVE, chess.WHITE) elif self.eves_black & chess.BB_SQUARES[square]: return chess.Piece(EVE, chess.BLACK) return super().piece_at(square) def generate_pseudo_legal_moves(self, from_mask: Bitboard = BB_ALL, to_mask: Bitboard = BB_ALL) -> Iterator[Move]: our_pieces = self.occupied_co[self.turn] if self.turn == chess.WHITE: our_amazons = self.amazons_white our_cyrils = self.cyrils_white our_eves = self.eves_white else: our_amazons = self.amazons_black our_cyrils = self.cyrils_black our_eves = self.eves_black # Generování tahů pro amazonky for from_square in chess.scan_forward(our_amazons & from_mask): attacks = self.amazon_attacks(from_square) valid_moves = attacks & ~our_pieces & to_mask for to_square in chess.scan_forward(valid_moves): yield Move(from_square, to_square) # Generování tahů pro Cyrily for from_square in chess.scan_forward(our_cyrils & from_mask): attacks = self.cyril_attacks(from_square) valid_moves = attacks & ~our_pieces & to_mask for to_square in chess.scan_forward(valid_moves): yield Move(from_square, to_square) # Generování tahů pro Evy for from_square in chess.scan_forward(our_eves & from_mask): attacks = self.eve_attacks(from_square) valid_moves = attacks & ~our_pieces & to_mask for to_square in chess.scan_forward(valid_moves): yield Move(from_square, to_square) # Generování tahů pro standardní figury for move in super().generate_pseudo_legal_moves(from_mask, to_mask): piece = self.piece_at(move.from_square) if piece and piece.piece_type not in [AMAZON, CYRIL, EVE]: yield move def queen_attacks(self, square): return self.bishop_attacks(square) | self.rook_attacks(square) def bishop_attacks(self, square): return chess.BB_DIAG_ATTACKS[square][self.occupied & chess.BB_DIAG_MASKS[square]] def rook_attacks(self, square): return (chess.BB_RANK_ATTACKS[square][self.occupied & chess.BB_RANK_MASKS[square]] | chess.BB_FILE_ATTACKS[square][self.occupied & chess.BB_FILE_MASKS[square]]) def amazon_attacks(self, square): return self.queen_attacks(square) | chess.BB_KNIGHT_ATTACKS[square] def cyril_attacks(self, square): return self.rook_attacks(square) | chess.BB_KNIGHT_ATTACKS[quare] def eve_attacks(self, square): return self.bishop_attacks(square) | chess.BB_KNIGHT_ATTACKS[square] def is_pseudo_legal(self, move): from_square = move.from_square to_square = move.to_square piece = self.piece_at(from_square) if not piece or piece.color != self.turn: return False if self.occupied_co[self.turn] & chess.BB_SQUARES[to_square]: return False if self.is_castling(move): return True if piece.piece_type == AMAZON: return bool(self.amazon_attacks(from_square) & chess.BB_SQUARES[to_square]) elif piece.piece_type == CYRIL: return bool(self.cyril_attacks(from_square) & chess.BB_SQUARES[to_square]) elif piece.piece_type == EVE: return bool(self.eve_attacks(from_square) & chess.BB_SQUARES[to_square]) else: return super().is_pseudo_legal(move) def is_legal(self, move): if not self.is_pseudo_legal(move): return False from_square = move.from_square to_square = move.to_square piece = self.piece_at(from_square) captured_piece = self.piece_at(to_square) # Kontrola pro všechny figury: nelze brát figuru stejné barvy if captured_piece and captured_piece.color == piece.color: return False # Dočasně provést tah self.clear_square(from_square) self._set_piece_at(to_square, piece.piece_type, piece.color) # Najít pozici krále king_square = to_square if piece.piece_type == chess.KING else self.king(self.turn) # Kontrola, zda je král v šachu po tahu is_check = self._is_attacked_by(not self.turn, king_square) if king_square is not None else False # Vrátit pozici do původního stavu self.clear_square(to_square) self._set_piece_at(from_square, piece.piece_type, piece.color) if captured_piece: self._set_piece_at(to_square, captured_piece.piece_type, captured_piece.color) return not is_check def _is_attacked_by(self, color, square): attackers = self.attackers(color, square) return bool(attackers) def attackers(self, color: Color, square: chess.Square) -> Bitboard: if square is None: return chess.BB_EMPTY attackers = chess.BB_EMPTY occupied = self.occupied occupied_co = self.occupied_co[color] # Jezdci attackers |= chess.BB_KNIGHT_ATTACKS[square] & self.knights & occupied_co # Král attackers |= chess.BB_KING_ATTACKS[square] & self.kings & occupied_co # Pěšci if color == chess.WHITE: attackers |= chess.BB_PAWN_ATTACKS[chess.BLACK][square] & self.pawns & occupied_co else: attackers |= chess.BB_PAWN_ATTACKS[chess.WHITE][square] & self.pawns & occupied_co # Střelcové útoky (včetně dam a amazonek) bishop_attacks = chess.BB_DIAG_ATTACKS[square][occupied & chess.BB_DIAG_MASKS[square]] attackers |= bishop_attacks & ((self.bishops | self.queens) & occupied_co) # Věžové útoky (včetně dam, amazonek a cyrilů) rook_attacks = ( chess.BB_RANK_ATTACKS[square][occupied & chess.BB_RANK_MASKS[square]] | chess.BB_FILE_ATTACKS[square][occupied & chess.BB_FILE_MASKS[square]] ) attackers |= rook_attacks & ((self.rooks | self.queens) & occupied_co) # Amazonky (Dáma + Jezdec) amazons = self.amazons_white if color == chess.WHITE else self.amazons_black amazon_attacks = bishop_attacks | rook_attacks | chess.BB_KNIGHT_ATTACKS[square] attackers |= amazon_attacks & amazons # Cyrilové (Věž + Jezdec) cyrils = self.cyrils_white if color == chess.WHITE else self.cyrils_black cyril_attacks = rook_attacks | chess.BB_KNIGHT_ATTACKS[square] attackers |= cyril_attacks & cyrils # Evy (Střelec + Jezdec) eves = self.eves_white if color == chess.WHITE else self.eves_black eve_attacks = bishop_attacks | chess.BB_KNIGHT_ATTACKS[square] attackers |= eve_attacks & eves return attackers def push(self, move): if not self.is_legal(move): raise ValueError(f"Move {move} is not legal in position {self.fen()}") piece = self.piece_at(move.from_square) captured_piece = self.piece_at(move.to_square) self.clear_square(move.from_square) self.clear_square(move.to_square) self._set_piece_at(move.to_square, piece.piece_type, piece.color) self.turn = not self.turn self.move_stack.append((move, captured_piece)) def pop(self): if not self.move_stack: return None move, captured_piece = self.move_stack.pop() piece = self.piece_at(move.to_square) self.clear_square(move.from_square) self.clear_square(move.to_square) self._set_piece_at(move.from_square, piece.piece_type, piece.color) if captured_piece: self._set_piece_at(move.to_square, captured_piece.piece_type, captured_piece.color) self.turn = not self.turn return move def is_check(self): king_square = self.king(self.turn) if king_square is None: return False is_check = self._is_attacked_by(not self.turn, king_square) return is_check def is_checkmate(self): if not self.is_check(): return False legal_moves = list(self.generate_legal_moves()) return len(legal_moves) == 0 def is_game_over(self): return self.is_checkmate() or self.is_stalemate() or self.is_insufficient_material() def is_stalemate(self): if self.is_check(): return False legal_moves = list(self.generate_legal_moves()) return len(legal_moves) == 0 def is_insufficient_material(self): return (self.pawns | self.rooks | self.queens | self.amazons_white | self.amazons_black | self.cyrils_white | self.cyrils_black | self.eves_white | self.eves_black) == 0 and ( chess.popcount(self.occupied) <= 3 ) def generate_legal_moves(self, from_mask=chess.BB_ALL, to_mask=chess.BB_ALL): for move in self.generate_pseudo_legal_moves(from_mask, to_mask): if self.is_legal(move): yield move def debug_amazons(self): pass def debug_cyrils(self): pass def debug_eves(self): pass def piece_symbol(self, piece): 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 == EVE: return 'E' if piece.color == chess.WHITE else 'e' return piece.symbol() def piece_type_at(self, square): if (self.amazons_white | self.amazons_black) & chess.BB_SQUARES[square]: return AMAZON if (self.cyrils_white | self.cyrils_black) & chess.BB_SQUARES[square]: return CYRIL if (self.eves_white | self.eves_black) & chess.BB_SQUARES[square]: return EVE return super().piece_type_at(square) def color_at(self, square): if self.amazons_white & chess.BB_SQUARES[square]: return chess.WHITE if self.amazons_black & chess.BB_SQUARES[square]: return chess.BLACK if self.cyrils_white & chess.BB_SQUARES[square]: return chess.WHITE if self.cyrils_black & chess.BB_SQUARES[square]: return chess.BLACK if self.eves_white & chess.BB_SQUARES[square]: return chess.WHITE if self.eves_black & chess.BB_SQUARES[square]: return chess.BLACK return super().color_at(square) @property def legal_moves(self): return list(self.generate_legal_moves()) def __str__(self): builder = [] for square in chess.SQUARES_180: piece = self.piece_at(square) symbol = self.piece_symbol(piece) if piece else '.' builder.append(symbol) if chess.square_file(square) == 7: if square != chess.H1: builder.append('\n') return ''.join(builder) def format_time(seconds): 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 print_elapsed_time(stop_event, start_time): while not stop_event.is_set(): elapsed_time = time.time() - start_time print(f"\rUplynulý čas: {format_time(elapsed_time)}", end="", flush=True) time.sleep(1) def simplify_fen(fen): return ' '.join(fen.split()[:4]) def calculate_optimal_moves(start_fen: str) -> Dict[str, Tuple[int, str]]: print("Funkce calculate_optimal_moves byla zavolána8") print(f"Počáteční FEN: {start_fen}") board = CustomBoard(start_fen) POZ = {1: simplify_fen(start_fen)} AR = {simplify_fen(start_fen): {'used': 0, 'to_end': None, 'depth': 0, 'type': 'normal', 'parent': None}} N = 1 M = 0 start_time = time.time() current_depth = 0 positions_at_depth = {0: 0} depth_start_time = start_time stop_event = threading.Event() timer_thread = threading.Thread(target=print_elapsed_time, args=(stop_event, start_time)) timer_thread.start() try: print("Začínám generovat pozice...") print("Počáteční pozice:7") print_board(start_fen) depth_1_positions = [] # Seznam pro ukládání pozic v hloubce 1 # Generate all positions while M < N: M += 1 current_fen = POZ[M] board.set_custom_fen(current_fen) simplified_current_fen = simplify_fen(current_fen) current_depth = AR[simplified_current_fen]['depth'] if current_depth not in positions_at_depth: positions_at_depth[current_depth] = 0 if current_depth > 0: depth_time = time.time() - depth_start_time total_time = time.time() - start_time print(f"\nHloubka {current_depth - 1}: {positions_at_depth[current_depth - 1]} pozic, " f"Čas hloubky: {format_time(depth_time)} / Celkový čas: {format_time(total_time)}") if current_depth == 1: print("Všechny pozice v hloubce 1:") for pos in depth_1_positions: print_board(pos) print() depth_start_time = time.time() positions_at_depth[current_depth] += 1 if current_depth == 1: depth_1_positions.append(current_fen) if AR[simplified_current_fen]['used'] == 0: AR[simplified_current_fen]['used'] = 1 legal_moves = list(board.legal_moves) for move in legal_moves: board.push(move) POZ2 = board.fen() simplified_POZ2 = simplify_fen(POZ2) if simplified_POZ2 not in AR: N += 1 POZ[N] = simplified_POZ2 AR[simplified_POZ2] = { 'used': 0, 'to_end': None, 'depth': current_depth + 1, 'type': 'normal', 'parent': simplified_current_fen } board.pop() # Print last depth depth_time = time.time() - depth_start_time total_time = time.time() - start_time print(f"\nHloubka {current_depth}: {positions_at_depth[current_depth]} pozic, " f"Čas hloubky: {format_time(depth_time)} / Celkový čas: {format_time(total_time)}") print(f"Příklad pozice v hloubce {current_depth}:") print_board(current_fen) print(f"Generování pozic dokončeno. Celkový počet pozic: {N}") # Initial evaluation print("\nZačínám počáteční ohodnocení...") F_checkmate = 0 F_stalemate = 0 F_drawing = 0 F_check = 0 F_normal = 0 for i in range(1, N + 1): current_fen = POZ[i] board.set_custom_fen(current_fen) simplified_current_fen = simplify_fen(current_fen) if board.is_checkmate(): AR[simplified_current_fen]['to_end'] = -1000 AR[simplified_current_fen]['type'] = 'checkmate' F_checkmate += 1 elif board.is_stalemate(): AR[simplified_current_fen]['to_end'] = 0 AR[simplified_current_fen]['type'] = 'stalemate' F_stalemate += 1 elif board.is_insufficient_material(): AR[simplified_current_fen]['to_end'] = 0 AR[simplified_current_fen]['type'] = 'drawing' F_drawing += 1 elif board.is_check(): AR[simplified_current_fen]['to_end'] = None AR[simplified_current_fen]['type'] = 'check' F_check += 1 else: AR[simplified_current_fen]['to_end'] = None AR[simplified_current_fen]['type'] = 'normal' F_normal += 1 print(f"Počet pozic v matu je {F_checkmate}") print(f"Počet pozic v patu je {F_stalemate}") print(f"Počet pozic v remíze je {F_drawing}") print(f"Počet pozic v šachu je {F_check}") print(f"Počet normálních pozic je {F_normal}") # Iterative evaluation print("\nZačínám iterativní ohodnocení...6") uroven = 0 while True: uroven += 1 level_start_time = time.time() print(f"Výpočet v úrovni {uroven}") changed = False current_level_positions = 0 for i in range(1, N + 1): current_fen = POZ[i] board.set_custom_fen(current_fen) simplified_current_fen = simplify_fen(current_fen) if AR[simplified_current_fen]['to_end'] is None or AR[simplified_current_fen]['to_end'] == 0: hod = -2000 for move in board.legal_moves: board.push(move) POZ2 = board.fen() simplified_POZ2 = simplify_fen(POZ2) if simplified_POZ2 in AR and AR[simplified_POZ2]['to_end'] is not None: hod2 = -AR[simplified_POZ2]['to_end'] if hod2 > hod: hod = hod2 board.pop() if hod == 1001 - uroven: new_to_end = 1000 - uroven new_type = 'winning' elif hod == -1001 + uroven: new_to_end = -1000 + uroven new_type = 'losing' elif hod == 0: new_to_end = 0 new_type = 'drawing' else: new_to_end = None new_type = None if new_to_end is not None and (AR[simplified_current_fen]['to_end'] != new_to_end or AR[simplified_current_fen]['type'] != new_type): AR[simplified_current_fen]['to_end'] = new_to_end AR[simplified_current_fen]['type'] = new_type changed = True current_level_positions += 1 level_end_time = time.time() total_elapsed_time = level_end_time - start_time level_elapsed_time = level_end_time - level_start_time print(f"Nalezeno {current_level_positions} pozic v úrovni {uroven}") print(f"Čas úrovně: {format_time(level_elapsed_time)} / Celkový čas: {format_time(total_elapsed_time)}") if not changed: print("Hodnocení ukončeno - žádné další změny.5") break print(f"Celkem nalezeno {sum(1 for data in AR.values() if data['to_end'] is not None)} ohodnocených pozic") print(f"Celkem nalezeno {sum(1 for data in AR.values() if data['to_end'] is None)} neohodnocených pozic") print("\nVýpočet dokončen.") # Print optimal moves with parent check current_fen = start_fen simplified_current_fen = simplify_fen(current_fen) optimal_moves = [simplified_current_fen] while True: board = CustomBoard(current_fen) if board.is_checkmate(): print("Mat detekován!4") break if board.is_insufficient_material(): print("Nedostatečný materiál detekován!") break half_move_clock = current_fen.split()[-2] if half_move_clock != '-' and int(half_move_clock) >= 100: print("Remíza pravidlem 50 tahů detekována!") break if simplified_current_fen not in AR: print(f"Pozice {simplified_current_fen} není v AR.") break current_value = AR[simplified_current_fen]['to_end'] if current_value == 0: print("Remíza dosažena!") break hod = -2000 if current_value > 0 else 2000 best_fen = None for move in board.legal_moves: board.push(move) POZ2 = board.fen() simplified_POZ2 = simplify_fen(POZ2) if simplified_POZ2 in AR and AR[simplified_POZ2]['parent'] == simplified_current_fen: hod2 = -AR[simplified_POZ2]['to_end'] if current_value > 0: # Silnější hráč if hod2 > hod: hod = hod2 best_fen = simplified_POZ2 else: # Slabší hráč if hod2 < hod: hod = hod2 best_fen = simplified_POZ2 board.pop() if best_fen is None: print("Žádný další tah nebyl nalezen.") break optimal_moves.append(best_fen) current_fen = best_fen simplified_current_fen = simplify_fen(current_fen) print("\nOptimální tahy3:") for fen in optimal_moves: print_board(fen) hodnota = AR[simplify_fen(fen)]['to_end'] typ_pozice = AR[simplify_fen(fen)]['type'] print(f"Hodnota: {hodnota}, Typ: {typ_pozice}") print(fen) print("\n") return {fen: (data['to_end'], data['type']) for fen, data in AR.items() if data['to_end'] is not None} finally: stop_event.set() timer_thread.join() # Helper function to print the board def print_board(fen): board = CustomBoard(fen) print(board) # Najděte nejmenší kladnou hodnotu to_end ve všech FEN záznamech v AR def find_min_positive_value(AR): min_positive_value = float('inf') min_fen = None for fen, (value, type_pozice) in AR.items(): if value is not None and value > 0 and value < min_positive_value: min_positive_value = value min_fen = fen if min_positive_value == float('inf'): print("Žádná kladná hodnota nebyla nalezena.") else: print(f"Nejmenší kladná hodnota: {min_positive_value}, FEN: {min_fen}") # # Main execution # # Main execution # if __name__ == "__main__": # start_fen = "7K/8/k1P5/7p/8/8/8/8 w - - 0 1" # start_fen = "7K/8/8/8/8/k7/8/7A w - - 0 1" # # start_fen = "7K/8/8/2a5/8/1k6/8/7A w - - 0 1" # start_fen = "7K/8/k1P5/7p/8/8/8/8 w - - 0 1" # start_fen = "6K1/3E4/8/8/8/k7/8/8 w - - 0 1" # start_fen = "8/5A2/8/8/2K5/8/ka6/8 w - - 0 1" # start_fen = "8/8/8/2k5/8/8/1K6/3Q4 w - - 0 1" # start_fen = "8/7k/7r/8/8/RK6/8/8 w - - 0 1" # AR = calculate_optimal_moves(start_fen) # find_min_positive_value(AR) def print_20_successors(AR, start_fen): print("\nVýpis 20 následníků počáteční pozice:") simplified_start_fen = simplify_fen(start_fen) if simplified_start_fen not in AR: print(f"Počáteční pozice {simplified_start_fen} nebyla nalezena v AR.") return count = 0 for fen, (hodnota, typ_pozice) in AR.items(): if count >= 20: break print(f"\nFEN: {fen}") print("Hodnoty:") print(f" Hodnota: {hodnota}") print(f" Typ pozice: {typ_pozice}") print_board(fen) count += 1 if __name__ == "__main__": start_fen = "8/8/8/2k5/8/8/1K6/1Q6 w - - 0 1" start_fen = "8/7k/8/8/8/1K6/8/1Q6 w - - 0 1" start_fen = "8/7k/8/8/8/1K6/8/1A6 w - - 0 1" start_fen = "8/7k/8/8/8/1K6/1A6/8 w - - 0 1" start_fen = "8/8/8/5k2/8/1K6/8/4A3 w - - 0 1" start_fen = "8/8/8/5k2/8/8/K7/2A5 w - - 0 1" AR = calculate_optimal_moves(start_fen) find_min_positive_value(AR) # Přidáno: Volání nové funkce pro výpis 20 následníků # print_20_successors(AR, start_fen) # print("\nVýsledky:") # for hodnota in range(-996, -1001, -1): # Generuje hodnoty -996, -997, -998, -999, -1000 # for fen, (fen_hodnota, typ_pozice) in AR.items(): # if fen_hodnota == hodnota: # print(f"FEN: {fen}") # print(f"Hodnota: {fen_hodnota}") # print(f"Typ pozice: {typ_pozice}") # temp_board = CustomBoard(fen) # if temp_board.is_checkmate(): # print("Stav: Mat") # elif temp_board.is_stalemate(): # print("Stav: Pat") # elif temp_board.is_insufficient_material(): # print("Stav: Nedostatečný materiál") # elif temp_board.is_check(): # print("Stav: Šach") # else: # print("Stav: Normální pozice") # print_board(fen) # print() # Print optimal moves # Print optimal moves current_fen = start_fen simplified_current_fen = simplify_fen(current_fen) simplified_current_fen1 = simplified_current_fen optimal_moves = [start_fen] while True: board = CustomBoard(current_fen) if board.is_checkmate(): print("Mat detekován!2") break # Opravená část half_move_clock = current_fen.split()[-2] if board.is_insufficient_material() or (half_move_clock != '-' and int(half_move_clock) >= 100): if board.is_insufficient_material(): print("Nedostatečný materiál detekován!") else: print("Remíza pravidlem 50 tahů detekována!") AR[simplified_current_fen] = (0, 'drawing') # Aktualizujeme AR pro tuto pozici break if simplified_current_fen not in AR: print(f"Pozice {simplified_current_fen} není v AR.") break current_value = AR[simplified_current_fen][0] if current_value == 0: print("Remíza dosažena!") break hod = -2000 if current_value > 0 else 2000 best_fen = None for move in board.legal_moves: board.push(move) POZ2 = board.fen() simplified_POZ2 = simplify_fen(POZ2) if simplified_POZ2 in AR: hod2 = -AR[simplified_POZ2][0] if current_value > 0: # Silnější hráč if hod2 > hod: hod = hod2 best_fen = simplified_POZ2 else: # Slabší hráč if hod2 < hod: hod = hod2 best_fen = simplified_POZ2 board.pop() if best_fen is None: print("Žádný další tah nebyl nalezen.") break optimal_moves.append(best_fen) current_fen = best_fen simplified_current_fen = simplify_fen(current_fen) print("\nOptimální tahy1:") for fen in reversed(optimal_moves): print_board(fen) hodnota, typ_pozice = AR[simplify_fen(fen)] print(f"Hodnota: {hodnota}, Typ: {typ_pozice}") print(fen) print("\n")
The output is here:

Output:
Mat detekován!2 Optimální tahy1: ........ .......k .....A.. ........ ........ ........ K....... ........ Hodnota: -1000, Typ: checkmate 8/7k/5A2/8/8/8/K7/8 b - - ........ .......k ........ ....A... ........ ........ K....... ........ Hodnota: 999, Typ: winning 8/7k/8/4A3/8/8/K7/8 w - - ........ ........ ......k. ....A... ........ ........ K....... ........ Hodnota: -998, Typ: losing 8/8/6k1/4A3/8/8/K7/8 b - - ........ ........ ......k. ........ ........ ........ K....... A....... Hodnota: 997, Typ: winning 8/8/6k1/8/8/8/K7/A7 w - - ........ ........ ........ .....k.. ........ ........ K....... A....... Hodnota: -994, Typ: losing 8/8/8/5k2/8/8/K7/A7 b - - ........ ........ ........ .....k.. ........ ........ K....... ..A..... Hodnota: 993, Typ: winning 8/8/8/5k2/8/8/K7/2A5 w - - 0 1
The bad thing is that it outputs numbers like -994 and then it jumps to 997.
The fix amounts to outputting continuous chain of numbers like -994,995,-996,997,-998,999,-1000.
Once fixed I can offer around 100$.


This forum uses Lukasz Tkacz MyBB addons.
Forum use Krzysztof "Supryk" Supryczynski addons.