Prefix all getters with "get"

This commit is contained in:
2026-07-19 21:17:38 +02:00
parent 08752aeced
commit d412c69f82
51 changed files with 574 additions and 574 deletions

View File

@@ -19,7 +19,7 @@ static GameConfig loadConfig()
static void killEnemyStations(Simulation& sim)
{
sim.admin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
[](entt::entity, StationBodyComponent&, FactionComponent& faction, HealthComponent& health)
{
if (faction.isEnemy)
@@ -65,7 +65,7 @@ TEST_CASE("ArtifactWinCondition: artifact count is 0 and isWon is false at game
"[artifact_win]")
{
const Simulation sim(loadConfig());
CHECK(sim.artifactCount() == 0);
CHECK(sim.getArtifactCount() == 0);
CHECK_FALSE(sim.isWon());
}
@@ -145,7 +145,7 @@ TEST_CASE("ArtifactWinCondition: selecting artifact increments artifact count",
SimulationTestAccess::applySchematicChoice(sim,index);
CHECK(sim.artifactCount() == 1);
CHECK(sim.getArtifactCount() == 1);
}
TEST_CASE("ArtifactWinCondition: selecting a non-artifact option does not increment artifact count",
@@ -166,7 +166,7 @@ TEST_CASE("ArtifactWinCondition: selecting a non-artifact option does not increm
SimulationTestAccess::applySchematicChoice(sim,static_cast<int>(it - choices.begin()));
CHECK(sim.artifactCount() == 0);
CHECK(sim.getArtifactCount() == 0);
}
// ---------------------------------------------------------------------------
@@ -205,7 +205,7 @@ TEST_CASE("ArtifactWinCondition: isWon stays false when artifact count is below
REQUIRE(sim.hasSchematicChoicesPending());
SimulationTestAccess::applySchematicChoice(sim,findArtifactChoiceIndex(sim));
CHECK(sim.artifactCount() == 1);
CHECK(sim.getArtifactCount() == 1);
CHECK_FALSE(sim.isWon());
}
@@ -226,7 +226,7 @@ TEST_CASE("ArtifactWinCondition: isWon becomes true after collecting required nu
SimulationTestAccess::applySchematicChoice(sim,index);
}
CHECK(sim.artifactCount() == 2);
CHECK(sim.getArtifactCount() == 2);
CHECK(sim.isWon());
}
@@ -249,6 +249,6 @@ TEST_CASE("ArtifactWinCondition: reset clears artifact count and win state",
sim.reset();
CHECK(sim.artifactCount() == 0);
CHECK(sim.getArtifactCount() == 0);
CHECK_FALSE(sim.isWon());
}

View File

@@ -533,9 +533,9 @@ TEST_CASE("Blueprint placement: buildings land at anchor + offset from cursor",
REQUIRE(idA != kInvalidBuildingId);
REQUIRE(idB != kInvalidBuildingId);
REQUIRE(sim.buildings().isTileOccupied(cursor + offsetA)); // (-6, 0)
REQUIRE(sim.buildings().isTileOccupied(cursor + offsetB)); // (-4, 0)
REQUIRE_FALSE(sim.buildings().isTileOccupied(cursor)); // center not occupied
REQUIRE(sim.getBuildings().isTileOccupied(cursor + offsetA)); // (-6, 0)
REQUIRE(sim.getBuildings().isTileOccupied(cursor + offsetB)); // (-4, 0)
REQUIRE_FALSE(sim.getBuildings().isTileOccupied(cursor)); // center not occupied
}
TEST_CASE("Blueprint placement: cost is deducted for each building in sequence", "[blueprint]")
@@ -544,20 +544,20 @@ TEST_CASE("Blueprint placement: cost is deducted for each building in sequence",
// Find belt cost from config (belt cost = 2 in test config).
int beltCost = 0;
for (const BuildingDef& def : sim.config().buildings.buildings)
for (const BuildingDef& def : sim.getConfig().buildings.buildings)
{
if (def.type == BuildingType::Belt) { beltCost = def.cost; break; }
}
REQUIRE(beltCost > 0);
const int startBlocks = sim.buildingBlocksStock();
const int startBlocks = sim.getBuildingBlocksStock();
REQUIRE(startBlocks >= 2 * beltCost); // test config has enough starting blocks
SimulationTestAccess::place(sim,BuildingType::Belt, QPoint(-6, 0), Rotation::East);
REQUIRE(sim.buildingBlocksStock() == startBlocks - beltCost);
REQUIRE(sim.getBuildingBlocksStock() == startBlocks - beltCost);
SimulationTestAccess::place(sim,BuildingType::Belt, QPoint(-4, 0), Rotation::East);
REQUIRE(sim.buildingBlocksStock() == startBlocks - 2 * beltCost);
REQUIRE(sim.getBuildingBlocksStock() == startBlocks - 2 * beltCost);
}
TEST_CASE("Blueprint placement: insufficient blocks returns kInvalidBuildingId and deducts nothing",
@@ -567,7 +567,7 @@ TEST_CASE("Blueprint placement: insufficient blocks returns kInvalidBuildingId a
// Find miner cost (15 in test config) — expensive enough to exhaust a small stock.
int minerCost = 0;
for (const BuildingDef& def : sim.config().buildings.buildings)
for (const BuildingDef& def : sim.getConfig().buildings.buildings)
{
if (def.type == BuildingType::Miner) { minerCost = def.cost; break; }
}
@@ -576,26 +576,26 @@ TEST_CASE("Blueprint placement: insufficient blocks returns kInvalidBuildingId a
// Drain the stock by placing miners until we no longer have enough.
// Non-overlapping columns: miner body is 2 wide, so step by 2.
int col = -2;
while (sim.buildingBlocksStock() >= minerCost)
while (sim.getBuildingBlocksStock() >= minerCost)
{
SimulationTestAccess::place(sim,BuildingType::Miner, QPoint(col, 0), Rotation::East);
col -= 2;
}
const int blocksBeforeAttempt = sim.buildingBlocksStock();
const int blocksBeforeAttempt = sim.getBuildingBlocksStock();
const BuildingId id = SimulationTestAccess::place(sim,
BuildingType::Miner, QPoint(col - 2, 0), Rotation::East);
// Placement must fail and leave the stock unchanged.
REQUIRE(id == kInvalidBuildingId);
REQUIRE(sim.buildingBlocksStock() == blocksBeforeAttempt);
REQUIRE(sim.getBuildingBlocksStock() == blocksBeforeAttempt);
}
TEST_CASE("Simulation: tryPlaceBuilding rejects terrain-invalid placement and charges nothing",
"[blueprint]")
{
Simulation sim(loadConfig());
const int startBlocks = sim.buildingBlocksStock();
const int startBlocks = sim.getBuildingBlocksStock();
// A miner is all-asteroid; placing it in space (x >= 0) violates the terrain
// rule, so it must be rejected without consuming building blocks.
@@ -603,8 +603,8 @@ TEST_CASE("Simulation: tryPlaceBuilding rejects terrain-invalid placement and ch
SimulationTestAccess::place(sim,BuildingType::Miner, QPoint(0, 0), Rotation::East);
REQUIRE(id == kInvalidBuildingId);
REQUIRE(sim.buildingBlocksStock() == startBlocks);
REQUIRE(sim.buildings().allSites().empty());
REQUIRE(sim.getBuildingBlocksStock() == startBlocks);
REQUIRE(sim.getBuildings().getAllSites().empty());
}
TEST_CASE("Simulation: tryPlaceBuilding accepts a valid asteroid spot, occupies tiles, charges cost",
@@ -613,12 +613,12 @@ TEST_CASE("Simulation: tryPlaceBuilding accepts a valid asteroid spot, occupies
Simulation sim(loadConfig());
int minerCost = 0;
for (const BuildingDef& def : sim.config().buildings.buildings)
for (const BuildingDef& def : sim.getConfig().buildings.buildings)
{
if (def.type == BuildingType::Miner) { minerCost = def.cost; break; }
}
REQUIRE(minerCost > 0);
const int startBlocks = sim.buildingBlocksStock();
const int startBlocks = sim.getBuildingBlocksStock();
// Miner mask ["AA","A>"] East at (-3,0) → all-asteroid body at
// (-3,0),(-2,0),(-3,1); a valid spot.
@@ -626,12 +626,12 @@ TEST_CASE("Simulation: tryPlaceBuilding accepts a valid asteroid spot, occupies
SimulationTestAccess::place(sim,BuildingType::Miner, QPoint(-3, 0), Rotation::East);
REQUIRE(id != kInvalidBuildingId);
REQUIRE(sim.buildingBlocksStock() == startBlocks - minerCost);
REQUIRE(sim.buildings().isTileOccupied(QPoint(-3, 0)));
REQUIRE(sim.buildings().isTileOccupied(QPoint(-2, 0)));
REQUIRE(sim.buildings().isTileOccupied(QPoint(-3, 1)));
REQUIRE(sim.getBuildingBlocksStock() == startBlocks - minerCost);
REQUIRE(sim.getBuildings().isTileOccupied(QPoint(-3, 0)));
REQUIRE(sim.getBuildings().isTileOccupied(QPoint(-2, 0)));
REQUIRE(sim.getBuildings().isTileOccupied(QPoint(-3, 1)));
// The output-port tile (1,1)+anchor = (-2,1) is not a body cell.
REQUIRE_FALSE(sim.buildings().isTileOccupied(QPoint(-2, 1)));
REQUIRE_FALSE(sim.getBuildings().isTileOccupied(QPoint(-2, 1)));
}
// ---------------------------------------------------------------------------
@@ -671,7 +671,7 @@ TEST_CASE("Blueprint placement: setRecipe on construction site stores recipe", "
SimulationTestAccess::buildings(sim).setRecipe(id, "mine_iron_ore");
const ConstructionSite* site = sim.buildings().findSite(id);
const ConstructionSite* site = sim.getBuildings().findSite(id);
REQUIRE(site != nullptr);
REQUIRE(site->recipeId == "mine_iron_ore");
}
@@ -692,7 +692,7 @@ TEST_CASE("Blueprint placement: recipe transfers to building after construction
sim.tick();
}
const Building* b = sim.buildings().findBuilding(id);
const Building* b = sim.getBuildings().findBuilding(id);
REQUIRE(b != nullptr);
REQUIRE(b->recipeId == "mine_copper_ore");
}
@@ -712,8 +712,8 @@ TEST_CASE("Blueprint creation: a construction site is captured", "[blueprint]")
const BuildingId id =
SimulationTestAccess::place(sim, BuildingType::Belt, QPoint(-2, 0), Rotation::East);
REQUIRE(id != kInvalidBuildingId);
REQUIRE(sim.buildings().findSite(id) != nullptr);
REQUIRE(sim.buildings().findBuilding(id) == nullptr);
REQUIRE(sim.getBuildings().findSite(id) != nullptr);
REQUIRE(sim.getBuildings().findBuilding(id) == nullptr);
const Blueprint bp = captureBlueprintFromSelection(sim, { id });
@@ -748,14 +748,14 @@ TEST_CASE("Blueprint creation: mixed operational building and construction site
REQUIRE(idA != kInvalidBuildingId);
SimulationTestAccess::buildings(sim).setRecipe(idA, "mine_iron_ore");
for (int i = 0; i <= static_cast<int>(secondsToTicks(10.0)); ++i) { sim.tick(); }
REQUIRE(sim.buildings().findBuilding(idA) != nullptr);
REQUIRE(sim.getBuildings().findBuilding(idA) != nullptr);
// Building B: place and configure, but leave as a construction site.
const BuildingId idB =
SimulationTestAccess::place(sim, BuildingType::Miner, QPoint(-6, 0), Rotation::East);
REQUIRE(idB != kInvalidBuildingId);
SimulationTestAccess::buildings(sim).setRecipe(idB, "mine_copper_ore");
REQUIRE(sim.buildings().findSite(idB) != nullptr);
REQUIRE(sim.getBuildings().findSite(idB) != nullptr);
const Blueprint bp = captureBlueprintFromSelection(sim, { idA, idB });
@@ -779,7 +779,7 @@ TEST_CASE("Blueprint creation: selectionHasPlaceableBuilding sees a construction
const BuildingId id =
SimulationTestAccess::place(sim, BuildingType::Miner, QPoint(-2, 0), Rotation::East);
REQUIRE(id != kInvalidBuildingId);
REQUIRE(sim.buildings().findSite(id) != nullptr);
REQUIRE(sim.getBuildings().findSite(id) != nullptr);
REQUIRE(selectionHasPlaceableBuilding(sim, { id }));
}
@@ -859,7 +859,7 @@ TEST_CASE("Blueprint placement: setShipLayout on construction site stores layout
SimulationTestAccess::buildings(sim).setShipLayout(id, layout);
const ConstructionSite* site = sim.buildings().findSite(id);
const ConstructionSite* site = sim.getBuildings().findSite(id);
REQUIRE(site != nullptr);
REQUIRE(site->shipLayout.has_value());
REQUIRE(site->shipLayout->placedModules.size() == 1);
@@ -885,7 +885,7 @@ TEST_CASE("Blueprint placement: ship layout transfers to building after construc
// Shipyard construction_time_seconds = 30 in the test config.
double constructionTime = 0.0;
for (const BuildingDef& def : sim.config().buildings.buildings)
for (const BuildingDef& def : sim.getConfig().buildings.buildings)
{
if (def.type == BuildingType::Shipyard) { constructionTime = def.constructionTimeSeconds; break; }
}
@@ -896,7 +896,7 @@ TEST_CASE("Blueprint placement: ship layout transfers to building after construc
sim.tick();
}
const Building* b = sim.buildings().findBuilding(id);
const Building* b = sim.getBuildings().findBuilding(id);
REQUIRE(b != nullptr);
REQUIRE(b->shipLayout.has_value());
REQUIRE(b->shipLayout->placedModules.size() == 1);

View File

@@ -114,8 +114,8 @@ TEST_CASE("readBuildingConfig reads a queued construction site", "[copyconfig]")
const BuildingId id =
SimulationTestAccess::place(sim, BuildingType::Miner, QPoint(-2, 0), Rotation::East);
REQUIRE(id != kInvalidBuildingId);
REQUIRE(sim.buildings().findBuilding(id) == nullptr);
REQUIRE(sim.buildings().findSite(id) != nullptr);
REQUIRE(sim.getBuildings().findBuilding(id) == nullptr);
REQUIRE(sim.getBuildings().findSite(id) != nullptr);
SimulationTestAccess::buildings(sim).setRecipe(id, "mine_iron_ore");

View File

@@ -140,7 +140,7 @@ TEST_CASE("BuildingSystem: place rejects a building above the world (y < 0)", "[
// row sits above the world.
const BuildingId id = f.bs.place(BuildingType::Miner, QPoint(0, -1), Rotation::East, 0);
REQUIRE(id == kInvalidBuildingId);
REQUIRE(f.bs.allSites().empty());
REQUIRE(f.bs.getAllSites().empty());
REQUIRE_FALSE(f.bs.isTileOccupied(QPoint(0, 0)));
}
@@ -154,7 +154,7 @@ TEST_CASE("BuildingSystem: place rejects a building below the world (y >= height
const BuildingId id = f.bs.place(BuildingType::Miner,
QPoint(0, heightTiles - 1), Rotation::East, 0);
REQUIRE(id == kInvalidBuildingId);
REQUIRE(f.bs.allSites().empty());
REQUIRE(f.bs.getAllSites().empty());
}
TEST_CASE("BuildingSystem: place rejects a building left of the asteroid edge", "[building]")
@@ -165,7 +165,7 @@ TEST_CASE("BuildingSystem: place rejects a building left of the asteroid edge",
const BuildingId id = f.bs.place(BuildingType::Miner,
QPoint(leftEdgeX - 1, 0), Rotation::East, 0);
REQUIRE(id == kInvalidBuildingId);
REQUIRE(f.bs.allSites().empty());
REQUIRE(f.bs.getAllSites().empty());
}
TEST_CASE("BuildingSystem: place accepts a building flush against the world's left edge",
@@ -237,9 +237,9 @@ TEST_CASE("BuildingSystem: placing a belt registers it with BeltSystem after con
runTicks(bs, belts, static_cast<int>(secondsToTicks(1.0)) + 1, tick);
REQUIRE(belts.tryPutItem(QPoint(5, 5), makeItem("iron_ore"), Rotation::East));
REQUIRE(bs.allBuildings().size() == 1);
REQUIRE(bs.allBuildings()[0].type == BuildingType::Belt);
REQUIRE(bs.allBuildings()[0].anchor == QPoint(5, 5));
REQUIRE(bs.getAllBuildings().size() == 1);
REQUIRE(bs.getAllBuildings()[0].type == BuildingType::Belt);
REQUIRE(bs.getAllBuildings()[0].anchor == QPoint(5, 5));
}
TEST_CASE("BuildingSystem: placed building enters construction queue", "[building]")
@@ -258,8 +258,8 @@ TEST_CASE("BuildingSystem: placed building enters construction queue", "[buildin
const BuildingId id = bs.place(BuildingType::Miner, QPoint(0, 0), Rotation::East, 0);
REQUIRE(bs.allSites().size() == 1);
REQUIRE(bs.allBuildings().empty());
REQUIRE(bs.getAllSites().size() == 1);
REQUIRE(bs.getAllBuildings().empty());
REQUIRE(bs.findSite(id) != nullptr);
}
@@ -289,7 +289,7 @@ TEST_CASE("BuildingSystem: demolish frees tiles and returns refund", "[building]
// Miner cost = 15, refund = floor(15 * 75 / 100) = 11.
REQUIRE(refund == 15 * cfg.world.refundPercentage / 100);
REQUIRE_FALSE(bs.isTileOccupied(QPoint(0, 0)));
REQUIRE(bs.allSites().empty());
REQUIRE(bs.getAllSites().empty());
}
// ---------------------------------------------------------------------------
@@ -312,7 +312,7 @@ TEST_CASE("BuildingSystem: first queued building starts construction immediately
rng);
bs.place(BuildingType::Miner, QPoint(0, 0), Rotation::East, 0);
REQUIRE(bs.allSites().front().completesAt > 0);
REQUIRE(bs.getAllSites().front().completesAt > 0);
}
TEST_CASE("BuildingSystem: second queued building waits (completesAt == 0)", "[building]")
@@ -332,9 +332,9 @@ TEST_CASE("BuildingSystem: second queued building waits (completesAt == 0)", "[b
bs.place(BuildingType::Miner, QPoint(0, 0), Rotation::East, 0);
bs.place(BuildingType::Miner, QPoint(5, 5), Rotation::East, 0);
REQUIRE(bs.allSites().size() == 2);
REQUIRE(bs.allSites()[0].completesAt > 0);
REQUIRE(bs.allSites()[1].completesAt == 0);
REQUIRE(bs.getAllSites().size() == 2);
REQUIRE(bs.getAllSites()[0].completesAt > 0);
REQUIRE(bs.getAllSites()[1].completesAt == 0);
}
TEST_CASE("BuildingSystem: construction completes after configured duration", "[building]")
@@ -358,7 +358,7 @@ TEST_CASE("BuildingSystem: construction completes after configured duration", "[
Tick tick = 0;
runTicks(bs, belts, static_cast<int>(secondsToTicks(10.0)) + 1, tick);
REQUIRE(bs.allSites().empty());
REQUIRE(bs.getAllSites().empty());
REQUIRE(bs.findBuilding(id) != nullptr);
}
@@ -383,9 +383,9 @@ TEST_CASE("BuildingSystem: second building starts after first completes", "[buil
Tick tick = 0;
runTicks(bs, belts, static_cast<int>(secondsToTicks(10.0)) + 1, tick);
REQUIRE(bs.allSites().size() == 1);
REQUIRE(bs.allSites().front().id == id2);
REQUIRE(bs.allSites().front().completesAt > 0);
REQUIRE(bs.getAllSites().size() == 1);
REQUIRE(bs.getAllSites().front().id == id2);
REQUIRE(bs.getAllSites().front().completesAt > 0);
}
// ---------------------------------------------------------------------------
@@ -457,7 +457,7 @@ TEST_CASE("BuildingSystem: miner output buffer stalls when full", "[building]")
REQUIRE(b != nullptr);
// Both produced items are held on the output side (buffer + emerging lane),
// which is what the capacity rule counts (REQ-MAT-OUTPUT-EMERGE).
REQUIRE(b->outputItemCount() == 2);
REQUIRE(b->getOutputItemCount() == 2);
REQUIRE_FALSE(b->production.has_value());
}
@@ -485,23 +485,23 @@ TEST_CASE("BuildingSystem: productionBuildingCount excludes construction sites",
Tick tick = 0;
// Both still under construction.
REQUIRE(bs.productionBuildingCount() == 0);
REQUIRE(bs.getProductionBuildingCount() == 0);
// The queue builds one at a time: miner (10s) completes at tick 300, then
// the smelter (15s) starts and completes at tick 300 + 450 = 750.
runTicks(bs, belts, static_cast<int>(secondsToTicks(10.0)) + 1, tick);
REQUIRE(bs.productionBuildingCount() == 1);
REQUIRE(bs.getProductionBuildingCount() == 1);
runTicks(bs, belts, static_cast<int>(secondsToTicks(15.0)), tick);
REQUIRE(bs.productionBuildingCount() == 2);
REQUIRE(bs.getProductionBuildingCount() == 2);
// Neither is producing yet: the miner has no recipe selected, and the
// smelter (auto-recipe, REQ-BLD-SMELTER) has no input feeding it.
REQUIRE(bs.activeProductionBuildingCount() == 0);
REQUIRE(bs.getActiveProductionBuildingCount() == 0);
bs.setRecipe(minerId, "mine_iron_ore");
runTicks(bs, belts, 1, tick);
REQUIRE(bs.activeProductionBuildingCount() == 1);
REQUIRE(bs.getActiveProductionBuildingCount() == 1);
}
TEST_CASE("BuildingSystem: activeProductionBuildingCount tracks production cycle state",
@@ -524,11 +524,11 @@ TEST_CASE("BuildingSystem: activeProductionBuildingCount tracks production cycle
Tick tick = 0;
// Not yet operational while under construction.
REQUIRE(bs.activeProductionBuildingCount() == 0);
REQUIRE(bs.getActiveProductionBuildingCount() == 0);
// Construction completes at tick 300; cycle 1 starts the same tick (completesAt=330).
runTicks(bs, belts, static_cast<int>(secondsToTicks(10.0)) + 1, tick);
REQUIRE(bs.activeProductionBuildingCount() == 1);
REQUIRE(bs.getActiveProductionBuildingCount() == 1);
// Run cycles 1 and 2 to completion (1s each); cycle 3 stalls once the
// output buffer (capacity 2) is full (REQ-MAT-OUTPUT-BUFFER).
@@ -536,9 +536,9 @@ TEST_CASE("BuildingSystem: activeProductionBuildingCount tracks production cycle
const Building* b = bs.findBuilding(id);
REQUIRE(b != nullptr);
REQUIRE(b->outputItemCount() == 2);
REQUIRE(b->getOutputItemCount() == 2);
REQUIRE_FALSE(b->production.has_value());
REQUIRE(bs.activeProductionBuildingCount() == 0);
REQUIRE(bs.getActiveProductionBuildingCount() == 0);
}
// ---------------------------------------------------------------------------
@@ -882,7 +882,7 @@ TEST_CASE("BuildingSystem: direct coupling to a non-consumer leaves the item stu
REQUIRE(sink != nullptr);
// Nothing was delivered, and the producer's output side has backed up to its cap.
REQUIRE(sink->pendingInputCount(ItemType{"iron_ore"}) == 0);
REQUIRE(miner->outputItemCount() == miner->outputBuffer.capacity);
REQUIRE(miner->getOutputItemCount() == miner->outputBuffer.capacity);
}
// ---------------------------------------------------------------------------
@@ -916,7 +916,7 @@ TEST_CASE("BuildingSystem: setRecipe clears output buffer and active production"
{
const Building* b = bs.findBuilding(id);
REQUIRE(b != nullptr);
REQUIRE(b->outputItemCount() > 0);
REQUIRE(b->getOutputItemCount() > 0);
}
bs.setRecipe(id, "mine_copper_ore");
@@ -924,7 +924,7 @@ TEST_CASE("BuildingSystem: setRecipe clears output buffer and active production"
const Building* b = bs.findBuilding(id);
// Clearing the output buffer on a recipe change also discards emerging items
// (REQ-MAT-OUTPUT-EMERGE).
REQUIRE(b->outputItemCount() == 0);
REQUIRE(b->getOutputItemCount() == 0);
REQUIRE_FALSE(b->production.has_value());
}
@@ -1083,7 +1083,7 @@ TEST_CASE("BuildingSystem: findRotateInPlaceTarget returns the building id for a
Tick tick = 0;
runTicks(bs, belts, static_cast<int>(secondsToTicks(1.0)) + 1, tick);
REQUIRE(bs.allSites().empty());
REQUIRE(bs.getAllSites().empty());
const std::optional<BuildingId> result =
bs.findRotateInPlaceTarget(BuildingType::Belt, QPoint(0, 0), Rotation::South);
@@ -1295,12 +1295,12 @@ TEST_CASE("BuildingSystem: splitter filters configured on a construction site ca
// Run until construction completes.
Tick tick = 0;
while (f.bs.allBuildings().empty() && tick < 100000)
while (f.bs.getAllBuildings().empty() && tick < 100000)
{
runTicks(f.bs, f.belts, 1, tick);
}
REQUIRE(f.bs.allBuildings().size() == 1);
REQUIRE(f.bs.allBuildings()[0].type == BuildingType::Splitter);
REQUIRE(f.bs.getAllBuildings().size() == 1);
REQUIRE(f.bs.getAllBuildings()[0].type == BuildingType::Splitter);
// The built splitter is registered with BeltSystem carrying the filters.
const std::optional<BeltSystem::SplitterInfo> builtInfo = f.belts.getSplitterInfo(tile);

View File

@@ -183,7 +183,7 @@ TEST_CASE("CombatSystem: player station fires at enemy ship in range", "[combat]
// Find the player station entity via ECS.
entt::entity stationEntity = entt::null;
QVector2D stationCenter;
sim.admin().forEach<StationBodyComponent, FactionComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent>(
[&](entt::entity e, const StationBodyComponent& sb, const FactionComponent& f)
{
if (!f.isEnemy && stationEntity == entt::null)
@@ -194,12 +194,12 @@ TEST_CASE("CombatSystem: player station fires at enemy ship in range", "[combat]
sb.anchor.y() + sb.footprint.height() / 2.0f);
}
});
REQUIRE(sim.admin().isValid(stationEntity));
REQUIRE(sim.getAdmin().isValid(stationEntity));
const ShipDef* combatDef = findCombatShip(sim.config());
const ShipDef* combatDef = findCombatShip(sim.getConfig());
REQUIRE(combatDef != nullptr);
const entt::entity enemyShip = sim.ships().spawn(
const entt::entity enemyShip = sim.getShips().spawn(
combatDef->id,
QVector2D(stationCenter.x() + 1.0f, stationCenter.y()),
/*isEnemy=*/true);
@@ -221,7 +221,7 @@ TEST_CASE("CombatSystem: enemy station fires at player ship in range", "[combat]
entt::entity stationEntity = entt::null;
QVector2D stationCenter;
sim.admin().forEach<StationBodyComponent, FactionComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent>(
[&](entt::entity e, const StationBodyComponent& sb, const FactionComponent& f)
{
if (f.isEnemy && stationEntity == entt::null)
@@ -232,12 +232,12 @@ TEST_CASE("CombatSystem: enemy station fires at player ship in range", "[combat]
sb.anchor.y() + sb.footprint.height() / 2.0f);
}
});
REQUIRE(sim.admin().isValid(stationEntity));
REQUIRE(sim.getAdmin().isValid(stationEntity));
const ShipDef* combatDef = findCombatShip(sim.config());
const ShipDef* combatDef = findCombatShip(sim.getConfig());
REQUIRE(combatDef != nullptr);
sim.ships().spawn(
sim.getShips().spawn(
combatDef->id,
QVector2D(stationCenter.x() - 1.0f, stationCenter.y()),
/*isEnemy=*/false);
@@ -259,7 +259,7 @@ TEST_CASE("CombatSystem: player ship fires at enemy station in range", "[combat]
entt::entity stationEntity = entt::null;
QVector2D stationCenter;
sim.admin().forEach<StationBodyComponent, FactionComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent>(
[&](entt::entity e, const StationBodyComponent& sb, const FactionComponent& f)
{
if (f.isEnemy && stationEntity == entt::null)
@@ -270,12 +270,12 @@ TEST_CASE("CombatSystem: player ship fires at enemy station in range", "[combat]
sb.anchor.y() + sb.footprint.height() / 2.0f);
}
});
REQUIRE(sim.admin().isValid(stationEntity));
REQUIRE(sim.getAdmin().isValid(stationEntity));
const ShipDef* combatDef = findCombatShip(sim.config());
const ShipDef* combatDef = findCombatShip(sim.getConfig());
REQUIRE(combatDef != nullptr);
const entt::entity playerShip = sim.ships().spawn(
const entt::entity playerShip = sim.getShips().spawn(
combatDef->id,
QVector2D(stationCenter.x() - 1.0f, stationCenter.y()),
/*isEnemy=*/false);
@@ -390,17 +390,17 @@ TEST_CASE("CombatSystem: dead ship is removed after tick step 9", "[combat]")
{
Simulation sim(loadConfig(), 42);
const ShipDef* combatDef = findCombatShip(sim.config());
const ShipDef* combatDef = findCombatShip(sim.getConfig());
REQUIRE(combatDef != nullptr);
const entt::entity ship = sim.ships().spawn(combatDef->id,
const entt::entity ship = sim.getShips().spawn(combatDef->id,
QVector2D(10.0f, 10.0f));
sim.admin().get<HealthComponent>(ship).hp = -1.0f;
sim.getAdmin().get<HealthComponent>(ship).hp = -1.0f;
sim.tick();
REQUIRE_FALSE(sim.admin().isValid(ship));
REQUIRE_FALSE(sim.getAdmin().isValid(ship));
}
TEST_CASE("CombatSystem: scrap is spawned on ship death", "[combat]")
@@ -411,15 +411,15 @@ TEST_CASE("CombatSystem: scrap is spawned on ship death", "[combat]")
// (REQ-RES-SCRAP-DROP): round(threat * scrap_per_threat). The interceptor's
// threat is 59.0 and the test config sets scrap_per_threat = 1.0, so it drops
// round(59.0 * 1.0) = 59 scrap.
const entt::entity ship = sim.ships().spawn("interceptor",
const entt::entity ship = sim.getShips().spawn("interceptor",
QVector2D(10.0f, 10.0f));
sim.admin().get<HealthComponent>(ship).hp = -1.0f;
sim.getAdmin().get<HealthComponent>(ship).hp = -1.0f;
sim.tick();
const std::vector<ScrapInfo> scraps = sim.scraps().allScrapInfo();
const std::vector<ScrapInfo> scraps = sim.getScraps().getAllScrapInfo();
REQUIRE(scraps.size() == 1);
CHECK(sim.admin().get<ScrapDataComponent>(scraps[0].entity).amount == 59);
CHECK(sim.getAdmin().get<ScrapDataComponent>(scraps[0].entity).amount == 59);
}
TEST_CASE("CombatSystem: HQ death sets game over", "[combat]")
@@ -427,7 +427,7 @@ TEST_CASE("CombatSystem: HQ death sets game over", "[combat]")
Simulation sim(loadConfig(), 42);
// Damage the HQ proxy entity (has HqProxy + Health).
sim.admin().forEach<HqProxyComponent, HealthComponent>(
sim.getAdmin().forEach<HqProxyComponent, HealthComponent>(
[](entt::entity /*e*/, const HqProxyComponent& /*hq*/, HealthComponent& h)
{
h.hp = -1.0f;

View File

@@ -67,7 +67,7 @@ TEST_CASE("Hasher: identical inputs produce identical values", "[determinism]")
b.append(3.5f);
b.append(std::string("ore"));
REQUIRE(a.value() == b.value());
REQUIRE(a.getValue() == b.getValue());
}
TEST_CASE("Hasher: differing inputs produce differing values", "[determinism]")
@@ -77,7 +77,7 @@ TEST_CASE("Hasher: differing inputs produce differing values", "[determinism]")
a.append(42);
b.append(43);
REQUIRE(a.value() != b.value());
REQUIRE(a.getValue() != b.getValue());
}
TEST_CASE("Hasher: string concatenation does not collide", "[determinism]")
@@ -89,7 +89,7 @@ TEST_CASE("Hasher: string concatenation does not collide", "[determinism]")
b.append(std::string("a"));
b.append(std::string("bc"));
REQUIRE(a.value() != b.value());
REQUIRE(a.getValue() != b.getValue());
}
TEST_CASE("Hasher: negative and positive zero hash equally", "[determinism]")
@@ -99,7 +99,7 @@ TEST_CASE("Hasher: negative and positive zero hash equally", "[determinism]")
a.append(-0.0f);
b.append(0.0f);
REQUIRE(a.value() == b.value());
REQUIRE(a.getValue() == b.getValue());
}
// ---------------------------------------------------------------------------
@@ -124,7 +124,7 @@ TEST_CASE("Simulation::rngFingerprint is stable for equal seeds", "[determinism]
const Simulation a(loadConfig(), 777);
const Simulation b(loadConfig(), 777);
REQUIRE(a.rngFingerprint() == b.rngFingerprint());
REQUIRE(a.getRngFingerprint() == b.getRngFingerprint());
}
// ---------------------------------------------------------------------------

View File

@@ -37,7 +37,7 @@ TEST_CASE("Formula retains its source string", "[formula]")
const std::string source = "10 + x / 5";
const Formula f = Formula::compile(source);
REQUIRE(f.source() == source);
REQUIRE(f.getSource() == source);
}
TEST_CASE("Formula throws on malformed source", "[formula]")

View File

@@ -22,7 +22,7 @@ static GameConfig loadConfig()
// tickDeathsAndLoot fires, triggering the push and schematic choices.
static void killEnemyStations(Simulation& sim)
{
sim.admin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
[](entt::entity, StationBodyComponent&, FactionComponent& faction, HealthComponent& health)
{
if (faction.isEnemy)

View File

@@ -166,7 +166,7 @@ TEST_CASE("a recorded run replays to byte-identical state with no desync", "[rep
manager.drain();
for (int i = 0; i < 60; ++i) { rec.tick(); manager.recordTickCheckpoint(); }
replayPath = recorderPtr->currentFilePath();
replayPath = recorderPtr->getCurrentFilePath();
recordedFinalChecksum = rec.computeStateChecksum();
manager.setRecorder(nullptr); // close the file
}
@@ -185,11 +185,11 @@ TEST_CASE("a recorded run replays to byte-identical state with no desync", "[rep
while (!player.isFinished())
{
play.tick();
player.advanceTo(play.currentTick());
player.advanceTo(play.getCurrentTick());
}
REQUIRE_FALSE(player.getDesyncTick().has_value());
REQUIRE(play.currentTick() == 150);
REQUIRE(play.getCurrentTick() == 150);
REQUIRE(play.computeStateChecksum() == recordedFinalChecksum);
QFile::remove(QString::fromStdString(replayPath));
@@ -208,7 +208,7 @@ TEST_CASE("ReplayPlayer reports a desync when a checksum is corrupted", "[replay
ReplayRecorder* recorderPtr = recorder.get();
manager.setRecorder(std::move(recorder));
for (int i = 0; i < 60; ++i) { rec.tick(); manager.recordTickCheckpoint(); }
replayPath = recorderPtr->currentFilePath();
replayPath = recorderPtr->getCurrentFilePath();
manager.setRecorder(nullptr);
}
@@ -234,7 +234,7 @@ TEST_CASE("ReplayPlayer reports a desync when a checksum is corrupted", "[replay
while (!player.isFinished())
{
play.tick();
player.advanceTo(play.currentTick());
player.advanceTo(play.getCurrentTick());
}
REQUIRE(player.getDesyncTick().has_value());
@@ -267,7 +267,7 @@ TEST_CASE("a long recorded run (through waves and combat) replays with no desync
manager.drain();
for (int i = 0; i < 900; ++i) { rec.tick(); manager.recordTickCheckpoint(); }
replayPath = recorderPtr->currentFilePath();
replayPath = recorderPtr->getCurrentFilePath();
recordedFinalChecksum = rec.computeStateChecksum();
manager.setRecorder(nullptr);
}
@@ -281,11 +281,11 @@ TEST_CASE("a long recorded run (through waves and combat) replays with no desync
while (!player.isFinished())
{
play.tick();
player.advanceTo(play.currentTick());
player.advanceTo(play.getCurrentTick());
}
REQUIRE_FALSE(player.getDesyncTick().has_value());
REQUIRE(play.currentTick() == 2400);
REQUIRE(play.getCurrentTick() == 2400);
REQUIRE(play.computeStateChecksum() == recordedFinalChecksum);
QFile::remove(QString::fromStdString(replayPath));

View File

@@ -120,7 +120,7 @@ TEST_CASE("ReplayRecorder writes a well-formed file", "[replay]")
recorder.recordChecksum(30, 0x0ffffffffffffff0ull);
const std::string path = recorder.currentFilePath();
const std::string path = recorder.getCurrentFilePath();
REQUIRE_FALSE(path.empty());
recorder.close();
@@ -152,7 +152,7 @@ TEST_CASE("CommandManager records commands and an initial checksum on drain", "[
ReplayRecorder* recorderPtr = recorder.get();
// setRecorder opens the file and writes the header + the tick-0 checksum.
manager.setRecorder(std::move(recorder));
const std::string path = recorderPtr->currentFilePath();
const std::string path = recorderPtr->getCurrentFilePath();
REQUIRE_FALSE(path.empty());
std::shared_ptr<PlaceBuildingCommand> place = std::make_shared<PlaceBuildingCommand>();
@@ -175,10 +175,10 @@ TEST_CASE("ReplayRecorder startNewRun rolls to a new file", "[replay]")
ReplayRecorder recorder(CONFIG_DIR, tempOutputDir());
recorder.startNewRun(1u, 0ull);
const std::string first = recorder.currentFilePath();
const std::string first = recorder.getCurrentFilePath();
recorder.startNewRun(2u, 0ull);
const std::string second = recorder.currentFilePath();
const std::string second = recorder.getCurrentFilePath();
REQUIRE(first != second);
REQUIRE(second.find("_2.replay") != std::string::npos);
@@ -194,7 +194,7 @@ TEST_CASE("CommandManager rolls the replay file on a Reset command", "[replay]")
std::make_unique<ReplayRecorder>(CONFIG_DIR, tempOutputDir());
ReplayRecorder* recorderPtr = recorder.get();
manager.setRecorder(std::move(recorder));
const std::string firstPath = recorderPtr->currentFilePath();
const std::string firstPath = recorderPtr->getCurrentFilePath();
std::shared_ptr<ResetCommand> reset = std::make_shared<ResetCommand>();
reset->config = std::make_shared<GameConfig>(ConfigLoader::loadFromDirectory(CONFIG_DIR));
@@ -202,7 +202,7 @@ TEST_CASE("CommandManager rolls the replay file on a Reset command", "[replay]")
manager.enqueue(reset);
manager.drain();
const std::string secondPath = recorderPtr->currentFilePath();
const std::string secondPath = recorderPtr->getCurrentFilePath();
REQUIRE(firstPath != secondPath);
REQUIRE(secondPath.find("_999.replay") != std::string::npos);

View File

@@ -148,7 +148,7 @@ TEST_CASE("ScrapSystem: allScrapInfo returns all spawned scrap", "[scrap]")
ss.spawn(QVector2D(1.0f, 2.0f), 3, 100);
ss.spawn(QVector2D(4.0f, 5.0f), 6, 200);
const std::vector<ScrapInfo> info = ss.allScrapInfo();
const std::vector<ScrapInfo> info = ss.getAllScrapInfo();
REQUIRE(info.size() == 2);
}
@@ -160,7 +160,7 @@ TEST_CASE("ScrapSystem: allScrapInfo reports each pile's remaining amount", "[sc
const entt::entity a = ss.spawn(QVector2D(1.0f, 2.0f), 3, 100);
const entt::entity b = ss.spawn(QVector2D(4.0f, 5.0f), 6, 200);
const std::vector<ScrapInfo> info = ss.allScrapInfo();
const std::vector<ScrapInfo> info = ss.getAllScrapInfo();
REQUIRE(info.size() == 2);
for (const ScrapInfo& i : info)
{

View File

@@ -87,7 +87,7 @@ static void fillMaterials(Simulation& sim, BuildingId yardId,
}
for (const PlacedModule& pm : layout.placedModules)
{
for (const ModuleDef& modDef : sim.config().modules.modules)
for (const ModuleDef& modDef : sim.getConfig().modules.modules)
{
if (modDef.id == pm.moduleId)
{
@@ -109,22 +109,22 @@ static void fillMaterials(Simulation& sim, BuildingId yardId,
TEST_CASE("Ship spawn: no modules leaves base stats unchanged", "[modules]")
{
Simulation sim(loadConfig(), 42);
const ShipDef* def = findSchematic(sim.config(), "interceptor");
const ShipDef* def = findSchematic(sim.getConfig(), "interceptor");
REQUIRE(def != nullptr);
const float expectedHp = static_cast<float>(def->health.hp);
const entt::entity e = sim.ships().spawn("interceptor",
const entt::entity e = sim.getShips().spawn("interceptor",
QVector2D(5.0f, 5.0f), false, std::nullopt);
REQUIRE(sim.admin().isValid(e));
CHECK(sim.admin().get<HealthComponent>(e).maxHp == Approx(expectedHp));
REQUIRE(sim.getAdmin().isValid(e));
CHECK(sim.getAdmin().get<HealthComponent>(e).maxHp == Approx(expectedHp));
}
TEST_CASE("Ship spawn: multiplicative HP module applies correctly", "[modules]")
{
Simulation sim(loadConfig(), 42);
const ShipDef* def = findSchematic(sim.config(), "interceptor");
const ShipDef* def = findSchematic(sim.getConfig(), "interceptor");
REQUIRE(def != nullptr);
const float baseHp = static_cast<float>(def->health.hp);
@@ -136,23 +136,23 @@ TEST_CASE("Ship spawn: multiplicative HP module applies correctly", "[modules]")
pm.rotation = Rotation::East;
layout.placedModules.push_back(pm);
const entt::entity e = sim.ships().spawn("interceptor",
const entt::entity e = sim.getShips().spawn("interceptor",
QVector2D(5.0f, 5.0f), false, layout);
REQUIRE(sim.admin().isValid(e));
REQUIRE(sim.getAdmin().isValid(e));
// armor_plate has multiplied_hp_formula = "1.5"
// final = base * (1 + (1.5 - 1)) + 0 = base * 1.5
CHECK(sim.admin().get<HealthComponent>(e).maxHp == Approx(baseHp * 1.5f));
CHECK(sim.admin().get<HealthComponent>(e).hp == sim.admin().get<HealthComponent>(e).maxHp);
CHECK(sim.getAdmin().get<HealthComponent>(e).maxHp == Approx(baseHp * 1.5f));
CHECK(sim.getAdmin().get<HealthComponent>(e).hp == sim.getAdmin().get<HealthComponent>(e).maxHp);
}
TEST_CASE("Ship spawn: additive sensor module applies correctly", "[modules]")
{
Simulation sim(loadConfig(), 42);
const ShipDef* def = findSchematic(sim.config(), "interceptor");
const ShipDef* def = findSchematic(sim.getConfig(), "interceptor");
REQUIRE(def != nullptr);
const float tileSize = static_cast<float>(sim.config().world.tileSize_m);
const float tileSize = static_cast<float>(sim.getConfig().world.tileSize_m);
const float baseRange_tiles = static_cast<float>(def->sensor.sensorRange_m) / tileSize;
ShipLayoutConfig layout;
@@ -162,19 +162,19 @@ TEST_CASE("Ship spawn: additive sensor module applies correctly", "[modules]")
pm.rotation = Rotation::East;
layout.placedModules.push_back(pm);
const entt::entity e = sim.ships().spawn("interceptor",
const entt::entity e = sim.getShips().spawn("interceptor",
QVector2D(5.0f, 5.0f), false, layout);
REQUIRE(sim.admin().isValid(e));
REQUIRE(sim.getAdmin().isValid(e));
// sensor_booster has added_sensor_range_m_formula = "100" m → 100/10 = 10 tiles
// final = baseRange_tiles * 1.0 + 10 = baseRange_tiles + 10
CHECK(sim.admin().get<SensorRangeComponent>(e).value_tiles == Approx(baseRange_tiles + 10.0f));
CHECK(sim.getAdmin().get<SensorRangeComponent>(e).value_tiles == Approx(baseRange_tiles + 10.0f));
}
TEST_CASE("Ship spawn: multiple modules stack correctly", "[modules]")
{
Simulation sim(loadConfig(), 42);
const ShipDef* def = findSchematic(sim.config(), "interceptor");
const ShipDef* def = findSchematic(sim.getConfig(), "interceptor");
REQUIRE(def != nullptr);
const float baseHp = static_cast<float>(def->health.hp);
@@ -189,14 +189,14 @@ TEST_CASE("Ship spawn: multiple modules stack correctly", "[modules]")
layout.placedModules.push_back(pm);
}
const entt::entity e = sim.ships().spawn("interceptor",
const entt::entity e = sim.getShips().spawn("interceptor",
QVector2D(5.0f, 5.0f), false, layout);
REQUIRE(sim.admin().isValid(e));
REQUIRE(sim.getAdmin().isValid(e));
// Two armor_plates: each 1.5 multiplier
// total_mult = 1 + (1.5 - 1) + (1.5 - 1) = 2.0
// final = base * 2.0
CHECK(sim.admin().get<HealthComponent>(e).maxHp == Approx(baseHp * 2.0f));
CHECK(sim.getAdmin().get<HealthComponent>(e).maxHp == Approx(baseHp * 2.0f));
}
// ---------------------------------------------------------------------------
@@ -207,7 +207,7 @@ TEST_CASE("Shipyard: setShipLayout reinitializes buffers with module materials",
"[modules][shipyard]")
{
Simulation sim(loadConfig(), 42);
const BuildingDef* yardDef = findShipyardDef(sim.config());
const BuildingDef* yardDef = findShipyardDef(sim.getConfig());
REQUIRE(yardDef != nullptr);
const BuildingId yardId = placeShipyard(sim, *yardDef);
@@ -222,7 +222,7 @@ TEST_CASE("Shipyard: setShipLayout reinitializes buffers with module materials",
SimulationTestAccess::buildings(sim).setShipLayout(yardId, layout);
const Building* b = sim.buildings().findBuilding(yardId);
const Building* b = sim.getBuildings().findBuilding(yardId);
REQUIRE(b != nullptr);
// armor_plate needs 2 iron_ingot; interceptor needs 3 iron_ingot + 1 circuit_board
// Total iron_ingot = 5, buffer cap = 2 * 5 = 10
@@ -234,9 +234,9 @@ TEST_CASE("Shipyard: setShipLayout cancels in-progress production",
"[modules][shipyard]")
{
Simulation sim(loadConfig(), 42);
const ShipDef* def = findSchematic(sim.config(), "interceptor");
const ShipDef* def = findSchematic(sim.getConfig(), "interceptor");
REQUIRE(def != nullptr);
const BuildingDef* yardDef = findShipyardDef(sim.config());
const BuildingDef* yardDef = findShipyardDef(sim.getConfig());
REQUIRE(yardDef != nullptr);
const BuildingId yardId = placeShipyard(sim, *yardDef);
@@ -247,7 +247,7 @@ TEST_CASE("Shipyard: setShipLayout cancels in-progress production",
fillMaterials(sim, yardId, *def, emptyLayout);
sim.tick();
const Building* b1 = sim.buildings().findBuilding(yardId);
const Building* b1 = sim.getBuildings().findBuilding(yardId);
REQUIRE(b1 != nullptr);
REQUIRE(b1->production.has_value());
@@ -261,7 +261,7 @@ TEST_CASE("Shipyard: setShipLayout cancels in-progress production",
SimulationTestAccess::buildings(sim).setShipLayout(yardId, layout);
const Building* b2 = sim.buildings().findBuilding(yardId);
const Building* b2 = sim.getBuildings().findBuilding(yardId);
REQUIRE(b2 != nullptr);
CHECK_FALSE(b2->production.has_value());
}
@@ -270,7 +270,7 @@ TEST_CASE("Shipyard: builds a bare hull when no layout is configured",
"[modules][shipyard]")
{
Simulation sim(loadConfig(), 42);
const ShipDef* def = findSchematic(sim.config(), "interceptor");
const ShipDef* def = findSchematic(sim.getConfig(), "interceptor");
REQUIRE(def != nullptr);
// The schematic carries a weapon in its (wave-only) default loadout. This
// test pins that a player shipyard with no configured layout does NOT hand
@@ -278,7 +278,7 @@ TEST_CASE("Shipyard: builds a bare hull when no layout is configured",
// base-hull materials it was charged.
REQUIRE_FALSE(def->defaultModules.empty());
const BuildingDef* yardDef = findShipyardDef(sim.config());
const BuildingDef* yardDef = findShipyardDef(sim.getConfig());
REQUIRE(yardDef != nullptr);
const BuildingId yardId = placeShipyard(sim, *yardDef);
@@ -297,23 +297,23 @@ TEST_CASE("Shipyard: builds a bare hull when no layout is configured",
// Locate the freshly built player ship.
entt::entity built = entt::null;
sim.admin().forEach<ShipIdentityComponent, FactionComponent>(
sim.getAdmin().forEach<ShipIdentityComponent, FactionComponent>(
[&](entt::entity e, const ShipIdentityComponent& si, const FactionComponent& fac)
{
if (!fac.isEnemy && si.schematicId == "interceptor") { built = e; }
});
REQUIRE(sim.admin().isValid(built));
REQUIRE(sim.getAdmin().isValid(built));
// Bare hull: the schematic's default weapon must NOT have been installed.
const bool hasWeapon =
findFirstWeaponChild(sim.admin(), built) != entt::null;
findFirstWeaponChild(sim.getAdmin(), built) != entt::null;
CHECK_FALSE(hasWeapon);
}
TEST_CASE("Shipyard: setRecipe clears ship layout", "[modules][shipyard]")
{
Simulation sim(loadConfig(), 42);
const BuildingDef* yardDef = findShipyardDef(sim.config());
const BuildingDef* yardDef = findShipyardDef(sim.getConfig());
REQUIRE(yardDef != nullptr);
const BuildingId yardId = placeShipyard(sim, *yardDef);
@@ -327,13 +327,13 @@ TEST_CASE("Shipyard: setRecipe clears ship layout", "[modules][shipyard]")
layout.placedModules.push_back(pm);
SimulationTestAccess::buildings(sim).setShipLayout(yardId, layout);
const Building* b1 = sim.buildings().findBuilding(yardId);
const Building* b1 = sim.getBuildings().findBuilding(yardId);
REQUIRE(b1 != nullptr);
REQUIRE(b1->shipLayout.has_value());
SimulationTestAccess::buildings(sim).setRecipe(yardId,"destroyer");
const Building* b2 = sim.buildings().findBuilding(yardId);
const Building* b2 = sim.getBuildings().findBuilding(yardId);
REQUIRE(b2 != nullptr);
CHECK_FALSE(b2->shipLayout.has_value());
}
@@ -342,7 +342,7 @@ TEST_CASE("Shipyard: setRecipe with unchanged recipe keeps ship layout",
"[modules][shipyard]")
{
Simulation sim(loadConfig(), 42);
const BuildingDef* yardDef = findShipyardDef(sim.config());
const BuildingDef* yardDef = findShipyardDef(sim.getConfig());
REQUIRE(yardDef != nullptr);
const BuildingId yardId = placeShipyard(sim, *yardDef);
@@ -356,14 +356,14 @@ TEST_CASE("Shipyard: setRecipe with unchanged recipe keeps ship layout",
layout.placedModules.push_back(pm);
SimulationTestAccess::buildings(sim).setShipLayout(yardId, layout);
const Building* b1 = sim.buildings().findBuilding(yardId);
const Building* b1 = sim.getBuildings().findBuilding(yardId);
REQUIRE(b1 != nullptr);
REQUIRE(b1->shipLayout.has_value());
// Re-selecting the same recipe must be a no-op and preserve the layout.
SimulationTestAccess::buildings(sim).setRecipe(yardId,"interceptor");
const Building* b2 = sim.buildings().findBuilding(yardId);
const Building* b2 = sim.getBuildings().findBuilding(yardId);
REQUIRE(b2 != nullptr);
REQUIRE(b2->shipLayout.has_value());
REQUIRE(b2->shipLayout->placedModules.size() == 1);
@@ -377,7 +377,7 @@ TEST_CASE("Shipyard: setRecipe with unchanged recipe keeps ship layout",
TEST_CASE("Ship spawn: weapon_primer multiplies attack rate in simulation", "[modules]")
{
Simulation sim(loadConfig(), 42);
const ShipDef* def = findSchematic(sim.config(), "interceptor");
const ShipDef* def = findSchematic(sim.getConfig(), "interceptor");
REQUIRE(def != nullptr);
ShipLayoutConfig layout;
@@ -390,22 +390,22 @@ TEST_CASE("Ship spawn: weapon_primer multiplies attack rate in simulation", "[mo
layout.placedModules.push_back(pm);
}
const entt::entity ship = sim.ships().spawn("interceptor",
const entt::entity ship = sim.getShips().spawn("interceptor",
QVector2D(5.0f, 5.0f), false, layout);
const entt::entity weapon = findFirstWeaponChild(sim.admin(), ship);
REQUIRE(sim.admin().isValid(weapon));
const entt::entity weapon = findFirstWeaponChild(sim.getAdmin(), ship);
REQUIRE(sim.getAdmin().isValid(weapon));
// base rate = 2.0 hz; weapon_primer multiplier = 1.2 → 2.4 hz
CHECK(sim.admin().get<WeaponComponent>(weapon).fireRateHz == Approx(2.4f));
CHECK(sim.getAdmin().get<WeaponComponent>(weapon).fireRateHz == Approx(2.4f));
}
TEST_CASE("Ship spawn: weapon_stabilizer multiplies attack range in simulation", "[modules]")
{
Simulation sim(loadConfig(), 42);
const ShipDef* def = findSchematic(sim.config(), "interceptor");
const ShipDef* def = findSchematic(sim.getConfig(), "interceptor");
REQUIRE(def != nullptr);
const float tileSize = static_cast<float>(sim.config().world.tileSize_m);
const float tileSize = static_cast<float>(sim.getConfig().world.tileSize_m);
ShipLayoutConfig layout;
for (const std::string& id : {"laser_cannon", "weapon_stabilizer"})
@@ -417,22 +417,22 @@ TEST_CASE("Ship spawn: weapon_stabilizer multiplies attack range in simulation",
layout.placedModules.push_back(pm);
}
const entt::entity ship = sim.ships().spawn("interceptor",
const entt::entity ship = sim.getShips().spawn("interceptor",
QVector2D(5.0f, 5.0f), false, layout);
const entt::entity weapon = findFirstWeaponChild(sim.admin(), ship);
REQUIRE(sim.admin().isValid(weapon));
const entt::entity weapon = findFirstWeaponChild(sim.getAdmin(), ship);
REQUIRE(sim.getAdmin().isValid(weapon));
// base range = 50 m / tileSize = 5 tiles; weapon_stabilizer multiplier = 1.5 → 7.5 tiles
CHECK(sim.admin().get<WeaponComponent>(weapon).range_tiles == Approx(50.0f / tileSize * 1.5f));
CHECK(sim.getAdmin().get<WeaponComponent>(weapon).range_tiles == Approx(50.0f / tileSize * 1.5f));
}
TEST_CASE("Ship spawn: afterburner additive main_acceleration is converted m/s² to tiles/tick", "[modules]")
{
Simulation sim(loadConfig(), 42);
const ShipDef* def = findSchematic(sim.config(), "interceptor");
const ShipDef* def = findSchematic(sim.getConfig(), "interceptor");
REQUIRE(def != nullptr);
const float tileSize = static_cast<float>(sim.config().world.tileSize_m);
const float tileSize = static_cast<float>(sim.getConfig().world.tileSize_m);
const float tickRate = static_cast<float>(kTickRateHz);
const float base_mpss = static_cast<float>(def->movement.mainAcceleration_mpss);
@@ -443,21 +443,21 @@ TEST_CASE("Ship spawn: afterburner additive main_acceleration is converted m/s²
pm.rotation = Rotation::East;
layout.placedModules.push_back(pm);
const entt::entity e = sim.ships().spawn("interceptor",
const entt::entity e = sim.getShips().spawn("interceptor",
QVector2D(5.0f, 5.0f), false, layout);
// added_main_acceleration_mpss = 60; same conversion as base: / tileSize / tickRate
const float expected = (base_mpss + 60.0f) / tileSize / tickRate;
CHECK(sim.admin().get<DynamicBodyComponent>(e).mainAcceleration_tptt == Approx(expected));
CHECK(sim.getAdmin().get<DynamicBodyComponent>(e).mainAcceleration_tptt == Approx(expected));
}
TEST_CASE("Ship spawn: maneuvering_thrusters additive maneuvering_acceleration is converted m/s² to tiles/tick", "[modules]")
{
Simulation sim(loadConfig(), 42);
const ShipDef* def = findSchematic(sim.config(), "interceptor");
const ShipDef* def = findSchematic(sim.getConfig(), "interceptor");
REQUIRE(def != nullptr);
const float tileSize = static_cast<float>(sim.config().world.tileSize_m);
const float tileSize = static_cast<float>(sim.getConfig().world.tileSize_m);
const float tickRate = static_cast<float>(kTickRateHz);
const float base_mpss = static_cast<float>(def->movement.maneuveringAcceleration_mpss);
@@ -468,12 +468,12 @@ TEST_CASE("Ship spawn: maneuvering_thrusters additive maneuvering_acceleration i
pm.rotation = Rotation::East;
layout.placedModules.push_back(pm);
const entt::entity e = sim.ships().spawn("interceptor",
const entt::entity e = sim.getShips().spawn("interceptor",
QVector2D(5.0f, 5.0f), false, layout);
// added_maneuvering_acceleration_mpss = 10; same conversion as base: / tileSize / tickRate
const float expected = (base_mpss + 10.0f) / tileSize / tickRate;
CHECK(sim.admin().get<DynamicBodyComponent>(e).maneuveringAcceleration_tptt == Approx(expected));
CHECK(sim.getAdmin().get<DynamicBodyComponent>(e).maneuveringAcceleration_tptt == Approx(expected));
}
// ---------------------------------------------------------------------------

View File

@@ -56,7 +56,7 @@ static BuildingId placeShipyard(Simulation& sim, const BuildingDef& yardDef)
static int countShips(Simulation& sim)
{
int n = 0;
sim.admin().forEach<ShipIdentityComponent>(
sim.getAdmin().forEach<ShipIdentityComponent>(
[&n](entt::entity /*e*/, const ShipIdentityComponent& /*si*/) { ++n; });
return n;
}
@@ -85,9 +85,9 @@ TEST_CASE("Shipyard: spawns a player ship after production cycle completes",
{
Simulation sim(loadConfig(), 42);
const ShipDef* def = findAvailableSchematic(sim.config());
const ShipDef* def = findAvailableSchematic(sim.getConfig());
REQUIRE(def != nullptr);
const BuildingDef* yardDef = findShipyardDef(sim.config());
const BuildingDef* yardDef = findShipyardDef(sim.getConfig());
REQUIRE(yardDef != nullptr);
const int shipsBefore = countShips(sim);
@@ -115,7 +115,7 @@ TEST_CASE("Shipyard: spawns a player ship after production cycle completes",
REQUIRE(countShips(sim) == shipsBefore + 1);
bool foundPlayerShip = false;
sim.admin().forEach<ShipIdentityComponent, FactionComponent>(
sim.getAdmin().forEach<ShipIdentityComponent, FactionComponent>(
[&](entt::entity /*e*/, const ShipIdentityComponent& si, const FactionComponent& f)
{
if (!f.isEnemy && si.schematicId == def->id)
@@ -130,7 +130,7 @@ TEST_CASE("Shipyard: does not spawn without a schematic set", "[shipyard]")
{
Simulation sim(loadConfig(), 42);
const BuildingDef* yardDef = findShipyardDef(sim.config());
const BuildingDef* yardDef = findShipyardDef(sim.getConfig());
REQUIRE(yardDef != nullptr);
const int shipsBefore = countShips(sim);
@@ -146,9 +146,9 @@ TEST_CASE("Shipyard: does not spawn with insufficient materials", "[shipyard]")
{
Simulation sim(loadConfig(), 42);
const ShipDef* def = findAvailableSchematic(sim.config());
const ShipDef* def = findAvailableSchematic(sim.getConfig());
REQUIRE(def != nullptr);
const BuildingDef* yardDef = findShipyardDef(sim.config());
const BuildingDef* yardDef = findShipyardDef(sim.getConfig());
REQUIRE(yardDef != nullptr);
const int shipsBefore = countShips(sim);
@@ -170,9 +170,9 @@ TEST_CASE("Shipyard: spawns a second ship after materials replenished", "[shipya
{
Simulation sim(loadConfig(), 42);
const ShipDef* def = findAvailableSchematic(sim.config());
const ShipDef* def = findAvailableSchematic(sim.getConfig());
REQUIRE(def != nullptr);
const BuildingDef* yardDef = findShipyardDef(sim.config());
const BuildingDef* yardDef = findShipyardDef(sim.getConfig());
REQUIRE(yardDef != nullptr);
const BuildingId yardId = placeShipyard(sim, *yardDef);
@@ -203,7 +203,7 @@ TEST_CASE("Shipyard: spawns a second ship after materials replenished", "[shipya
// Verify the shipyard production field cleared (i.e. the cycle completed
// and is not still running).
bool productionCleared = false;
for (const Building& b : sim.buildings().allBuildings())
for (const Building& b : sim.getBuildings().getAllBuildings())
{
if (b.id == yardId)
{

View File

@@ -19,7 +19,7 @@ TEST_CASE("Simulation::currentTick starts at 0", "[simulation]")
{
const Simulation sim(loadConfig());
REQUIRE(sim.currentTick() == 0);
REQUIRE(sim.getCurrentTick() == 0);
}
TEST_CASE("Simulation::tick increments currentTick by 1", "[simulation]")
@@ -28,7 +28,7 @@ TEST_CASE("Simulation::tick increments currentTick by 1", "[simulation]")
sim.tick();
REQUIRE(sim.currentTick() == 1);
REQUIRE(sim.getCurrentTick() == 1);
}
TEST_CASE("Simulation::tick 10 times yields currentTick == 10", "[simulation]")
@@ -40,7 +40,7 @@ TEST_CASE("Simulation::tick 10 times yields currentTick == 10", "[simulation]")
sim.tick();
}
REQUIRE(sim.currentTick() == 10);
REQUIRE(sim.getCurrentTick() == 10);
}
TEST_CASE("Simulation::drainBeamFiredEvents returns empty initially", "[simulation]")

View File

@@ -22,8 +22,8 @@ class BuildingSystem;
// reached via buildings(sim)/belts(sim).
struct SimulationTestAccess
{
static BuildingSystem& buildings(Simulation& sim) { return sim.buildingsMutable(); }
static BeltSystem& belts(Simulation& sim) { return sim.beltsMutable(); }
static BuildingSystem& buildings(Simulation& sim) { return sim.getBuildingsMutable(); }
static BeltSystem& belts(Simulation& sim) { return sim.getBeltsMutable(); }
static BuildingId place(Simulation& sim, BuildingType type, QPoint anchor,
Rotation rotation)

View File

@@ -67,7 +67,7 @@ RecipeDef& findRecipe(GameConfig& cfg, const std::string& id)
// tickDeathsAndLoot fires, triggering the push and schematic choices.
void killEnemyStations(Simulation& sim)
{
sim.admin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
[](entt::entity, StationBodyComponent&, FactionComponent& faction, HealthComponent& health)
{
if (faction.isEnemy)

View File

@@ -49,7 +49,7 @@ TEST_CASE("WaveSystem: threat accumulates at boss wave counter rate", "[wave]")
ws.tickThreatAccumulation();
}
REQUIRE(ws.threatLevel() == Approx(1.0));
REQUIRE(ws.getThreatLevel() == Approx(1.0));
}
TEST_CASE("WaveSystem: threatAccumulationRate matches the rate formula outside quiet windows",
@@ -60,7 +60,7 @@ TEST_CASE("WaveSystem: threatAccumulationRate matches the rate formula outside q
WaveSystem ws(cfg, rng);
// threat_rate_formula = "x", boss wave counter starts at 1 → rate = 1 threat/s.
REQUIRE(ws.threatAccumulationRate() == Approx(1.0));
REQUIRE(ws.getThreatAccumulationRate() == Approx(1.0));
}
TEST_CASE("WaveSystem: threatAccumulationRate is 0 during a quiet window", "[wave]")
@@ -71,14 +71,14 @@ TEST_CASE("WaveSystem: threatAccumulationRate is 0 during a quiet window", "[wav
std::mt19937 rng(42);
WaveSystem ws(cfg, rng);
REQUIRE(ws.threatAccumulationRate() == Approx(0.0));
REQUIRE(ws.getThreatAccumulationRate() == Approx(0.0));
const double before = ws.threatLevel();
const double before = ws.getThreatLevel();
for (int i = 0; i < static_cast<int>(secondsToTicks(1.0)); ++i)
{
ws.tickThreatAccumulation();
}
REQUIRE(ws.threatLevel() == Approx(before));
REQUIRE(ws.getThreatLevel() == Approx(before));
}
TEST_CASE("WaveSystem: generation starts at 0 and increments on station destruction", "[wave]")
@@ -87,11 +87,11 @@ TEST_CASE("WaveSystem: generation starts at 0 and increments on station destruct
std::mt19937 rng(42);
WaveSystem ws(cfg, rng);
REQUIRE(ws.generation() == 0);
REQUIRE(ws.getGeneration() == 0);
ws.onEnemyStationsDestroyed();
REQUIRE(ws.generation() == 1);
REQUIRE(ws.getGeneration() == 1);
ws.onEnemyStationsDestroyed();
REQUIRE(ws.generation() == 2);
REQUIRE(ws.getGeneration() == 2);
}
// ---------------------------------------------------------------------------
@@ -104,7 +104,7 @@ TEST_CASE("WaveSystem: Simulation pre-places HQ + 2 player + 2 enemy stations",
// HQ is still a Building (for belt integration).
int hqCount = 0;
for (const Building& b : sim.buildings().allBuildings())
for (const Building& b : sim.getBuildings().getAllBuildings())
{
if (b.type == BuildingType::Hq) { ++hqCount; }
}
@@ -112,7 +112,7 @@ TEST_CASE("WaveSystem: Simulation pre-places HQ + 2 player + 2 enemy stations",
// Stations are ECS entities.
int playerCount = 0;
int enemyCount = 0;
sim.admin().forEach<StationBodyComponent, FactionComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent>(
[&](entt::entity /*e*/, const StationBodyComponent& /*sb*/, const FactionComponent& f)
{
if (f.isEnemy) { ++enemyCount; }
@@ -129,10 +129,10 @@ TEST_CASE("WaveSystem: HQ has correct initial HP from config", "[wave]")
const Simulation sim(loadConfig(), 42);
const float expectedHp =
static_cast<float>(sim.config().stations.hq.hpFormula.evaluate(0.0));
static_cast<float>(sim.getConfig().stations.hq.hpFormula.evaluate(0.0));
bool found = false;
float actualHp = 0.0f;
sim.admin().forEach<HqProxyComponent, HealthComponent>(
sim.getAdmin().forEach<HqProxyComponent, HealthComponent>(
[&](entt::entity /*e*/, const HqProxyComponent& /*hq*/, const HealthComponent& h)
{
found = true;
@@ -147,7 +147,7 @@ TEST_CASE("WaveSystem: HQ anchor is at asteroid right edge", "[wave]")
{
const Simulation sim(loadConfig(), 42);
for (const Building& b : sim.buildings().allBuildings())
for (const Building& b : sim.getBuildings().getAllBuildings())
{
if (b.type != BuildingType::Hq) { continue; }
// Rightmost body cell must be at x = -1 (asteroid right edge).
@@ -165,11 +165,11 @@ TEST_CASE("WaveSystem: player stations have weapon set", "[wave]")
Simulation sim(loadConfig(), 42);
int armedPlayerStations = 0;
sim.admin().forEach<WeaponComponent, ModuleOwnerComponent>(
sim.getAdmin().forEach<WeaponComponent, ModuleOwnerComponent>(
[&](entt::entity /*e*/, const WeaponComponent& w, const ModuleOwnerComponent& mo)
{
if (!sim.admin().hasAll<StationBodyComponent>(mo.owner)) { return; }
const FactionComponent& f = sim.admin().get<FactionComponent>(mo.owner);
if (!sim.getAdmin().hasAll<StationBodyComponent>(mo.owner)) { return; }
const FactionComponent& f = sim.getAdmin().get<FactionComponent>(mo.owner);
if (!f.isEnemy)
{
++armedPlayerStations;
@@ -186,11 +186,11 @@ TEST_CASE("WaveSystem: enemy stations have weapon set", "[wave]")
Simulation sim(loadConfig(), 42);
int armedEnemyStations = 0;
sim.admin().forEach<WeaponComponent, ModuleOwnerComponent>(
sim.getAdmin().forEach<WeaponComponent, ModuleOwnerComponent>(
[&](entt::entity /*e*/, const WeaponComponent& w, const ModuleOwnerComponent& mo)
{
if (!sim.admin().hasAll<StationBodyComponent>(mo.owner)) { return; }
const FactionComponent& f = sim.admin().get<FactionComponent>(mo.owner);
if (!sim.getAdmin().hasAll<StationBodyComponent>(mo.owner)) { return; }
const FactionComponent& f = sim.getAdmin().get<FactionComponent>(mo.owner);
if (f.isEnemy)
{
++armedEnemyStations;
@@ -221,7 +221,7 @@ TEST_CASE("WaveSystem: enemy ships spawn after the initial gap elapses", "[wave]
sim.tick();
if (!foundEnemyShip)
{
sim.admin().forEach<ShipIdentityComponent, FactionComponent>(
sim.getAdmin().forEach<ShipIdentityComponent, FactionComponent>(
[&](entt::entity /*e*/, const ShipIdentityComponent& /*si*/,
const FactionComponent& f)
{
@@ -253,7 +253,7 @@ TEST_CASE("WaveSystem: destroying both enemy stations triggers a push", "[wave]"
Simulation sim(loadConfig(), 42);
// Damage both enemy stations to 0.
sim.admin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
[](entt::entity /*e*/, const StationBodyComponent& /*sb*/, const FactionComponent& f, HealthComponent& h)
{
if (f.isEnemy) { h.hp = -1.0f; }
@@ -263,7 +263,7 @@ TEST_CASE("WaveSystem: destroying both enemy stations triggers a push", "[wave]"
// After push: should have 2 new enemy stations.
int enemyCount = 0;
sim.admin().forEach<StationBodyComponent, FactionComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent>(
[&](entt::entity /*e*/, const StationBodyComponent& /*sb*/, const FactionComponent& f)
{
if (f.isEnemy) { ++enemyCount; }
@@ -275,7 +275,7 @@ TEST_CASE("WaveSystem: push generates pending schematic choices", "[wave]")
{
Simulation sim(loadConfig(), 42);
sim.admin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
[](entt::entity /*e*/, const StationBodyComponent& /*sb*/, const FactionComponent& f, HealthComponent& h)
{
if (f.isEnemy) { h.hp = -1.0f; }
@@ -293,7 +293,7 @@ TEST_CASE("WaveSystem: push schematic choices have valid ids", "[wave]")
{
Simulation sim(loadConfig(), 42);
sim.admin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
[](entt::entity /*e*/, const StationBodyComponent& /*sb*/, const FactionComponent& f, HealthComponent& h)
{
if (f.isEnemy) { h.hp = -1.0f; }
@@ -306,20 +306,20 @@ TEST_CASE("WaveSystem: push schematic choices have valid ids", "[wave]")
for (const SchematicChoiceOption& opt : choices)
{
bool validId = false;
for (const ShipDef& def : sim.config().ships.ships)
for (const ShipDef& def : sim.getConfig().ships.ships)
{
if (def.id == opt.schematicId) { validId = true; break; }
}
if (!validId)
{
for (const ModuleDef& def : sim.config().modules.modules)
for (const ModuleDef& def : sim.getConfig().modules.modules)
{
if (def.id == opt.schematicId) { validId = true; break; }
}
}
if (!validId)
{
for (const RecipeDef& def : sim.config().recipes.recipes)
for (const RecipeDef& def : sim.getConfig().recipes.recipes)
{
if (def.id == opt.schematicId) { validId = true; break; }
}
@@ -332,7 +332,7 @@ TEST_CASE("WaveSystem: schematic choices have no duplicates", "[wave]")
{
Simulation sim(loadConfig(), 42);
sim.admin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
[](entt::entity /*e*/, const StationBodyComponent& /*sb*/, const FactionComponent& f, HealthComponent& h)
{
if (f.isEnemy) { h.hp = -1.0f; }
@@ -352,7 +352,7 @@ TEST_CASE("WaveSystem: applySchematicChoice clears pending and applies", "[wave]
{
Simulation sim(loadConfig(), 42);
sim.admin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
[](entt::entity /*e*/, const StationBodyComponent& /*sb*/, const FactionComponent& f, HealthComponent& h)
{
if (f.isEnemy) { h.hp = -1.0f; }
@@ -370,7 +370,7 @@ TEST_CASE("WaveSystem: push places new enemy stations further right", "[wave]")
// Record the X position of the initial enemy stations.
int initialX = std::numeric_limits<int>::min();
sim.admin().forEach<StationBodyComponent, FactionComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent>(
[&](entt::entity /*e*/, const StationBodyComponent& sb, const FactionComponent& f)
{
if (f.isEnemy && sb.anchor.x() > initialX)
@@ -379,7 +379,7 @@ TEST_CASE("WaveSystem: push places new enemy stations further right", "[wave]")
}
});
sim.admin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
[](entt::entity /*e*/, const StationBodyComponent& /*sb*/, const FactionComponent& f, HealthComponent& h)
{
if (f.isEnemy) { h.hp = -1.0f; }
@@ -387,7 +387,7 @@ TEST_CASE("WaveSystem: push places new enemy stations further right", "[wave]")
sim.tick();
int newX = std::numeric_limits<int>::min();
sim.admin().forEach<StationBodyComponent, FactionComponent>(
sim.getAdmin().forEach<StationBodyComponent, FactionComponent>(
[&](entt::entity /*e*/, const StationBodyComponent& sb, const FactionComponent& f)
{
if (f.isEnemy && sb.anchor.x() > newX)