perf: 优化肉鸽干员攻击范围计算、及一些部署逻辑等

This commit is contained in:
MistEO
2022-07-28 22:24:02 +08:00
parent d9837786fb
commit 4fa3e60150
5 changed files with 67 additions and 72 deletions

View File

@@ -1,17 +1,4 @@
[
{
"stage_name": "驯兽小屋",
"replacement_home": [
[
8,
3
],
[
8,
4
]
]
},
{
"stage_name": "巡逻队",
"replacement_home": [

View File

@@ -22,22 +22,26 @@ namespace asst
return iter->second.role;
}
static inline const BattleAttackRange& EmptyRange{ {0, 0} };
const BattleAttackRange& get_range(const std::string& name, size_t index) const
{
static const BattleAttackRange empty = { {0, 0} };
auto char_iter = m_chars.find(name);
if (char_iter == m_chars.cend()) {
return empty;
return EmptyRange;
}
const auto& ranges = char_iter->second.ranges;
if (index < 0 || index >= ranges.size()) {
return empty;
if (ranges.empty()) {
return EmptyRange;
}
index = 0;
}
const std::string& range_name = ranges.at(index);
auto range_iter = m_ranges.find(range_name);
if (range_iter == m_ranges.cend()) {
return empty;
return EmptyRange;
}
return range_iter->second;
}

View File

@@ -250,7 +250,7 @@ bool asst::RoguelikeBattleTaskPlugin::auto_battle()
wait_melee = true;
}
}
else if (m_used_tiles.size() == 1) {
else if (m_used_tiles.size() == 1 && m_homes.size() == 1) {
if (op.role == BattleRole::Medic) {
wait_medic = true;
}
@@ -301,10 +301,11 @@ bool asst::RoguelikeBattleTaskPlugin::auto_battle()
if (oper_name_analyzer.analyze()) {
oper_name_analyzer.sort_result_by_score();
oper_name = oper_name_analyzer.get_result().front().text;
opt_oper.name = oper_name;
}
// 计算最优部署位置及方向
const auto& [placed_loc, direction] = calc_best_plan(opt_oper.role);
const auto& [placed_loc, direction] = calc_best_plan(opt_oper);
// 将干员拖动到场上
Point placed_point = m_side_tile_info.at(placed_loc).pos;
@@ -526,10 +527,10 @@ bool asst::RoguelikeBattleTaskPlugin::wait_start()
// return placed_rect;
//}
asst::RoguelikeBattleTaskPlugin::DeployInfo asst::RoguelikeBattleTaskPlugin::calc_best_plan(BattleRole role)
asst::RoguelikeBattleTaskPlugin::DeployInfo asst::RoguelikeBattleTaskPlugin::calc_best_plan(const BattleRealTimeOper& oper)
{
auto buildable_type = Loc::All;
switch (role) {
switch (oper.role) {
case BattleRole::Medic:
case BattleRole::Support:
case BattleRole::Sniper:
@@ -594,7 +595,7 @@ asst::RoguelikeBattleTaskPlugin::DeployInfo asst::RoguelikeBattleTaskPlugin::cal
return DeployInfo();
}
m_used_tiles.clear();
return calc_best_plan(role);
return calc_best_plan(oper);
}
std::sort(available_locations.begin(), available_locations.end(), comp_dist);
@@ -613,12 +614,12 @@ asst::RoguelikeBattleTaskPlugin::DeployInfo asst::RoguelikeBattleTaskPlugin::cal
int min_dist = std::abs(near_loc.x - home.x) + std::abs(near_loc.y - home.y);
for (const auto& loc : available_locations) {
auto cur_result = calc_best_direction_and_score(loc, role);
auto cur_result = calc_best_direction_and_score(loc, oper);
// 离得远的要扣分
constexpr int DistWeights = -1050;
int extra_dist = std::abs(loc.x - home.x) + std::abs(loc.y - home.y) - min_dist;
int extra_dist_score = DistWeights * extra_dist;
if (role == BattleRole::Medic) { // 医疗干员离得远无所谓
if (oper.role == BattleRole::Medic) { // 医疗干员离得远无所谓
extra_dist_score = 0;
}
@@ -631,7 +632,7 @@ asst::RoguelikeBattleTaskPlugin::DeployInfo asst::RoguelikeBattleTaskPlugin::cal
return { best_location, best_direction };
}
std::pair<asst::Point, int> asst::RoguelikeBattleTaskPlugin::calc_best_direction_and_score(Point loc, BattleRole role)
std::pair<asst::Point, int> asst::RoguelikeBattleTaskPlugin::calc_best_direction_and_score(Point loc, const BattleRealTimeOper& oper)
{
LogTraceFunction;
@@ -658,51 +659,54 @@ std::pair<asst::Point, int> asst::RoguelikeBattleTaskPlugin::calc_best_direction
base_direction.x = sgn(loc.x - home_loc.x);
}
// 医疗反着算
if (role == BattleRole::Medic) {
if (oper.role == BattleRole::Medic) {
base_direction = -base_direction;
}
int64_t elite = m_status->get_number("Roguelike-" + oper.name).value_or(0);
// 按朝右算,后面根据方向做转换
std::vector<Point> right_attack_range = { Point(0, 0) };
BattleAttackRange right_attack_range = Resrc.battle_data().get_range(oper.name, elite);
switch (role) {
case BattleRole::Support:
right_attack_range = {
Point(-1, -1),Point(0, -1),Point(1, -1),Point(2, -1),
Point(-1, 0), Point(0, 0), Point(1, 0), Point(2, 0),
Point(-1, 1), Point(0, 1), Point(1, 1), Point(2, 1),
};
break;
case BattleRole::Caster:
right_attack_range = {
Point(0, -1),Point(1, -1),Point(2, -1),
Point(0, 0), Point(1, 0), Point(2, 0), Point(3, 0),
Point(0, 1), Point(1, 1), Point(2, 1),
};
break;
case BattleRole::Medic:
case BattleRole::Sniper:
right_attack_range = {
Point(0, -1),Point(1, -1),Point(2, -1),Point(3, -1),
Point(0, 0), Point(1, 0), Point(2, 0), Point(3, 0),
Point(0, 1), Point(1, 1), Point(2, 1), Point(3, 1),
};
break;
case BattleRole::Warrior:
right_attack_range = {
Point(0, 0), Point(1, 0), Point(2, 0)
};
break;
case BattleRole::Special:
case BattleRole::Tank:
case BattleRole::Pioneer:
case BattleRole::Drone:
right_attack_range = {
Point(0, 0), Point(1, 0)
};
break;
default:
break;
if (right_attack_range == BattleDataConfiger::EmptyRange) {
switch (oper.role) {
case BattleRole::Support:
right_attack_range = {
Point(-1, -1),Point(0, -1),Point(1, -1),Point(2, -1),
Point(-1, 0), Point(0, 0), Point(1, 0), Point(2, 0),
Point(-1, 1), Point(0, 1), Point(1, 1), Point(2, 1),
};
break;
case BattleRole::Caster:
right_attack_range = {
Point(0, -1),Point(1, -1),Point(2, -1),
Point(0, 0), Point(1, 0), Point(2, 0), Point(3, 0),
Point(0, 1), Point(1, 1), Point(2, 1),
};
break;
case BattleRole::Medic:
case BattleRole::Sniper:
right_attack_range = {
Point(0, -1),Point(1, -1),Point(2, -1),Point(3, -1),
Point(0, 0), Point(1, 0), Point(2, 0), Point(3, 0),
Point(0, 1), Point(1, 1), Point(2, 1), Point(3, 1),
};
break;
case BattleRole::Warrior:
right_attack_range = {
Point(0, 0), Point(1, 0), Point(2, 0)
};
break;
case BattleRole::Special:
case BattleRole::Tank:
case BattleRole::Pioneer:
case BattleRole::Drone:
right_attack_range = {
Point(0, 0), Point(1, 0)
};
break;
default:
break;
}
}
int max_score = 0;
@@ -721,7 +725,7 @@ std::pair<asst::Point, int> asst::RoguelikeBattleTaskPlugin::calc_best_direction
{ TileKey::Wall, 500 },
{ TileKey::Road, 1000 },
{ TileKey::Home, 500 },
{ TileKey::EnemyHome, 900 },
{ TileKey::EnemyHome, 1200 },
{ TileKey::Floor, 1000 },
{ TileKey::Hole, 0 },
{ TileKey::Telin, 700 },
@@ -745,7 +749,7 @@ std::pair<asst::Point, int> asst::RoguelikeBattleTaskPlugin::calc_best_direction
{ TileKey::Healing, 1000 },
};
switch (role) {
switch (oper.role) {
case BattleRole::Medic:
if (m_used_tiles.find(absolute_pos) != m_used_tiles.end()) // 根据哪个方向上人多决定朝向哪
score += 10000;

View File

@@ -41,11 +41,11 @@ namespace asst
Point direction;
};
DeployInfo calc_best_plan(BattleRole role);
DeployInfo calc_best_plan(const BattleRealTimeOper& oper);
// 计算摆放干员的朝向
// 返回滑动的方向、得分
std::pair<Point, int> calc_best_direction_and_score(Point loc, BattleRole role);
std::pair<Point, int> calc_best_direction_and_score(Point loc, const BattleRealTimeOper& oper);
bool m_opers_used = false;
int m_pre_hp = 0;

View File

@@ -81,9 +81,9 @@ int main([[maybe_unused]] int argc, char** argv)
AsstAppendTask(ptr, "Roguelike", R"(
{
"squad": "",
"roles": "先手必胜",
"core_char": "空弦"
"squad": "突击战术分队",
"roles": "近卫",
"core_char": "棘刺"
}
)");