From 51583b66feb1d13b285bb2e9c05364659c854130 Mon Sep 17 00:00:00 2001 From: zaaarf Date: Tue, 3 Oct 2023 15:51:45 +0200 Subject: feat: implemented basic technology and school loading (modifier processing is still missing) --- .gitignore | 3 + src/openvic-simulation/GameManager.hpp | 10 ++ src/openvic-simulation/dataloader/Dataloader.cpp | 22 +++++ src/openvic-simulation/dataloader/Dataloader.hpp | 3 + src/openvic-simulation/misc/Modifier.cpp | 1 + src/openvic-simulation/misc/Modifier.hpp | 1 + src/openvic-simulation/tech/Technology.cpp | 121 +++++++++++++++++++++++ src/openvic-simulation/tech/Technology.hpp | 80 +++++++++++++++ 8 files changed, 241 insertions(+) create mode 100644 src/openvic-simulation/tech/Technology.cpp create mode 100644 src/openvic-simulation/tech/Technology.hpp diff --git a/.gitignore b/.gitignore index 209b874..e02298a 100644 --- a/.gitignore +++ b/.gitignore @@ -82,3 +82,6 @@ bin/* .cache compile_commands.json src/openvic-simulation/testing/test_results/results.txt + +# ccls +.ccls-cache diff --git a/src/openvic-simulation/GameManager.hpp b/src/openvic-simulation/GameManager.hpp index 5b66c8b..5cac9c5 100644 --- a/src/openvic-simulation/GameManager.hpp +++ b/src/openvic-simulation/GameManager.hpp @@ -10,6 +10,15 @@ #include "openvic-simulation/military/MilitaryManager.hpp" #include "openvic-simulation/misc/Define.hpp" #include "openvic-simulation/politics/PoliticsManager.hpp" +#include "openvic-simulation/pop/Pop.hpp" +#include "openvic-simulation/tech/Technology.hpp" +#include "utility/Getters.hpp" + +#define DECLARE_WITH_REF_GETTERS(Type, name) \ + Type name; \ +public: \ + REF_GETTERS(name) \ +private: namespace OpenVic { struct GameManager { @@ -23,6 +32,7 @@ namespace OpenVic { ModifierManager PROPERTY_REF(modifier_manager); PoliticsManager PROPERTY_REF(politics_manager); HistoryManager PROPERTY_REF(history_manager); + TechnologyManager PROPERTY_REF(technology_manager); PopManager PROPERTY_REF(pop_manager); CountryManager PROPERTY_REF(country_manager); UIManager PROPERTY_REF(ui_manager); diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index 7ffd68a..68e5b92 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -636,6 +636,18 @@ bool Dataloader::_load_units(UnitManager& unit_manager, GoodManager const& good_ return ret; } +bool Dataloader::_load_technologies(TechnologyManager& technology_manager, ModifierManager& modifier_manager) const { + static constexpr std::string_view technologies_directory = "technologies"; + bool ret = apply_to_files( + lookup_files_in_dir(technologies_directory, ".txt"), + [&technology_manager, &modifier_manager](fs::path const& file) -> bool { + return technology_manager.load_technologies_file(modifier_manager, parse_defines(file).get_file_node()); + } + ); + technology_manager.lock_technologies(); + return ret; +} + bool Dataloader::_load_history(GameManager& game_manager, bool unused_history_file_warnings) const { /* Country History */ @@ -847,6 +859,7 @@ bool Dataloader::load_defines(GameManager& game_manager) const { static const std::string national_values_file = "common/nationalvalues.txt"; static const std::string production_types_file = "common/production_types.txt"; static const std::string religion_file = "common/religion.txt"; + static const std::string technology_file = "common/technology.txt"; static const std::string leader_traits_file = "common/traits.txt"; static const std::string cb_types_file = "common/cb_types.txt"; static const std::string crime_modifiers_file = "common/crime.txt"; @@ -905,6 +918,15 @@ bool Dataloader::load_defines(GameManager& game_manager) const { Logger::error("Failed to load units!"); ret = false; } + if (!game_manager.get_technology_manager().load_technology_file(game_manager.get_modifier_manager(), + parse_defines(lookup_file(technology_file)).get_file_node())) { + Logger::error("Failed to load technology areas!"); + ret = false; + } + if (!_load_technologies(game_manager.get_technology_manager(), game_manager.get_modifier_manager())) { + Logger::error("Failed to load technologies!"); + ret = false; + } if (!_load_pop_types( game_manager.get_pop_manager(), game_manager.get_military_manager().get_unit_manager(), game_manager.get_economy_manager().get_good_manager() diff --git a/src/openvic-simulation/dataloader/Dataloader.hpp b/src/openvic-simulation/dataloader/Dataloader.hpp index 5039582..4e2f42e 100644 --- a/src/openvic-simulation/dataloader/Dataloader.hpp +++ b/src/openvic-simulation/dataloader/Dataloader.hpp @@ -15,6 +15,8 @@ namespace OpenVic { class UIManager; struct PopManager; struct UnitManager; + struct ModifierManager; + struct TechnologyManager; struct GoodManager; class Dataloader { @@ -27,6 +29,7 @@ namespace OpenVic { bool _load_interface_files(UIManager& ui_manager) const; bool _load_pop_types(PopManager& pop_manager, UnitManager const& unit_manager, GoodManager const& good_manager) const; bool _load_units(UnitManager& unit_manager, GoodManager const& good_manager) const; + bool _load_technologies(TechnologyManager& technology_manager, ModifierManager& modifier_manager) const; bool _load_map_dir(GameManager& game_manager) const; bool _load_history(GameManager& game_manager, bool unused_history_file_warnings) const; diff --git a/src/openvic-simulation/misc/Modifier.cpp b/src/openvic-simulation/misc/Modifier.cpp index 89a411c..f46718a 100644 --- a/src/openvic-simulation/misc/Modifier.cpp +++ b/src/openvic-simulation/misc/Modifier.cpp @@ -185,6 +185,7 @@ bool ModifierManager::setup_modifier_effects() { // TODO: make technology group modifiers dynamic ret &= add_modifier_effect("army_tech_research_bonus", true); + ret &= add_modifier_effect("navy_tech_research_bonus", true); ret &= add_modifier_effect("commerce_tech_research_bonus", true); ret &= add_modifier_effect("culture_tech_research_bonus", true); ret &= add_modifier_effect("industry_tech_research_bonus", true); diff --git a/src/openvic-simulation/misc/Modifier.hpp b/src/openvic-simulation/misc/Modifier.hpp index c1c532a..74f0336 100644 --- a/src/openvic-simulation/misc/Modifier.hpp +++ b/src/openvic-simulation/misc/Modifier.hpp @@ -72,6 +72,7 @@ namespace OpenVic { /* A modifier can have no icon (zero). */ const icon_t PROPERTY(icon); + protected: Modifier(std::string_view new_identifier, ModifierValue&& new_values, icon_t new_icon); public: diff --git a/src/openvic-simulation/tech/Technology.cpp b/src/openvic-simulation/tech/Technology.cpp new file mode 100644 index 0000000..71d026e --- /dev/null +++ b/src/openvic-simulation/tech/Technology.cpp @@ -0,0 +1,121 @@ +#include "Technology.hpp" + +using namespace OpenVic; +using namespace OpenVic::NodeTools; + +TechnologyFolder::TechnologyFolder(std::string_view identifier) : HasIdentifier { identifier } {} + +TechnologyArea::TechnologyArea(std::string_view identifier, TechnologyFolder const& folder) : HasIdentifier { identifier }, folder { folder } {} + +Technology::Technology(std::string_view identifier, TechnologyArea const& area, year_t year, fixed_point_t cost, bool unciv_military, ModifierValue&& values) + : Modifier { identifier, std::move(values), 0 }, area { area }, year { year }, cost { cost }, unciv_military { unciv_military } {} + +TechnologySchool::TechnologySchool(std::string_view new_identifier, ModifierValue&& new_values) + : Modifier { new_identifier, std::move(new_values), 0 } {} //TODO: school icon + +TechnologyManager::TechnologyManager() : technology_folders { "technology folders" }, technology_areas { "technology areas" }, + technologies { "technologies" }, technology_schools { "technology schools" } {} + +bool TechnologyManager::add_technology_folder(std::string_view identifier) { + if (identifier.empty()) { + Logger::error("Invalid technology folder identifier - empty!"); + return false; + } + + return technology_folders.add_item({ identifier }); +} + +bool TechnologyManager::add_technology_area(std::string_view identifier, TechnologyFolder const* folder) { + if (identifier.empty()) { + Logger::error("Invalid technology area identifier - empty!"); + return false; + } + + if (folder == nullptr) { + Logger::error("Null folder for technology area \"", identifier, "\"!"); + return false; + } + + return technology_areas.add_item({ identifier, *folder }); +} + +bool TechnologyManager::add_technology(std::string_view identifier, TechnologyArea const* area, Technology::year_t year, fixed_point_t cost, bool unciv_military, ModifierValue&& values) { + if (identifier.empty()) { + Logger::error("Invalid technology identifier - empty!"); + return false; + } + + if (area == nullptr) { + Logger::error("Null area for technology \"", identifier, "\"!"); + return false; + } + + return technologies.add_item({ identifier, *area, year, cost, unciv_military, std::move(values) }); +} + +bool TechnologyManager::add_technology_school(std::string_view identifier, ModifierValue&& values) { + if (identifier.empty()) { + Logger::error("Invalid modifier effect identifier - empty!"); + return false; + } + + return technology_schools.add_item({ identifier, std::move(values) }); +} + +bool TechnologyManager::load_technology_file(ModifierManager const& modifier_manager, ast::NodeCPtr root) { + return expect_dictionary([this, &modifier_manager](std::string_view root_key, ast::NodeCPtr root_value) -> bool { + if (root_key == "folders") { + return expect_dictionary([this](std::string_view folder_key, ast::NodeCPtr folder_value) -> bool { + bool ret = add_technology_folder(folder_key); + TechnologyFolder const* current_folder = get_technology_folder_by_identifier(folder_key); + if (current_folder == nullptr) + return false; + ret &= expect_list(expect_identifier([this, current_folder](std::string_view area) -> bool { + return add_technology_area(area, current_folder); + }))(folder_value); + return ret; + })(root_value); + lock_technology_folders(); + lock_technology_areas(); + } else if (root_key == "schools") { + return expect_dictionary([this, &modifier_manager](std::string_view school_key, ast::NodeCPtr school_value) -> bool { + ModifierValue modifiers; + bool ret = modifier_manager.expect_modifier_value(move_variable_callback(modifiers))(school_value); + ret &= add_technology_school(school_key, std::move(modifiers)); + return ret; + })(root_value); + lock_technology_schools(); + } else return false; + })(root); +} + +bool TechnologyManager::load_technologies_file(ModifierManager const& modifier_manager, ast::NodeCPtr root) { + size_t expected_technologies = 0; + bool ret = expect_dictionary_reserve_length(technologies, [this, &expected_technologies](std::string_view key, ast::NodeCPtr value) -> bool { + return expect_length(add_variable_callback(expected_technologies))(value); + })(root); + technologies.reserve(technologies.size() + expected_technologies); + + ret &= expect_dictionary([this, &modifier_manager](std::string_view tech_key, ast::NodeCPtr tech_value) -> bool { + ModifierValue modifiers; + std::string_view area_identifier; + Technology::year_t year; + fixed_point_t cost; + bool unciv_military = false; + + bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(modifiers), + "area", ONE_EXACTLY, expect_identifier(assign_variable_callback(area_identifier)), + "year", ONE_EXACTLY, expect_uint(assign_variable_callback(year)), + "cost", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(cost)), + "unciv_military", ZERO_OR_ONE, expect_bool(assign_variable_callback(unciv_military)), + "ai_chance", ONE_EXACTLY, expect_dictionary([this](std::string_view school_key, ast::NodeCPtr school_value) -> bool { return true; }) + )(tech_value); + + TechnologyArea const* area = get_technology_area_by_identifier(area_identifier); + + ret &= add_technology(tech_key, area, year, cost, unciv_military, std::move(modifiers)); + return ret; + })(root); + + return ret; +} \ No newline at end of file diff --git a/src/openvic-simulation/tech/Technology.hpp b/src/openvic-simulation/tech/Technology.hpp new file mode 100644 index 0000000..e6ce2fa --- /dev/null +++ b/src/openvic-simulation/tech/Technology.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include "misc/Modifier.hpp" +#include "types/Date.hpp" +#include "types/IdentifierRegistry.hpp" +#include "types/fixed_point/FixedPoint.hpp" + +namespace OpenVic { + struct TechnologyFolder : HasIdentifier { + friend struct TechnologyManager; + + private: + TechnologyFolder(std::string_view identifier); + + public: + TechnologyFolder(TechnologyFolder&&) = default; + }; + + struct TechnologyArea : HasIdentifier { + friend struct TechnologyManager; + + private: + TechnologyFolder const& PROPERTY(folder); + + TechnologyArea(std::string_view identifier, TechnologyFolder const& folder); + + public: + TechnologyArea(TechnologyArea&&) = default; + }; + + struct Technology : Modifier { + friend struct TechnologyManager; + using year_t = Date::year_t; + + private: + TechnologyArea const& PROPERTY(area); + const year_t PROPERTY(year); + const fixed_point_t PROPERTY(cost); + const bool PROPERTY(unciv_military); + + //TODO: implement rules/modifiers and ai_chance + + Technology(std::string_view identifier, TechnologyArea const& area, year_t year, fixed_point_t cost, bool unciv_military, ModifierValue&& values); + + public: + Technology(Technology&&) = default; + }; + + struct TechnologySchool : Modifier { + friend struct TechnologyManager; + + private: + TechnologySchool(std::string_view new_identifier, ModifierValue&& new_values); + }; + + struct TechnologyManager { + IdentifierRegistry technology_folders; + IdentifierRegistry technology_areas; + IdentifierRegistry technologies; + IdentifierRegistry technology_schools; + + public: + TechnologyManager(); + + bool add_technology_folder(std::string_view identifier); + IDENTIFIER_REGISTRY_ACCESSORS(technology_folder) + + bool add_technology_area(std::string_view identifier, TechnologyFolder const* folder); + IDENTIFIER_REGISTRY_ACCESSORS(technology_area) + + bool add_technology(std::string_view identifier, TechnologyArea const* area, Technology::year_t year, fixed_point_t cost, bool unciv_military, ModifierValue&& values); + IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(technology, technologies) + + bool add_technology_school(std::string_view identifier, ModifierValue&& values); //, Modifier::icon_t icon); + IDENTIFIER_REGISTRY_ACCESSORS(technology_school); + + bool load_technology_file(ModifierManager const& modifier_manager, ast::NodeCPtr root); // common/technology.txt + bool load_technologies_file(ModifierManager const& modifier_manager, ast::NodeCPtr root); // technologies/*.txt + }; +} \ No newline at end of file -- cgit v1.2.3-56-ga3b1