71 lines
2.8 KiB
Python
71 lines
2.8 KiB
Python
"""动作:把求解器算出的 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 动作引用本类。无可行交换时返回 False(pipeline 可据此
|
||
判定本局结束或刷新棋盘)。
|
||
"""
|
||
|
||
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
|