Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3
- import time
- import threading
- import sys
- from math import inf
- # Globální konstanty – pohyby jezdce (relativní souřadnice)
- knight_moves = [(2,1),(2,-1),(-2,1),(-2,-1),(1,2),(1,-2),(-1,2),(-1,-2)]
- # Globální proměnné pro sledování času
- running = False
- start_time = 0
- ###############################################################################
- # Funkce pro výpis času v samostatném vlákně
- ###############################################################################
- def time_reporter():
- """Funkce pro výpis aktuálního času každou sekundu na stejném řádku."""
- global running, start_time
- while running:
- elapsed = time.time() - start_time
- hrs = int(elapsed // 3600)
- mins = int((elapsed % 3600) // 60)
- secs = int(elapsed % 60)
- # Použijeme \r pro návrat na začátek řádku a přepsání předchozího výpisu
- sys.stdout.write(f"\r[INFO] Uplynulý čas: {hrs:02d}h {mins:02d}m {secs:02d}s")
- sys.stdout.flush()
- time.sleep(1)
- ###############################################################################
- # Třída Board – reprezentuje šachovnici a umí ji inicializovat z FEN řetězce.
- ###############################################################################
- class Board:
- def __init__(self, fen=None):
- """Inicializace šachovnice; pokud je zadán FEN, nastaví pozici podle něj."""
- self.grid = [[' ' for _ in range(8)] for _ in range(8)]
- self.to_move = 'w'
- self.castling_rights = set() # např. {'K','Q','k','q'}
- self.en_passant = None # (row, col) nebo None
- self.halfmove_clock = 0
- self.fullmove_number = 1
- if fen:
- self.set_fen(fen)
- def set_fen(self, fen):
- """Nastaví šachovnici podle FEN řetězce."""
- parts = fen.split()
- while len(parts) < 6:
- parts.append('0')
- board_part, turn_part = parts[0], parts[1]
- castling_part = parts[2] if len(parts) > 2 else '-'
- en_passant_part = parts[3] if len(parts) > 3 else '-'
- halfmove = parts[4] if len(parts) > 4 else '0'
- fullmove = parts[5] if len(parts) > 5 else '1'
- self.grid = [['.' for _ in range(8)] for _ in range(8)]
- ranks = board_part.split('/')
- # FEN řady začínají od horní (8.) a jdou dolů
- for rank_idx, rank_str in enumerate(ranks):
- file_idx = 0
- for ch in rank_str:
- if ch.isdigit():
- file_idx += int(ch)
- else:
- self.grid[rank_idx][file_idx] = ch
- file_idx += 1
- self.to_move = 'w' if turn_part == 'w' else 'b'
- self.castling_rights = set() if castling_part == '-' else set(castling_part)
- self.en_passant = None
- if en_passant_part != '-' and en_passant_part != '':
- file = ord(en_passant_part[0]) - ord('a')
- rank = int(en_passant_part[1])
- ri = 8 - rank
- fi = file
- if 0 <= ri < 8 and 0 <= fi < 8:
- self.en_passant = (ri, fi)
- try:
- self.halfmove_clock = int(halfmove)
- except:
- self.halfmove_clock = 0
- try:
- self.fullmove_number = int(fullmove)
- except:
- self.fullmove_number = 1
- def copy(self):
- """Vytvoří hlubokou kopii šachovnice."""
- new_board = Board()
- new_board.grid = [row.copy() for row in self.grid]
- new_board.to_move = self.to_move
- new_board.castling_rights = set(self.castling_rights)
- new_board.en_passant = None if self.en_passant is None else (self.en_passant[0], self.en_passant[1])
- new_board.halfmove_clock = self.halfmove_clock
- new_board.fullmove_number = self.fullmove_number
- return new_board
- def display(self):
- """Vrátí textovou reprezentaci šachovnice."""
- lines = []
- for ri in range(8):
- line = ""
- for fi in range(8):
- line += self.grid[ri][fi] + " "
- lines.append(line)
- return "\n".join(lines)
- ###############################################################################
- # Funkce pro detekci šachu, generování tahů a jejich provádění
- ###############################################################################
- def find_king(board, side):
- """Najde pozici krále pro stranu 'w' nebo 'b'."""
- target = 'K' if side=='w' else 'k'
- for r in range(8):
- for c in range(8):
- if board.grid[r][c] == target:
- return (r, c)
- return None
- def is_square_attacked(board, r, c, by_side):
- """Zjistí, zda je pole (r,c) napadeno stranou by_side."""
- # Útoky pěšcem
- if by_side == 'b':
- if r+1 < 8 and c-1 >= 0 and board.grid[r+1][c-1] == 'p': return True
- if r+1 < 8 and c+1 < 8 and board.grid[r+1][c+1] == 'p': return True
- else:
- if r-1 >= 0 and c-1 >= 0 and board.grid[r-1][c-1] == 'P': return True
- if r-1 >= 0 and c+1 < 8 and board.grid[r-1][c+1] == 'P': return True
- # Útoky jezdcem a dalšími s jezdcovým pohybem (N, A, C, E)
- enemy_knights = ['n','a','c','e'] if by_side=='b' else ['N','A','C','E']
- for dr, dc in knight_moves:
- nr, nc = r+dr, c+dc
- if 0<=nr<8 and 0<=nc<8 and board.grid[nr][nc] in enemy_knights:
- return True
- # Útoky po řadách/sloupcích (R, Q, E, A)
- enemy_rook_like = ['r','q','e','a'] if by_side=='b' else ['R','Q','E','A']
- for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:
- nr, nc = r+dr, c+dc
- while 0<=nr<8 and 0<=nc<8:
- if board.grid[nr][nc] != '.':
- if board.grid[nr][nc] in enemy_rook_like:
- return True
- break
- nr += dr; nc += dc
- # Útoky diagonálně (B, Q, C, A)
- enemy_bishop_like = ['b','q','c','a'] if by_side=='b' else ['B','Q','C','A']
- for dr, dc in [(1,1),(1,-1),(-1,1),(-1,-1)]:
- nr, nc = r+dr, c+dc
- while 0<=nr<8 and 0<=nc<8:
- if board.grid[nr][nc] != '.':
- if board.grid[nr][nc] in enemy_bishop_like:
- return True
- break
- nr += dr; nc += dc
- # Sousední král
- enemy_king = 'k' if by_side=='b' else 'K'
- for dr in [-1,0,1]:
- for dc in [-1,0,1]:
- if dr==0 and dc==0: continue
- nr, nc = r+dr, c+dc
- if 0<=nr<8 and 0<=nc<8 and board.grid[nr][nc] == enemy_king:
- return True
- return False
- def is_in_check(board, side):
- """Zjistí, zda je král strany side ('w' nebo 'b') v šachu."""
- king_pos = find_king(board, side)
- if not king_pos:
- return False
- kr, kc = king_pos
- enemy_side = 'b' if side=='w' else 'w'
- return is_square_attacked(board, kr, kc, enemy_side)
- def generate_pseudo_moves(board, side):
- """Generuje všechny pseudolegální tahy pro stranu side ('w' nebo 'b')."""
- moves = []
- enemy = 'b' if side=='w' else 'w'
- is_white = (side=='w')
- pawn_dir = -1 if is_white else 1
- start_rank = 6 if is_white else 1
- promote_rank = 0 if is_white else 7
- for r in range(8):
- for c in range(8):
- piece = board.grid[r][c]
- if piece == '.': continue
- if is_white and not piece.isupper(): continue
- if not is_white and not piece.islower(): continue
- pt = piece.upper()
- if pt == 'P':
- nr = r + pawn_dir
- if 0<=nr<8 and board.grid[nr][c]=='.':
- if nr==promote_rank:
- for promo in ['Q','R','B','N','A','E','C']:
- moves.append((r, c, nr, c, promo if is_white else promo.lower(), None))
- else:
- moves.append((r, c, nr, c, None, None))
- if r==start_rank and board.grid[r+pawn_dir*2][c]=='.' and board.grid[r+pawn_dir][c]=='.':
- moves.append((r, c, r+pawn_dir*2, c, None, 'double'))
- for dc in [-1,1]:
- nc = c + dc
- if 0<=nc<8 and 0<=nr<8:
- if board.grid[nr][nc] != '.' and ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
- if nr==promote_rank:
- for promo in ['Q','R','B','N','A','E','C']:
- moves.append((r, c, nr, nc, promo if is_white else promo.lower(), None))
- else:
- moves.append((r, c, nr, nc, None, None))
- if board.en_passant == (nr, nc):
- moves.append((r, c, nr, nc, None, 'enpassant'))
- elif pt == 'K':
- for dr in [-1,0,1]:
- for dc in [-1,0,1]:
- if dr==0 and dc==0: continue
- nr, nc = r+dr, c+dc
- if 0<=nr<8 and 0<=nc<8:
- if board.grid[nr][nc]=='.' or ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
- moves.append((r, c, nr, nc, None, None))
- # Rošády (základní verze)
- if is_white and r==7 and c==4:
- if 'K' in board.castling_rights and board.grid[7][5]=='.' and board.grid[7][6]=='.':
- moves.append((7,4,7,6,None,'castle'))
- if 'Q' in board.castling_rights and board.grid[7][3]=='.' and board.grid[7][2]=='.' and board.grid[7][1]=='.':
- moves.append((7,4,7,2,None,'castle'))
- if not is_white and r==0 and c==4:
- if 'k' in board.castling_rights and board.grid[0][5]=='.' and board.grid[0][6]=='.':
- moves.append((0,4,0,6,None,'castle'))
- if 'q' in board.castling_rights and board.grid[0][3]=='.' and board.grid[0][2]=='.' and board.grid[0][1]=='.':
- moves.append((0,4,0,2,None,'castle'))
- else:
- # Tahy pro figury s jezdcovým pohybem (N, A, C, E)
- if pt in ['N','A','C','E']:
- for dr, dc in knight_moves:
- nr, nc = r+dr, c+dc
- if 0<=nr<8 and 0<=nc<8:
- if board.grid[nr][nc]=='.' or ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
- moves.append((r, c, nr, nc, None, None))
- # Klouzavé tahy – pro R, Q, E, A
- if pt in ['R','Q','E','A']:
- for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:
- nr, nc = r+dr, c+dc
- while 0<=nr<8 and 0<=nc<8:
- if board.grid[nr][nc]=='.':
- moves.append((r, c, nr, nc, None, None))
- else:
- if ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
- moves.append((r, c, nr, nc, None, None))
- break
- nr += dr; nc += dc
- if pt in ['B','Q','C','A']:
- for dr, dc in [(1,1),(1,-1),(-1,1),(-1,-1)]:
- nr, nc = r+dr, c+dc
- while 0<=nr<8 and 0<=nc<8:
- if board.grid[nr][nc]=='.':
- moves.append((r, c, nr, nc, None, None))
- else:
- if ((is_white and board.grid[nr][nc].islower()) or (not is_white and board.grid[nr][nc].isupper())):
- moves.append((r, c, nr, nc, None, None))
- break
- nr += dr; nc += dc
- return moves
- def get_legal_moves(board, side):
- """Vrátí seznam legálních tahů pro danou stranu."""
- moves = generate_pseudo_moves(board, side)
- legal_moves = []
- for move in moves:
- make_move(move, board)
- if not is_in_check(board, side):
- legal_moves.append(move)
- undo_move(board)
- return legal_moves
- # Zásobník pro tahy (pro undo)
- move_stack = []
- def make_move(move, board):
- """Provede tah na šachovnici a uloží stav pro možnost undo.
- move: (r1, c1, r2, c2, promo, special)"""
- r1, c1, r2, c2, promo, special = move
- piece = board.grid[r1][c1]
- captured = board.grid[r2][c2] if special != 'enpassant' else ('p' if piece=='P' else 'P')
- prev_state = (set(board.castling_rights), board.en_passant)
- move_stack.append((r1, c1, r2, c2, promo, special, piece, captured, prev_state))
- board.grid[r1][c1] = '.'
- if special == 'castle':
- board.grid[r2][c2] = piece
- if piece == 'K':
- if c2 == 6:
- board.grid[7][5] = 'R'; board.grid[7][7] = '.'
- else:
- board.grid[7][3] = 'R'; board.grid[7][0] = '.'
- else:
- if c2 == 6:
- board.grid[0][5] = 'r'; board.grid[0][7] = '.'
- else:
- board.grid[0][3] = 'r'; board.grid[0][0] = '.'
- elif special == 'enpassant':
- board.grid[r2][c2] = piece
- if piece == 'P':
- board.grid[r2+1][c2] = '.'
- else:
- board.grid[r2-1][c2] = '.'
- else:
- board.grid[r2][c2] = promo if promo else piece
- if piece == 'K':
- board.castling_rights.discard('K'); board.castling_rights.discard('Q')
- if piece == 'k':
- board.castling_rights.discard('k'); board.castling_rights.discard('q')
- if piece == 'R' and (r1, c1)==(7,7):
- board.castling_rights.discard('K')
- if piece == 'R' and (r1, c1)==(7,0):
- board.castling_rights.discard('Q')
- if piece == 'r' and (r1, c1)==(0,7):
- board.castling_rights.discard('k')
- if piece == 'r' and (r1, c1)==(0,0):
- board.castling_rights.discard('q')
- if special == 'double':
- board.en_passant = (r1 + (-1 if board.to_move=='w' else 1), c1)
- else:
- board.en_passant = None
- board.to_move = 'b' if board.to_move=='w' else 'w'
- def undo_move(board):
- """Vrátí poslední provedený tah."""
- r1, c1, r2, c2, promo, special, piece, captured, prev_state = move_stack.pop()
- board.grid[r1][c1] = piece
- if special == 'castle':
- board.grid[r2][c2] = '.'
- if piece == 'K':
- if c2 == 6:
- board.grid[7][7] = 'R'; board.grid[7][5] = '.'
- else:
- board.grid[7][0] = 'R'; board.grid[7][3] = '.'
- else:
- if c2 == 6:
- board.grid[0][7] = 'r'; board.grid[0][5] = '.'
- else:
- board.grid[0][0] = 'r'; board.grid[0][3] = '.'
- elif special == 'enpassant':
- board.grid[r2][c2] = '.'
- if piece == 'P':
- board.grid[r2+1][c2] = 'p'
- else:
- board.grid[r2-1][c2] = 'P'
- else:
- board.grid[r2][c2] = captured
- board.castling_rights, board.en_passant = prev_state
- board.to_move = 'b' if board.to_move=='w' else 'w'
- ###############################################################################
- # Jednoduchá funkce pro zjištění, zda je mat v určité hloubce
- # (pro pomoc s detekcí matů za určitý počet tahů)
- ###############################################################################
- def is_mate_in_n(board, side, depth):
- """Zkontroluje, zda je pozice mat (pro stranu side) v zadané hloubce."""
- if depth == 0:
- # Kontrola matu
- legal_moves = get_legal_moves(board, side)
- return not legal_moves and is_in_check(board, side)
- # Rekurzivní kontrola pro stranu side (zda má vynucený mat)
- legal_moves = get_legal_moves(board, side)
- if not legal_moves:
- return False # Nemáme tahy, nemůžeme dát mat
- # Zkontrolujeme všechny tahy, musí existovat alespoň jeden, který vede k matu
- opponent = 'b' if side=='w' else 'w'
- for move in legal_moves:
- make_move(move, board)
- # Pro všechny odpovědi protivníka musí být mat
- opponent_can_avoid_mate = False
- opponent_legal_moves = get_legal_moves(board, opponent)
- if not opponent_legal_moves:
- # Protivník nemá tahy - buď je to mat nebo pat
- if is_in_check(board, opponent):
- undo_move(board)
- return True # Již nyní máme mat
- # Jinak je to pat a to není výhra
- # Pokud má protivník tahy, musíme prověřit všechny
- for op_move in opponent_legal_moves:
- make_move(op_move, board)
- if not is_mate_in_n(board, side, depth-1):
- opponent_can_avoid_mate = True
- undo_move(board)
- if opponent_can_avoid_mate:
- break
- undo_move(board)
- # Pokud protivník nemůže vyhnout matu, máme mat za 'depth' tahů
- if not opponent_can_avoid_mate:
- return True
- return False
- ###############################################################################
- # Negamax s alfa-beta ořezáváním pro hledání nejlepší sekvence
- ###############################################################################
- def negamax(board, depth, alpha, beta, side):
- """Negamax s alfa-beta ořezáváním.
- side: 1 pro bílého, -1 pro černého.
- Vrací (hodnota, tahová sekvence)."""
- # Koncové podmínky - mat (nebo pat když depth=0)
- curr_color = 'w' if side == 1 else 'b'
- legal_moves = get_legal_moves(board, curr_color)
- # Kontrola na mat nebo pat (terminální stavy)
- if not legal_moves:
- if is_in_check(board, curr_color):
- return -inf, [] # Mat
- return 0, [] # Pat
- # Dosáhli jsme maximální hloubky - základní ohodnocení
- if depth == 0:
- # Kontrola, zda máme mat v nejbližších tazích
- enemy_color = 'b' if curr_color == 'w' else 'w'
- for move in legal_moves:
- make_move(move, board)
- enemy_legal_moves = get_legal_moves(board, enemy_color)
- if not enemy_legal_moves and is_in_check(board, enemy_color):
- undo_move(board)
- return inf, [move] # Našli jsme mat
- undo_move(board)
- # Pro jednoduchost zde neohodnocujeme materiál, pozici atd.
- # V reálném šachovém enginu bychom zde vraceli pozici na základě materiálu, struktury pěšců atd.
- return 0, []
- best_val = -inf
- best_line = []
- # Seřazení tahů pro alfa-beta
- legal_moves.sort(key=lambda m: 1 if board.grid[m[2]][m[3]] != '.' else 0, reverse=True)
- for move in legal_moves:
- make_move(move, board)
- val, line = negamax(board, depth-1, -beta, -alpha, -side)
- val = -val
- undo_move(board)
- if val > best_val:
- best_val = val
- best_line = [move] + line
- alpha = max(alpha, best_val)
- if alpha >= beta:
- break
- return best_val, best_line
- ###############################################################################
- # Iterativní prohlubování – hledáme do maximální hloubky a vypisujeme uplynulý čas
- ###############################################################################
- def iterative_deepening(board, max_depth=50, time_limit=300):
- """Iterativní prohlubování s časovým limitem (výchozí 5 minut)."""
- global running, start_time
- # Spuštění časovacího vlákna
- running = True
- start_time = time.time()
- timer_thread = threading.Thread(target=time_reporter)
- timer_thread.daemon = True
- timer_thread.start()
- best_line = []
- best_val = 0
- try:
- # Nejdříve zkontrolujeme, zda máme vůbec nějaké legální tahy
- curr_side = board.to_move
- enemy_side = 'b' if curr_side=='w' else 'w'
- legal_moves = get_legal_moves(board, curr_side)
- # Pokud nemáme žádné legální tahy, je to pat nebo mat
- if not legal_moves:
- total_elapsed = time.time() - start_time
- running = False
- if is_in_check(board, curr_side):
- return -inf, [], total_elapsed # Mat
- return 0, [], total_elapsed # Pat
- # Zkontrolujeme, zda máme mat v jednom tahu
- for move in legal_moves:
- make_move(move, board)
- enemy_legal = get_legal_moves(board, enemy_side)
- if not enemy_legal and is_in_check(board, enemy_side):
- # Našli jsme mat v jednom tahu
- undo_move(board)
- running = False
- return inf, [move], 0.1
- undo_move(board)
- # Pokud máme jen jeden legální tah, vrátíme ho bez dalšího počítání
- if len(legal_moves) == 1:
- running = False
- return 0, legal_moves, 0.1
- # Nyní začněme iterativní prohlubování
- for depth in range(1, max_depth+1):
- t0 = time.time()
- val, line = negamax(board, depth, -inf, inf, 1 if board.to_move=='w' else -1)
- t1 = time.time()
- elapsed = time.time() - start_time
- # Výpis času po dosažení každé hloubky
- hrs = int(elapsed // 3600)
- mins = int((elapsed % 3600) // 60)
- secs = int(elapsed % 60)
- # Po výpisu každé hloubky přejdeme na nový řádek
- move_time = t1 - t0
- sys.stdout.write("\n") # Nový řádek po časovém informačním řádku
- print(f"Hloubka {depth:2d} – uplynulý čas: {hrs:02d}h {mins:02d}m {secs:02d}s (poslední krok: {move_time:.2f}s)")
- # Zobrazení aktuální nejlepší pozice pro tuto hloubku
- if line:
- print(f"\nNejlepší sekvence v hloubce {depth}:")
- variant_board = board.copy()
- move = line[0] # Vezmeme pouze první tah
- make_move(move, variant_board)
- print(f"Tah: {move_to_notation(move)}")
- print(variant_board.display())
- print("-" * 40)
- else:
- print("\nŽádná nalezená sekvence v této hloubce.")
- # Aktualizujeme nejlepší nalezenou sekvenci
- best_val = val
- best_line = line
- # Pokud jsme našli vynucený mat nebo pat, končíme
- if abs(val) == inf or time.time() - start_time > time_limit:
- if time.time() - start_time > time_limit:
- print(f"Časový limit vypršel po {time_limit} sekundách")
- break
- # Ověření, že když máme tahy, tak vrátíme nejlepší z nich (i když je remíza)
- if not best_line and legal_moves:
- best_line = [legal_moves[0]]
- total_elapsed = time.time() - start_time
- return best_val, best_line, total_elapsed
- finally:
- # Zajistíme ukončení časovacího vlákna
- running = False
- timer_thread.join(timeout=1.0)
- # Přejdeme na nový řádek po posledním časovém výpisu
- sys.stdout.write("\n")
- sys.stdout.flush()
- ###############################################################################
- # Testovací funkce pro kontrolu, zda jsou tahy e4 správně generovány
- ###############################################################################
- def debug_king_moves(fen="8/8/8/8/8/kq2K3/8/8 w - - 0 1"):
- """Testovací funkce pro zobrazení generovaných tahů krále."""
- board = Board(fen)
- print("Pozice:")
- print(board.display())
- side = board.to_move
- king_pos = find_king(board, side)
- if not king_pos:
- print("Král nenalezen!")
- return
- kr, kc = king_pos
- print(f"Král na pozici: {'abcdefgh'[kc]}{8-kr} ({kr},{kc})")
- # Generujeme tahy krále
- king_moves = []
- for dr in [-1, 0, 1]:
- for dc in [-1, 0, 1]:
- if dr == 0 and dc == 0:
- continue
- nr, nc = kr + dr, kc + dc
- if 0 <= nr < 8 and 0 <= nc < 8:
- king_moves.append((nr, nc))
- print("Možné tahy krále:")
- for nr, nc in king_moves:
- # Zjistíme, zda je tam vlastní figura
- piece = board.grid[nr][nc]
- enemy_side = 'b' if side == 'w' else 'w'
- attacked = is_square_attacked(board, nr, nc, enemy_side)
- status = ""
- if piece != '.':
- is_own = (side == 'w' and piece.isupper()) or (side == 'b' and piece.islower())
- if is_own:
- status = "vlastní figura"
- else:
- status = f"soupeřova figura {piece}"
- if attacked:
- status += " (napadeno)"
- if not status:
- status = "volné pole"
- print(f" {'abcdefgh'[nc]}{8-nr} ({nr},{nc}): {status}")
- # Generování legálních tahů pomocí generate_pseudo_moves
- print("\nLegální tahy podle generate_pseudo_moves:")
- moves = generate_pseudo_moves(board, side)
- king_moves = []
- for move in moves:
- r1, c1, r2, c2, _, _ = move
- if r1 == kr and c1 == kc:
- king_moves.append(move)
- for move in king_moves:
- r1, c1, r2, c2, _, _ = move
- make_move(move, board)
- in_check = is_in_check(board, side)
- undo_move(board)
- print(f" {'abcdefgh'[c1]}{8-r1} -> {'abcdefgh'[c2]}{8-r2}: {'nelegální (šach)' if in_check else 'legální'}")
- ###############################################################################
- # Převod tahu do šachové notace
- ###############################################################################
- def move_to_notation(move):
- cols = "abcdefgh"
- r1, c1, r2, c2, promo, special = move
- if special == 'castle':
- return "O-O" if c2 > c1 else "O-O-O"
- s = cols[c1] + str(8 - r1) + cols[c2] + str(8 - r2)
- if promo:
- s += "=" + promo.upper()
- if special == 'enpassant':
- s += " e.p."
- return s
- ###############################################################################
- # Analýza pozice pro určení výsledku
- ###############################################################################
- def analyze_position(board):
- """Analyzuje pozici a vrací výsledek."""
- # Zjistíme stranu na tahu
- side_to_move = board.to_move
- # Zjistíme, zda má strana na tahu legální tahy
- legal_moves = get_legal_moves(board, side_to_move)
- # Kontrola na mat nebo pat
- if not legal_moves:
- if is_in_check(board, side_to_move):
- if side_to_move == 'w':
- return "Mat – černý vyhrává"
- else:
- return "Mat – bílý vyhrává"
- else:
- return "Pat (remíza)"
- # Zjistíme, zda po provedení tahu bude mat
- for move in legal_moves:
- make_move(move, board)
- opponent = 'b' if side_to_move == 'w' else 'w'
- opponent_legal_moves = get_legal_moves(board, opponent)
- if not opponent_legal_moves and is_in_check(board, opponent):
- undo_move(board)
- if side_to_move == 'w':
- return "Mat v příštím tahu – bílý vyhrává"
- else:
- return "Mat v příštím tahu – černý vyhrává"
- undo_move(board)
- # Pokud nemáme ani mat ani pat, pozice je otevřená
- return "Pozice není rozhodnuta"
- ###############################################################################
- # Hlavní program – inicializace z FEN a výpis optimální tahové sekvence
- ###############################################################################
- def main():
- # Nastavíme pozici ze zadaného FEN
- fen = "8/6A1/8/8/8/k1K5/8/8 w - - 0 1"
- fen = "8/8/8/8/8/kq2K3/8/8 w - - 0 1"
- # Další příklad pozice
- #fen = "8/8/8/8/8/kq2K3/6A1/8 w - - 0 1"
- # Nejprve spustíme debug pro ověření tahů krále
- print("DEBUG TAHŮ KRÁLE:")
- print("-" * 40)
- debug_king_moves(fen)
- print("-" * 40)
- board_obj = Board(fen)
- board = board_obj.copy()
- print("Počáteční pozice:")
- print(board.display())
- print("\nVyhledávání optimální tahové sekvence – iterativní prohlubování...\n")
- # Nastavíme časový limit na 5 minut (300 sekund)
- best_val, best_line, total_elapsed = iterative_deepening(board, max_depth=500, time_limit=inf)
- hrs = int(total_elapsed // 3600)
- mins = int((total_elapsed % 3600) // 60)
- secs = int(total_elapsed % 60)
- variant_board = board.copy()
- moves_notation = []
- print("Postup tahů:")
- print("-"*40)
- print("Start:")
- print(variant_board.display())
- print("-"*40)
- # Vykonání sekvence tahů a zobrazení průběhu
- for move in best_line:
- s = move_to_notation(move)
- moves_notation.append(s)
- make_move(move, variant_board)
- print("Tah:", s)
- print(variant_board.display())
- print("-"*40)
- # Vyhodnocení výsledné pozice
- if best_val == inf:
- result_text = "Mat – bílý vyhrává"
- elif best_val == -inf:
- result_text = "Mat – černý vyhrává"
- else:
- # Pokud engine nenašel jednoznačný výsledek, analyzujeme pozici znovu
- result_text = analyze_position(variant_board)
- print("Optimální tahová sekvence:", " ".join(moves_notation) if moves_notation else "(žádný tah)")
- print("Výsledek:", result_text)
- print(f"Celkový uplynulý čas: {hrs:02d}h {mins:02d}m {secs:02d}s")
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement