aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
m---------deps/lexy-vdf0
m---------deps/openvic-dataloader0
m---------scripts0
-rw-r--r--src/openvic-simulation/GameManager.cpp92
-rw-r--r--src/openvic-simulation/GameManager.hpp51
-rw-r--r--src/openvic-simulation/Modifier.cpp16
-rw-r--r--src/openvic-simulation/Modifier.hpp36
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp94
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.hpp8
-rw-r--r--src/openvic-simulation/dataloader/NodeTools.cpp136
-rw-r--r--src/openvic-simulation/dataloader/NodeTools.hpp151
-rw-r--r--src/openvic-simulation/economy/Building.cpp (renamed from src/openvic-simulation/map/Building.cpp)14
-rw-r--r--src/openvic-simulation/economy/Building.hpp (renamed from src/openvic-simulation/map/Building.hpp)8
-rw-r--r--src/openvic-simulation/economy/EconomyManager.hpp26
-rw-r--r--src/openvic-simulation/economy/Good.hpp4
-rw-r--r--src/openvic-simulation/economy/ProductionType.cpp84
-rw-r--r--src/openvic-simulation/economy/ProductionType.hpp10
-rw-r--r--src/openvic-simulation/map/Map.cpp7
-rw-r--r--src/openvic-simulation/map/Map.hpp12
-rw-r--r--src/openvic-simulation/map/Province.hpp5
-rw-r--r--src/openvic-simulation/map/TerrainType.cpp105
-rw-r--r--src/openvic-simulation/map/TerrainType.hpp6
-rw-r--r--src/openvic-simulation/military/MilitaryManager.hpp12
-rw-r--r--src/openvic-simulation/military/Unit.cpp (renamed from src/openvic-simulation/units/Unit.cpp)74
-rw-r--r--src/openvic-simulation/military/Unit.hpp (renamed from src/openvic-simulation/units/Unit.hpp)22
-rw-r--r--src/openvic-simulation/politics/Government.cpp132
-rw-r--r--src/openvic-simulation/politics/Government.hpp57
-rw-r--r--src/openvic-simulation/politics/Ideology.hpp4
-rw-r--r--src/openvic-simulation/politics/Issue.cpp11
-rw-r--r--src/openvic-simulation/politics/Issue.hpp10
-rw-r--r--src/openvic-simulation/politics/PoliticsManager.hpp22
-rw-r--r--src/openvic-simulation/pop/Culture.cpp18
-rw-r--r--src/openvic-simulation/pop/Culture.hpp8
-rw-r--r--src/openvic-simulation/pop/Pop.cpp36
-rw-r--r--src/openvic-simulation/pop/Pop.hpp2
-rw-r--r--src/openvic-simulation/pop/Religion.cpp2
-rw-r--r--src/openvic-simulation/pop/Religion.hpp4
-rw-r--r--src/openvic-simulation/testing/test_scripts/A_002_economy_tests.cpp2
-rw-r--r--src/openvic-simulation/types/Date.cpp13
-rw-r--r--src/openvic-simulation/types/Date.hpp4
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.cpp2
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.hpp176
-rw-r--r--src/openvic-simulation/types/Vector.cpp4
-rw-r--r--src/openvic-simulation/types/Vector.hpp12
-rw-r--r--src/openvic-simulation/utility/Logger.hpp3
45 files changed, 815 insertions, 680 deletions
diff --git a/deps/lexy-vdf b/deps/lexy-vdf
-Subproject eeb10288f707cdc87981b43edc441fc833b6cff
+Subproject 96c316c52b45e2fa78a9562938f931f97247451
diff --git a/deps/openvic-dataloader b/deps/openvic-dataloader
-Subproject 92961412af3ae908633b4ef7b8453091448ffd4
+Subproject 92c67f318114771999a73b05659023b59b103e0
diff --git a/scripts b/scripts
-Subproject 3060e56388ac00d90deb6693ec19d47bad52deb
+Subproject accb77a0af7d200818d4521b12492c078e4b7f4
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 3acfa56..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<ModifierValue&&> modifier_callback, key_value_callback_t default_callback) const {
+node_callback_t ModifierManager::expect_modifier_value_and_default(callback_t<ModifierValue&&> 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,16 +154,24 @@ node_callback_t ModifierManager::expect_modifier_value(callback_t<ModifierValue&
};
}
-node_callback_t ModifierManager::_expect_modifier_value_and_keys(callback_t<ModifierValue&&> modifier_callback, key_map_t&& key_map) const {
+node_callback_t ModifierManager::expect_modifier_value(callback_t<ModifierValue&&> 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<ModifierValue&&> 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(
- modifier_callback, dictionary_keys_callback(key_map, false)
+ 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);
return ret;
};
}
+node_callback_t ModifierManager::expect_modifier_value_and_key_map(callback_t<ModifierValue&&> 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 f88102b..2e1b03a 100644
--- a/src/openvic-simulation/Modifier.hpp
+++ b/src/openvic-simulation/Modifier.hpp
@@ -92,33 +92,39 @@ namespace OpenVic {
IdentifierRegistry<ModifierEffect> modifier_effects;
IdentifierRegistry<Modifier> modifiers;
- NodeTools::node_callback_t _expect_modifier_value_and_keys(NodeTools::callback_t<ModifierValue&&> modifier_callback, NodeTools::key_map_t&& key_map) const;
-
- template<typename... Args>
- NodeTools::node_callback_t _expect_modifier_value_and_keys(
- NodeTools::callback_t<ModifierValue&&> 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();
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();
- NodeTools::node_callback_t expect_modifier_value(NodeTools::callback_t<ModifierValue&&> modifier_callback, NodeTools::key_value_callback_t default_callback) const;
+ NodeTools::node_callback_t expect_modifier_value_and_default(NodeTools::callback_t<ModifierValue&&> modifier_callback, NodeTools::key_value_callback_t default_callback) const;
+ NodeTools::node_callback_t expect_modifier_value(NodeTools::callback_t<ModifierValue&&> modifier_callback) const;
+
+ NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default(NodeTools::callback_t<ModifierValue&&> 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<ModifierValue&&> modifier_callback, NodeTools::key_map_t&& key_map) const;
template<typename... Args>
+ NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default(
+ NodeTools::callback_t<ModifierValue&&> 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<typename... Args>
+ NodeTools::node_callback_t expect_modifier_value_and_keys_and_default(NodeTools::callback_t<ModifierValue&&> 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<typename... Args>
NodeTools::node_callback_t expect_modifier_value_and_keys(NodeTools::callback_t<ModifierValue&&> 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 70164c3..718218f 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<fs::path const&> 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;
}
@@ -433,6 +436,14 @@ v2script::Parser Dataloader::parse_defines(fs::path const& path) {
return _run_ovdl_parser<v2script::Parser, &_v2script_parse>(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<v2script::Parser, &_lua_parse>(path);
+}
+
static bool _csv_parse(csv::Windows1252Parser& parser) {
return parser.parse_csv();
}
@@ -441,12 +452,6 @@ csv::Windows1252Parser Dataloader::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(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 +462,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 +504,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<Province::index_t>(
+ std::bind(&Map::set_max_provinces, &map, std::placeholders::_1)
),
"sea_starts", ONE_EXACTLY,
expect_list_reserve_length(
@@ -537,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;
}
@@ -556,19 +557,23 @@ 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())) {
+ 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;
}
@@ -597,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;
}
@@ -605,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!");
@@ -648,7 +657,8 @@ 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_military_manager().get_unit_manager(),
+ game_manager.get_economy_manager().get_good_manager(), units_directory)) {
Logger::error("Failed to load units!");
ret = false;
}
@@ -659,11 +669,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..c4cd7c7 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,11 +24,12 @@ 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:
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;
@@ -89,5 +91,3 @@ namespace OpenVic {
inline static std::unordered_map<hint_path_t, game_path_t, fshash> _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<T const&> callback) {
};
}
-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) {
- return [callback](T const& node) -> bool {
- return callback(node._name);
+template<std::derived_from<ast::AbstractStringNode> T>
+static callback_t<T const&> _abstract_string_node_callback(callback_t<std::string_view> 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<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, false));
}
-node_callback_t NodeTools::expect_string(callback_t<std::string_view> callback) {
- return _expect_type<ast::StringNode>(_abstract_string_node_callback<ast::StringNode>(callback));
+node_callback_t NodeTools::expect_string(callback_t<std::string_view> callback, bool allow_empty) {
+ return _expect_type<ast::StringNode>(_abstract_string_node_callback<ast::StringNode>(callback, allow_empty));
}
node_callback_t NodeTools::expect_identifier_or_string(callback_t<std::string_view> callback) {
@@ -43,7 +51,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<ast::AbstractStringNode>(callback)(*cast_node);
+ return _abstract_string_node_callback<ast::AbstractStringNode>(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<std::string_vi
}
node_callback_t NodeTools::expect_bool(callback_t<bool> 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> bool_map = {
+ { "yes", true }, { "no", false }
+ };
+ return expect_identifier(expect_mapped_string(bool_map, callback));
+}
+
+node_callback_t NodeTools::expect_int_bool(callback_t<bool> callback) {
+ static const string_map_t<bool> bool_map = {
+ { "1", true }, { "0", false }
+ };
+ return expect_identifier(expect_mapped_string(bool_map, callback));
}
-node_callback_t NodeTools::expect_int(callback_t<int64_t> callback) {
+node_callback_t NodeTools::expect_int64(callback_t<int64_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<int64_t> callback) {
);
}
-node_callback_t NodeTools::expect_uint(callback_t<uint64_t> callback) {
+node_callback_t NodeTools::expect_uint64(callback_t<uint64_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<colour_t> callback) {
};
}
-node_callback_t NodeTools::expect_timespan(callback_t<Timespan> callback) {
- return expect_int(callback);
-}
-
node_callback_t NodeTools::expect_date(callback_t<Date> callback) {
return expect_identifier(
[callback](std::string_view identifier) -> bool {
@@ -152,6 +156,24 @@ node_callback_t NodeTools::expect_date(callback_t<Date> callback) {
);
}
+node_callback_t NodeTools::expect_years(callback_t<Timespan> callback) {
+ return expect_uint<Timespan::day_t>([callback](Timespan::day_t val) -> bool {
+ return callback(Timespan::fromYears(val));
+ });
+}
+
+node_callback_t NodeTools::expect_months(callback_t<Timespan> callback) {
+ return expect_uint<Timespan::day_t>([callback](Timespan::day_t val) -> bool {
+ return callback(Timespan::fromMonths(val));
+ });
+}
+
+node_callback_t NodeTools::expect_days(callback_t<Timespan> callback) {
+ return expect_uint<Timespan::day_t>([callback](Timespan::day_t val) -> bool {
+ return callback(Timespan::fromDays(val));
+ });
+}
+
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 {
@@ -166,7 +188,7 @@ node_callback_t _expect_vec2(callback_t<vec2_t<T>> callback) {
}
node_callback_t NodeTools::expect_ivec2(callback_t<ivec2_t> callback) {
- return _expect_vec2<int64_t, expect_int>(callback);
+ return _expect_vec2<int32_t, expect_int>(callback);
}
node_callback_t NodeTools::expect_fvec2(callback_t<fvec2_t> callback) {
@@ -238,17 +260,24 @@ node_callback_t NodeTools::expect_length(callback_t<size_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<ast::AbstractListNode>(
- [key, callback](ast::AbstractListNode const& list_node) -> bool {
+ [key, callback, key_found](ast::AbstractListNode const& list_node) -> bool {
std::vector<ast::NodeUPtr> const& list = list_node._statements;
for (ast::NodeUPtr const& sub_node : list_node._statements) {
ast::AssignNode const* assign_node = sub_node->cast_to<ast::AssignNode>();
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<std::string>& list) {
return expect_list_reserve_length(
list,
@@ -325,3 +375,7 @@ node_callback_t NodeTools::name_list_callback(std::vector<std::string>& list) {
)
);
}
+
+callback_t<std::string_view> NodeTools::assign_variable_callback_string(std::string& var) {
+ return assign_variable_callback_cast<std::string_view>(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<typename T>
+ using string_map_t = std::map<std::string, T, std::less<void>>;
+
namespace NodeTools {
template<typename... Args>
@@ -21,17 +26,55 @@ namespace OpenVic {
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; }
+ 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<std::string_view> callback);
- node_callback_t expect_string(callback_t<std::string_view> callback);
+ node_callback_t expect_string(callback_t<std::string_view> callback, bool allow_empty = true);
node_callback_t expect_identifier_or_string(callback_t<std::string_view> callback);
+
node_callback_t expect_bool(callback_t<bool> callback);
- node_callback_t expect_int(callback_t<int64_t> callback);
- node_callback_t expect_uint(callback_t<uint64_t> callback);
+ node_callback_t expect_int_bool(callback_t<bool> callback);
+
+ node_callback_t expect_int64(callback_t<int64_t> callback);
+ node_callback_t expect_uint64(callback_t<uint64_t> callback);
+
+ template<std::signed_integral T>
+ node_callback_t expect_int(callback_t<T> callback) {
+ return expect_int64([callback](int64_t val) -> bool {
+ if (static_cast<int64_t>(std::numeric_limits<T>::lowest()) <= val &&
+ val <= static_cast<int64_t>(std::numeric_limits<T>::max())) {
+ return callback(val);
+ }
+ Logger::error("Invalid int: ", val, " (valid range: [",
+ static_cast<int64_t>(std::numeric_limits<T>::lowest()), ", ",
+ static_cast<int64_t>(std::numeric_limits<T>::max()), "])");
+ return false;
+ });
+ }
+
+ template<std::integral T>
+ node_callback_t expect_uint(callback_t<T> callback) {
+ return expect_uint64([callback](uint64_t val) -> bool {
+ if (val <= static_cast<uint64_t>(std::numeric_limits<T>::max())) {
+ return callback(val);
+ }
+ Logger::error("Invalid uint: ", val, " (valid range: [0, ",
+ static_cast<uint64_t>(std::numeric_limits<T>::max()), "])");
+ return false;
+ });
+ }
+
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_timespan(callback_t<Timespan> callback);
+
node_callback_t expect_date(callback_t<Date> callback);
+ node_callback_t expect_years(callback_t<Timespan> callback);
+ node_callback_t expect_months(callback_t<Timespan> callback);
+ node_callback_t expect_days(callback_t<Timespan> 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);
@@ -44,7 +87,7 @@ namespace OpenVic {
node_callback_t expect_list(node_callback_t callback);
node_callback_t expect_length(callback_t<size_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<std::string, dictionary_entry_t, std::less<void>>;
+ using key_map_t = string_map_t<dictionary_entry_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<typename... Args>
- 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<typename... Args>
- 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<typename... Args>
- 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<typename... Args>
+ 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<typename... Args>
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<typename T>
@@ -133,7 +180,19 @@ namespace OpenVic {
node_callback_t name_list_callback(std::vector<std::string>& list);
template<typename T>
- callback_t<T> assign_variable_callback(T& var) {
+ callback_t<std::string_view> expect_mapped_string(string_map_t<T> const& map, callback_t<T> callback) {
+ return [&map, callback](std::string_view string) -> bool {
+ const typename string_map_t<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<typename T, typename U>
+ callback_t<T> assign_variable_callback_cast(U& var) {
return [&var](T val) -> bool {
var = val;
return true;
@@ -141,6 +200,13 @@ namespace OpenVic {
}
template<typename T>
+ callback_t<T> assign_variable_callback(T& var) {
+ return assign_variable_callback_cast<T, T>(var);
+ }
+
+ callback_t<std::string_view> assign_variable_callback_string(std::string& var);
+
+ template<typename T>
callback_t<T&&> move_variable_callback(T& var) {
return [&var](T&& val) -> bool {
var = std::move(val);
@@ -161,41 +227,12 @@ namespace OpenVic {
template<typename T>
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<typename T>
- requires(std::integral<T>)
- callback_t<uint64_t> assign_variable_callback_uint(T& var) {
- return [&var](uint64_t val) -> bool {
- if (val <= static_cast<uint64_t>(std::numeric_limits<T>::max())) {
- var = val;
- return true;
- }
- Logger::error("Invalid uint: ", val, " (valid range: [0, ",
- static_cast<uint64_t>(std::numeric_limits<T>::max()), "])");
- return false;
- };
+ t++;
}
-
- template<typename T>
- requires(std::signed_integral<T>)
- callback_t<int64_t> assign_variable_callback_int(T& var) {
- return [&var](int64_t val) -> bool {
- if (static_cast<int64_t>(std::numeric_limits<T>::lowest()) <= val && val <= static_cast<int64_t>(std::numeric_limits<T>::max())) {
- var = val;
- return true;
- }
- Logger::error("Invalid int: ", val, " (valid range: [",
- static_cast<int64_t>(std::numeric_limits<T>::lowest()), ", ",
- static_cast<int64_t>(std::numeric_limits<T>::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/map/Building.cpp b/src/openvic-simulation/economy/Building.cpp
index 6f4c099..23bd04c 100644
--- a/src/openvic-simulation/map/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;
}
@@ -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/economy/Building.hpp
index 9b445bf..3d1e24b 100644
--- a/src/openvic-simulation/map/Building.hpp
+++ b/src/openvic-simulation/economy/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;
@@ -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<Good const*, fixed_point_t> const& get_goods_cost() const;
@@ -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/economy/EconomyManager.hpp b/src/openvic-simulation/economy/EconomyManager.hpp
new file mode 100644
index 0000000..05dfc91
--- /dev/null
+++ b/src/openvic-simulation/economy/EconomyManager.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "openvic-simulation/economy/Building.hpp"
+#include "openvic-simulation/economy/Good.hpp"
+#include "openvic-simulation/economy/ProductionType.hpp"
+
+namespace OpenVic {
+ struct EconomyManager {
+ private:
+ BuildingManager building_manager;
+ GoodManager good_manager;
+ ProductionTypeManager production_type_manager;
+ public:
+ REF_GETTERS(building_manager)
+ REF_GETTERS(good_manager)
+ REF_GETTERS(production_type_manager)
+
+ inline bool load_production_types_file(PopManager const& pop_manager, ast::NodeCPtr root) {
+ return production_type_manager.load_production_types_file(good_manager, pop_manager, root);
+ }
+
+ inline bool load_buildings_file(ModifierManager const& modifier_manager, ast::NodeCPtr root) {
+ return building_manager.load_buildings_file(good_manager, production_type_manager, modifier_manager, root);
+ }
+ };
+}
diff --git a/src/openvic-simulation/economy/Good.hpp b/src/openvic-simulation/economy/Good.hpp
index 7f020fe..1dce41f 100644
--- a/src/openvic-simulation/economy/Good.hpp
+++ b/src/openvic-simulation/economy/Good.hpp
@@ -66,11 +66,11 @@ namespace OpenVic {
GoodManager();
bool add_good_category(std::string_view identifier);
- IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(GoodCategory, good_category, good_categories)
+ IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(good_category, good_categories)
bool add_good(std::string_view identifier, colour_t colour, GoodCategory const* category, Good::price_t base_price,
bool available_from_start, bool tradeable, bool money, bool overseas_penalty);
- IDENTIFIER_REGISTRY_ACCESSORS(Good, good)
+ IDENTIFIER_REGISTRY_ACCESSORS(good)
void reset_to_defaults();
bool load_goods_file(ast::NodeCPtr root);
diff --git a/src/openvic-simulation/economy/ProductionType.cpp b/src/openvic-simulation/economy/ProductionType.cpp
index 2c7c431..01d45be 100644
--- a/src/openvic-simulation/economy/ProductionType.cpp
+++ b/src/openvic-simulation/economy/ProductionType.cpp
@@ -82,16 +82,22 @@ bool ProductionType::is_mine() const {
ProductionTypeManager::ProductionTypeManager() : production_types { "production types" } {}
-node_callback_t ProductionTypeManager::_expect_employed_pop(GoodManager& good_manager, PopManager& pop_manager,
+node_callback_t ProductionTypeManager::_expect_employed_pop(GoodManager const& good_manager, PopManager const& pop_manager,
callback_t<EmployedPop> cb) {
return [this, &good_manager, &pop_manager, cb](ast::NodeCPtr node) -> bool {
- std::string_view pop_type, effect;
+ std::string_view pop_type;
+ EmployedPop::effect_t effect;
fixed_point_t effect_multiplier = 1, amount = 1;
+ using enum EmployedPop::effect_t;
+ static const string_map_t<EmployedPop::effect_t> effect_map = {
+ { "input", INPUT }, { "output", OUTPUT }, { "throughput", THROUGHPUT }
+ };
+
bool res = expect_dictionary_keys(
"poptype", ONE_EXACTLY, expect_identifier(assign_variable_callback(pop_type)),
- "effect", ONE_EXACTLY, expect_identifier(assign_variable_callback(effect)),
+ "effect", ONE_EXACTLY, expect_identifier(expect_mapped_string(effect_map, assign_variable_callback(effect))),
"effect_multiplier", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(effect_multiplier)),
"amount", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(amount))
)(node);
@@ -107,20 +113,11 @@ node_callback_t ProductionTypeManager::_expect_employed_pop(GoodManager& good_ma
}
}
- EmployedPop::effect_t found_effect;
- if (effect == "input") found_effect = EmployedPop::effect_t::INPUT;
- else if (effect == "output") found_effect = EmployedPop::effect_t::OUTPUT;
- else if (effect == "throughput") found_effect = EmployedPop::effect_t::THROUGHPUT;
- else {
- Logger::error("Found invalid effect ", effect, " while parsing production types!");
- return false;
- }
-
- return res & cb(EmployedPop { found_pop_type, artisan, found_effect, effect_multiplier, amount });
+ return res & cb(EmployedPop { found_pop_type, artisan, effect, effect_multiplier, amount });
};
}
-node_callback_t ProductionTypeManager::_expect_employed_pop_list(GoodManager& good_manager, PopManager& pop_manager,
+node_callback_t ProductionTypeManager::_expect_employed_pop_list(GoodManager const& good_manager, PopManager const& pop_manager,
callback_t<std::vector<EmployedPop>> cb) {
return [this, &good_manager, &pop_manager, cb](ast::NodeCPtr node) -> bool {
@@ -141,7 +138,7 @@ node_callback_t ProductionTypeManager::_expect_employed_pop_list(GoodManager& go
return false; \
}
-bool ProductionTypeManager::add_production_type(PRODUCTION_TYPE_ARGS, GoodManager& good_manager) {
+bool ProductionTypeManager::add_production_type(PRODUCTION_TYPE_ARGS, GoodManager const& good_manager) {
if (identifier.empty()) {
Logger::error("Invalid production type identifier - empty!");
return false;
@@ -174,21 +171,22 @@ bool ProductionTypeManager::add_production_type(PRODUCTION_TYPE_ARGS, GoodManage
});
}
-#define PARSE_NODE(target_node) expect_dictionary_keys(ALLOW_OTHER_KEYS, \
+#define PARSE_NODE expect_dictionary_keys_and_default( \
+ key_value_success_callback, \
"owner", ZERO_OR_ONE, _expect_employed_pop(good_manager, pop_manager, move_variable_callback(owner)), \
"employees", ZERO_OR_ONE, _expect_employed_pop_list(good_manager, pop_manager, move_variable_callback(employees)), \
- "type", ZERO_OR_ONE, expect_identifier(assign_variable_callback(type)), \
- "workforce", ZERO_OR_ONE, expect_uint(assign_variable_callback_uint(workforce)), \
+ "type", ZERO_OR_ONE, expect_identifier(expect_mapped_string(type_map, assign_variable_callback(type))), \
+ "workforce", ZERO_OR_ONE, expect_uint(assign_variable_callback(workforce)), \
"input_goods", ZERO_OR_ONE, good_manager.expect_good_decimal_map(move_variable_callback(input_goods)), \
- "output_goods", ZERO_OR_ONE, good_manager.expect_good_identifier(assign_variable_callback_pointer(output_goods)), \
+ "output_goods", ZERO_OR_ONE, expect_identifier(good_manager.expect_good_identifier(assign_variable_callback_pointer(output_goods))), \
"value", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(value)), \
"efficiency", ZERO_OR_ONE, good_manager.expect_good_decimal_map(move_variable_callback(efficiency)), \
"is_coastal", ZERO_OR_ONE, expect_bool(assign_variable_callback(coastal)), \
"farm", ZERO_OR_ONE, expect_bool(assign_variable_callback(farm)), \
"mine", ZERO_OR_ONE, expect_bool(assign_variable_callback(mine)) \
- )(target_node)
+ )
-bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager, PopManager& pop_manager, ast::NodeCPtr root) {
+bool ProductionTypeManager::load_production_types_file(GoodManager const& good_manager, PopManager const& pop_manager, ast::NodeCPtr root) {
size_t expected_types = 0;
// pass 1: find and store template identifiers
@@ -196,25 +194,27 @@ bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager
std::map<std::string_view, std::string_view> template_target_map;
bool ret = expect_dictionary(
[this, &expected_types, &templates, &template_target_map](std::string_view key, ast::NodeCPtr value) -> bool {
- std::string_view template_id = "";
- bool ret = expect_dictionary_keys(ALLOW_OTHER_KEYS,
- "template", ZERO_OR_ONE, expect_identifier(assign_variable_callback(template_id))
- )(value);
-
- if (!template_id.empty()) {
- templates.emplace(template_id);
- template_target_map.emplace(key, template_id);
- }
-
expected_types++;
- return ret;
+ std::string_view template_id = "";
+ bool found_template = false;
+ const bool ret = expect_key("template", expect_identifier(assign_variable_callback(template_id)), &found_template)(value);
+ if (found_template) {
+ if (ret) {
+ templates.emplace(template_id);
+ template_target_map.emplace(key, template_id);
+ } else {
+ Logger::error("Failed get template identifier for ", key);
+ return false;
+ }
+ }
+ return true;
}
)(root);
// pass 2: create and populate the template map
std::map<std::string_view, ast::NodeCPtr> template_node_map;
- expect_dictionary(
+ ret &= expect_dictionary(
[this, &expected_types, &templates, &template_node_map](std::string_view key, ast::NodeCPtr value) -> bool {
if (templates.contains(key)) {
template_node_map.emplace(key, value);
@@ -233,7 +233,7 @@ bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager
EmployedPop owner;
std::vector<EmployedPop> employees;
- std::string_view type;
+ ProductionType::type_t type;
Good const* output_goods = nullptr;
Pop::pop_size_t workforce = 0; // 0 is a meaningless value -> unset
std::map<Good const*, fixed_point_t> input_goods, efficiency;
@@ -243,6 +243,11 @@ bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager
bool ret = true;
+ using enum ProductionType::type_t;
+ static const string_map_t<ProductionType::type_t> type_map = {
+ { "factory", FACTORY }, { "rgo", RGO }, { "artisan", ARTISAN }
+ };
+
// apply template first
if (template_target_map.contains(key)) {
std::string_view template_id = template_target_map[key];
@@ -254,17 +259,8 @@ bool ProductionTypeManager::load_production_types_file(GoodManager& good_manager
ret &= PARSE_NODE(node);
- ProductionType::type_t type_enum;
- if (type == "factory") type_enum = ProductionType::type_t::FACTORY;
- else if (type == "rgo") type_enum = ProductionType::type_t::RGO;
- else if (type == "artisan") type_enum = ProductionType::type_t::ARTISAN;
- else {
- Logger::error("Invalid production type for ", key, ": ", type);
- ret = false;
- }
-
ret &= add_production_type(
- key, owner, employees, type_enum, workforce, input_goods, output_goods, value,
+ key, owner, employees, type, workforce, input_goods, output_goods, value,
bonuses, efficiency, coastal, farm, mine, good_manager
);
return ret;
diff --git a/src/openvic-simulation/economy/ProductionType.hpp b/src/openvic-simulation/economy/ProductionType.hpp
index 755eda8..420e70e 100644
--- a/src/openvic-simulation/economy/ProductionType.hpp
+++ b/src/openvic-simulation/economy/ProductionType.hpp
@@ -95,17 +95,17 @@ namespace OpenVic {
private:
IdentifierRegistry<ProductionType> production_types;
- NodeTools::node_callback_t _expect_employed_pop(GoodManager& good_manager, PopManager& pop_manager,
+ NodeTools::node_callback_t _expect_employed_pop(GoodManager const& good_manager, PopManager const& pop_manager,
NodeTools::callback_t<EmployedPop> cb);
- NodeTools::node_callback_t _expect_employed_pop_list(GoodManager& good_manager, PopManager& pop_manager,
+ NodeTools::node_callback_t _expect_employed_pop_list(GoodManager const& good_manager, PopManager const& pop_manager,
NodeTools::callback_t<std::vector<EmployedPop>> cb);
public:
ProductionTypeManager();
- bool add_production_type(PRODUCTION_TYPE_ARGS, GoodManager& good_manager);
- IDENTIFIER_REGISTRY_ACCESSORS(ProductionType, production_type)
+ bool add_production_type(PRODUCTION_TYPE_ARGS, GoodManager const& good_manager);
+ IDENTIFIER_REGISTRY_ACCESSORS(production_type)
- bool load_production_types_file(GoodManager& good_manager, PopManager& pop_manager, ast::NodeCPtr root);
+ bool load_production_types_file(GoodManager const& good_manager, PopManager const& pop_manager, ast::NodeCPtr root);
};
} \ No newline at end of file
diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp
index 386e7be..acd882e 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<std::string_view> 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;
}
@@ -271,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 9c97960..578b471 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<std::string_view> const& list);
@@ -93,16 +93,16 @@ namespace OpenVic {
TerrainTypeManager const& get_terrain_type_manager() const;
bool add_region(std::string_view identifier, std::vector<std::string_view> 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;
- 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 31b5d4c..d925898 100644
--- a/src/openvic-simulation/map/Province.hpp
+++ b/src/openvic-simulation/map/Province.hpp
@@ -2,7 +2,7 @@
#include <cassert>
-#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<index_t>::max();
@@ -93,7 +92,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<TerrainTypeMapping::index_t>&& 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<TerrainTypeMapping::index_t> 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<TerrainTypeMapping::index_t>::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<TerrainTypeMapping::index_t>(
+ [&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<TerrainTypeMapping::index_t>&& 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/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/units/Unit.cpp b/src/openvic-simulation/military/Unit.cpp
index 8d519f1..63ece91 100644
--- a/src/openvic-simulation/units/Unit.cpp
+++ b/src/openvic-simulation/military/Unit.cpp
@@ -1,9 +1,12 @@
#include "Unit.hpp"
+#include <set>
+
#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
@@ -24,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;
}
@@ -32,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;
}
@@ -76,9 +79,26 @@ std::map<Good const*, fixed_point_t> 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_view LandUnit::get_sprite_override() const {
+ return sprite_override;
+}
+
+std::string_view LandUnit::get_sprite_mount() const {
+ return sprite_mount;
+}
+
+std::string_view LandUnit::get_sprite_mount_attach_node() const {
+ return sprite_mount_attach_node;
+}
fixed_point_t LandUnit::get_reconnaissance() const {
return reconnaissance;
@@ -126,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;
}
@@ -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<std::string, std::less<void>> 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<Good const*, fixed_point_t> 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/military/Unit.hpp
index 3555cce..de30763 100644
--- a/src/openvic-simulation/units/Unit.hpp
+++ b/src/openvic-simulation/military/Unit.hpp
@@ -14,8 +14,9 @@
fixed_point_t maximum_speed, fixed_point_t weighted_value, Timespan build_time, \
std::map<Good const*, fixed_point_t> build_cost, fixed_point_t supply_consumption, \
std::map<Good const*, fixed_point_t> 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, \
@@ -56,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;
@@ -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_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;
fixed_point_t get_defence() const;
@@ -130,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;
@@ -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/politics/Government.cpp b/src/openvic-simulation/politics/Government.cpp
index 869ac3d..16b3bc4 100644
--- a/src/openvic-simulation/politics/Government.cpp
+++ b/src/openvic-simulation/politics/Government.cpp
@@ -2,98 +2,110 @@
#include <set>
-#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<Ideology const*> 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<Ideology const*>&& 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<Ideology const*> 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;
+ return flag_type_identifier;
}
GovernmentTypeManager::GovernmentTypeManager() : government_types { "government types" } {}
-bool GovernmentTypeManager::add_government_type(std::string_view identifier, std::vector<Ideology const*> 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<Ideology const*> 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<Ideology const*> 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<std::string, std::less<void>> 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<Ideology const*> 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<std::string, std::less<void>> 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..ba8496f 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<Ideology const*> ideologies;
- const bool elections, appoint_ruling_party;
- const Timespan election_duration;
- const std::string flag_type_identifier;
+ private:
+ const std::vector<Ideology const*> 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<Ideology const*> 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<Ideology const*>&& 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<Ideology const*> 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<Ideology const*> const& get_ideologies() const;
+ bool holds_elections() const;
+ bool can_appoint_ruling_party() const;
+ Timespan get_term_duration() const;
+ std::string_view get_flag_type() const;
+ };
- struct GovernmentTypeManager {
- private:
- IdentifierRegistry<GovernmentType> government_types;
+ struct GovernmentTypeManager {
+ private:
+ IdentifierRegistry<GovernmentType> government_types;
- public:
- GovernmentTypeManager();
+ public:
+ GovernmentTypeManager();
- bool add_government_type(std::string_view identifier, std::vector<Ideology const*> 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<Ideology const*> 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);
- };
-} // namespace OpenVic
+ 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/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/pop/Culture.cpp b/src/openvic-simulation/pop/Culture.cpp
index 6285305..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;
}
@@ -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..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;
};
@@ -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<std::string> const& first_names, std::vector<std::string> 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<PopType::strata_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<std::string, PopType::strata_t, std::less<void>>;
- 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/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/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.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 7fe2656..3ba7fc4 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,
@@ -24,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);
@@ -68,42 +72,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<typename T>
- requires(std::derived_from<T, HasIdentifier>)
- class IdentifierRegistry {
- using identifier_index_map_t = std::map<std::string, size_t, std::less<void>>;
+ using get_identifier_func_t = std::string_view(T::*)(void) const;
+
+ template<typename _Base, std::derived_from<_Base> _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<T> items;
+ std::vector<_Storage> items;
bool locked = false;
- identifier_index_map_t identifier_index_map;
+ string_map_t<size_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 {
+ std::string_view 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);
+ 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) {
- 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.emplace(new_identifier, items.size());
items.push_back(std::move(item));
return true;
}
@@ -143,15 +155,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 +171,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 +183,38 @@ namespace OpenVic {
return get_item_by_index(index) != nullptr;
}
- std::vector<T>& get_items() {
- return items;
- }
-
- std::vector<T> const& get_items() const {
- return items;
- }
+ REF_GETTERS(items)
std::vector<std::string_view> get_item_identifiers() const {
std::vector<std::string_view> 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<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<std::string_view> expect_item_identifier(NodeTools::callback_t<value_type&> 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<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::callback_t<std::string_view> expect_item_identifier(NodeTools::callback_t<value_type const&> 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<T&, ast::NodeCPtr> callback) {
+ NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t<value_type&, ast::NodeCPtr> 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 +223,9 @@ namespace OpenVic {
});
}
- NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t<T const&, ast::NodeCPtr> callback) const {
+ NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t<value_type 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);
+ value_type const* item = get_item_by_identifier(key);
if (item != nullptr) {
return callback(*item, value);
}
@@ -232,10 +234,10 @@ namespace OpenVic {
});
}
- NodeTools::node_callback_t expect_item_decimal_map(NodeTools::callback_t<std::map<T const*, fixed_point_t>&&> callback) const {
+ NodeTools::node_callback_t expect_item_decimal_map(NodeTools::callback_t<std::map<value_type const*, fixed_point_t>&&> callback) const {
return [this, callback](ast::NodeCPtr node) -> bool {
- std::map<T const*, fixed_point_t> map;
- bool ret = expect_item_dictionary([&map](T const& key, ast::NodeCPtr value) -> bool {
+ std::map<value_type const*, fixed_point_t> 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 +249,64 @@ namespace OpenVic {
}
};
-#define IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(type, singular, plural) \
+ template<typename T>
+ [[nodiscard]] inline constexpr T* _addressof(T& v) noexcept {
+ return std::addressof<T>(v);
+ }
+
+ template<typename T>
+ const T* _addressof(const T&&) = delete;
+
+ template<typename _Base, std::derived_from<_Base> _Type, get_identifier_func_t<_Base> get_identifier>
+ using ValueRegistry = UniqueKeyRegistry<_Base, _Type, get_identifier, _Type, _addressof<_Type>, _addressof<const _Type>>;
+
+ template<typename _Type>
+ constexpr _Type* get_ptr(std::unique_ptr<_Type>& storage) {
+ return storage.get();
+ }
+ template<typename _Type>
+ constexpr _Type const* get_cptr(std::unique_ptr<_Type> const& storage) {
+ return storage.get();
+ }
+
+ template<typename _Base, std::derived_from<_Base> _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<std::derived_from<HasIdentifier> _Type>
+ using IdentifierRegistry = ValueRegistry<HasIdentifier, _Type, &HasIdentifier::get_identifier>;
+
+ template<std::derived_from<HasIdentifier> _Type>
+ using IdentifierInstanceRegistry = InstanceRegistry<HasIdentifier, _Type, &HasIdentifier::get_identifier>;
+
+#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<type> const& get_##plural() const { \
+ std::vector<decltype(plural)::storage_type> const& get_##plural() const { \
return plural.get_items(); } \
std::vector<std::string_view> get_##singular##_identifiers() const { \
return plural.get_item_identifiers(); } \
- NodeTools::node_callback_t expect_##singular##_identifier(NodeTools::callback_t<type const&> callback) const { \
+ NodeTools::callback_t<std::string_view> expect_##singular##_identifier(NodeTools::callback_t<decltype(plural)::value_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 { \
+ NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t<decltype(plural)::value_type const&, ast::NodeCPtr> callback) const { \
return plural.expect_item_dictionary(callback); } \
- NodeTools::node_callback_t expect_##singular##_decimal_map(NodeTools::callback_t<std::map<type const*, fixed_point_t>&&> callback) const { \
+ NodeTools::node_callback_t expect_##singular##_decimal_map(NodeTools::callback_t<std::map<decltype(plural)::value_type const*, fixed_point_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<type&> callback) { \
+ NodeTools::callback_t<std::string_view> expect_##singular##_identifier(NodeTools::callback_t<decltype(plural)::value_type&> callback) { \
return plural.expect_item_identifier(callback); } \
- NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t<type&, ast::NodeCPtr> callback) { \
+ NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t<decltype(plural)::value_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)
+#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<T> const& value)
template struct OpenVic::vec2_t<int64_t>;
template struct OpenVic::vec2_t<fixed_point_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<typename T>
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 <typename S>
+ template<typename S>
constexpr friend vec2_t<S> operator+(vec2_t<S> const& left, vec2_t<S> const& right);
constexpr vec2_t& operator+=(vec2_t const& right);
- template <typename S>
+ template<typename S>
constexpr friend vec2_t<S> operator-(vec2_t<S> const& arg);
- template <typename S>
+ template<typename S>
constexpr friend vec2_t<S> operator-(vec2_t<S> const& left, vec2_t<S> const& right);
constexpr vec2_t& operator-=(vec2_t const& right);
- template <typename S>
+ template<typename S>
constexpr friend std::ostream& operator<<(std::ostream& stream, vec2_t<S> const& value);
};
- using ivec2_t = vec2_t<int64_t>;
+ using ivec2_t = vec2_t<int32_t>;
using fvec2_t = vec2_t<fixed_point_t>;
}
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>(ts)), ...);
stream << std::endl;
log_queue.push(stream.str());