Compare commits

...

8 commits

Author SHA1 Message Date
8ad03a02d0 适配源石锭花完
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-25 14:01:43 +08:00
34710de065 构想数量计算获取
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-25 13:39:35 +08:00
a52396d40d 调整招募点击位置 2024-12-25 13:38:48 +08:00
c88245f509 结算场景改为tap 2024-12-25 13:38:23 +08:00
49683082b5 适配通过两层选奖励
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-25 12:45:42 +08:00
623b0be8bc 减轻负荷优化 2024-12-25 12:44:03 +08:00
52a5661a3c 补充肉鸽超时 2024-12-25 12:19:25 +08:00
889e439658 节点选项数据移到类里 2024-12-25 12:18:17 +08:00
15 changed files with 107 additions and 39 deletions

View file

@ -827,6 +827,10 @@
"label": "ROGUE_SARKAZ_LIGHTEN_LOAD", "label": "ROGUE_SARKAZ_LIGHTEN_LOAD",
"comment": "舍弃负荷确认" "comment": "舍弃负荷确认"
}, },
"1729": {
"label": "ROGUE_AWARD_BEFORE_EXPLORE",
"comment": "上次通关两层后探索前奖励"
},
"9998": { "9998": {
"label": "LOADING", "label": "LOADING",
"comment": "场景跳转时的等待界面" "comment": "场景跳转时的等待界面"

BIN
mower/resources/rogue/choose_support.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -1,11 +1,13 @@
from datetime import timedelta from datetime import datetime, timedelta
from mower.utils import config from mower.utils import config
from mower.utils.email import send_message from mower.utils.email import send_message
from mower.utils.graph import SceneGraphSolver from mower.utils.graph import SceneGraphSolver
from mower.utils.log import logger
from mower.utils.recognize import Scene from mower.utils.recognize import Scene
from .choose_next_node import ChooseNextNodeSolver from .choose_next_node import ChooseNextNodeSolver
from .choose_support_award import ChooseSupportAwardSolver
from .node_option_select import NodeOptionSelectSolver from .node_option_select import NodeOptionSelectSolver
from .rogue_abandon_explore import RogueAbandonExploreSolver from .rogue_abandon_explore import RogueAbandonExploreSolver
from .rogue_navi import RogueNaviSolver from .rogue_navi import RogueNaviSolver
@ -33,6 +35,9 @@ class RogueSolver(SceneGraphSolver):
return self.full return self.full
def transition(self): def transition(self):
if self.deadline and self.deadline < datetime.now():
logger.info("任务打断肉鸽")
return True
if (scene := self.scene()) == Scene.ROGUE_INDEX: if (scene := self.scene()) == Scene.ROGUE_INDEX:
if self.animation(((0, 100), (450, 800)), interval=0.2, ratio=0.5): if self.animation(((0, 100), (450, 800)), interval=0.2, ratio=0.5):
return return
@ -49,13 +54,16 @@ class RogueSolver(SceneGraphSolver):
elif scene == Scene.ROGUE_TEAM_SELECT: elif scene == Scene.ROGUE_TEAM_SELECT:
return not RogueSelectTeamSolver().run("蓝图测绘分队") return not RogueSelectTeamSolver().run("蓝图测绘分队")
elif scene == Scene.ROGUE_AWARD_BEFORE_EXPLORE:
ChooseSupportAwardSolver().run()
elif scene == Scene.ROGUE_INIT_RECRUIT: elif scene == Scene.ROGUE_INIT_RECRUIT:
if pos := self.find("rogue/green_recruit"): if pos := self.find("rogue/green_recruit"):
self.ctap(pos, 2) self.ctap(pos, 2)
return return
self.tap((1820, 540)) self.tap((1820, 540))
elif scene == Scene.ROGUE_RECRUIT_AGENT_SELECT: elif scene == Scene.ROGUE_RECRUIT_AGENT_SELECT:
self.tap("rogue/check_recruit") self.tap((1450, 1010))
elif scene == Scene.ROGUE_ABANDON_RECRUIT: elif scene == Scene.ROGUE_ABANDON_RECRUIT:
self.ctap("double_confirm/main", 2, x_rate=1) self.ctap("double_confirm/main", 2, x_rate=1)

View file

@ -24,6 +24,7 @@ class ChooseNextNodeSolver(SceneGraphSolver):
def run(self): def run(self):
self.success = False self.success = False
self.start_time = datetime.now() self.start_time = datetime.now()
self.idea_num = None
super().run() super().run()
data.next_step = {} data.next_step = {}
if self.success and self.node_id: if self.success and self.node_id:
@ -32,11 +33,16 @@ class ChooseNextNodeSolver(SceneGraphSolver):
data.last_node_id = self.node_id data.last_node_id = self.node_id
logger.info(f"{data.next_step=}") logger.info(f"{data.next_step=}")
@property
def current_idea_num(self) -> int:
if self.idea_num is None:
self.idea_num = get_idea_num()
return self.idea_num
def get_next_node_id(self) -> str: def get_next_node_id(self) -> str:
current_idea_num = get_idea_num()
layer = detect_layer() layer = detect_layer()
logger.debug(f"{current_idea_num=} {layer=}") logger.debug(f"{self.current_idea_num=} {layer=}")
idea_num = current_idea_num if layer == 5 else current_idea_num - 2 idea_num = self.current_idea_num if layer == 5 else self.current_idea_num - 2
if config.conf.rogue.mode == 1: if config.conf.rogue.mode == 1:
compare_rules: list = [("紧急作战", True), ("length", True), ("idea", True)] compare_rules: list = [("紧急作战", True), ("length", True), ("idea", True)]
elif config.conf.rogue.mode == 0: elif config.conf.rogue.mode == 0:
@ -53,6 +59,8 @@ class ChooseNextNodeSolver(SceneGraphSolver):
if not refresh_time: if not refresh_time:
continue continue
road = get_optimal_path(node_id, idea_num) road = get_optimal_path(node_id, idea_num)
if road.idea > self.current_idea_num:
continue
valid_road.append(road) valid_road.append(road)
if not valid_road: if not valid_road:
self.node_id = "" self.node_id = ""
@ -139,13 +147,11 @@ class ChooseNextNodeSolver(SceneGraphSolver):
f"{type=} {data.nodes[self.node_id].type=} {data.next_step=}" f"{type=} {data.nodes[self.node_id].type=} {data.next_step=}"
) )
data.nodes[self.node_id].type = node_type data.nodes[self.node_id].type = node_type
if data.next_step[self.node_id] == 0: # 第二次刷新时,构想数量-1
self.idea_num -= 1
return return
self.tap("rogue/refresh") self.tap("rogue/refresh")
return return
if self.need_idea > get_idea_num():
data.next_step[self.node_id] = 0
return
self.ctap("rogue/go", 3) self.ctap("rogue/go", 3)
self.success = True self.success = True

