mower-ng/mower/solvers/sss/sss_drop.py

164 lines
5.7 KiB
Python

from datetime import datetime, timedelta
import cv2
from mower.data import agent_list
from mower.utils import config
from mower.utils import typealias as tp
from mower.utils.character_recognize import match_portrait
from mower.utils.graph import SceneGraphSolver
from mower.utils.image import cropimg, loadres, thres2
from mower.utils.log import logger
from mower.utils.recognize import Scene
from mower.utils.vector import ss, va
from .utils import generate_image
agent = [
"无需增调干员",
"PIONEER",
"WARRIOR",
"TANK",
"CASTER",
"SNIPER",
"MEDIC",
"SUPPORT",
"SPECIAL",
]
class SSSDROPSolver(SceneGraphSolver):
solver_name = "保全增调干员或仪器"
def run(self) -> bool:
copilot = config.works["sss"]
self.drops = copilot.drops
self.choose = False
self.blacklist = set(copilot.blacklist)
self.success = True
self.start_time = datetime.now()
super().run()
return self.success
def timeout(self) -> bool:
return datetime.now() > self.start_time + timedelta(seconds=20)
def find_EC(self, drop: str, fs: int, scope: tp.Scope):
img = cropimg(config.recog.gray, scope)
res = generate_image(drop, fs)
result = cv2.matchTemplate(img, res, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
h, w = res.shape
logger.debug(f"drop:{drop},max_val:{max_val}")
if max_val > 0.8:
return va((max_loc[0], max_loc[1]), scope[0])
def find_PR_in_fight(self, drop: str, scope: tp.Scope):
img = cropimg(config.recog.img, scope)
res = loadres(f"sss/drop/{drop}")
res = cv2.resize(res, (61, 61), interpolation=cv2.INTER_LINEAR)
result = cv2.matchTemplate(img, res, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
h, w, _ = res.shape
logger.debug(f"drop:{drop},max_val:{max_val}")
if max_val > 0.8:
return va((max_loc[0], max_loc[1]), scope[0])
def match_operators(self):
img = cropimg(config.recog.gray, ((50, 231), (1900, 850)))
img = thres2(img, 38)
contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
rect = filter(
lambda x: x[2] > 200, map(lambda c: cv2.boundingRect(c), contours)
)
segment = []
for x, y, w, h in rect:
top_left = va((x, y), (50, 350))
bottom_right = va((x + w + 50, y + h + 231), (0, -230))
segment.append(ss(2 / 3, 2 / 3, (top_left, bottom_right)))
match_opers = dict(
match_portrait(
cv2.resize(config.recog.gray, (int(1920 / 1.5), int(1080 / 1.5))),
segment=segment,
)
)
logger.info(match_opers.keys())
res = {}
for name, scope in match_opers.items():
if name and name not in self.blacklist:
res[agent_list[name]["profession"]] = self.get_pos(ss(1.5, 1.5, scope))
logger.info(f"不在黑名单的干员:{res}")
return res
def transition(self):
if (scene := self.scene()) == Scene.SSS_DROP_AGENT_BEFORE_FIGHT:
if self.timeout():
self.success = False
return True
if self.choose and (
self.find("sss/drop_check") or self.find("sss/no_drop_check")
):
self.tap((1794, 900))
self.choose = False
self.sleep(2)
return
else:
opers = self.match_operators()
if pos := self.find("sss/drop/无需增调干员"):
opers["无需增调干员"] = pos
for drop in self.drops:
if drop in opers:
self.tap(opers[drop])
self.sleep(0.5)
self.choose = True
return
if len(opers):
self.tap(opers.popitem()[1])
self.sleep(0.5)
self.choose = True
return
elif scene == Scene.SSS_DROP_IN_FIGHT:
for drop in self.drops:
if drop not in agent:
if pos := self.find_EC(drop, 29, ((510, 700), (1480, 770))):
self.tap(pos)
self.sleep(0.5)
self.tap((1750, 550))
return
else:
if pos := self.find_PR_in_fight(drop, ((468, 735), (1321, 797))):
self.tap(pos)
self.sleep(0.5)
self.tap((1750, 550))
return
self.tap("sss/abandon")
elif scene == Scene.SSS_DROP_EC_BEFORE_FIGHT:
if self.timeout():
self.success = False
return True
if self.choose and self.find("sss/drop_check"):
self.tap((1794, 900))
return
else:
for drop in self.drops:
if drop not in agent:
if pos := self.find_EC(drop, 30, ((640, 630), (1280, 700))):
self.tap(pos)
self.sleep(0.5)
self.choose = True
return
elif scene == Scene.SSS_ABANDON_DROP_IN_FIGHT:
self.scene_graph_step(Scene.OPERATOR_FIGHT)
elif scene in [Scene.OPERATOR_FIGHT, Scene.SSS_ACTION]:
return True
elif scene in self.waiting_scene:
self.waiting_solver()
else:
return True