Made it work again, automatic goal moves messing with me though

This commit is contained in:
Lukas Wölfer
2020-06-13 03:51:14 +02:00
parent b5d74d1ac0
commit 63d4348f94
3 changed files with 71 additions and 46 deletions

View File

@@ -1,5 +1,5 @@
import time import time
from typing import List, Tuple, Dict, Any from typing import List, Tuple, Dict, Any, Union
import pyautogui import pyautogui
import shenzhen_solitaire.board as board import shenzhen_solitaire.board as board
@@ -8,6 +8,10 @@ import shenzhen_solitaire.card_detection.configuration as configuration
import warnings import warnings
from dataclasses import dataclass from dataclasses import dataclass
from shenzhen_solitaire.board import SpecialCard
DRAG_DURATION = 0.4
CLICK_DURATION = 0.5
def drag( def drag(
@@ -18,39 +22,18 @@ def drag(
pyautogui.dragTo( pyautogui.dragTo(
x=dst[0] + offset[0], x=dst[0] + offset[0],
y=dst[1] + offset[1], y=dst[1] + offset[1],
duration=0.4, duration=DRAG_DURATION,
tween=lambda x: 0 if x < 0.5 else 1, 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: 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.moveTo(x=point[0] + offset[0], y=point[1] + offset[1])
pyautogui.mouseDown() pyautogui.mouseDown()
time.sleep(0.2) time.sleep(CLICK_DURATION)
pyautogui.mouseUp() 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 @dataclass
class DragAction: class DragAction:
source: Tuple[int, int] source: Tuple[int, int]
@@ -70,12 +53,20 @@ def _parse_field(
field: Dict[str, Any], conf: configuration.Configuration field: Dict[str, Any], conf: configuration.Configuration
) -> Tuple[int, int]: ) -> Tuple[int, int]:
return ( return (
int(field["column"]) * conf.field_adjustment.dx + conf.field_adjustment.x, int(field["column"]) * conf.field_adjustment.dx
int(field["row"]) * conf.field_adjustment.dy + conf.field_adjustment.y, + conf.field_adjustment.x
+ conf.field_adjustment.w // 2,
int(field["row"]) * conf.field_adjustment.dy
+ conf.field_adjustment.y
+ conf.field_adjustment.h // 2,
) )
def parse_action(action: Dict[str, Any], conf: configuration.Configuration): def parse_action(
action: Dict[str, Any],
conf: configuration.Configuration,
goal_values: Dict[str, int],
) -> Union[DragAction, ClickAction, WaitAction]:
assert len(action) == 1 assert len(action) == 1
action_name, info = next(iter(action.items())) action_name, info = next(iter(action.items()))
action_name = action_name.lower() action_name = action_name.lower()
@@ -83,8 +74,9 @@ def parse_action(action: Dict[str, Any], conf: configuration.Configuration):
field = _parse_field(info["field_position"], conf) field = _parse_field(info["field_position"], conf)
bunker = ( bunker = (
int(info["bunker_slot_index"]) * conf.bunker_adjustment.dx int(info["bunker_slot_index"]) * conf.bunker_adjustment.dx
+ conf.bunker_adjustment.x, + conf.bunker_adjustment.x
conf.bunker_adjustment.y, + conf.bunker_adjustment.w // 2,
conf.bunker_adjustment.y + conf.bunker_adjustment.h // 2,
) )
if str(info["to_bunker"]).lower() == "true": if str(info["to_bunker"]).lower() == "true":
return DragAction(source=field, destination=bunker) return DragAction(source=field, destination=bunker)
@@ -93,23 +85,50 @@ def parse_action(action: Dict[str, Any], conf: configuration.Configuration):
elif action_name == "move": elif action_name == "move":
return DragAction( return DragAction(
source=_parse_field(info["source"], conf), source=_parse_field(info["source"], conf),
destination=_parse_field(info["source"], conf), destination=_parse_field(info["destination"], conf),
) )
elif action_name == "dragonkill": elif action_name == "dragonkill":
return ClickAction() dragon_sequence = [SpecialCard.Zhong, SpecialCard.Fa, SpecialCard.Bai]
dragon_name_map = {
"zhong": SpecialCard.Zhong,
"fa": SpecialCard.Fa,
"bai": SpecialCard.Bai,
}
card_type = dragon_name_map[info["card"].lower()]
dragon_id = dragon_sequence.index(card_type)
return ClickAction(
destination=(
conf.special_button_adjustment.x
+ conf.special_button_adjustment.w // 2,
conf.special_button_adjustment.y
+ dragon_id * conf.special_button_adjustment.dy
+ conf.special_button_adjustment.h // 2,
)
)
elif action_name == "goal": elif action_name == "goal":
obvious = (
goal_values[info["card"]["suit"].lower()] <= min(goal_values.values()) + 1
)
assert (goal_values[info["card"]["suit"].lower()] == 0) or (
goal_values[info["card"]["suit"].lower()] + 1 == info["card"]["value"]
)
goal_values[info["card"]["suit"].lower()] = info["card"]["value"]
if obvious:
return WaitAction()
goal = ( goal = (
int(info["goal_slot_index"]) * conf.goal_adjustment.dx int(info["goal_slot_index"]) * conf.goal_adjustment.dx
+ conf.goal_adjustment.x, + conf.goal_adjustment.x
conf.goal_adjustment.y, + conf.goal_adjustment.w // 2,
conf.goal_adjustment.y + conf.goal_adjustment.h // 2,
) )
if "Field" in info["source"]: if "Field" in info["source"]:
source = _parse_field(info["source"]["Field"], conf) source = _parse_field(info["source"]["Field"], conf)
else: else:
source = ( source = (
int(info["source"]["Bunker"]["slot_index"]) * conf.bunker_adjustment.dx int(info["source"]["Bunker"]["slot_index"]) * conf.bunker_adjustment.dx
+ conf.bunker_adjustment.x, + conf.bunker_adjustment.x
conf.bunker_adjustment.y, + conf.bunker_adjustment.w // 2,
conf.bunker_adjustment.y + conf.bunker_adjustment.h // 2,
) )
return DragAction(source=source, destination=goal) return DragAction(source=source, destination=goal)
elif action_name == "huakill": elif action_name == "huakill":
@@ -121,13 +140,15 @@ def handle_actions(
offset: Tuple[int, int], offset: Tuple[int, int],
conf: configuration.Configuration, conf: configuration.Configuration,
) -> None: ) -> None:
automatic_count = 0 goal_values = {"red": 0, "black": 0, "green": 0}
for action in actions: action_tuples = [
print(action) (action, parse_action(action, conf, goal_values)) for action in actions
if isinstance(action, board_actions.HuaKillAction): ]
automatic_count += 1 for name, action in action_tuples:
else: print(name)
time.sleep(0.5 * automatic_count) if isinstance(action, DragAction):
automatic_count = 0 drag(action.source, action.destination, offset)
handle_action(action, offset, conf) elif isinstance(action, ClickAction):
time.sleep(0.5 * automatic_count) click(action.destination, offset)
elif isinstance(action, WaitAction):
time.sleep(2)

View File

@@ -42,7 +42,7 @@ def solve(conf: configuration.Configuration) -> None:
board = parse_start_board(image, conf) board = parse_start_board(image, conf)
assert board.check_correct() assert board.check_correct()
actions = extern_solve(board) actions = extern_solve(board)
assert 0 print(actions)
print(f"Solved in {len(actions)} steps") print(f"Solved in {len(actions)} steps")
clicker.handle_actions(actions, OFFSET, conf) clicker.handle_actions(actions, OFFSET, conf)
print("Solved") print("Solved")

View File

@@ -75,6 +75,10 @@ def main() -> None:
conf.hua_adjustment = adjustment.adjust_squares( conf.hua_adjustment = adjustment.adjust_squares(
image, count_x=1, count_y=1, adjustment=copy.deepcopy(conf.hua_adjustment) image, count_x=1, count_y=1, adjustment=copy.deepcopy(conf.hua_adjustment)
) )
print("Special button")
conf.special_button_adjustment = adjustment.adjust_squares(
image, count_x=1, count_y=3, adjustment=copy.deepcopy(conf.special_button_adjustment)
)
configuration.save(conf, args.config) configuration.save(conf, args.config)