refactor AI system

This commit is contained in:
2026-06-15 09:16:56 +02:00
parent 8451f5a281
commit e8dd73bcb0
67 changed files with 1731 additions and 919 deletions

View File

@@ -0,0 +1,9 @@
#pragma once
// Baseline fallback behavior, present on every ship. The executor moves the ship
// toward the opposing side (direction derived from FactionComponent), so a ship
// with no better behavior keeps advancing.
struct AdvanceBehavior
{
float score = 0.0f;
};

View File

@@ -0,0 +1,13 @@
#pragma once
#include <optional>
#include "entt/entity/entity.hpp"
// Combat behavior for ships with weapons (was ThreatResponseBehaviorComponent).
// The evaluator sets currentTarget; the executor pushes it to in-range weapons.
struct AttackBehavior
{
std::optional<entt::entity> currentTarget;
float score = 0.0f;
};

View File

@@ -0,0 +1,15 @@
#pragma once
// Identifies a ship behavior. Written into SelectedBehaviorComponent by the
// AiSystem selection pass so each behavior's executor can tell whether it won.
enum class BehaviorKind
{
None,
Advance,
Rally,
Retreat,
Attack,
Repair,
SalvageScrap,
DeliverScrap
};

View File

@@ -0,0 +1,22 @@
#pragma once
// Score bands for ship-behavior evaluation. The AiSystem selection pass picks
// the behavior with the highest score per ship; these constants define a single
// comparable scale so the desired priority falls out:
// Retreat > Attack > Repair / Salvage / Deliver > Rally > Advance.
// Evaluators may return kInactive when their behavior does not apply this tick.
namespace BehaviorScores
{
constexpr float kInactive = 0.0f;
constexpr float kAdvance = 0.05f; // baseline fallback; always present
constexpr float kRally = 0.20f;
constexpr float kDeliver = 0.50f; // cargo full
constexpr float kRepair = 0.55f;
constexpr float kSalvage = 0.55f; // cargo not full and scrap in range
constexpr float kAttack = 0.60f; // healthy and target in sensor range
constexpr float kRetreat = 0.90f;
// Health fraction at/below which a ship is considered "low HP" — used by the
// Attack evaluator (do not attack when low) and the Retreat evaluator.
constexpr float kLowHpFraction = 0.3f;
}

View File

@@ -1,24 +1,29 @@
SET(HDRS
${HDRS}
${CMAKE_CURRENT_SOURCE_DIR}/AdvanceBehavior.h
${CMAKE_CURRENT_SOURCE_DIR}/AttackBehavior.h
${CMAKE_CURRENT_SOURCE_DIR}/BehaviorKind.h
${CMAKE_CURRENT_SOURCE_DIR}/BehaviorScores.h
${CMAKE_CURRENT_SOURCE_DIR}/DeliverScrapBehavior.h
${CMAKE_CURRENT_SOURCE_DIR}/DespawnAtComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/DynamicBodyComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/FacingComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/FactionComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/HealthComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/HomeReturnBehaviorComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/HqProxyComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/MovementIntentComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/PositionComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/RallyBehaviorComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/RepairBehaviorComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/RallyBehavior.h
${CMAKE_CURRENT_SOURCE_DIR}/RepairBehavior.h
${CMAKE_CURRENT_SOURCE_DIR}/RepairToolComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/SalvageBehaviorComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/RetreatBehavior.h
${CMAKE_CURRENT_SOURCE_DIR}/SalvageCargoComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/SalvageScrapBehavior.h
${CMAKE_CURRENT_SOURCE_DIR}/ScrapDataComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/SelectedBehaviorComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/SensorRangeComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/ShipIdentityComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/StationBodyComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/ThreatResponseBehaviorComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/WeaponComponent.h
PARENT_SCOPE
)

View File