View file

@ -0,0 +1,26 @@
from mower.utils.graph import SceneGraphSolver
from mower.utils.recognize import Scene
from .utils.utils import find_text
class ChooseSupportAwardSolver(SceneGraphSolver):
solver_name = "选择支援奖励"
_award = ["做思想准备", "随手拿点啥", "出发前演讲", "储备金支援"]
def transition(self):
if (scene := self.scene()) == Scene.ROGUE_AWARD_BEFORE_EXPLORE:
if self.animation(interval=0.2):
return
if pos := self.find("rogue/team_check_to_do"):
self.ctap(pos, 3)
return
for text in self._award:
if pos := find_text(text, 39, scope=((250, 600), (1750, 800))):
self.tap(pos)
return
elif scene in self.waiting_scene:
self.waiting_solver()
else:
return True

View file

@ -21,21 +21,6 @@ node_type = {
] ]
} }
node_option = {
"Sarkaz": {
"相遇": ["它邀请对方共享猎物"],
"在故事结束之后": ["时光的永恒在此定格", "战士的长角生根发芽"],
"虫卡兹!": ["这怎么可能嘛?"],
"阴魂不散": ["问他为什么哭"],
"戴冠式": ["兄长为妹妹戴上冠冕"],
"高空坠物": ["找些帮手来把这里搬空", "从中寻找有用的物件"],
"前瞻": ["留意当下"],
"原初异途": ["一个方盒", "那是一只角,还是一把铳?"],
"待诉说的真相": ["收集散落的思绪"],
"解惑": ["他们的头顶都生出了光环", "萨科塔杀死了萨卡兹"],
}
}
class Node: class Node:
def __init__(self, scope): def __init__(self, scope):

View file

@ -6,6 +6,7 @@ class LightenLoadSolver(SceneGraphSolver):
solver_name = "减轻负荷" solver_name = "减轻负荷"
def run(self): def run(self):
self.check = False
super().run() super().run()
def transition(self): def transition(self):
@ -13,10 +14,14 @@ class LightenLoadSolver(SceneGraphSolver):
self.ctap("rogue/Sarkaz_load/lose", 3) self.ctap("rogue/Sarkaz_load/lose", 3)
elif scene == Scene.ROGUE_SARKAZ_LOAD: elif scene == Scene.ROGUE_SARKAZ_LOAD:
if self.animation(interval=0.2):
return
if not self.find("rogue/Sarkaz_load/block"): if not self.find("rogue/Sarkaz_load/block"):
self.scene_graph_step(Scene.ROGUE_MAIN) self.scene_graph_step(Scene.ROGUE_MAIN)
return return
if not self.find("rogue/Sarkaz_load/concentrate"): if self.find("rogue/Sarkaz_load/concentrate"):
self.check = True
elif not self.check:
self.ctap((1800, 180), 2) self.ctap((1800, 180), 2)
return return
if pos := self.find("rogue/Sarkaz_load/idea"): if pos := self.find("rogue/Sarkaz_load/idea"):

