Загрузка данных
import time
import random
import pyautogui
import crop
# Отключаем системную задержку pyautogui для полного контроля скорости
pyautogui.PAUSE = 0.01
pyautogui.FAILSAFE = False
class ChessMover:
def __init__(self):
self.auto_move_enabled = False
self.humanly_mode = True # По умолчанию включен плавно-человечный режим
self.move_duration = 0.35 # Скорость перемещения (в секундах)
def toggle_auto_move(self):
"""Включение / Выключение автоматических ходов (Клавиша L)"""
self.auto_move_enabled = not self.auto_move_enabled
status = "ВКЛЮЧЁН" if self.auto_move_enabled else "ВЫКЛЮЧЕН"
print(f"\n[AUTO-MOVE]: Автоход -> {status}")
def toggle_humanly_mode(self):
"""Переключение между плавным зажатием и кликами (Клавиша H)"""
self.humanly_mode = not self.humanly_mode
mode_str = "HUMANLY (Плавный перенос)" if self.humanly_mode else "CLICK (Клик-Клик)"
print(f"\n[MOVE MODE]: Режим движения -> {mode_str}")
def speed_up(self):
"""Увеличить скорость движения мыши (Клавиша '+')"""
self.move_duration = max(0.05, self.move_duration - 0.05)
print(f"\n[SPEED +]: Время перемещения уменьшено до {self.move_duration:.2f} сек")
def speed_down(self):
"""Уменьшить скорость движения мыши (Клавиша '-')"""
self.move_duration = min(2.0, self.move_duration + 0.05)
print(f"\n[SPEED -]: Время перемещения увеличено до {self.move_duration:.2f} сек")
def get_absolute_board_rect(self):
"""Вычисляет абсолютные координаты доски на всём экране на основе crop.py"""
if crop._tracker.last_board_rect is None:
return None
bx, by, size = crop._tracker.last_board_rect
mon = crop._tracker.monitor
abs_x = mon["left"] + bx
abs_y = mon["top"] + by
return (abs_x, abs_y, size)
def square_to_screen_coords(self, square_str, board_rect, my_color='w'):
"""Преобразует нотацию шахматной клетки (например, 'e2') в координаты экрана (X, Y)"""
if not board_rect or len(square_str) < 2:
return None
abs_x, abs_y, board_size = board_rect
cell_size = board_size / 8.0
file_char = square_str[0].lower()
rank_char = square_str[1]
file_idx = ord(file_char) - ord('a') # 0..7 (столбцы a-h)
rank_idx = int(rank_char) # 1..8 (горизонтали)
# Ориентация доски в зависимости от цвета игрока
if my_color == 'w':
col = file_idx
row = 8 - rank_idx
else:
col = 7 - file_idx
row = rank_idx - 1
# Случайное микро-отклонение от центра клетки (человеческий фактор)
jitter_x = random.uniform(-cell_size * 0.12, cell_size * 0.12)
jitter_y = random.uniform(-cell_size * 0.12, cell_size * 0.12)
center_x = int(abs_x + (col + 0.5) * cell_size + jitter_x)
center_y = int(abs_y + (row + 0.5) * cell_size + jitter_y)
return center_x, center_y
def execute_move(self, uci_move, my_color='w'):
"""Выполняет передвижение фигуры на экране по UCI-строке (например, 'e2e4')"""
if not self.auto_move_enabled:
return
board_rect = self.get_absolute_board_rect()
if not board_rect:
print("[!] Ошибка физического хода: Координаты доски не найдены в crop!")
return
from_sq = uci_move[:2]
to_sq = uci_move[2:4]
start_pos = self.square_to_screen_coords(from_sq, board_rect, my_color)
end_pos = self.square_to_screen_coords(to_sq, board_rect, my_color)
if not start_pos or not end_pos:
print(f"[!] Не удалось рассчитать координаты для хода: {uci_move}")
return
start_x, start_y = start_pos
end_x, end_y = end_pos
mode_desc = "Humanly (Drag)" if self.humanly_mode else "Click"
print(f"[PHYSICAL MOVE]: Выполняем {uci_move} | {mode_desc} | Скорость: {self.move_duration:.2f}s")
if self.humanly_mode:
# --- 3 РЕЖИМ: HUMANLY (Подвод, зажатие, плавное перемещение, отпускание) ---
pyautogui.moveTo(start_x, start_y, duration=self.move_duration * 0.4, tween=pyautogui.easeOutQuad)
pyautogui.mouseDown()
time.sleep(random.uniform(0.02, 0.05))
# Плавная траектория движения к клетке назначения
pyautogui.moveTo(end_x, end_y, duration=self.move_duration, tween=pyautogui.easeInOutQuad)
time.sleep(random.uniform(0.02, 0.05))
pyautogui.mouseUp()
else:
# --- РЕЖИМ КЛИКОВ (Обычное нажатие на фигуру и на клетку) ---
pyautogui.moveTo(start_x, start_y, duration=self.move_duration * 0.3)
pyautogui.click()
time.sleep(random.uniform(0.04, 0.08))
pyautogui.moveTo(end_x, end_y, duration=self.move_duration * 0.3)
pyautogui.click()
# При превращении пешки (e7e8q) делается дополнительный клик
if len(uci_move) == 5:
time.sleep(0.1)
pyautogui.click()