From e27ed35e265f4cb5c9a5a2864364391eaea3e32d Mon Sep 17 00:00:00 2001 From: zaaarf Date: Sat, 23 Sep 2023 22:36:56 +0200 Subject: feat: implemented ProductionType, implemented (broken) loading for it --- src/openvic-simulation/GameManager.cpp | 10 +- src/openvic-simulation/GameManager.hpp | 4 + src/openvic-simulation/dataloader/Dataloader.cpp | 7 + src/openvic-simulation/economy/ProductionType.cpp | 223 ++++++++++++++++++++++ src/openvic-simulation/economy/ProductionType.hpp | 111 +++++++++++ 5 files changed, 353 insertions(+), 2 deletions(-) create mode 100644 src/openvic-simulation/economy/ProductionType.cpp create mode 100644 src/openvic-simulation/economy/ProductionType.hpp (limited to 'src/openvic-simulation') diff --git a/src/openvic-simulation/GameManager.cpp b/src/openvic-simulation/GameManager.cpp index e314593..249808d 100644 --- a/src/openvic-simulation/GameManager.cpp +++ b/src/openvic-simulation/GameManager.cpp @@ -1,7 +1,5 @@ #include "GameManager.hpp" -#include "openvic-simulation/utility/Logger.hpp" - using namespace OpenVic; GameManager::GameManager(state_updated_func_t state_updated_callback) @@ -56,6 +54,14 @@ IssueManager const& GameManager::get_issue_manager() const { return issue_manager; } +ProductionTypeManager& GameManager::get_production_type_manager() { + return production_type_manager; +} + +ProductionTypeManager const& GameManager::get_production_type_manager() const { + return production_type_manager; +} + UnitManager& GameManager::get_unit_manager() { return unit_manager; } diff --git a/src/openvic-simulation/GameManager.hpp b/src/openvic-simulation/GameManager.hpp index 9d0c6cd..eb73331 100644 --- a/src/openvic-simulation/GameManager.hpp +++ b/src/openvic-simulation/GameManager.hpp @@ -9,6 +9,7 @@ #include "openvic-simulation/economy/Good.hpp" #include "openvic-simulation/map/Map.hpp" #include "openvic-simulation/units/Unit.hpp" +#include "openvic-simulation/economy/ProductionType.hpp" namespace OpenVic { struct GameManager { @@ -21,6 +22,7 @@ namespace OpenVic { PopManager pop_manager; IdeologyManager ideology_manager; IssueManager issue_manager; + ProductionTypeManager production_type_manager; UnitManager unit_manager; GameAdvancementHook clock; @@ -48,6 +50,8 @@ namespace OpenVic { IdeologyManager const& get_ideology_manager() const; IssueManager& get_issue_manager(); IssueManager const& get_issue_manager() const; + ProductionTypeManager& get_production_type_manager(); + ProductionTypeManager const& get_production_type_manager() const; UnitManager& get_unit_manager(); UnitManager const& get_unit_manager() const; GameAdvancementHook& get_clock(); diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index 4ff190f..6396967 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -266,6 +266,7 @@ bool Dataloader::load_defines(GameManager& game_manager) const { static const fs::path religion_file = "common/religion.txt"; static const fs::path ideology_file = "common/ideologies.txt"; static const fs::path issues_file = "common/issues.txt"; + static const fs::path production_types_file = "common/production_types.txt"; static const fs::path map_directory = "map"; static const fs::path units_directory = "units"; @@ -299,6 +300,12 @@ bool Dataloader::load_defines(GameManager& game_manager) const { Logger::error("Failed to load issues!"); ret = false; } + if (!game_manager.get_production_type_manager().load_production_types_file( + game_manager.get_good_manager(), game_manager.get_pop_manager(), + _parse_defines(lookup_file(production_types_file)).get_file_node())) { + Logger::error("Failed to load production types!"); + ret = false; + } if (!_load_units(game_manager, units_directory)) { Logger::error("Failed to load units!"); ret = false; diff --git a/src/openvic-simulation/economy/ProductionType.cpp b/src/openvic-simulation/economy/ProductionType.cpp new file mode 100644 index 0000000..c5e131d --- /dev/null +++ b/src/openvic-simulation/economy/ProductionType.cpp @@ -0,0 +1,223 @@ +#include "ProductionType.hpp" + +using namespace OpenVic; +using namespace OpenVic::NodeTools; + +EmployedPop::EmployedPop(const PopType* pop_type, effect_t effect, fixed_point_t effect_multiplier, fixed_point_t amount) + : pop_type { pop_type }, effect { effect }, effect_multiplier { effect_multiplier }, amount { amount } {} + +const PopType* EmployedPop::get_pop_type() const { + return pop_type; +} + +EmployedPop::effect_t EmployedPop::get_effect() const { + return effect; +} + +fixed_point_t EmployedPop::get_effect_multiplier() const { + return effect_multiplier; +} + +fixed_point_t EmployedPop::get_amount() const { + return amount; +} + +ProductionType::ProductionType(ARGS(type_t, const Good*)) : HasIdentifier { identifier }, owner { owner }, + employees { employees }, type { type }, workforce { workforce }, input_goods { input_goods }, output_goods { output_goods }, + value { value }, bonuses { bonuses }, efficiency { efficiency }, coastal { coastal }, farm { farm }, mine { mine } {} + +EmployedPop const& ProductionType::get_owner() const { + return owner; +} + +std::vector const& ProductionType::get_employees() const { + return employees; +} + +ProductionType::type_t ProductionType::get_type() const { + return type; +} + +uint32_t ProductionType::get_workforce() const { + return workforce; +} + +std::map const& ProductionType::get_input_goods() { + return input_goods; +} + +const Good* ProductionType::get_output_goods() const { + return output_goods; +} + +fixed_point_t ProductionType::get_value() const { + return value; +} + +std::vector const& ProductionType::get_bonuses() { + return bonuses; +} + +std::map const& ProductionType::get_efficiency() { + return efficiency; +} + +bool ProductionType::is_coastal() const { + return coastal; +} + +bool ProductionType::is_farm() const { + return farm; +} + +bool ProductionType::is_mine() const { + return mine; +} + +ProductionTypeManager::ProductionTypeManager() : production_types { "production types" } {} + +node_callback_t ProductionTypeManager::_expect_employed_pop(GoodManager& good_manager, PopManager& pop_manager, + callback_t cb) { + + return [this, &good_manager, &pop_manager, &cb](ast::NodeCPtr node) -> bool { + std::string_view pop_type, effect; + fixed_point_t effect_multiplier = 1, amount = 1; + + bool res = expect_dictionary_keys( + "pop_type", ONE_EXACTLY, expect_identifier(assign_variable_callback(pop_type)), + "effect", ONE_EXACTLY, expect_identifier(assign_variable_callback(effect)), + "effect_multiplier", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(effect_multiplier)), + "amount", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(amount)) + )(node); + + const PopType* found_pop_type = pop_manager.get_pop_type_by_identifier(pop_type); + if (found_pop_type == nullptr) { + Logger::error("Found invalid pop type ", pop_type, " while parsing production types!"); + return false; + } + + EmployedPop::effect_t found_effect; + if (effect == "input") found_effect = EmployedPop::effect_t::INPUT; + else if (effect == "output") found_effect = EmployedPop::effect_t::OUTPUT; + else if (effect == "throughput") found_effect = EmployedPop::effect_t::THROUGHPUT; + else { + Logger::error("Found invalid effect ", effect, " while parsing production types!"); + return false; + } + + return res & cb(EmployedPop { found_pop_type, found_effect, effect_multiplier, amount }); + }; +} + +node_callback_t ProductionTypeManager::_expect_employed_pop_list(GoodManager& good_manager, PopManager& pop_manager, + callback_t> cb) { + + return [this, &good_manager, &pop_manager, &cb](ast::NodeCPtr node) -> bool { + std::vector employed_pops; + bool res = expect_list([this, &good_manager, &pop_manager, &employed_pops](ast::NodeCPtr node) -> bool { + EmployedPop* owner = nullptr; + bool res_partial = _expect_employed_pop(good_manager, pop_manager, assign_variable_callback(*owner))(node); + if (owner != nullptr) + employed_pops.push_back(*owner); + return res_partial; + })(node); + return res & cb(employed_pops); + }; +} + +bool ProductionTypeManager::add_production_type(ARGS(std::string_view, std::string_view), GoodManager& good_manager) { + if (identifier.empty()) { + Logger::error("Invalid production type identifier - empty!"); + return false; + } + + ProductionType::type_t type_enum; + if (type == "factory") type_enum = ProductionType::type_t::FACTORY; + else if (type == "rgo") type_enum = ProductionType::type_t::RGO; + else if (type == "artisan") type_enum = ProductionType::type_t::ARTISAN; + else { + Logger::error("Bad type ", type, " for production type ", identifier, "!"); + return false; + } + + const Good* output = good_manager.get_good_by_identifier(output_goods); + if (output == nullptr) { + Logger::error("Invalid output for production type ", output_goods, "!"); + return false; + } + + return production_types.add_item({ + identifier, owner, employees, type_enum, workforce, input_goods, + output, value, bonuses, efficiency, coastal, farm, mine + }); +} + +bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager, PopManager& pop_manager, ast::NodeCPtr root) { + size_t expected_types = 0; + + //pass 1: find and store template identifiers + std::set templates; + bool ret = expect_dictionary([this, &expected_types, &templates](std::string_view key, ast::NodeCPtr value) -> bool { + std::string_view template_id = ""; + bool ret = expect_dictionary_keys(ALLOW_OTHER_KEYS, + "template", ZERO_OR_ONE, expect_identifier(assign_variable_callback(template_id)) + )(value); + + if (!template_id.empty()) + templates.emplace(template_id); + else expected_types++; + + return ret; + })(root); + + //pass 2: create and populate the template map + std::map template_map; + expect_dictionary([this, &templates, &template_map](std::string_view key, ast::NodeCPtr value) -> bool { + if (templates.contains(key)) + template_map.emplace(key, value); + return true; + })(root); + + //pass 3: actually load production types + production_types.reserve(production_types.size() + expected_types); + ret &= expect_dictionary( + [this, &good_manager, &pop_manager, &template_map](std::string_view key, ast::NodeCPtr node) -> bool { + EmployedPop* owner; + std::vector employees; + std::string_view type; + uint32_t workforce; + std::map input_goods; + std::string_view output_goods; + fixed_point_t value; + std::vector bonuses; + std::map efficiency; + bool coastal = false; //is_coastal + bool farm = false; + bool mine = false; + + return expect_dictionary_keys(ALLOW_OTHER_KEYS, + "owner", ONE_EXACTLY, _expect_employed_pop( + good_manager, pop_manager, move_variable_callback(*owner)), + "employees", ONE_EXACTLY, _expect_employed_pop_list( + good_manager, pop_manager, move_variable_callback(employees)), + "type", ONE_EXACTLY, expect_identifier(assign_variable_callback(type)), + "workforce", ONE_EXACTLY, expect_uint(assign_variable_callback(workforce)), + "input_goods", ZERO_OR_ONE, good_manager.expect_good_decimal_map(assign_variable_callback(input_goods)), + "output_goods_id", ONE_EXACTLY, expect_identifier(assign_variable_callback(output_goods)), + "value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(value)), + //"bonus", ONE_OR_MORE, TODO + "efficiency", ZERO_OR_ONE, good_manager.expect_good_decimal_map(assign_variable_callback(efficiency)), + "is_coastal", ZERO_OR_ONE, expect_bool(assign_variable_callback(coastal)), + "farm", ZERO_OR_ONE, expect_bool(assign_variable_callback(farm)), + "mine", ZERO_OR_ONE, expect_bool(assign_variable_callback(mine)) + )(node) & add_production_type( + key, *owner, employees, type, workforce, input_goods, output_goods, value, + bonuses, efficiency, coastal, farm, mine, good_manager + ); + } + )(root); + + production_types.lock(); + + return ret; +} \ No newline at end of file diff --git a/src/openvic-simulation/economy/ProductionType.hpp b/src/openvic-simulation/economy/ProductionType.hpp new file mode 100644 index 0000000..abe70ce --- /dev/null +++ b/src/openvic-simulation/economy/ProductionType.hpp @@ -0,0 +1,111 @@ +#pragma once + +#include +#include +#include +#include "openvic-simulation/economy/Good.hpp" +#include "openvic-simulation/pop/Pop.hpp" +#include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/dataloader/NodeTools.hpp" +#include "openvic-dataloader/v2script/AbstractSyntaxTree.hpp" + +#define ARGS(enum_type, output) std::string_view identifier, EmployedPop owner, std::vector employees, enum_type type, \ + uint32_t workforce, std::map input_goods, output output_goods, \ + fixed_point_t value, std::vector bonuses, std::map efficiency, \ + bool coastal, bool farm, bool mine + +namespace OpenVic { + struct ProductionTypeManager; + + struct EmployedPop { + friend struct ProductionTypeManager; + + private: + const PopType* pop_type; + const enum struct effect_t { + INPUT, + OUTPUT, + THROUGHPUT + } effect; + const fixed_point_t effect_multiplier; + const fixed_point_t amount; + + EmployedPop(const PopType* pop_type, effect_t effect, fixed_point_t effect_multiplier, fixed_point_t amount); + + public: + const PopType* get_pop_type() const; + effect_t get_effect() const; + fixed_point_t get_effect_multiplier() const; + fixed_point_t get_amount() const; + }; + + struct Bonus { + //TODO: trigger condition(s) + const fixed_point_t value; + }; + + struct ProductionType : HasIdentifier { + friend struct ProductionTypeManager; + + private: + const EmployedPop owner; + const std::vector employees; + const enum struct type_t { + FACTORY, + RGO, + ARTISAN + } type; + const uint32_t workforce; + + const std::map input_goods; //farms generally lack this + const Good* output_goods; + const fixed_point_t value; + const std::vector bonuses; //some + + const std::map efficiency; //some + const bool coastal; //is_coastal some(false) + + const bool farm; //some (false) + const bool mine; //some (false) + + ProductionType(ARGS(type_t, const Good*)); + + public: + ProductionType(ProductionType&&) = default; + + EmployedPop const& get_owner() const; + std::vector const& get_employees() const; + type_t get_type() const; + uint32_t get_workforce() const; + + std::map const& get_input_goods(); + const Good* get_output_goods() const; + fixed_point_t get_value() const; + std::vector const& get_bonuses(); + + std::map const& get_efficiency(); + bool is_coastal() const; + + bool is_farm() const; + bool is_mine() const; + }; + + struct ProductionTypeManager { + private: + IdentifierRegistry production_types; + + NodeTools::node_callback_t _expect_employed_pop(GoodManager& good_manager, PopManager& pop_manager, + NodeTools::callback_t cb); + NodeTools::node_callback_t _expect_employed_pop_list(GoodManager& good_manager, PopManager& pop_manager, + NodeTools::callback_t> cb); + + public: + ProductionTypeManager(); + + bool add_production_type(ARGS(std::string_view, std::string_view), GoodManager& good_manager); + IDENTIFIER_REGISTRY_ACCESSORS(ProductionType, production_type) + + bool load_production_types_file(GoodManager& good_manager, PopManager& pop_manager, ast::NodeCPtr root); + }; +} \ No newline at end of file -- cgit v1.2.3-56-ga3b1 From febd529195df8ef881d01b2ad787e54978728ff4 Mon Sep 17 00:00:00 2001 From: zaaarf Date: Sun, 24 Sep 2023 15:20:34 +0200 Subject: feat: implemented template loading, fixed compilation errors --- src/openvic-simulation/economy/ProductionType.cpp | 136 +++++++++++++--------- src/openvic-simulation/economy/ProductionType.hpp | 20 ++-- 2 files changed, 95 insertions(+), 61 deletions(-) (limited to 'src/openvic-simulation') diff --git a/src/openvic-simulation/economy/ProductionType.cpp b/src/openvic-simulation/economy/ProductionType.cpp index c5e131d..eae1311 100644 --- a/src/openvic-simulation/economy/ProductionType.cpp +++ b/src/openvic-simulation/economy/ProductionType.cpp @@ -1,24 +1,29 @@ #include "ProductionType.hpp" +#include +#include "dataloader/NodeTools.hpp" +#include "openvic-dataloader/v2script/AbstractSyntaxTree.hpp" +#include "pop/Pop.hpp" +#include "utility/Logger.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; -EmployedPop::EmployedPop(const PopType* pop_type, effect_t effect, fixed_point_t effect_multiplier, fixed_point_t amount) +EmployedPop::EmployedPop(PopType const* pop_type, effect_t effect, fixed_point_t effect_multiplier, fixed_point_t amount) : pop_type { pop_type }, effect { effect }, effect_multiplier { effect_multiplier }, amount { amount } {} -const PopType* EmployedPop::get_pop_type() const { +PopType const* EmployedPop::get_pop_type() { return pop_type; } -EmployedPop::effect_t EmployedPop::get_effect() const { +EmployedPop::effect_t EmployedPop::get_effect() { return effect; } -fixed_point_t EmployedPop::get_effect_multiplier() const { +fixed_point_t EmployedPop::get_effect_multiplier() { return effect_multiplier; } -fixed_point_t EmployedPop::get_amount() const { +fixed_point_t EmployedPop::get_amount() { return amount; } @@ -84,7 +89,7 @@ node_callback_t ProductionTypeManager::_expect_employed_pop(GoodManager& good_ma fixed_point_t effect_multiplier = 1, amount = 1; bool res = expect_dictionary_keys( - "pop_type", ONE_EXACTLY, expect_identifier(assign_variable_callback(pop_type)), + "poptype", ONE_EXACTLY, expect_identifier(assign_variable_callback(pop_type)), "effect", ONE_EXACTLY, expect_identifier(assign_variable_callback(effect)), "effect_multiplier", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(effect_multiplier)), "amount", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(amount)) @@ -142,7 +147,7 @@ bool ProductionTypeManager::add_production_type(ARGS(std::string_view, std::stri const Good* output = good_manager.get_good_by_identifier(output_goods); if (output == nullptr) { - Logger::error("Invalid output for production type ", output_goods, "!"); + Logger::error("Invalid output ", output_goods, " for production type ", identifier, "!"); return false; } @@ -152,66 +157,93 @@ bool ProductionTypeManager::add_production_type(ARGS(std::string_view, std::stri }); } +/* TODO check that these are valid and set +"owner", ONE_EXACTLY, _expect_employed_pop(good_manager, pop_manager, move_variable_callback(owner)), +"workforce", ONE_EXACTLY, expect_uint(assign_variable_callback(workforce)), +"output_goods", ONE_EXACTLY, expect_identifier(assign_variable_callback(output_goods)), +"value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(value)), +*/ + +#define PARSE_NODE(target_node) expect_dictionary_keys(ALLOW_OTHER_KEYS, \ + "owner", ZERO_OR_ONE, _expect_employed_pop(good_manager, pop_manager, move_variable_callback(owner)), \ + "employees", ZERO_OR_ONE, _expect_employed_pop_list(good_manager, pop_manager, move_variable_callback(employees)), \ + "type", ZERO_OR_ONE, expect_identifier(assign_variable_callback(type)), \ + "workforce", ZERO_OR_ONE, expect_uint(assign_variable_callback(workforce)), \ + "input_goods", ZERO_OR_ONE, good_manager.expect_good_decimal_map(move_variable_callback(input_goods)), \ + "output_goods", ZERO_OR_ONE, expect_identifier(assign_variable_callback(output_goods)), \ + "value", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(value)), \ + "efficiency", ZERO_OR_ONE, good_manager.expect_good_decimal_map(move_variable_callback(efficiency)), \ + "is_coastal", ZERO_OR_ONE, expect_bool(assign_variable_callback(coastal)), \ + "farm", ZERO_OR_ONE, expect_bool(assign_variable_callback(farm)), \ + "mine", ZERO_OR_ONE, expect_bool(assign_variable_callback(mine)) \ + )(target_node) + bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager, PopManager& pop_manager, ast::NodeCPtr root) { size_t expected_types = 0; //pass 1: find and store template identifiers std::set templates; - bool ret = expect_dictionary([this, &expected_types, &templates](std::string_view key, ast::NodeCPtr value) -> bool { - std::string_view template_id = ""; - bool ret = expect_dictionary_keys(ALLOW_OTHER_KEYS, - "template", ZERO_OR_ONE, expect_identifier(assign_variable_callback(template_id)) - )(value); - - if (!template_id.empty()) - templates.emplace(template_id); - else expected_types++; - - return ret; - })(root); + std::map template_target_map; + bool ret = expect_dictionary( + [this, &expected_types, &templates, &template_target_map](std::string_view key, ast::NodeCPtr value) -> bool { + std::string_view template_id = ""; + bool ret = expect_dictionary_keys(ALLOW_OTHER_KEYS, + "template", ZERO_OR_ONE, expect_identifier(assign_variable_callback(template_id)) + )(value); + + if (!template_id.empty()) { + templates.emplace(template_id); + template_target_map.emplace(key, template_id); + } + + expected_types++; + + return ret; + } + )(root); //pass 2: create and populate the template map - std::map template_map; - expect_dictionary([this, &templates, &template_map](std::string_view key, ast::NodeCPtr value) -> bool { - if (templates.contains(key)) - template_map.emplace(key, value); - return true; - })(root); + std::map template_node_map; + expect_dictionary( + [this, &expected_types, &templates, &template_node_map](std::string_view key, ast::NodeCPtr value) -> bool { + if (templates.contains(key)) { + template_node_map.emplace(key, value); + expected_types--; + } + return true; + } + )(root); //pass 3: actually load production types production_types.reserve(production_types.size() + expected_types); ret &= expect_dictionary( - [this, &good_manager, &pop_manager, &template_map](std::string_view key, ast::NodeCPtr node) -> bool { - EmployedPop* owner; + [this, &good_manager, &pop_manager, &template_target_map, &template_node_map](std::string_view key, ast::NodeCPtr node) -> bool { + if (template_node_map.contains(key)) + return true; + + EmployedPop owner; std::vector employees; - std::string_view type; + std::string_view type, output_goods; uint32_t workforce; - std::map input_goods; - std::string_view output_goods; + std::map input_goods, efficiency; fixed_point_t value; std::vector bonuses; - std::map efficiency; - bool coastal = false; //is_coastal - bool farm = false; - bool mine = false; - - return expect_dictionary_keys(ALLOW_OTHER_KEYS, - "owner", ONE_EXACTLY, _expect_employed_pop( - good_manager, pop_manager, move_variable_callback(*owner)), - "employees", ONE_EXACTLY, _expect_employed_pop_list( - good_manager, pop_manager, move_variable_callback(employees)), - "type", ONE_EXACTLY, expect_identifier(assign_variable_callback(type)), - "workforce", ONE_EXACTLY, expect_uint(assign_variable_callback(workforce)), - "input_goods", ZERO_OR_ONE, good_manager.expect_good_decimal_map(assign_variable_callback(input_goods)), - "output_goods_id", ONE_EXACTLY, expect_identifier(assign_variable_callback(output_goods)), - "value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(value)), - //"bonus", ONE_OR_MORE, TODO - "efficiency", ZERO_OR_ONE, good_manager.expect_good_decimal_map(assign_variable_callback(efficiency)), - "is_coastal", ZERO_OR_ONE, expect_bool(assign_variable_callback(coastal)), - "farm", ZERO_OR_ONE, expect_bool(assign_variable_callback(farm)), - "mine", ZERO_OR_ONE, expect_bool(assign_variable_callback(mine)) - )(node) & add_production_type( - key, *owner, employees, type, workforce, input_goods, output_goods, value, + bool coastal = false, farm = false, mine = false; + + bool ret = true; + + //apply template first + if (template_target_map.contains(key)) { + std::string_view template_id = template_target_map[key]; + if (template_node_map.contains(template_id)) { + ast::NodeCPtr template_node = template_node_map[template_id]; + Logger::info("Applying template ", template_id," to ", key); //TODO temp, remove once it works + ret &= PARSE_NODE(template_node); + } + } + + return ret & PARSE_NODE(node) & add_production_type( + key, owner, employees, type, workforce, input_goods, output_goods, value, bonuses, efficiency, coastal, farm, mine, good_manager ); } diff --git a/src/openvic-simulation/economy/ProductionType.hpp b/src/openvic-simulation/economy/ProductionType.hpp index abe70ce..2d0586c 100644 --- a/src/openvic-simulation/economy/ProductionType.hpp +++ b/src/openvic-simulation/economy/ProductionType.hpp @@ -22,22 +22,24 @@ namespace OpenVic { friend struct ProductionTypeManager; private: - const PopType* pop_type; - const enum struct effect_t { + PopType const* pop_type; //poptype + enum struct effect_t { INPUT, OUTPUT, THROUGHPUT } effect; - const fixed_point_t effect_multiplier; - const fixed_point_t amount; + fixed_point_t effect_multiplier; + fixed_point_t amount; - EmployedPop(const PopType* pop_type, effect_t effect, fixed_point_t effect_multiplier, fixed_point_t amount); + EmployedPop(PopType const* pop_type, effect_t effect, fixed_point_t effect_multiplier, fixed_point_t amount); public: - const PopType* get_pop_type() const; - effect_t get_effect() const; - fixed_point_t get_effect_multiplier() const; - fixed_point_t get_amount() const; + EmployedPop() = default; + + PopType const* get_pop_type(); + effect_t get_effect(); + fixed_point_t get_effect_multiplier(); + fixed_point_t get_amount(); }; struct Bonus { -- cgit v1.2.3-56-ga3b1 From eb425a600c03ca02d922a1b20a2815a57104f3cc Mon Sep 17 00:00:00 2001 From: zaaarf Date: Sun, 24 Sep 2023 19:38:54 +0200 Subject: fix: fixed segfault, added ulterior checks) --- src/openvic-simulation/economy/ProductionType.cpp | 66 +++++++++++++++-------- src/openvic-simulation/economy/ProductionType.hpp | 10 ++-- 2 files changed, 50 insertions(+), 26 deletions(-) (limited to 'src/openvic-simulation') diff --git a/src/openvic-simulation/economy/ProductionType.cpp b/src/openvic-simulation/economy/ProductionType.cpp index eae1311..4ea7967 100644 --- a/src/openvic-simulation/economy/ProductionType.cpp +++ b/src/openvic-simulation/economy/ProductionType.cpp @@ -8,13 +8,17 @@ using namespace OpenVic; using namespace OpenVic::NodeTools; -EmployedPop::EmployedPop(PopType const* pop_type, effect_t effect, fixed_point_t effect_multiplier, fixed_point_t amount) - : pop_type { pop_type }, effect { effect }, effect_multiplier { effect_multiplier }, amount { amount } {} +EmployedPop::EmployedPop(PopType const* pop_type, bool artisan, effect_t effect, fixed_point_t effect_multiplier, fixed_point_t amount) + : pop_type { pop_type }, artisan { artisan }, effect { effect }, effect_multiplier { effect_multiplier }, amount { amount } {} PopType const* EmployedPop::get_pop_type() { return pop_type; } +bool EmployedPop::is_artisan() { + return artisan; +} + EmployedPop::effect_t EmployedPop::get_effect() { return effect; } @@ -43,7 +47,7 @@ ProductionType::type_t ProductionType::get_type() const { return type; } -uint32_t ProductionType::get_workforce() const { +size_t ProductionType::get_workforce() const { return workforce; } @@ -84,7 +88,7 @@ ProductionTypeManager::ProductionTypeManager() : production_types { "production node_callback_t ProductionTypeManager::_expect_employed_pop(GoodManager& good_manager, PopManager& pop_manager, callback_t cb) { - return [this, &good_manager, &pop_manager, &cb](ast::NodeCPtr node) -> bool { + return [this, &good_manager, &pop_manager, cb](ast::NodeCPtr node) -> bool { std::string_view pop_type, effect; fixed_point_t effect_multiplier = 1, amount = 1; @@ -96,9 +100,14 @@ node_callback_t ProductionTypeManager::_expect_employed_pop(GoodManager& good_ma )(node); const PopType* found_pop_type = pop_manager.get_pop_type_by_identifier(pop_type); + bool artisan = false; if (found_pop_type == nullptr) { - Logger::error("Found invalid pop type ", pop_type, " while parsing production types!"); - return false; + if (pop_type == "artisan") { + artisan = true; + } else { + Logger::error("Found invalid pop type ", pop_type, " while parsing production types!"); + return false; + } } EmployedPop::effect_t found_effect; @@ -110,26 +119,31 @@ node_callback_t ProductionTypeManager::_expect_employed_pop(GoodManager& good_ma return false; } - return res & cb(EmployedPop { found_pop_type, found_effect, effect_multiplier, amount }); + return res & cb(EmployedPop { found_pop_type, artisan, found_effect, effect_multiplier, amount }); }; } node_callback_t ProductionTypeManager::_expect_employed_pop_list(GoodManager& good_manager, PopManager& pop_manager, callback_t> cb) { - return [this, &good_manager, &pop_manager, &cb](ast::NodeCPtr node) -> bool { + return [this, &good_manager, &pop_manager, cb](ast::NodeCPtr node) -> bool { std::vector employed_pops; bool res = expect_list([this, &good_manager, &pop_manager, &employed_pops](ast::NodeCPtr node) -> bool { - EmployedPop* owner = nullptr; - bool res_partial = _expect_employed_pop(good_manager, pop_manager, assign_variable_callback(*owner))(node); - if (owner != nullptr) - employed_pops.push_back(*owner); + EmployedPop owner; + bool res_partial = _expect_employed_pop(good_manager, pop_manager, assign_variable_callback(owner))(node); + employed_pops.push_back(owner); return res_partial; })(node); return res & cb(employed_pops); }; } +#define POPTYPE_CHECK(employed_pop) \ + if ((employed_pop.pop_type == nullptr && !employed_pop.artisan) || (employed_pop.pop_type != nullptr && employed_pop.artisan)) {\ + Logger::error("Invalid pop type parsed for owner of production type ", identifier, "!"); \ + return false; \ + } + bool ProductionTypeManager::add_production_type(ARGS(std::string_view, std::string_view), GoodManager& good_manager) { if (identifier.empty()) { Logger::error("Invalid production type identifier - empty!"); @@ -145,6 +159,22 @@ bool ProductionTypeManager::add_production_type(ARGS(std::string_view, std::stri return false; } + if (workforce == 0) { + Logger::error("Workforce for production type ", identifier, " was 0 or unset!"); + return false; + } + + if (value == 0) { + Logger::error("Value for production type ", identifier, " was 0 or unset!"); + return false; + } + + POPTYPE_CHECK(owner) + + for (int i = 0; i < employees.size(); i++) { + POPTYPE_CHECK(employees[i]) + } + const Good* output = good_manager.get_good_by_identifier(output_goods); if (output == nullptr) { Logger::error("Invalid output ", output_goods, " for production type ", identifier, "!"); @@ -157,13 +187,6 @@ bool ProductionTypeManager::add_production_type(ARGS(std::string_view, std::stri }); } -/* TODO check that these are valid and set -"owner", ONE_EXACTLY, _expect_employed_pop(good_manager, pop_manager, move_variable_callback(owner)), -"workforce", ONE_EXACTLY, expect_uint(assign_variable_callback(workforce)), -"output_goods", ONE_EXACTLY, expect_identifier(assign_variable_callback(output_goods)), -"value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(value)), -*/ - #define PARSE_NODE(target_node) expect_dictionary_keys(ALLOW_OTHER_KEYS, \ "owner", ZERO_OR_ONE, _expect_employed_pop(good_manager, pop_manager, move_variable_callback(owner)), \ "employees", ZERO_OR_ONE, _expect_employed_pop_list(good_manager, pop_manager, move_variable_callback(employees)), \ @@ -224,9 +247,9 @@ bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager EmployedPop owner; std::vector employees; std::string_view type, output_goods; - uint32_t workforce; + size_t workforce = 0; //0 is a meaningless value -> unset std::map input_goods, efficiency; - fixed_point_t value; + fixed_point_t value = 0; //0 is a meaningless value -> unset std::vector bonuses; bool coastal = false, farm = false, mine = false; @@ -237,7 +260,6 @@ bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager std::string_view template_id = template_target_map[key]; if (template_node_map.contains(template_id)) { ast::NodeCPtr template_node = template_node_map[template_id]; - Logger::info("Applying template ", template_id," to ", key); //TODO temp, remove once it works ret &= PARSE_NODE(template_node); } } diff --git a/src/openvic-simulation/economy/ProductionType.hpp b/src/openvic-simulation/economy/ProductionType.hpp index 2d0586c..1e715d8 100644 --- a/src/openvic-simulation/economy/ProductionType.hpp +++ b/src/openvic-simulation/economy/ProductionType.hpp @@ -11,7 +11,7 @@ #include "openvic-dataloader/v2script/AbstractSyntaxTree.hpp" #define ARGS(enum_type, output) std::string_view identifier, EmployedPop owner, std::vector employees, enum_type type, \ - uint32_t workforce, std::map input_goods, output output_goods, \ + size_t workforce, std::map input_goods, output output_goods, \ fixed_point_t value, std::vector bonuses, std::map efficiency, \ bool coastal, bool farm, bool mine @@ -23,6 +23,7 @@ namespace OpenVic { private: PopType const* pop_type; //poptype + bool artisan; //set by the parser if the magic "artisan" poptype is passed enum struct effect_t { INPUT, OUTPUT, @@ -31,12 +32,13 @@ namespace OpenVic { fixed_point_t effect_multiplier; fixed_point_t amount; - EmployedPop(PopType const* pop_type, effect_t effect, fixed_point_t effect_multiplier, fixed_point_t amount); + EmployedPop(PopType const* pop_type, bool artisan, effect_t effect, fixed_point_t effect_multiplier, fixed_point_t amount); public: EmployedPop() = default; PopType const* get_pop_type(); + bool is_artisan(); effect_t get_effect(); fixed_point_t get_effect_multiplier(); fixed_point_t get_amount(); @@ -58,7 +60,7 @@ namespace OpenVic { RGO, ARTISAN } type; - const uint32_t workforce; + const size_t workforce; const std::map input_goods; //farms generally lack this const Good* output_goods; @@ -79,7 +81,7 @@ namespace OpenVic { EmployedPop const& get_owner() const; std::vector const& get_employees() const; type_t get_type() const; - uint32_t get_workforce() const; + size_t get_workforce() const; std::map const& get_input_goods(); const Good* get_output_goods() const; -- cgit v1.2.3-56-ga3b1