diff --git a/src/core/include/warfactory/ASerializable.h b/src/core/include/warfactory/ASerializable.h new file mode 100644 index 0000000..c531e40 --- /dev/null +++ b/src/core/include/warfactory/ASerializable.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +using json = nlohmann::json; + +namespace warfactory { + +class SerializationRegistry; + +class ASerializable { +private: + std::string instance_id; + +public: + ASerializable(const std::string& id); + virtual ~ASerializable(); + + const std::string& getInstanceId() const { return instance_id; } + + virtual json serialize() const = 0; + virtual void deserialize(const json& data) = 0; + +protected: + void registerForSerialization(); + void unregisterFromSerialization(); +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/ISerializable.h b/src/core/include/warfactory/ISerializable.h new file mode 100644 index 0000000..d66739d --- /dev/null +++ b/src/core/include/warfactory/ISerializable.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +using json = nlohmann::json; + +namespace warfactory { + +class ISerializable { +public: + virtual ~ISerializable() = default; + + virtual json serialize() const = 0; + virtual void deserialize(const json& data) = 0; +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/Resource.h b/src/core/include/warfactory/Resource.h new file mode 100644 index 0000000..7ffcc8e --- /dev/null +++ b/src/core/include/warfactory/Resource.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include + +using json = nlohmann::json; + +namespace warfactory { + +class Resource { +private: + std::string resource_id; + std::string name; + std::string category; + std::string logistic_category; + float density; + int stack_size; + std::string container_type; + json ui_data; + +public: + Resource() = default; + Resource(const json& resource_data); + + const std::string& getResourceId() const { return resource_id; } + const std::string& getName() const { return name; } + const std::string& getCategory() const { return category; } + const std::string& getLogisticCategory() const { return logistic_category; } + float getDensity() const { return density; } + int getStackSize() const { return stack_size; } + const std::string& getContainerType() const { return container_type; } + const json& getUIData() const { return ui_data; } + + static Resource loadFromJson(const std::string& resource_id, const json& resource_data); +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/SerializationRegistry.h b/src/core/include/warfactory/SerializationRegistry.h new file mode 100644 index 0000000..fdd7eb6 --- /dev/null +++ b/src/core/include/warfactory/SerializationRegistry.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include +#include + +using json = nlohmann::json; + +namespace warfactory { + +class ASerializable; + +class SerializationRegistry { +private: + std::unordered_map registered_objects; + + SerializationRegistry() = default; + +public: + static SerializationRegistry& getInstance(); + + void registerObject(const std::string& instance_id, ASerializable* object); + void unregisterObject(const std::string& instance_id); + + json serializeAll() const; + void deserializeAll(const json& data); + + json serializeObject(const std::string& instance_id) const; + void deserializeObject(const std::string& instance_id, const json& data); + + size_t getRegisteredCount() const { return registered_objects.size(); } + std::vector getRegisteredIds() const; + + void clear(); +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/CLAUDE.md b/src/modules/world-generation-realist/CLAUDE.md new file mode 100644 index 0000000..2d6c2c5 --- /dev/null +++ b/src/modules/world-generation-realist/CLAUDE.md @@ -0,0 +1,51 @@ +# World Generation Realist Module + +**Responsabilité**: Génération procédurale géologiquement réaliste avec architecture Phase/Step. + +## Description + +Ce module définit les interfaces pour un système de génération procédurale basé sur une architecture Phase/Step modulaire. Conçu pour implémenter le système 8-phases défini dans `gameData/WorldGeneration/Regular_world.json`. + +## Architecture + +### Interfaces Core +- **IWorldGenerationPhase**: Interface pour les phases de génération (ex: Geological, Climate, Budget, Resource) +- **IWorldGenerationStep**: Interface pour les étapes individuelles au sein d'une phase + +### Conception +- **Phase**: Groupe logique d'étapes (ex: Phase Géologique = Cratères + Tectonique + Volcans + Érosion) +- **Step**: Opération atomique de génération avec dépendances explicites +- **Modularité**: Chaque phase/step isolé et testable +- **Progress tracking**: Suivi granulaire de progression + +## Contraintes Modules +- **200-300 lignes max** par implémentation +- **JSON-only communication** via IDataNode +- **Autonomous builds**: `cd src/modules/world-generation-realist/ && cmake .` +- **Hot-reload compatible**: State serialization requise + +## Build System + +### Commands +```bash +cd src/modules/world-generation-realist/ +cmake . # Configuration autonome +# Note: Aucune library créée tant qu'il n'y a pas d'implémentations +``` + +### Dependencies +- `nlohmann/json`: Configuration JSON processing +- `IDataNode`: Interface configuration depuis core/ +- `C++20`: Features modernes + +### Structure Prévue +``` +include/ +├── IWorldGenerationPhase.h # Interface phase +├── IWorldGenerationStep.h # Interface step +└── (futures implémentations...) +``` + +--- + +**État actuel**: Interfaces définies, prêt pour implémentations concrètes. \ No newline at end of file diff --git a/src/modules/world-generation-realist/CMakeLists.txt b/src/modules/world-generation-realist/CMakeLists.txt new file mode 100644 index 0000000..e8bc922 --- /dev/null +++ b/src/modules/world-generation-realist/CMakeLists.txt @@ -0,0 +1,47 @@ +cmake_minimum_required(VERSION 3.20) +project(world-generation-realist) + +set(CMAKE_CXX_STANDARD 20) + +# Add compiler flags +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0 -fsanitize=address -fsanitize=undefined") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -DNDEBUG") + +# Include directories +include_directories(include) +include_directories(../../core/include) + +# Find required packages +find_package(nlohmann_json REQUIRED) + +# Source files (empty for now, just interfaces) +set(SOURCES + # Add source files here when implementations are created +) + +# Create the module library (when sources exist) +if(SOURCES) + add_library(world-generation-realist SHARED ${SOURCES}) + + # Link libraries + target_link_libraries(world-generation-realist + nlohmann_json::nlohmann_json + ) + + # Set output directory + set_target_properties(world-generation-realist PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + ) + + # Install targets + install(TARGETS world-generation-realist + LIBRARY DESTINATION lib + ) +endif() + +# Install headers +install(DIRECTORY include/ + DESTINATION include/world-generation-realist + FILES_MATCHING PATTERN "*.h" +) \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/GMap.h b/src/modules/world-generation-realist/include/GMap.h new file mode 100644 index 0000000..491f745 --- /dev/null +++ b/src/modules/world-generation-realist/include/GMap.h @@ -0,0 +1,90 @@ +#pragma once + +#include "GTile.h" +#include "warfactory/ASerializable.h" + +namespace warfactory { + +class GMap : public ASerializable { +private: + int width, height; + GTile* tiles; // Contiguous memory block: tiles[y * width + x] + +public: + GMap(int w, int h); + ~GMap(); + + // Prevent copy (expensive with large maps) + GMap(const GMap&) = delete; + GMap& operator=(const GMap&) = delete; + + // Move constructor/assignment for efficiency + GMap(GMap&& other) noexcept; + GMap& operator=(GMap&& other) noexcept; + + // ======================================== + // MAP ACCESS + // ======================================== + + GTile* getTile(int x, int y); + const GTile* getTile(int x, int y) const; + + bool isValidCoordinate(int x, int y) const { + return x >= 0 && x < width && y >= 0 && y < height; + } + + int getWidth() const { return width; } + int getHeight() const { return height; } + + // ======================================== + // BULK OPERATIONS (Phase 1 specific) + // ======================================== + + /** + * @brief Apply cooling to all tiles + */ + void coolAllTiles(float cooling_rate_celsius); + + /** + * @brief Apply impact effects to circular area + */ + void applyImpactToArea(float center_x, float center_y, float radius_meters, + float heat_celsius, uint16_t crater_depth, uint8_t crater_scale); + + /** + * @brief Apply volcanic heat to specific location + */ + void applyVolcanicHeat(float x, float y, float heat_celsius, float radius_meters); + + /** + * @brief Get average temperature across map + */ + float getAverageTemperature() const; + + /** + * @brief Get average elevation across map + */ + float getAverageElevation() const; + + // ======================================== + // ITERATION SUPPORT (cache-friendly) + // ======================================== + + GTile* begin() { return tiles; } + GTile* end() { return tiles + (width * height); } + const GTile* begin() const { return tiles; } + const GTile* end() const { return tiles + (width * height); } + + // ======================================== + // SERIALIZATION + // ======================================== + + json serialize() const override; + void deserialize(const json& data) override; + +private: + void allocateTiles(); + void deallocateTiles(); +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/GTile.h b/src/modules/world-generation-realist/include/GTile.h new file mode 100644 index 0000000..9315f94 --- /dev/null +++ b/src/modules/world-generation-realist/include/GTile.h @@ -0,0 +1,261 @@ +#pragma once + +#include +#include +#include + +namespace warfactory { + +struct GTile { + // ======================================== + // CORE DATA (16 bytes total) - Complete tile data + // ======================================== + uint16_t elevation; // Elevation: 0-65535 = -32km to +32km (geological range) + int16_t temperature; // Temperature: -32768 to +32767 = -3276°C to +3276°C (0.1°C increments) + uint16_t biome_type_id; // Biome classification + uint8_t water_token; // Water/rain tokens from climate simulation + uint8_t wind_token; // Wind tokens from climate simulation + int8_t target_budget_score; // Target budget score: -10 to +10 + uint16_t destruction_token; // Bits 1-4: highWind, 5-8: flood, 9-12: hurricane, 13-16: reserved + uint16_t flags; // Tile properties and state flags + uint32_t feature_set_id; // Features present on this tile (0 = no features) + + /** + * @brief Constructor with default values + */ + GTile() : elevation(0), temperature(-1000), biome_type_id(0), water_token(0), wind_token(0), + target_budget_score(0), destruction_token(0), flags(0), feature_set_id(0) {} + + // ======================================== + // ELEVATION CONVERSION (same as WorldTileData) + // ======================================== + + /** + * @brief Convert elevation to meters (geological range: -32km to +32km) + */ + float getElevationMeters() const { + return (elevation / 65535.0f) * 64000.0f - 32000.0f; + } + + /** + * @brief Set elevation from meters + */ + void setElevationMeters(float meters) { + float normalized = (meters + 32000.0f) / 64000.0f; + elevation = static_cast(std::clamp(normalized * 65535.0f, 0.0f, 65535.0f)); + } + + // ======================================== + // TEMPERATURE CONVERSION (same as WorldTileData) + // ======================================== + + /** + * @brief Convert temperature to Celsius (0.1°C precision, range: -3276°C to +3276°C) + */ + float getTemperatureCelsius() const { + return temperature * 0.1f; + } + + /** + * @brief Set temperature from Celsius + */ + void setTemperatureCelsius(float celsius) { + temperature = static_cast(std::clamp(celsius * 10.0f, -32768.0f, 32767.0f)); + } + + // ======================================== + // BIOME & CLIMATE DATA + // ======================================== + + /** + * @brief Get biome type ID + */ + uint16_t getBiomeTypeId() const { return biome_type_id; } + + /** + * @brief Set biome type ID + */ + void setBiomeTypeId(uint16_t biome_id) { biome_type_id = biome_id; } + + /** + * @brief Get water tokens from climate simulation + */ + uint8_t getWaterToken() const { return water_token; } + + /** + * @brief Set water tokens + */ + void setWaterToken(uint8_t tokens) { water_token = tokens; } + + /** + * @brief Add water tokens + */ + void addWaterToken(uint8_t additional_tokens) { + uint16_t new_total = static_cast(water_token) + additional_tokens; + water_token = static_cast(std::min(new_total, 255u)); + } + + /** + * @brief Get wind tokens from climate simulation + */ + uint8_t getWindToken() const { return wind_token; } + + /** + * @brief Set wind tokens + */ + void setWindToken(uint8_t tokens) { wind_token = tokens; } + + /** + * @brief Add wind tokens + */ + void addWindToken(uint8_t additional_tokens) { + uint16_t new_total = static_cast(wind_token) + additional_tokens; + wind_token = static_cast(std::min(new_total, 255u)); + } + + // ======================================== + // DESTRUCTION TOKEN (packed in 16 bits) + // ======================================== + + /** + * @brief Get high wind token (bits 1-4) + */ + uint8_t getHighWindToken() const { + return destruction_token & 0x0F; + } + + /** + * @brief Set high wind token (0-15) + */ + void setHighWindToken(uint8_t tokens) { + destruction_token = (destruction_token & 0xFFF0) | (tokens & 0x0F); + } + + /** + * @brief Get flood token (bits 5-8) + */ + uint8_t getFloodToken() const { + return (destruction_token >> 4) & 0x0F; + } + + /** + * @brief Set flood token (0-15) + */ + void setFloodToken(uint8_t tokens) { + destruction_token = (destruction_token & 0xFF0F) | ((tokens & 0x0F) << 4); + } + + /** + * @brief Get hurricane token (bits 9-12) + */ + uint8_t getHurricaneToken() const { + return (destruction_token >> 8) & 0x0F; + } + + /** + * @brief Set hurricane token (0-15) + */ + void setHurricaneToken(uint8_t tokens) { + destruction_token = (destruction_token & 0xF0FF) | ((tokens & 0x0F) << 8); + } + + /** + * @brief Add high wind tokens + */ + void addHighWindToken(uint8_t additional) { + uint8_t current = getHighWindToken(); + setHighWindToken(std::min(static_cast(current + additional), static_cast(15))); + } + + /** + * @brief Add flood tokens + */ + void addFloodToken(uint8_t additional) { + uint8_t current = getFloodToken(); + setFloodToken(std::min(static_cast(current + additional), static_cast(15))); + } + + /** + * @brief Add hurricane tokens + */ + void addHurricaneToken(uint8_t additional) { + uint8_t current = getHurricaneToken(); + setHurricaneToken(std::min(static_cast(current + additional), static_cast(15))); + } + + // ======================================== + // BUDGET SYSTEM + // ======================================== + + /** + * @brief Get target budget score (-10 to +10) + */ + int8_t getTargetBudgetScore() const { return target_budget_score; } + + /** + * @brief Set target budget score + */ + void setTargetBudgetScore(int8_t score) { target_budget_score = score; } + + // ======================================== + // FLAGS & FEATURES + // ======================================== + + /** + * @brief Get tile flags + */ + uint16_t getFlags() const { return flags; } + + /** + * @brief Set specific flag + */ + void setFlag(uint16_t flag, bool value) { + if (value) { + flags |= flag; + } else { + flags &= ~flag; + } + } + + /** + * @brief Check if flag is set + */ + bool hasFlag(uint16_t flag) const { return (flags & flag) != 0; } + + /** + * @brief Get feature set ID + */ + uint32_t getFeatureSetId() const { return feature_set_id; } + + /** + * @brief Set feature set ID + */ + void setFeatureSetId(uint32_t feature_id) { feature_set_id = feature_id; } + + /** + * @brief Check if tile has features + */ + bool hasFeatures() const { return feature_set_id != 0; } + + // ======================================== + // PHASE 1 OPERATIONS + // ======================================== + + /** + * @brief Apply heat from meteorite impact + */ + void applyImpactHeat(float heat_celsius) { + float current_temp = getTemperatureCelsius(); + setTemperatureCelsius(current_temp + heat_celsius); + } + + /** + * @brief Cool tile by given amount + */ + void coolTile(float cooling_celsius) { + float current_temp = getTemperatureCelsius(); + setTemperatureCelsius(current_temp - cooling_celsius); + } +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/IAttachedElement.h b/src/modules/world-generation-realist/include/IAttachedElement.h new file mode 100644 index 0000000..a891996 --- /dev/null +++ b/src/modules/world-generation-realist/include/IAttachedElement.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include + +using json = nlohmann::json; + +namespace warfactory { + +class IAttachedElement { +public: + virtual ~IAttachedElement() = default; + + virtual int getElementId() const = 0; + + virtual float getX() const = 0; + virtual float getY() const = 0; + + virtual float getMass() const = 0; + virtual float getRadius() const = 0; + + virtual std::string getElementType() const = 0; + + virtual std::vector getAttachedToElements() const = 0; + virtual void attachToElement(int element_id) = 0; + virtual void detachFromElement(int element_id) = 0; + virtual bool isAttachedTo(int element_id) const = 0; + + virtual json serialize() const = 0; + virtual void deserialize(const json& data) = 0; +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/IElementData.h b/src/modules/world-generation-realist/include/IElementData.h new file mode 100644 index 0000000..37df5ff --- /dev/null +++ b/src/modules/world-generation-realist/include/IElementData.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +using json = nlohmann::json; + +namespace warfactory { + +class IElementData { +public: + virtual ~IElementData() = default; + + virtual std::string getDataType() const = 0; + + virtual json serialize() const = 0; + virtual void deserialize(const json& data) = 0; +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/IRegion.h b/src/modules/world-generation-realist/include/IRegion.h new file mode 100644 index 0000000..5de3a9b --- /dev/null +++ b/src/modules/world-generation-realist/include/IRegion.h @@ -0,0 +1,35 @@ +#pragma once + +#include "IAttachedElement.h" +#include "IElementData.h" +#include + +namespace warfactory { + +class IRegion : public IAttachedElement { +public: + virtual ~IRegion() = default; + + virtual void setPosition(float x, float y) = 0; + + virtual void setMass(float mass) = 0; + + virtual void setRadius(float radius) = 0; + + virtual std::unique_ptr getRegionData() const = 0; + virtual void setRegionData(std::unique_ptr data) = 0; + + virtual void updatePosition(float delta_x, float delta_y) = 0; + + virtual void updateMass(float delta_mass) = 0; + + virtual void updateRadius(float delta_radius) = 0; + + virtual float getAttachmentStrength(int attached_element_id) const = 0; + virtual void setAttachmentStrength(int attached_element_id, float strength) = 0; + + virtual bool canFuseWith(const IRegion& other) const = 0; + virtual void fuseWith(const IRegion& other) = 0; +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/IWorldGenerationPhase.h b/src/modules/world-generation-realist/include/IWorldGenerationPhase.h new file mode 100644 index 0000000..9b22f54 --- /dev/null +++ b/src/modules/world-generation-realist/include/IWorldGenerationPhase.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include "warfactory/IDataNode.h" + +class WorldData; +class IWorldGenerationStep; + +namespace warfactory { + +class IWorldGenerationPhase { +public: + virtual ~IWorldGenerationPhase() = default; + + virtual std::string getPhaseName() const = 0; + + virtual std::vector> getSteps() const = 0; + + virtual bool execute(WorldData& world, const IDataNode& config) = 0; + + virtual float getProgress() const = 0; + + virtual bool isComplete() const = 0; + + virtual void reset() = 0; + + virtual std::string getPhaseDescription() const = 0; + + virtual int getPhaseNumber() const = 0; + + virtual std::vector getRequiredPreviousPhases() const = 0; + + virtual std::vector getProducedData() const = 0; + + virtual bool canExecute(const WorldData& world) const = 0; +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/IWorldGenerationStep.h b/src/modules/world-generation-realist/include/IWorldGenerationStep.h new file mode 100644 index 0000000..f8636e3 --- /dev/null +++ b/src/modules/world-generation-realist/include/IWorldGenerationStep.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include "warfactory/IDataNode.h" + +class WorldData; + +namespace warfactory { + +class IWorldGenerationStep { +public: + virtual ~IWorldGenerationStep() = default; + + virtual std::string getStepName() const = 0; + + virtual bool execute(WorldData& world, const IDataNode& config) = 0; + + virtual bool canExecute(const WorldData& world) const = 0; + + virtual float getProgress() const = 0; + + virtual bool isComplete() const = 0; + + virtual void reset() = 0; + + virtual std::string getStepDescription() const = 0; + + virtual float getEstimatedDuration() const = 0; + + virtual std::vector getRequiredPreviousSteps() const = 0; + + virtual std::vector getProducedData() const = 0; + + virtual int getStepOrder() const = 0; + + virtual std::string getParentPhase() const = 0; +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/Meteorite.h b/src/modules/world-generation-realist/include/Meteorite.h new file mode 100644 index 0000000..0a816b4 --- /dev/null +++ b/src/modules/world-generation-realist/include/Meteorite.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include + +using json = nlohmann::json; + +namespace warfactory { + +class Meteorite { +private: + std::string meteorite_type; + std::unordered_map resource_composition; + float impact_energy_multiplier; + float crater_formation_factor; + float surface_metal_deposit_ratio; + +public: + Meteorite() = default; + Meteorite(const json& meteorite_data); + + const std::string& getMeteoriteType() const { return meteorite_type; } + + const std::unordered_map& getResourceComposition() const { return resource_composition; } + float getResourceQuantity(const std::string& resource_id) const; + bool hasResource(const std::string& resource_id) const; + + float getImpactEnergyMultiplier() const { return impact_energy_multiplier; } + float getCraterFormationFactor() const { return crater_formation_factor; } + float getSurfaceMetalDepositRatio() const { return surface_metal_deposit_ratio; } + + static Meteorite loadFromJson(const std::string& meteorite_type, const json& meteorite_data); +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/MeteoriteImpact.h b/src/modules/world-generation-realist/include/MeteoriteImpact.h new file mode 100644 index 0000000..7544385 --- /dev/null +++ b/src/modules/world-generation-realist/include/MeteoriteImpact.h @@ -0,0 +1,44 @@ +#pragma once + +#include "Meteorite.h" +#include "WorldData.h" +#include "PlanetaryCore.h" + +namespace warfactory { + +class SurfaceState; + +class MeteoriteImpact { +private: + Meteorite meteorite_template; + float impact_size; + float impact_velocity; + float impact_angle; + float x_position, y_position; + +public: + MeteoriteImpact(const Meteorite& meteorite, float size, float velocity, float angle, float x, float y); + + void applyImpactEffects(WorldData& world, PlanetaryCore& core); + + void createCrater(WorldData& world); + + void depositMaterials(PlanetaryCore& core, SurfaceState& surface, RegionManager& region_manager); + + void generateHeat(WorldData& world); + + float calculateKineticEnergy() const; + float calculateImpactRadius() const; + float calculateHeatGeneration() const; + float calculateCraterDepth() const; + float calculateCraterRadius() const; + + const Meteorite& getMeteoriteTemplate() const { return meteorite_template; } + float getImpactSize() const { return impact_size; } + float getImpactVelocity() const { return impact_velocity; } + float getImpactAngle() const { return impact_angle; } + float getX() const { return x_position; } + float getY() const { return y_position; } +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/PhaseRegistry.h b/src/modules/world-generation-realist/include/PhaseRegistry.h new file mode 100644 index 0000000..9760b56 --- /dev/null +++ b/src/modules/world-generation-realist/include/PhaseRegistry.h @@ -0,0 +1,40 @@ +#pragma once + +#include "IWorldGenerationPhase.h" +#include "IWorldGenerationStep.h" +#include +#include +#include + +namespace warfactory { + +class PhaseRegistry { +private: + std::unordered_map()>> phase_factories; + std::unordered_map()>> step_factories; + +public: + static PhaseRegistry& getInstance(); + + template + void registerPhase(const std::string& phase_name) { + phase_factories[phase_name] = []() { + return std::make_unique(); + }; + } + + template + void registerStep(const std::string& step_name) { + step_factories[step_name] = []() { + return std::make_unique(); + }; + } + + std::unique_ptr createPhase(const std::string& phase_name); + std::unique_ptr createStep(const std::string& step_name); + + std::vector getRegisteredPhases() const; + std::vector getRegisteredSteps() const; +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/PlanetaryCore.h b/src/modules/world-generation-realist/include/PlanetaryCore.h new file mode 100644 index 0000000..54c4a53 --- /dev/null +++ b/src/modules/world-generation-realist/include/PlanetaryCore.h @@ -0,0 +1,53 @@ +#pragma once + +#include "ASerializable.h" +#include +#include + +namespace warfactory { + +class PlanetaryCore : public ASerializable { +private: + float core_mass; + float core_temperature_celsius; + float max_core_capacity; + std::unordered_map composition; + +public: + PlanetaryCore(); + PlanetaryCore(float initial_mass, float initial_temperature, float max_capacity); + + float getCoreMass() const { return core_mass; } + void setCoreMass(float mass) { core_mass = mass; } + + float getCoreTemperature() const { return core_temperature_celsius; } + void setCoreTemperature(float temperature) { core_temperature_celsius = temperature; } + + float getMaxCoreCapacity() const { return max_core_capacity; } + void setMaxCoreCapacity(float capacity) { max_core_capacity = capacity; } + + float getRemainingCapacity() const { return max_core_capacity - core_mass; } + bool hasCapacityFor(float additional_mass) const { return (core_mass + additional_mass) <= max_core_capacity; } + + const std::unordered_map& getComposition() const { return composition; } + + void addMaterial(const std::string& material_type, float quantity); + void removeMaterial(const std::string& material_type, float quantity); + float getMaterialQuantity(const std::string& material_type) const; + bool hasMaterial(const std::string& material_type) const; + + void updateMass(); + + void coolDown(float cooling_rate_per_cycle); + void heatUp(float heating_amount); + + float getCoreOverflowPressure() const; + bool shouldOverflow(float pressure_threshold) const; + + json serialize() const override; + void deserialize(const json& data) override; + + void reset(); +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/RegionManager.h b/src/modules/world-generation-realist/include/RegionManager.h new file mode 100644 index 0000000..a5c9181 --- /dev/null +++ b/src/modules/world-generation-realist/include/RegionManager.h @@ -0,0 +1,40 @@ +#pragma once + +#include "warfactory/IRegion.h" +#include +#include +#include + +namespace warfactory { + +class RegionManager { +private: + std::vector> regions; + int next_region_id; + +public: + RegionManager(); + + int createRegion(const std::string& region_type, float x, float y, float mass, float radius); + + void addRegion(std::unique_ptr region); + + void removeRegion(int region_id); + + IRegion* getRegion(int region_id); + const IRegion* getRegion(int region_id) const; + + std::vector getRegionsInRadius(float center_x, float center_y, float radius); + + std::vector getRegionsByType(const std::string& region_type); + + void updateAllRegions(float delta_time); + + void processFusions(); + + size_t getRegionCount() const { return regions.size(); } + + void clear(); +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/WorldData.h b/src/modules/world-generation-realist/include/WorldData.h new file mode 100644 index 0000000..ffc90d8 --- /dev/null +++ b/src/modules/world-generation-realist/include/WorldData.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include + +using json = nlohmann::json; + +namespace warfactory { + +class WorldData { +private: + json world_state; + std::unordered_map phase_completed; + std::unordered_map step_completed; + +public: + WorldData() = default; + + void setPhaseData(const std::string& phase_name, const json& data); + json getPhaseData(const std::string& phase_name) const; + bool hasPhaseData(const std::string& phase_name) const; + + void markPhaseComplete(const std::string& phase_name); + bool isPhaseComplete(const std::string& phase_name) const; + + void markStepComplete(const std::string& step_name); + bool isStepComplete(const std::string& step_name) const; + + json& getWorldState() { return world_state; } + const json& getWorldState() const { return world_state; } + + json exportState() const; + void importState(const json& state); +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/WorldGenerationOrchestrator.h b/src/modules/world-generation-realist/include/WorldGenerationOrchestrator.h new file mode 100644 index 0000000..ea17179 --- /dev/null +++ b/src/modules/world-generation-realist/include/WorldGenerationOrchestrator.h @@ -0,0 +1,51 @@ +#pragma once + +#include "IWorldGenerationPhase.h" +#include "WorldData.h" +#include "warfactory/IDataNode.h" +#include +#include + +namespace warfactory { + +class WorldGenerationOrchestrator { +private: + std::vector> phases; + WorldData world_data; + + size_t current_phase_index; + bool generation_complete; + +public: + WorldGenerationOrchestrator(); + ~WorldGenerationOrchestrator() = default; + + void loadConfiguration(const IDataNode& config); + + bool executeNextPhase(const IDataNode& config); + + bool executeAllPhases(const IDataNode& config); + + float getOverallProgress() const; + + bool isGenerationComplete() const { return generation_complete; } + + const WorldData& getWorldData() const { return world_data; } + + size_t getCurrentPhaseIndex() const { return current_phase_index; } + + size_t getTotalPhases() const { return phases.size(); } + + std::string getCurrentPhaseName() const; + + void reset(); + +private: + void buildPhasesFromConfig(const IDataNode& config); + + std::unique_ptr createStepFromConfig(const IDataNode& step_config); + + std::unique_ptr createPhaseFromConfig(const IDataNode& phase_config); +}; + +} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation/include/IWorldGenerationPhase.h b/src/modules/world-generation/include/IWorldGenerationPhase.h new file mode 100644 index 0000000..54aeadf --- /dev/null +++ b/src/modules/world-generation/include/IWorldGenerationPhase.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include +#include "warfactory/IDataNode.h" + +class WorldData; +class IWorldGenerationStep; + +class IWorldGenerationPhase { +public: + virtual ~IWorldGenerationPhase() = default; + + virtual std::string getPhaseName() const = 0; + + virtual std::vector> getSteps() const = 0; + + virtual bool execute(WorldData& world, const IDataNode& config) = 0; + + virtual float getProgress() const = 0; + + virtual bool isComplete() const = 0; + + virtual void reset() = 0; + + virtual std::string getPhaseDescription() const = 0; + + virtual int getPhaseNumber() const = 0; +}; \ No newline at end of file diff --git a/src/modules/world-generation/include/IWorldGenerationStep.h b/src/modules/world-generation/include/IWorldGenerationStep.h new file mode 100644 index 0000000..120cb95 --- /dev/null +++ b/src/modules/world-generation/include/IWorldGenerationStep.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include "warfactory/IDataNode.h" + +class WorldData; + +class IWorldGenerationStep { +public: + virtual ~IWorldGenerationStep() = default; + + virtual std::string getStepName() const = 0; + + virtual bool execute(WorldData& world, const IDataNode& config) = 0; + + virtual bool canExecute(const WorldData& world) const = 0; + + virtual float getProgress() const = 0; + + virtual bool isComplete() const = 0; + + virtual void reset() = 0; + + virtual std::string getStepDescription() const = 0; + + virtual float getEstimatedDuration() const = 0; + + virtual std::vector getRequiredPreviousSteps() const = 0; + + virtual std::vector getProducedData() const = 0; +}; \ No newline at end of file diff --git a/tools/count_project_stats.py b/tools/count_project_stats.py new file mode 100644 index 0000000..6c1fb9b --- /dev/null +++ b/tools/count_project_stats.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 +""" +Project Statistics Counter +Counts lines, characters, and files in the Warfactory project +""" + +import os +import sys +from pathlib import Path +from collections import defaultdict + +def get_file_extension(file_path): + """Get file extension, handling special cases""" + if file_path.name in ['CLAUDE.md', 'README.md', 'TODO.md']: + return '.md' + return file_path.suffix.lower() + +def is_text_file(file_path): + """Determine if file is likely a text file""" + text_extensions = { + '.md', '.txt', '.json', '.cpp', '.h', '.hpp', '.c', '.cc', '.cxx', + '.py', '.js', '.ts', '.html', '.css', '.xml', '.yaml', '.yml', + '.cmake', '.sh', '.bat', '.ps1', '.toml', '.ini', '.cfg', '.conf' + } + + # Special files without extensions + special_files = {'CLAUDE.md', 'README.md', 'TODO.md', 'CMakeLists.txt', 'Makefile'} + + return (get_file_extension(file_path) in text_extensions or + file_path.name in special_files) + +def should_skip_directory(dir_path): + """Check if directory should be skipped""" + dir_name = Path(dir_path).name + + # Skip common build/temp directories + skip_dirs = { + '.git', '.vs', '.vscode', '__pycache__', 'node_modules', + 'build', 'bin', 'obj', 'Debug', 'Release', '.idea', 'external' + } + + # Skip any directory starting with build + if dir_name.startswith('build'): + return True + + # Skip any _deps directories (external dependencies) + if '_deps' in dir_name: + return True + + # Skip CMakeFiles directories + if 'CMakeFiles' in dir_name: + return True + + # Skip external libraries directory + if dir_name == 'external': + return True + + return dir_name in skip_dirs + +def count_file_stats(file_path): + """Count lines and characters in a file""" + try: + with open(file_path, 'r', encoding='utf-8', errors='ignore') as f: + content = f.read() + lines = content.count('\n') + (1 if content and not content.endswith('\n') else 0) + chars = len(content) + return lines, chars + except Exception as e: + print(f"Warning: Could not read {file_path}: {e}") + return 0, 0 + +def main(): + """Main function to count project statistics""" + # Get project root (parent of tools directory) + script_dir = Path(__file__).parent + project_root = script_dir.parent + + print(f"Analyzing project: {project_root}") + print("=" * 60) + + # Statistics tracking + total_files = 0 + total_lines = 0 + total_chars = 0 + + stats_by_extension = defaultdict(lambda: {'files': 0, 'lines': 0, 'chars': 0}) + stats_by_directory = defaultdict(lambda: {'files': 0, 'lines': 0, 'chars': 0}) + + # Walk through all files + processed_files = 0 + for root, dirs, files in os.walk(project_root): + # Skip unwanted directories + dirs[:] = [d for d in dirs if not should_skip_directory(d)] + + root_path = Path(root) + relative_root = root_path.relative_to(project_root) + + # Show progress for each directory + if files: + print(f"Processing: {relative_root}") + + for file in files: + file_path = root_path / file + + # Only process text files + if not is_text_file(file_path): + continue + + processed_files += 1 + if processed_files % 10 == 0: + print(f" Processed {processed_files} files...") + + lines, chars = count_file_stats(file_path) + + total_files += 1 + total_lines += lines + total_chars += chars + + # Track by extension + ext = get_file_extension(file_path) + if not ext: + ext = '(no extension)' + + stats_by_extension[ext]['files'] += 1 + stats_by_extension[ext]['lines'] += lines + stats_by_extension[ext]['chars'] += chars + + # Track by directory + dir_name = str(relative_root) if relative_root != Path('.') else '(root)' + stats_by_directory[dir_name]['files'] += 1 + stats_by_directory[dir_name]['lines'] += lines + stats_by_directory[dir_name]['chars'] += chars + + # Print overall statistics + print(f"📊 TOTAL PROJECT STATISTICS") + print(f"Files: {total_files:,}") + print(f"Lines: {total_lines:,}") + print(f"Characters: {total_chars:,}") + print() + + # Print statistics by file type + print("📝 BY FILE TYPE:") + print(f"{'Extension':<15} {'Files':<8} {'Lines':<12} {'Characters':<15}") + print("-" * 60) + + for ext in sorted(stats_by_extension.keys()): + stats = stats_by_extension[ext] + print(f"{ext:<15} {stats['files']:<8} {stats['lines']:<12,} {stats['chars']:<15,}") + + print() + + # Print statistics by directory (top level) + print("📁 BY DIRECTORY:") + print(f"{'Directory':<20} {'Files':<8} {'Lines':<12} {'Characters':<15}") + print("-" * 65) + + # Sort by line count (descending) + sorted_dirs = sorted(stats_by_directory.items(), + key=lambda x: x[1]['lines'], reverse=True) + + for dir_name, stats in sorted_dirs: + if stats['files'] > 0: # Only show directories with files + display_name = dir_name[:19] + "..." if len(dir_name) > 19 else dir_name + print(f"{display_name:<20} {stats['files']:<8} {stats['lines']:<12,} {stats['chars']:<15,}") + + print() + print("🎯 Analysis complete!") + + # Calculate some fun metrics + avg_lines_per_file = total_lines / total_files if total_files > 0 else 0 + avg_chars_per_line = total_chars / total_lines if total_lines > 0 else 0 + + print(f"📈 METRICS:") + print(f"Average lines per file: {avg_lines_per_file:.1f}") + print(f"Average characters per line: {avg_chars_per_line:.1f}") + + # Estimate pages (assuming ~50 lines per page) + estimated_pages = total_lines / 50 + print(f"Estimated printed pages: {estimated_pages:.0f}") + + return 0 + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file