@@ -0,0 +1,12 @@
#pragma once
#include "BuildingId.h"
// Deliver-scrap behavior (one half of the old SalvageBehaviorComponent). Scored
// high only when cargo is full. The evaluator assigns the nearest SalvageBay;
// SalvagerSystem performs the actual delivery.
struct DeliverScrapBehavior
{
BuildingId deliveryBay = kInvalidBuildingId;
float score = 0.0f;
};

View File

@@ -1,9 +0,0 @@
#pragma once
#include <QVector2D>
struct HomeReturnBehaviorComponent
{
float retreatHpFraction;
QVector2D homePos;
};

View File

@@ -2,11 +2,12 @@
#include <QVector2D>
// A ship-behavior system writes this each tick before movement runs; the
// highest-priority write wins. Priority order is fixed globally — see
// architecture.md "Movement Arbitration".
// The winning behavior's executor writes this each tick before movement runs.
// `active` is false when no behavior set a destination (the ship brakes); the
// score-based selection (see architecture.md "Movement Arbitration") decides
// which single executor writes here.
struct MovementIntentComponent
{
int priority;
bool active = false;
QVector2D target;
};

View File

@@ -0,0 +1,11 @@
#pragma once
#include <QVector2D>
// Player combat ships loiter at the rally point until the departure timer
// removes this component (ShipSystem::triggerRallyDeparture).
struct RallyBehavior
{
QVector2D rallyPoint;
float score = 0.0f;
};

View File

@@ -1,8 +0,0 @@
#pragma once
#include <QVector2D>
struct RallyBehaviorComponent
{
QVector2D rallyPoint;
};

View File

@@ -0,0 +1,15 @@
#pragma once
#include <optional>
#include "entt/entity/entity.hpp"
// Repair behavior for ships with repair modules. The evaluator picks the nearest
// damaged friendly as currentTarget; the executor moves toward it and assigns
// in-range repair tools. RepairSystem applies the actual healing.
struct RepairBehavior
{
std::optional<entt::entity> currentTarget;
float maxRepairRange_tiles = 0.0f;
float score = 0.0f;
};

View File

@@ -1,11 +0,0 @@
#pragma once
#include <optional>
#include "entt/entity/entity.hpp"
struct RepairBehaviorComponent
{
std::optional<entt::entity> currentTarget;
float maxRepairRange_tiles = 0.0f;
};

View File

@@ -0,0 +1,13 @@
#pragma once
#include <QVector2D>
// Player-only retreat behavior (replaces HomeReturnBehaviorComponent). Scored
// high when HP is low, or when an enemy is in sensor range and the ship cannot
// fight back. The executor moves the ship to retreatPoint (the rally point).
struct RetreatBehavior
{
float retreatHpFraction = 0.0f;
QVector2D retreatPoint;
float score = 0.0f;
};

View File

@@ -1,14 +0,0 @@
#pragma once
#include <optional>
#include <QVector2D>
#include "BuildingId.h"
struct SalvageBehaviorComponent
{
std::optional<QVector2D> scrapTarget;
BuildingId deliveryBay; // kInvalidBuildingId until assigned at a salvage bay
float maxCollectionRange_tiles = 0.0f;
};

View File

@@ -0,0 +1,14 @@
#pragma once
#include <optional>
#include <QVector2D>
// Collect-scrap behavior (one half of the old SalvageBehaviorComponent). The
// evaluator finds the nearest scrap and sets scrapTarget when cargo is not full.
struct SalvageScrapBehavior
{
std::optional<QVector2D> scrapTarget;
float maxCollectionRange_tiles = 0.0f;
float score = 0.0f;
};

View File

@@ -0,0 +1,11 @@
#pragma once
#include "BehaviorKind.h"
// Result of the AiSystem selection pass: the highest-scoring behavior for a
// ship this tick. Each behavior's executor acts only when it is the winner.
struct SelectedBehaviorComponent
{
BehaviorKind winner = BehaviorKind::None;
float bestScore = 0.0f;
};

View File

@@ -1,10 +0,0 @@
#pragma once
#include <optional>
#include "entt/entity/entity.hpp"
struct ThreatResponseBehaviorComponent
{
std::optional<entt::entity> currentTarget;
};