import chess
import chess.engine
class ChessEngine:
def __init__(self, engine_path="stockfish.exe", time_limit=0.1):
self.engine_path = engine_path
self.time_limit = time_limit
self.engine = None
self.enabled = False # Отключен по умолчанию
self._start_engine()
def _start_engine(self):
"""Запуск или перезапуск процесса Stockfish."""
# Если старый процесс еще существует — закрываем его
if self.engine:
try:
self.engine.quit()
except Exception:
pass
self.engine = None
try:
# Ищем Stockfish в папке Windows или текущей директории
path_to_use = self.engine_path
self.engine = chess.engine.SimpleEngine.popen_uci(path_to_use)
options = {
"Hash": 16,
"Threads": 1
}
for key, value in options.items():
if key in self.engine.options:
self.engine.configure({key: value})
print("[ОК] Движок Stockfish готов!")
except Exception as e:
print(f"[ПРЕДУПРЕЖДЕНИЕ] Не удалось запустить движок: {e}")
self.engine = None
def toggle(self):
"""Переключает активное состояние движка."""
self.enabled = not self.enabled
# При включении проверяем, жив ли процесс
if self.enabled and (not self.engine or self.engine.is_terminated()):
self._start_engine()
return self.enabled
def analyze_fen(self, fen):
if not self.enabled:
return None, "Движок отключен [Жми S]"
# Если процесс Stockfish упал — перезапускаем его прямо на лету!
if not self.engine or self.engine.is_terminated():
self._start_engine()
if not self.engine:
return None, "Ошибка: Stockfish не запущен"
try:
board = chess.Board(fen)
# Проверка корректности FEN позиции перед отправкой
if not board.is_valid():
return None, "Некорректная позиция FEN"
result = self.engine.analyse(board, chess.engine.Limit(time=self.time_limit))
best_move = result.get("pv")[0] if "pv" in result and result["pv"] else None
score = result.get("score")
if score is not None:
if score.is_mate():
eval_str = f"Мат в {score.relative.mate()}"
else:
cp = score.relative.score() / 100.0
eval_str = f"{'+' if cp > 0 else ''}{cp:.2f}"
else:
eval_str = "0.00"
return best_move.uci() if best_move else None, eval_str
except chess.engine.EngineTerminatedError:
print("[ОШИБКА] Stockfish аварийно завершился! Перезапуск...")
self._start_engine()
return None, "Перезапуск Stockfish..."
except Exception as e:
return None, f"Ошибка анализа: {e}"
def close(self):
if self.engine:
try:
self.engine.quit()
except Exception:
pass