diff options
author | Hop311 <Hop3114@gmail.com> | 2023-10-13 10:16:44 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-13 10:16:44 +0200 |
commit | 32fdf7c38b2e56339a2fffa71a7a61a854759e2c (patch) | |
tree | 4ad745778dea488ad10509cf17d349c3ef0cc229 /src/openvic-simulation/economy | |
parent | bb22324da1225a0ac458c1d69893bb3bd28bd6b7 (diff) | |
parent | d95c3c9da75018e3e959e5493ebd9c520e00bf7a (diff) |
Merge pull request #50 from OpenVicProject/changes
Lots of accumulated changes
Diffstat (limited to 'src/openvic-simulation/economy')
-rw-r--r-- | src/openvic-simulation/economy/Building.cpp | 292 | ||||
-rw-r--r-- | src/openvic-simulation/economy/Building.hpp | 174 | ||||
-rw-r--r-- | src/openvic-simulation/economy/EconomyManager.hpp | 26 | ||||
-rw-r--r-- | src/openvic-simulation/economy/Good.hpp | 4 | ||||
-rw-r--r-- | src/openvic-simulation/economy/ProductionType.cpp | 84 | ||||
-rw-r--r-- | src/openvic-simulation/economy/ProductionType.hpp | 10 |
6 files changed, 539 insertions, 51 deletions
diff --git a/src/openvic-simulation/economy/Building.cpp b/src/openvic-simulation/economy/Building.cpp new file mode 100644 index 0000000..23bd04c --- /dev/null +++ b/src/openvic-simulation/economy/Building.cpp @@ -0,0 +1,292 @@ +#include "Building.hpp" + +#include "openvic-simulation/map/Province.hpp" //imported here so the hpp doesn't get circular imports + +using namespace OpenVic; +using namespace OpenVic::NodeTools; + +Building::Building(std::string_view identifier, BuildingType const& type, ARGS) : HasIdentifier { identifier }, ModifierValue { std::move(modifiers) }, type { type }, + on_completion { on_completion }, completion_size { completion_size }, max_level { max_level }, goods_cost { goods_cost }, cost { cost }, build_time { build_time }, + visibility { visibility }, on_map { on_map }, default_enabled { default_enabled }, production_type { production_type }, pop_build_factory { pop_build_factory }, + strategic_factory { strategic_factory }, advanced_factory { advanced_factory }, fort_level { fort_level }, naval_capacity { naval_capacity }, + colonial_points { colonial_points }, in_province { in_province }, one_per_state { one_per_state }, colonial_range { colonial_range }, + infrastructure { infrastructure }, movement_cost { movement_cost }, local_ship_build { local_ship_build }, spawn_railway_track { spawn_railway_track }, + sail { sail }, steam { steam }, capital { capital }, port { port } {} + +BuildingType const& Building::get_type() const { + return type; +} + +std::string_view Building::get_on_completion() const { + return on_completion; +} + +fixed_point_t Building::get_completion_size() const { + return completion_size; +} + +Building::level_t Building::get_max_level() const { + return max_level; +} + +std::map<Good const*, fixed_point_t> const& Building::get_goods_cost() const { + return goods_cost; +} + +fixed_point_t Building::get_cost() const { + return cost; +} + +Timespan Building::get_build_time() const { + return build_time; +} + +bool Building::has_visibility() const { + return visibility; +} + +bool Building::is_on_map() const { + return on_map; +} + +bool Building::is_default_enabled() const { + return default_enabled; +} + +ProductionType const* Building::get_production_type() const { + return production_type; +} + +bool Building::is_pop_built_factory() const { + return pop_build_factory; +} + +bool Building::is_strategic_factory() const { + return strategic_factory; +} + +bool Building::is_advanced_factory() const { + return advanced_factory; +} + +Building::level_t Building::get_fort_level() const { + return fort_level; +} + +uint64_t Building::get_naval_capacity() const { + return naval_capacity; +} + +std::vector<fixed_point_t> const& Building::get_colonial_points() const { + return colonial_points; +} + +bool Building::is_in_province() const { + return in_province; +} + +bool Building::is_one_per_state() const { + return one_per_state; +} + +fixed_point_t Building::get_colonial_range() const { + return colonial_range; +} + +fixed_point_t Building::get_infrastructure() const { + return infrastructure; +} + +fixed_point_t Building::get_movement_cost() const { + return movement_cost; +} + +bool Building::spawned_railway_track() const { + return spawn_railway_track; +} + +BuildingType::BuildingType(std::string_view new_identifier) : HasIdentifier { new_identifier } {} + +BuildingInstance::BuildingInstance(Building const& building) : HasIdentifier { building.get_identifier() }, building { building } {} + +Building const& BuildingInstance::get_building() const { + return building; +} + +bool BuildingInstance::_can_expand() const { + return level < building.get_max_level(); +} + +BuildingInstance::level_t BuildingInstance::get_current_level() const { + return level; +} + +ExpansionState BuildingInstance::get_expansion_state() const { + return expansion_state; +} + +Date const& BuildingInstance::get_start_date() const { + return start; +} + +Date const& BuildingInstance::get_end_date() const { + return end; +} + +float BuildingInstance::get_expansion_progress() const { + return expansion_progress; +} + +bool BuildingInstance::expand() { + if (expansion_state == ExpansionState::CanExpand) { + expansion_state = ExpansionState::Preparing; + expansion_progress = 0.0f; + return true; + } + return false; +} + +/* REQUIREMENTS: + * MAP-71, MAP-74, MAP-77 + */ +void BuildingInstance::update_state(Date const& today) { + switch (expansion_state) { + case ExpansionState::Preparing: + start = today; + end = start + building.get_build_time(); + break; + case ExpansionState::Expanding: + expansion_progress = static_cast<double>(today - start) / static_cast<double>(end - start); + break; + default: expansion_state = _can_expand() ? ExpansionState::CanExpand : ExpansionState::CannotExpand; + } +} + +void BuildingInstance::tick(Date const& today) { + if (expansion_state == ExpansionState::Preparing) { + expansion_state = ExpansionState::Expanding; + } + if (expansion_state == ExpansionState::Expanding) { + if (end <= today) { + level++; + expansion_state = ExpansionState::CannotExpand; + } + } +} + +BuildingManager::BuildingManager() : building_types { "building types" }, buildings { "buildings" } {} + +bool BuildingManager::add_building_type(std::string_view identifier) { + if (identifier.empty()) { + Logger::error("Invalid building type identifier - empty!"); + return false; + } + return building_types.add_item({ identifier }); +} + +bool BuildingManager::add_building(std::string_view identifier, BuildingType const* type, ARGS) { + if (identifier.empty()) { + Logger::error("Invalid building identifier - empty!"); + return false; + } + if (type == nullptr) { + Logger::error("Invalid building type for ", identifier, ": null"); + return false; + } + + return buildings.add_item({ + identifier, *type, on_completion, completion_size, max_level, goods_cost, cost, build_time, visibility, on_map, default_enabled, + production_type, pop_build_factory, strategic_factory, advanced_factory, fort_level, naval_capacity, colonial_points, in_province, one_per_state, + colonial_range, infrastructure, movement_cost, local_ship_build, spawn_railway_track, sail, steam, capital, port, std::move(modifiers) + }); +} + +bool BuildingManager::load_buildings_file(GoodManager const& good_manager, ProductionTypeManager const& production_type_manager, ModifierManager const& modifier_manager, ast::NodeCPtr root) { + bool ret = expect_dictionary_reserve_length(buildings, [this](std::string_view, ast::NodeCPtr value) -> bool { + return expect_key("type", expect_identifier( + [this](std::string_view identifier) -> bool { + if (!building_types.has_identifier(identifier)) { + return building_types.add_item({ identifier }); + } + return true; + } + ))(value); + })(root); + lock_building_types(); + + ret &= expect_dictionary([this, &good_manager, &production_type_manager, &modifier_manager](std::string_view key, ast::NodeCPtr value) -> bool { + BuildingType const* type = nullptr; + ProductionType const* production_type = nullptr; + std::string_view on_completion; + fixed_point_t completion_size = 0, cost = 0, infrastructure = 0, movement_cost = 0, colonial_range = 0, local_ship_build = 0; + Building::level_t max_level = 0, fort_level = 0; + std::map<Good const*, fixed_point_t> goods_cost; + Timespan build_time; + bool visibility = false, on_map = false, default_enabled = false, pop_build_factory = false, strategic_factory = false, advanced_factory = false; + bool in_province = false, one_per_state = false, spawn_railway_track = false, sail = false, steam = false, capital = false, port = false; + uint64_t naval_capacity = 0; + std::vector<fixed_point_t> colonial_points; + ModifierValue modifiers; + + bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(modifiers), + "type", ONE_EXACTLY, expect_identifier(expect_building_type_identifier(assign_variable_callback_pointer(type))), + "on_completion", ZERO_OR_ONE, expect_identifier(assign_variable_callback(on_completion)), + "completion_size", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(completion_size)), + "max_level", ONE_EXACTLY, expect_uint(assign_variable_callback(max_level)), + "goods_cost", ONE_EXACTLY, good_manager.expect_good_decimal_map(move_variable_callback(goods_cost)), + "cost", ZERO_OR_MORE, expect_fixed_point(assign_variable_callback(cost)), + "time", ONE_EXACTLY, expect_days(assign_variable_callback(build_time)), + "visibility", ONE_EXACTLY, expect_bool(assign_variable_callback(visibility)), + "onmap", ONE_EXACTLY, expect_bool(assign_variable_callback(on_map)), + "default_enabled", ZERO_OR_ONE, expect_bool(assign_variable_callback(default_enabled)), + "production_type", ZERO_OR_ONE, expect_identifier(production_type_manager.expect_production_type_identifier(assign_variable_callback_pointer(production_type))), + "pop_build_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(pop_build_factory)), + "strategic_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(strategic_factory)), + "advanced_factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(advanced_factory)), + "fort_level", ZERO_OR_ONE, expect_uint(assign_variable_callback(fort_level)), + "naval_capacity", ZERO_OR_ONE, expect_uint(assign_variable_callback(naval_capacity)), + "colonial_points", ZERO_OR_ONE, expect_list(expect_fixed_point([&colonial_points](fixed_point_t points) -> bool { + colonial_points.push_back(points); + return true; + })), + "province", ZERO_OR_ONE, expect_bool(assign_variable_callback(in_province)), + "one_per_state", ZERO_OR_ONE, expect_bool(assign_variable_callback(one_per_state)), + "colonial_range", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(colonial_range)), + "infrastructure", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(infrastructure)), + "movement_cost", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(movement_cost)), + "local_ship_build", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(local_ship_build)), + "spawn_railway_track", ZERO_OR_ONE, expect_bool(assign_variable_callback(spawn_railway_track)), + "sail", ZERO_OR_ONE, expect_bool(assign_variable_callback(sail)), + "steam", ZERO_OR_ONE, expect_bool(assign_variable_callback(steam)), + "capital", ZERO_OR_ONE, expect_bool(assign_variable_callback(capital)), + "port", ZERO_OR_ONE, expect_bool(assign_variable_callback(port)) + )(value); + + ret &= add_building( + key, type, on_completion, completion_size, max_level, goods_cost, cost, build_time, visibility, on_map, default_enabled, + production_type, pop_build_factory, strategic_factory, advanced_factory, fort_level, naval_capacity, colonial_points, in_province, + one_per_state, colonial_range, infrastructure, movement_cost, local_ship_build, spawn_railway_track, sail, steam, capital, port, std::move(modifiers) + ); + + return ret; + })(root); + lock_buildings(); + + return ret; +} + +bool BuildingManager::generate_province_buildings(Province& province) const { + province.reset_buildings(); + if (!building_types.is_locked()) { + Logger::error("Cannot generate buildings until building types are locked!"); + return false; + } + bool ret = true; + if (!province.get_water()) { + for (Building const& building : buildings.get_items()) { + ret &= province.add_building({ building }); + } + } + province.lock_buildings(); + return ret; +} diff --git a/src/openvic-simulation/economy/Building.hpp b/src/openvic-simulation/economy/Building.hpp new file mode 100644 index 0000000..3d1e24b --- /dev/null +++ b/src/openvic-simulation/economy/Building.hpp @@ -0,0 +1,174 @@ +#pragma once + +#include "openvic-simulation/types/Date.hpp" +#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/economy/Good.hpp" +#include "openvic-simulation/economy/ProductionType.hpp" +#include "openvic-simulation/Modifier.hpp" + +#define ARGS std::string_view on_completion, fixed_point_t completion_size, level_t max_level, \ + std::map<Good const*, fixed_point_t> goods_cost, fixed_point_t cost, Timespan build_time, bool visibility, bool on_map, bool default_enabled, \ + ProductionType const* production_type, bool pop_build_factory, bool strategic_factory, bool advanced_factory, level_t fort_level, \ + uint64_t naval_capacity, std::vector<fixed_point_t> colonial_points, bool in_province, bool one_per_state, fixed_point_t colonial_range, \ + fixed_point_t infrastructure, fixed_point_t movement_cost, fixed_point_t local_ship_build, bool spawn_railway_track, bool sail, bool steam, \ + bool capital, bool port, ModifierValue&& modifiers + +namespace OpenVic { + + struct BuildingManager; + struct BuildingType; + + /* REQUIREMENTS: + * MAP-11, MAP-72, MAP-73 + * MAP-12, MAP-75, MAP-76 + * MAP-13, MAP-78, MAP-79 + */ + struct Building : HasIdentifier, ModifierValue { + friend struct BuildingManager; + + using level_t = int16_t; + + private: + BuildingType const& type; + const std::string on_completion; //probably sound played on completion + const fixed_point_t completion_size; + const level_t max_level; + const std::map<Good const*, fixed_point_t> goods_cost; + const fixed_point_t cost; + const Timespan build_time; //time + const bool visibility; + const bool on_map; //onmap + + const bool default_enabled; + ProductionType const* production_type; + const bool pop_build_factory; + const bool strategic_factory; + const bool advanced_factory; + + const level_t fort_level; //probably the step-per-level + + const uint64_t naval_capacity; + const std::vector<fixed_point_t> colonial_points; + const bool in_province; //province + const bool one_per_state; + const fixed_point_t colonial_range; + + const fixed_point_t infrastructure; + const fixed_point_t movement_cost; + const fixed_point_t local_ship_build; + const bool spawn_railway_track; + + const bool sail; //only in clipper shipyard + const bool steam; //only in steamer shipyard + const bool capital; //only in naval base + const bool port; //only in naval base + + Building(std::string_view identifier, BuildingType const& type, ARGS); + + public: + Building(Building&&) = default; + + BuildingType const& get_type() const; + std::string_view get_on_completion() const; + fixed_point_t get_completion_size() const; + level_t get_max_level() const; + std::map<Good const*, fixed_point_t> const& get_goods_cost() const; + fixed_point_t get_cost() const; + Timespan get_build_time() const; + bool has_visibility() const; + bool is_on_map() const; + + bool is_default_enabled() const; + ProductionType const* get_production_type() const; + bool is_pop_built_factory() const; + bool is_strategic_factory() const; + bool is_advanced_factory() const; + + level_t get_fort_level() const; + + uint64_t get_naval_capacity() const; + std::vector<fixed_point_t> const& get_colonial_points() const; + bool is_in_province() const; + bool is_one_per_state() const; + fixed_point_t get_colonial_range() const; + + fixed_point_t get_infrastructure() const; + fixed_point_t get_movement_cost() const; + fixed_point_t get_local_ship_build() const; + bool spawned_railway_track() const; + }; + + struct BuildingType : HasIdentifier { + friend struct BuildingManager; + + private: + BuildingType(std::string_view new_identifier); + + public: + BuildingType(BuildingType&&) = default; + }; + + enum class ExpansionState { + CannotExpand, + CanExpand, + Preparing, + Expanding + }; + + struct BuildingInstance : HasIdentifier { //used in the actual game + friend struct BuildingManager; + using level_t = Building::level_t; + + private: + Building const& building; + + level_t level = 0; + ExpansionState expansion_state = ExpansionState::CannotExpand; + Date start, end; + float expansion_progress; + + bool _can_expand() const; + + BuildingInstance(Building const& building); + + public: + BuildingInstance(BuildingInstance&&) = default; + + Building const& get_building() const; + + level_t get_current_level() const; + ExpansionState get_expansion_state() const; + Date const& get_start_date() const; + Date const& get_end_date() const; + float get_expansion_progress() const; + + bool expand(); + void update_state(Date const& today); + void tick(Date const& today); + + }; + + struct Province; + + struct BuildingManager { + using level_t = Building::level_t; //this is getting ridiculous + + private: + IdentifierRegistry<BuildingType> building_types; + IdentifierRegistry<Building> buildings; + + public: + BuildingManager(); + + bool add_building_type(std::string_view identifier); + IDENTIFIER_REGISTRY_ACCESSORS(building_type) + + bool add_building(std::string_view identifier, BuildingType const* type, ARGS); + IDENTIFIER_REGISTRY_ACCESSORS(building) + + bool load_buildings_file(GoodManager const& good_manager, ProductionTypeManager const& production_type_manager, ModifierManager const& modifier_manager, ast::NodeCPtr root); + + bool generate_province_buildings(Province& province) const; + }; +} diff --git a/src/openvic-simulation/economy/EconomyManager.hpp b/src/openvic-simulation/economy/EconomyManager.hpp new file mode 100644 index 0000000..05dfc91 --- /dev/null +++ b/src/openvic-simulation/economy/EconomyManager.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "openvic-simulation/economy/Building.hpp" +#include "openvic-simulation/economy/Good.hpp" +#include "openvic-simulation/economy/ProductionType.hpp" + +namespace OpenVic { + struct EconomyManager { + private: + BuildingManager building_manager; + GoodManager good_manager; + ProductionTypeManager production_type_manager; + public: + REF_GETTERS(building_manager) + REF_GETTERS(good_manager) + REF_GETTERS(production_type_manager) + + inline bool load_production_types_file(PopManager const& pop_manager, ast::NodeCPtr root) { + return production_type_manager.load_production_types_file(good_manager, pop_manager, root); + } + + inline bool load_buildings_file(ModifierManager const& modifier_manager, ast::NodeCPtr root) { + return building_manager.load_buildings_file(good_manager, production_type_manager, modifier_manager, root); + } + }; +} diff --git a/src/openvic-simulation/economy/Good.hpp b/src/openvic-simulation/economy/Good.hpp index 7f020fe..1dce41f 100644 --- a/src/openvic-simulation/economy/Good.hpp +++ b/src/openvic-simulation/economy/Good.hpp @@ -66,11 +66,11 @@ namespace OpenVic { GoodManager(); bool add_good_category(std::string_view identifier); - IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(GoodCategory, good_category, good_categories) + IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(good_category, good_categories) bool add_good(std::string_view identifier, colour_t colour, GoodCategory const* category, Good::price_t base_price, bool available_from_start, bool tradeable, bool money, bool overseas_penalty); - IDENTIFIER_REGISTRY_ACCESSORS(Good, good) + IDENTIFIER_REGISTRY_ACCESSORS(good) void reset_to_defaults(); bool load_goods_file(ast::NodeCPtr root); diff --git a/src/openvic-simulation/economy/ProductionType.cpp b/src/openvic-simulation/economy/ProductionType.cpp index 2c7c431..01d45be 100644 --- a/src/openvic-simulation/economy/ProductionType.cpp +++ b/src/openvic-simulation/economy/ProductionType.cpp @@ -82,16 +82,22 @@ bool ProductionType::is_mine() const { ProductionTypeManager::ProductionTypeManager() : production_types { "production types" } {} -node_callback_t ProductionTypeManager::_expect_employed_pop(GoodManager& good_manager, PopManager& pop_manager, +node_callback_t ProductionTypeManager::_expect_employed_pop(GoodManager const& good_manager, PopManager const& pop_manager, callback_t<EmployedPop> cb) { return [this, &good_manager, &pop_manager, cb](ast::NodeCPtr node) -> bool { - std::string_view pop_type, effect; + std::string_view pop_type; + EmployedPop::effect_t effect; fixed_point_t effect_multiplier = 1, amount = 1; + using enum EmployedPop::effect_t; + static const string_map_t<EmployedPop::effect_t> effect_map = { + { "input", INPUT }, { "output", OUTPUT }, { "throughput", THROUGHPUT } + }; + bool res = expect_dictionary_keys( "poptype", ONE_EXACTLY, expect_identifier(assign_variable_callback(pop_type)), - "effect", ONE_EXACTLY, expect_identifier(assign_variable_callback(effect)), + "effect", ONE_EXACTLY, expect_identifier(expect_mapped_string(effect_map, 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); @@ -107,20 +113,11 @@ node_callback_t ProductionTypeManager::_expect_employed_pop(GoodManager& good_ma } } - 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, artisan, found_effect, effect_multiplier, amount }); + return res & cb(EmployedPop { found_pop_type, artisan, effect, effect_multiplier, amount }); }; } -node_callback_t ProductionTypeManager::_expect_employed_pop_list(GoodManager& good_manager, PopManager& pop_manager, +node_callback_t ProductionTypeManager::_expect_employed_pop_list(GoodManager const& good_manager, PopManager const& pop_manager, callback_t<std::vector<EmployedPop>> cb) { return [this, &good_manager, &pop_manager, cb](ast::NodeCPtr node) -> bool { @@ -141,7 +138,7 @@ node_callback_t ProductionTypeManager::_expect_employed_pop_list(GoodManager& go return false; \ } -bool ProductionTypeManager::add_production_type(PRODUCTION_TYPE_ARGS, GoodManager& good_manager) { +bool ProductionTypeManager::add_production_type(PRODUCTION_TYPE_ARGS, GoodManager const& good_manager) { if (identifier.empty()) { Logger::error("Invalid production type identifier - empty!"); return false; @@ -174,21 +171,22 @@ bool ProductionTypeManager::add_production_type(PRODUCTION_TYPE_ARGS, GoodManage }); } -#define PARSE_NODE(target_node) expect_dictionary_keys(ALLOW_OTHER_KEYS, \ +#define PARSE_NODE expect_dictionary_keys_and_default( \ + key_value_success_callback, \ "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_uint(workforce)), \ + "type", ZERO_OR_ONE, expect_identifier(expect_mapped_string(type_map, 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, good_manager.expect_good_identifier(assign_variable_callback_pointer(output_goods)), \ + "output_goods", ZERO_OR_ONE, expect_identifier(good_manager.expect_good_identifier(assign_variable_callback_pointer(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) { +bool ProductionTypeManager::load_production_types_file(GoodManager const& good_manager, PopManager const& pop_manager, ast::NodeCPtr root) { size_t expected_types = 0; // pass 1: find and store template identifiers @@ -196,25 +194,27 @@ bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager std::map<std::string_view, std::string_view> 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; + std::string_view template_id = ""; + bool found_template = false; + const bool ret = expect_key("template", expect_identifier(assign_variable_callback(template_id)), &found_template)(value); + if (found_template) { + if (ret) { + templates.emplace(template_id); + template_target_map.emplace(key, template_id); + } else { + Logger::error("Failed get template identifier for ", key); + return false; + } + } + return true; } )(root); // pass 2: create and populate the template map std::map<std::string_view, ast::NodeCPtr> template_node_map; - expect_dictionary( + ret &= 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); @@ -233,7 +233,7 @@ bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager EmployedPop owner; std::vector<EmployedPop> employees; - std::string_view type; + ProductionType::type_t type; Good const* output_goods = nullptr; Pop::pop_size_t workforce = 0; // 0 is a meaningless value -> unset std::map<Good const*, fixed_point_t> input_goods, efficiency; @@ -243,6 +243,11 @@ bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager bool ret = true; + using enum ProductionType::type_t; + static const string_map_t<ProductionType::type_t> type_map = { + { "factory", FACTORY }, { "rgo", RGO }, { "artisan", ARTISAN } + }; + // apply template first if (template_target_map.contains(key)) { std::string_view template_id = template_target_map[key]; @@ -254,17 +259,8 @@ bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager ret &= PARSE_NODE(node); - 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("Invalid production type for ", key, ": ", type); - ret = false; - } - ret &= add_production_type( - key, owner, employees, type_enum, workforce, input_goods, output_goods, value, + key, owner, employees, type, workforce, input_goods, output_goods, value, bonuses, efficiency, coastal, farm, mine, good_manager ); return ret; diff --git a/src/openvic-simulation/economy/ProductionType.hpp b/src/openvic-simulation/economy/ProductionType.hpp index 755eda8..420e70e 100644 --- a/src/openvic-simulation/economy/ProductionType.hpp +++ b/src/openvic-simulation/economy/ProductionType.hpp @@ -95,17 +95,17 @@ namespace OpenVic { private: IdentifierRegistry<ProductionType> production_types; - NodeTools::node_callback_t _expect_employed_pop(GoodManager& good_manager, PopManager& pop_manager, + NodeTools::node_callback_t _expect_employed_pop(GoodManager const& good_manager, PopManager const& pop_manager, NodeTools::callback_t<EmployedPop> cb); - NodeTools::node_callback_t _expect_employed_pop_list(GoodManager& good_manager, PopManager& pop_manager, + NodeTools::node_callback_t _expect_employed_pop_list(GoodManager const& good_manager, PopManager const& pop_manager, NodeTools::callback_t<std::vector<EmployedPop>> cb); public: ProductionTypeManager(); - bool add_production_type(PRODUCTION_TYPE_ARGS, GoodManager& good_manager); - IDENTIFIER_REGISTRY_ACCESSORS(ProductionType, production_type) + bool add_production_type(PRODUCTION_TYPE_ARGS, GoodManager const& good_manager); + IDENTIFIER_REGISTRY_ACCESSORS(production_type) - bool load_production_types_file(GoodManager& good_manager, PopManager& pop_manager, ast::NodeCPtr root); + bool load_production_types_file(GoodManager const& good_manager, PopManager const& pop_manager, ast::NodeCPtr root); }; }
\ No newline at end of file |