| import pyautogui
|
| import chess
|
| import time
|
| import math
|
|
|
| class MirrorHandler:
|
| def __init__(self):
|
|
|
| pyautogui.FAILSAFE = True
|
| pyautogui.PAUSE = 0.1
|
|
|
| def execute_move(self, move, region, is_flipped=False):
|
| """
|
| Execute a chess move on the screen region using mouse drag.
|
|
|
| Args:
|
| move (chess.Move): The move to execute.
|
| region (dict): {'left', 'top', 'width', 'height'} of the target board.
|
| is_flipped (bool): If True, board is viewed from Black's perspective (rank 1 at top).
|
| """
|
| if not region or not move:
|
| return
|
|
|
| start_sq = move.from_square
|
| end_sq = move.to_square
|
|
|
|
|
| start_x, start_y = self._get_square_center(start_sq, region, is_flipped)
|
| end_x, end_y = self._get_square_center(end_sq, region, is_flipped)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| pyautogui.moveTo(start_x, start_y)
|
|
|
| pyautogui.dragTo(end_x, end_y, button='left')
|
|
|
|
|
| if move.promotion:
|
|
|
|
|
|
|
|
|
| time.sleep(0.1)
|
| pyautogui.click()
|
|
|
| def _get_square_center(self, square, region, is_flipped):
|
| """
|
| Calculate center x, y for a given square index (0-63).
|
| """
|
| file_idx = chess.square_file(square)
|
| rank_idx = chess.square_rank(square)
|
|
|
| if is_flipped:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| col = 7 - file_idx
|
| row = rank_idx
|
| else:
|
|
|
|
|
| col = file_idx
|
| row = 7 - rank_idx
|
|
|
| sq_w = region['width'] / 8
|
| sq_h = region['height'] / 8
|
|
|
| center_x = region['left'] + (col * sq_w) + (sq_w / 2)
|
| center_y = region['top'] + (row * sq_h) + (sq_h / 2)
|
|
|
| return center_x, center_y
|
|
|