94 lines
3.1 KiB
C++
94 lines
3.1 KiB
C++
#include "AiSystem.h"
|
|
|
|
#include <limits>
|
|
|
|
#include "GameConfig.h"
|
|
|
|
#include "AdvanceBehavior.h"
|
|
#include "AttackBehavior.h"
|
|
#include "BehaviorKind.h"
|
|
#include "DeliverScrapBehavior.h"
|
|
#include "EntityAdmin.h"
|
|
#include "RallyBehavior.h"
|
|
#include "RepairBehavior.h"
|
|
#include "RetreatBehavior.h"
|
|
#include "SalvageScrapBehavior.h"
|
|
#include "SelectedBehaviorComponent.h"
|
|
#include "StandbyBehavior.h"
|
|
#include "tracing.h"
|
|
|
|
namespace
|
|
{
|
|
// Records a behavior's score for its owning ship, keeping the highest seen.
|
|
// Considered high-priority first, so strict '>' breaks ties toward priority.
|
|
template <typename Behavior>
|
|
void consider(EntityAdmin& admin, BehaviorKind kind)
|
|
{
|
|
admin.forEach<Behavior, SelectedBehaviorComponent>(
|
|
[kind](entt::entity /*e*/, const Behavior& behavior,
|
|
SelectedBehaviorComponent& selected)
|
|
{
|
|
if (behavior.score > selected.bestScore)
|
|
{
|
|
selected.bestScore = behavior.score;
|
|
selected.winner = kind;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
AiSystem::AiSystem(const GameConfig& config)
|
|
: m_attackEvaluator(config.world.targeting)
|
|
{
|
|
}
|
|
|
|
void AiSystem::tick(EntityAdmin& admin, const BuildingSystem& buildings,
|
|
const DebrisSystem& debris)
|
|
{
|
|
TRACE();
|
|
|
|
// Phase 1: evaluators score behaviors and set their target data.
|
|
m_advanceEvaluator.evaluate(admin);
|
|
m_standbyEvaluator.evaluate(admin);
|
|
m_rallyEvaluator.evaluate(admin);
|
|
m_retreatEvaluator.evaluate(admin);
|
|
m_attackEvaluator.evaluate(admin);
|
|
m_repairEvaluator.evaluate(admin);
|
|
m_salvageScrapEvaluator.evaluate(admin, debris);
|
|
m_deliverScrapEvaluator.evaluate(admin, buildings);
|
|
|
|
// Phase 2: pick the highest-scoring behavior per ship.
|
|
selectWinningBehaviors(admin);
|
|
|
|
// Phase 3: executors run for the winning behavior.
|
|
m_advanceExecutor.execute(admin);
|
|
m_standbyExecutor.execute(admin);
|
|
m_rallyExecutor.execute(admin);
|
|
m_retreatExecutor.execute(admin);
|
|
m_attackExecutor.execute(admin);
|
|
m_repairExecutor.execute(admin);
|
|
m_salvageScrapExecutor.execute(admin);
|
|
m_deliverScrapExecutor.execute(admin, buildings);
|
|
}
|
|
|
|
void AiSystem::selectWinningBehaviors(EntityAdmin& admin)
|
|
{
|
|
TRACE();
|
|
admin.forEach<SelectedBehaviorComponent>(
|
|
[](entt::entity /*e*/, SelectedBehaviorComponent& selected)
|
|
{
|
|
selected.winner = BehaviorKind::None;
|
|
selected.bestScore = std::numeric_limits<float>::lowest();
|
|
});
|
|
|
|
// Highest priority first so ties resolve toward the more urgent behavior.
|
|
consider<RetreatBehavior>(admin, BehaviorKind::Retreat);
|
|
consider<AttackBehavior>(admin, BehaviorKind::Attack);
|
|
consider<RepairBehavior>(admin, BehaviorKind::Repair);
|
|
consider<SalvageScrapBehavior>(admin, BehaviorKind::SalvageScrap);
|
|
consider<DeliverScrapBehavior>(admin, BehaviorKind::DeliverScrap);
|
|
consider<RallyBehavior>(admin, BehaviorKind::Rally);
|
|
consider<StandbyBehavior>(admin, BehaviorKind::Standby);
|
|
consider<AdvanceBehavior>(admin, BehaviorKind::Advance);
|
|
}
|