Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import chess
- import math
- import time
- from copy import deepcopy
- def knight_moves():
- return [(2, 1), (1, 2), (-1, 2), (-2, 1),
- (-2, -1), (-1, -2), (1, -2), (2, -1)]
- def rook_moves():
- moves = []
- for i in range(1, 8):
- moves.extend([(i, 0), (-i, 0), (0, i), (0, -i)])
- return moves
- def bishop_moves():
- moves = []
- for i in range(1, 8):
- moves.extend([(i, i), (i, -i), (-i, i), (-i, -i)])
- return moves
- def queen_moves():
- return rook_moves() + bishop_moves()
- def amazon_moves():
- return queen_moves() + knight_moves()
- def cyril_moves():
- return rook_moves() + knight_moves()
- def eve_moves():
- return bishop_moves() + knight_moves()
- def print_board(board):
- print(" a b c d e f g h")
- for i in range(8):
- print(f"{8-i} ", end="")
- for j in range(8):
- print(f"{board[i][j]} ", end="")
- print(f"{8-i}")
- print(" a b c d e f g h")
- print()
- def generate_moves(board, piece, row, col):
- size = 8
- moves = []
- if piece.upper() == 'A':
- directions = amazon_moves()
- elif piece.upper() == 'C':
- directions = cyril_moves()
- elif piece.upper() == 'E':
- directions = eve_moves()
- elif piece.upper() == 'K':
- directions = [(-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)]
- else:
- return moves
- for dx, dy in directions:
- new_row, new_col = row + dx, col + dy
- if 0 <= new_row < size and 0 <= new_col < size:
- target = board[new_row][new_col]
- if piece.upper() == 'K' and target.upper() == 'K':
- continue
- if piece.upper() in ['A', 'C', 'E'] and (dx, dy) not in knight_moves():
- blocked = False
- step_x = 1 if dx > 0 else (-1 if dx < 0 else 0)
- step_y = 1 if dy > 0 else (-1 if dy < 0 else 0)
- check_x, check_y = row + step_x, col + step_y
- while (check_x, check_y) != (new_row, new_col):
- if board[check_x][check_y] != '.':
- blocked = True
- break
- check_x += step_x
- check_y += step_y
- if blocked:
- continue
- if target == '.':
- moves.append((new_row, new_col))
- elif target.islower() != piece.islower():
- moves.append((new_row, new_col))
- return moves
- def board_to_fen(board):
- fen_rows = []
- for row in board:
- fen_row = ""
- empty_count = 0
- for cell in row:
- if cell == '.':
- empty_count += 1
- else:
- if empty_count > 0:
- fen_row += str(empty_count)
- empty_count = 0
- fen_row += cell
- if empty_count > 0:
- fen_row += str(empty_count)
- fen_rows.append(fen_row)
- return "/".join(fen_rows) + " w - - 0 1"
- def fen_to_board(fen):
- fen_board = fen.split()[0]
- board = []
- for row_fen in fen_board.split('/'):
- row = []
- for char in row_fen:
- if char.isdigit():
- row.extend(['.'] * int(char))
- else:
- row.append(char)
- board.append(row)
- return board
- def is_under_attack(board, row, col, by_white):
- for i in range(8):
- for j in range(8):
- piece = board[i][j]
- if piece == '.' or piece.isupper() != by_white:
- continue
- if piece.upper() in ['A', 'C', 'E']:
- moves = generate_moves(board, piece, i, j)
- if (row, col) in moves:
- return True
- elif piece.upper() == 'K':
- if abs(i - row) <= 1 and abs(j - col) <= 1 and (i != row or j != col):
- return True
- return False
- def get_all_legal_moves(board, white_to_move):
- legal_moves = []
- for i in range(8):
- for j in range(8):
- piece = board[i][j]
- if piece == '.' or piece.isupper() != white_to_move:
- continue
- if piece.upper() in ['A', 'C', 'E', 'K']:
- possible_moves = generate_moves(board, piece, i, j)
- for new_row, new_col in possible_moves:
- test_board = deepcopy(board)
- test_board[new_row][new_col] = piece
- test_board[i][j] = '.'
- king_pos = None
- for ki in range(8):
- for kj in range(8):
- if test_board[ki][kj] == ('K' if white_to_move else 'k'):
- king_pos = (ki, kj)
- break
- if king_pos:
- break
- if king_pos and not is_under_attack(test_board, king_pos[0], king_pos[1], not white_to_move):
- legal_moves.append(((i, j), (new_row, new_col)))
- return legal_moves
- def is_check_or_mate(fen, white_to_move=True):
- try:
- board = fen_to_board(fen)
- white_king = None
- black_king = None
- for i in range(8):
- for j in range(8):
- if board[i][j] == 'K':
- white_king = (i, j)
- elif board[i][j] == 'k':
- black_king = (i, j)
- if not white_king or not black_king:
- return {
- 'checkmate': False,
- 'stalemate': False,
- 'insufficient_material': False,
- 'seventyfive_moves': False,
- 'check': False,
- 'winner': None
- }
- current_king = white_king if white_to_move else black_king
- in_check = is_under_attack(board, current_king[0], current_king[1], not white_to_move)
- legal_moves = get_all_legal_moves(board, white_to_move)
- if not legal_moves:
- if in_check:
- winner = 'black' if white_to_move else 'white'
- return {
- 'checkmate': True,
- 'stalemate': False,
- 'insufficient_material': False,
- 'seventyfive_moves': False,
- 'check': True,
- 'winner': winner
- }
- else:
- return {
- 'checkmate': False,
- 'stalemate': True,
- 'insufficient_material': False,
- 'seventyfive_moves': False,
- 'check': False,
- 'winner': None
- }
- return {
- 'checkmate': False,
- 'stalemate': False,
- 'insufficient_material': False,
- 'seventyfive_moves': False,
- 'check': in_check,
- 'winner': None
- }
- except Exception:
- return {
- 'checkmate': False,
- 'stalemate': False,
- 'insufficient_material': False,
- 'seventyfive_moves': False,
- 'check': False,
- 'winner': None
- }
- def create_successors(index, state, all_states, seen_fens):
- board = state['board']
- new_states = []
- new_outputs = []
- current_player_white = index % 2 == 0
- legal_moves = get_all_legal_moves(board, current_player_white)
- for ((from_row, from_col), (to_row, to_col)) in legal_moves:
- piece = board[from_row][from_col]
- new_board = deepcopy(board)
- new_board[to_row][to_col] = piece
- new_board[from_row][from_col] = '.'
- fen = board_to_fen(new_board)
- if fen not in seen_fens:
- seen_fens.add(fen)
- new_state = {
- 'radek': len(all_states),
- 'N': [],
- 'P': [index],
- 'FEN': fen,
- 'board': new_board,
- 'to_mate': None,
- 'to_end': None
- }
- all_states.append(new_state)
- new_states.append(new_state['radek'])
- new_outputs.append(f"{new_state['radek']}({state['radek']})")
- else:
- for s in all_states:
- if s['FEN'] == fen:
- if index not in s['P']:
- s['P'].append(index)
- new_states.append(s['radek'])
- break
- if new_outputs:
- max_radek = max(new_states) if new_states else index
- print(f"\rDepth={index} max={max_radek} : {' '.join(new_outputs[:5])}" +
- (f" ...({len(new_outputs)-5} more)" if len(new_outputs) > 5 else ""),
- end='', flush=True)
- return new_states
- def create_initial_board():
- board = [['.' for _ in range(8)] for _ in range(8)]
- board[7][0] = 'A' # Bílá amazonka na a1
- board[7][7] = 'K' # Bílý král na h1
- board[0][4] = 'k' # Černý král na e8
- return board
- def propagate_values(L):
- print("\nPropaguji hodnoty s minimax logikou...")
- start_time = time.time()
- round_num = 0
- max_rounds = 100
- # Nejdřív označ stavy bez následníků jako koncové
- for state in L:
- if not state['N'] and state['to_end'] is None:
- state['to_mate'] = math.inf
- state['to_end'] = 0
- while round_num < max_rounds:
- round_num += 1
- changed = False
- # Projdi všechny stavy zpětně
- for state in reversed(L):
- if state['to_mate'] is None or state['to_end'] is None:
- if state['N']: # Má následníky
- # Získej hodnoty následníků
- succ_mate_vals = []
- succ_end_vals = []
- for idx in state['N']:
- if idx < len(L):
- succ = L[idx]
- if succ['to_mate'] is not None:
- succ_mate_vals.append(succ['to_mate'])
- if succ['to_end'] is not None:
- succ_end_vals.append(succ['to_end'])
- # KLÍČOVÁ OPRAVA: Minimax logika podle toho, kdo je na tahu
- if succ_mate_vals and state['to_mate'] is None:
- white_to_move = state['radek'] % 2 == 0
- if white_to_move: # Bílý na tahu - hledá minimum (nejrychlejší mat)
- if all(val == math.inf for val in succ_mate_vals):
- new_mate_val = math.inf
- else:
- finite_vals = [val for val in succ_mate_vals if val != math.inf]
- if finite_vals:
- new_mate_val = 1 + min(finite_vals)
- else:
- new_mate_val = math.inf
- else: # Černý na tahu - hledá maximum (nejpomalejší mat)
- finite_vals = [val for val in succ_mate_vals if val != math.inf]
- if finite_vals:
- new_mate_val = 1 + max(finite_vals) # Maximum z konečných hodnot
- else:
- new_mate_val = math.inf # Jen pokud jsou všechny inf
- state['to_mate'] = new_mate_val
- changed = True
- # to_end vždy minimum (nejkratší cesta k jakémukoli konci)
- if succ_end_vals and state['to_end'] is None:
- new_end_val = 1 + min(succ_end_vals)
- state['to_end'] = new_end_val
- changed = True
- elapsed = int(time.time() - start_time)
- hh, rem = divmod(elapsed, 3600)
- mm, ss = divmod(rem, 60)
- states_with_mate = sum(1 for s in L if s['to_mate'] is not None)
- states_with_end = sum(1 for s in L if s['to_end'] is not None)
- print(f"\rPrůchod {round_num}: čas {hh:02d}h{mm:02d}m{ss:02d}s, "
- f"změněno: {changed}, stavů s to_mate: {states_with_mate}/{len(L)}, "
- f"stavů s to_end: {states_with_end}/{len(L)}", end='', flush=True)
- if not changed:
- print("\nŽádné další změny - ukončuji propagaci")
- break
- if all(s['to_mate'] is not None and s['to_end'] is not None for s in L):
- print(f"\nVšechny stavy vyhodnocené po {round_num} průchodech")
- break
- print()
- def find_optimal_path(L):
- print("\n--- Hledání optimální cesty k matu ---")
- if L[0]['to_mate'] is None or L[0]['to_mate'] == math.inf:
- print(f"L[0] nemá cestu k matu (to_mate = {L[0]['to_mate']})")
- return []
- path = []
- current_index = 0
- move_number = 0
- print(f"L[0] má to_mate = {L[0]['to_mate']}, hledám cestu...")
- while True:
- current_state = L[current_index]
- path.append(current_index)
- print(f"\nTah {move_number}: L[{current_index}]")
- print(f"to_mate: {current_state['to_mate']}, to_end: {current_state['to_end']}")
- print_board(current_state['board'])
- if current_state['to_mate'] == 0:
- print("Mat dosažen!")
- break
- if not current_state['N']:
- print("Žádní následníci - konec")
- break
- # OPRAVENÁ LOGIKA: Najdi následníka s hodnotou o 1 menší
- target_value = current_state['to_mate'] - 1
- best_successor = None
- print(f"Hledám následníka s to_mate = {target_value}")
- for succ_idx in current_state['N']:
- succ_state = L[succ_idx]
- print(f" L[{succ_idx}]: to_mate = {succ_state['to_mate']}")
- if succ_state['to_mate'] == target_value:
- best_successor = succ_idx
- break
- if best_successor is None:
- print("CHYBA: Nelze najít následníka s očekávanou hodnotou!")
- print("Dostupní následníci:")
- for succ_idx in current_state['N']:
- succ_state = L[succ_idx]
- print(f" L[{succ_idx}]: to_mate = {succ_state['to_mate']}")
- break
- player = "bílý" if move_number % 2 == 0 else "černý"
- print(f"{player} vybírá L[{best_successor}] s to_mate={target_value}")
- current_index = best_successor
- move_number += 1
- if move_number > 20:
- print("Příliš mnoho tahů - přerušuji")
- break
- return path
- def main():
- print("=== Chess Endgame Analyzer ===")
- print("Figury: A=Amazonka(Q+N), C=Cyril(R+N), E=Eve(B+N), K=Král")
- print("Mat = král v šachu + žádné legální tahy\n")
- board = create_initial_board()
- start_fen = board_to_fen(board)
- print("Počáteční pozice:")
- print_board(board)
- print(f"Start FEN: {start_fen}\n")
- L = []
- seen_fens = set()
- seen_fens.add(start_fen)
- L.append({
- 'radek': 0,
- 'N': [],
- 'P': [],
- 'FEN': start_fen,
- 'board': board,
- 'to_mate': None,
- 'to_end': None
- })
- print("Generuji následníky...")
- start_generation = time.time()
- i = 0
- max_states = 3000
- while i < len(L) and len(L) < max_states:
- L[i]['N'] = create_successors(i, L[i], L, seen_fens)
- i += 1
- if i % 200 == 0:
- elapsed = time.time() - start_generation
- print(f"\nZpracováno {i} stavů, celkem {len(L)} stavů, čas: {elapsed:.1f}s")
- generation_time = time.time() - start_generation
- print(f"\nVygenerováno {len(L)} stavů za {generation_time:.1f}s")
- print("\nHledám koncové stavy...")
- end_states_found = 0
- for state in L:
- white_to_move = state['radek'] % 2 == 0
- check_result = is_check_or_mate(state['FEN'], white_to_move)
- if check_result['checkmate']:
- state['to_mate'] = 0
- state['to_end'] = 0
- end_states_found += 1
- winner = check_result.get('winner', 'neznámý')
- player_on_move = "bílý" if white_to_move else "černý"
- print(f"Mat nalezen ve stavu L[{state['radek']}] - {player_on_move} je matován, vyhrál {winner}")
- elif (check_result['stalemate'] or
- check_result['insufficient_material'] or
- check_result['seventyfive_moves']):
- state['to_mate'] = math.inf
- state['to_end'] = 0
- end_states_found += 1
- print(f"Nalezeno {end_states_found} koncových stavů")
- propagate_values(L)
- print(f"\n=== VÝSLEDKY ===")
- print(f"Počáteční stav L[0]:")
- print(f" to_mate: {L[0]['to_mate']}")
- print(f" to_end: {L[0]['to_end']}")
- print(f" Počet následníků: {len(L[0]['N'])}")
- path = find_optimal_path(L)
- if path:
- print(f"\nOptimální cesta: {' -> '.join(map(str, path))}")
- if len(L) > 22:
- print(f"\nL[22] = {L[22]}")
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement