卫戍协议

This commit is contained in:
zhbaor 2024-11-19 00:52:34 +08:00
parent 7c1f2041c6
commit 21dc3d1793
25 changed files with 243 additions and 35 deletions

View file

@ -8,7 +8,9 @@ res_path = Path(res_path_name)
data = "from typing import Literal\n\nRes = Literal[\n" data = "from typing import Literal\n\nRes = Literal[\n"
references = {} references = {}
for i in sorted(res_path.glob("**/*.png"), key=lambda x: x.as_posix()): for i in sorted(res_path.glob("**/*"), key=lambda x: x.as_posix()):
if not i.is_file():
continue
res_name = i.as_posix() res_name = i.as_posix()
res_name = res_name.replace(res_path_name, "") res_name = res_name.replace(res_path_name, "")
res_name = res_name.replace(".png", "") res_name = res_name.replace(".png", "")

View file

@ -707,6 +707,38 @@
"label": "ROGUE_REFRESH_SHOP", "label": "ROGUE_REFRESH_SHOP",
"comment": "肉鸽商店刷新确认" "comment": "肉鸽商店刷新确认"
}, },
"1801": {
"label": "SP_MAIN",
"comment": "卫戍协议首页"
},
"1802": {
"label": "SP_DEFENCE",
"comment": "卫戍协议防守方策略"
},
"1803": {
"label": "SP_ACTION",
"comment": "卫戍协议玩家行动"
},
"1804": {
"label": "SP_AUTO",
"comment": "卫戍协议玩家发呆"
},
"1805": {
"label": "SP_GIVEUP_CONFIRM",
"comment": "卫戍协议放弃模拟确认"
},
"1806": {
"label": "SP_COMPLETE",
"comment": "卫戍协议结算"
},
"1807": {
"label": "SP_BACK_CONFIRM",
"comment": "卫戍协议回到主页确认"
},
"1808": {
"label": "SP_ANIMATION",
"comment": "卫戍协议动画"
},
"9998": { "9998": {
"label": "LOADING", "label": "LOADING",
"comment": "场景跳转时的等待界面" "comment": "场景跳转时的等待界面"

View file

@ -1,3 +0,0 @@
# Resources
资源文件,用于识别游戏中的元素和场景判定

BIN
mower/resources/double_confirm/stronghold_protocol_back.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
mower/resources/stronghold_protocol/action.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/stronghold_protocol/animation.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/stronghold_protocol/auto.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/stronghold_protocol/complete.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/stronghold_protocol/defence.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

BIN
mower/resources/stronghold_protocol/main.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/stronghold_protocol/medic.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/stronghold_protocol/start.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/stronghold_protocol/stop.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -5,13 +5,7 @@ import cv2
from mower.utils import config from mower.utils import config
from mower.utils.graph import SceneGraphSolver from mower.utils.graph import SceneGraphSolver
from mower.utils.image import loadres, saveimg
from mower.utils.log import logger from mower.utils.log import logger
from mower.utils.matcher import (
GOOD_DISTANCE_LIMIT,
flann,
keypoints_scale_invariant,
)
from mower.utils.scene import Scene from mower.utils.scene import Scene
from mower.utils.vector import va, vs from mower.utils.vector import va, vs
@ -72,30 +66,7 @@ class ActivityNavigation(SceneGraphSolver):
def transition(self) -> bool: def transition(self) -> bool:
if (scene := self.scene()) == Scene.TERMINAL_MAIN: if (scene := self.scene()) == Scene.TERMINAL_MAIN:
img = loadres("navigation/activity/terminal.jpg", True) self.terminal_entry("navigation/activity/terminal.jpg")
kp1, des1 = keypoints_scale_invariant(img)
kp2, des2 = config.recog.matcher.kp, config.recog.matcher.des
matches = flann.knnMatch(des1, des2, k=2)
good = []
for pair in matches:
if (len_pair := len(pair)) == 2:
x, y = pair
if x.distance < GOOD_DISTANCE_LIMIT * y.distance:
good.append(x)
elif len_pair == 1:
good.append(pair[0])
good = sorted(good, key=lambda x: x.distance)
debug_img = cv2.drawMatches(
img,
kp1,
config.recog.gray,
kp2,
good[:10],
None,
flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS,
)
saveimg(debug_img, "navigation")
self.tap(kp2[good[0].trainIdx].pt, interval=4)
elif scene == Scene.ACTIVITY_MAIN: elif scene == Scene.ACTIVITY_MAIN:
self.tap("navigation/activity/entry") self.tap("navigation/activity/entry")
elif scene == Scene.ACTIVITY_CHOOSE_LEVEL: elif scene == Scene.ACTIVITY_CHOOSE_LEVEL:

View file

@ -0,0 +1,62 @@
import cv2
from mower.solvers.fight.mixin import FightMixin
from mower.utils import config
from mower.utils.graph import SceneGraphSolver
from mower.utils.image import cropimg, thres2
from mower.utils.scene import Scene
from mower.utils.vector import va
class StrongholdProtocol(SceneGraphSolver, FightMixin):
solver_name = "卫戍协议"
def run(self):
self.buy = True
self.depoly = True
return super().run()
def transition(self):
if (scene := self.scene()) == Scene.TERMINAL_MAIN:
self.terminal_entry("stronghold_protocol/entry.jpg")
elif scene == Scene.SP_MAIN:
if pos := self.find("stronghold_protocol/stop"):
self.tap(pos)
return
self.tap((1664, 911))
elif scene == Scene.SP_DEFENCE:
if pos := self.find("stronghold_protocol/start"):
self.tap(pos)
return
self.buy = True
self.deploy = True
self.tap((383, 948))
elif scene == Scene.SP_ACTION:
img = cropimg(config.recog.gray, ((1045, 24), (1063, 46)))
img = cv2.bitwise_not(thres2(img, 127))
if config.recog.num.number_int("secret_front", img=img) >= 2:
self.back()
return
if self.buy:
for pos in [(407, 540), (804, 513), (875, 431)]:
self.tap(pos, interval=0.5)
if not self.find("stronghold_protocol/medic"):
break
self.tap((1056, 482))
self.buy = False
return
if self.deploy:
for pos in [(1475, 524), (1058, 746)]:
self.swipe_ext([(1602, 989), pos], [500], up_wait=100, interval=0.4)
if self.drag_success():
self.swipe_ext(
[pos, va(pos, (300, 0))], [200], up_wait=100, interval=0.4
)
self.deploy = False
break
return
self.tap((1827, 93))
elif scene == Scene.SP_AUTO:
self.sleep()
else:
self.scene_graph_step(Scene.TERMINAL_MAIN)

View file

@ -10,6 +10,7 @@ from . import (
rogue, rogue,
shop, shop,
sss, sss,
stronghold_protocol,
terminal, terminal,
) )
from .utils import DG, SceneGraphSolver, edge from .utils import DG, SceneGraphSolver, edge
@ -30,4 +31,5 @@ __all__ = [
"sss", "sss",
"terminal", "terminal",
"rogue", "rogue",
"stronghold_protocol",
] ]

View file

@ -52,6 +52,7 @@ from .utils import edge
@edge(Scene.OPERATOR_MANAGEMENT, Scene.NAVIGATION_BAR) @edge(Scene.OPERATOR_MANAGEMENT, Scene.NAVIGATION_BAR)
@edge(Scene.OPERATOR_DETAILS, Scene.NAVIGATION_BAR) @edge(Scene.OPERATOR_DETAILS, Scene.NAVIGATION_BAR)
@edge(Scene.ROGUE_INDEX, Scene.NAVIGATION_BAR) @edge(Scene.ROGUE_INDEX, Scene.NAVIGATION_BAR)
@edge(Scene.SP_MAIN, Scene.NAVIGATION_BAR)
def index_nav(solver: BaseSolver): def index_nav(solver: BaseSolver):
solver.tap("nav_button") solver.tap("nav_button")

View file

@ -0,0 +1,26 @@
from mower.utils.scene import Scene
from mower.utils.solver import BaseSolver
from .utils import edge
# 卫戍协议
@edge(Scene.SP_MAIN, Scene.TERMINAL_MAIN)
@edge(Scene.SP_DEFENCE, Scene.SP_MAIN)
@edge(Scene.SP_ACTION, Scene.SP_MAIN)
@edge(Scene.SP_AUTO, Scene.SP_BACK_CONFIRM)
@edge(Scene.SP_COMPLETE, Scene.SP_BACK_CONFIRM)
def sp_back(solver: BaseSolver):
solver.back()
@edge(Scene.SP_GIVEUP_CONFIRM, Scene.SP_MAIN)
@edge(Scene.SP_BACK_CONFIRM, Scene.SP_MAIN)
def dialog_confirm(solver: BaseSolver):
solver.tap("double_confirm/main", x_rate=1)
@edge(Scene.SP_ANIMATION, Scene.SP_ACTION)
def wait(solver: BaseSolver):
solver.sleep()

View file

