Загрузка данных
import time
import random
import pyautogui
import crop
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'):
"""Преобразует шахматную клетку в координаты экрана"""
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
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.10, cell_size * 0.10)
jitter_y = random.uniform(-cell_size * 0.10, cell_size * 0.10)
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'):
"""Выполняет физический ход мышью на экране"""
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:
# --- HUMANLY MODE: Наведение -> Зажатие -> Плавная затайка -> Отпускание ---
pyautogui.moveTo(start_x, start_y, duration=self.move_duration * 0.35, tween=pyautogui.easeOutQuad)
pyautogui.mouseDown()
time.sleep(random.uniform(0.02, 0.04))
pyautogui.moveTo(end_x, end_y, duration=self.move_duration, tween=pyautogui.easeInOutQuad)
time.sleep(random.uniform(0.02, 0.04))
pyautogui.mouseUp()
else:
# --- CLICK MODE: Клик на начальную -> Клик на конечную ---
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()
# При превращении пешки
if len(uci_move) == 5:
time.sleep(0.1)
pyautogui.click()