happy-birds-cracker/src/hbc/actuator.py

71 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""动作:把求解器算出的 Swap 转成屏幕滑动ADB swipe
两层结构:
1. 纯函数 `swap_to_swipe(swap, grid)` —— 把交换转成 (x1,y1,x2,y2),便于离线测试。
2. `SwapAction` —— MaaFramework 自定义动作适配器(仅在装了 MaaFw 时可用)。
"""
from __future__ import annotations
from .config import GridConfig
from .solver import Solver, Swap
from .state import GameState
def swap_to_swipe(swap: Swap, grid: GridConfig) -> tuple[int, int, int, int]:
"""把一次交换映射为屏幕滑动起止像素坐标。
返回 (x1, y1, x2, y2):从 (x1,y1) 滑到 (x2,y2)。
重要:**水平交换一律从右往左滑**(起点在右、终点在左)。因为本游戏里
从左往右滑会触发返回/退出手势。交换两格的结果与滑动方向无关,所以反向滑同样有效。
上下滑动不受影响。
"""
p1 = grid.cell_center(swap.r1, swap.c1)
p2 = grid.cell_center(swap.r2, swap.c2)
if swap.r1 == swap.r2 and p1[0] < p2[0]:
# 水平交换且当前是左->右,交换起止,强制右->左
p1, p2 = p2, p1
return p1[0], p1[1], p2[0], p2[1]
# ---------------------------------------------------------------------------#
# MaaFramework 自定义动作适配器
# ---------------------------------------------------------------------------#
try:
from maa.custom_action import CustomAction # type: ignore
class SwapAction(CustomAction):
"""读取共享 Board -> 求最优交换 -> 通过控制器滑动。
在 pipeline 中以 Custom 动作引用本类。无可行交换时返回 Falsepipeline 可据此
判定本局结束或刷新棋盘)。
"""
def __init__(self, state: GameState, solver: Solver | None = None,
swipe_duration_ms: int = 200) -> None:
super().__init__()
self.state = state
self.solver = solver or Solver()
self.swipe_duration_ms = swipe_duration_ms
def run(self, context, argv) -> bool:
board = self.state.board
if board is None:
return False
result = self.solver.find_best_swap(board)
if result is None:
# 没有可行消除:交给 pipeline 处理(如洗牌/重识别)
return False
grid = self.state.grid_runtime or self.state.grid
x1, y1, x2, y2 = swap_to_swipe(result.swap, grid)
# MaaFw 控制器滑动;不同版本 API 名称可能为 post_swipe / swipe
controller = context.tasker.controller
controller.post_swipe(x1, y1, x2, y2, self.swipe_duration_ms).wait()
return True
except Exception: # pragma: no cover - 未安装 MaaFw 时跳过
SwapAction = None # type: ignore