Made it work again, automatic goal moves messing with me though
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user