自动战斗列表(初版)

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:
def run(
self,
level_name,
opers,
actions,
level_name: str,
opers: list,
actions: list,
groups=[],
auto_choose: bool = True,
squad: int = None,
support_oper: list = [],
support_oper: str = "",
retry_times: int = 5,
):
"""
Args:
@ -20,27 +20,41 @@ class FightSolver:
actions: 行动列表
groups: 干员组列表
auto_choose: 是否自动选择干员编队
squad: 队伍编号
support_oper: 助战干员
min_elite: 助战干员精英化等级的最低要求
min_level: 助战干员等级的最低要求
retry_times: 助战刷新次数
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:
BattleChooseSolver().run(
if not BattleChooseSolver().run(
level_name,
opers,
groups,
squad,
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:
if "skill" not in oper:
oper["skill"] = 1
if "skill_usage" not in oper:
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("行动结束")
return True
elif scene == Scene.CONFIRM:
logger.warning("被顶号")
self.success = False
return True
elif scene in self.waiting_scene:
self.waiting_solver()
elif scene == Scene.OPERATOR_SELECT:

View file

@ -14,7 +14,6 @@ class BattleChooseSolver(SceneGraphSolver):
level_name: str = "",
opers: list = [],
groups: list = [],
squad: int = 0,
support_oper: list = [],
):
"""
@ -25,15 +24,18 @@ class BattleChooseSolver(SceneGraphSolver):
squad: 队伍编号
support_oper: 助战干员
"""
if squad:
ChooseSquadSolver().run(level_name, squad)
lack = BattleAgentChooseSolver().run(opers + groups)
if config.conf.work.squad:
ChooseSquadSolver().run(level_name, config.conf.work.squad)
lack = BattleAgentChooseSolver().run(opers + groups, level_name)
if len(lack) + len(support_oper) >= 2:
return False
if config.conf.choose.add_low_trust_opers:
num = 12 - len(opers) - len(groups) + len(lack)
BattleFillChooseSolver().run("信赖值", num)
super().run()
support_oper = support_oper if support_oper else lack
ChooseSupportSolver().run(support_oper)
return True
def transition(self):
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_tag_choose import BattleTagChoose
from mower.solvers.fight.battle_choose.choose_skill import ChooseSkillSolver
from mower.solvers.navigation import NavigationSolver
from mower.utils import config
from mower.utils.character_recognize import (
operator_team_select,
@ -15,7 +16,7 @@ from mower.utils.scene import Scene
class BattleAgentChooseSolver(SceneGraphSolver):
def run(self, agents: list) -> None:
def run(self, agents: list, level_name: str = "") -> None:
if agents == []:
raise ValueError("干员列表为空")
self.agents = agents
@ -29,6 +30,7 @@ class BattleAgentChooseSolver(SceneGraphSolver):
self.lack = []
self.tmp_data = None
self.tag = "ALL"
self.level_name = level_name
super().run()
return self.lack
@ -115,4 +117,4 @@ class BattleAgentChooseSolver(SceneGraphSolver):
elif scene in self.waiting_scene:
self.waiting_solver()
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_core import PydanticUndefined
from mower.utils.typealias import WorkItem
class ConfModel(BaseModel):
@model_validator(mode="before")
@ -124,12 +128,30 @@ class FightPart(ConfModel):
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
"作战中识别干员时暂停"
choose: ChooseConf
"自动选干员设置"
support: SupportConf
"借助战要求"
work: WorkConf
"自动作战列表设置"
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
from numpy.typing import NDArray
@ -34,3 +34,10 @@ BasePlan = Dict[str, List[str]]
# Parameter
ParamArgs = List[str]
# Work
class WorkItem(TypedDict):
stage: str
retry_times: int = 5
support_oper: str = ""