@ -256,6 +256,10 @@ class Recognizer:
self.scene = Scene.ROGUE_REFRESH_SHOP self.scene = Scene.ROGUE_REFRESH_SHOP
elif self.find("double_confirm/headhunting"): elif self.find("double_confirm/headhunting"):
self.scene = Scene.HEADHUNTING_FREE_CONFIRM self.scene = Scene.HEADHUNTING_FREE_CONFIRM
elif self.find("double_confirm/stronghold_protocol_back"):
self.scene = Scene.SP_BACK_CONFIRM
elif self.find("double_confirm/stronghold_protocol_giveup"):
self.scene = Scene.SP_GIVEUP_CONFIRM
else: else:
self.scene = Scene.DOUBLE_CONFIRM self.scene = Scene.DOUBLE_CONFIRM
elif self.find("mission_trainee_on"): elif self.find("mission_trainee_on"):
@ -341,6 +345,17 @@ class Recognizer:
self.scene = Scene.SIGN_IN_ORUNDUM self.scene = Scene.SIGN_IN_ORUNDUM
elif self.find("start_story"): elif self.find("start_story"):
self.scene = Scene.STORY_STAGE self.scene = Scene.STORY_STAGE
elif self.find("stronghold_protocol/main"):
self.scene = Scene.SP_MAIN
elif self.find("stronghold_protocol/defence"):
self.scene = Scene.SP_DEFENCE
elif self.find("stronghold_protocol/auto"):
self.scene = Scene.SP_AUTO
elif self.find("stronghold_protocol/complete"):
self.scene = Scene.SP_COMPLETE
elif self.find("stronghold_protocol/animation"):
self.scene = Scene.SP_ANIMATION
elif self.is_black(): elif self.is_black():
self.scene = Scene.LOADING self.scene = Scene.LOADING
@ -434,6 +449,8 @@ class Recognizer:
self.scene = Scene.STORY_SKIP self.scene = Scene.STORY_SKIP
elif self.find("story_skip"): elif self.find("story_skip"):
self.scene = Scene.STORY self.scene = Scene.STORY
elif self.find("stronghold_protocol/action"):
self.scene = Scene.SP_ACTION
# 没弄完的 # 没弄完的
# elif self.find("ope_elimi_finished"): # elif self.find("ope_elimi_finished"):

View file

@ -37,6 +37,8 @@ color = {
"double_confirm/refresh_shop": (901, 435), "double_confirm/refresh_shop": (901, 435),
"double_confirm/sss": (901, 465), "double_confirm/sss": (901, 465),
"double_confirm/sss_abandon_drop": (901, 463), "double_confirm/sss_abandon_drop": (901, 463),
"double_confirm/stronghold_protocol_back": (1056, 437),
"double_confirm/stronghold_protocol_giveup": (921, 434),
"double_confirm/voice": (745, 435), "double_confirm/voice": (745, 435),
"drone": (274, 437), "drone": (274, 437),
"factory_collect": (1542, 886), "factory_collect": (1542, 886),
@ -160,6 +162,13 @@ color = {
"sss/switch_to_ex": (1255, 942), "sss/switch_to_ex": (1255, 942),
"sss/switch_to_normal": (1255, 934), "sss/switch_to_normal": (1255, 934),
"start_story": (1392, 623), "start_story": (1392, 623),
"stronghold_protocol/animation": (803, 391),
"stronghold_protocol/auto": (898, 56),
"stronghold_protocol/complete": (231, 101),
"stronghold_protocol/defence": (29, 14),
"stronghold_protocol/main": (1456, 472),
"stronghold_protocol/start": (1709, 879),
"stronghold_protocol/stop": (1272, 801),
"terminal_main": (1658, 734), "terminal_main": (1658, 734),
} }
@ -307,6 +316,8 @@ template_matching = {
"stone_fragment": None, "stone_fragment": None,
"story_skip": (1718, 58), "story_skip": (1718, 58),
"story_skip_confirm_dialog": ((685, 504), (1234, 730)), "story_skip_confirm_dialog": ((685, 504), (1234, 730)),
"stronghold_protocol/action": (849, 60),
"stronghold_protocol/medic": (37, 167),
"switch_order/check": None, "switch_order/check": None,
"switch_order/lmb": (1442, 891), "switch_order/lmb": (1442, 891),
"switch_order/oru": (1442, 891), "switch_order/oru": (1442, 891),

View file

@ -353,6 +353,22 @@ class Scene:
"放弃本次肉鸽探索" "放弃本次肉鸽探索"
ROGUE_REFRESH_SHOP = 1704 ROGUE_REFRESH_SHOP = 1704
"肉鸽商店刷新确认" "肉鸽商店刷新确认"
SP_MAIN = 1801
"卫戍协议首页"
SP_DEFENCE = 1802
"卫戍协议防守方策略"
SP_ACTION = 1803
"卫戍协议玩家行动"
SP_AUTO = 1804
"卫戍协议玩家发呆"
SP_GIVEUP_CONFIRM = 1805
"卫戍协议放弃模拟确认"
SP_COMPLETE = 1806
"卫戍协议结算"
SP_BACK_CONFIRM = 1807
"卫戍协议回到主页确认"
SP_ANIMATION = 1808
"卫戍协议动画"
LOADING = 9998 LOADING = 9998
"场景跳转时的等待界面" "场景跳转时的等待界面"
CONFIRM = 9999 CONFIRM = 9999
@ -537,6 +553,14 @@ SceneComment = {
1702: "肉鸽首页", 1702: "肉鸽首页",
1703: "放弃本次肉鸽探索", 1703: "放弃本次肉鸽探索",
1704: "肉鸽商店刷新确认", 1704: "肉鸽商店刷新确认",
1801: "卫戍协议首页",
1802: "卫戍协议防守方策略",
1803: "卫戍协议玩家行动",
1804: "卫戍协议玩家发呆",
1805: "卫戍协议放弃模拟确认",
1806: "卫戍协议结算",
1807: "卫戍协议回到主页确认",
1808: "卫戍协议动画",
9998: "场景跳转时的等待界面", 9998: "场景跳转时的等待界面",
9999: "确认对话框", 9999: "确认对话框",
} }

