From 35c6417af51e919194043af65870420656f48ae3 Mon Sep 17 00:00:00 2001 From: hop311 Date: Sat, 2 Mar 2024 00:21:07 +0000 Subject: Cleaned up tech loading and added tech lists for areas --- src/openvic-simulation/dataloader/Dataloader.cpp | 9 +- src/openvic-simulation/research/Technology.cpp | 113 ++++++++++++++++------- src/openvic-simulation/research/Technology.hpp | 21 ++++- 3 files changed, 106 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index b7ccba3..9df9725 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -426,15 +426,15 @@ bool Dataloader::_load_technologies(GameManager& game_manager) { const v2script::Parser technology_file_parser = parse_defines(lookup_file(technology_file)); - if (!technology_manager.load_technology_file_areas(technology_file_parser.get_file_node())) { - Logger::error("Failed to load technology areas and folders!"); + if (!technology_manager.load_technology_file_folders_and_areas(technology_file_parser.get_file_node())) { + Logger::error("Failed to load technology folders and areas!"); ret = false; } ModifierManager& modifier_manager = game_manager.get_modifier_manager(); if (!technology_manager.generate_modifiers(modifier_manager)) { - Logger::error("Failed to generate technollogy-based modifiers!"); + Logger::error("Failed to generate technology-based modifiers!"); ret = false; } @@ -460,6 +460,9 @@ bool Dataloader::_load_technologies(GameManager& game_manager) { } technology_manager.lock_technologies(); + + ret &= technology_manager.generate_technology_lists(); + return ret; } diff --git a/src/openvic-simulation/research/Technology.cpp b/src/openvic-simulation/research/Technology.cpp index 1d209ba..00b736c 100644 --- a/src/openvic-simulation/research/Technology.cpp +++ b/src/openvic-simulation/research/Technology.cpp @@ -76,41 +76,71 @@ bool TechnologyManager::add_technology_school(std::string_view identifier, Modif return technology_schools.add_item({ identifier, std::move(values) }); } -bool TechnologyManager::load_technology_file_areas(ast::NodeCPtr root) { - return expect_dictionary_reserve_length(technology_folders, [this](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); +bool TechnologyManager::load_technology_file_folders_and_areas(ast::NodeCPtr root) { + return expect_dictionary_keys( + "folders", ONE_EXACTLY, [this](ast::NodeCPtr root_value) -> bool { + const bool ret = expect_dictionary_reserve_length( + technology_folders, + [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) { + Logger::error("Failed to add and retrieve technology folder: \"", folder_key, "\""); + return false; + } + + ret &= expect_list_reserve_length( + technology_areas, + expect_identifier( + std::bind(&TechnologyManager::add_technology_area, this, std::placeholders::_1, current_folder) + ) + )(folder_value); + + return ret; + } + )(root_value); + lock_technology_folders(); lock_technology_areas(); - } else { - return root_key == "schools"; /* Ignore schools, error otherwise */ - } - })(root); + + return ret; + }, + /* Never fail because of "schools", even if it's missing or there are duplicate entries, + * those issues will be caught by load_technology_file_schools. */ + "schools", ZERO_OR_MORE, success_callback + )(root); } -bool TechnologyManager::load_technology_file_schools(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 == "schools") { - return expect_dictionary_reserve_length(technology_schools, [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); +bool TechnologyManager::load_technology_file_schools( + ModifierManager const& modifier_manager, ast::NodeCPtr root +) { + if (!technology_folders.is_locked() || !technology_areas.is_locked()) { + Logger::error("Cannot load technology schools until technology folders and areas are locked!"); + return false; + } + return expect_dictionary_keys( + /* Never fail because of "folders", even if it's missing or there are duplicate entries, + * those issues will have been caught by load_technology_file_folders_and_areas. */ + "folders", ZERO_OR_MORE, success_callback, + "schools", ONE_EXACTLY, [this, &modifier_manager](ast::NodeCPtr root_value) -> bool { + const bool ret = expect_dictionary_reserve_length( + technology_schools, + [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 root_key == "folders"; /* Ignore folders, error otherwise */ + + return ret; } - })(root); + )(root); } bool TechnologyManager::load_technologies_file( @@ -118,7 +148,8 @@ bool TechnologyManager::load_technologies_file( ast::NodeCPtr root ) { return expect_dictionary_reserve_length(technologies, [this, &modifier_manager, &unit_manager, &building_type_manager]( - std::string_view tech_key, ast::NodeCPtr tech_value) -> bool { + std::string_view tech_key, ast::NodeCPtr tech_value + ) -> bool { ModifierValue modifiers; TechnologyArea const* area = nullptr; Date::year_t year = 0; @@ -129,7 +160,8 @@ bool TechnologyManager::load_technologies_file( Technology::building_set_t activated_buildings; ConditionalWeight ai_chance { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE }; - bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(modifiers), + bool ret = modifier_manager.expect_modifier_value_and_keys( + move_variable_callback(modifiers), "area", ONE_EXACTLY, expect_technology_area_identifier(assign_variable_callback_pointer(area)), "year", ONE_EXACTLY, expect_uint(assign_variable_callback(year)), "cost", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(cost)), @@ -164,8 +196,27 @@ bool TechnologyManager::generate_modifiers(ModifierManager& modifier_manager) co bool TechnologyManager::parse_scripts(GameManager const& game_manager) { bool ret = true; + for (Technology& technology : technologies.get_items()) { ret &= technology.parse_scripts(game_manager); } + return ret; } + +bool TechnologyManager::generate_technology_lists() { + if (!technology_folders.is_locked() || !technology_areas.is_locked() || !technologies.is_locked()) { + Logger::error("Cannot generate technology lists until technology folders, areas, and technologies are locked!"); + return false; + } + + for (TechnologyArea const& area : technology_areas.get_items()) { + const_cast(area.folder).technology_areas.push_back(&area); + } + + for (Technology const& tech : technologies.get_items()) { + const_cast(tech.area).technologies.push_back(&tech); + } + + return true; +} diff --git a/src/openvic-simulation/research/Technology.hpp b/src/openvic-simulation/research/Technology.hpp index a4287a5..aa47301 100644 --- a/src/openvic-simulation/research/Technology.hpp +++ b/src/openvic-simulation/research/Technology.hpp @@ -10,21 +10,28 @@ #include "openvic-simulation/types/OrderedContainers.hpp" namespace OpenVic { + struct TechnologyArea; + struct TechnologyFolder : HasIdentifier { friend struct TechnologyManager; private: + std::vector PROPERTY(technology_areas); + TechnologyFolder(std::string_view new_identifier); public: TechnologyFolder(TechnologyFolder&&) = default; }; + struct Technology; + struct TechnologyArea : HasIdentifier { friend struct TechnologyManager; private: TechnologyFolder const& PROPERTY(folder); + std::vector PROPERTY(technologies); TechnologyArea(std::string_view new_identifier, TechnologyFolder const& new_folder); @@ -86,14 +93,22 @@ namespace OpenVic { bool add_technology_school(std::string_view identifier, ModifierValue&& values); - bool load_technology_file_areas(ast::NodeCPtr root); // common/technology.txt - bool load_technology_file_schools(ModifierManager const& modifier_manager, ast::NodeCPtr root); // also common/technology.txt + /* Both of these functions load data from "common/technology.txt", they are separated because the schools depend + * on modifiers generated from the folder definitions and so loading must be staggered. */ + bool load_technology_file_folders_and_areas(ast::NodeCPtr root); + bool load_technology_file_schools(ModifierManager const& modifier_manager, ast::NodeCPtr root); + + /* Loaded from "technologies/.txt" files named after technology folders. */ bool load_technologies_file( ModifierManager const& modifier_manager, UnitManager const& unit_manager, BuildingTypeManager const& building_type_manager, ast::NodeCPtr root - ); // technologies/*.txt + ); + bool generate_modifiers(ModifierManager& modifier_manager) const; + /* Populates the lists of technology areas for each technology folder and technologies for each technology area. */ + bool generate_technology_lists(); + bool parse_scripts(GameManager const& game_manager); }; } \ No newline at end of file -- cgit v1.2.3-56-ga3b1