From e50c67eb1aaa54f5fb31425f81616bea4e6b880a Mon Sep 17 00:00:00 2001 From: hop311 Date: Thu, 12 Oct 2023 20:19:00 +0100 Subject: Lots of accumulated changes --- deps/openvic-dataloader | 2 +- src/openvic-simulation/Modifier.cpp | 2 +- src/openvic-simulation/Modifier.hpp | 4 +- src/openvic-simulation/dataloader/Dataloader.cpp | 37 ++--- src/openvic-simulation/dataloader/Dataloader.hpp | 7 +- src/openvic-simulation/dataloader/NodeTools.cpp | 136 ++++++++++++------ src/openvic-simulation/dataloader/NodeTools.hpp | 151 ++++++++++++-------- src/openvic-simulation/economy/Good.hpp | 4 +- src/openvic-simulation/economy/ProductionType.cpp | 80 +++++------ src/openvic-simulation/economy/ProductionType.hpp | 6 +- src/openvic-simulation/map/Building.cpp | 12 +- src/openvic-simulation/map/Building.hpp | 6 +- src/openvic-simulation/map/Map.cpp | 5 + src/openvic-simulation/map/Map.hpp | 10 +- src/openvic-simulation/map/Province.hpp | 2 +- src/openvic-simulation/map/TerrainType.cpp | 105 ++++++-------- src/openvic-simulation/map/TerrainType.hpp | 6 +- src/openvic-simulation/politics/Government.cpp | 134 ++++++++++-------- src/openvic-simulation/politics/Government.hpp | 55 ++++---- src/openvic-simulation/politics/Ideology.hpp | 4 +- src/openvic-simulation/politics/Issue.cpp | 11 +- src/openvic-simulation/politics/Issue.hpp | 10 +- src/openvic-simulation/pop/Culture.cpp | 16 +-- src/openvic-simulation/pop/Culture.hpp | 6 +- src/openvic-simulation/pop/Pop.cpp | 36 ++--- src/openvic-simulation/pop/Pop.hpp | 2 +- src/openvic-simulation/pop/Religion.cpp | 2 +- src/openvic-simulation/pop/Religion.hpp | 4 +- src/openvic-simulation/types/Date.cpp | 13 ++ src/openvic-simulation/types/Date.hpp | 4 + .../types/IdentifierRegistry.hpp | 156 ++++++++++++--------- src/openvic-simulation/types/Vector.cpp | 4 +- src/openvic-simulation/types/Vector.hpp | 12 +- src/openvic-simulation/units/Unit.cpp | 66 +++++++-- src/openvic-simulation/units/Unit.hpp | 14 +- src/openvic-simulation/utility/Logger.hpp | 3 +- 36 files changed, 635 insertions(+), 492 deletions(-) diff --git a/deps/openvic-dataloader b/deps/openvic-dataloader index 9296141..4009e1d 160000 --- a/deps/openvic-dataloader +++ b/deps/openvic-dataloader @@ -1 +1 @@ -Subproject commit 92961412af3ae908633b4ef7b8453091448ffd4d +Subproject commit 4009e1d576ad177aff59c8fce0339963303fc6e5 diff --git a/src/openvic-simulation/Modifier.cpp b/src/openvic-simulation/Modifier.cpp index 3acfa56..5aadd79 100644 --- a/src/openvic-simulation/Modifier.cpp +++ b/src/openvic-simulation/Modifier.cpp @@ -157,7 +157,7 @@ node_callback_t ModifierManager::expect_modifier_value(callback_t modifier_callback, key_map_t&& key_map) const { return [this, modifier_callback, key_map = std::move(key_map)](ast::NodeCPtr node) mutable -> bool { bool ret = expect_modifier_value( - modifier_callback, dictionary_keys_callback(key_map, false) + modifier_callback, dictionary_keys_callback(key_map, key_value_invalid_callback) )(node); ret &= check_key_map_counts(key_map); return ret; diff --git a/src/openvic-simulation/Modifier.hpp b/src/openvic-simulation/Modifier.hpp index f88102b..0c4e636 100644 --- a/src/openvic-simulation/Modifier.hpp +++ b/src/openvic-simulation/Modifier.hpp @@ -107,10 +107,10 @@ namespace OpenVic { ModifierManager(); bool add_modifier_effect(std::string_view identifier, bool province_good); - IDENTIFIER_REGISTRY_ACCESSORS(ModifierEffect, modifier_effect) + IDENTIFIER_REGISTRY_ACCESSORS(modifier_effect) bool add_modifier(std::string_view identifier, ModifierValue&& values, Modifier::icon_t icon); - IDENTIFIER_REGISTRY_ACCESSORS(Modifier, modifier) + IDENTIFIER_REGISTRY_ACCESSORS(modifier) bool setup_modifier_effects(); diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index 70164c3..bd634ce 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -381,7 +381,10 @@ Dataloader::path_vector_t Dataloader::lookup_files_in_dir(fs::path const& path, bool Dataloader::apply_to_files_in_dir(fs::path const& path, fs::path const& extension, callback_t callback) const { bool ret = true; for (fs::path const& file : lookup_files_in_dir(path, extension)) { - ret &= callback(file); + if (!callback(file)) { + Logger::error("Callback failed for file: ", file); + ret = false; + } } return ret; } @@ -441,12 +444,6 @@ csv::Windows1252Parser Dataloader::parse_csv(fs::path const& path) { return _run_ovdl_parser(path); } -static callback_t _parse_defines_callback(node_callback_t callback) { - return [callback](fs::path const& path) -> bool { - return callback(Dataloader::parse_defines(path).get_file_node()); - }; -} - bool Dataloader::_load_pop_types(PopManager& pop_manager, fs::path const& pop_type_directory) const { const bool ret = apply_to_files_in_dir(pop_type_directory, ".txt", [&pop_manager](fs::path const& file) -> bool { @@ -457,13 +454,13 @@ bool Dataloader::_load_pop_types(PopManager& pop_manager, fs::path const& pop_ty return ret; } -bool Dataloader::_load_units(GameManager& game_manager, fs::path const& units_directory) const { +bool Dataloader::_load_units(UnitManager& unit_manager, GoodManager const& good_manager, fs::path const& units_directory) const { const bool ret = apply_to_files_in_dir(units_directory, ".txt", - [&game_manager](fs::path const& file) -> bool { - return game_manager.get_unit_manager().load_unit_file(game_manager.get_good_manager(), parse_defines(file).get_file_node()); + [&unit_manager, &good_manager](fs::path const& file) -> bool { + return unit_manager.load_unit_file(good_manager, parse_defines(file).get_file_node()); } ); - game_manager.get_unit_manager().lock_units(); + unit_manager.lock_units(); return ret; } @@ -499,15 +496,8 @@ bool Dataloader::_load_map_dir(GameManager& game_manager, fs::path const& map_di bool ret = expect_dictionary_keys( "max_provinces", ONE_EXACTLY, - expect_uint( - [&map](uint64_t val) -> bool { - if (Province::NULL_INDEX < val && val <= Province::MAX_INDEX) { - return map.set_max_provinces(val); - } - Logger::error("Invalid max province count ", val, " (out of valid range ", - Province::NULL_INDEX, " < max_provinces <= ", Province::MAX_INDEX, ")"); - return false; - } + expect_uint( + std::bind(&Map::set_max_provinces, &map, std::placeholders::_1) ), "sea_starts", ONE_EXACTLY, expect_list_reserve_length( @@ -556,7 +546,6 @@ bool Dataloader::_load_map_dir(GameManager& game_manager, fs::path const& map_di Logger::error("Failed to set water provinces!"); ret = false; } - map.lock_water_provinces(); if (!map.get_terrain_type_manager().load_terrain_types(game_manager.get_modifier_manager(), parse_defines(lookup_file(map_directory / terrain_definition)).get_file_node())) { Logger::error("Failed to load terrain types!"); @@ -648,7 +637,7 @@ bool Dataloader::load_defines(GameManager& game_manager) const { Logger::error("Failed to load map!"); ret = false; } - if (!_load_units(game_manager, units_directory)) { + if (!_load_units(game_manager.get_unit_manager(), game_manager.get_good_manager(), units_directory)) { Logger::error("Failed to load units!"); ret = false; } @@ -659,11 +648,11 @@ bool Dataloader::load_defines(GameManager& game_manager) const { bool Dataloader::load_pop_history(GameManager& game_manager, fs::path const& path) const { return apply_to_files_in_dir(path, ".txt", [&game_manager](fs::path const& file) -> bool { - return _parse_defines_callback(game_manager.get_map().expect_province_dictionary( + return game_manager.get_map().expect_province_dictionary( [&game_manager](Province& province, ast::NodeCPtr value) -> bool { return province.load_pop_list(game_manager.get_pop_manager(), value); } - ))(file); + )(parse_defines(file).get_file_node()); } ); } diff --git a/src/openvic-simulation/dataloader/Dataloader.hpp b/src/openvic-simulation/dataloader/Dataloader.hpp index 705da00..30eed6e 100644 --- a/src/openvic-simulation/dataloader/Dataloader.hpp +++ b/src/openvic-simulation/dataloader/Dataloader.hpp @@ -13,7 +13,8 @@ namespace OpenVic { struct GameManager; struct PopManager; - struct Map; + struct UnitManager; + struct GoodManager; class Dataloader { public: @@ -23,7 +24,7 @@ namespace OpenVic { path_vector_t roots; bool _load_pop_types(PopManager& pop_manager, fs::path const& pop_type_directory) const; - bool _load_units(GameManager& unit_manager, fs::path const& units_directory) const; + bool _load_units(UnitManager& unit_manager, GoodManager const& good_manager, fs::path const& units_directory) const; bool _load_map_dir(GameManager& game_manager, fs::path const& map_directory) const; public: @@ -89,5 +90,3 @@ namespace OpenVic { inline static std::unordered_map _cached_paths; }; } - - diff --git a/src/openvic-simulation/dataloader/NodeTools.cpp b/src/openvic-simulation/dataloader/NodeTools.cpp index 5ef09d1..391ffb6 100644 --- a/src/openvic-simulation/dataloader/NodeTools.cpp +++ b/src/openvic-simulation/dataloader/NodeTools.cpp @@ -19,20 +19,28 @@ static node_callback_t _expect_type(callback_t callback) { }; } -template -requires(std::derived_from) -static callback_t _abstract_string_node_callback(callback_t callback) { - return [callback](T const& node) -> bool { - return callback(node._name); +template T> +static callback_t _abstract_string_node_callback(callback_t callback, bool allow_empty) { + return [callback, allow_empty](T const& node) -> bool { + if (allow_empty) { + return callback(node._name); + } else { + if (!node._name.empty()) { + return callback(node._name); + } else { + Logger::error("Invalid string value - empty!"); + return false; + } + } }; } node_callback_t NodeTools::expect_identifier(callback_t callback) { - return _expect_type(_abstract_string_node_callback(callback)); + return _expect_type(_abstract_string_node_callback(callback, false)); } -node_callback_t NodeTools::expect_string(callback_t callback) { - return _expect_type(_abstract_string_node_callback(callback)); +node_callback_t NodeTools::expect_string(callback_t callback, bool allow_empty) { + return _expect_type(_abstract_string_node_callback(callback, allow_empty)); } node_callback_t NodeTools::expect_identifier_or_string(callback_t callback) { @@ -43,7 +51,7 @@ node_callback_t NodeTools::expect_identifier_or_string(callback_tcast_to(); } if (cast_node != nullptr) { - return _abstract_string_node_callback(callback)(*cast_node); + return _abstract_string_node_callback(callback, false)(*cast_node); } Logger::error("Invalid node type ", node->get_type(), " when expecting ", ast::IdentifierNode::get_type_static(), " or ", ast::StringNode::get_type_static()); } else { @@ -54,20 +62,20 @@ node_callback_t NodeTools::expect_identifier_or_string(callback_t callback) { - return expect_identifier( - [callback](std::string_view identifier) -> bool { - if (identifier == "yes") { - return callback(true); - } else if (identifier == "no") { - return callback(false); - } - Logger::error("Invalid bool identifier text: ", identifier); - return false; - } - ); + static const string_map_t bool_map = { + { "yes", true }, { "no", false } + }; + return expect_identifier(expect_mapped_string(bool_map, callback)); +} + +node_callback_t NodeTools::expect_int_bool(callback_t callback) { + static const string_map_t bool_map = { + { "1", true }, { "0", false } + }; + return expect_identifier(expect_mapped_string(bool_map, callback)); } -node_callback_t NodeTools::expect_int(callback_t callback) { +node_callback_t NodeTools::expect_int64(callback_t callback) { return expect_identifier( [callback](std::string_view identifier) -> bool { bool successful = false; @@ -81,7 +89,7 @@ node_callback_t NodeTools::expect_int(callback_t callback) { ); } -node_callback_t NodeTools::expect_uint(callback_t callback) { +node_callback_t NodeTools::expect_uint64(callback_t callback) { return expect_identifier( [callback](std::string_view identifier) -> bool { bool successful = false; @@ -134,10 +142,6 @@ node_callback_t NodeTools::expect_colour(callback_t callback) { }; } -node_callback_t NodeTools::expect_timespan(callback_t callback) { - return expect_int(callback); -} - node_callback_t NodeTools::expect_date(callback_t callback) { return expect_identifier( [callback](std::string_view identifier) -> bool { @@ -152,6 +156,24 @@ node_callback_t NodeTools::expect_date(callback_t callback) { ); } +node_callback_t NodeTools::expect_years(callback_t callback) { + return expect_uint([callback](Timespan::day_t val) -> bool { + return callback(Timespan::fromYears(val)); + }); +} + +node_callback_t NodeTools::expect_months(callback_t callback) { + return expect_uint([callback](Timespan::day_t val) -> bool { + return callback(Timespan::fromMonths(val)); + }); +} + +node_callback_t NodeTools::expect_days(callback_t callback) { + return expect_uint([callback](Timespan::day_t val) -> bool { + return callback(Timespan::fromDays(val)); + }); +} + template)> node_callback_t _expect_vec2(callback_t> callback) { return [callback](ast::NodeCPtr node) -> bool { @@ -166,7 +188,7 @@ node_callback_t _expect_vec2(callback_t> callback) { } node_callback_t NodeTools::expect_ivec2(callback_t callback) { - return _expect_vec2(callback); + return _expect_vec2(callback); } node_callback_t NodeTools::expect_fvec2(callback_t callback) { @@ -238,17 +260,24 @@ node_callback_t NodeTools::expect_length(callback_t callback) { }; } -node_callback_t NodeTools::expect_key(std::string_view key, node_callback_t callback) { +node_callback_t NodeTools::expect_key(std::string_view key, node_callback_t callback, bool* key_found) { return _expect_type( - [key, callback](ast::AbstractListNode const& list_node) -> bool { + [key, callback, key_found](ast::AbstractListNode const& list_node) -> bool { std::vector const& list = list_node._statements; for (ast::NodeUPtr const& sub_node : list_node._statements) { ast::AssignNode const* assign_node = sub_node->cast_to(); if (assign_node != nullptr && assign_node->_name == key) { + if (key_found != nullptr) { + *key_found = true; + } return callback(&*assign_node->_initializer); } } - Logger::error("Failed to find expected key: ", key); + if (key_found != nullptr) { + *key_found = false; + } else { + Logger::error("Failed to find expected key: ", key); + } return false; } ); @@ -262,21 +291,30 @@ node_callback_t NodeTools::expect_dictionary(key_value_callback_t callback) { return expect_dictionary_and_length(default_length_callback, callback); } -void NodeTools::add_key_map_entry(key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback) { +bool NodeTools::add_key_map_entry(key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback) { if (key_map.find(key) == key_map.end()) { key_map.emplace(key, dictionary_entry_t { expected_count, callback }); - } else { - Logger::error("Duplicate expected dictionary key: ", key); + return true; + } + Logger::error("Duplicate expected dictionary key: ", key); + return false; +} + +bool NodeTools::remove_key_map_entry(key_map_t& key_map, std::string_view key) { + const key_map_t::const_iterator it = key_map.find(key); + if (it != key_map.end()) { + key_map.erase(it); + return true; } + Logger::error("Failed to find dictionary key to remove: ", key); + return false; } -key_value_callback_t NodeTools::dictionary_keys_callback(key_map_t& key_map, bool allow_other_keys) { - return [&key_map, allow_other_keys](std::string_view key, ast::NodeCPtr value) -> bool { +key_value_callback_t NodeTools::dictionary_keys_callback(key_map_t& key_map, key_value_callback_t default_callback) { + return [&key_map, default_callback](std::string_view key, ast::NodeCPtr value) -> bool { const key_map_t::iterator it = key_map.find(key); if (it == key_map.end()) { - if (allow_other_keys) return true; - Logger::error("Invalid dictionary key: ", key); - return false; + return default_callback(key, value); } dictionary_entry_t& entry = it->second; if (++entry.count > 1 && !entry.can_repeat()) { @@ -300,16 +338,28 @@ bool NodeTools::check_key_map_counts(key_map_t& key_map) { return ret; } -node_callback_t NodeTools::_expect_dictionary_keys_and_length(length_callback_t length_callback, bool allow_other_keys, key_map_t&& key_map) { - return [length_callback, allow_other_keys, key_map = std::move(key_map)](ast::NodeCPtr node) mutable -> bool { +node_callback_t NodeTools::expect_dictionary_key_map_and_length_and_default(key_map_t key_map, length_callback_t length_callback, key_value_callback_t default_callback) { + return [length_callback, default_callback, key_map = std::move(key_map)](ast::NodeCPtr node) mutable -> bool { bool ret = expect_dictionary_and_length( - length_callback, dictionary_keys_callback(key_map, allow_other_keys) + length_callback, dictionary_keys_callback(key_map, default_callback) )(node); ret &= check_key_map_counts(key_map); return ret; }; } +node_callback_t NodeTools::expect_dictionary_key_map_and_length(key_map_t key_map, length_callback_t length_callback) { + return expect_dictionary_key_map_and_length_and_default(std::move(key_map), length_callback, key_value_invalid_callback); +} + +node_callback_t NodeTools::expect_dictionary_key_map_and_default(key_map_t key_map, key_value_callback_t default_callback) { + return expect_dictionary_key_map_and_length_and_default(std::move(key_map), default_length_callback, default_callback); +} + +node_callback_t NodeTools::expect_dictionary_key_map(key_map_t key_map) { + return expect_dictionary_key_map_and_length_and_default(std::move(key_map), default_length_callback, key_value_invalid_callback); +} + node_callback_t NodeTools::name_list_callback(std::vector& list) { return expect_list_reserve_length( list, @@ -325,3 +375,7 @@ node_callback_t NodeTools::name_list_callback(std::vector& list) { ) ); } + +callback_t NodeTools::assign_variable_callback_string(std::string& var) { + return assign_variable_callback_cast(var); +} diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp index 5ba9d63..44ac271 100644 --- a/src/openvic-simulation/dataloader/NodeTools.hpp +++ b/src/openvic-simulation/dataloader/NodeTools.hpp @@ -11,6 +11,11 @@ namespace OpenVic { namespace ast = ovdl::v2script::ast; + /* Template for map from strings to Ts, in which string_views can be + * searched for without needing to be copied into a string, */ + template + using string_map_t = std::map>; + namespace NodeTools { template @@ -21,17 +26,55 @@ namespace OpenVic { using key_value_callback_t = callback_t; constexpr bool key_value_success_callback(std::string_view, ast::NodeCPtr) { return true; } + inline bool key_value_invalid_callback(std::string_view key, ast::NodeCPtr) { + Logger::error("Invalid dictionary key: ", key); + return false; + } node_callback_t expect_identifier(callback_t callback); - node_callback_t expect_string(callback_t callback); + node_callback_t expect_string(callback_t callback, bool allow_empty = true); node_callback_t expect_identifier_or_string(callback_t callback); + node_callback_t expect_bool(callback_t callback); - node_callback_t expect_int(callback_t callback); - node_callback_t expect_uint(callback_t callback); + node_callback_t expect_int_bool(callback_t callback); + + node_callback_t expect_int64(callback_t callback); + node_callback_t expect_uint64(callback_t callback); + + template + node_callback_t expect_int(callback_t callback) { + return expect_int64([callback](int64_t val) -> bool { + if (static_cast(std::numeric_limits::lowest()) <= val && + val <= static_cast(std::numeric_limits::max())) { + return callback(val); + } + Logger::error("Invalid int: ", val, " (valid range: [", + static_cast(std::numeric_limits::lowest()), ", ", + static_cast(std::numeric_limits::max()), "])"); + return false; + }); + } + + template + node_callback_t expect_uint(callback_t callback) { + return expect_uint64([callback](uint64_t val) -> bool { + if (val <= static_cast(std::numeric_limits::max())) { + return callback(val); + } + Logger::error("Invalid uint: ", val, " (valid range: [0, ", + static_cast(std::numeric_limits::max()), "])"); + return false; + }); + } + node_callback_t expect_fixed_point(callback_t callback); node_callback_t expect_colour(callback_t callback); - node_callback_t expect_timespan(callback_t callback); + node_callback_t expect_date(callback_t callback); + node_callback_t expect_years(callback_t callback); + node_callback_t expect_months(callback_t callback); + node_callback_t expect_days(callback_t callback); + node_callback_t expect_ivec2(callback_t callback); node_callback_t expect_fvec2(callback_t callback); node_callback_t expect_assign(key_value_callback_t callback); @@ -44,7 +87,7 @@ namespace OpenVic { node_callback_t expect_list(node_callback_t callback); node_callback_t expect_length(callback_t callback); - node_callback_t expect_key(std::string_view key, node_callback_t callback); + node_callback_t expect_key(std::string_view key, node_callback_t callback, bool* key_found = nullptr); node_callback_t expect_dictionary_and_length(length_callback_t length_callback, key_value_callback_t callback); node_callback_t expect_dictionary(key_value_callback_t callback); @@ -73,41 +116,45 @@ namespace OpenVic { } }; using enum dictionary_entry_t::expected_count_t; - using key_map_t = std::map>; + using key_map_t = string_map_t; - void add_key_map_entry(key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback); - key_value_callback_t dictionary_keys_callback(key_map_t& key_map, bool allow_other_keys); + bool add_key_map_entry(key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback); + bool remove_key_map_entry(key_map_t& key_map, std::string_view key); + key_value_callback_t dictionary_keys_callback(key_map_t& key_map, key_value_callback_t default_callback); bool check_key_map_counts(key_map_t& key_map); - constexpr struct allow_other_keys_t {} ALLOW_OTHER_KEYS; - - node_callback_t _expect_dictionary_keys_and_length(length_callback_t length_callback, bool allow_other_keys, key_map_t&& key_map); + node_callback_t expect_dictionary_key_map_and_length_and_default(key_map_t key_map, length_callback_t length_callback, key_value_callback_t default_callback); + node_callback_t expect_dictionary_key_map_and_length(key_map_t key_map, length_callback_t length_callback); + node_callback_t expect_dictionary_key_map_and_default(key_map_t key_map, key_value_callback_t default_callback); + node_callback_t expect_dictionary_key_map(key_map_t key_map); template - node_callback_t _expect_dictionary_keys_and_length(length_callback_t length_callback, - bool allow_other_keys, key_map_t&& key_map, + node_callback_t expect_dictionary_key_map_and_length_and_default(key_map_t key_map, length_callback_t length_callback, key_value_callback_t default_callback, std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback, Args... args) { + // TODO - pass return value back up (part of big key_map_t rewrite?) add_key_map_entry(key_map, key, expected_count, callback); - return _expect_dictionary_keys_and_length(length_callback, allow_other_keys, std::move(key_map), args...); + return expect_dictionary_key_map_and_length_and_default(std::move(key_map), length_callback, default_callback, args...); } template - node_callback_t expect_dictionary_keys_and_length(length_callback_t length_callback, - std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback, - Args... args) { - return _expect_dictionary_keys_and_length(length_callback, false, {}, key, expected_count, callback, args...); + node_callback_t expect_dictionary_keys_and_length_and_default(length_callback_t length_callback, key_value_callback_t default_callback, Args... args) { + return expect_dictionary_key_map_and_length_and_default({}, length_callback, default_callback, args...); } template - node_callback_t expect_dictionary_keys_and_length(length_callback_t length_callback, - allow_other_keys_t, Args... args) { - return _expect_dictionary_keys_and_length(length_callback, true, {}, args...); + node_callback_t expect_dictionary_keys_and_length(length_callback_t length_callback, Args... args) { + return expect_dictionary_key_map_and_length_and_default({}, length_callback, key_value_invalid_callback, args...); + } + + template + node_callback_t expect_dictionary_keys_and_default(key_value_callback_t default_callback, Args... args) { + return expect_dictionary_key_map_and_length_and_default({}, default_length_callback, default_callback, args...); } template node_callback_t expect_dictionary_keys(Args... args) { - return expect_dictionary_keys_and_length(default_length_callback, args...); + return expect_dictionary_key_map_and_length_and_default({}, default_length_callback, key_value_invalid_callback, args...); } template @@ -133,13 +180,32 @@ namespace OpenVic { node_callback_t name_list_callback(std::vector& list); template - callback_t assign_variable_callback(T& var) { + callback_t expect_mapped_string(string_map_t const& map, callback_t callback) { + return [&map, callback](std::string_view string) -> bool { + const typename string_map_t::const_iterator it = map.find(string); + if (it != map.end()) { + return callback(it->second); + } + Logger::error("String not found in map: ", string); + return false; + }; + } + + template + callback_t assign_variable_callback_cast(U& var) { return [&var](T val) -> bool { var = val; return true; }; } + template + callback_t assign_variable_callback(T& var) { + return assign_variable_callback_cast(var); + } + + callback_t assign_variable_callback_string(std::string& var); + template callback_t move_variable_callback(T& var) { return [&var](T&& val) -> bool { @@ -161,41 +227,12 @@ namespace OpenVic { template requires requires(T& t) { - t--; - } - node_callback_t decrement_callback(T& var, node_callback_t callback) { - return [&var, callback](ast::NodeCPtr node) -> bool { - var--; - return callback(node); - }; - } - - template - requires(std::integral) - callback_t assign_variable_callback_uint(T& var) { - return [&var](uint64_t val) -> bool { - if (val <= static_cast(std::numeric_limits::max())) { - var = val; - return true; - } - Logger::error("Invalid uint: ", val, " (valid range: [0, ", - static_cast(std::numeric_limits::max()), "])"); - return false; - }; + t++; } - - template - requires(std::signed_integral) - callback_t assign_variable_callback_int(T& var) { - return [&var](int64_t val) -> bool { - if (static_cast(std::numeric_limits::lowest()) <= val && val <= static_cast(std::numeric_limits::max())) { - var = val; - return true; - } - Logger::error("Invalid int: ", val, " (valid range: [", - static_cast(std::numeric_limits::lowest()), ", ", - static_cast(std::numeric_limits::max()), "])"); - return false; + key_value_callback_t increment_callback(T& var) { + return [&var](std::string_view, ast::NodeCPtr) -> bool { + var++; + return true; }; } 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..b2d94c3 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 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 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> cb) { return [this, &good_manager, &pop_manager, cb](ast::NodeCPtr node) -> bool { @@ -174,19 +171,20 @@ 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) { size_t expected_types = 0; @@ -196,25 +194,27 @@ bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager 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; + 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 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 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 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 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..fdb0010 100644 --- a/src/openvic-simulation/economy/ProductionType.hpp +++ b/src/openvic-simulation/economy/ProductionType.hpp @@ -95,16 +95,16 @@ namespace OpenVic { private: IdentifierRegistry 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 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> cb); public: ProductionTypeManager(); bool add_production_type(PRODUCTION_TYPE_ARGS, GoodManager& good_manager); - IDENTIFIER_REGISTRY_ACCESSORS(ProductionType, production_type) + IDENTIFIER_REGISTRY_ACCESSORS(production_type) bool load_production_types_file(GoodManager& good_manager, PopManager& pop_manager, ast::NodeCPtr root); }; diff --git a/src/openvic-simulation/map/Building.cpp b/src/openvic-simulation/map/Building.cpp index 6f4c099..d27c91a 100644 --- a/src/openvic-simulation/map/Building.cpp +++ b/src/openvic-simulation/map/Building.cpp @@ -229,22 +229,22 @@ bool BuildingManager::load_buildings_file(GoodManager const& good_manager, Produ ModifierValue modifiers; bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(modifiers), - "type", ONE_EXACTLY, expect_building_type_identifier(assign_variable_callback_pointer(type)), + "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_uint(max_level)), + "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_timespan(assign_variable_callback(build_time)), + "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, production_type_manager.expect_production_type_identifier(assign_variable_callback_pointer(production_type)), + "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_uint(fort_level)), - "naval_capacity", ZERO_OR_ONE, expect_uint(assign_variable_callback_uint(naval_capacity)), + "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; diff --git a/src/openvic-simulation/map/Building.hpp b/src/openvic-simulation/map/Building.hpp index 9b445bf..3f74c3d 100644 --- a/src/openvic-simulation/map/Building.hpp +++ b/src/openvic-simulation/map/Building.hpp @@ -27,7 +27,7 @@ namespace OpenVic { struct Building : HasIdentifier, ModifierValue { friend struct BuildingManager; - using level_t = int8_t; + using level_t = int16_t; private: BuildingType const& type; @@ -162,10 +162,10 @@ namespace OpenVic { BuildingManager(); bool add_building_type(std::string_view identifier); - IDENTIFIER_REGISTRY_ACCESSORS(BuildingType, building_type) + IDENTIFIER_REGISTRY_ACCESSORS(building_type) bool add_building(std::string_view identifier, BuildingType const* type, ARGS); - IDENTIFIER_REGISTRY_ACCESSORS(Building, building) + IDENTIFIER_REGISTRY_ACCESSORS(building) bool load_buildings_file(GoodManager const& good_manager, ProductionTypeManager const& production_type_manager, ModifierManager const& modifier_manager, ast::NodeCPtr root); diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp index 386e7be..8362ff4 100644 --- a/src/openvic-simulation/map/Map.cpp +++ b/src/openvic-simulation/map/Map.cpp @@ -78,11 +78,16 @@ bool Map::set_water_province(std::string_view identifier) { } bool Map::set_water_province_list(std::vector const& list) { + if (water_provinces.is_locked()) { + Logger::error("The map's water provinces have already been locked!"); + return false; + } bool ret = true; water_provinces.reserve(water_provinces.size() + list.size()); for (std::string_view const& identifier : list) { ret &= set_water_province(identifier); } + lock_water_provinces(); return ret; } diff --git a/src/openvic-simulation/map/Map.hpp b/src/openvic-simulation/map/Map.hpp index 9c97960..a959158 100644 --- a/src/openvic-simulation/map/Map.hpp +++ b/src/openvic-simulation/map/Map.hpp @@ -70,8 +70,8 @@ namespace OpenVic { Map(); bool add_province(std::string_view identifier, colour_t colour); - IDENTIFIER_REGISTRY_ACCESSORS(Province, province) - IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS(Province, province) + IDENTIFIER_REGISTRY_ACCESSORS(province) + IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS(province) bool set_water_province(std::string_view identifier); bool set_water_province_list(std::vector const& list); @@ -93,11 +93,11 @@ namespace OpenVic { TerrainTypeManager const& get_terrain_type_manager() const; bool add_region(std::string_view identifier, std::vector const& province_identifiers); - IDENTIFIER_REGISTRY_ACCESSORS(Region, region) - IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS(Region, region) + IDENTIFIER_REGISTRY_ACCESSORS(region) + IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS(region) bool add_mapmode(std::string_view identifier, Mapmode::colour_func_t colour_func); - IDENTIFIER_REGISTRY_ACCESSORS(Mapmode, mapmode) + IDENTIFIER_REGISTRY_ACCESSORS(mapmode) Mapmode const* get_mapmode_by_index(size_t index) const; static constexpr size_t MAPMODE_COLOUR_SIZE = 4; bool generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) const; diff --git a/src/openvic-simulation/map/Province.hpp b/src/openvic-simulation/map/Province.hpp index 31b5d4c..c9b29ea 100644 --- a/src/openvic-simulation/map/Province.hpp +++ b/src/openvic-simulation/map/Province.hpp @@ -93,7 +93,7 @@ namespace OpenVic { bool load_positions(BuildingManager const& building_manager, ast::NodeCPtr root); bool add_building(BuildingInstance&& building_instance); - IDENTIFIER_REGISTRY_ACCESSORS(BuildingInstance, building) + IDENTIFIER_REGISTRY_ACCESSORS(building) void reset_buildings(); bool expand_building(std::string_view building_type_identifier); Good const* get_rgo() const; diff --git a/src/openvic-simulation/map/TerrainType.cpp b/src/openvic-simulation/map/TerrainType.cpp index 2438df6..ce0b7e7 100644 --- a/src/openvic-simulation/map/TerrainType.cpp +++ b/src/openvic-simulation/map/TerrainType.cpp @@ -49,7 +49,7 @@ bool TerrainTypeManager::add_terrain_type(std::string_view identifier, colour_t bool TerrainTypeManager::add_terrain_type_mapping(std::string_view identifier, TerrainType const* type, std::vector&& terrain_indicies, TerrainTypeMapping::index_t priority, bool has_texture) { - if (!terrain_types.is_locked()) { + if (!terrain_types_are_locked()) { Logger::error("Cannot register terrain type mappings until terrain types are locked!"); return false; } @@ -76,48 +76,53 @@ bool TerrainTypeManager::add_terrain_type_mapping(std::string_view identifier, T return ret; } -bool TerrainTypeManager::_load_terrain_type_categories(ModifierManager const& modifier_manager, ast::NodeCPtr root) { - const bool ret = expect_dictionary_reserve_length(terrain_types, - [this, &modifier_manager](std::string_view type_key, ast::NodeCPtr type_node) -> bool { - ModifierValue values; - colour_t colour = NULL_COLOUR; - bool is_water = false; - bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(values), - "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), - "is_water", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_water)) - )(type_node); - ret &= add_terrain_type(type_key, colour, std::move(values), is_water); - return ret; - } - )(root); - terrain_types.lock(); - return ret; +node_callback_t TerrainTypeManager::_load_terrain_type_categories(ModifierManager const& modifier_manager) { + return [this, &modifier_manager](ast::NodeCPtr root) -> bool { + const bool ret = expect_dictionary_reserve_length(terrain_types, + [this, &modifier_manager](std::string_view type_key, ast::NodeCPtr type_node) -> bool { + ModifierValue values; + colour_t colour = NULL_COLOUR; + bool is_water = false; + bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(values), + "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), + "is_water", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_water)) + )(type_node); + ret &= add_terrain_type(type_key, colour, std::move(values), is_water); + return ret; + } + )(root); + lock_terrain_types(); + return ret; + }; } bool TerrainTypeManager::_load_terrain_type_mapping(std::string_view mapping_key, ast::NodeCPtr mapping_value) { + if (terrain_texture_limit <= 0) { + Logger::error("Cannot define terrain type mapping before terrain texture limit: ", mapping_key); + return false; + } + if (!terrain_types_are_locked()) { + Logger::error("Cannot define terrain type mapping before categories: ", mapping_key); + return false; + } TerrainType const* type = nullptr; std::vector terrain_indicies; TerrainTypeMapping::index_t priority = 0; bool has_texture = true; bool ret = expect_dictionary_keys( - "type", ONE_EXACTLY, expect_terrain_type_identifier(assign_variable_callback_pointer(type)), - "color", ONE_EXACTLY, expect_list_reserve_length(terrain_indicies, expect_uint( - [&terrain_indicies](uint64_t val) -> bool { - if (val <= std::numeric_limits::max()) { - TerrainTypeMapping::index_t index = val; - if (std::find(terrain_indicies.begin(), terrain_indicies.end(), index) == terrain_indicies.end()) { - terrain_indicies.push_back(val); - return true; - } - Logger::error("Repeat terrain type mapping index: ", val); - return false; + "type", ONE_EXACTLY, expect_identifier(expect_terrain_type_identifier(assign_variable_callback_pointer(type))), + "color", ONE_EXACTLY, expect_list_reserve_length(terrain_indicies, expect_uint( + [&terrain_indicies](TerrainTypeMapping::index_t val) -> bool { + if (std::find(terrain_indicies.begin(), terrain_indicies.end(), val) == terrain_indicies.end()) { + terrain_indicies.push_back(val); + return true; } - Logger::error("Index too big for terrain type mapping index: ", val); + Logger::error("Repeat terrain type mapping index: ", val); return false; } )), - "priority", ZERO_OR_ONE, expect_uint(assign_variable_callback_uint(priority)), + "priority", ZERO_OR_ONE, expect_uint(assign_variable_callback(priority)), "has_texture", ZERO_OR_ONE, expect_bool(assign_variable_callback(has_texture)) )(mapping_value); if (has_texture) { @@ -143,45 +148,15 @@ TerrainTypeMapping::index_t TerrainTypeManager::get_terrain_texture_limit() cons } bool TerrainTypeManager::load_terrain_types(ModifierManager const& modifier_manager, ast::NodeCPtr root) { - bool terrain = false, categories = false; - bool ret = expect_dictionary_and_length( + const bool ret = expect_dictionary_keys_and_length_and_default( [this](size_t size) -> size_t { terrain_type_mappings.reserve(size - 2); return size; }, - [this, &terrain, &categories, &modifier_manager](std::string_view key, ast::NodeCPtr value) -> bool { - if (key == "terrain") { - if (!terrain) { - terrain = true; - return expect_uint(assign_variable_callback_uint(terrain_texture_limit))(value); - } else { - Logger::error("Duplicate terrain key!"); - return false; - } - } else if (key == "categories") { - if (!categories) { - categories = true; - return _load_terrain_type_categories(modifier_manager, value); - } else { - Logger::error("Duplicate categories key!"); - return false; - } - } else if (terrain && categories) { - return _load_terrain_type_mapping(key, value); - } else { - Logger::error("Cannot define terrain type mapping before terrain and categories keys: ", key); - return false; - } - } + std::bind(&TerrainTypeManager::_load_terrain_type_mapping, this, std::placeholders::_1, std::placeholders::_2), + "terrain", ONE_EXACTLY, expect_uint(assign_variable_callback(terrain_texture_limit)), + "categories", ONE_EXACTLY, _load_terrain_type_categories(modifier_manager) )(root); - if (!terrain) { - Logger::error("Missing expected key: \"terrain\""); - ret = false; - } - if (!categories) { - Logger::error("Missing expected key: \"categories\""); - ret = false; - } - terrain_type_mappings.lock(); + lock_terrain_type_mappings(); return ret; } diff --git a/src/openvic-simulation/map/TerrainType.hpp b/src/openvic-simulation/map/TerrainType.hpp index 3b491ae..1353130 100644 --- a/src/openvic-simulation/map/TerrainType.hpp +++ b/src/openvic-simulation/map/TerrainType.hpp @@ -50,18 +50,18 @@ namespace OpenVic { TerrainTypeMapping::index_t terrain_texture_limit = 0, terrain_texture_count = 0; - bool _load_terrain_type_categories(ModifierManager const& modifier_manager, ast::NodeCPtr root); + NodeTools::node_callback_t _load_terrain_type_categories(ModifierManager const& modifier_manager); bool _load_terrain_type_mapping(std::string_view key, ast::NodeCPtr value); public: TerrainTypeManager(); bool add_terrain_type(std::string_view identifier, colour_t colour, ModifierValue&& values, bool is_water); - IDENTIFIER_REGISTRY_ACCESSORS(TerrainType, terrain_type) + IDENTIFIER_REGISTRY_ACCESSORS(terrain_type) bool add_terrain_type_mapping(std::string_view identifier, TerrainType const* type, std::vector&& terrain_indicies, TerrainTypeMapping::index_t priority, bool has_texture); - IDENTIFIER_REGISTRY_ACCESSORS(TerrainTypeMapping, terrain_type_mapping) + IDENTIFIER_REGISTRY_ACCESSORS(terrain_type_mapping) TerrainTypeMapping const* get_terrain_type_mapping_for(TerrainTypeMapping::index_t idx) const; diff --git a/src/openvic-simulation/politics/Government.cpp b/src/openvic-simulation/politics/Government.cpp index 869ac3d..1a48806 100644 --- a/src/openvic-simulation/politics/Government.cpp +++ b/src/openvic-simulation/politics/Government.cpp @@ -2,98 +2,110 @@ #include -#include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/GameManager.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; -GovernmentType::GovernmentType(std::string_view new_identifier, std::vector new_ideologies, bool new_elections, bool new_appoint_ruling_party, Timespan new_election_duration, std::string_view new_flag_type_identifier) - : HasIdentifier { new_identifier }, ideologies { new_ideologies }, elections { new_elections }, appoint_ruling_party { new_appoint_ruling_party }, election_duration { new_election_duration }, flag_type_identifier { new_flag_type_identifier } {} +GovernmentType::GovernmentType(std::string_view new_identifier, std::vector&& new_ideologies, bool new_elections, bool new_appoint_ruling_party, Timespan new_term_duration, std::string_view new_flag_type_identifier) + : HasIdentifier { new_identifier }, ideologies { std::move(new_ideologies) }, elections { new_elections }, appoint_ruling_party { new_appoint_ruling_party }, term_duration { new_term_duration }, flag_type_identifier { new_flag_type_identifier } {} bool GovernmentType::is_ideology_compatible(Ideology const* ideology) const { - return std::find(ideologies.begin(), ideologies.end(), ideology) != ideologies.end(); + return std::find(ideologies.begin(), ideologies.end(), ideology) != ideologies.end(); } std::vector const& GovernmentType::get_ideologies() const { - return ideologies; + return ideologies; } bool GovernmentType::holds_elections() const { - return elections; + return elections; } bool GovernmentType::can_appoint_ruling_party() const { - return appoint_ruling_party; + return appoint_ruling_party; } -Timespan GovernmentType::get_election_duration() const { - return election_duration; +Timespan GovernmentType::get_term_duration() const { + return term_duration; } -std::string_view GovernmentType::get_flag_type() const { - return flag_type_identifier; +std::string const& GovernmentType::get_flag_type() const { + return flag_type_identifier; } GovernmentTypeManager::GovernmentTypeManager() : government_types { "government types" } {} -bool GovernmentTypeManager::add_government_type(std::string_view identifier, std::vector ideologies, bool elections, bool appoint_ruling_party, Timespan election_duration, std::string_view flag_type) { - if (identifier.empty()) { - Logger::error("Invalid government type identifier - empty!"); - return false; - } +bool GovernmentTypeManager::add_government_type(std::string_view identifier, std::vector ideologies, bool elections, bool appoint_ruling_party, Timespan term_duration, std::string_view flag_type) { + if (identifier.empty()) { + Logger::error("Invalid government type identifier - empty!"); + return false; + } - if (ideologies.empty()) { - Logger::error("No compatible ideologies defined for government type ", identifier); - return false; - } + if (ideologies.empty()) { + Logger::error("No compatible ideologies defined for government type ", identifier); + return false; + } - if (elections && election_duration == 0) { - Logger::error("No or invalid election duration for government type ", identifier); - return false; - } + if (elections && term_duration < 0) { + Logger::error("No or invalid term duration for government type ", identifier); + return false; + } - return government_types.add_item({ identifier, ideologies, elections, appoint_ruling_party, election_duration, flag_type }); + return government_types.add_item({ identifier, std::move(ideologies), elections, appoint_ruling_party, term_duration, flag_type }); } /* REQUIREMENTS: FS-525, SIM-27 */ bool GovernmentTypeManager::load_government_types_file(IdeologyManager const& ideology_manager, ast::NodeCPtr root) { - bool ret = expect_dictionary( - [this, &ideology_manager](std::string_view government_type_identifier, ast::NodeCPtr value) -> bool { - std::vector ideologies; - bool elections = false, appoint_ruling_party = false; - uint16_t election_duration = 0; /* in months */ - std::string_view flag_type_identifier = "republic"; - - bool ret = expect_dictionary_keys( - ALLOW_OTHER_KEYS, - "election", ONE_EXACTLY, expect_bool(assign_variable_callback(elections)), - "duration", ZERO_OR_ONE, expect_uint(assign_variable_callback_uint(election_duration)), - "appoint_ruling_party", ONE_EXACTLY, expect_bool(assign_variable_callback(appoint_ruling_party)), - "flagType", ZERO_OR_ONE, expect_identifier(assign_variable_callback(flag_type_identifier)) - )(value); - - ret &= expect_dictionary( - [this, &ideology_manager, &ideologies, government_type_identifier](std::string_view key, ast::NodeCPtr value) -> bool { - static const std::set> reserved_keys = { + bool ret = expect_dictionary_reserve_length( + government_types, + [this, &ideology_manager](std::string_view government_type_identifier, ast::NodeCPtr government_type_value) -> bool { + std::vector ideologies; + bool elections = false, appoint_ruling_party = false; + Timespan term_duration = 0; + std::string_view flag_type_identifier = "republic"; + + size_t total_expected_ideologies = 0; + bool ret = expect_dictionary_keys_and_default( + increment_callback(total_expected_ideologies), + "election", ONE_EXACTLY, expect_bool(assign_variable_callback(elections)), + "duration", ZERO_OR_ONE, expect_months(assign_variable_callback(term_duration)), + "appoint_ruling_party", ONE_EXACTLY, expect_bool(assign_variable_callback(appoint_ruling_party)), + "flagType", ZERO_OR_ONE, expect_identifier(assign_variable_callback(flag_type_identifier)) + )(government_type_value); + ideologies.reserve(total_expected_ideologies); + + ret &= expect_dictionary( + [this, &ideology_manager, &ideologies, government_type_identifier](std::string_view key, ast::NodeCPtr value) -> bool { + static const std::set> reserved_keys = { "election", "duration", "appoint_ruling_party", "flagType" }; - if (reserved_keys.find(key) != reserved_keys.end()) return true; - Ideology const* ideology = ideology_manager.get_ideology_by_identifier(key); - if (ideology == nullptr) { - Logger::error("When loading government type ", government_type_identifier, ", specified ideology ", key, " is invalid!"); - return false; - } - ideologies.push_back(ideology); - return true; - } - )(value); - - ret &= add_government_type(government_type_identifier, ideologies, elections, appoint_ruling_party, Timespan(election_duration * 30), flag_type_identifier); - return ret; - } - )(root); - lock_government_types(); - - return ret; + if (reserved_keys.find(key) != reserved_keys.end()) return true; + Ideology const* ideology = ideology_manager.get_ideology_by_identifier(key); + if (ideology == nullptr) { + Logger::error("When loading government type ", government_type_identifier, ", specified ideology ", key, " is invalid!"); + return false; + } + return expect_bool([&ideologies, ideology, government_type_identifier](bool val) -> bool { + if (val) { + if (std::find(ideologies.begin(), ideologies.end(), ideology) == ideologies.end()) { + ideologies.push_back(ideology); + return true; + } + Logger::error("Government type ", government_type_identifier, " marked as supporting ideology ", ideology->get_identifier()); + return false; + } + Logger::error("Government type ", government_type_identifier, " redundantly marked as not supporting ideology ", ideology->get_identifier(), " multiple times"); + return false; + })(value); + } + )(government_type_value); + + ret &= add_government_type(government_type_identifier, std::move(ideologies), elections, appoint_ruling_party, term_duration, flag_type_identifier); + return ret; + } + )(root); + lock_government_types(); + + return ret; } \ No newline at end of file diff --git a/src/openvic-simulation/politics/Government.hpp b/src/openvic-simulation/politics/Government.hpp index a8fc00f..3bc754c 100644 --- a/src/openvic-simulation/politics/Government.hpp +++ b/src/openvic-simulation/politics/Government.hpp @@ -1,43 +1,42 @@ #pragma once -#include "openvic-simulation/types/IdentifierRegistry.hpp" #include "openvic-simulation/politics/Ideology.hpp" namespace OpenVic { - struct GovernmentTypeManager; + struct GovernmentTypeManager; - struct GovernmentType : HasIdentifier { - friend struct GovernmentTypeManager; + struct GovernmentType : HasIdentifier { + friend struct GovernmentTypeManager; - private: - std::vector ideologies; - const bool elections, appoint_ruling_party; - const Timespan election_duration; - const std::string flag_type_identifier; + private: + const std::vector ideologies; + const bool elections, appoint_ruling_party; + const Timespan term_duration; + const std::string flag_type_identifier; - GovernmentType(std::string_view new_identifier, std::vector new_ideologies, bool new_elections, bool new_appoint_ruling_party, Timespan new_election_duration, std::string_view new_flag_type_identifier); + GovernmentType(std::string_view new_identifier, std::vector&& new_ideologies, bool new_elections, bool new_appoint_ruling_party, Timespan new_term_duration, std::string_view new_flag_type_identifier); - public: - GovernmentType(GovernmentType&&) = default; + public: + GovernmentType(GovernmentType&&) = default; - bool is_ideology_compatible(Ideology const* ideology) const; - std::vector const& get_ideologies() const; - bool holds_elections() const; - bool can_appoint_ruling_party() const; - Timespan get_election_duration() const; - std::string_view get_flag_type() const; - }; + bool is_ideology_compatible(Ideology const* ideology) const; + std::vector const& get_ideologies() const; + bool holds_elections() const; + bool can_appoint_ruling_party() const; + Timespan get_term_duration() const; + std::string const& get_flag_type() const; + }; - struct GovernmentTypeManager { - private: - IdentifierRegistry government_types; + struct GovernmentTypeManager { + private: + IdentifierRegistry government_types; - public: - GovernmentTypeManager(); + public: + GovernmentTypeManager(); - bool add_government_type(std::string_view identifier, std::vector ideologies, bool elections, bool appoint_ruling_party, Timespan election_duration, std::string_view flag_type); - IDENTIFIER_REGISTRY_ACCESSORS(GovernmentType, government_type) + bool add_government_type(std::string_view identifier, std::vector ideologies, bool elections, bool appoint_ruling_party, Timespan term_duration, std::string_view flag_type); + IDENTIFIER_REGISTRY_ACCESSORS(government_type) - bool load_government_types_file(IdeologyManager const& ideology_manager, ast::NodeCPtr root); - }; + bool load_government_types_file(IdeologyManager const& ideology_manager, ast::NodeCPtr root); + }; } // namespace OpenVic diff --git a/src/openvic-simulation/politics/Ideology.hpp b/src/openvic-simulation/politics/Ideology.hpp index ab761b1..557333e 100644 --- a/src/openvic-simulation/politics/Ideology.hpp +++ b/src/openvic-simulation/politics/Ideology.hpp @@ -45,10 +45,10 @@ namespace OpenVic { IdeologyManager(); bool add_ideology_group(std::string_view identifier); - IDENTIFIER_REGISTRY_ACCESSORS(IdeologyGroup, ideology_group) + IDENTIFIER_REGISTRY_ACCESSORS(ideology_group) bool add_ideology(std::string_view identifier, colour_t colour, IdeologyGroup const* group, bool uncivilised, bool can_reduce_militancy, Date spawn_date); - IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(Ideology, ideology, ideologies) + IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(ideology, ideologies) bool load_ideology_file(ast::NodeCPtr root); }; diff --git a/src/openvic-simulation/politics/Issue.cpp b/src/openvic-simulation/politics/Issue.cpp index 73978ee..3f2fd10 100644 --- a/src/openvic-simulation/politics/Issue.cpp +++ b/src/openvic-simulation/politics/Issue.cpp @@ -122,13 +122,10 @@ bool IssueManager::_load_issue(std::string_view identifier, IssueGroup const* gr bool IssueManager::_load_reform_group(size_t& expected_reforms, std::string_view identifier, ReformType const* type, ast::NodeCPtr node) { bool ordered = false, administrative = false; - bool ret = expect_dictionary_keys_and_length( - [&expected_reforms](size_t size) -> size_t { - expected_reforms += size; - return size; - }, ALLOW_OTHER_KEYS, - "next_step_only", ZERO_OR_ONE, decrement_callback(expected_reforms, expect_bool(assign_variable_callback(ordered))), - "administrative", ZERO_OR_ONE, decrement_callback(expected_reforms, expect_bool(assign_variable_callback(administrative))) + bool ret = expect_dictionary_keys_and_default( + increment_callback(expected_reforms), + "next_step_only", ZERO_OR_ONE, expect_bool(assign_variable_callback(ordered)), + "administrative", ZERO_OR_ONE, expect_bool(assign_variable_callback(administrative)) )(node); ret &= add_reform_group(identifier, type, ordered, administrative); return ret; diff --git a/src/openvic-simulation/politics/Issue.hpp b/src/openvic-simulation/politics/Issue.hpp index ddd6295..9d72334 100644 --- a/src/openvic-simulation/politics/Issue.hpp +++ b/src/openvic-simulation/politics/Issue.hpp @@ -107,19 +107,19 @@ namespace OpenVic { IssueManager(); bool add_issue_group(std::string_view identifier); - IDENTIFIER_REGISTRY_ACCESSORS(IssueGroup, issue_group) + IDENTIFIER_REGISTRY_ACCESSORS(issue_group) bool add_issue(std::string_view identifier, IssueGroup const* group); - IDENTIFIER_REGISTRY_ACCESSORS(Issue, issue) + IDENTIFIER_REGISTRY_ACCESSORS(issue) bool add_reform_type(std::string_view identifier, bool uncivilised); - IDENTIFIER_REGISTRY_ACCESSORS(ReformType, reform_type) + IDENTIFIER_REGISTRY_ACCESSORS(reform_type) bool add_reform_group(std::string_view identifier, ReformType const* type, bool ordered, bool administrative); - IDENTIFIER_REGISTRY_ACCESSORS(ReformGroup, reform_group) + IDENTIFIER_REGISTRY_ACCESSORS(reform_group) bool add_reform(std::string_view identifier, ReformGroup const* group, size_t ordinal); - IDENTIFIER_REGISTRY_ACCESSORS(Reform, reform) + IDENTIFIER_REGISTRY_ACCESSORS(reform) bool load_issues_file(ast::NodeCPtr root); }; diff --git a/src/openvic-simulation/pop/Culture.cpp b/src/openvic-simulation/pop/Culture.cpp index 6285305..261ad4c 100644 --- a/src/openvic-simulation/pop/Culture.cpp +++ b/src/openvic-simulation/pop/Culture.cpp @@ -118,16 +118,12 @@ bool CultureManager::_load_culture_group(size_t& total_expected_cultures, GraphicalCultureType const* unit_graphical_culture_type = default_unit_graphical_culture_type; bool is_overseas = true; - bool ret = expect_dictionary_keys_and_length( - [&total_expected_cultures](size_t size) -> size_t { - total_expected_cultures += size; - return size; - }, - ALLOW_OTHER_KEYS, - "leader", ONE_EXACTLY, decrement_callback(total_expected_cultures, expect_identifier(assign_variable_callback(leader))), - "unit", ZERO_OR_ONE, decrement_callback(total_expected_cultures, expect_graphical_culture_type_identifier(assign_variable_callback_pointer(unit_graphical_culture_type))), - "union", ZERO_OR_ONE, decrement_callback(total_expected_cultures, success_callback), - "is_overseas", ZERO_OR_ONE, decrement_callback(total_expected_cultures, expect_bool(assign_variable_callback(is_overseas))) + bool ret = expect_dictionary_keys_and_default( + increment_callback(total_expected_cultures), + "leader", ONE_EXACTLY, expect_identifier(assign_variable_callback(leader)), + "unit", ZERO_OR_ONE, expect_identifier(expect_graphical_culture_type_identifier(assign_variable_callback_pointer(unit_graphical_culture_type))), + "union", ZERO_OR_ONE, success_callback, + "is_overseas", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_overseas)) )(culture_group_node); ret &= add_culture_group(culture_group_key, leader, unit_graphical_culture_type, is_overseas); return ret; diff --git a/src/openvic-simulation/pop/Culture.hpp b/src/openvic-simulation/pop/Culture.hpp index becc289..b6b4952 100644 --- a/src/openvic-simulation/pop/Culture.hpp +++ b/src/openvic-simulation/pop/Culture.hpp @@ -69,13 +69,13 @@ namespace OpenVic { CultureManager(); bool add_graphical_culture_type(std::string_view identifier); - IDENTIFIER_REGISTRY_ACCESSORS(GraphicalCultureType, graphical_culture_type) + IDENTIFIER_REGISTRY_ACCESSORS(graphical_culture_type) bool add_culture_group(std::string_view identifier, std::string_view leader, GraphicalCultureType const* new_graphical_culture_type, bool is_overseas); - IDENTIFIER_REGISTRY_ACCESSORS(CultureGroup, culture_group) + IDENTIFIER_REGISTRY_ACCESSORS(culture_group) bool add_culture(std::string_view identifier, colour_t colour, CultureGroup const* group, std::vector const& first_names, std::vector const& last_names); - IDENTIFIER_REGISTRY_ACCESSORS(Culture, culture) + IDENTIFIER_REGISTRY_ACCESSORS(culture) bool load_graphical_culture_type_file(ast::NodeCPtr root); bool load_culture_file(ast::NodeCPtr root); diff --git a/src/openvic-simulation/pop/Pop.cpp b/src/openvic-simulation/pop/Pop.cpp index 38cd883..14c2a41 100644 --- a/src/openvic-simulation/pop/Pop.cpp +++ b/src/openvic-simulation/pop/Pop.cpp @@ -146,34 +146,24 @@ bool PopManager::add_pop_type(std::string_view identifier, colour_t colour, PopT * POP-3, POP-4, POP-5, POP-6, POP-7, POP-8, POP-9, POP-10, POP-11, POP-12, POP-13, POP-14 */ bool PopManager::load_pop_type_file(std::string_view filestem, ast::NodeCPtr root) { + static const string_map_t strata_map = { + { "poor", PopType::strata_t::POOR }, + { "middle", PopType::strata_t::MIDDLE }, + { "rich", PopType::strata_t::RICH } + }; + colour_t colour = NULL_COLOUR; PopType::strata_t strata = PopType::strata_t::POOR; PopType::sprite_t sprite = 0; bool state_capital_only = false, is_artisan = false, is_slave = false, demote_migrant = false; Pop::pop_size_t max_size = 0, merge_max_size = 0; bool ret = expect_dictionary_keys( - "sprite", ONE_EXACTLY, expect_uint(assign_variable_callback_uint(sprite)), + "sprite", ONE_EXACTLY, expect_uint(assign_variable_callback(sprite)), "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), "is_artisan", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_artisan)), - "max_size", ZERO_OR_ONE, expect_uint(assign_variable_callback_uint(max_size)), - "merge_max_size", ZERO_OR_ONE, expect_uint(assign_variable_callback_uint(merge_max_size)), - "strata", ONE_EXACTLY, expect_identifier( - [&strata](std::string_view identifier) -> bool { - using strata_map_t = std::map>; - static const strata_map_t strata_map = { - { "poor", PopType::strata_t::POOR }, - { "middle", PopType::strata_t::MIDDLE }, - { "rich", PopType::strata_t::RICH } - }; - const strata_map_t::const_iterator it = strata_map.find(identifier); - if (it != strata_map.end()) { - strata = it->second; - return true; - } - Logger::error("Invalid pop type strata: ", identifier); - return false; - } - ), + "max_size", ZERO_OR_ONE, expect_uint(assign_variable_callback(max_size)), + "merge_max_size", ZERO_OR_ONE, expect_uint(assign_variable_callback(merge_max_size)), + "strata", ONE_EXACTLY, expect_identifier(expect_mapped_string(strata_map, assign_variable_callback(strata))), "state_capital_only", ZERO_OR_ONE, expect_bool(assign_variable_callback(state_capital_only)), "research_points", ZERO_OR_ONE, success_callback, "research_optimum", ZERO_OR_ONE, success_callback, @@ -216,9 +206,9 @@ bool PopManager::load_pop_into_province(Province& province, std::string_view pop Religion const* religion = nullptr; Pop::pop_size_t size = 0; bool ret = expect_dictionary_keys( - "culture", ONE_EXACTLY, culture_manager.expect_culture_identifier(assign_variable_callback_pointer(culture)), - "religion", ONE_EXACTLY, religion_manager.expect_religion_identifier(assign_variable_callback_pointer(religion)), - "size", ONE_EXACTLY, expect_uint(assign_variable_callback_uint(size)), + "culture", ONE_EXACTLY, expect_identifier(culture_manager.expect_culture_identifier(assign_variable_callback_pointer(culture))), + "religion", ONE_EXACTLY, expect_identifier(religion_manager.expect_religion_identifier(assign_variable_callback_pointer(religion))), + "size", ONE_EXACTLY, expect_uint(assign_variable_callback(size)), "militancy", ZERO_OR_ONE, success_callback, "rebel_type", ZERO_OR_ONE, success_callback )(pop_node); diff --git a/src/openvic-simulation/pop/Pop.hpp b/src/openvic-simulation/pop/Pop.hpp index 0ab3d06..e299468 100644 --- a/src/openvic-simulation/pop/Pop.hpp +++ b/src/openvic-simulation/pop/Pop.hpp @@ -96,7 +96,7 @@ namespace OpenVic { bool add_pop_type(std::string_view identifier, colour_t new_colour, PopType::strata_t strata, PopType::sprite_t sprite, Pop::pop_size_t max_size, Pop::pop_size_t merge_max_size, bool state_capital_only, bool demote_migrant, bool is_artisan, bool is_slave); - IDENTIFIER_REGISTRY_ACCESSORS(PopType, pop_type) + IDENTIFIER_REGISTRY_ACCESSORS(pop_type) bool load_pop_type_file(std::string_view filestem, ast::NodeCPtr root); bool load_pop_into_province(Province& province, std::string_view pop_type_identifier, ast::NodeCPtr pop_node) const; diff --git a/src/openvic-simulation/pop/Religion.cpp b/src/openvic-simulation/pop/Religion.cpp index 32a3219..1152ae5 100644 --- a/src/openvic-simulation/pop/Religion.cpp +++ b/src/openvic-simulation/pop/Religion.cpp @@ -91,7 +91,7 @@ bool ReligionManager::load_religion_file(ast::NodeCPtr root) { bool pagan = false; bool ret = expect_dictionary_keys( - "icon", ONE_EXACTLY, expect_uint(assign_variable_callback_uint(icon)), + "icon", ONE_EXACTLY, expect_uint(assign_variable_callback(icon)), "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), "pagan", ZERO_OR_ONE, expect_bool(assign_variable_callback(pagan)) )(value); diff --git a/src/openvic-simulation/pop/Religion.hpp b/src/openvic-simulation/pop/Religion.hpp index 6d1c205..6b17266 100644 --- a/src/openvic-simulation/pop/Religion.hpp +++ b/src/openvic-simulation/pop/Religion.hpp @@ -46,10 +46,10 @@ namespace OpenVic { ReligionManager(); bool add_religion_group(std::string_view identifier); - IDENTIFIER_REGISTRY_ACCESSORS(ReligionGroup, religion_group) + IDENTIFIER_REGISTRY_ACCESSORS(religion_group) bool add_religion(std::string_view identifier, colour_t colour, ReligionGroup const* group, Religion::icon_t icon, bool pagan); - IDENTIFIER_REGISTRY_ACCESSORS(Religion, religion) + IDENTIFIER_REGISTRY_ACCESSORS(religion) bool load_religion_file(ast::NodeCPtr root); }; diff --git a/src/openvic-simulation/types/Date.cpp b/src/openvic-simulation/types/Date.cpp index 27d554c..f167b7b 100644 --- a/src/openvic-simulation/types/Date.cpp +++ b/src/openvic-simulation/types/Date.cpp @@ -64,6 +64,19 @@ Timespan::operator std::string() const { return to_string(); } +Timespan Timespan::fromYears(day_t num) { + return num * Date::DAYS_IN_YEAR; +} + +Timespan Timespan::fromMonths(day_t num) { + return (num / Date::MONTHS_IN_YEAR) * Date::DAYS_IN_YEAR + + Date::DAYS_UP_TO_MONTH[num % Date::MONTHS_IN_YEAR]; +} + +Timespan Timespan::fromDays(day_t num) { + return num; +} + std::ostream& OpenVic::operator<<(std::ostream& out, Timespan const& timespan) { return out << timespan.to_string(); } diff --git a/src/openvic-simulation/types/Date.hpp b/src/openvic-simulation/types/Date.hpp index b2df666..718de80 100644 --- a/src/openvic-simulation/types/Date.hpp +++ b/src/openvic-simulation/types/Date.hpp @@ -35,6 +35,10 @@ namespace OpenVic { explicit operator double() const; std::string to_string() const; explicit operator std::string() const; + + static Timespan fromYears(day_t num); + static Timespan fromMonths(day_t num); + static Timespan fromDays(day_t num); }; std::ostream& operator<<(std::ostream& out, Timespan const& timespan); diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp index 7fe2656..4e13813 100644 --- a/src/openvic-simulation/types/IdentifierRegistry.hpp +++ b/src/openvic-simulation/types/IdentifierRegistry.hpp @@ -68,42 +68,50 @@ namespace OpenVic { distribution_t::value_type get_largest_item(distribution_t const& dist); - /* - * Template for a list of objects with unique string identifiers that can - * be locked to prevent any further additions. The template argument T is - * the type of object that the registry will store, and the second part ensures - * that HasIdentifier is a base class of T. - */ template - requires(std::derived_from) - class IdentifierRegistry { - using identifier_index_map_t = std::map>; + using get_identifier_func_t = std::string const&(T::*)(void) const; + + template _Type, get_identifier_func_t<_Base> get_identifier, + typename _Storage, _Type* (*get_ptr)(_Storage&), _Type const* (*get_cptr)(_Storage const&)> + class UniqueKeyRegistry { const std::string name; const bool log_lock; - std::vector items; + std::vector<_Storage> items; bool locked = false; - identifier_index_map_t identifier_index_map; + string_map_t identifier_index_map; public: - IdentifierRegistry(std::string_view new_name, bool new_log_lock = true) + using value_type = _Type; + using storage_type = _Storage; + + UniqueKeyRegistry(std::string_view new_name, bool new_log_lock = true) : name { new_name }, log_lock { new_log_lock } {} std::string const& get_name() const { return name; } - bool add_item(T&& item) { + bool add_item(storage_type&& item, bool fail_on_duplicate = true) { if (locked) { Logger::error("Cannot add item to the ", name, " registry - locked!"); return false; } - T const* old_item = get_item_by_identifier(item.get_identifier()); + value_type const* new_item = (*get_cptr)(item); + std::string const& new_identifier = (new_item->*get_identifier)(); + value_type const* old_item = get_item_by_identifier(new_identifier); if (old_item != nullptr) { - Logger::error("Cannot add item to the ", name, " registry - an item with the identifier \"", item.get_identifier(), "\" already exists!"); - return false; +#define DUPLICATE_MESSAGE "Cannot add item to the ", name, " registry - an item with the identifier \"", new_identifier, "\" already exists!" + if (fail_on_duplicate) { + Logger::error(DUPLICATE_MESSAGE); + return false; + } else { + Logger::warning(DUPLICATE_MESSAGE); + return true; + } +#undef DUPLICATE_MESSAGE } - identifier_index_map[item.get_identifier()] = items.size(); + identifier_index_map[new_identifier] = items.size(); items.push_back(std::move(item)); return true; } @@ -143,15 +151,15 @@ namespace OpenVic { } } - T* get_item_by_identifier(std::string_view identifier) { - const identifier_index_map_t::const_iterator it = identifier_index_map.find(identifier); - if (it != identifier_index_map.end()) return &items[it->second]; + value_type* get_item_by_identifier(std::string_view identifier) { + const typename decltype(identifier_index_map)::const_iterator it = identifier_index_map.find(identifier); + if (it != identifier_index_map.end()) return (*get_ptr)(items[it->second]); return nullptr; } - T const* get_item_by_identifier(std::string_view identifier) const { - const identifier_index_map_t::const_iterator it = identifier_index_map.find(identifier); - if (it != identifier_index_map.end()) return &items[it->second]; + value_type const* get_item_by_identifier(std::string_view identifier) const { + const typename decltype(identifier_index_map)::const_iterator it = identifier_index_map.find(identifier); + if (it != identifier_index_map.end()) return (*get_cptr)(items[it->second]); return nullptr; } @@ -159,11 +167,11 @@ namespace OpenVic { return get_item_by_identifier(identifier) != nullptr; } - T* get_item_by_index(size_t index) { + value_type* get_item_by_index(size_t index) { return index < items.size() ? &items[index] : nullptr; } - T const* get_item_by_index(size_t index) const { + value_type const* get_item_by_index(size_t index) const { return index < items.size() ? &items[index] : nullptr; } @@ -171,48 +179,44 @@ namespace OpenVic { return get_item_by_index(index) != nullptr; } - std::vector& get_items() { + std::vector& get_items() { return items; } - std::vector const& get_items() const { + std::vector const& get_items() const { return items; } std::vector get_item_identifiers() const { std::vector identifiers; identifiers.reserve(items.size()); - for (identifier_index_map_t::value_type const& entry : identifier_index_map) { + for (typename decltype(identifier_index_map)::value_type const& entry : identifier_index_map) { identifiers.push_back(entry.first); } return identifiers; } - NodeTools::node_callback_t expect_item_identifier(NodeTools::callback_t callback) { - return NodeTools::expect_identifier( - [this, callback](std::string_view identifier) -> bool { - T* item = get_item_by_identifier(identifier); - if (item != nullptr) return callback(*item); - Logger::error("Invalid ", name, ": ", identifier); - return false; - } - ); + NodeTools::callback_t expect_item_identifier(NodeTools::callback_t callback) { + return [this, callback](std::string_view identifier) -> bool { + value_type* item = get_item_by_identifier(identifier); + if (item != nullptr) return callback(*item); + Logger::error("Invalid ", name, ": ", identifier); + return false; + }; } - NodeTools::node_callback_t expect_item_identifier(NodeTools::callback_t callback) const { - return NodeTools::expect_identifier( - [this, callback](std::string_view identifier) -> bool { - T const* item = get_item_by_identifier(identifier); - if (item != nullptr) return callback(*item); - Logger::error("Invalid ", name, ": ", identifier); - return false; - } - ); + NodeTools::callback_t expect_item_identifier(NodeTools::callback_t callback) const { + return [this, callback](std::string_view identifier) -> bool { + value_type const* item = get_item_by_identifier(identifier); + if (item != nullptr) return callback(*item); + Logger::error("Invalid ", name, ": ", identifier); + return false; + }; } - NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t callback) { + NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t callback) { return NodeTools::expect_dictionary([this, callback](std::string_view key, ast::NodeCPtr value) -> bool { - T* item = get_item_by_identifier(key); + value_type* item = get_item_by_identifier(key); if (item != nullptr) { return callback(*item, value); } @@ -221,9 +225,9 @@ namespace OpenVic { }); } - NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t callback) const { + NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t callback) const { return NodeTools::expect_dictionary([this, callback](std::string_view key, ast::NodeCPtr value) -> bool { - T const* item = get_item_by_identifier(key); + value_type const* item = get_item_by_identifier(key); if (item != nullptr) { return callback(*item, value); } @@ -232,10 +236,10 @@ namespace OpenVic { }); } - NodeTools::node_callback_t expect_item_decimal_map(NodeTools::callback_t&&> callback) const { + NodeTools::node_callback_t expect_item_decimal_map(NodeTools::callback_t&&> callback) const { return [this, callback](ast::NodeCPtr node) -> bool { - std::map map; - bool ret = expect_item_dictionary([&map](T const& key, ast::NodeCPtr value) -> bool { + std::map map; + bool ret = expect_item_dictionary([&map](value_type const& key, ast::NodeCPtr value) -> bool { fixed_point_t val; const bool ret = NodeTools::expect_fixed_point(NodeTools::assign_variable_callback(val))(value); map.emplace(&key, val); @@ -247,34 +251,56 @@ namespace OpenVic { } }; -#define IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(type, singular, plural) \ + template _Type, get_identifier_func_t<_Base> get_identifier> + using ValueRegistry = UniqueKeyRegistry<_Base, _Type, get_identifier, _Type, std::addressof<_Type>, std::addressof>; + + template + constexpr _Type* get_ptr(std::unique_ptr<_Type>& storage) { + return storage.get(); + } + template + constexpr _Type const* get_cptr(std::unique_ptr<_Type> const& storage) { + return storage.get(); + } + + template _Type, get_identifier_func_t<_Base> get_identifier> + using InstanceRegistry = UniqueKeyRegistry<_Base, _Type, get_identifier, std::unique_ptr<_Type>, + get_ptr<_Type>, get_cptr<_Type>>; + + template _Type> + using IdentifierRegistry = ValueRegistry; + + template _Type> + using IdentifierInstanceRegistry = InstanceRegistry; + +#define IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(singular, plural) \ void lock_##plural() { plural.lock(); } \ bool plural##_are_locked() const { return plural.is_locked(); } \ - type const* get_##singular##_by_identifier(std::string_view identifier) const { \ + decltype(plural)::value_type const* get_##singular##_by_identifier(std::string_view identifier) const { \ return plural.get_item_by_identifier(identifier); } \ bool has_##singular##_identifier(std::string_view identifier) const { \ return plural.has_identifier(identifier); } \ size_t get_##singular##_count() const { \ return plural.size(); } \ - std::vector const& get_##plural() const { \ + std::vector const& get_##plural() const { \ return plural.get_items(); } \ std::vector get_##singular##_identifiers() const { \ return plural.get_item_identifiers(); } \ - NodeTools::node_callback_t expect_##singular##_identifier(NodeTools::callback_t callback) const { \ + NodeTools::callback_t expect_##singular##_identifier(NodeTools::callback_t callback) const { \ return plural.expect_item_identifier(callback); } \ - NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t callback) const { \ + NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t callback) const { \ return plural.expect_item_dictionary(callback); } \ - NodeTools::node_callback_t expect_##singular##_decimal_map(NodeTools::callback_t&&> callback) const { \ + NodeTools::node_callback_t expect_##singular##_decimal_map(NodeTools::callback_t&&> callback) const { \ return plural.expect_item_decimal_map(callback); } -#define IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS_CUSTOM_PLURAL(type, singular, plural) \ - type* get_##singular##_by_identifier(std::string_view identifier) { \ +#define IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS_CUSTOM_PLURAL(singular, plural) \ + decltype(plural)::value_type* get_##singular##_by_identifier(std::string_view identifier) { \ return plural.get_item_by_identifier(identifier); } \ - NodeTools::node_callback_t expect_##singular##_identifier(NodeTools::callback_t callback) { \ + NodeTools::callback_t expect_##singular##_identifier(NodeTools::callback_t callback) { \ return plural.expect_item_identifier(callback); } \ - NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t callback) { \ + NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t callback) { \ return plural.expect_item_dictionary(callback); } -#define IDENTIFIER_REGISTRY_ACCESSORS(type, name) IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(type, name, name##s) -#define IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS(type, name) IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS_CUSTOM_PLURAL(type, name, name##s) +#define IDENTIFIER_REGISTRY_ACCESSORS(name) IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(name, name##s) +#define IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS(name) IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS_CUSTOM_PLURAL(name, name##s) } diff --git a/src/openvic-simulation/types/Vector.cpp b/src/openvic-simulation/types/Vector.cpp index aa44710..10d2dd2 100644 --- a/src/openvic-simulation/types/Vector.cpp +++ b/src/openvic-simulation/types/Vector.cpp @@ -76,5 +76,5 @@ constexpr std::ostream& operator<<(std::ostream& stream, vec2_t const& value) template struct OpenVic::vec2_t; template struct OpenVic::vec2_t; -static_assert(sizeof(ivec2_t) == 2 * sizeof(int64_t), "ivec2_t size does not equal the sum of its parts' sizes"); -static_assert(sizeof(fvec2_t) == 2 * sizeof(fixed_point_t), "fvec2_t size does not equal the sum of its parts' sizes"); +static_assert(sizeof(ivec2_t) == 2 * sizeof(ivec2_t::type), "ivec2_t size does not equal the sum of its parts' sizes"); +static_assert(sizeof(fvec2_t) == 2 * sizeof(fvec2_t::type), "fvec2_t size does not equal the sum of its parts' sizes"); diff --git a/src/openvic-simulation/types/Vector.hpp b/src/openvic-simulation/types/Vector.hpp index eecd738..9f576d7 100644 --- a/src/openvic-simulation/types/Vector.hpp +++ b/src/openvic-simulation/types/Vector.hpp @@ -6,6 +6,8 @@ namespace OpenVic { template struct vec2_t { + using type = T; + T x, y; constexpr vec2_t() = default; @@ -21,21 +23,21 @@ namespace OpenVic { constexpr T& operator[](size_t index); constexpr T const& operator[](size_t index) const; - template + template constexpr friend vec2_t operator+(vec2_t const& left, vec2_t const& right); constexpr vec2_t& operator+=(vec2_t const& right); - template + template constexpr friend vec2_t operator-(vec2_t const& arg); - template + template constexpr friend vec2_t operator-(vec2_t const& left, vec2_t const& right); constexpr vec2_t& operator-=(vec2_t const& right); - template + template constexpr friend std::ostream& operator<<(std::ostream& stream, vec2_t const& value); }; - using ivec2_t = vec2_t; + using ivec2_t = vec2_t; using fvec2_t = vec2_t; } diff --git a/src/openvic-simulation/units/Unit.cpp b/src/openvic-simulation/units/Unit.cpp index 8d519f1..3da24da 100644 --- a/src/openvic-simulation/units/Unit.cpp +++ b/src/openvic-simulation/units/Unit.cpp @@ -1,9 +1,12 @@ #include "Unit.hpp" +#include + #define UNIT_ARGS icon, sprite, active, unit_type, floating_flag, priority, max_strength, \ default_organisation, maximum_speed, weighted_value, build_time, build_cost, supply_consumption, \ supply_cost -#define LAND_ARGS reconnaissance, attack, defence, discipline, support, maneuver, siege +#define LAND_ARGS primary_culture, sprite_override, sprite_mount, sprite_mount_attach_node, \ + reconnaissance, attack, defence, discipline, support, maneuver, siege #define NAVY_ARGS naval_icon, sail, transport, capital, move_sound, select_sound, colonial_points, build_overseas, min_port_level, \ limit_per_port, supply_consumption_score, hull, gun_power, fire_range, evasion, torpedo_attack @@ -76,9 +79,26 @@ std::map const& Unit::get_supply_cost() const { return supply_cost; } -LandUnit::LandUnit(std::string_view identifier, UNIT_PARAMS, LAND_PARAMS) : Unit { identifier, type_t::LAND, UNIT_ARGS }, - reconnaissance { reconnaissance }, attack { attack }, defence { defence }, discipline { discipline }, support { support }, - maneuver { maneuver }, siege { siege } {} +LandUnit::LandUnit(std::string_view identifier, UNIT_PARAMS, LAND_PARAMS) + : Unit { identifier, type_t::LAND, UNIT_ARGS }, primary_culture { primary_culture }, sprite_override { sprite_override }, + sprite_mount { sprite_mount }, sprite_mount_attach_node { sprite_mount_attach_node }, reconnaissance { reconnaissance }, + attack { attack }, defence { defence }, discipline { discipline }, support { support }, maneuver { maneuver }, siege { siege } {} + +bool LandUnit::get_primary_culture() const { + return primary_culture; +} + +std::string const& LandUnit::get_sprite_override() const { + return sprite_override; +} + +std::string const& LandUnit::get_sprite_mount() const { + return sprite_mount; +} + +std::string const& LandUnit::get_sprite_mount_attach_node() const { + return sprite_mount_attach_node; +} fixed_point_t LandUnit::get_reconnaissance() const { return reconnaissance; @@ -215,6 +235,17 @@ bool UnitManager::add_naval_unit(std::string_view identifier, UNIT_PARAMS, NAVY_ return units.add_item(NavalUnit { identifier, UNIT_ARGS, NAVY_ARGS }); } +static bool shared_keys_callback(std::string_view key, ast::NodeCPtr) { + static const std::set> reserved_keys = { + "icon", "type", "sprite", "active", "unit_type", "floating_flag", "priority", + "max_strength", "default_organisation", "maximum_speed", "weighted_value", + "build_time", "build_cost", "supply_consumption", "supply_cost" + }; + if (reserved_keys.contains(key)) return true; + Logger::error("Invalid key: ", key); + return false; +}; + bool UnitManager::load_unit_file(GoodManager const& good_manager, ast::NodeCPtr root) { return expect_dictionary([this, &good_manager](std::string_view key, ast::NodeCPtr value) -> bool { Unit::icon_t icon = 0; @@ -226,28 +257,36 @@ bool UnitManager::load_unit_file(GoodManager const& good_manager, ast::NodeCPtr std::map build_cost, supply_cost; //shared - bool ret = expect_dictionary_keys(ALLOW_OTHER_KEYS, - "icon", ONE_EXACTLY, expect_uint(assign_variable_callback_uint(icon)), + bool ret = expect_dictionary_keys_and_default( + key_value_success_callback, + "icon", ONE_EXACTLY, expect_uint(assign_variable_callback(icon)), "type", ONE_EXACTLY, expect_identifier(assign_variable_callback(type)), "sprite", ONE_EXACTLY, expect_identifier(assign_variable_callback(sprite)), "active", ZERO_OR_ONE, expect_bool(assign_variable_callback(active)), "unit_type", ONE_EXACTLY, expect_identifier(assign_variable_callback(unit_type)), "floating_flag", ONE_EXACTLY, expect_bool(assign_variable_callback(floating_flag)), - "priority", ONE_EXACTLY, expect_uint(assign_variable_callback_uint(priority)), + "priority", ONE_EXACTLY, expect_uint(assign_variable_callback(priority)), "max_strength", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_strength)), "default_organisation", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(default_organisation)), "maximum_speed", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(maximum_speed)), "weighted_value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(weighted_value)), - "build_time", ONE_EXACTLY, expect_timespan(assign_variable_callback(build_time)), + "build_time", ONE_EXACTLY, expect_days(assign_variable_callback(build_time)), "build_cost", ONE_EXACTLY, good_manager.expect_good_decimal_map(move_variable_callback(build_cost)), "supply_consumption", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(supply_consumption)), "supply_cost", ONE_EXACTLY, good_manager.expect_good_decimal_map(move_variable_callback(supply_cost)) )(value); if (type == "land") { + bool primary_culture = false; + std::string_view sprite_override, sprite_mount, sprite_mount_attach_node; fixed_point_t reconnaissance = 0, attack = 0, defence = 0, discipline = 0, support = 0, maneuver = 0, siege = 0; - ret &= expect_dictionary_keys(ALLOW_OTHER_KEYS, + ret &= expect_dictionary_keys_and_default( + shared_keys_callback, + "primary_culture", ZERO_OR_ONE, expect_bool(assign_variable_callback(primary_culture)), + "sprite_override", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_override)), + "sprite_mount", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_mount)), + "sprite_mount_attach_node", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_mount_attach_node)), "reconnaissance", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(reconnaissance)), "attack", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(attack)), "defence", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(defence)), @@ -268,8 +307,9 @@ bool UnitManager::load_unit_file(GoodManager const& good_manager, ast::NodeCPtr int32_t limit_per_port = 0; fixed_point_t fire_range = 0, evasion = 0, supply_consumption_score = 0, hull = 0, gun_power = 0, colonial_points = 0, torpedo_attack = 0; - ret &= expect_dictionary_keys(ALLOW_OTHER_KEYS, - "naval_icon", ONE_EXACTLY, expect_uint(assign_variable_callback_uint(naval_icon)), + ret &= expect_dictionary_keys_and_default( + shared_keys_callback, + "naval_icon", ONE_EXACTLY, expect_uint(assign_variable_callback(naval_icon)), "sail", ZERO_OR_ONE, expect_bool(assign_variable_callback(sail)), "transport", ZERO_OR_ONE, expect_bool(assign_variable_callback(transport)), "capital", ZERO_OR_ONE, expect_bool(assign_variable_callback(capital)), @@ -277,8 +317,8 @@ bool UnitManager::load_unit_file(GoodManager const& good_manager, ast::NodeCPtr "select_sound", ZERO_OR_ONE, expect_identifier(assign_variable_callback(select_sound)), "colonial_points", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(colonial_points)), "can_build_overseas", ZERO_OR_ONE, expect_bool(assign_variable_callback(build_overseas)), - "min_port_level", ONE_EXACTLY, expect_uint(assign_variable_callback_uint(min_port_level)), - "limit_per_port", ONE_EXACTLY, expect_int(assign_variable_callback_int(limit_per_port)), + "min_port_level", ONE_EXACTLY, expect_uint(assign_variable_callback(min_port_level)), + "limit_per_port", ONE_EXACTLY, expect_int(assign_variable_callback(limit_per_port)), "supply_consumption_score", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(supply_consumption_score)), "hull", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(hull)), "gun_power", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gun_power)), diff --git a/src/openvic-simulation/units/Unit.hpp b/src/openvic-simulation/units/Unit.hpp index 3555cce..65e6259 100644 --- a/src/openvic-simulation/units/Unit.hpp +++ b/src/openvic-simulation/units/Unit.hpp @@ -14,8 +14,9 @@ fixed_point_t maximum_speed, fixed_point_t weighted_value, Timespan build_time, \ std::map build_cost, fixed_point_t supply_consumption, \ std::map supply_cost -#define LAND_PARAMS fixed_point_t reconnaissance, fixed_point_t attack, fixed_point_t defence, fixed_point_t discipline, \ - fixed_point_t support, fixed_point_t maneuver, fixed_point_t siege +#define LAND_PARAMS bool primary_culture, std::string_view sprite_override, std::string_view sprite_mount, \ + std::string_view sprite_mount_attach_node, fixed_point_t reconnaissance, fixed_point_t attack, \ + fixed_point_t defence, fixed_point_t discipline, fixed_point_t support, fixed_point_t maneuver, fixed_point_t siege #define NAVY_PARAMS Unit::icon_t naval_icon, bool sail, bool transport, bool capital, std::string_view move_sound, \ std::string_view select_sound, fixed_point_t colonial_points, bool build_overseas, uint32_t min_port_level, \ int32_t limit_per_port, fixed_point_t supply_consumption_score, fixed_point_t hull, fixed_point_t gun_power, \ @@ -77,6 +78,8 @@ namespace OpenVic { friend struct UnitManager; private: + const bool primary_culture; + const std::string sprite_override, sprite_mount, sprite_mount_attach_node; const fixed_point_t reconnaissance; const fixed_point_t attack; const fixed_point_t defence; @@ -90,6 +93,11 @@ namespace OpenVic { public: LandUnit(LandUnit&&) = default; + bool get_primary_culture() const; + std::string const& get_sprite_override() const; + std::string const& get_sprite_mount() const; + std::string const& get_sprite_mount_attach_node() const; + fixed_point_t get_reconnaissance() const; fixed_point_t get_attack() const; fixed_point_t get_defence() const; @@ -156,7 +164,7 @@ namespace OpenVic { bool add_land_unit(std::string_view identifier, UNIT_PARAMS, LAND_PARAMS); bool add_naval_unit(std::string_view identifier, UNIT_PARAMS, NAVY_PARAMS); - IDENTIFIER_REGISTRY_ACCESSORS(Unit, unit) + IDENTIFIER_REGISTRY_ACCESSORS(unit) bool load_unit_file(GoodManager const& good_manager, ast::NodeCPtr root); }; diff --git a/src/openvic-simulation/utility/Logger.hpp b/src/openvic-simulation/utility/Logger.hpp index c7b8c51..55e0862 100644 --- a/src/openvic-simulation/utility/Logger.hpp +++ b/src/openvic-simulation/utility/Logger.hpp @@ -49,7 +49,8 @@ namespace OpenVic { log(log_func_t log_func, log_queue_t& log_queue, Ts&&... ts, source_location const& location) { std::stringstream stream; stream << "\n" << get_filename(location.file_name()) << "(" - << location.line() << ") `" << location.function_name() << "`: "; + //<< location.line() << ") `" << location.function_name() << "`: "; + << location.line() << "): "; ((stream << std::forward(ts)), ...); stream << std::endl; log_queue.push(stream.str()); -- cgit v1.2.3-56-ga3b1 From 6b3d2315225468e03bef30e942263fe9b8fc06fa Mon Sep 17 00:00:00 2001 From: hop311 Date: Thu, 12 Oct 2023 23:05:49 +0100 Subject: Further cleanup and rearrangement --- deps/lexy-vdf | 2 +- deps/openvic-dataloader | 2 +- scripts | 2 +- src/openvic-simulation/GameManager.cpp | 92 +----- src/openvic-simulation/GameManager.hpp | 51 +--- src/openvic-simulation/Modifier.cpp | 14 +- src/openvic-simulation/Modifier.hpp | 32 +- src/openvic-simulation/dataloader/Dataloader.cpp | 59 ++-- src/openvic-simulation/dataloader/Dataloader.hpp | 1 + src/openvic-simulation/economy/Building.cpp | 292 ++++++++++++++++++ src/openvic-simulation/economy/Building.hpp | 174 +++++++++++ src/openvic-simulation/economy/EconomyManager.hpp | 26 ++ src/openvic-simulation/economy/ProductionType.cpp | 4 +- src/openvic-simulation/economy/ProductionType.hpp | 4 +- src/openvic-simulation/map/Building.cpp | 292 ------------------ src/openvic-simulation/map/Building.hpp | 174 ----------- src/openvic-simulation/map/Map.cpp | 2 +- src/openvic-simulation/map/Map.hpp | 2 +- src/openvic-simulation/map/Province.hpp | 3 +- .../military/MilitaryManager.hpp | 12 + src/openvic-simulation/military/Unit.cpp | 338 +++++++++++++++++++++ src/openvic-simulation/military/Unit.hpp | 171 +++++++++++ src/openvic-simulation/politics/Government.hpp | 2 +- .../politics/PoliticsManager.hpp | 22 ++ .../testing/test_scripts/A_002_economy_tests.cpp | 2 +- .../types/IdentifierRegistry.hpp | 12 +- src/openvic-simulation/units/Unit.cpp | 338 --------------------- src/openvic-simulation/units/Unit.hpp | 171 ----------- 28 files changed, 1140 insertions(+), 1156 deletions(-) create mode 100644 src/openvic-simulation/economy/Building.cpp create mode 100644 src/openvic-simulation/economy/Building.hpp create mode 100644 src/openvic-simulation/economy/EconomyManager.hpp delete mode 100644 src/openvic-simulation/map/Building.cpp delete mode 100644 src/openvic-simulation/map/Building.hpp create mode 100644 src/openvic-simulation/military/MilitaryManager.hpp create mode 100644 src/openvic-simulation/military/Unit.cpp create mode 100644 src/openvic-simulation/military/Unit.hpp create mode 100644 src/openvic-simulation/politics/PoliticsManager.hpp delete mode 100644 src/openvic-simulation/units/Unit.cpp delete mode 100644 src/openvic-simulation/units/Unit.hpp diff --git a/deps/lexy-vdf b/deps/lexy-vdf index eeb1028..96c316c 160000 --- a/deps/lexy-vdf +++ b/deps/lexy-vdf @@ -1 +1 @@ -Subproject commit eeb10288f707cdc87981b43edc441fc833b6cff1 +Subproject commit 96c316c52b45e2fa78a9562938f931f972474518 diff --git a/deps/openvic-dataloader b/deps/openvic-dataloader index 4009e1d..92c67f3 160000 --- a/deps/openvic-dataloader +++ b/deps/openvic-dataloader @@ -1 +1 @@ -Subproject commit 4009e1d576ad177aff59c8fce0339963303fc6e5 +Subproject commit 92c67f318114771999a73b05659023b59b103e06 diff --git a/scripts b/scripts index 3060e56..accb77a 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit 3060e56388ac00d90deb6693ec19d47bad52deb2 +Subproject commit accb77a0af7d200818d4521b12492c078e4b7f42 diff --git a/src/openvic-simulation/GameManager.cpp b/src/openvic-simulation/GameManager.cpp index 69adaac..1c4efb3 100644 --- a/src/openvic-simulation/GameManager.cpp +++ b/src/openvic-simulation/GameManager.cpp @@ -6,94 +6,6 @@ GameManager::GameManager(state_updated_func_t state_updated_callback) : clock { [this]() { tick(); }, [this]() { update_state(); } }, state_updated { state_updated_callback } {} -Map& GameManager::get_map() { - return map; -} - -Map const& GameManager::get_map() const { - return map; -} - -BuildingManager& GameManager::get_building_manager() { - return building_manager; -} - -BuildingManager const& GameManager::get_building_manager() const { - return building_manager; -} - -GoodManager& GameManager::get_good_manager() { - return good_manager; -} - -GoodManager const& GameManager::get_good_manager() const { - return good_manager; -} - -GovernmentTypeManager& GameManager::get_government_type_manager() { - return government_type_manager; -} - -GovernmentTypeManager const& GameManager::get_government_type_manager() const { - return government_type_manager; -} - -PopManager& GameManager::get_pop_manager() { - return pop_manager; -} - -PopManager const& GameManager::get_pop_manager() const { - return pop_manager; -} - -IdeologyManager& GameManager::get_ideology_manager() { - return ideology_manager; -} - -IdeologyManager const& GameManager::get_ideology_manager() const { - return ideology_manager; -} - -IssueManager& GameManager::get_issue_manager() { - return issue_manager; -} - -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; -} - -UnitManager const& GameManager::get_unit_manager() const { - return unit_manager; -} - -ModifierManager& GameManager::get_modifier_manager() { - return modifier_manager; -} - -ModifierManager const& GameManager::get_modifier_manager() const { - return modifier_manager; -} - -GameAdvancementHook& GameManager::get_clock() { - return clock; -} - -GameAdvancementHook const& GameManager::get_clock() const { - return clock; -} - void GameManager::set_needs_update() { needs_update = true; } @@ -120,8 +32,8 @@ bool GameManager::setup() { session_start = time(nullptr); clock.reset(); today = { 1836 }; - good_manager.reset_to_defaults(); - bool ret = map.setup(good_manager, building_manager, pop_manager); + economy_manager.get_good_manager().reset_to_defaults(); + bool ret = map.setup(economy_manager.get_building_manager(), pop_manager); set_needs_update(); return ret; } diff --git a/src/openvic-simulation/GameManager.hpp b/src/openvic-simulation/GameManager.hpp index 8982e21..6e6c0b8 100644 --- a/src/openvic-simulation/GameManager.hpp +++ b/src/openvic-simulation/GameManager.hpp @@ -1,13 +1,11 @@ #pragma once #include "openvic-simulation/GameAdvancementHook.hpp" -#include "openvic-simulation/economy/Good.hpp" -#include "openvic-simulation/politics/Government.hpp" -#include "openvic-simulation/economy/ProductionType.hpp" +#include "openvic-simulation/Modifier.hpp" +#include "openvic-simulation/economy/EconomyManager.hpp" #include "openvic-simulation/map/Map.hpp" -#include "openvic-simulation/politics/Ideology.hpp" -#include "openvic-simulation/politics/Issue.hpp" -#include "openvic-simulation/units/Unit.hpp" +#include "openvic-simulation/military/MilitaryManager.hpp" +#include "openvic-simulation/politics/PoliticsManager.hpp" namespace OpenVic { struct GameManager { @@ -15,15 +13,11 @@ namespace OpenVic { private: Map map; - BuildingManager building_manager; - GoodManager good_manager; - GovernmentTypeManager government_type_manager; - PopManager pop_manager; - IdeologyManager ideology_manager; - IssueManager issue_manager; - ProductionTypeManager production_type_manager; - UnitManager unit_manager; + EconomyManager economy_manager; + MilitaryManager military_manager; ModifierManager modifier_manager; + PoliticsManager politics_manager; + PopManager pop_manager; GameAdvancementHook clock; time_t session_start; /* SS-54, as well as allowing time-tracking */ @@ -38,28 +32,13 @@ namespace OpenVic { public: GameManager(state_updated_func_t state_updated_callback); - Map& get_map(); - Map const& get_map() const; - BuildingManager& get_building_manager(); - BuildingManager const& get_building_manager() const; - GoodManager& get_good_manager(); - GoodManager const& get_good_manager() const; - GovernmentTypeManager& get_government_type_manager(); - GovernmentTypeManager const& get_government_type_manager() const; - PopManager& get_pop_manager(); - PopManager const& get_pop_manager() const; - IdeologyManager& get_ideology_manager(); - 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; - ModifierManager& get_modifier_manager(); - ModifierManager const& get_modifier_manager() const; - GameAdvancementHook& get_clock(); - GameAdvancementHook const& get_clock() const; + REF_GETTERS(map) + REF_GETTERS(economy_manager) + REF_GETTERS(military_manager) + REF_GETTERS(modifier_manager) + REF_GETTERS(politics_manager) + REF_GETTERS(pop_manager) + REF_GETTERS(clock) bool setup(); diff --git a/src/openvic-simulation/Modifier.cpp b/src/openvic-simulation/Modifier.cpp index 5aadd79..4e5b860 100644 --- a/src/openvic-simulation/Modifier.cpp +++ b/src/openvic-simulation/Modifier.cpp @@ -131,7 +131,7 @@ bool ModifierManager::setup_modifier_effects() { return ret; } -node_callback_t ModifierManager::expect_modifier_value(callback_t modifier_callback, key_value_callback_t default_callback) const { +node_callback_t ModifierManager::expect_modifier_value_and_default(callback_t modifier_callback, key_value_callback_t default_callback) const { return [this, modifier_callback, default_callback](ast::NodeCPtr root) -> bool { ModifierValue modifier; bool ret = expect_dictionary( @@ -154,9 +154,13 @@ node_callback_t ModifierManager::expect_modifier_value(callback_t modifier_callback, key_map_t&& key_map) const { +node_callback_t ModifierManager::expect_modifier_value(callback_t modifier_callback) const { + return expect_modifier_value_and_default(modifier_callback, key_value_invalid_callback); +} + +node_callback_t ModifierManager::expect_modifier_value_and_key_map_and_default(callback_t modifier_callback, key_value_callback_t default_callback, key_map_t&& key_map) const { return [this, modifier_callback, key_map = std::move(key_map)](ast::NodeCPtr node) mutable -> bool { - bool ret = expect_modifier_value( + bool ret = expect_modifier_value_and_default( modifier_callback, dictionary_keys_callback(key_map, key_value_invalid_callback) )(node); ret &= check_key_map_counts(key_map); @@ -164,6 +168,10 @@ node_callback_t ModifierManager::_expect_modifier_value_and_keys(callback_t modifier_callback, key_map_t&& key_map) const { + return expect_modifier_value_and_key_map_and_default(modifier_callback, key_value_invalid_callback, std::move(key_map)); +} + namespace OpenVic { //so the compiler shuts up std::ostream& operator<<(std::ostream& stream, ModifierValue const& value) { for (ModifierValue::effect_map_t::value_type const& effect : value.values) { diff --git a/src/openvic-simulation/Modifier.hpp b/src/openvic-simulation/Modifier.hpp index 0c4e636..2e1b03a 100644 --- a/src/openvic-simulation/Modifier.hpp +++ b/src/openvic-simulation/Modifier.hpp @@ -92,17 +92,6 @@ namespace OpenVic { IdentifierRegistry modifier_effects; IdentifierRegistry modifiers; - NodeTools::node_callback_t _expect_modifier_value_and_keys(NodeTools::callback_t modifier_callback, NodeTools::key_map_t&& key_map) const; - - template - NodeTools::node_callback_t _expect_modifier_value_and_keys( - NodeTools::callback_t modifier_callback, NodeTools::key_map_t&& key_map, - std::string_view key, NodeTools::dictionary_entry_t::expected_count_t expected_count, NodeTools::node_callback_t callback, - Args... args) const { - NodeTools::add_key_map_entry(key_map, key, expected_count, callback); - return _expect_modifier_value_and_keys(modifier_callback, std::move(key_map), args...); - } - public: ModifierManager(); @@ -114,11 +103,28 @@ namespace OpenVic { bool setup_modifier_effects(); - NodeTools::node_callback_t expect_modifier_value(NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback) const; + NodeTools::node_callback_t expect_modifier_value_and_default(NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback) const; + NodeTools::node_callback_t expect_modifier_value(NodeTools::callback_t modifier_callback) const; + + NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default(NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback, NodeTools::key_map_t&& key_map) const; + NodeTools::node_callback_t expect_modifier_value_and_key_map(NodeTools::callback_t modifier_callback, NodeTools::key_map_t&& key_map) const; + template + NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default( + NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback, NodeTools::key_map_t&& key_map, + std::string_view key, NodeTools::dictionary_entry_t::expected_count_t expected_count, NodeTools::node_callback_t callback, + Args... args) const { + NodeTools::add_key_map_entry(key_map, key, expected_count, callback); + return expect_modifier_value_and_key_map_and_default(modifier_callback, default_callback, std::move(key_map), args...); + } + + template + NodeTools::node_callback_t expect_modifier_value_and_keys_and_default(NodeTools::callback_t modifier_callback, NodeTools::key_value_callback_t default_callback, Args... args) const { + return expect_modifier_value_and_key_map_and_default(modifier_callback, default_callback, {}, args...); + } template NodeTools::node_callback_t expect_modifier_value_and_keys(NodeTools::callback_t modifier_callback, Args... args) const { - return _expect_modifier_value_and_keys(modifier_callback, {}, args...); + return expect_modifier_value_and_key_map_and_default(modifier_callback, NodeTools::key_value_invalid_callback, {}, args...); } }; } diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index bd634ce..718218f 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -436,6 +436,14 @@ v2script::Parser Dataloader::parse_defines(fs::path const& path) { return _run_ovdl_parser(path); } +static bool _lua_parse(v2script::Parser& parser) { + return parser.lua_defines_parse(); +} + +static ovdl::v2script::Parser parse_lua_defines(fs::path const& path) { + return _run_ovdl_parser(path); +} + static bool _csv_parse(csv::Windows1252Parser& parser) { return parser.parse_csv(); } @@ -527,17 +535,20 @@ bool Dataloader::_load_map_dir(GameManager& game_manager, fs::path const& map_di Logger::error("Failed to load map default file!"); } - if (!map.load_province_definitions(parse_csv(lookup_file(map_directory / definitions)).get_lines())) { + if (!map.load_province_definitions( + parse_csv(lookup_file(map_directory / definitions)).get_lines())) { Logger::error("Failed to load province definitions file!"); ret = false; } - if (!map.load_province_positions(game_manager.get_building_manager(), parse_defines(lookup_file(map_directory / positions)).get_file_node())) { + if (!map.load_province_positions( + game_manager.get_economy_manager().get_building_manager(), parse_defines(lookup_file(map_directory / positions)).get_file_node())) { Logger::error("Failed to load province positions file!"); ret = false; } - if (!map.load_region_file(parse_defines(lookup_file(map_directory / region)).get_file_node())) { + if (!map.load_region_file( + parse_defines(lookup_file(map_directory / region)).get_file_node())) { Logger::error("Failed to load region file!"); ret = false; } @@ -547,17 +558,22 @@ bool Dataloader::_load_map_dir(GameManager& game_manager, fs::path const& map_di ret = false; } - if (!map.get_terrain_type_manager().load_terrain_types(game_manager.get_modifier_manager(), parse_defines(lookup_file(map_directory / terrain_definition)).get_file_node())) { + if (!map.get_terrain_type_manager().load_terrain_types( + game_manager.get_modifier_manager(), + parse_defines(lookup_file(map_directory / terrain_definition)).get_file_node())) { Logger::error("Failed to load terrain types!"); ret = false; } - if (!map.load_map_images(lookup_file(map_directory / provinces), lookup_file(map_directory / terrain), false)) { + if (!map.load_map_images( + lookup_file(map_directory / provinces), + lookup_file(map_directory / terrain), false)) { Logger::error("Failed to load map images!"); ret = false; } - if (!map.generate_and_load_province_adjacencies(parse_csv(lookup_file(map_directory / adjacencies)).get_lines())) { + if (!map.generate_and_load_province_adjacencies( + parse_csv(lookup_file(map_directory / adjacencies)).get_lines())) { Logger::error("Failed to generate and load province adjacencies!"); ret = false; } @@ -586,7 +602,8 @@ bool Dataloader::load_defines(GameManager& game_manager) const { Logger::error("Failed to set up modifier effects!"); ret = false; } - if (!game_manager.get_good_manager().load_goods_file(parse_defines(lookup_file(goods_file)).get_file_node())) { + if (!game_manager.get_economy_manager().get_good_manager().load_goods_file( + parse_defines(lookup_file(goods_file)).get_file_node())) { Logger::error("Failed to load goods!"); ret = false; } @@ -594,40 +611,43 @@ bool Dataloader::load_defines(GameManager& game_manager) const { Logger::error("Failed to load pop types!"); ret = false; } - if (!game_manager.get_pop_manager().get_culture_manager().load_graphical_culture_type_file(parse_defines(lookup_file(graphical_culture_type_file)).get_file_node())) { + if (!game_manager.get_pop_manager().get_culture_manager().load_graphical_culture_type_file( + parse_defines(lookup_file(graphical_culture_type_file)).get_file_node())) { Logger::error("Failed to load graphical culture types!"); ret = false; } - if (!game_manager.get_pop_manager().get_culture_manager().load_culture_file(parse_defines(lookup_file(culture_file)).get_file_node())) { + if (!game_manager.get_pop_manager().get_culture_manager().load_culture_file( + parse_defines(lookup_file(culture_file)).get_file_node())) { Logger::error("Failed to load cultures!"); ret = false; } - if (!game_manager.get_pop_manager().get_religion_manager().load_religion_file(parse_defines(lookup_file(religion_file)).get_file_node())) { + if (!game_manager.get_pop_manager().get_religion_manager().load_religion_file( + parse_defines(lookup_file(religion_file)).get_file_node())) { Logger::error("Failed to load religions!"); ret = false; } - if (!game_manager.get_ideology_manager().load_ideology_file(parse_defines(lookup_file(ideology_file)).get_file_node())) { + if (!game_manager.get_politics_manager().get_ideology_manager().load_ideology_file( + parse_defines(lookup_file(ideology_file)).get_file_node())) { Logger::error("Failed to load ideologies!"); ret = false; } - if (!game_manager.get_government_type_manager().load_government_types_file(game_manager.get_ideology_manager(), parse_defines(lookup_file(governments_file)).get_file_node())) { + if (!game_manager.get_politics_manager().load_government_types_file( + parse_defines(lookup_file(governments_file)).get_file_node())) { Logger::error("Failed to load government types!"); ret = false; } - if (!game_manager.get_issue_manager().load_issues_file(parse_defines(lookup_file(issues_file)).get_file_node())) { + if (!game_manager.get_politics_manager().get_issue_manager().load_issues_file( + parse_defines(lookup_file(issues_file)).get_file_node())) { Logger::error("Failed to load issues!"); ret = false; } - if (!game_manager.get_production_type_manager().load_production_types_file( - game_manager.get_good_manager(), + if (!game_manager.get_economy_manager().load_production_types_file( 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 (!game_manager.get_building_manager().load_buildings_file( - game_manager.get_good_manager(), - game_manager.get_production_type_manager(), + if (!game_manager.get_economy_manager().load_buildings_file( game_manager.get_modifier_manager(), parse_defines(lookup_file(buildings_file)).get_file_node())) { Logger::error("Failed to load buildings!"); @@ -637,7 +657,8 @@ bool Dataloader::load_defines(GameManager& game_manager) const { Logger::error("Failed to load map!"); ret = false; } - if (!_load_units(game_manager.get_unit_manager(), game_manager.get_good_manager(), units_directory)) { + if (!_load_units(game_manager.get_military_manager().get_unit_manager(), + game_manager.get_economy_manager().get_good_manager(), units_directory)) { Logger::error("Failed to load units!"); ret = false; } diff --git a/src/openvic-simulation/dataloader/Dataloader.hpp b/src/openvic-simulation/dataloader/Dataloader.hpp index 30eed6e..c4cd7c7 100644 --- a/src/openvic-simulation/dataloader/Dataloader.hpp +++ b/src/openvic-simulation/dataloader/Dataloader.hpp @@ -29,6 +29,7 @@ namespace OpenVic { public: static ovdl::v2script::Parser parse_defines(fs::path const& path); + static ovdl::v2script::Parser parse_lua_defines(fs::path const& path); static ovdl::csv::Windows1252Parser parse_csv(fs::path const& path); Dataloader() = default; diff --git a/src/openvic-simulation/economy/Building.cpp b/src/openvic-simulation/economy/Building.cpp new file mode 100644 index 0000000..d27c91a --- /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 const& 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 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 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(today - start) / static_cast(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 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 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..3f74c3d --- /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 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 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 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 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 const& get_on_completion() const; + fixed_point_t get_completion_size() const; + level_t get_max_level() const; + std::map 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 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 building_types; + IdentifierRegistry 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/ProductionType.cpp b/src/openvic-simulation/economy/ProductionType.cpp index b2d94c3..01d45be 100644 --- a/src/openvic-simulation/economy/ProductionType.cpp +++ b/src/openvic-simulation/economy/ProductionType.cpp @@ -138,7 +138,7 @@ node_callback_t ProductionTypeManager::_expect_employed_pop_list(GoodManager con 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; @@ -186,7 +186,7 @@ bool ProductionTypeManager::add_production_type(PRODUCTION_TYPE_ARGS, GoodManage "mine", ZERO_OR_ONE, expect_bool(assign_variable_callback(mine)) \ ) -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 diff --git a/src/openvic-simulation/economy/ProductionType.hpp b/src/openvic-simulation/economy/ProductionType.hpp index fdb0010..420e70e 100644 --- a/src/openvic-simulation/economy/ProductionType.hpp +++ b/src/openvic-simulation/economy/ProductionType.hpp @@ -103,9 +103,9 @@ namespace OpenVic { public: ProductionTypeManager(); - bool add_production_type(PRODUCTION_TYPE_ARGS, GoodManager& good_manager); + 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 diff --git a/src/openvic-simulation/map/Building.cpp b/src/openvic-simulation/map/Building.cpp deleted file mode 100644 index d27c91a..0000000 --- a/src/openvic-simulation/map/Building.cpp +++ /dev/null @@ -1,292 +0,0 @@ -#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 const& 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 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 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(today - start) / static_cast(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 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 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/map/Building.hpp b/src/openvic-simulation/map/Building.hpp deleted file mode 100644 index 3f74c3d..0000000 --- a/src/openvic-simulation/map/Building.hpp +++ /dev/null @@ -1,174 +0,0 @@ -#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 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 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 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 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 const& get_on_completion() const; - fixed_point_t get_completion_size() const; - level_t get_max_level() const; - std::map 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 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 building_types; - IdentifierRegistry 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/map/Map.cpp b/src/openvic-simulation/map/Map.cpp index 8362ff4..acd882e 100644 --- a/src/openvic-simulation/map/Map.cpp +++ b/src/openvic-simulation/map/Map.cpp @@ -276,7 +276,7 @@ Pop::pop_size_t Map::get_total_map_population() const { return total_map_population; } -bool Map::setup(GoodManager const& good_manager, BuildingManager const& building_manager, PopManager const& pop_manager) { +bool Map::setup(BuildingManager const& building_manager, PopManager const& pop_manager) { bool ret = true; for (Province& province : provinces.get_items()) { province.clear_pops(); diff --git a/src/openvic-simulation/map/Map.hpp b/src/openvic-simulation/map/Map.hpp index a959158..578b471 100644 --- a/src/openvic-simulation/map/Map.hpp +++ b/src/openvic-simulation/map/Map.hpp @@ -102,7 +102,7 @@ namespace OpenVic { static constexpr size_t MAPMODE_COLOUR_SIZE = 4; bool generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) const; - bool setup(GoodManager const& good_manager, BuildingManager const& building_manager, PopManager const& pop_manager); + bool setup(BuildingManager const& building_manager, PopManager const& pop_manager); void update_highest_province_population(); Pop::pop_size_t get_highest_province_population() const; diff --git a/src/openvic-simulation/map/Province.hpp b/src/openvic-simulation/map/Province.hpp index c9b29ea..d925898 100644 --- a/src/openvic-simulation/map/Province.hpp +++ b/src/openvic-simulation/map/Province.hpp @@ -2,7 +2,7 @@ #include -#include "openvic-simulation/map/Building.hpp" +#include "openvic-simulation/economy/Building.hpp" #include "openvic-simulation/pop/Pop.hpp" namespace OpenVic { @@ -55,7 +55,6 @@ namespace OpenVic { fvec2_t navalbase; fixed_point_t navalbase_rotation; }; - static constexpr index_t NULL_INDEX = 0, MAX_INDEX = std::numeric_limits::max(); diff --git a/src/openvic-simulation/military/MilitaryManager.hpp b/src/openvic-simulation/military/MilitaryManager.hpp new file mode 100644 index 0000000..36b5010 --- /dev/null +++ b/src/openvic-simulation/military/MilitaryManager.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "openvic-simulation/military/Unit.hpp" + +namespace OpenVic { + struct MilitaryManager { + private: + UnitManager unit_manager; + public: + REF_GETTERS(unit_manager) + }; +} diff --git a/src/openvic-simulation/military/Unit.cpp b/src/openvic-simulation/military/Unit.cpp new file mode 100644 index 0000000..3da24da --- /dev/null +++ b/src/openvic-simulation/military/Unit.cpp @@ -0,0 +1,338 @@ +#include "Unit.hpp" + +#include + +#define UNIT_ARGS icon, sprite, active, unit_type, floating_flag, priority, max_strength, \ + default_organisation, maximum_speed, weighted_value, build_time, build_cost, supply_consumption, \ + supply_cost +#define LAND_ARGS primary_culture, sprite_override, sprite_mount, sprite_mount_attach_node, \ + reconnaissance, attack, defence, discipline, support, maneuver, siege +#define NAVY_ARGS naval_icon, sail, transport, capital, move_sound, select_sound, colonial_points, build_overseas, min_port_level, \ + limit_per_port, supply_consumption_score, hull, gun_power, fire_range, evasion, torpedo_attack + +using namespace OpenVic; +using namespace OpenVic::NodeTools; + +Unit::Unit(std::string_view identifier, type_t type, UNIT_PARAMS) : HasIdentifier { identifier }, + icon { icon }, type { type }, sprite { sprite }, active { active }, unit_type { unit_type }, + floating_flag { floating_flag }, priority { priority }, max_strength { max_strength }, + default_organisation { default_organisation }, maximum_speed { maximum_speed }, weighted_value { weighted_value }, + build_time { build_time }, build_cost { build_cost }, supply_consumption { supply_consumption }, supply_cost { supply_cost } {} + +Unit::icon_t Unit::get_icon() const { + return icon; +} + +Unit::type_t Unit::get_type() const { + return type; +} + +std::string const& Unit::get_sprite() const { + return sprite; +} + +bool Unit::is_active() const { + return active; +} + +std::string const& Unit::get_unit_type() const { + return unit_type; +} + +bool Unit::has_floating_flag() const { + return floating_flag; +} + +uint32_t Unit::get_priority() const { + return priority; +} + +fixed_point_t Unit::get_max_strength() const { + return max_strength; +} + +fixed_point_t Unit::get_default_organisation() const { + return default_organisation; +} + +fixed_point_t Unit::get_maximum_speed() const { + return maximum_speed; +} + +Timespan Unit::get_build_time() const { + return build_time; +} + +fixed_point_t Unit::get_weighted_value() const { + return weighted_value; +} + +std::map const& Unit::get_build_cost() const { + return build_cost; +} + +fixed_point_t Unit::get_supply_consumption() const { + return supply_consumption; +} + +std::map const& Unit::get_supply_cost() const { + return supply_cost; +} + +LandUnit::LandUnit(std::string_view identifier, UNIT_PARAMS, LAND_PARAMS) + : Unit { identifier, type_t::LAND, UNIT_ARGS }, primary_culture { primary_culture }, sprite_override { sprite_override }, + sprite_mount { sprite_mount }, sprite_mount_attach_node { sprite_mount_attach_node }, reconnaissance { reconnaissance }, + attack { attack }, defence { defence }, discipline { discipline }, support { support }, maneuver { maneuver }, siege { siege } {} + +bool LandUnit::get_primary_culture() const { + return primary_culture; +} + +std::string const& LandUnit::get_sprite_override() const { + return sprite_override; +} + +std::string const& LandUnit::get_sprite_mount() const { + return sprite_mount; +} + +std::string const& LandUnit::get_sprite_mount_attach_node() const { + return sprite_mount_attach_node; +} + +fixed_point_t LandUnit::get_reconnaissance() const { + return reconnaissance; +} + +fixed_point_t LandUnit::get_attack() const { + return attack; +} + +fixed_point_t LandUnit::get_defence() const { + return defence; +} + +fixed_point_t LandUnit::get_discipline() const { + return discipline; +} + +fixed_point_t LandUnit::get_support() const { + return support; +} + +fixed_point_t LandUnit::get_maneuver() const { + return maneuver; +} + +fixed_point_t LandUnit::get_siege() const { + return siege; +} + +NavalUnit::NavalUnit(std::string_view identifier, UNIT_PARAMS, NAVY_PARAMS) : Unit { identifier, type_t::NAVAL, UNIT_ARGS }, + naval_icon { naval_icon }, sail { sail }, transport { transport }, capital { capital }, move_sound { move_sound }, + select_sound { select_sound }, colonial_points { colonial_points }, build_overseas { build_overseas }, + min_port_level { min_port_level }, limit_per_port { limit_per_port }, supply_consumption_score { supply_consumption_score }, + hull { hull }, gun_power { gun_power }, fire_range { fire_range }, evasion { evasion }, torpedo_attack { torpedo_attack } {}; + +NavalUnit::icon_t NavalUnit::get_naval_icon() const { + return naval_icon; +} + +bool NavalUnit::can_sail() const { + return sail; +} + +bool NavalUnit::is_transport() const { + return transport; +} + +std::string const& NavalUnit::get_move_sound() const { + return move_sound; +} + +std::string const& NavalUnit::get_select_sound() const { + return select_sound; +} + +fixed_point_t NavalUnit::get_colonial_points() const { + return colonial_points; +} + +bool NavalUnit::can_build_overseas() const { + return build_overseas; +} + +uint32_t NavalUnit::get_min_port_level() const { + return min_port_level; +} + +int32_t NavalUnit::get_limit_per_port() const { + return limit_per_port; +} + +fixed_point_t NavalUnit::get_supply_consumption_score() const { + return supply_consumption_score; +} + +fixed_point_t NavalUnit::get_hull() const { + return hull; +} + +fixed_point_t NavalUnit::get_gun_power() const { + return gun_power; +} + +fixed_point_t NavalUnit::get_fire_range() const { + return fire_range; +} + +fixed_point_t NavalUnit::get_evasion() const { + return evasion; +} + +fixed_point_t NavalUnit::get_torpedo_attack() const { + return torpedo_attack; +} + +UnitManager::UnitManager() : units { "units" } {} + +bool UnitManager::_check_shared_parameters(std::string_view identifier, UNIT_PARAMS) { + if (identifier.empty()) { + Logger::error("Invalid religion identifier - empty!"); + return false; + } + + if (sprite.empty()) { + Logger::error("Invalid sprite identifier - empty!"); + return false; + } + + if (unit_type.empty()) { + Logger::error("Invalid unit type - empty!"); + return false; + } + + //TODO check that icon and sprite exist + + return true; +} + +bool UnitManager::add_land_unit(std::string_view identifier, UNIT_PARAMS, LAND_PARAMS) { + if (!_check_shared_parameters(identifier, UNIT_ARGS)) { + return false; + } + + return units.add_item(LandUnit { identifier, UNIT_ARGS, LAND_ARGS }); +} + +bool UnitManager::add_naval_unit(std::string_view identifier, UNIT_PARAMS, NAVY_PARAMS) { + if (!_check_shared_parameters(identifier, UNIT_ARGS)) { + return false; + } + + //TODO: check that icon and sounds exist + + return units.add_item(NavalUnit { identifier, UNIT_ARGS, NAVY_ARGS }); +} + +static bool shared_keys_callback(std::string_view key, ast::NodeCPtr) { + static const std::set> reserved_keys = { + "icon", "type", "sprite", "active", "unit_type", "floating_flag", "priority", + "max_strength", "default_organisation", "maximum_speed", "weighted_value", + "build_time", "build_cost", "supply_consumption", "supply_cost" + }; + if (reserved_keys.contains(key)) return true; + Logger::error("Invalid key: ", key); + return false; +}; + +bool UnitManager::load_unit_file(GoodManager const& good_manager, ast::NodeCPtr root) { + return expect_dictionary([this, &good_manager](std::string_view key, ast::NodeCPtr value) -> bool { + Unit::icon_t icon = 0; + std::string_view type, unit_type, sprite; + bool active = true, floating_flag = false; + uint32_t priority = 0; + Timespan build_time; + fixed_point_t maximum_speed = 0, max_strength = 0, default_organisation = 0, weighted_value = 0, supply_consumption = 0; + std::map build_cost, supply_cost; + + //shared + bool ret = expect_dictionary_keys_and_default( + key_value_success_callback, + "icon", ONE_EXACTLY, expect_uint(assign_variable_callback(icon)), + "type", ONE_EXACTLY, expect_identifier(assign_variable_callback(type)), + "sprite", ONE_EXACTLY, expect_identifier(assign_variable_callback(sprite)), + "active", ZERO_OR_ONE, expect_bool(assign_variable_callback(active)), + "unit_type", ONE_EXACTLY, expect_identifier(assign_variable_callback(unit_type)), + "floating_flag", ONE_EXACTLY, expect_bool(assign_variable_callback(floating_flag)), + "priority", ONE_EXACTLY, expect_uint(assign_variable_callback(priority)), + "max_strength", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_strength)), + "default_organisation", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(default_organisation)), + "maximum_speed", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(maximum_speed)), + "weighted_value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(weighted_value)), + "build_time", ONE_EXACTLY, expect_days(assign_variable_callback(build_time)), + "build_cost", ONE_EXACTLY, good_manager.expect_good_decimal_map(move_variable_callback(build_cost)), + "supply_consumption", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(supply_consumption)), + "supply_cost", ONE_EXACTLY, good_manager.expect_good_decimal_map(move_variable_callback(supply_cost)) + )(value); + + if (type == "land") { + bool primary_culture = false; + std::string_view sprite_override, sprite_mount, sprite_mount_attach_node; + fixed_point_t reconnaissance = 0, attack = 0, defence = 0, discipline = 0, support = 0, maneuver = 0, siege = 0; + + ret &= expect_dictionary_keys_and_default( + shared_keys_callback, + "primary_culture", ZERO_OR_ONE, expect_bool(assign_variable_callback(primary_culture)), + "sprite_override", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_override)), + "sprite_mount", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_mount)), + "sprite_mount_attach_node", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_mount_attach_node)), + "reconnaissance", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(reconnaissance)), + "attack", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(attack)), + "defence", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(defence)), + "discipline", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(discipline)), + "support", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(support)), + "maneuver", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(maneuver)), + "siege", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(siege)) + )(value); + + ret &= add_land_unit(key, UNIT_ARGS, LAND_ARGS); + + return ret; + } else if (type == "naval") { + Unit::icon_t naval_icon = 0; + bool sail = false, transport = false, capital = false, build_overseas = false; + std::string_view move_sound, select_sound; //TODO defaults for both + uint32_t min_port_level = 0; + int32_t limit_per_port = 0; + fixed_point_t fire_range = 0, evasion = 0, supply_consumption_score = 0, hull = 0, gun_power = 0, colonial_points = 0, torpedo_attack = 0; + + ret &= expect_dictionary_keys_and_default( + shared_keys_callback, + "naval_icon", ONE_EXACTLY, expect_uint(assign_variable_callback(naval_icon)), + "sail", ZERO_OR_ONE, expect_bool(assign_variable_callback(sail)), + "transport", ZERO_OR_ONE, expect_bool(assign_variable_callback(transport)), + "capital", ZERO_OR_ONE, expect_bool(assign_variable_callback(capital)), + "move_sound", ZERO_OR_ONE, expect_identifier(assign_variable_callback(move_sound)), + "select_sound", ZERO_OR_ONE, expect_identifier(assign_variable_callback(select_sound)), + "colonial_points", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(colonial_points)), + "can_build_overseas", ZERO_OR_ONE, expect_bool(assign_variable_callback(build_overseas)), + "min_port_level", ONE_EXACTLY, expect_uint(assign_variable_callback(min_port_level)), + "limit_per_port", ONE_EXACTLY, expect_int(assign_variable_callback(limit_per_port)), + "supply_consumption_score", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(supply_consumption_score)), + "hull", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(hull)), + "gun_power", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gun_power)), + "fire_range", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(fire_range)), + "evasion", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(evasion)), + "torpedo_attack", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(torpedo_attack)) + )(value); + + ret &= add_naval_unit(key, UNIT_ARGS, NAVY_ARGS); + + return ret; + } else { + Logger::error("Invalid type for unit ", key, ": ", type); + return false; + } + })(root); +} \ No newline at end of file diff --git a/src/openvic-simulation/military/Unit.hpp b/src/openvic-simulation/military/Unit.hpp new file mode 100644 index 0000000..65e6259 --- /dev/null +++ b/src/openvic-simulation/military/Unit.hpp @@ -0,0 +1,171 @@ +#pragma once + +#include +#include +#include "openvic-simulation/economy/Good.hpp" +#include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/dataloader/NodeTools.hpp" +#include "openvic-simulation/economy/Good.hpp" +#include "openvic-simulation/types/Date.hpp" + +#define UNIT_PARAMS Unit::icon_t icon, std::string_view sprite, bool active, std::string_view unit_type, \ + bool floating_flag, uint32_t priority, fixed_point_t max_strength, fixed_point_t default_organisation, \ + fixed_point_t maximum_speed, fixed_point_t weighted_value, Timespan build_time, \ + std::map build_cost, fixed_point_t supply_consumption, \ + std::map supply_cost +#define LAND_PARAMS bool primary_culture, std::string_view sprite_override, std::string_view sprite_mount, \ + std::string_view sprite_mount_attach_node, fixed_point_t reconnaissance, fixed_point_t attack, \ + fixed_point_t defence, fixed_point_t discipline, fixed_point_t support, fixed_point_t maneuver, fixed_point_t siege +#define NAVY_PARAMS Unit::icon_t naval_icon, bool sail, bool transport, bool capital, std::string_view move_sound, \ + std::string_view select_sound, fixed_point_t colonial_points, bool build_overseas, uint32_t min_port_level, \ + int32_t limit_per_port, fixed_point_t supply_consumption_score, fixed_point_t hull, fixed_point_t gun_power, \ + fixed_point_t fire_range, fixed_point_t evasion, fixed_point_t torpedo_attack + +namespace OpenVic { + struct Unit : HasIdentifier { + using icon_t = uint32_t; + + enum struct type_t { + LAND, NAVAL + }; + + private: + const type_t type; + const icon_t icon; + const std::string sprite; + const bool active; + const std::string unit_type; + const bool floating_flag; + + const uint32_t priority; + const fixed_point_t max_strength; + const fixed_point_t default_organisation; + const fixed_point_t maximum_speed; + const fixed_point_t weighted_value; + + const Timespan build_time; + const std::map build_cost; + const fixed_point_t supply_consumption; + const std::map supply_cost; + + protected: + Unit(std::string_view identifier, type_t type, UNIT_PARAMS); + + public: + Unit(Unit&&) = default; + + icon_t get_icon() const; + type_t get_type() const; + std::string const& get_sprite() const; + bool is_active() const; + std::string const& get_unit_type() const; + bool has_floating_flag() const; + + uint32_t get_priority() const; + fixed_point_t get_max_strength() const; + fixed_point_t get_default_organisation() const; + fixed_point_t get_maximum_speed() const; + fixed_point_t get_weighted_value() const; + + Timespan get_build_time() const; + std::map const& get_build_cost() const; + fixed_point_t get_supply_consumption() const; + std::map const& get_supply_cost() const; + }; + + struct LandUnit : Unit { + friend struct UnitManager; + + private: + const bool primary_culture; + const std::string sprite_override, sprite_mount, sprite_mount_attach_node; + const fixed_point_t reconnaissance; + const fixed_point_t attack; + const fixed_point_t defence; + const fixed_point_t discipline; + const fixed_point_t support; + const fixed_point_t maneuver; + const fixed_point_t siege; + + LandUnit(std::string_view identifier, UNIT_PARAMS, LAND_PARAMS); + + public: + LandUnit(LandUnit&&) = default; + + bool get_primary_culture() const; + std::string const& get_sprite_override() const; + std::string const& get_sprite_mount() const; + std::string const& get_sprite_mount_attach_node() const; + + fixed_point_t get_reconnaissance() const; + fixed_point_t get_attack() const; + fixed_point_t get_defence() const; + fixed_point_t get_discipline() const; + fixed_point_t get_support() const; + fixed_point_t get_maneuver() const; + fixed_point_t get_siege() const; + }; + + struct NavalUnit : Unit { + friend struct UnitManager; + + private: + const icon_t naval_icon; + const bool sail; + const bool transport; + const bool capital; + const std::string move_sound; + const std::string select_sound; + const fixed_point_t colonial_points; + const bool build_overseas; + const uint32_t min_port_level; + const int32_t limit_per_port; + const fixed_point_t supply_consumption_score; + + const fixed_point_t hull; + const fixed_point_t gun_power; + const fixed_point_t fire_range; + const fixed_point_t evasion; + const fixed_point_t torpedo_attack; + + NavalUnit(std::string_view identifier, UNIT_PARAMS, NAVY_PARAMS); + + public: + NavalUnit(NavalUnit&&) = default; + + icon_t get_naval_icon() const; + bool can_sail() const; + bool is_transport() const; + bool is_capital() const; + std::string const& get_move_sound() const; + std::string const& get_select_sound() const; + fixed_point_t get_colonial_points() const; + bool can_build_overseas() const; + uint32_t get_min_port_level() const; + int32_t get_limit_per_port() const; + fixed_point_t get_supply_consumption_score() const; + + fixed_point_t get_hull() const; + fixed_point_t get_gun_power() const; + fixed_point_t get_fire_range() const; + fixed_point_t get_evasion() const; + fixed_point_t get_torpedo_attack() const; + }; + + struct UnitManager { + private: + IdentifierRegistry units; + + bool _check_shared_parameters(std::string_view identifier, UNIT_PARAMS); + + public: + UnitManager(); + + bool add_land_unit(std::string_view identifier, UNIT_PARAMS, LAND_PARAMS); + bool add_naval_unit(std::string_view identifier, UNIT_PARAMS, NAVY_PARAMS); + IDENTIFIER_REGISTRY_ACCESSORS(unit) + + bool load_unit_file(GoodManager const& good_manager, ast::NodeCPtr root); + }; +} \ No newline at end of file diff --git a/src/openvic-simulation/politics/Government.hpp b/src/openvic-simulation/politics/Government.hpp index 3bc754c..c72dae6 100644 --- a/src/openvic-simulation/politics/Government.hpp +++ b/src/openvic-simulation/politics/Government.hpp @@ -39,4 +39,4 @@ namespace OpenVic { bool load_government_types_file(IdeologyManager const& ideology_manager, ast::NodeCPtr root); }; -} // namespace OpenVic +} // namespace OpenVic diff --git a/src/openvic-simulation/politics/PoliticsManager.hpp b/src/openvic-simulation/politics/PoliticsManager.hpp new file mode 100644 index 0000000..9072d72 --- /dev/null +++ b/src/openvic-simulation/politics/PoliticsManager.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "openvic-simulation/politics/Government.hpp" +#include "openvic-simulation/politics/Ideology.hpp" +#include "openvic-simulation/politics/Issue.hpp" + +namespace OpenVic { + struct PoliticsManager { + private: + GovernmentTypeManager government_type_manager; + IdeologyManager ideology_manager; + IssueManager issue_manager; + public: + REF_GETTERS(government_type_manager) + REF_GETTERS(ideology_manager) + REF_GETTERS(issue_manager) + + inline bool load_government_types_file(ast::NodeCPtr root) { + return government_type_manager.load_government_types_file(ideology_manager, root); + } + }; +} diff --git a/src/openvic-simulation/testing/test_scripts/A_002_economy_tests.cpp b/src/openvic-simulation/testing/test_scripts/A_002_economy_tests.cpp index c74c5e9..d1a857f 100644 --- a/src/openvic-simulation/testing/test_scripts/A_002_economy_tests.cpp +++ b/src/openvic-simulation/testing/test_scripts/A_002_economy_tests.cpp @@ -505,7 +505,7 @@ namespace OpenVic { void check_base_price(std::string identifier, std::string target_value, std::string req_name) { // Get string of base_price from goods manager - fixed_point_t base_price_fp = get_game_manager()->get_good_manager().get_good_by_identifier(identifier)->get_base_price(); + fixed_point_t base_price_fp = get_game_manager()->get_economy_manager().get_good_manager().get_good_by_identifier(identifier)->get_base_price(); std::stringstream ss; ss << std::fixed << std::setprecision(1) << base_price_fp.to_double(); // Use a single digit floating point of the value std::string base_price = ss.str(); diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp index 4e13813..aea5728 100644 --- a/src/openvic-simulation/types/IdentifierRegistry.hpp +++ b/src/openvic-simulation/types/IdentifierRegistry.hpp @@ -6,6 +6,10 @@ #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/utility/Logger.hpp" +#define REF_GETTERS(var) \ + constexpr decltype(var)& get_##var() { return var; } \ + constexpr decltype(var) const& get_##var() const { return var; } + namespace OpenVic { /* * Base class for objects with a non-empty string identifier, @@ -179,13 +183,7 @@ namespace OpenVic { return get_item_by_index(index) != nullptr; } - std::vector& get_items() { - return items; - } - - std::vector const& get_items() const { - return items; - } + REF_GETTERS(items) std::vector get_item_identifiers() const { std::vector identifiers; diff --git a/src/openvic-simulation/units/Unit.cpp b/src/openvic-simulation/units/Unit.cpp deleted file mode 100644 index 3da24da..0000000 --- a/src/openvic-simulation/units/Unit.cpp +++ /dev/null @@ -1,338 +0,0 @@ -#include "Unit.hpp" - -#include - -#define UNIT_ARGS icon, sprite, active, unit_type, floating_flag, priority, max_strength, \ - default_organisation, maximum_speed, weighted_value, build_time, build_cost, supply_consumption, \ - supply_cost -#define LAND_ARGS primary_culture, sprite_override, sprite_mount, sprite_mount_attach_node, \ - reconnaissance, attack, defence, discipline, support, maneuver, siege -#define NAVY_ARGS naval_icon, sail, transport, capital, move_sound, select_sound, colonial_points, build_overseas, min_port_level, \ - limit_per_port, supply_consumption_score, hull, gun_power, fire_range, evasion, torpedo_attack - -using namespace OpenVic; -using namespace OpenVic::NodeTools; - -Unit::Unit(std::string_view identifier, type_t type, UNIT_PARAMS) : HasIdentifier { identifier }, - icon { icon }, type { type }, sprite { sprite }, active { active }, unit_type { unit_type }, - floating_flag { floating_flag }, priority { priority }, max_strength { max_strength }, - default_organisation { default_organisation }, maximum_speed { maximum_speed }, weighted_value { weighted_value }, - build_time { build_time }, build_cost { build_cost }, supply_consumption { supply_consumption }, supply_cost { supply_cost } {} - -Unit::icon_t Unit::get_icon() const { - return icon; -} - -Unit::type_t Unit::get_type() const { - return type; -} - -std::string const& Unit::get_sprite() const { - return sprite; -} - -bool Unit::is_active() const { - return active; -} - -std::string const& Unit::get_unit_type() const { - return unit_type; -} - -bool Unit::has_floating_flag() const { - return floating_flag; -} - -uint32_t Unit::get_priority() const { - return priority; -} - -fixed_point_t Unit::get_max_strength() const { - return max_strength; -} - -fixed_point_t Unit::get_default_organisation() const { - return default_organisation; -} - -fixed_point_t Unit::get_maximum_speed() const { - return maximum_speed; -} - -Timespan Unit::get_build_time() const { - return build_time; -} - -fixed_point_t Unit::get_weighted_value() const { - return weighted_value; -} - -std::map const& Unit::get_build_cost() const { - return build_cost; -} - -fixed_point_t Unit::get_supply_consumption() const { - return supply_consumption; -} - -std::map const& Unit::get_supply_cost() const { - return supply_cost; -} - -LandUnit::LandUnit(std::string_view identifier, UNIT_PARAMS, LAND_PARAMS) - : Unit { identifier, type_t::LAND, UNIT_ARGS }, primary_culture { primary_culture }, sprite_override { sprite_override }, - sprite_mount { sprite_mount }, sprite_mount_attach_node { sprite_mount_attach_node }, reconnaissance { reconnaissance }, - attack { attack }, defence { defence }, discipline { discipline }, support { support }, maneuver { maneuver }, siege { siege } {} - -bool LandUnit::get_primary_culture() const { - return primary_culture; -} - -std::string const& LandUnit::get_sprite_override() const { - return sprite_override; -} - -std::string const& LandUnit::get_sprite_mount() const { - return sprite_mount; -} - -std::string const& LandUnit::get_sprite_mount_attach_node() const { - return sprite_mount_attach_node; -} - -fixed_point_t LandUnit::get_reconnaissance() const { - return reconnaissance; -} - -fixed_point_t LandUnit::get_attack() const { - return attack; -} - -fixed_point_t LandUnit::get_defence() const { - return defence; -} - -fixed_point_t LandUnit::get_discipline() const { - return discipline; -} - -fixed_point_t LandUnit::get_support() const { - return support; -} - -fixed_point_t LandUnit::get_maneuver() const { - return maneuver; -} - -fixed_point_t LandUnit::get_siege() const { - return siege; -} - -NavalUnit::NavalUnit(std::string_view identifier, UNIT_PARAMS, NAVY_PARAMS) : Unit { identifier, type_t::NAVAL, UNIT_ARGS }, - naval_icon { naval_icon }, sail { sail }, transport { transport }, capital { capital }, move_sound { move_sound }, - select_sound { select_sound }, colonial_points { colonial_points }, build_overseas { build_overseas }, - min_port_level { min_port_level }, limit_per_port { limit_per_port }, supply_consumption_score { supply_consumption_score }, - hull { hull }, gun_power { gun_power }, fire_range { fire_range }, evasion { evasion }, torpedo_attack { torpedo_attack } {}; - -NavalUnit::icon_t NavalUnit::get_naval_icon() const { - return naval_icon; -} - -bool NavalUnit::can_sail() const { - return sail; -} - -bool NavalUnit::is_transport() const { - return transport; -} - -std::string const& NavalUnit::get_move_sound() const { - return move_sound; -} - -std::string const& NavalUnit::get_select_sound() const { - return select_sound; -} - -fixed_point_t NavalUnit::get_colonial_points() const { - return colonial_points; -} - -bool NavalUnit::can_build_overseas() const { - return build_overseas; -} - -uint32_t NavalUnit::get_min_port_level() const { - return min_port_level; -} - -int32_t NavalUnit::get_limit_per_port() const { - return limit_per_port; -} - -fixed_point_t NavalUnit::get_supply_consumption_score() const { - return supply_consumption_score; -} - -fixed_point_t NavalUnit::get_hull() const { - return hull; -} - -fixed_point_t NavalUnit::get_gun_power() const { - return gun_power; -} - -fixed_point_t NavalUnit::get_fire_range() const { - return fire_range; -} - -fixed_point_t NavalUnit::get_evasion() const { - return evasion; -} - -fixed_point_t NavalUnit::get_torpedo_attack() const { - return torpedo_attack; -} - -UnitManager::UnitManager() : units { "units" } {} - -bool UnitManager::_check_shared_parameters(std::string_view identifier, UNIT_PARAMS) { - if (identifier.empty()) { - Logger::error("Invalid religion identifier - empty!"); - return false; - } - - if (sprite.empty()) { - Logger::error("Invalid sprite identifier - empty!"); - return false; - } - - if (unit_type.empty()) { - Logger::error("Invalid unit type - empty!"); - return false; - } - - //TODO check that icon and sprite exist - - return true; -} - -bool UnitManager::add_land_unit(std::string_view identifier, UNIT_PARAMS, LAND_PARAMS) { - if (!_check_shared_parameters(identifier, UNIT_ARGS)) { - return false; - } - - return units.add_item(LandUnit { identifier, UNIT_ARGS, LAND_ARGS }); -} - -bool UnitManager::add_naval_unit(std::string_view identifier, UNIT_PARAMS, NAVY_PARAMS) { - if (!_check_shared_parameters(identifier, UNIT_ARGS)) { - return false; - } - - //TODO: check that icon and sounds exist - - return units.add_item(NavalUnit { identifier, UNIT_ARGS, NAVY_ARGS }); -} - -static bool shared_keys_callback(std::string_view key, ast::NodeCPtr) { - static const std::set> reserved_keys = { - "icon", "type", "sprite", "active", "unit_type", "floating_flag", "priority", - "max_strength", "default_organisation", "maximum_speed", "weighted_value", - "build_time", "build_cost", "supply_consumption", "supply_cost" - }; - if (reserved_keys.contains(key)) return true; - Logger::error("Invalid key: ", key); - return false; -}; - -bool UnitManager::load_unit_file(GoodManager const& good_manager, ast::NodeCPtr root) { - return expect_dictionary([this, &good_manager](std::string_view key, ast::NodeCPtr value) -> bool { - Unit::icon_t icon = 0; - std::string_view type, unit_type, sprite; - bool active = true, floating_flag = false; - uint32_t priority = 0; - Timespan build_time; - fixed_point_t maximum_speed = 0, max_strength = 0, default_organisation = 0, weighted_value = 0, supply_consumption = 0; - std::map build_cost, supply_cost; - - //shared - bool ret = expect_dictionary_keys_and_default( - key_value_success_callback, - "icon", ONE_EXACTLY, expect_uint(assign_variable_callback(icon)), - "type", ONE_EXACTLY, expect_identifier(assign_variable_callback(type)), - "sprite", ONE_EXACTLY, expect_identifier(assign_variable_callback(sprite)), - "active", ZERO_OR_ONE, expect_bool(assign_variable_callback(active)), - "unit_type", ONE_EXACTLY, expect_identifier(assign_variable_callback(unit_type)), - "floating_flag", ONE_EXACTLY, expect_bool(assign_variable_callback(floating_flag)), - "priority", ONE_EXACTLY, expect_uint(assign_variable_callback(priority)), - "max_strength", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(max_strength)), - "default_organisation", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(default_organisation)), - "maximum_speed", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(maximum_speed)), - "weighted_value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(weighted_value)), - "build_time", ONE_EXACTLY, expect_days(assign_variable_callback(build_time)), - "build_cost", ONE_EXACTLY, good_manager.expect_good_decimal_map(move_variable_callback(build_cost)), - "supply_consumption", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(supply_consumption)), - "supply_cost", ONE_EXACTLY, good_manager.expect_good_decimal_map(move_variable_callback(supply_cost)) - )(value); - - if (type == "land") { - bool primary_culture = false; - std::string_view sprite_override, sprite_mount, sprite_mount_attach_node; - fixed_point_t reconnaissance = 0, attack = 0, defence = 0, discipline = 0, support = 0, maneuver = 0, siege = 0; - - ret &= expect_dictionary_keys_and_default( - shared_keys_callback, - "primary_culture", ZERO_OR_ONE, expect_bool(assign_variable_callback(primary_culture)), - "sprite_override", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_override)), - "sprite_mount", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_mount)), - "sprite_mount_attach_node", ZERO_OR_ONE, expect_identifier(assign_variable_callback(sprite_mount_attach_node)), - "reconnaissance", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(reconnaissance)), - "attack", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(attack)), - "defence", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(defence)), - "discipline", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(discipline)), - "support", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(support)), - "maneuver", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(maneuver)), - "siege", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(siege)) - )(value); - - ret &= add_land_unit(key, UNIT_ARGS, LAND_ARGS); - - return ret; - } else if (type == "naval") { - Unit::icon_t naval_icon = 0; - bool sail = false, transport = false, capital = false, build_overseas = false; - std::string_view move_sound, select_sound; //TODO defaults for both - uint32_t min_port_level = 0; - int32_t limit_per_port = 0; - fixed_point_t fire_range = 0, evasion = 0, supply_consumption_score = 0, hull = 0, gun_power = 0, colonial_points = 0, torpedo_attack = 0; - - ret &= expect_dictionary_keys_and_default( - shared_keys_callback, - "naval_icon", ONE_EXACTLY, expect_uint(assign_variable_callback(naval_icon)), - "sail", ZERO_OR_ONE, expect_bool(assign_variable_callback(sail)), - "transport", ZERO_OR_ONE, expect_bool(assign_variable_callback(transport)), - "capital", ZERO_OR_ONE, expect_bool(assign_variable_callback(capital)), - "move_sound", ZERO_OR_ONE, expect_identifier(assign_variable_callback(move_sound)), - "select_sound", ZERO_OR_ONE, expect_identifier(assign_variable_callback(select_sound)), - "colonial_points", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(colonial_points)), - "can_build_overseas", ZERO_OR_ONE, expect_bool(assign_variable_callback(build_overseas)), - "min_port_level", ONE_EXACTLY, expect_uint(assign_variable_callback(min_port_level)), - "limit_per_port", ONE_EXACTLY, expect_int(assign_variable_callback(limit_per_port)), - "supply_consumption_score", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(supply_consumption_score)), - "hull", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(hull)), - "gun_power", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(gun_power)), - "fire_range", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(fire_range)), - "evasion", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(evasion)), - "torpedo_attack", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(torpedo_attack)) - )(value); - - ret &= add_naval_unit(key, UNIT_ARGS, NAVY_ARGS); - - return ret; - } else { - Logger::error("Invalid type for unit ", key, ": ", type); - return false; - } - })(root); -} \ No newline at end of file diff --git a/src/openvic-simulation/units/Unit.hpp b/src/openvic-simulation/units/Unit.hpp deleted file mode 100644 index 65e6259..0000000 --- a/src/openvic-simulation/units/Unit.hpp +++ /dev/null @@ -1,171 +0,0 @@ -#pragma once - -#include -#include -#include "openvic-simulation/economy/Good.hpp" -#include "openvic-simulation/types/IdentifierRegistry.hpp" -#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" -#include "openvic-simulation/dataloader/NodeTools.hpp" -#include "openvic-simulation/economy/Good.hpp" -#include "openvic-simulation/types/Date.hpp" - -#define UNIT_PARAMS Unit::icon_t icon, std::string_view sprite, bool active, std::string_view unit_type, \ - bool floating_flag, uint32_t priority, fixed_point_t max_strength, fixed_point_t default_organisation, \ - fixed_point_t maximum_speed, fixed_point_t weighted_value, Timespan build_time, \ - std::map build_cost, fixed_point_t supply_consumption, \ - std::map supply_cost -#define LAND_PARAMS bool primary_culture, std::string_view sprite_override, std::string_view sprite_mount, \ - std::string_view sprite_mount_attach_node, fixed_point_t reconnaissance, fixed_point_t attack, \ - fixed_point_t defence, fixed_point_t discipline, fixed_point_t support, fixed_point_t maneuver, fixed_point_t siege -#define NAVY_PARAMS Unit::icon_t naval_icon, bool sail, bool transport, bool capital, std::string_view move_sound, \ - std::string_view select_sound, fixed_point_t colonial_points, bool build_overseas, uint32_t min_port_level, \ - int32_t limit_per_port, fixed_point_t supply_consumption_score, fixed_point_t hull, fixed_point_t gun_power, \ - fixed_point_t fire_range, fixed_point_t evasion, fixed_point_t torpedo_attack - -namespace OpenVic { - struct Unit : HasIdentifier { - using icon_t = uint32_t; - - enum struct type_t { - LAND, NAVAL - }; - - private: - const type_t type; - const icon_t icon; - const std::string sprite; - const bool active; - const std::string unit_type; - const bool floating_flag; - - const uint32_t priority; - const fixed_point_t max_strength; - const fixed_point_t default_organisation; - const fixed_point_t maximum_speed; - const fixed_point_t weighted_value; - - const Timespan build_time; - const std::map build_cost; - const fixed_point_t supply_consumption; - const std::map supply_cost; - - protected: - Unit(std::string_view identifier, type_t type, UNIT_PARAMS); - - public: - Unit(Unit&&) = default; - - icon_t get_icon() const; - type_t get_type() const; - std::string const& get_sprite() const; - bool is_active() const; - std::string const& get_unit_type() const; - bool has_floating_flag() const; - - uint32_t get_priority() const; - fixed_point_t get_max_strength() const; - fixed_point_t get_default_organisation() const; - fixed_point_t get_maximum_speed() const; - fixed_point_t get_weighted_value() const; - - Timespan get_build_time() const; - std::map const& get_build_cost() const; - fixed_point_t get_supply_consumption() const; - std::map const& get_supply_cost() const; - }; - - struct LandUnit : Unit { - friend struct UnitManager; - - private: - const bool primary_culture; - const std::string sprite_override, sprite_mount, sprite_mount_attach_node; - const fixed_point_t reconnaissance; - const fixed_point_t attack; - const fixed_point_t defence; - const fixed_point_t discipline; - const fixed_point_t support; - const fixed_point_t maneuver; - const fixed_point_t siege; - - LandUnit(std::string_view identifier, UNIT_PARAMS, LAND_PARAMS); - - public: - LandUnit(LandUnit&&) = default; - - bool get_primary_culture() const; - std::string const& get_sprite_override() const; - std::string const& get_sprite_mount() const; - std::string const& get_sprite_mount_attach_node() const; - - fixed_point_t get_reconnaissance() const; - fixed_point_t get_attack() const; - fixed_point_t get_defence() const; - fixed_point_t get_discipline() const; - fixed_point_t get_support() const; - fixed_point_t get_maneuver() const; - fixed_point_t get_siege() const; - }; - - struct NavalUnit : Unit { - friend struct UnitManager; - - private: - const icon_t naval_icon; - const bool sail; - const bool transport; - const bool capital; - const std::string move_sound; - const std::string select_sound; - const fixed_point_t colonial_points; - const bool build_overseas; - const uint32_t min_port_level; - const int32_t limit_per_port; - const fixed_point_t supply_consumption_score; - - const fixed_point_t hull; - const fixed_point_t gun_power; - const fixed_point_t fire_range; - const fixed_point_t evasion; - const fixed_point_t torpedo_attack; - - NavalUnit(std::string_view identifier, UNIT_PARAMS, NAVY_PARAMS); - - public: - NavalUnit(NavalUnit&&) = default; - - icon_t get_naval_icon() const; - bool can_sail() const; - bool is_transport() const; - bool is_capital() const; - std::string const& get_move_sound() const; - std::string const& get_select_sound() const; - fixed_point_t get_colonial_points() const; - bool can_build_overseas() const; - uint32_t get_min_port_level() const; - int32_t get_limit_per_port() const; - fixed_point_t get_supply_consumption_score() const; - - fixed_point_t get_hull() const; - fixed_point_t get_gun_power() const; - fixed_point_t get_fire_range() const; - fixed_point_t get_evasion() const; - fixed_point_t get_torpedo_attack() const; - }; - - struct UnitManager { - private: - IdentifierRegistry units; - - bool _check_shared_parameters(std::string_view identifier, UNIT_PARAMS); - - public: - UnitManager(); - - bool add_land_unit(std::string_view identifier, UNIT_PARAMS, LAND_PARAMS); - bool add_naval_unit(std::string_view identifier, UNIT_PARAMS, NAVY_PARAMS); - IDENTIFIER_REGISTRY_ACCESSORS(unit) - - bool load_unit_file(GoodManager const& good_manager, ast::NodeCPtr root); - }; -} \ No newline at end of file -- cgit v1.2.3-56-ga3b1 From d95c3c9da75018e3e959e5493ebd9c520e00bf7a Mon Sep 17 00:00:00 2001 From: hop311 Date: Thu, 12 Oct 2023 23:43:10 +0100 Subject: Changed return types to std::string_view --- src/openvic-simulation/economy/Building.cpp | 2 +- src/openvic-simulation/economy/Building.hpp | 2 +- src/openvic-simulation/military/Unit.cpp | 14 +++++++------- src/openvic-simulation/military/Unit.hpp | 14 +++++++------- src/openvic-simulation/politics/Government.cpp | 2 +- src/openvic-simulation/politics/Government.hpp | 2 +- src/openvic-simulation/pop/Culture.cpp | 2 +- src/openvic-simulation/pop/Culture.hpp | 2 +- src/openvic-simulation/types/IdentifierRegistry.cpp | 2 +- src/openvic-simulation/types/IdentifierRegistry.hpp | 20 ++++++++++++++------ 10 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/openvic-simulation/economy/Building.cpp b/src/openvic-simulation/economy/Building.cpp index d27c91a..23bd04c 100644 --- a/src/openvic-simulation/economy/Building.cpp +++ b/src/openvic-simulation/economy/Building.cpp @@ -17,7 +17,7 @@ BuildingType const& Building::get_type() const { return type; } -std::string const& Building::get_on_completion() const { +std::string_view Building::get_on_completion() const { return on_completion; } diff --git a/src/openvic-simulation/economy/Building.hpp b/src/openvic-simulation/economy/Building.hpp index 3f74c3d..3d1e24b 100644 --- a/src/openvic-simulation/economy/Building.hpp +++ b/src/openvic-simulation/economy/Building.hpp @@ -70,7 +70,7 @@ namespace OpenVic { Building(Building&&) = default; BuildingType const& get_type() const; - std::string const& get_on_completion() const; + std::string_view get_on_completion() const; fixed_point_t get_completion_size() const; level_t get_max_level() const; std::map const& get_goods_cost() const; diff --git a/src/openvic-simulation/military/Unit.cpp b/src/openvic-simulation/military/Unit.cpp index 3da24da..63ece91 100644 --- a/src/openvic-simulation/military/Unit.cpp +++ b/src/openvic-simulation/military/Unit.cpp @@ -27,7 +27,7 @@ Unit::type_t Unit::get_type() const { return type; } -std::string const& Unit::get_sprite() const { +std::string_view Unit::get_sprite() const { return sprite; } @@ -35,7 +35,7 @@ bool Unit::is_active() const { return active; } -std::string const& Unit::get_unit_type() const { +std::string_view Unit::get_unit_type() const { return unit_type; } @@ -88,15 +88,15 @@ bool LandUnit::get_primary_culture() const { return primary_culture; } -std::string const& LandUnit::get_sprite_override() const { +std::string_view LandUnit::get_sprite_override() const { return sprite_override; } -std::string const& LandUnit::get_sprite_mount() const { +std::string_view LandUnit::get_sprite_mount() const { return sprite_mount; } -std::string const& LandUnit::get_sprite_mount_attach_node() const { +std::string_view LandUnit::get_sprite_mount_attach_node() const { return sprite_mount_attach_node; } @@ -146,11 +146,11 @@ bool NavalUnit::is_transport() const { return transport; } -std::string const& NavalUnit::get_move_sound() const { +std::string_view NavalUnit::get_move_sound() const { return move_sound; } -std::string const& NavalUnit::get_select_sound() const { +std::string_view NavalUnit::get_select_sound() const { return select_sound; } diff --git a/src/openvic-simulation/military/Unit.hpp b/src/openvic-simulation/military/Unit.hpp index 65e6259..de30763 100644 --- a/src/openvic-simulation/military/Unit.hpp +++ b/src/openvic-simulation/military/Unit.hpp @@ -57,9 +57,9 @@ namespace OpenVic { icon_t get_icon() const; type_t get_type() const; - std::string const& get_sprite() const; + std::string_view get_sprite() const; bool is_active() const; - std::string const& get_unit_type() const; + std::string_view get_unit_type() const; bool has_floating_flag() const; uint32_t get_priority() const; @@ -94,9 +94,9 @@ namespace OpenVic { LandUnit(LandUnit&&) = default; bool get_primary_culture() const; - std::string const& get_sprite_override() const; - std::string const& get_sprite_mount() const; - std::string const& get_sprite_mount_attach_node() const; + std::string_view get_sprite_override() const; + std::string_view get_sprite_mount() const; + std::string_view get_sprite_mount_attach_node() const; fixed_point_t get_reconnaissance() const; fixed_point_t get_attack() const; @@ -138,8 +138,8 @@ namespace OpenVic { bool can_sail() const; bool is_transport() const; bool is_capital() const; - std::string const& get_move_sound() const; - std::string const& get_select_sound() const; + std::string_view get_move_sound() const; + std::string_view get_select_sound() const; fixed_point_t get_colonial_points() const; bool can_build_overseas() const; uint32_t get_min_port_level() const; diff --git a/src/openvic-simulation/politics/Government.cpp b/src/openvic-simulation/politics/Government.cpp index 1a48806..16b3bc4 100644 --- a/src/openvic-simulation/politics/Government.cpp +++ b/src/openvic-simulation/politics/Government.cpp @@ -30,7 +30,7 @@ Timespan GovernmentType::get_term_duration() const { return term_duration; } -std::string const& GovernmentType::get_flag_type() const { +std::string_view GovernmentType::get_flag_type() const { return flag_type_identifier; } diff --git a/src/openvic-simulation/politics/Government.hpp b/src/openvic-simulation/politics/Government.hpp index c72dae6..ba8496f 100644 --- a/src/openvic-simulation/politics/Government.hpp +++ b/src/openvic-simulation/politics/Government.hpp @@ -24,7 +24,7 @@ namespace OpenVic { bool holds_elections() const; bool can_appoint_ruling_party() const; Timespan get_term_duration() const; - std::string const& get_flag_type() const; + std::string_view get_flag_type() const; }; struct GovernmentTypeManager { diff --git a/src/openvic-simulation/pop/Culture.cpp b/src/openvic-simulation/pop/Culture.cpp index 261ad4c..e3ba5dd 100644 --- a/src/openvic-simulation/pop/Culture.cpp +++ b/src/openvic-simulation/pop/Culture.cpp @@ -15,7 +15,7 @@ CultureGroup::CultureGroup(std::string_view new_identifier, std::string_view new unit_graphical_culture_type { new_unit_graphical_culture_type }, is_overseas { new_is_overseas } {} -std::string const& CultureGroup::get_leader() const { +std::string_view CultureGroup::get_leader() const { return leader; } diff --git a/src/openvic-simulation/pop/Culture.hpp b/src/openvic-simulation/pop/Culture.hpp index b6b4952..d36a90b 100644 --- a/src/openvic-simulation/pop/Culture.hpp +++ b/src/openvic-simulation/pop/Culture.hpp @@ -31,7 +31,7 @@ namespace OpenVic { public: CultureGroup(CultureGroup&&) = default; - std::string const& get_leader() const; + std::string_view get_leader() const; GraphicalCultureType const& get_unit_graphical_culture_type() const; bool get_is_overseas() const; }; diff --git a/src/openvic-simulation/types/IdentifierRegistry.cpp b/src/openvic-simulation/types/IdentifierRegistry.cpp index d6afd3a..8e93cb1 100644 --- a/src/openvic-simulation/types/IdentifierRegistry.cpp +++ b/src/openvic-simulation/types/IdentifierRegistry.cpp @@ -9,7 +9,7 @@ HasIdentifier::HasIdentifier(std::string_view new_identifier) assert(!identifier.empty()); } -std::string const& HasIdentifier::get_identifier() const { +std::string_view HasIdentifier::get_identifier() const { return identifier; } diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp index aea5728..3ba7fc4 100644 --- a/src/openvic-simulation/types/IdentifierRegistry.hpp +++ b/src/openvic-simulation/types/IdentifierRegistry.hpp @@ -28,7 +28,7 @@ namespace OpenVic { HasIdentifier& operator=(HasIdentifier const&) = delete; HasIdentifier& operator=(HasIdentifier&&) = delete; - std::string const& get_identifier() const; + std::string_view get_identifier() const; }; std::ostream& operator<<(std::ostream& stream, HasIdentifier const& obj); @@ -73,7 +73,7 @@ namespace OpenVic { distribution_t::value_type get_largest_item(distribution_t const& dist); template - using get_identifier_func_t = std::string const&(T::*)(void) const; + using get_identifier_func_t = std::string_view(T::*)(void) const; template _Type, get_identifier_func_t<_Base> get_identifier, typename _Storage, _Type* (*get_ptr)(_Storage&), _Type const* (*get_cptr)(_Storage const&)> @@ -92,7 +92,7 @@ namespace OpenVic { UniqueKeyRegistry(std::string_view new_name, bool new_log_lock = true) : name { new_name }, log_lock { new_log_lock } {} - std::string const& get_name() const { + std::string_view get_name() const { return name; } @@ -102,7 +102,7 @@ namespace OpenVic { return false; } value_type const* new_item = (*get_cptr)(item); - std::string const& new_identifier = (new_item->*get_identifier)(); + const std::string_view new_identifier = (new_item->*get_identifier)(); value_type const* old_item = get_item_by_identifier(new_identifier); if (old_item != nullptr) { #define DUPLICATE_MESSAGE "Cannot add item to the ", name, " registry - an item with the identifier \"", new_identifier, "\" already exists!" @@ -115,7 +115,7 @@ namespace OpenVic { } #undef DUPLICATE_MESSAGE } - identifier_index_map[new_identifier] = items.size(); + identifier_index_map.emplace(new_identifier, items.size()); items.push_back(std::move(item)); return true; } @@ -249,8 +249,16 @@ namespace OpenVic { } }; + template + [[nodiscard]] inline constexpr T* _addressof(T& v) noexcept { + return std::addressof(v); + } + + template + const T* _addressof(const T&&) = delete; + template _Type, get_identifier_func_t<_Base> get_identifier> - using ValueRegistry = UniqueKeyRegistry<_Base, _Type, get_identifier, _Type, std::addressof<_Type>, std::addressof>; + using ValueRegistry = UniqueKeyRegistry<_Base, _Type, get_identifier, _Type, _addressof<_Type>, _addressof>; template constexpr _Type* get_ptr(std::unique_ptr<_Type>& storage) { -- cgit v1.2.3-56-ga3b1