View file

@ -5,23 +5,33 @@ from mower.utils.graph import SceneGraphSolver
from mower.utils.log import logger from mower.utils.log import logger
from mower.utils.recognize import Scene from mower.utils.recognize import Scene
from . import data
from .utils.utils import find_text from .utils.utils import find_text
class NodeOptionSelectSolver(SceneGraphSolver): class NodeOptionSelectSolver(SceneGraphSolver):
solver_name = "节点选项选择" solver_name = "节点选项选择"
_option = {
def run(self): "Sarkaz": {
super().run() "相遇": ["它邀请对方共享猎物"],
"在故事结束之后": ["时光的永恒在此定格", "战士的长角生根发芽"],
"虫卡兹!": ["这怎么可能嘛?"],
"阴魂不散": ["问他为什么哭"],
"戴冠式": ["兄长为妹妹戴上冠冕"],
"高空坠物": ["找些帮手来把这里搬空", "从中寻找有用的物件"],
"前瞻": ["留意当下"],
"原初异途": ["一个方盒", "那是一只角,还是一把铳?"],
"待诉说的真相": ["收集散落的思绪"],
"解惑": ["他们的头顶都生出了光环", "萨科塔杀死了萨卡兹"],
}
}
@cached_property @cached_property
def options(self): def options(self):
for stage_name in data.node_option[config.conf.maa_rg_theme]: for stage_name in self._option[config.conf.maa_rg_theme]:
if find_text( if find_text(
stage_name, 36, scope=([165, 700], [165 + len(stage_name) * 50, 800]) stage_name, 36, scope=([165, 700], [165 + len(stage_name) * 50, 800])
): ):
return data.node_option[config.conf.maa_rg_theme][stage_name] return self._option[config.conf.maa_rg_theme][stage_name]
logger.error("未登记节点选项") logger.error("未登记节点选项")
return [] return []

View file

@ -1,31 +1,40 @@
from mower.utils.graph import SceneGraphSolver from mower.utils.graph import SceneGraphSolver
from mower.utils.recognize import Scene from mower.utils.recognize import Scene
from .utils.utils import get_money_num
class RogueShopSolver(SceneGraphSolver): class RogueShopSolver(SceneGraphSolver):
solver_name = "诡意行商投资" solver_name = "诡意行商投资"
def run(self):
super().run()
def transition(self): def transition(self):
if (scene := self.scene()) == Scene.ROGUE_SHOP: if (scene := self.scene()) == Scene.ROGUE_SHOP:
if self.animation(((0, 150), (1920, 880)), interval=0.2, ratio=0.2): if self.animation(((0, 150), (1920, 880)), interval=0.2, ratio=0.2):
return return
if self.find("rogue/shop/full_1") or self.find("rogue/shop/stop_invest"): if (
self.find("rogue/shop/full_1")
or self.find("rogue/shop/stop_invest")
or get_money_num() == 0
):
self.tap((1800, 830)) self.tap((1800, 830))
return return
self.tap((750, 360)) self.tap((750, 360))
elif scene == Scene.ROGUE_INVESTMENT_PORTAL: elif scene == Scene.ROGUE_INVESTMENT_PORTAL:
if self.find("rogue/shop/full_2") or self.find("rogue/shop/stop_service"): if (
self.find("rogue/shop/full_2")
or self.find("rogue/shop/stop_service")
or get_money_num() == 0
):
self.ctap((1200, 750), 3) self.ctap((1200, 750), 3)
return return
self.tap("rogue/shop/investment_portal") self.tap("rogue/shop/investment_portal")
elif scene == Scene.ROGUE_INVESTMENT: elif scene == Scene.ROGUE_INVESTMENT:
if self.find("rogue/shop/full_3") or self.find( if (
"rogue/shop/restricted_investment" self.find("rogue/shop/full_3")
or self.find("rogue/shop/restricted_investment")
or get_money_num() == 0
): ):
self.ctap((940, 740), 3) self.ctap((940, 740), 3)
return return

View file

@ -47,3 +47,7 @@ def get_idea_num() -> int:
return config.recog.num.number_int( return config.recog.num.number_int(
"secret_front", ((1265, 1025), (1350, 1070)), 32, 120 "secret_front", ((1265, 1025), (1350, 1070)), 32, 120
) )
def get_money_num() -> int:
return config.recog.num.number_int("riic_base", ((1760, 30), (1880, 70)), 25, 130)

View file

