mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-28 20:55:44 +00:00
Hoist repeated APD score lookups (#8769)
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "AbstractAIScoreCalculator.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "AIScoreCalculatorSharedUtilities.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/ai/AIScoreUtilities.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/ai/AIStrategy.hpp"
|
||||
@@ -41,16 +43,44 @@ auto AbstractAIScoreCalculator::CalculateUnitsScoreComponents(
|
||||
|
||||
bool isLateGame = cachedCurrentRound > 18; // Inline IsLateGame for efficiency
|
||||
|
||||
// APDCache now has built-in thread-local caching - no need for PreCachedAPDs
|
||||
ActionPoints braveWaterCost = GetBraveWaterCost();
|
||||
|
||||
// Memoization cache for EffectiveDistance calls
|
||||
EffectiveDistanceCache distanceCache;
|
||||
|
||||
// Early return for empty game states
|
||||
const size_t estimatedUnitCount = cachedUnits->size();
|
||||
if (estimatedUnitCount == 0) { return UnitsScoreComponents{0.0, 0.0}; }
|
||||
|
||||
ActionPoints braveWaterCost = GetBraveWaterCost();
|
||||
|
||||
struct ResolvedActionPointDistances {
|
||||
const ActionPointDistances *notBraving = nullptr;
|
||||
const ActionPointDistances *braving = nullptr;
|
||||
};
|
||||
std::array<ResolvedActionPointDistances, BattalionTypeId::BattalionTypeId_MAX + 1>
|
||||
resolvedActionPointDistances{};
|
||||
|
||||
// A scoring call repeatedly asks for the same map/type APDs. Resolve each pointer once while
|
||||
// leaving ownership and cross-call caching with ActionPointDistancesCache.
|
||||
const auto notBravingApdFor = [&](int battalionTypeId, const BattalionTypeSPtr &battalionType) {
|
||||
auto &resolved = resolvedActionPointDistances[battalionTypeId];
|
||||
if (resolved.notBraving == nullptr) {
|
||||
resolved.notBraving = GetApdCache()->GetRaw(cachedHexMap, mapId, battalionType, false);
|
||||
}
|
||||
return resolved.notBraving;
|
||||
};
|
||||
const auto bravingApdFor = [&](int battalionTypeId, const BattalionTypeSPtr &battalionType) {
|
||||
if (!battalionType->allowsBraveWater) {
|
||||
return static_cast<const ActionPointDistances *>(nullptr);
|
||||
}
|
||||
|
||||
auto &resolved = resolvedActionPointDistances[battalionTypeId];
|
||||
if (resolved.braving == nullptr) {
|
||||
resolved.braving =
|
||||
GetApdCache()->GetRaw(cachedHexMap, mapId, battalionType, true, braveWaterCost);
|
||||
}
|
||||
return resolved.braving;
|
||||
};
|
||||
|
||||
// Memoization cache for EffectiveDistance calls
|
||||
EffectiveDistanceCache distanceCache;
|
||||
|
||||
std::vector<const Unit *> attackerUnits{};
|
||||
std::vector<const Unit *> defenderUnits{};
|
||||
// Pre-allocate vectors based on estimated unit ratios to avoid reallocations
|
||||
@@ -115,16 +145,8 @@ auto AbstractAIScoreCalculator::CalculateUnitsScoreComponents(
|
||||
// Cache battalion type reference to avoid shared_ptr atomic operations
|
||||
const auto &battalionType = GetBattalionType(static_cast<BattalionTypeId>(battTypeId));
|
||||
|
||||
// Cache APD lookups - same battalion type is used multiple times below
|
||||
const auto *notBravingApd =
|
||||
GetApdCache()->GetRaw(cachedHexMap, mapId, battalionType, false);
|
||||
const auto *bravingApd = battalionType->allowsBraveWater ? GetApdCache()->GetRaw(
|
||||
cachedHexMap,
|
||||
mapId,
|
||||
battalionType,
|
||||
true,
|
||||
braveWaterCost)
|
||||
: nullptr;
|
||||
const auto *notBravingApd = notBravingApdFor(battTypeId, battalionType);
|
||||
const auto *bravingApd = bravingApdFor(battTypeId, battalionType);
|
||||
|
||||
const auto &priorityList = std::ranges::find_if(
|
||||
attackerTargetPriorities,
|
||||
@@ -174,9 +196,7 @@ auto AbstractAIScoreCalculator::CalculateUnitsScoreComponents(
|
||||
// Cache battalion type reference to avoid shared_ptr atomic operations
|
||||
const auto &battalionType = GetBattalionType(static_cast<BattalionTypeId>(battTypeId));
|
||||
|
||||
// Cache APD lookups for this defender unit
|
||||
const auto *defenderNotBravingApd =
|
||||
GetApdCache()->GetRaw(cachedHexMap, mapId, battalionType, false);
|
||||
const auto *defenderNotBravingApd = notBravingApdFor(battTypeId, battalionType);
|
||||
|
||||
auto dv = UnitValue(
|
||||
unit,
|
||||
@@ -211,14 +231,8 @@ auto AbstractAIScoreCalculator::CalculateUnitsScoreComponents(
|
||||
const DIST_T thisDistance = distanceCache.GetOrCompute(
|
||||
attackerUnit,
|
||||
unit->location(),
|
||||
GetApdCache()->GetRaw(cachedHexMap, mapId, attackerBattalionType, false),
|
||||
attackerBattalionType->allowsBraveWater ? GetApdCache()->GetRaw(
|
||||
cachedHexMap,
|
||||
mapId,
|
||||
attackerBattalionType,
|
||||
true,
|
||||
braveWaterCost)
|
||||
: nullptr,
|
||||
notBravingApdFor(attackerBattTypeId, attackerBattalionType),
|
||||
bravingApdFor(attackerBattTypeId, attackerBattalionType),
|
||||
cachedHexMap);
|
||||
if (thisDistance < closestDistanceToEnemy) {
|
||||
closestDistanceToEnemy = thisDistance;
|
||||
@@ -241,19 +255,8 @@ auto AbstractAIScoreCalculator::CalculateUnitsScoreComponents(
|
||||
const DIST_T thisDistance = distanceCache.GetOrCompute(
|
||||
defenderUnit,
|
||||
unit->location(),
|
||||
GetApdCache()->GetRaw(
|
||||
cachedHexMap,
|
||||
mapId,
|
||||
defenderBattalionType,
|
||||
false),
|
||||
defenderBattalionType->allowsBraveWater
|
||||
? GetApdCache()->GetRaw(
|
||||
cachedHexMap,
|
||||
mapId,
|
||||
defenderBattalionType,
|
||||
true,
|
||||
braveWaterCost)
|
||||
: nullptr,
|
||||
notBravingApdFor(defenderBattTypeId, defenderBattalionType),
|
||||
bravingApdFor(defenderBattTypeId, defenderBattalionType),
|
||||
cachedHexMap);
|
||||
if (thisDistance < closestDistanceToFriendly) {
|
||||
closestDistanceToFriendly = thisDistance;
|
||||
|
||||
Reference in New Issue
Block a user