implement sensor range requirements
This commit is contained in:
@@ -439,3 +439,132 @@ TEST_CASE("BehaviorSystem: full-cargo salvage ship moves toward SalvageBay", "[b
|
||||
REQUIRE(s->intent.priority == 1);
|
||||
REQUIRE(s->intent.target.x() < s->position.x());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Sensor range — spawn
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("SensorRange: sensorRange is populated from config formula at spawn", "[sensor]")
|
||||
{
|
||||
Fixture f;
|
||||
// interceptor sensor_range_formula = "200" (test config); verify at level 1.
|
||||
const EntityId id = f.ships.spawn("interceptor", 1, QVector2D(0.0f, 0.0f));
|
||||
REQUIRE(f.ships.findShip(id)->sensorRange == Approx(200.0f));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Sensor range — tickThreatResponse
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("SensorRange: player combat ship acquires enemy just inside sensor range", "[sensor]")
|
||||
{
|
||||
Fixture f;
|
||||
// interceptor sensor_range = 200 (test config); enemy at 190 tiles.
|
||||
const EntityId playerId = f.ships.spawn("interceptor", 1, QVector2D(0.0f, 0.0f));
|
||||
const EntityId enemyId = f.ships.spawn("interceptor", 1, QVector2D(190.0f, 0.0f),
|
||||
/*isEnemy=*/true);
|
||||
|
||||
f.ships.clearMovementIntents();
|
||||
f.ships.tickThreatResponse(f.buildings);
|
||||
|
||||
const Ship* player = f.ships.findShip(playerId);
|
||||
REQUIRE(player->threatResponse->currentTarget == enemyId);
|
||||
}
|
||||
|
||||
TEST_CASE("SensorRange: player combat ship ignores enemy just outside sensor range", "[sensor]")
|
||||
{
|
||||
Fixture f;
|
||||
// interceptor sensor_range = 200 (test config); enemy at 210 tiles.
|
||||
const EntityId playerId = f.ships.spawn("interceptor", 1, QVector2D(0.0f, 0.0f));
|
||||
f.ships.spawn("interceptor", 1, QVector2D(210.0f, 0.0f), /*isEnemy=*/true);
|
||||
|
||||
f.ships.clearMovementIntents();
|
||||
f.ships.tickThreatResponse(f.buildings);
|
||||
|
||||
const Ship* player = f.ships.findShip(playerId);
|
||||
REQUIRE_FALSE(player->threatResponse->currentTarget.has_value());
|
||||
}
|
||||
|
||||
TEST_CASE("SensorRange: enemy ship ignores player just outside sensor range", "[sensor]")
|
||||
{
|
||||
Fixture f;
|
||||
// interceptor sensor_range = 200 (test config); player at 210 tiles from enemy.
|
||||
f.ships.spawn("interceptor", 1, QVector2D(0.0f, 0.0f));
|
||||
const EntityId enemyId = f.ships.spawn("interceptor", 1, QVector2D(210.0f, 0.0f),
|
||||
/*isEnemy=*/true);
|
||||
|
||||
f.ships.clearMovementIntents();
|
||||
f.ships.tickThreatResponse(f.buildings);
|
||||
|
||||
const Ship* enemy = f.ships.findShip(enemyId);
|
||||
REQUIRE_FALSE(enemy->threatResponse->currentTarget.has_value());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Sensor range — tickRepairBehavior
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("SensorRange: repair ship retreats from enemy within sensor range", "[sensor]")
|
||||
{
|
||||
Fixture f;
|
||||
// repair_ship sensor_range = 250; enemy at 200 tiles.
|
||||
const EntityId repairId = f.ships.spawn("repair_ship", 1, QVector2D(0.0f, 0.0f));
|
||||
f.ships.spawn("interceptor", 1, QVector2D(200.0f, 0.0f), /*isEnemy=*/true);
|
||||
|
||||
f.ships.clearMovementIntents();
|
||||
f.ships.tickRepairBehavior(f.buildings);
|
||||
|
||||
const Ship* repair = f.ships.findShip(repairId);
|
||||
REQUIRE(repair->intent.priority == 2);
|
||||
REQUIRE(repair->intent.target.x() < 0.0f); // retreating leftward
|
||||
}
|
||||
|
||||
TEST_CASE("SensorRange: repair ship does not retreat from enemy beyond sensor range", "[sensor]")
|
||||
{
|
||||
Fixture f;
|
||||
// repair_ship sensor_range = 250; enemy at 300 tiles.
|
||||
const EntityId repairId = f.ships.spawn("repair_ship", 1, QVector2D(0.0f, 0.0f));
|
||||
f.ships.spawn("interceptor", 1, QVector2D(300.0f, 0.0f), /*isEnemy=*/true);
|
||||
|
||||
f.ships.clearMovementIntents();
|
||||
f.ships.tickRepairBehavior(f.buildings);
|
||||
|
||||
// Enemy outside sensor range → repair ship patrols rightward instead of retreating.
|
||||
const Ship* repair = f.ships.findShip(repairId);
|
||||
REQUIRE(repair->intent.target.x() > repair->position.x());
|
||||
}
|
||||
|
||||
TEST_CASE("SensorRange: repair ship does not acquire damaged ally beyond sensor range", "[sensor]")
|
||||
{
|
||||
Fixture f;
|
||||
// repair_ship sensor_range = 250; damaged friendly at 300 tiles.
|
||||
const EntityId repairId = f.ships.spawn("repair_ship", 1, QVector2D(0.0f, 0.0f));
|
||||
const EntityId friendlyId = f.ships.spawn("interceptor", 1, QVector2D(300.0f, 0.0f));
|
||||
f.ships.forEach([friendlyId](Ship& s) {
|
||||
if (s.id == friendlyId) { s.hp = s.maxHp * 0.5f; }
|
||||
});
|
||||
|
||||
f.ships.clearMovementIntents();
|
||||
f.ships.tickRepairBehavior(f.buildings);
|
||||
|
||||
REQUIRE_FALSE(f.ships.findShip(repairId)->repairBehavior->currentTarget.has_value());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Sensor range — tickScrapCollector
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("SensorRange: salvage ship ignores scrap beyond sensor range", "[sensor]")
|
||||
{
|
||||
Fixture f;
|
||||
// salvage_ship sensor_range = 250; scrap at 300 tiles.
|
||||
const EntityId shipId = f.ships.spawn("salvage_ship", 1, QVector2D(0.0f, 0.0f));
|
||||
f.scraps.spawn(QVector2D(300.0f, 0.0f), 1, 100000);
|
||||
|
||||
f.ships.clearMovementIntents();
|
||||
f.ships.tickScrapCollector(f.scraps, f.buildings);
|
||||
|
||||
const Ship* s = f.ships.findShip(shipId);
|
||||
REQUIRE(s->scrapCollector->scrapTarget == std::nullopt);
|
||||
REQUIRE(s->intent.target.x() > s->position.x()); // patrolling rightward
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user