AutoFight使用场景图分类并导航到对应关卡
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful

This commit is contained in:
Elaina 2024-10-07 20:24:26 +08:00
parent 125464dc42
commit 83372c9751

View file

@ -5,20 +5,23 @@ from scipy.signal import argrelmax
from skimage.metrics import structural_similarity
from mower.models import secret_front
from mower.solvers.navigation import NavigationSolver
from mower.utils import config
from mower.utils import typealias as tp
from mower.utils.character_recognize import match_avatar
from mower.utils.graph import SceneGraphSolver
from mower.utils.image import cropimg, loadres, thres2
from mower.utils.log import logger
from mower.utils.solver import BaseSolver
from mower.utils.scene import Scene
from mower.utils.tile_pos import Calc, find_level
from mower.utils.vector import sa, va
class AutoFight(BaseSolver):
class AutoFight(SceneGraphSolver):
def run(self, level_name, opers, actions):
logger.info("Start: 自动战斗")
logger.info("地图坐标计算https://github.com/yuanyan3060/Arknights-Tile-Pos")
self.level_name = level_name
level = find_level(level_name, None)
self.calc = Calc(1920, 1080, level)
self.actions = actions
@ -101,39 +104,6 @@ class AutoFight(BaseSolver):
logger.debug(f"{min_val=} {min_loc=}")
return min_val <= 0.2
def in_fight(self) -> bool:
"是否在战斗中"
img = cropimg(config.recog.img, ((725, 16), (797, 76)))
img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
img = cv2.inRange(img, (12, 0, 0), (16, 255, 255))
tpl = loadres("fight/enemy", True)
result = cv2.matchTemplate(img, tpl, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
value = 0.4
logger.debug(f"{min_val}小于{value}则判定在战斗")
return min_val < value
def battle_complete(self) -> bool:
"识别行动是否结束"
img = cropimg(config.recog.gray, ((87, 268), (529, 383)))
img = thres2(img, 200)
tpl = loadres("fight/complete", True)
result = cv2.matchTemplate(img, tpl, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
value = 0.4
logger.debug(f"{min_val}小于{value}则判定行动结束/胜利")
return min_val < value
def battle_fail(self) -> bool:
"识别行动是否失败"
img = cropimg(config.recog.gray, ((1129, 455), (1626, 531)))
tpl = loadres("fight/failed_text", True)
result = cv2.matchTemplate(img, tpl, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
value = 0.05
logger.debug(f"{min_val}小于{value}则判定行动失败")
return min_val < value # 测试时数值很低基本为0或有其他方法
def update_operators(self):
"识别可部署的干员"
config.recog.update()
@ -273,44 +243,49 @@ class AutoFight(BaseSolver):
sleep(0.5)
def transition(self):
config.recog.update()
if not self.in_fight():
if self.battle_fail():
logger.warning("行动失败,请检查干员/练度")
return True
elif self.battle_complete():
logger.info("行动结束")
return True
else:
sleep(2)
if (scene := self.scene()) == Scene.OPERATOR_FIGHT:
if self.loading:
self.pause()
self.loading = False
self.update_operators()
self.play()
return
# if self.action is None:
# self.sleep(10)
# return
if self.loading:
self.pause()
self.loading = False
self.update_operators()
self.play()
return
if self.playing:
for w, d in self.watching.items():
if w not in self.location:
continue
x, y = self.location[w]
if self.skill_ready(x, y):
self.use_skill(x, y)
if d["skill_usage"] == 2:
d["skill_times"] -= 1
if d["skill_times"] <= 0:
del self.watching[w]
return
if self.playing:
for w, d in self.watching.items():
if w not in self.location:
continue
x, y = self.location[w]
if self.skill_ready(x, y):
self.use_skill(x, y)
if d["skill_usage"] == 2:
d["skill_times"] -= 1
if d["skill_times"] <= 0:
del self.watching[w]
return
if self.action["type"] == "SpeedUp":
self.toggle_speed()
elif self.action["type"] == "Deploy":
self.deploy()
elif self.action["type"] == "Retreat":
self.withdraw()
if self.action["type"] == "SpeedUp":
self.toggle_speed()
elif self.action["type"] == "Deploy":
self.deploy()
elif self.action["type"] == "Retreat":
self.withdraw()
elif scene == Scene.OPERATOR_FAILED:
logger.warning("行动失败,请检查干员/练度")
return True
elif scene == Scene.OPERATOR_FINISH:
logger.info("行动结束")
return True
elif scene == Scene.CONFIRM:
logger.warning("被顶号")
return True
elif scene in self.waiting_scene:
self.waiting_solver()
elif scene == Scene.OPERATOR_SELECT:
self.tap((1655, 781))
else:
NavigationSolver().run(self.level_name, mode="copy")