134 lines
3.8 KiB
Python
134 lines
3.8 KiB
Python
import time
|
|
from typing import List, Tuple, Dict, Any
|
|
|
|
import pyautogui
|
|
import shenzhen_solitaire.board as board
|
|
import shenzhen_solitaire.card_detection.adjustment as adjustment
|
|
import shenzhen_solitaire.card_detection.configuration as configuration
|
|
import warnings
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
def drag(
|
|
src: Tuple[int, int], dst: Tuple[int, int], offset: Tuple[int, int] = (0, 0)
|
|
) -> None:
|
|
|
|
pyautogui.moveTo(x=src[0] + offset[0], y=src[1] + offset[1])
|
|
pyautogui.dragTo(
|
|
x=dst[0] + offset[0],
|
|
y=dst[1] + offset[1],
|
|
duration=0.4,
|
|
tween=lambda x: 0 if x < 0.5 else 1,
|
|
)
|
|
|
|
|
|
def dragSquare(
|
|
src: Tuple[int, int, int, int],
|
|
dst: Tuple[int, int, int, int],
|
|
offset: Tuple[int, int] = (0, 0),
|
|
) -> None:
|
|
drag(
|
|
(src[0] + (src[2] - src[0]) // 2, src[1] + (src[3] - src[1]) // 2),
|
|
(dst[0] + (dst[2] - dst[0]) // 2, dst[1] + (dst[3] - dst[1]) // 2),
|
|
offset,
|
|
)
|
|
|
|
|
|
def click(point: Tuple[int, int], offset: Tuple[int, int] = (0, 0)) -> None:
|
|
pyautogui.moveTo(x=point[0] + offset[0], y=point[1] + offset[1])
|
|
pyautogui.mouseDown()
|
|
time.sleep(0.2)
|
|
pyautogui.mouseUp()
|
|
|
|
|
|
def clickSquare(
|
|
field: Tuple[int, int, int, int], offset: Tuple[int, int] = (0, 0)
|
|
) -> None:
|
|
click(
|
|
(field[0] + (field[2] - field[0]) // 2, field[1] + (field[3] - field[1]) // 2),
|
|
offset,
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class DragAction:
|
|
source: Tuple[int, int]
|
|
destination: Tuple[int, int]
|
|
|
|
|
|
@dataclass
|
|
class ClickAction:
|
|
destination: Tuple[int, int]
|
|
|
|
|
|
class WaitAction:
|
|
pass
|
|
|
|
|
|
def _parse_field(
|
|
field: Dict[str, Any], conf: configuration.Configuration
|
|
) -> Tuple[int, int]:
|
|
return (
|
|
int(field["column"]) * conf.field_adjustment.dx + conf.field_adjustment.x,
|
|
int(field["row"]) * conf.field_adjustment.dy + conf.field_adjustment.y,
|
|
)
|
|
|
|
|
|
def parse_action(action: Dict[str, Any], conf: configuration.Configuration):
|
|
assert len(action) == 1
|
|
action_name, info = next(iter(action.items()))
|
|
action_name = action_name.lower()
|
|
if action_name == "bunkerize":
|
|
field = _parse_field(info["field_position"], conf)
|
|
bunker = (
|
|
int(info["bunker_slot_index"]) * conf.bunker_adjustment.dx
|
|
+ conf.bunker_adjustment.x,
|
|
conf.bunker_adjustment.y,
|
|
)
|
|
if str(info["to_bunker"]).lower() == "true":
|
|
return DragAction(source=field, destination=bunker)
|
|
else:
|
|
return DragAction(source=bunker, destination=field)
|
|
elif action_name == "move":
|
|
return DragAction(
|
|
source=_parse_field(info["source"], conf),
|
|
destination=_parse_field(info["source"], conf),
|
|
)
|
|
elif action_name == "dragonkill":
|
|
return ClickAction()
|
|
elif action_name == "goal":
|
|
goal = (
|
|
int(info["goal_slot_index"]) * conf.goal_adjustment.dx
|
|
+ conf.goal_adjustment.x,
|
|
conf.goal_adjustment.y,
|
|
)
|
|
if "Field" in info["source"]:
|
|
source = _parse_field(info["source"]["Field"], conf)
|
|
else:
|
|
source = (
|
|
int(info["source"]["Bunker"]["slot_index"]) * conf.bunker_adjustment.dx
|
|
+ conf.bunker_adjustment.x,
|
|
conf.bunker_adjustment.y,
|
|
)
|
|
return DragAction(source=source, destination=goal)
|
|
elif action_name == "huakill":
|
|
return WaitAction()
|
|
|
|
|
|
def handle_actions(
|
|
actions: List[Dict[str, Dict[str, Any]]],
|
|
offset: Tuple[int, int],
|
|
conf: configuration.Configuration,
|
|
) -> None:
|
|
automatic_count = 0
|
|
for action in actions:
|
|
print(action)
|
|
if isinstance(action, board_actions.HuaKillAction):
|
|
automatic_count += 1
|
|
else:
|
|
time.sleep(0.5 * automatic_count)
|
|
automatic_count = 0
|
|
handle_action(action, offset, conf)
|
|
time.sleep(0.5 * automatic_count)
|