自动战斗列表(初版)
This commit is contained in:
parent
e3e8b8b44a
commit
58356eb328
7 changed files with 141 additions and 28 deletions
71
mower/solvers/copy_works.py
Normal file
71
mower/solvers/copy_works.py
Normal 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
|
|
@ -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]
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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 = ""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue