自动战斗列表(初版)

This commit is contained in:
Elaina 2024-11-01 20:59:42 +08:00
parent e3e8b8b44a
commit 58356eb328
7 changed files with 141 additions and 28 deletions

View file

@ -0,0 +1,71 @@
import json
from mower.solvers.fight import FightSolver
from mower.utils import config
from mower.utils.path import get_path
class Oper:
def __init__(self, name, skill=1):
self.name = name
self.skill = skill
# 定义哈希函数,以便在 set 中去重
def __hash__(self):
return hash((self.name, self.skill))
# 定义相等性判断
def __eq__(self, other):
if isinstance(other, Oper):
return self.name == other.name and self.skill == other.skill
return False
class CopyWorksSolver:
def run(self):
self.auto_choose = True
# if config.conf.work.try_select_all:
# self.init_all_opers_and_groups()
while len(config.conf.work.works):
# if config.conf.work.try_select_all and not self.auto_choose:
work = config.conf.work.works[0]
work_path = get_path(f"@app/works/{work["stage"]}.json")
with work_path.open("r", encoding="utf-8") as f:
work_data = json.load(f)
if not FightSolver().run(
work["stage"],
work_data["opers"],
work_data["actions"],
work_data["groups"],
self.auto_choose,
work["support_oper"],
work["retry_times"],
):
return
config.conf.work.works.pop(0)
def init_all_opers_and_groups(self):
all_opers = set()
all_groups = set()
for work in config.conf.work.works:
work_path = get_path(f"@app/works/{work["stage"]}.json")
with work_path.open("r", encoding="utf-8") as f:
work_data = json.load(f)
for oper in work_data["opers"]:
name = oper["name"]
skill = oper.get("skill", 1)
all_opers.add(Oper(name, skill))
for group in work_data["groups"]:
all_groups.add(group)
self.all_groups = [
group
for group in all_groups
if not any(
Oper(op["name"], op.get("skill", 1)) in all_opers
for op in group["opers"]
)
]
self.all_opers = list({"name": op.name, "skill": op.skill} for op in all_opers)
if len(all_opers) + len(all_groups) <= 12:
self.auto_choose = False

View file

@ -5,13 +5,13 @@ from .battle_choose import BattleChooseSolver
class FightSolver: class FightSolver:
def run( def run(
self, self,
level_name, level_name: str,
opers, opers: list,
actions, actions: list,
groups=[], groups=[],
auto_choose: bool = True, auto_choose: bool = True,
squad: int = None, support_oper: str = "",
support_oper: list = [], retry_times: int = 5,
): ):
""" """
Args: Args:
@ -20,27 +20,41 @@ class FightSolver:
actions: 行动列表 actions: 行动列表
groups: 干员组列表 groups: 干员组列表
auto_choose: 是否自动选择干员编队 auto_choose: 是否自动选择干员编队
squad: 队伍编号
support_oper: 助战干员 support_oper: 助战干员
min_elite: 助战干员精英化等级的最低要求 retry_times: 战斗失败重试次数
min_level: 助战干员等级的最低要求
retry_times: 助战刷新次数
""" """
opers = self.check_opers_skill(opers) self.check_opers_skill(opers, groups)
if support_oper:
support_oper = self.find_support_oper(support_oper, opers, groups)
if auto_choose: if auto_choose:
BattleChooseSolver().run( if not BattleChooseSolver().run(
level_name, level_name,
opers, opers,
groups, groups,
squad,
support_oper, support_oper,
) ):
AutoFight().run(level_name, opers, actions, groups) return False
while retry_times + 1:
if AutoFight().run(level_name, opers, actions, groups):
return True
retry_times -= 1
return False
def check_opers_skill(self, opers: list): def check_opers_skill(self, opers: list, groups: list):
for oper in opers: for oper in opers:
if "skill" not in oper: if "skill" not in oper:
oper["skill"] = 1 oper["skill"] = 1
if "skill_usage" not in oper: if "skill_usage" not in oper:
oper["skill_usage"] = 0 oper["skill_usage"] = 0
return opers for group in groups:
for oper in group["opers"]:
if "skill" not in oper:
oper["skill"] = 1
if "skill_usage" not in oper:
oper["skill_usage"] = 0
def find_support_oper(self, support_oper: str, opers: list, groups: list):
for op in opers + groups:
if op["name"] == support_oper:
op["support"] = True
return [op]

View file

@ -61,11 +61,6 @@ class AutoFight(SceneGraphSolver, FightMixin):
logger.info("行动结束") logger.info("行动结束")
return True return True
elif scene == Scene.CONFIRM:
logger.warning("被顶号")
self.success = False
return True
elif scene in self.waiting_scene: elif scene in self.waiting_scene:
self.waiting_solver() self.waiting_solver()
elif scene == Scene.OPERATOR_SELECT: elif scene == Scene.OPERATOR_SELECT:

View file

