#pragma once #include #include #include #include #include #include #include "BalancingConfig.h" #include "BeltSystem.h" #include "EcsComponents.h" #include "EntityAdmin.h" #include "BuildingId.h" #include "entt/entity/entity.hpp" #include "FireEvent.h" #include "GameConfig.h" #include "Tick.h" class AiSystem; class BuildingSystem; class CombatSystem; class DynamicBodySystem; class MovementIntentSystem; class ShipSystem; class ScrapSystem; struct ArenaStatus { struct Entry { std::string displayName; int level; int total; int surviving; }; struct TeamStatus { std::string name; std::vector entries; // HQ first, then ships, then stations }; TeamStatus teams[2]; bool finished = false; int winnerTeam = -1; // 0 or 1 when finished; -1 while running }; class ArenaSimulation { public: ArenaSimulation(const GameConfig& gameConfig, ArenaConfig arenaConfig, unsigned int seed = 0); ~ArenaSimulation(); void run(); void requestStop(); void tickOnce(); std::vector drainFireEvents(); ArenaStatus status() const; bool isFinished() const; int winnerTeam() const; Tick currentTick() const; const ArenaConfig& arenaConfig() const; const BuildingSystem& buildings() const; const ShipSystem& ships() const; const ScrapSystem& scraps() const; EntityAdmin& admin(); const EntityAdmin& admin() const; private: BuildingId allocateBuildingId(); void placeStructures(); void spawnShips(); void tick(); void tickDeaths(); void updateStatus(); const GameConfig& m_gameConfig; ArenaConfig m_arenaConfig; std::mt19937 m_rng; Tick m_currentTick; BuildingId m_nextBuildingId; EntityAdmin m_admin; BeltSystem m_beltSystem; std::unique_ptr m_buildingSystem; std::unique_ptr m_shipSystem; std::unique_ptr m_aiSystem; std::unique_ptr m_movementIntentSystem; std::unique_ptr m_dynamicBodySystem; std::unique_ptr m_combatSystem; std::unique_ptr m_scrapSystem; entt::entity m_team1HqEntity; entt::entity m_team2HqEntity; bool m_finished; int m_winnerTeam; std::atomic m_stopRequested; std::vector m_fireEvents; mutable std::mutex m_statusMutex; ArenaStatus m_status; };