mower-ng/mower/solvers/fight/battle_choose/battle_agent_choose.py

196 lines
6.8 KiB
Python

import math
from copy import deepcopy
import cv2
from mower.data import agent_list
from mower.utils import config
from mower.utils.character_recognize import (
match_portrait,
operator_team_select,
)
from mower.utils.graph.utils import SceneGraphSolver
from mower.utils.log import logger
from mower.utils.scene import Scene
from .choose_skill import ChooseSkillSolver
class BattleAgentChooseSolver(SceneGraphSolver):
def run(self, agents: list) -> None:
if agents == []:
raise ValueError("干员列表为空")
self.agents = agents
self.agents_copy = deepcopy(agents)
self.cleard = False
self.filter = False
self.agent = None
self.choosed = []
self.final_check = False
self.check = []
self.lack = []
self.tmp_data = {}
self.swipe_time = 0
super().run()
return self.lack
def choose_agents(self):
if self.final_check:
check = self.get_agent_pos()
if check:
for i in check:
if i in self.choosed:
self.check.append(i)
if (len(self.check) + len(self.lack)) == len(self.agents):
return True
elif (len(self.check) + len(self.lack)) < len(self.agents):
self.swipe_noinertia((1000, 540), (-1900, 0))
return
else:
logger.error(f"{self.choosed-self.check} 确认失败")
return False
if pos := self.find("choose_agent/open_profession"):
self.tap(pos, interval=0.1)
if self.cleard is False:
if self.find("choose_agent/battle_empty"):
self.cleard = True
else:
self.tap_element("choose_agent/clear_battle", interval=0.1)
return
if self.agent is None:
if len(self.agents_copy) > 0:
self.agent = self.agents_copy.pop(0)
else:
self.final_check = True
self.tag_choosed()
return
elif self.agent["name"] not in self.choosed:
now_choose = self.get_agent_pos()
if self.agent["name"] in now_choose:
ChooseSkillSolver().run(self.agent["skill"])
self.choosed.append(self.agent["name"])
if len(self.agents_copy) > 0:
tmp = self.agents_copy.pop(0)
else:
self.final_check = True
self.tag_choosed()
return
if "opers" in tmp:
tag = agent_list[tmp["opers"][-1]["name"]]["profession"]
else:
tag = agent_list[tmp["name"]]["profession"]
if agent_list[self.agent["name"]]["profession"] == tag:
self.tag_choosed()
self.tag_choosed(tag)
self.agent = tmp
config.recog.update()
agents = dict(operator_team_select(config.recog.img))
if "opers" in self.agent:
# 太靠右点不下去,需要往左滑一点
if agents[i["name"]][0][0] > 1650:
self.wait_choose = None
self.swipe_noinertia((1000, 540), (-500, 0))
return
for i in self.agent["opers"]:
if i["name"] in agents.keys():
self.agent = i
self.tap(agents[i["name"]], interval=0.2)
return
else:
try:
# 太靠右点不下去,需要往左滑一点
if agents[self.agent["name"]][0][0] > 1650:
self.wait_choose = None
self.swipe_noinertia((1000, 540), (-500, 0))
return
self.tap(agents[self.agent["name"]], interval=0.2)
return
except KeyError:
if self.tag_choosed(agent_list[self.agent["name"]]["profession"]):
return
if set(agents.keys()).issubset(self.tmp_data.keys()):
self.swipe_time = self.swipe_time + 1
if self.swipe_time > 1:
logger.error(f"选择干员: {self.agent}失败 滑动次数过多")
self.lack.append(self.agent)
self.agent = None
return
else:
self.swipe_time = 0
self.swipe_noinertia((1000, 540), (-1900, 0))
self.tmp_data = agents
return
def get_agent_pos(self):
img = cv2.cvtColor(config.recog.img, cv2.COLOR_RGB2HSV)
img = cv2.inRange(img, (90, 200, 120), (200, 255, 255))
contours, _ = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
segments = []
for contour in contours:
if cv2.contourArea(contour) < 40000 or cv2.contourArea(contour) > 100000:
continue
# 近似轮廓
x, y, w, h = cv2.boundingRect(contour)
current_segment = ((x, y), (x + w, y + h))
is_close = False
for segment in segments:
if (
math.sqrt(
math.pow(segment[0][0] - current_segment[0][0], 2)
+ math.pow(segment[0][1] - current_segment[0][1], 2)
)
< 40
):
is_close = True
break
# 如果不相近,则添加到列表中
if not is_close:
segments.append(current_segment)
logger.debug(f"segments:{segments}")
return list(dict(match_portrait(config.recog.gray, segment=segments)).keys())
def tag_choosed(self, profession: str = "ALL"):
str = "choose_agent/profession/" + profession
if pos := self.find(str):
if arrow := self.find("choose_agent/profession/choose_arrow"):
if (
math.sqrt(
math.pow(pos[0][0] - arrow[0][0], 2)
+ math.pow(pos[0][1] - arrow[0][1], 2)
)
< 100
):
return False
else:
self.tap(pos[0], interval=0.2)
return True
else:
self.tap(pos[0], interval=0.2)
return True
def transition(self) -> bool:
if (scene := self.scene()) == Scene.OPERATOR_AGENT_SELECT:
return self.choose_agents()
elif scene == Scene.OPERATOR_SELECT:
self.tap_element("choose_agent/fast_select")
elif scene == Scene.SSS_SQUAD:
self.tap_element("sss/choose/fast_select")
elif scene in self.waiting_scene:
self.waiting_solver()
else:
return False