@ -6,6 +6,7 @@ from .utils import edge
@edge(Scene.UNKNOWN_ROGUE, Scene.ROGUE_INDEX) @edge(Scene.UNKNOWN_ROGUE, Scene.ROGUE_INDEX)
@edge(Scene.ROGUE_SELECT, Scene.ROGUE_INDEX) @edge(Scene.ROGUE_SELECT, Scene.ROGUE_INDEX)
@edge(Scene.ROGUE_AWARD_BEFORE_EXPLORE, Scene.ROGUE_INDEX)
@edge(Scene.ROGUE_TEAM_SELECT, Scene.ROGUE_INDEX) @edge(Scene.ROGUE_TEAM_SELECT, Scene.ROGUE_INDEX)
@edge(Scene.ROGUE_INIT_RECRUIT, Scene.ROGUE_INDEX) @edge(Scene.ROGUE_INIT_RECRUIT, Scene.ROGUE_INDEX)
@edge(Scene.ROGUE_RECRUIT_SELECT, Scene.ROGUE_INDEX) @edge(Scene.ROGUE_RECRUIT_SELECT, Scene.ROGUE_INDEX)
@ -32,7 +33,7 @@ def to_rogue_main(solver: BaseSolver):
@edge(Scene.ROGUE_LEVEL_UP, Scene.ROGUE_INDEX) @edge(Scene.ROGUE_LEVEL_UP, Scene.ROGUE_INDEX)
@edge(Scene.ROGUE_SETTLEMENT, Scene.ROGUE_INDEX) @edge(Scene.ROGUE_SETTLEMENT, Scene.ROGUE_INDEX)
def settlement_to_index(solver: BaseSolver): def settlement_to_index(solver: BaseSolver):
solver.ctap((960, 950), 3) solver.tap((960, 950))
@edge(Scene.ROGUE_ABANDON, Scene.ROGUE_INDEX) @edge(Scene.ROGUE_ABANDON, Scene.ROGUE_INDEX)

View file

@ -331,6 +331,8 @@ class Recognizer:
elif self.find("rogue/back"): elif self.find("rogue/back"):
if self.find("rogue/select_team"): if self.find("rogue/select_team"):
self.scene = Scene.ROGUE_TEAM_SELECT self.scene = Scene.ROGUE_TEAM_SELECT
elif self.find("rogue/choose_support"):
self.scene = Scene.ROGUE_AWARD_BEFORE_EXPLORE
elif self.find("rogue/init_recruit"): elif self.find("rogue/init_recruit"):
self.scene = Scene.ROGUE_INIT_RECRUIT self.scene = Scene.ROGUE_INIT_RECRUIT
elif self.find("rogue/select_recruit_combination"): elif self.find("rogue/select_recruit_combination"):

View file

@ -115,6 +115,7 @@ color = {
"rogue/action": (1430, 964), "rogue/action": (1430, 964),
"rogue/back": ((28, 14), (264, 14)), "rogue/back": ((28, 14), (264, 14)),
"rogue/check_recruit": (1705, 997), "rogue/check_recruit": (1705, 997),
"rogue/choose_support": (940, 33),
"rogue/double_confirm/check_blank": (802, 563), "rogue/double_confirm/check_blank": (802, 563),
"rogue/double_confirm/main": (906, 678), "rogue/double_confirm/main": (906, 678),
"rogue/double_confirm/no_more_tips": (977, 559), "rogue/double_confirm/no_more_tips": (977, 559),

View file

@ -413,6 +413,8 @@ class Scene:
"思维负荷" "思维负荷"
ROGUE_SARKAZ_LIGHTEN_LOAD = 1728 ROGUE_SARKAZ_LIGHTEN_LOAD = 1728
"舍弃负荷确认" "舍弃负荷确认"
ROGUE_AWARD_BEFORE_EXPLORE = 1729
"上次通关两层后探索前奖励"
LOADING = 9998 LOADING = 9998
"场景跳转时的等待界面" "场景跳转时的等待界面"
CONFIRM = 9999 CONFIRM = 9999
@ -627,6 +629,7 @@ SceneComment = {
1726: "前瞻性投资", 1726: "前瞻性投资",
1727: "思维负荷", 1727: "思维负荷",
1728: "舍弃负荷确认", 1728: "舍弃负荷确认",
1729: "上次通关两层后探索前奖励",
9998: "场景跳转时的等待界面", 9998: "场景跳转时的等待界面",
9999: "确认对话框", 9999: "确认对话框",
} }

View file

@ -408,6 +408,7 @@ Res = Literal[
"rogue/action", "rogue/action",
"rogue/back", "rogue/back",
"rogue/check_recruit", "rogue/check_recruit",
"rogue/choose_support",
"rogue/double_confirm/check_blank", "rogue/double_confirm/check_blank",
"rogue/double_confirm/confusion", "rogue/double_confirm/confusion",
"rogue/double_confirm/main", "rogue/double_confirm/main",