196 lines
6.8 KiB
Python
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
|