140 lines
4.3 KiB
Python
140 lines
4.3 KiB
Python
import time
|
|
from typing import List, Tuple
|
|
|
|
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 shenzhen_solitaire.solver.board_actions as board_actions
|
|
import warnings
|
|
|
|
|
|
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,
|
|
)
|
|
|
|
|
|
def handle_action(
|
|
action: board_actions.Action,
|
|
offset: Tuple[int, int],
|
|
conf: configuration.Configuration,
|
|
) -> None:
|
|
if isinstance(action, board_actions.MoveAction):
|
|
src = adjustment.get_square(
|
|
conf.field_adjustment,
|
|
index_x=action.source_id,
|
|
index_y=action.source_row_index,
|
|
)
|
|
dst = adjustment.get_square(
|
|
conf.field_adjustment,
|
|
index_x=action.destination_id,
|
|
index_y=action.destination_row_index,
|
|
)
|
|
dragSquare(src, dst, offset)
|
|
return
|
|
if isinstance(action, board_actions.HuaKillAction):
|
|
warnings.warn("Hua kill should be handled before handle_action")
|
|
return
|
|
if isinstance(action, board_actions.BunkerizeAction):
|
|
field = adjustment.get_square(
|
|
conf.field_adjustment,
|
|
index_x=action.field_id,
|
|
index_y=action.field_row_index,
|
|
)
|
|
bunker = adjustment.get_square(
|
|
conf.bunker_adjustment, index_x=action.bunker_id, index_y=0,
|
|
)
|
|
if action.to_bunker:
|
|
dragSquare(field, bunker, offset)
|
|
else:
|
|
dragSquare(bunker, field, offset)
|
|
return
|
|
if isinstance(action, board_actions.DragonKillAction):
|
|
dragon_sequence = [
|
|
board.SpecialCard.Zhong,
|
|
board.SpecialCard.Fa,
|
|
board.SpecialCard.Bai,
|
|
]
|
|
field = adjustment.get_square(
|
|
conf.special_button_adjustment,
|
|
index_x=0,
|
|
index_y=dragon_sequence.index(action.dragon),
|
|
)
|
|
clickSquare(
|
|
field, offset,
|
|
)
|
|
time.sleep(1)
|
|
return
|
|
if isinstance(action, board_actions.GoalAction):
|
|
dst = adjustment.get_square(
|
|
conf.goal_adjustment, index_x=action.goal_id, index_y=0,
|
|
)
|
|
if action.source_position == board.Position.Field:
|
|
assert action.source_row_index is not None
|
|
src = adjustment.get_square(
|
|
conf.field_adjustment,
|
|
index_x=action.source_id,
|
|
index_y=action.source_row_index,
|
|
)
|
|
else:
|
|
assert action.source_position == board.Position.Bunker
|
|
src = adjustment.get_square(
|
|
conf.bunker_adjustment, index_x=action.source_id, index_y=0,
|
|
)
|
|
dragSquare(src, dst, offset)
|
|
return
|
|
raise AssertionError("You forgot an Action type")
|
|
|
|
|
|
def handle_actions(
|
|
actions: List[board_actions.Action],
|
|
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)
|