View file

@ -14,8 +14,9 @@ from mower.utils.csleep import MowerExit, csleep
from mower.utils.device.adb_client.const import KeyCode from mower.utils.device.adb_client.const import KeyCode
from mower.utils.device.adb_client.session import Session from mower.utils.device.adb_client.session import Session
from mower.utils.device.device import Device from mower.utils.device.device import Device
from mower.utils.image import cropimg, thres2 from mower.utils.image import cropimg, loadres, thres2
from mower.utils.log import logger from mower.utils.log import logger
from mower.utils.matcher import GOOD_DISTANCE_LIMIT, flann, keypoints_scale_invariant
from mower.utils.recognize import RecognizeError, Recognizer, Scene from mower.utils.recognize import RecognizeError, Recognizer, Scene
from mower.utils.simulator import restart_simulator from mower.utils.simulator import restart_simulator
from mower.utils.traceback import caller_info from mower.utils.traceback import caller_info
@ -642,3 +643,19 @@ class BaseSolver:
csleep(3) csleep(3)
self.check_current_focus() self.check_current_focus()
return False return False
def terminal_entry(self, res: tp.Res):
img = loadres(res, True)
kp1, des1 = keypoints_scale_invariant(img)
kp2, des2 = config.recog.matcher.kp, config.recog.matcher.des
matches = flann.knnMatch(des1, des2, k=2)
good = []
for pair in matches:
if (len_pair := len(pair)) == 2:
x, y = pair
if x.distance < GOOD_DISTANCE_LIMIT * y.distance:
good.append(x)
elif len_pair == 1:
good.append(pair[0])
good = sorted(good, key=lambda x: x.distance)
self.tap(kp2[good[0].trainIdx].pt, interval=4)

View file

@ -87,6 +87,8 @@ Res = Literal[
"double_confirm/refresh_shop", "double_confirm/refresh_shop",
"double_confirm/sss", "double_confirm/sss",
"double_confirm/sss_abandon_drop", "double_confirm/sss_abandon_drop",
"double_confirm/stronghold_protocol_back",
"double_confirm/stronghold_protocol_giveup",
"double_confirm/voice", "double_confirm/voice",
"drone", "drone",
"episode", "episode",
@ -175,6 +177,7 @@ Res = Literal[
"navigation/act/2", "navigation/act/2",
"navigation/activity/banner", "navigation/activity/banner",
"navigation/activity/entry", "navigation/activity/entry",
"navigation/activity/terminal.jpg",
"navigation/biography/OF_banner", "navigation/biography/OF_banner",
"navigation/biography/OF_entry", "navigation/biography/OF_entry",
"navigation/collection/AP-1", "navigation/collection/AP-1",
@ -504,6 +507,16 @@ Res = Literal[
"story_skip", "story_skip",
"story_skip_confirm_dialog", "story_skip_confirm_dialog",
"story_stage", "story_stage",
"stronghold_protocol/action",
"stronghold_protocol/animation",
"stronghold_protocol/auto",
"stronghold_protocol/complete",
"stronghold_protocol/defence",
"stronghold_protocol/entry.jpg",
"stronghold_protocol/main",
"stronghold_protocol/medic",
"stronghold_protocol/start",
"stronghold_protocol/stop",
"switch_order/check", "switch_order/check",
"switch_order/lmb", "switch_order/lmb",
"switch_order/oru", "switch_order/oru",