diff options
author | Hop311 <Hop3114@gmail.com> | 2023-09-19 17:40:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-19 17:40:09 +0200 |
commit | 9c89100e0c8854dff3174b078d235148585a8b03 (patch) | |
tree | 77f81dfd3ec85a659741e979c148b33b22595dd0 | |
parent | 64d134ad20c333afa60373526d6fab27a07c6adc (diff) | |
parent | 72add97c47f0d17fc0019bb4cfec7506740a9c7d (diff) |
Merge pull request #17 from OpenVicProject/dataloading-the-third
Scaffolding for `positions.txt` + modifier loading
m--------- | deps/openvic-dataloader | 0 | ||||
-rw-r--r-- | src/openvic-simulation/Modifier.cpp | 21 | ||||
-rw-r--r-- | src/openvic-simulation/Modifier.hpp | 5 | ||||
-rw-r--r-- | src/openvic-simulation/dataloader/Dataloader.cpp | 38 | ||||
-rw-r--r-- | src/openvic-simulation/dataloader/Dataloader.hpp | 8 | ||||
-rw-r--r-- | src/openvic-simulation/dataloader/NodeTools.cpp | 31 | ||||
-rw-r--r-- | src/openvic-simulation/dataloader/NodeTools.hpp | 42 | ||||
-rw-r--r-- | src/openvic-simulation/economy/Good.cpp | 2 | ||||
-rw-r--r-- | src/openvic-simulation/economy/Good.hpp | 2 | ||||
-rw-r--r-- | src/openvic-simulation/map/Map.cpp | 100 | ||||
-rw-r--r-- | src/openvic-simulation/map/Map.hpp | 17 | ||||
-rw-r--r-- | src/openvic-simulation/map/Province.cpp | 6 | ||||
-rw-r--r-- | src/openvic-simulation/map/Province.hpp | 2 | ||||
-rw-r--r-- | src/openvic-simulation/pop/Culture.cpp | 9 | ||||
-rw-r--r-- | src/openvic-simulation/pop/Pop.cpp | 4 | ||||
-rw-r--r-- | src/openvic-simulation/types/IdentifierRegistry.hpp | 58 | ||||
-rw-r--r-- | src/openvic-simulation/types/Vector.hpp | 1 |
17 files changed, 220 insertions, 126 deletions
diff --git a/deps/openvic-dataloader b/deps/openvic-dataloader -Subproject 8f71abc25ec993ce7e85f5342a52fb456bdba26 +Subproject 977661f6f4301be19fa64abfc6cda5040c3899b diff --git a/src/openvic-simulation/Modifier.cpp b/src/openvic-simulation/Modifier.cpp index d2e21c6..46bba48 100644 --- a/src/openvic-simulation/Modifier.cpp +++ b/src/openvic-simulation/Modifier.cpp @@ -1,6 +1,7 @@ #include "Modifier.hpp" using namespace OpenVic; +using namespace OpenVic::NodeTools; ModifierEffect::ModifierEffect(const std::string_view new_identifier, bool new_positive_good) : HasIdentifier { new_identifier }, positive_good { new_positive_good } {} @@ -114,3 +115,23 @@ bool ModifierManager::add_modifier(const std::string_view identifier, ModifierVa } return modifiers.add_item({ identifier, std::move(values), icon }); } + +node_callback_t ModifierManager::expect_modifier_value(callback_t<ModifierValue&&> callback) const { + return [this, callback](ast::NodeCPtr root) -> bool { + ModifierValue modifier; + bool ret = expect_dictionary( + [this, &modifier](std::string_view key, ast::NodeCPtr value) -> bool { + ModifierEffect const* effect = get_modifier_effect_by_identifier(key); + if (effect != nullptr) { + return expect_fixed_point( + assign_variable_callback(modifier.values[effect]) + )(value); + } + Logger::error("Invalid modifier effect: ", key); + return false; + } + )(root); + ret &= callback(std::move(modifier)); + return ret; + }; +} diff --git a/src/openvic-simulation/Modifier.hpp b/src/openvic-simulation/Modifier.hpp index eb63788..acdadfe 100644 --- a/src/openvic-simulation/Modifier.hpp +++ b/src/openvic-simulation/Modifier.hpp @@ -25,6 +25,8 @@ namespace OpenVic { }; struct ModifierValue { + friend struct ModifierManager; + using effect_map_t = std::map<ModifierEffect const*, fixed_point_t>; private: effect_map_t values; @@ -57,6 +59,7 @@ namespace OpenVic { using icon_t = uint8_t; private: + /* A modifier can have no icon (zero). */ const icon_t icon; Modifier(const std::string_view new_identifier, ModifierValue&& new_values, icon_t new_icon); @@ -92,5 +95,7 @@ namespace OpenVic { bool add_modifier(const std::string_view identifier, ModifierValue&& values, Modifier::icon_t icon); IDENTIFIER_REGISTRY_ACCESSORS(Modifier, modifier) + + NodeTools::node_callback_t expect_modifier_value(NodeTools::callback_t<ModifierValue&&> callback) const; }; } diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index e85f499..a30983b 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -50,7 +50,6 @@ fs::path Dataloader::lookup_file(fs::path const& path) const { } static bool contains_file_with_name(Dataloader::path_vector_t const& paths, fs::path const& name) { - for (fs::path const& path : paths) { if (path.filename() == name) return true; } @@ -76,8 +75,7 @@ Dataloader::path_vector_t Dataloader::lookup_files_in_dir(fs::path const& path, return ret; } -bool Dataloader::apply_to_files_in_dir(fs::path const& path, fs::path const& extension, std::function<bool(fs::path const&)> callback) const { - +bool Dataloader::apply_to_files_in_dir(fs::path const& path, fs::path const& extension, callback_t<fs::path const&> callback) const { bool ret = true; for (fs::path const& file : lookup_files_in_dir(path, extension)) { ret &= callback(file); @@ -140,6 +138,12 @@ static csv::Windows1252Parser _parse_csv(fs::path const& path) { return _run_ovdl_parser<csv::Windows1252Parser, &_csv_parse>(path); } +static callback_t<fs::path const&> _parse_defines_callback(node_callback_t callback) { + return [callback](fs::path const& path) -> bool { + return callback(_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 { @@ -153,7 +157,9 @@ bool Dataloader::_load_pop_types(PopManager& pop_manager, fs::path const& pop_ty return ret; } -bool Dataloader::_load_map_dir(Map& map, fs::path const& map_directory) const { +bool Dataloader::_load_map_dir(GameManager& game_manager, fs::path const& map_directory) const { + Map& map = game_manager.map; + static const fs::path defaults_filename = "default.map"; static const std::string default_definitions = "definition.csv"; static const std::string default_provinces = "provinces.bmp"; @@ -226,6 +232,11 @@ bool Dataloader::_load_map_dir(Map& map, fs::path const& map_directory) const { ret = false; } + if (!map.load_province_positions(game_manager.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())) { Logger::error("Failed to load region file!"); ret = false; @@ -241,7 +252,7 @@ bool Dataloader::_load_map_dir(Map& map, fs::path const& map_directory) const { } bool Dataloader::load_defines(GameManager& game_manager) const { - static const fs::path good_file = "common/goods.txt"; + static const fs::path goods_file = "common/goods.txt"; static const fs::path pop_type_directory = "poptypes"; static const fs::path graphical_culture_type_file = "common/graphicalculturetype.txt"; static const fs::path culture_file = "common/cultures.txt"; @@ -250,7 +261,7 @@ bool Dataloader::load_defines(GameManager& game_manager) const { bool ret = true; - if (!game_manager.good_manager.load_good_file(_parse_defines(lookup_file(good_file)).get_file_node())) { + if (!game_manager.good_manager.load_goods_file(_parse_defines(lookup_file(goods_file)).get_file_node())) { Logger::error("Failed to load goods!"); ret = false; } @@ -270,7 +281,7 @@ bool Dataloader::load_defines(GameManager& game_manager) const { Logger::error("Failed to load religions!"); ret = false; } - if (!_load_map_dir(game_manager.map, map_directory)) { + if (!_load_map_dir(game_manager, map_directory)) { Logger::error("Failed to load map!"); ret = false; } @@ -281,16 +292,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 expect_dictionary( - [&game_manager](std::string_view province_key, ast::NodeCPtr province_node) -> bool { - Province* province = game_manager.map.get_province_by_identifier(province_key); - if (province == nullptr) { - Logger::error("Invalid province id: ", province_key); - return false; - } - return province->load_pop_list(game_manager.pop_manager, province_node); + return _parse_defines_callback(game_manager.map.expect_province_dictionary( + [&game_manager](Province& province, ast::NodeCPtr value) -> bool { + return province.load_pop_list(game_manager.pop_manager, value); } - )(_parse_defines(file).get_file_node()); + ))(file); } ); } diff --git a/src/openvic-simulation/dataloader/Dataloader.hpp b/src/openvic-simulation/dataloader/Dataloader.hpp index 2b358b6..6741361 100644 --- a/src/openvic-simulation/dataloader/Dataloader.hpp +++ b/src/openvic-simulation/dataloader/Dataloader.hpp @@ -4,6 +4,8 @@ #include <functional> #include <vector> +#include "openvic-simulation/dataloader/NodeTools.hpp" + namespace OpenVic { namespace fs = std::filesystem; @@ -19,7 +21,7 @@ namespace OpenVic { path_vector_t roots; bool _load_pop_types(PopManager& pop_manager, fs::path const& pop_type_directory) const; - bool _load_map_dir(Map& map, fs::path const& map_directory) const; + bool _load_map_dir(GameManager& game_manager, fs::path const& map_directory) const; public: Dataloader() = default; @@ -33,7 +35,7 @@ namespace OpenVic { fs::path lookup_file(fs::path const& path) const; path_vector_t lookup_files_in_dir(fs::path const& path, fs::path const& extension) const; bool apply_to_files_in_dir(fs::path const& path, fs::path const& extension, - std::function<bool(fs::path const&)> callback) const; + NodeTools::callback_t<fs::path const&> callback) const; bool load_defines(GameManager& game_manager) const; bool load_pop_history(GameManager& game_manager, fs::path const& path) const; @@ -46,7 +48,7 @@ namespace OpenVic { }; /* Args: key, locale, localisation */ - using localisation_callback_t = std::function<bool(std::string_view, locale_t, std::string_view)>; + using localisation_callback_t = NodeTools::callback_t<std::string_view, locale_t, std::string_view>; bool load_localisation_files(localisation_callback_t callback, fs::path const& localisation_dir = "localisation"); }; } diff --git a/src/openvic-simulation/dataloader/NodeTools.cpp b/src/openvic-simulation/dataloader/NodeTools.cpp index 63a97ad..7dd6e16 100644 --- a/src/openvic-simulation/dataloader/NodeTools.cpp +++ b/src/openvic-simulation/dataloader/NodeTools.cpp @@ -19,20 +19,20 @@ static node_callback_t _expect_type(callback_t<T const&> callback) { }; } -template<typename T = ast::AbstractStringNode> +template<typename T> requires(std::derived_from<T, ast::AbstractStringNode>) -static callback_t<T const&> abstract_string_node_callback(callback_t<std::string_view> callback) { +static callback_t<T const&> _abstract_string_node_callback(callback_t<std::string_view> callback) { return [callback](T const& node) -> bool { return callback(node._name); }; } node_callback_t NodeTools::expect_identifier(callback_t<std::string_view> callback) { - return _expect_type<ast::IdentifierNode>(abstract_string_node_callback<ast::IdentifierNode>(callback)); + return _expect_type<ast::IdentifierNode>(_abstract_string_node_callback<ast::IdentifierNode>(callback)); } node_callback_t NodeTools::expect_string(callback_t<std::string_view> callback) { - return _expect_type<ast::StringNode>(abstract_string_node_callback<ast::StringNode>(callback)); + return _expect_type<ast::StringNode>(_abstract_string_node_callback<ast::StringNode>(callback)); } node_callback_t NodeTools::expect_identifier_or_string(callback_t<std::string_view> callback) { @@ -43,7 +43,7 @@ node_callback_t NodeTools::expect_identifier_or_string(callback_t<std::string_vi cast_node = node->cast_to<ast::StringNode>(); } if (cast_node != nullptr) { - return abstract_string_node_callback(callback)(*cast_node); + return _abstract_string_node_callback<ast::AbstractStringNode>(callback)(*cast_node); } Logger::error("Invalid node type ", node->get_type(), " when expecting ", ast::IdentifierNode::get_type_static(), " or ", ast::StringNode::get_type_static()); } else { @@ -148,6 +148,27 @@ node_callback_t NodeTools::expect_date(callback_t<Date> callback) { ); } +template<typename T, node_callback_t (*expect_func)(callback_t<T>)> +node_callback_t _expect_vec2(callback_t<vec2_t<T>> callback) { + return [callback](ast::NodeCPtr node) -> bool { + vec2_t<T> vec; + bool ret = expect_dictionary_keys( + "x", ONE_EXACTLY, expect_func(assign_variable_callback(vec.x)), + "y", ONE_EXACTLY, expect_func(assign_variable_callback(vec.y)) + )(node); + ret &= callback(vec); + return ret; + }; +} + +node_callback_t NodeTools::expect_ivec2(callback_t<ivec2_t> callback) { + return _expect_vec2<int64_t, expect_int>(callback); +} + +node_callback_t NodeTools::expect_fvec2(callback_t<fvec2_t> callback) { + return _expect_vec2<fixed_point_t, expect_fixed_point>(callback); +} + node_callback_t NodeTools::expect_assign(key_value_callback_t callback) { return _expect_type<ast::AssignNode>( [callback](ast::AssignNode const& assign_node) -> bool { diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp index a68e922..51bbfa9 100644 --- a/src/openvic-simulation/dataloader/NodeTools.hpp +++ b/src/openvic-simulation/dataloader/NodeTools.hpp @@ -6,7 +6,7 @@ #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/types/Date.hpp" -#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/types/Vector.hpp" namespace OpenVic { namespace ast = ovdl::v2script::ast; @@ -20,6 +20,7 @@ namespace OpenVic { constexpr bool success_callback(ast::NodeCPtr) { return true; } using key_value_callback_t = callback_t<std::string_view, ast::NodeCPtr>; + constexpr bool key_value_success_callback(std::string_view, ast::NodeCPtr) { return true; } node_callback_t expect_identifier(callback_t<std::string_view> callback); node_callback_t expect_string(callback_t<std::string_view> callback); @@ -30,6 +31,8 @@ namespace OpenVic { node_callback_t expect_fixed_point(callback_t<fixed_point_t> callback); node_callback_t expect_colour(callback_t<colour_t> callback); node_callback_t expect_date(callback_t<Date> callback); + node_callback_t expect_ivec2(callback_t<ivec2_t> callback); + node_callback_t expect_fvec2(callback_t<fvec2_t> callback); node_callback_t expect_assign(key_value_callback_t callback); using length_callback_t = std::function<size_t(size_t)>; @@ -133,31 +136,38 @@ namespace OpenVic { }; } - template<typename T> - requires(std::integral<T>) - callback_t<uint64_t> assign_variable_callback_uint(const std::string_view name, T& var) { - return [&var, name](uint64_t val) -> bool { - if (val <= std::numeric_limits<T>::max()) { + template<typename I, typename T> + requires(std::integral<I>, std::integral<T>) + callback_t<I> _assign_variable_callback_int(const std::string_view name, T& var) { + return [&var, name](I val) -> bool { + if (std::numeric_limits<T>::lowest() <= val && val <= std::numeric_limits<T>::max()) { var = val; return true; } - Logger::error("Invalid ", name, ": ", val, " (valid range: [0, ", static_cast<uint64_t>(std::numeric_limits<T>::max()), "])"); + Logger::error("Invalid ", name, ": ", val, " (valid range: [", + static_cast<int64_t>(std::numeric_limits<T>::lowest()), ", ", + static_cast<uint64_t>(std::numeric_limits<T>::max()), "])"); return false; }; } template<typename T> requires(std::integral<T>) + callback_t<uint64_t> assign_variable_callback_uint(const std::string_view name, T& var) { + return _assign_variable_callback_int<uint64_t>(name, var); + } + + template<typename T> + requires(std::integral<T>) callback_t<int64_t> assign_variable_callback_int(const std::string_view name, T& var) { - return [&var, name](int64_t val) -> bool { - if (std::numeric_limits<T>::lowest() <= val && val <= std::numeric_limits<T>::max()) { - var = val; - return true; - } - Logger::error("Invalid ", name, ": ", val, " (valid range: [", - static_cast<int64_t>(std::numeric_limits<T>::lowest()), ", ", - static_cast<uint64_t>(std::numeric_limits<T>::max()), "])"); - return false; + return _assign_variable_callback_int<int64_t>(name, var); + } + + template<typename T> + callback_t<T const&> assign_variable_callback_pointer(T const*& var) { + return [&var](T const& val) -> bool { + var = &val; + return true; }; } } diff --git a/src/openvic-simulation/economy/Good.cpp b/src/openvic-simulation/economy/Good.cpp index 6edf631..8675369 100644 --- a/src/openvic-simulation/economy/Good.cpp +++ b/src/openvic-simulation/economy/Good.cpp @@ -92,7 +92,7 @@ void GoodManager::reset_to_defaults() { good.reset_to_defaults(); } -bool GoodManager::load_good_file(ast::NodeCPtr root) { +bool GoodManager::load_goods_file(ast::NodeCPtr root) { size_t total_expected_goods = 0; bool ret = expect_dictionary_reserve_length( good_categories, diff --git a/src/openvic-simulation/economy/Good.hpp b/src/openvic-simulation/economy/Good.hpp index ce97cad..6c237b1 100644 --- a/src/openvic-simulation/economy/Good.hpp +++ b/src/openvic-simulation/economy/Good.hpp @@ -74,6 +74,6 @@ namespace OpenVic { IDENTIFIER_REGISTRY_ACCESSORS(Good, good) void reset_to_defaults(); - bool load_good_file(ast::NodeCPtr root); + bool load_goods_file(ast::NodeCPtr root); }; } diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp index e8178e9..0173ab6 100644 --- a/src/openvic-simulation/map/Map.cpp +++ b/src/openvic-simulation/map/Map.cpp @@ -54,10 +54,6 @@ bool Map::add_province(const std::string_view identifier, colour_t colour) { return provinces.add_item(std::move(new_province)); } -void Map::lock_provinces() { - provinces.lock(); -} - bool Map::set_water_province(const std::string_view identifier) { if (water_provinces.is_locked()) { Logger::error("The map's water provinces have already been locked!"); @@ -133,36 +129,6 @@ bool Map::add_region(const std::string_view identifier, std::vector<std::string_ return ret; } -void Map::lock_regions() { - regions.lock(); - for (Region& region : regions.get_items()) { - if (!region.meta) { - for (Province* province : region.get_provinces()) { - if (!province->get_has_region()) { - Logger::error("Province in non-meta region without has_region set: ", province->get_identifier()); - province->has_region = true; - } - province->region = ®ion; - } - } - } - for (Province& province : provinces.get_items()) { - const bool region_null = province.get_region() == nullptr; - if (province.get_has_region() == region_null) { - Logger::error("Province has_region / region mismatch: has_region = ", province.get_has_region(), ", region = ", province.get_region()); - province.has_region = !region_null; - } - } -} - -size_t Map::get_province_count() const { - return provinces.size(); -} - -std::vector<Province> const& Map::get_provinces() const { - return provinces.get_items(); -} - Province* Map::get_province_by_index(Province::index_t index) { return index != Province::NULL_INDEX ? provinces.get_item_by_index(index - 1) : nullptr; } @@ -171,14 +137,6 @@ Province const* Map::get_province_by_index(Province::index_t index) const { return index != Province::NULL_INDEX ? provinces.get_item_by_index(index - 1) : nullptr; } -Province* Map::get_province_by_identifier(const std::string_view identifier) { - return provinces.get_item_by_identifier(identifier); -} - -Province const* Map::get_province_by_identifier(const std::string_view identifier) const { - return provinces.get_item_by_identifier(identifier); -} - Province::index_t Map::get_index_from_colour(colour_t colour) const { const colour_index_map_t::const_iterator it = colour_index_map.find(colour); if (it != colour_index_map.end()) return it->second; @@ -224,22 +182,6 @@ Province const* Map::get_selected_province() const { return get_province_by_index(get_selected_province_index()); } -Region* Map::get_region_by_identifier(const std::string_view identifier) { - return regions.get_item_by_identifier(identifier); -} - -Region const* Map::get_region_by_identifier(const std::string_view identifier) const { - return regions.get_item_by_identifier(identifier); -} - -size_t Map::get_region_count() const { - return regions.size(); -} - -std::vector<Region> const& Map::get_regions() const { - return regions.get_items(); -} - static colour_t colour_at(uint8_t const* colour_data, int32_t idx) { idx *= 3; return (colour_data[idx] << 16) | (colour_data[idx + 1] << 8) | colour_data[idx + 2]; @@ -344,6 +286,9 @@ bool Map::generate_province_shape_image(size_t new_width, size_t new_height, uin Logger::error("Province image is missing ", missing, " province colours"); ret = false; } + + ret &= _generate_province_adjacencies(); + return ret; } @@ -427,9 +372,6 @@ bool Map::setup(GoodManager const& good_manager, BuildingManager const& building bool ret = true; for (Province& province : provinces.get_items()) { province.clear_pops(); - // Set all land provinces to have an RGO based on their index to test them - if (!province.get_water() && !good_manager.get_good_count() > 0) - province.rgo = good_manager.get_good_by_index(province.get_index() % good_manager.get_good_count()); ret &= building_manager.generate_province_buildings(province); } return ret; @@ -512,6 +454,14 @@ bool Map::load_province_definitions(std::vector<LineObject> const& lines) { return ret; } +bool Map::load_province_positions(BuildingManager const& building_manager, ast::NodeCPtr root) { + return expect_province_dictionary( + [&building_manager](Province& province, ast::NodeCPtr node) -> bool { + return province.load_positions(building_manager, node); + } + )(root); +} + bool Map::load_region_file(ast::NodeCPtr root) { const bool ret = expect_dictionary_reserve_length( regions, @@ -529,5 +479,33 @@ bool Map::load_region_file(ast::NodeCPtr root) { } )(root); lock_regions(); + for (Region& region : regions.get_items()) { + if (!region.meta) { + for (Province* province : region.get_provinces()) { + if (!province->get_has_region()) { + Logger::error("Province in non-meta region without has_region set: ", province->get_identifier()); + province->has_region = true; + } + province->region = ®ion; + } + } + } + for (Province& province : provinces.get_items()) { + const bool region_null = province.get_region() == nullptr; + if (province.get_has_region() == region_null) { + Logger::error("Province has_region / region mismatch: has_region = ", province.get_has_region(), ", region = ", province.get_region()); + province.has_region = !region_null; + } + } return ret; } + +bool Map::_generate_province_adjacencies() { + /* TODO - generate default province adjacencies + * variables available for use: + * - width, height + * - province_shape_image, so the index at (x,y) is: + * province_shape_image[x + y * width].index + */ + return true; +} diff --git a/src/openvic-simulation/map/Map.hpp b/src/openvic-simulation/map/Map.hpp index d5157ef..163a21f 100644 --- a/src/openvic-simulation/map/Map.hpp +++ b/src/openvic-simulation/map/Map.hpp @@ -61,24 +61,23 @@ namespace OpenVic { Pop::pop_size_t highest_province_population, total_map_population; Province::index_t get_index_from_colour(colour_t colour) const; + bool _generate_province_adjacencies(); public: Map(); bool add_province(const std::string_view identifier, colour_t colour); - void lock_provinces(); + IDENTIFIER_REGISTRY_ACCESSORS(Province, province) + IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS(Province, province) bool set_water_province(const std::string_view identifier); bool set_water_province_list(std::vector<std::string_view> const& list); void lock_water_provinces(); bool add_region(const std::string_view identifier, std::vector<std::string_view> const& province_identifiers); - void lock_regions(); + IDENTIFIER_REGISTRY_ACCESSORS(Region, region) + IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS(Region, region) - size_t get_province_count() const; - std::vector<Province> const& get_provinces() const; Province* get_province_by_index(Province::index_t index); Province const* get_province_by_index(Province::index_t index) const; - Province* get_province_by_identifier(const std::string_view identifier); - Province const* get_province_by_identifier(const std::string_view identifier) const; Province::index_t get_province_index_at(size_t x, size_t y) const; bool set_max_provinces(Province::index_t new_max_provinces); Province::index_t get_max_provinces() const; @@ -86,11 +85,6 @@ namespace OpenVic { Province::index_t get_selected_province_index() const; Province const* get_selected_province() const; - Region* get_region_by_identifier(const std::string_view identifier); - Region const* get_region_by_identifier(const std::string_view identifier) const; - size_t get_region_count() const; - std::vector<Region> const& get_regions() const; - bool generate_province_shape_image(size_t new_width, size_t new_height, uint8_t const* colour_data, uint8_t const* terrain_data, terrain_variant_map_t const& terrain_variant_map, bool detailed_errors); size_t get_width() const; @@ -113,6 +107,7 @@ namespace OpenVic { void tick(Date const& today); bool load_province_definitions(std::vector<ovdl::csv::LineObject> const& lines); + bool load_province_positions(BuildingManager const& building_manager, ast::NodeCPtr root); bool load_region_file(ast::NodeCPtr root); }; } diff --git a/src/openvic-simulation/map/Province.cpp b/src/openvic-simulation/map/Province.cpp index 49a9bfc..775c0a4 100644 --- a/src/openvic-simulation/map/Province.cpp +++ b/src/openvic-simulation/map/Province.cpp @@ -34,6 +34,12 @@ Province::life_rating_t Province::get_life_rating() const { return life_rating; } +bool Province::load_positions(BuildingManager const& building_manager, ast::NodeCPtr root) { + // TODO - implement province position loading + // (root is the dictionary after the province identifier) + return true; +} + bool Province::add_building(Building&& building) { return buildings.add_item(std::move(building)); } diff --git a/src/openvic-simulation/map/Province.hpp b/src/openvic-simulation/map/Province.hpp index ca8138f..bf407ae 100644 --- a/src/openvic-simulation/map/Province.hpp +++ b/src/openvic-simulation/map/Province.hpp @@ -43,6 +43,8 @@ namespace OpenVic { bool get_has_region() const; bool get_water() const; life_rating_t get_life_rating() const; + bool load_positions(BuildingManager const& building_manager, ast::NodeCPtr root); + bool add_building(Building&& building); IDENTIFIER_REGISTRY_ACCESSORS(Building, building) void reset_buildings(); diff --git a/src/openvic-simulation/pop/Culture.cpp b/src/openvic-simulation/pop/Culture.cpp index bf14df9..dadc0a6 100644 --- a/src/openvic-simulation/pop/Culture.cpp +++ b/src/openvic-simulation/pop/Culture.cpp @@ -1,5 +1,7 @@ #include "Culture.hpp" +#include <set> + #include "openvic-simulation/dataloader/NodeTools.hpp" using namespace OpenVic; @@ -128,7 +130,7 @@ bool CultureManager::_load_culture_group(size_t& total_expected_cultures, }, "unit", ZERO_OR_ONE, [this, &total_expected_cultures, &unit_graphical_culture_type](ast::NodeCPtr node) -> bool { total_expected_cultures--; - return expect_graphical_culture_type(unit_graphical_culture_type)(node); + return expect_graphical_culture_type_identifier(assign_variable_callback_pointer(unit_graphical_culture_type))(node); }, "union", ZERO_OR_ONE, [&total_expected_cultures](ast::NodeCPtr) -> bool { total_expected_cultures--; @@ -207,7 +209,10 @@ bool CultureManager::load_culture_file(ast::NodeCPtr root) { CultureGroup const* culture_group = get_culture_group_by_identifier(culture_group_key); return expect_dictionary( [this, culture_group](std::string_view key, ast::NodeCPtr value) -> bool { - if (key == "leader" || key == "unit" || key == "union" || key == "is_overseas") return true; + static const std::set<std::string, std::less<void>> reserved_keys = { + "leader", "unit", "union", "is_overseas" + }; + if (reserved_keys.find(key) != reserved_keys.end()) return true; return _load_culture(culture_group, key, value); } )(culture_group_value); diff --git a/src/openvic-simulation/pop/Pop.cpp b/src/openvic-simulation/pop/Pop.cpp index 1c11b80..8feead9 100644 --- a/src/openvic-simulation/pop/Pop.cpp +++ b/src/openvic-simulation/pop/Pop.cpp @@ -142,8 +142,8 @@ bool PopManager::load_pop_into_province(Province& province, const std::string_vi Pop::pop_size_t size = 0; bool ret = expect_dictionary_keys( - "culture", ONE_EXACTLY, culture_manager.expect_culture(culture), - "religion", ONE_EXACTLY, religion_manager.expect_religion(religion), + "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("pop size", size)), "militancy", ZERO_OR_ONE, success_callback, "rebel_type", ZERO_OR_ONE, success_callback diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp index 3f73a2c..c79e51b 100644 --- a/src/openvic-simulation/types/IdentifierRegistry.hpp +++ b/src/openvic-simulation/types/IdentifierRegistry.hpp @@ -171,30 +171,72 @@ namespace OpenVic { return items; } - NodeTools::node_callback_t expect_item(T const*& ret) const { + NodeTools::node_callback_t expect_item_identifier(NodeTools::callback_t<T&> callback) { return NodeTools::expect_identifier( - [this, &ret](std::string_view identifier) -> bool { - ret = get_item_by_identifier(identifier); - if (ret != nullptr) return true; + [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::node_callback_t expect_item_identifier(NodeTools::callback_t<T const&> 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::node_callback_t expect_item_dictionary(NodeTools::callback_t<T&, ast::NodeCPtr> callback) { + return NodeTools::expect_dictionary([this, callback](std::string_view key, ast::NodeCPtr value) -> bool { + T* item = get_item_by_identifier(key); + if (item != nullptr) { + return callback(*item, value); + } + Logger::error("Invalid ", name, " identifier: ", key); + return false; + }); + } + + NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t<T const&, ast::NodeCPtr> callback) const { + return NodeTools::expect_dictionary([this, callback](std::string_view key, ast::NodeCPtr value) -> bool { + T const* item = get_item_by_identifier(key); + if (item != nullptr) { + return callback(*item, value); + } + Logger::error("Invalid ", name, " identifier: ", key); + return false; + }); + } }; #define IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(type, singular, plural) \ void lock_##plural() { plural.lock(); } \ - type const* get_##singular##_by_index(size_t index) const { \ - return plural.get_item_by_index(index); } \ type const* get_##singular##_by_identifier(const std::string_view identifier) const { \ return plural.get_item_by_identifier(identifier); } \ size_t get_##singular##_count() const { \ return plural.size(); } \ std::vector<type> const& get_##plural() const { \ return plural.get_items(); } \ - NodeTools::node_callback_t expect_##singular(type const*& ret) const { \ - return plural.expect_item(ret); } + NodeTools::node_callback_t expect_##singular##_identifier(NodeTools::callback_t<type const&> callback) const { \ + return plural.expect_item_identifier(callback); } \ + NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t<type const&, ast::NodeCPtr> callback) const { \ + return plural.expect_item_dictionary(callback); } + +#define IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS_CUSTOM_PLURAL(type, singular, plural) \ + type* get_##singular##_by_identifier(const std::string_view identifier) { \ + return plural.get_item_by_identifier(identifier); } \ + NodeTools::node_callback_t expect_##singular##_identifier(NodeTools::callback_t<type&> callback) { \ + return plural.expect_item_identifier(callback); } \ + NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t<type&, ast::NodeCPtr> 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) } diff --git a/src/openvic-simulation/types/Vector.hpp b/src/openvic-simulation/types/Vector.hpp index fdf7d70..66f8d2b 100644 --- a/src/openvic-simulation/types/Vector.hpp +++ b/src/openvic-simulation/types/Vector.hpp @@ -27,6 +27,7 @@ namespace OpenVic { constexpr friend vec2_t operator-(vec2_t const& arg); constexpr friend vec2_t operator-(vec2_t const& left, vec2_t const& right); constexpr vec2_t& operator-=(vec2_t const& right); + constexpr friend std::ostream& operator<<(std::ostream& stream, vec2_t const& value); }; |