@ -14,7 +14,6 @@ class BattleChooseSolver(SceneGraphSolver):
level_name: str = "", level_name: str = "",
opers: list = [], opers: list = [],
groups: list = [], groups: list = [],
squad: int = 0,
support_oper: list = [], support_oper: list = [],
): ):
""" """
@ -25,15 +24,18 @@ class BattleChooseSolver(SceneGraphSolver):
squad: 队伍编号 squad: 队伍编号
support_oper: 助战干员 support_oper: 助战干员
""" """
if squad: if config.conf.work.squad:
ChooseSquadSolver().run(level_name, squad) ChooseSquadSolver().run(level_name, config.conf.work.squad)
lack = BattleAgentChooseSolver().run(opers + groups) lack = BattleAgentChooseSolver().run(opers + groups, level_name)
if len(lack) + len(support_oper) >= 2:
return False
if config.conf.choose.add_low_trust_opers: if config.conf.choose.add_low_trust_opers:
num = 12 - len(opers) - len(groups) + len(lack) num = 12 - len(opers) - len(groups) + len(lack)
BattleFillChooseSolver().run("信赖值", num) BattleFillChooseSolver().run("信赖值", num)
super().run() super().run()
support_oper = support_oper if support_oper else lack support_oper = support_oper if support_oper else lack
ChooseSupportSolver().run(support_oper) ChooseSupportSolver().run(support_oper)
return True
def transition(self): def transition(self):
if (scene := self.scene()) == Scene.OPERATOR_AGENT_SELECT: if (scene := self.scene()) == Scene.OPERATOR_AGENT_SELECT:

View file

@ -4,6 +4,7 @@ from mower.data import agent_list
from mower.solvers.fight.battle_choose.battle_filter import BattleFilterSolver from mower.solvers.fight.battle_choose.battle_filter import BattleFilterSolver
from mower.solvers.fight.battle_choose.battle_tag_choose import BattleTagChoose from mower.solvers.fight.battle_choose.battle_tag_choose import BattleTagChoose
from mower.solvers.fight.battle_choose.choose_skill import ChooseSkillSolver from mower.solvers.fight.battle_choose.choose_skill import ChooseSkillSolver
from mower.solvers.navigation import NavigationSolver
from mower.utils import config from mower.utils import config
from mower.utils.character_recognize import ( from mower.utils.character_recognize import (
operator_team_select, operator_team_select,
@ -15,7 +16,7 @@ from mower.utils.scene import Scene
class BattleAgentChooseSolver(SceneGraphSolver): class BattleAgentChooseSolver(SceneGraphSolver):
def run(self, agents: list) -> None: def run(self, agents: list, level_name: str = "") -> None:
if agents == []: if agents == []:
raise ValueError("干员列表为空") raise ValueError("干员列表为空")
self.agents = agents self.agents = agents
@ -29,6 +30,7 @@ class BattleAgentChooseSolver(SceneGraphSolver):
self.lack = [] self.lack = []
self.tmp_data = None self.tmp_data = None
self.tag = "ALL" self.tag = "ALL"
self.level_name = level_name
super().run() super().run()
return self.lack return self.lack
@ -115,4 +117,4 @@ class BattleAgentChooseSolver(SceneGraphSolver):
elif scene in self.waiting_scene: elif scene in self.waiting_scene:
self.waiting_solver() self.waiting_solver()
else: else:
return False NavigationSolver().run(self.level_name, mode="copy")

View file

@ -1,6 +1,10 @@
from typing import Literal
from pydantic import BaseModel, model_validator from pydantic import BaseModel, model_validator
from pydantic_core import PydanticUndefined from pydantic_core import PydanticUndefined
from mower.utils.typealias import WorkItem
class ConfModel(BaseModel): class ConfModel(BaseModel):
@model_validator(mode="before") @model_validator(mode="before")
@ -124,12 +128,30 @@ class FightPart(ConfModel):
refresh: int = 10 refresh: int = 10
"最大刷新次数" "最大刷新次数"
class WorkConf(ConfModel):
work_enable: bool = False
"是否执行自动作战列表"
squad: int = 0
"作战编队"
use_medicine: bool = False
"是否使用理智药"
enemy_breach_strategy: Literal["overlook", "give_up", "restart_game"] = (
"give_up"
)
"被敌人进入时采取的策略"
try_select_all: bool = False
"尝试一次性选择全部干员和干员组"
works: list[WorkItem] = []
"自动作战列表"
avatar_recog_pause: bool = False avatar_recog_pause: bool = False
"作战中识别干员时暂停" "作战中识别干员时暂停"
choose: ChooseConf choose: ChooseConf
"自动选干员设置" "自动选干员设置"
support: SupportConf support: SupportConf
"借助战要求" "借助战要求"
work: WorkConf
"自动作战列表设置"
class LongTaskPart(ConfModel): class LongTaskPart(ConfModel):

View file

@ -1,4 +1,4 @@
from typing import Dict, List, Tuple, Union from typing import Dict, List, Tuple, TypedDict, Union
import numpy as np import numpy as np
from numpy.typing import NDArray from numpy.typing import NDArray
@ -34,3 +34,10 @@ BasePlan = Dict[str, List[str]]
# Parameter # Parameter
ParamArgs = List[str] ParamArgs = List[str]
# Work
class WorkItem(TypedDict):
stage: str
retry_times: int = 5
support_oper: str = ""