aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation')
-rw-r--r--src/openvic-simulation/country/Country.cpp35
-rw-r--r--src/openvic-simulation/country/Country.hpp2
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.hpp1
-rw-r--r--src/openvic-simulation/dataloader/NodeTools.cpp15
-rw-r--r--src/openvic-simulation/dataloader/NodeTools.hpp47
-rw-r--r--src/openvic-simulation/diplomacy/DiplomaticAction.cpp23
-rw-r--r--src/openvic-simulation/history/CountryHistory.cpp84
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.cpp36
-rw-r--r--src/openvic-simulation/map/Map.cpp2
-rw-r--r--src/openvic-simulation/map/Province.cpp8
-rw-r--r--src/openvic-simulation/military/Wargoal.cpp13
-rw-r--r--src/openvic-simulation/misc/Event.cpp6
-rw-r--r--src/openvic-simulation/misc/Modifier.cpp12
-rw-r--r--src/openvic-simulation/politics/NationalFocus.cpp88
-rw-r--r--src/openvic-simulation/politics/NationalFocus.hpp10
-rw-r--r--src/openvic-simulation/politics/Rebel.cpp15
-rw-r--r--src/openvic-simulation/politics/Rule.cpp11
-rw-r--r--src/openvic-simulation/pop/Culture.cpp8
-rw-r--r--src/openvic-simulation/pop/Culture.hpp10
-rw-r--r--src/openvic-simulation/pop/Pop.cpp24
-rw-r--r--src/openvic-simulation/scripts/Condition.cpp2
-rw-r--r--src/openvic-simulation/types/HasIdentifier.hpp88
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.hpp204
-rw-r--r--src/openvic-simulation/types/OrderedContainers.hpp2
24 files changed, 428 insertions, 318 deletions
diff --git a/src/openvic-simulation/country/Country.cpp b/src/openvic-simulation/country/Country.cpp
index 299407c..463d1bf 100644
--- a/src/openvic-simulation/country/Country.cpp
+++ b/src/openvic-simulation/country/Country.cpp
@@ -1,10 +1,6 @@
#include "Country.hpp"
-#include <filesystem>
#include <string_view>
-#include <system_error>
-#include <unordered_map>
-#include <vector>
#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp>
@@ -125,8 +121,7 @@ node_callback_t CountryManager::load_country_party(
return politics_manager.get_issue_manager().expect_issue_identifier(
[&policies, &group](Issue const& issue) -> bool {
if (&issue.get_group() == &group) {
- policies.emplace(&group, &issue);
- return true;
+ return map_callback(policies, &group)(&issue);
}
// TODO - change this back to error/false once TGC no longer has this issue
Logger::warning("Invalid policy ", issue.get_identifier(), ", group is ",
@@ -161,19 +156,10 @@ bool CountryManager::load_country_data_file(
Country::unit_names_map_t unit_names;
Country::government_colour_map_t alternative_colours;
bool ret = expect_dictionary_keys_and_default(
- [&game_manager, &alternative_colours, &name](std::string_view key, ast::NodeCPtr value) -> bool {
+ [&game_manager, &alternative_colours](std::string_view key, ast::NodeCPtr value) -> bool {
return game_manager.get_politics_manager().get_government_type_manager().expect_government_type_str(
- [&alternative_colours, &name, &value](GovernmentType const& government_type) -> bool {
- if (alternative_colours.contains(&government_type)) {
- Logger::error(
- "Country ", name, " has duplicate entry for ", government_type.get_identifier(),
- " alternative colour"
- );
- return false;
- }
- return expect_colour([&alternative_colours, &government_type](colour_t colour) -> bool {
- return alternative_colours.emplace(&government_type, std::move(colour)).second;
- })(value);
+ [&alternative_colours, value](GovernmentType const& government_type) -> bool {
+ return expect_colour(map_callback(alternative_colours, &government_type))(value);
}
)(key);
},
@@ -184,15 +170,10 @@ bool CountryManager::load_country_data_file(
),
"party", ZERO_OR_MORE, load_country_party(game_manager.get_politics_manager(), parties),
"unit_names", ZERO_OR_ONE,
- game_manager.get_military_manager().get_unit_manager().expect_unit_dictionary(
- [&unit_names, &name](Unit const& unit, ast::NodeCPtr value) -> bool {
- if (unit_names.contains(&unit)) {
- Logger::error("Country ", name, " has duplicate entry for ", unit.get_identifier(), " name list");
- return false;
- }
- return name_list_callback([&unit_names, &unit](std::vector<std::string>&& list) -> bool {
- return unit_names.emplace(&unit, std::move(list)).second;
- })(value);
+ game_manager.get_military_manager().get_unit_manager().expect_unit_dictionary_reserve_length(
+ unit_names,
+ [&unit_names](Unit const& unit, ast::NodeCPtr value) -> bool {
+ return name_list_callback(map_callback(unit_names, &unit))(value);
}
)
)(root);
diff --git a/src/openvic-simulation/country/Country.hpp b/src/openvic-simulation/country/Country.hpp
index 76254a2..5f60534 100644
--- a/src/openvic-simulation/country/Country.hpp
+++ b/src/openvic-simulation/country/Country.hpp
@@ -51,7 +51,7 @@ namespace OpenVic {
struct Country : HasIdentifierAndColour {
friend struct CountryManager;
- using unit_names_map_t = ordered_map<Unit const*, std::vector<std::string>>;
+ using unit_names_map_t = ordered_map<Unit const*, name_list_t>;
using government_colour_map_t = ordered_map<GovernmentType const*, colour_t>;
private:
diff --git a/src/openvic-simulation/dataloader/Dataloader.hpp b/src/openvic-simulation/dataloader/Dataloader.hpp
index 069ccec..de72fcd 100644
--- a/src/openvic-simulation/dataloader/Dataloader.hpp
+++ b/src/openvic-simulation/dataloader/Dataloader.hpp
@@ -2,7 +2,6 @@
#include <openvic-dataloader/csv/Parser.hpp>
#include <openvic-dataloader/v2script/Parser.hpp>
-#include <unordered_map> //keep this here or mac builds will fail
#include "openvic-simulation/dataloader/NodeTools.hpp"
diff --git a/src/openvic-simulation/dataloader/NodeTools.cpp b/src/openvic-simulation/dataloader/NodeTools.cpp
index 4612f77..957aa01 100644
--- a/src/openvic-simulation/dataloader/NodeTools.cpp
+++ b/src/openvic-simulation/dataloader/NodeTools.cpp
@@ -400,9 +400,9 @@ node_callback_t NodeTools::expect_dictionary_key_map(key_map_t key_map) {
);
}
-node_callback_t NodeTools::name_list_callback(callback_t<std::vector<std::string>&&> callback) {
+node_callback_t NodeTools::name_list_callback(callback_t<name_list_t&&> callback) {
return [callback](ast::NodeCPtr node) -> bool {
- std::vector<std::string> list;
+ name_list_t list;
bool ret = expect_list_reserve_length(
list, expect_identifier_or_string(vector_callback<std::string_view>(list))
)(node);
@@ -411,6 +411,17 @@ node_callback_t NodeTools::name_list_callback(callback_t<std::vector<std::string
};
}
+std::ostream& OpenVic::operator<<(std::ostream& stream, name_list_t const& name_list) {
+ stream << '[';
+ if (!name_list.empty()) {
+ stream << name_list.front();
+ std::for_each(name_list.begin() + 1, name_list.end(), [&stream](std::string const& name) -> void {
+ stream << ", " << name;
+ });
+ }
+ return stream << ']';
+}
+
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 00ba02d..b3fce16 100644
--- a/src/openvic-simulation/dataloader/NodeTools.hpp
+++ b/src/openvic-simulation/dataloader/NodeTools.hpp
@@ -11,6 +11,7 @@
#include "openvic-simulation/types/Colour.hpp"
#include "openvic-simulation/types/Date.hpp"
+#include "openvic-simulation/types/HasIdentifier.hpp"
#include "openvic-simulation/types/OrderedContainers.hpp"
#include "openvic-simulation/types/Vector.hpp"
@@ -28,6 +29,9 @@ namespace OpenVic {
using string_set_t = ordered_set<std::string>;
using case_insensitive_string_set_t = case_insensitive_ordered_set<std::string>;
+ using name_list_t = std::vector<std::string>;
+ std::ostream& operator<<(std::ostream& stream, name_list_t const& name_list);
+
namespace NodeTools {
template<typename Fn, typename Return = void, typename... Args>
@@ -234,21 +238,22 @@ namespace OpenVic {
t.reserve(size_t {});
};
template<Reservable T>
+ LengthCallback auto reserve_length_callback(T& t) {
+ return [&t](size_t size) -> size_t {
+ t.reserve(size);
+ return size;
+ };
+ }
+ template<Reservable T>
NodeCallback auto expect_list_reserve_length(T& t, NodeCallback auto callback) {
- return expect_list_and_length(
- [&t](size_t size) -> size_t {
- t.reserve(t.size() + size);
- return size;
- },
- callback
- );
+ return expect_list_and_length(reserve_length_callback(t), callback);
}
template<Reservable T>
NodeCallback auto expect_dictionary_reserve_length(T& t, KeyValueCallback auto callback) {
return expect_list_reserve_length(t, expect_assign(callback));
}
- node_callback_t name_list_callback(callback_t<std::vector<std::string>&&> callback);
+ node_callback_t name_list_callback(callback_t<name_list_t&&> callback);
template<typename T, class Hash, class KeyEqual>
Callback<std::string_view> auto expect_mapped_string(
@@ -351,10 +356,32 @@ namespace OpenVic {
};
}
- template<typename T, typename...SetArgs>
+ template<typename T, typename U, typename...SetArgs>
+ Callback<T> auto set_callback(tsl::ordered_set<U, SetArgs...>& set) {
+ return [&set](T val) -> bool {
+ if (!set.emplace(std::move(val)).second) {
+ Logger::warning("Duplicate set entry: \"", val, "\"");
+ }
+ return true;
+ };
+ }
+
+ template<std::derived_from<HasIdentifier> T, typename...SetArgs>
Callback<T const&> auto set_callback_pointer(tsl::ordered_set<T const*, SetArgs...>& set) {
return [&set](T const& val) -> bool {
- set.insert(&val);
+ if (!set.emplace(&val).second) {
+ Logger::warning("Duplicate set entry: \"", &val, "\"");
+ }
+ return true;
+ };
+ }
+
+ template<std::derived_from<HasIdentifier> Key, typename Value, typename... MapArgs>
+ Callback<Value> auto map_callback(tsl::ordered_map<Key const*, Value, MapArgs...>& map, Key const* key) {
+ return [&map, key](Value value) -> bool {
+ if (!map.emplace(key, std::move(value)).second) {
+ Logger::warning("Duplicate map entry with key: \"", key, "\"");
+ }
return true;
};
}
diff --git a/src/openvic-simulation/diplomacy/DiplomaticAction.cpp b/src/openvic-simulation/diplomacy/DiplomaticAction.cpp
index c1aa3df..d10eda3 100644
--- a/src/openvic-simulation/diplomacy/DiplomaticAction.cpp
+++ b/src/openvic-simulation/diplomacy/DiplomaticAction.cpp
@@ -9,13 +9,12 @@
using namespace OpenVic;
DiplomaticActionType::DiplomaticActionType(DiplomaticActionType::Initializer&& initializer)
- : commit_action_caller { std::move(initializer.commit) },
- allowed_to_commit { std::move(initializer.allowed) }, get_acceptance { std::move(initializer.get_acceptance) } {}
+ : commit_action_caller { std::move(initializer.commit) },
+ allowed_to_commit { std::move(initializer.allowed) }, get_acceptance { std::move(initializer.get_acceptance) } {}
CancelableDiplomaticActionType::CancelableDiplomaticActionType(CancelableDiplomaticActionType::Initializer&& initializer)
: allowed_to_cancel{std::move(initializer.allowed_cancel)}, DiplomaticActionType(std::move(initializer)) {}
-
DiplomaticActionManager::DiplomaticActionManager() {}
bool DiplomaticActionManager::add_diplomatic_action(
@@ -49,7 +48,7 @@ DiplomaticActionTickCache DiplomaticActionManager::create_diplomatic_action_tick
result.acceptance = type.get_acceptance(result.argument);
}
});
-
+
return result;
}
@@ -78,38 +77,38 @@ bool DiplomaticActionManager::setup_diplomatic_actions() {
}
);
result &= add_diplomatic_action(
- "give_military_access",
+ "give_military_access",
{ [](Argument& arg) {} }
);
result &= add_diplomatic_action(
- "increase_relations",
+ "increase_relations",
{
.commit = [](Argument& arg) {},
.allowed = [](const Argument& arg) { return false; },
}
);
result &= add_diplomatic_action(
- "decrease_relations",
+ "decrease_relations",
{ [](Argument& arg) {} }
);
result &= add_diplomatic_action(
- "war_subsidies",
+ "war_subsidies",
{ [](Argument& arg) {} }
);
result &= add_diplomatic_action(
- "declare_war",
+ "declare_war",
{ [](Argument& arg) {} }
);
result &= add_diplomatic_action(
- "offer_peace",
+ "offer_peace",
{ [](Argument& arg) {} }
);
result &= add_diplomatic_action(
- "command_units",
+ "command_units",
{ [](Argument& arg) {} }
);
result &= add_diplomatic_action(
- "discredit",
+ "discredit",
{ [](Argument& arg) {} }
);
result &= add_diplomatic_action(
diff --git a/src/openvic-simulation/history/CountryHistory.cpp b/src/openvic-simulation/history/CountryHistory.cpp
index 96a0b7c..3b4dfd8 100644
--- a/src/openvic-simulation/history/CountryHistory.cpp
+++ b/src/openvic-simulation/history/CountryHistory.cpp
@@ -1,7 +1,6 @@
#include "CountryHistory.hpp"
#include "openvic-simulation/GameManager.hpp"
-#include <string_view>
using namespace OpenVic;
using namespace OpenVic::NodeTools;
@@ -28,22 +27,20 @@ bool CountryHistoryMap::_load_history_entry(
DecisionManager const& decision_manager = game_manager.get_decision_manager();
return expect_dictionary_keys_and_default(
- [this, &game_manager, &dataloader, &deployment_manager, &issue_manager,
- &technology_manager, &invention_manager, &country_manager, &entry](std::string_view key, ast::NodeCPtr value) -> bool {
+ [this, &game_manager, &dataloader, &deployment_manager, &issue_manager, &technology_manager, &invention_manager,
+ &country_manager, &entry](std::string_view key, ast::NodeCPtr value) -> bool {
ReformGroup const* reform_group = issue_manager.get_reform_group_by_identifier(key);
if (reform_group != nullptr) {
return issue_manager.expect_reform_identifier([&entry, reform_group](Reform const& reform) -> bool {
if (&reform.get_reform_group() != reform_group) {
Logger::warning(
- "Listing ", reform.get_identifier(), " as belonging to the reform group ",
- reform_group->get_identifier(), " when it actually belongs to ",
- reform.get_reform_group().get_identifier(), " in history of ", entry.get_country().get_identifier()
+ "Listing ", reform.get_identifier(), " as belonging to the reform group ", reform_group,
+ " when it actually belongs to ", reform.get_reform_group(), " in history of ", entry.get_country()
);
}
if (std::find(entry.reforms.begin(), entry.reforms.end(), &reform) != entry.reforms.end()) {
Logger::error(
- "Redefinition of reform ", reform.get_identifier(), " in history of ",
- entry.get_country().get_identifier()
+ "Redefinition of reform ", reform.get_identifier(), " in history of ", entry.get_country()
);
return false;
}
@@ -55,36 +52,14 @@ bool CountryHistoryMap::_load_history_entry(
{
Technology const* technology = technology_manager.get_technology_by_identifier(key);
if (technology != nullptr) {
- return expect_int_bool(
- [&entry, technology](bool flag) -> bool {
- if (!entry.technologies.emplace(technology, flag).second) {
- Logger::error(
- "Duplicate entry for technology ", technology->get_identifier(), " in history of ",
- entry.get_country().get_identifier(), " at date ", entry.get_date()
- );
- return false;
- }
- return true;
- }
- )(value);
+ return expect_int_bool(map_callback(entry.technologies, technology))(value);
}
}
{
Invention const* invention = invention_manager.get_invention_by_identifier(key);
if (invention != nullptr) {
- return expect_bool(
- [&entry, invention](bool flag) -> bool {
- if (!entry.inventions.emplace(invention, flag).second) {
- Logger::error(
- "Duplicate entry for invention ", invention->get_identifier(), " in history of ",
- entry.get_country().get_identifier(), " at date ", entry.get_date()
- );
- return false;
- }
- return true;
- }
- )(value);
+ return expect_bool(map_callback(entry.inventions, invention))(value);
}
}
@@ -113,12 +88,10 @@ bool CountryHistoryMap::_load_history_entry(
"prestige", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.prestige)),
"ruling_party", ZERO_OR_ONE, country.expect_party_identifier(assign_variable_callback_pointer(entry.ruling_party)),
"last_election", ZERO_OR_ONE, expect_date(assign_variable_callback(entry.last_election)),
- "upper_house", ZERO_OR_ONE, politics_manager.get_ideology_manager().expect_ideology_dictionary(
+ "upper_house", ZERO_OR_ONE, politics_manager.get_ideology_manager().expect_ideology_dictionary_reserve_length(
+ entry.upper_house,
[&entry](Ideology const& ideology, ast::NodeCPtr value) -> bool {
- return expect_fixed_point([&entry, &ideology](fixed_point_t val) -> bool {
- entry.upper_house[&ideology] = val;
- return true;
- })(value);
+ return expect_fixed_point(map_callback(entry.upper_house, &ideology))(value);
}
),
"oob", ZERO_OR_ONE, expect_identifier_or_string(
@@ -134,9 +107,11 @@ bool CountryHistoryMap::_load_history_entry(
"schools", ZERO_OR_ONE, technology_manager.expect_technology_school_identifier(
assign_variable_callback_pointer(entry.tech_school)
),
- "foreign_investment", ZERO_OR_ONE, country_manager.expect_country_decimal_map(move_variable_callback(entry.foreign_investment)),
+ "foreign_investment", ZERO_OR_ONE,
+ country_manager.expect_country_decimal_map(move_variable_callback(entry.foreign_investment)),
"literacy", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.literacy)),
- "non_state_culture_literacy", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.nonstate_culture_literacy)),
+ "non_state_culture_literacy", ZERO_OR_ONE,
+ expect_fixed_point(assign_variable_callback(entry.nonstate_culture_literacy)),
"consciousness", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.consciousness)),
"nonstate_consciousness", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.nonstate_consciousness)),
"is_releasable_vassal", ZERO_OR_ONE, expect_bool(assign_variable_callback(entry.releasable_vassal)),
@@ -153,7 +128,7 @@ bool CountryHistoryMap::_load_history_entry(
if (flag_expected) {
Logger::error(
"Government key found when expect flag type override for ", government_type,
- " in history of ", entry.get_country().get_identifier()
+ " in history of ", entry.get_country()
);
ret = false;
}
@@ -173,22 +148,19 @@ bool CountryHistoryMap::_load_history_entry(
/* If the first government type is null, the "government" section will have already output
* an error, so no need to output another one here. */
if (government_type != nullptr && flag_override_government_type != nullptr) {
- ret &= entry.government_flag_overrides.emplace(
- government_type, flag_override_government_type
- ).second;
+ ret &= map_callback(entry.government_flag_overrides, government_type)(flag_override_government_type);
}
return ret;
} else {
Logger::error(
"Flag key found when expecting government type for flag type override in history of ",
- entry.get_country().get_identifier()
+ entry.get_country()
);
return false;
}
} else {
Logger::error(
- "Invalid key ", id, " in government flag overrides in history of ",
- entry.get_country().get_identifier()
+ "Invalid key ", id, " in government flag overrides in history of ", entry.get_country()
);
return false;
}
@@ -196,20 +168,15 @@ bool CountryHistoryMap::_load_history_entry(
)(value);
if (flag_expected) {
Logger::error(
- "Missing flag type override for government type ", government_type, " in history of ",
- entry.get_country().get_identifier()
+ "Missing flag type override for government type ", government_type, " in history of ", entry.get_country()
);
ret = false;
}
return ret;
},
"colonial_points", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.colonial_points)),
- "set_country_flag", ZERO_OR_MORE, expect_identifier_or_string([&entry](std::string_view flag) -> bool {
- return entry.country_flags.emplace(flag).second;
- }),
- "set_global_flag", ZERO_OR_MORE, expect_identifier_or_string([&entry](std::string_view flag) -> bool {
- return entry.global_flags.emplace(flag).second;
- })
+ "set_country_flag", ZERO_OR_MORE, expect_identifier_or_string(set_callback<std::string_view>(entry.country_flags)),
+ "set_global_flag", ZERO_OR_MORE, expect_identifier_or_string(set_callback<std::string_view>(entry.global_flags))
)(root);
}
@@ -231,7 +198,7 @@ CountryHistoryMap const* CountryHistoryManager::get_country_history(Country cons
if (country_registry != country_histories.end()) {
return &country_registry->second;
} else {
- Logger::error("Attempted to access history of country ", country->get_identifier(), " but none has been defined!");
+ Logger::error("Attempted to access history of country ", country, " but none has been defined!");
return nullptr;
}
}
@@ -240,10 +207,7 @@ bool CountryHistoryManager::load_country_history_file(
GameManager& game_manager, Dataloader const& dataloader, Country const& country, ast::NodeCPtr root
) {
if (locked) {
- Logger::error(
- "Attempted to load country history file for ", country.get_identifier(),
- " after country history registry was locked!"
- );
+ Logger::error("Attempted to load country history file for ", country, " after country history registry was locked!");
return false;
}
@@ -258,7 +222,7 @@ bool CountryHistoryManager::load_country_history_file(
if (result.second) {
it = result.first;
} else {
- Logger::error("Failed to create country history map for country ", country.get_identifier());
+ Logger::error("Failed to create country history map for country ", country);
return false;
}
}
diff --git a/src/openvic-simulation/history/ProvinceHistory.cpp b/src/openvic-simulation/history/ProvinceHistory.cpp
index f5e5187..4117450 100644
--- a/src/openvic-simulation/history/ProvinceHistory.cpp
+++ b/src/openvic-simulation/history/ProvinceHistory.cpp
@@ -35,10 +35,15 @@ bool ProvinceHistoryMap::_load_history_entry(
// used for province buildings like forts or railroads
BuildingType const* building_type = building_type_manager.get_building_type_by_identifier(key);
if (building_type != nullptr) {
- return expect_uint<BuildingType::level_t>([&entry, building_type](BuildingType::level_t level) -> bool {
- entry.province_buildings[building_type] = level;
- return true;
- })(value);
+ if (building_type->is_in_province()) {
+ return expect_uint<BuildingType::level_t>(map_callback(entry.province_buildings, building_type))(value);
+ } else {
+ Logger::error(
+ "Attempted to add state building \"", building_type, "\" at top scope of province history for ",
+ entry.get_province()
+ );
+ return false;
+ }
}
return _load_history_sub_entry_callback(game_manager, entry.get_date(), value, key, value);
@@ -65,27 +70,39 @@ bool ProvinceHistoryMap::_load_history_entry(
Ideology const* ideology = nullptr;
fixed_point_t amount = 0; // percent I do believe
- const bool ret = expect_dictionary_keys(
+ bool ret = expect_dictionary_keys(
"ideology", ONE_EXACTLY, ideology_manager.expect_ideology_identifier(
assign_variable_callback_pointer(ideology)
),
"loyalty_value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(amount))
)(node);
- entry.party_loyalties[ideology] = amount;
+ if (ideology != nullptr) {
+ ret &= map_callback(entry.party_loyalties, ideology)(amount);
+ }
return ret;
},
"state_building", ZERO_OR_MORE, [&building_type_manager, &entry](ast::NodeCPtr node) -> bool {
BuildingType const* building_type = nullptr;
uint8_t level = 0;
- const bool ret = expect_dictionary_keys(
+ bool ret = expect_dictionary_keys(
"level", ONE_EXACTLY, expect_uint(assign_variable_callback(level)),
"building", ONE_EXACTLY, building_type_manager.expect_building_type_identifier(
assign_variable_callback_pointer(building_type)
),
"upgrade", ZERO_OR_ONE, success_callback // doesn't appear to have an effect
)(node);
- entry.state_buildings[building_type] = level;
+ if (building_type != nullptr) {
+ if (!building_type->is_in_province()) {
+ ret &= map_callback(entry.state_buildings, building_type)(level);
+ } else {
+ Logger::error(
+ "Attempted to add province building \"", building_type, "\" to state building list of province history for ",
+ entry.get_province()
+ );
+ ret = false;
+ }
+ }
return ret;
}
)(root);
@@ -174,7 +191,8 @@ bool ProvinceHistoryEntry::_load_province_pop_history(
) {
PopManager const& pop_manager = game_manager.get_pop_manager();
RebelManager const& rebel_manager = game_manager.get_politics_manager().get_rebel_manager();
- return pop_manager.expect_pop_type_dictionary(
+ return pop_manager.expect_pop_type_dictionary_reserve_length(
+ pops,
[this, &pop_manager, &rebel_manager, non_integer_size](PopType const& pop_type, ast::NodeCPtr pop_node) -> bool {
return pop_manager.load_pop_into_vector(rebel_manager, pops, pop_type, pop_node, non_integer_size);
}
diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp
index 27079f4..1415e2c 100644
--- a/src/openvic-simulation/map/Map.cpp
+++ b/src/openvic-simulation/map/Map.cpp
@@ -893,6 +893,8 @@ bool Map::load_continent_file(ModifierManager const& modifier_manager, ast::Node
[&prov_list](Province const& province) -> bool {
if (province.continent == nullptr) {
prov_list.emplace_back(&province);
+ } else {
+ Logger::warning("Province ", province, " found in multiple continents");
}
return true;
}
diff --git a/src/openvic-simulation/map/Province.cpp b/src/openvic-simulation/map/Province.cpp
index 1c3c76f..acabbf8 100644
--- a/src/openvic-simulation/map/Province.cpp
+++ b/src/openvic-simulation/map/Province.cpp
@@ -36,12 +36,10 @@ bool Province::load_positions(BuildingTypeManager const& building_type_manager,
"factory", ZERO_OR_ONE, expect_fvec2(assign_variable_callback(positions.factory)),
"building_construction", ZERO_OR_ONE, expect_fvec2(assign_variable_callback(positions.building_construction)),
"military_construction", ZERO_OR_ONE, expect_fvec2(assign_variable_callback(positions.military_construction)),
- "building_position", ZERO_OR_ONE, building_type_manager.expect_building_type_dictionary(
+ "building_position", ZERO_OR_ONE, building_type_manager.expect_building_type_dictionary_reserve_length(
+ positions.building_position,
[this](BuildingType const& type, ast::NodeCPtr value) -> bool {
- return expect_fvec2([this, &type](fvec2_t position) -> bool {
- positions.building_position.emplace(&type, std::move(position));
- return true;
- })(value);
+ return expect_fvec2(map_callback(positions.building_position, &type))(value);
}
),
"building_rotation", ZERO_OR_ONE, building_type_manager.expect_building_type_decimal_map(
diff --git a/src/openvic-simulation/military/Wargoal.cpp b/src/openvic-simulation/military/Wargoal.cpp
index 174cd09..6351ce3 100644
--- a/src/openvic-simulation/military/Wargoal.cpp
+++ b/src/openvic-simulation/military/Wargoal.cpp
@@ -122,10 +122,15 @@ bool WargoalTypeManager::load_wargoal_file(ast::NodeCPtr root) {
};
const decltype(peace_modifier_map)::const_iterator it = peace_modifier_map.find(key);
if (it != peace_modifier_map.end()) {
- return expect_fixed_point([&modifiers, peace_modifier = it->second](fixed_point_t val) -> bool {
- modifiers[peace_modifier] = val;
- return true;
- })(value);
+ return expect_fixed_point(
+ [&modifiers, &identifier, &key, peace_modifier = it->second](fixed_point_t val) -> bool {
+ if (modifiers.emplace(peace_modifier, val).second) {
+ return true;
+ }
+ Logger::error("Duplicate peace modifier ", key, " in wargoal ", identifier, "!");
+ return false;
+ }
+ )(value);
}
Logger::error("Modifier ", key, " in wargoal ", identifier, " is invalid.");
diff --git a/src/openvic-simulation/misc/Event.cpp b/src/openvic-simulation/misc/Event.cpp
index eb5f7da..d6750c1 100644
--- a/src/openvic-simulation/misc/Event.cpp
+++ b/src/openvic-simulation/misc/Event.cpp
@@ -196,7 +196,9 @@ bool EventManager::load_event_file(IssueManager const& issue_manager, ast::NodeC
bool EventManager::load_on_action_file(ast::NodeCPtr root) {
bool ret = expect_dictionary([this](std::string_view identifier, ast::NodeCPtr node) -> bool {
OnAction::weight_map_t weighted_events;
- bool ret = expect_dictionary([this, &identifier, &weighted_events](std::string_view weight_str, ast::NodeCPtr event_node) -> bool {
+ bool ret = expect_dictionary_reserve_length(
+ weighted_events,
+ [this, &identifier, &weighted_events](std::string_view weight_str, ast::NodeCPtr event_node) -> bool {
bool ret = false;
uint64_t weight = StringUtils::string_to_uint64(weight_str, &ret);
if (!ret) {
@@ -208,7 +210,7 @@ bool EventManager::load_on_action_file(ast::NodeCPtr root) {
ret &= expect_event_identifier(assign_variable_callback_pointer(event))(event_node);
if (event != nullptr) {
- ret &= weighted_events.emplace(event, weight).second;
+ ret &= map_callback(weighted_events, event)(weight);
} else {
Logger::warning(
"Non-existing event ", event->get_identifier(), " loaded on action ", identifier, "with weight",
diff --git a/src/openvic-simulation/misc/Modifier.cpp b/src/openvic-simulation/misc/Modifier.cpp
index c83fcf0..2d95f0d 100644
--- a/src/openvic-simulation/misc/Modifier.cpp
+++ b/src/openvic-simulation/misc/Modifier.cpp
@@ -372,12 +372,7 @@ key_value_callback_t ModifierManager::_modifier_effect_callback(
) const {
const auto add_modifier_cb = [this, &modifier, effect_validator](ModifierEffect const* effect, ast::NodeCPtr value) -> bool {
if (effect_validator(*effect)) {
- if (!modifier.values.contains(effect)) {
- return expect_fixed_point(assign_variable_callback(modifier.values[effect]))(value);
- } else {
- Logger::error("Duplicate modifier effect: ", effect->get_identifier());
- return false;
- }
+ return expect_fixed_point(map_callback(modifier.values, effect))(value);
} else {
Logger::error("Failed to validate modifier effect: ", effect->get_identifier());
return false;
@@ -424,7 +419,10 @@ node_callback_t ModifierManager::expect_validated_modifier_value_and_default(
) const {
return [this, modifier_callback, default_callback, effect_validator](ast::NodeCPtr root) -> bool {
ModifierValue modifier;
- bool ret = expect_dictionary(_modifier_effect_callback(modifier, default_callback, effect_validator))(root);
+ bool ret = expect_dictionary_reserve_length(
+ modifier.values,
+ _modifier_effect_callback(modifier, default_callback, effect_validator)
+ )(root);
ret &= modifier_callback(std::move(modifier));
return ret;
};
diff --git a/src/openvic-simulation/politics/NationalFocus.cpp b/src/openvic-simulation/politics/NationalFocus.cpp
index e509039..c2084be 100644
--- a/src/openvic-simulation/politics/NationalFocus.cpp
+++ b/src/openvic-simulation/politics/NationalFocus.cpp
@@ -11,16 +11,18 @@ NationalFocus::NationalFocus(
NationalFocusGroup const& new_group,
ModifierValue&& new_modifiers,
pop_promotion_map_t&& new_encouraged_promotion,
- party_loyalty_map_t&& new_encouraged_loyalty,
production_map_t&& new_encouraged_production,
+ Ideology const* new_loyalty_ideology,
+ fixed_point_t new_loyalty_value,
ConditionScript&& new_limit
) : HasIdentifier { new_identifier },
icon { new_icon },
group { new_group },
modifiers { std::move(new_modifiers) },
encouraged_promotion { std::move(new_encouraged_promotion) },
- encouraged_loyalty { std::move(new_encouraged_loyalty) },
encouraged_production { std::move(new_encouraged_production) },
+ loyalty_ideology { new_loyalty_ideology },
+ loyalty_value { new_loyalty_value },
limit { std::move(new_limit) } {}
bool NationalFocus::parse_scripts(GameManager const& game_manager) {
@@ -41,8 +43,9 @@ inline bool NationalFocusManager::add_national_focus(
NationalFocusGroup const& group,
ModifierValue&& modifiers,
NationalFocus::pop_promotion_map_t&& encouraged_promotion,
- NationalFocus::party_loyalty_map_t&& encouraged_loyalty,
NationalFocus::production_map_t&& encouraged_production,
+ Ideology const* loyalty_ideology,
+ fixed_point_t loyalty_value,
ConditionScript&& limit
) {
if (identifier.empty()) {
@@ -53,74 +56,79 @@ inline bool NationalFocusManager::add_national_focus(
Logger::error("Invalid icon ", icon, " for national focus ", identifier);
return false;
}
+ if ((loyalty_ideology == nullptr) != (loyalty_value == 0)) {
+ Logger::warning(
+ "Party loyalty incorrectly defined for national focus ", identifier, ": ideology = ", loyalty_ideology,
+ ", value = ", loyalty_value
+ );
+ }
return national_foci.add_item({
- identifier, icon, group, std::move(modifiers), std::move(encouraged_promotion), std::move(encouraged_loyalty),
- std::move(encouraged_production), std::move(limit)
+ identifier, icon, group, std::move(modifiers), std::move(encouraged_promotion), std::move(encouraged_production),
+ loyalty_ideology, loyalty_value, std::move(limit)
});
}
-bool NationalFocusManager::load_national_foci_file(PopManager const& pop_manager, IdeologyManager const& ideology_manager, GoodManager const& good_manager, ModifierManager const& modifier_manager, ast::NodeCPtr root) {
- bool ret = expect_dictionary_reserve_length(national_focus_groups, [this](std::string_view identifier, ast::NodeCPtr node) -> bool {
- return add_national_focus_group(identifier);
- })(root);
+bool NationalFocusManager::load_national_foci_file(
+ PopManager const& pop_manager, IdeologyManager const& ideology_manager, GoodManager const& good_manager,
+ ModifierManager const& modifier_manager, ast::NodeCPtr root
+) {
+ size_t expected_national_foci = 0;
+ bool ret = expect_dictionary_reserve_length(
+ national_focus_groups,
+ [this, &expected_national_foci](std::string_view identifier, ast::NodeCPtr node) -> bool {
+ return expect_length(add_variable_callback(expected_national_foci))(node) & add_national_focus_group(identifier);
+ }
+ )(root);
lock_national_focus_groups();
- ret &= expect_national_focus_group_dictionary([this, &pop_manager, &ideology_manager, &good_manager, &modifier_manager](NationalFocusGroup const& group, ast::NodeCPtr node) -> bool {
- bool ret = expect_dictionary([this, &group, &pop_manager, &ideology_manager, &good_manager, &modifier_manager](std::string_view identifier, ast::NodeCPtr node) -> bool {
- uint8_t icon;
+ national_foci.reserve(expected_national_foci);
+
+ ret &= expect_national_focus_group_dictionary([this, &pop_manager, &ideology_manager, &good_manager, &modifier_manager](
+ NationalFocusGroup const& group, ast::NodeCPtr group_node
+ ) -> bool {
+ return expect_dictionary([this, &group, &pop_manager, &ideology_manager, &good_manager, &modifier_manager](
+ std::string_view identifier, ast::NodeCPtr node
+ ) -> bool {
+ uint8_t icon = 0;
ModifierValue modifiers;
NationalFocus::pop_promotion_map_t promotions;
- NationalFocus::party_loyalty_map_t loyalties;
NationalFocus::production_map_t production;
+ Ideology const* loyalty_ideology = nullptr;
+ fixed_point_t loyalty_value = 0;
ConditionScript limit { scope_t::PROVINCE | scope_t::COUNTRY, scope_t::PROVINCE | scope_t::COUNTRY, scope_t::NO_SCOPE };
- Ideology const* last_specified_ideology = nullptr; // weird, I know
-
bool ret = modifier_manager.expect_modifier_value_and_keys_and_default(
move_variable_callback(modifiers),
- [&promotions, &pop_manager, &production, &good_manager, &modifiers, &modifier_manager](std::string_view key, ast::NodeCPtr value) -> bool {
+ [&promotions, &pop_manager, &production, &good_manager, &modifiers, &modifier_manager](
+ std::string_view key, ast::NodeCPtr value
+ ) -> bool {
PopType const* pop_type = pop_manager.get_pop_type_by_identifier(key);
if (pop_type != nullptr) {
- fixed_point_t boost;
- bool ret = expect_fixed_point(assign_variable_callback(boost))(value);
- promotions[pop_type] = boost;
- return ret;
+ return expect_fixed_point(map_callback(promotions, pop_type))(value);
}
Good const* good = good_manager.get_good_by_identifier(key);
if (good != nullptr) {
- fixed_point_t boost;
- bool ret = expect_fixed_point(assign_variable_callback(boost))(value);
- production[good] = boost;
- return ret;
+ return expect_fixed_point(map_callback(production, good))(value);
}
return key_value_invalid_callback(key, value);
},
"icon", ONE_EXACTLY, expect_uint(assign_variable_callback(icon)),
- "ideology", ZERO_OR_MORE, ideology_manager.expect_ideology_identifier(assign_variable_callback_pointer(last_specified_ideology)),
- "loyalty_value", ZERO_OR_MORE, [&identifier, &last_specified_ideology, &loyalties](ast::NodeCPtr value) -> bool {
- if (last_specified_ideology == nullptr) {
- Logger::error("In national focus ", identifier, ": No ideology selected for loyalty_value!");
- return false;
- }
- fixed_point_t boost;
- bool ret = expect_fixed_point(assign_variable_callback(boost))(value);
- loyalties[last_specified_ideology] += boost;
- return ret;
- },
+ "ideology", ZERO_OR_ONE,
+ ideology_manager.expect_ideology_identifier(assign_variable_callback_pointer(loyalty_ideology)),
+ "loyalty_value", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(loyalty_value)),
"limit", ZERO_OR_ONE, limit.expect_script(),
"has_flashpoint", ZERO_OR_ONE, success_callback, // special case, include in limit
"own_provinces", ZERO_OR_ONE, success_callback, // special case, include in limit
"outliner_show_as_percent", ZERO_OR_ONE, success_callback // special case
)(node);
- add_national_focus(
- identifier, icon, group, std::move(modifiers), std::move(promotions), std::move(loyalties),
- std::move(production), std::move(limit)
+ ret &= add_national_focus(
+ identifier, icon, group, std::move(modifiers), std::move(promotions), std::move(production),
+ loyalty_ideology, loyalty_value, std::move(limit)
);
return ret;
- })(node);
- return ret;
+ })(group_node);
})(root);
lock_national_foci();
diff --git a/src/openvic-simulation/politics/NationalFocus.hpp b/src/openvic-simulation/politics/NationalFocus.hpp
index 44e58e3..6e064f1 100644
--- a/src/openvic-simulation/politics/NationalFocus.hpp
+++ b/src/openvic-simulation/politics/NationalFocus.hpp
@@ -23,7 +23,6 @@ namespace OpenVic {
public:
using pop_promotion_map_t = fixed_point_map_t<PopType const*>;
- using party_loyalty_map_t = fixed_point_map_t<Ideology const*>;
using production_map_t = fixed_point_map_t<Good const*>;
private:
@@ -31,8 +30,9 @@ namespace OpenVic {
NationalFocusGroup const& PROPERTY(group);
ModifierValue PROPERTY(modifiers);
pop_promotion_map_t PROPERTY(encouraged_promotion);
- party_loyalty_map_t PROPERTY(encouraged_loyalty);
production_map_t PROPERTY(encouraged_production);
+ Ideology const* PROPERTY(loyalty_ideology);
+ fixed_point_t PROPERTY(loyalty_value);
ConditionScript PROPERTY(limit);
NationalFocus(
@@ -41,8 +41,9 @@ namespace OpenVic {
NationalFocusGroup const& new_group,
ModifierValue&& new_modifiers,
pop_promotion_map_t&& new_encouraged_promotion,
- party_loyalty_map_t&& new_encouraged_loyalty,
production_map_t&& new_encouraged_production,
+ Ideology const* new_loyalty_ideology,
+ fixed_point_t new_loyalty_value,
ConditionScript&& new_limit
);
@@ -66,8 +67,9 @@ namespace OpenVic {
NationalFocusGroup const& group,
ModifierValue&& modifiers,
NationalFocus::pop_promotion_map_t&& encouraged_promotion,
- NationalFocus::party_loyalty_map_t&& encouraged_loyalty,
NationalFocus::production_map_t&& encouraged_production,
+ Ideology const* loyalty_ideology,
+ fixed_point_t loyalty_value,
ConditionScript&& limit
);
diff --git a/src/openvic-simulation/politics/Rebel.cpp b/src/openvic-simulation/politics/Rebel.cpp
index 6370786..f86bb51 100644
--- a/src/openvic-simulation/politics/Rebel.cpp
+++ b/src/openvic-simulation/politics/Rebel.cpp
@@ -115,17 +115,14 @@ bool RebelManager::load_rebels_file(
"icon", ONE_EXACTLY, expect_uint(assign_variable_callback(icon)),
"area", ONE_EXACTLY, expect_identifier(expect_mapped_string(area_map, assign_variable_callback(area))),
"break_alliance_on_win", ZERO_OR_ONE, expect_bool(assign_variable_callback(break_alliance_on_win)),
- "government", ONE_EXACTLY, government_type_manager.expect_government_type_dictionary(
- [this, &government_type_manager, &desired_governments](GovernmentType const& from,
- ast::NodeCPtr value) -> bool {
- if (desired_governments.contains(&from)) {
- Logger::error("Duplicate \"from\" government type in rebel type: ", from.get_identifier());
- return false;
- }
+ "government", ONE_EXACTLY, government_type_manager.expect_government_type_dictionary_reserve_length(
+ desired_governments,
+ [this, &government_type_manager, &desired_governments](
+ GovernmentType const& from, ast::NodeCPtr value
+ ) -> bool {
return government_type_manager.expect_government_type_identifier(
[&desired_governments, &from](GovernmentType const& to) -> bool {
- desired_governments.emplace(&from, &to);
- return true;
+ return map_callback(desired_governments, &from)(&to);
}
)(value);
}
diff --git a/src/openvic-simulation/politics/Rule.cpp b/src/openvic-simulation/politics/Rule.cpp
index 9ac992a..19e92af 100644
--- a/src/openvic-simulation/politics/Rule.cpp
+++ b/src/openvic-simulation/politics/Rule.cpp
@@ -109,8 +109,8 @@ bool RuleSet::set_rule(Rule const* rule, bool value) {
Logger::error("Invalid rule - null!");
return false;
}
- rule_map_t& rule_map = rule_groups[rule->get_group()];
- return rule_groups[rule->get_group()].emplace(rule, value).second;
+ rule_groups[rule->get_group()][rule] = value;
+ return true;
}
RuleSet& RuleSet::operator|=(RuleSet const& right) {
@@ -193,10 +193,9 @@ node_callback_t RuleManager::expect_rule_set(callback_t<RuleSet&&> ruleset_callb
if (rule != nullptr) {
return expect_bool(
[&ruleset, rule](bool value) -> bool {
- if (!ruleset.rule_groups[rule->get_group()].emplace(rule, value).second) {
- Logger::warning("Duplicate rule entry: ", rule, " - ignoring!");
- }
- return true;
+ /* Wrapped in a lambda function so that the rule group is only initialised
+ * if the value bool is successfully parsed. */
+ return map_callback(ruleset.rule_groups[rule->get_group()], rule)(value);
}
)(rule_value);
} else {
diff --git a/src/openvic-simulation/pop/Culture.cpp b/src/openvic-simulation/pop/Culture.cpp
index 9b9d6c2..2cd6005 100644
--- a/src/openvic-simulation/pop/Culture.cpp
+++ b/src/openvic-simulation/pop/Culture.cpp
@@ -16,7 +16,7 @@ CultureGroup::CultureGroup(
Culture::Culture(
std::string_view new_identifier, colour_t new_colour, CultureGroup const& new_group,
- std::vector<std::string>&& new_first_names, std::vector<std::string>&& new_last_names
+ name_list_t&& new_first_names, name_list_t&& new_last_names
) : HasIdentifierAndColour { new_identifier, new_colour, false }, group { new_group },
first_names { std::move(new_first_names) }, last_names { std::move(new_last_names) } {}
@@ -51,8 +51,8 @@ bool CultureManager::add_culture_group(
}
bool CultureManager::add_culture(
- std::string_view identifier, colour_t colour, CultureGroup const& group, std::vector<std::string>&& first_names,
- std::vector<std::string>&& last_names
+ std::string_view identifier, colour_t colour, CultureGroup const& group, name_list_t&& first_names,
+ name_list_t&& last_names
) {
if (!culture_groups.is_locked()) {
Logger::error("Cannot register cultures until culture groups are locked!");
@@ -99,7 +99,7 @@ bool CultureManager::_load_culture(
) {
colour_t colour = colour_t::null();
- std::vector<std::string> first_names, last_names;
+ name_list_t first_names, last_names;
bool ret = expect_dictionary_keys(
"color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)),
diff --git a/src/openvic-simulation/pop/Culture.hpp b/src/openvic-simulation/pop/Culture.hpp
index 1c6b75f..c8dfe7a 100644
--- a/src/openvic-simulation/pop/Culture.hpp
+++ b/src/openvic-simulation/pop/Culture.hpp
@@ -40,14 +40,14 @@ namespace OpenVic {
private:
CultureGroup const& PROPERTY(group);
- const std::vector<std::string> PROPERTY(first_names);
- const std::vector<std::string> PROPERTY(last_names);
+ const name_list_t PROPERTY(first_names);
+ const name_list_t PROPERTY(last_names);
// TODO - radicalism, primary tag
Culture(
std::string_view new_identifier, colour_t new_colour, CultureGroup const& new_group,
- std::vector<std::string>&& new_first_names, std::vector<std::string>&& new_last_names
+ name_list_t&& new_first_names, name_list_t&& new_last_names
);
public:
@@ -75,8 +75,8 @@ namespace OpenVic {
);
bool add_culture(
- std::string_view identifier, colour_t colour, CultureGroup const& group, std::vector<std::string>&& first_names,
- std::vector<std::string>&& last_names
+ std::string_view identifier, colour_t colour, CultureGroup const& group, name_list_t&& first_names,
+ name_list_t&& last_names
);
bool load_graphical_culture_type_file(ast::NodeCPtr root);
diff --git a/src/openvic-simulation/pop/Pop.cpp b/src/openvic-simulation/pop/Pop.cpp
index ce310e1..0c70842 100644
--- a/src/openvic-simulation/pop/Pop.cpp
+++ b/src/openvic-simulation/pop/Pop.cpp
@@ -194,14 +194,12 @@ bool PopManager::load_pop_type_file(
"country_migration_target", ZERO_OR_ONE, country_migration_target.expect_conditional_weight(ConditionalWeight::FACTOR),
"migration_target", ZERO_OR_ONE, migration_target.expect_conditional_weight(ConditionalWeight::FACTOR),
"promote_to", ZERO_OR_ONE, assign_variable_callback(promote_to_node),
- "ideologies", ZERO_OR_ONE, ideology_manager.expect_ideology_dictionary(
+ "ideologies", ZERO_OR_ONE, ideology_manager.expect_ideology_dictionary_reserve_length(
+ ideologies,
[&filestem, &ideologies](Ideology const& ideology, ast::NodeCPtr node) -> bool {
ConditionalWeight weight { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE };
bool ret = weight.expect_conditional_weight(ConditionalWeight::FACTOR)(node);
- if (!ideologies.emplace(&ideology, std::move(weight)).second) {
- Logger::error("Duplicate ideology in pop type ", filestem, " ideology weights: ", ideology);
- ret = false;
- }
+ ret &= map_callback(ideologies, &ideology)(std::move(weight));
return ret;
}
),
@@ -233,7 +231,8 @@ bool PopManager::load_delayed_parse_pop_type_data(IssueManager const& issue_mana
for (size_t index = 0; index < delayed_parse_promote_to_and_issues_nodes.size(); ++index) {
const auto [promote_to_node, issues_node] = delayed_parse_promote_to_and_issues_nodes[index];
PopType* pop_type = pop_types.get_item_by_index(index);
- if (promote_to_node != nullptr && !expect_pop_type_dictionary(
+ if (promote_to_node != nullptr && !expect_pop_type_dictionary_reserve_length(
+ pop_type->promote_to,
[pop_type](PopType const& type, ast::NodeCPtr node) -> bool {
if (pop_type == &type) {
Logger::error("Pop type ", type, " cannot have promotion weight to itself!");
@@ -241,17 +240,15 @@ bool PopManager::load_delayed_parse_pop_type_data(IssueManager const& issue_mana
}
ConditionalWeight weight { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE };
bool ret = weight.expect_conditional_weight(ConditionalWeight::FACTOR)(node);
- if (!pop_type->promote_to.emplace(&type, std::move(weight)).second) {
- Logger::error("Duplicate pop type in pop type ", pop_type, " promotion weights: ", type);
- ret = false;
- }
+ ret &= map_callback(pop_type->promote_to, &type)(std::move(weight));
return ret;
}
)(promote_to_node)) {
Logger::error("Errors parsing pop type ", pop_type, " promotion weights!");
ret = false;
}
- if (issues_node != nullptr && !expect_dictionary(
+ if (issues_node != nullptr && !expect_dictionary_reserve_length(
+ pop_type->issues,
[pop_type, &issue_manager](std::string_view key, ast::NodeCPtr node) -> bool {
Issue const* issue = issue_manager.get_issue_by_identifier(key);
if (issue == nullptr) {
@@ -263,10 +260,7 @@ bool PopManager::load_delayed_parse_pop_type_data(IssueManager const& issue_mana
}
ConditionalWeight weight { scope_t::POP, scope_t::POP, scope_t::NO_SCOPE };
bool ret = weight.expect_conditional_weight(ConditionalWeight::FACTOR)(node);
- if (!pop_type->issues.emplace(issue, std::move(weight)).second) {
- Logger::error("Duplicate issue in pop type ", pop_type, " issue weights: ", issue->get_identifier());
- ret = false;
- }
+ ret &= map_callback(pop_type->issues, issue)(std::move(weight));
return ret;
}
)(issues_node)) {
diff --git a/src/openvic-simulation/scripts/Condition.cpp b/src/openvic-simulation/scripts/Condition.cpp
index 73b3606..ce18824 100644
--- a/src/openvic-simulation/scripts/Condition.cpp
+++ b/src/openvic-simulation/scripts/Condition.cpp
@@ -721,7 +721,7 @@ node_callback_t ConditionManager::expect_condition_node_list(
};
bool ret = conditions.expect_item_dictionary_and_default(
- expect_node, top_scope ? top_scope_fallback : key_value_invalid_callback
+ top_scope ? top_scope_fallback : key_value_invalid_callback, expect_node
)(node);
if (!ret) {
Logger::error("Error parsing condition node:\n", node);
diff --git a/src/openvic-simulation/types/HasIdentifier.hpp b/src/openvic-simulation/types/HasIdentifier.hpp
new file mode 100644
index 0000000..9457e75
--- /dev/null
+++ b/src/openvic-simulation/types/HasIdentifier.hpp
@@ -0,0 +1,88 @@
+#pragma once
+
+#include <algorithm>
+#include <cassert>
+#include <ostream>
+
+#include "openvic-simulation/types/Colour.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
+
+namespace OpenVic {
+ constexpr bool valid_basic_identifier_char(char c) {
+ return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || c == '_';
+ }
+ constexpr bool valid_basic_identifier(std::string_view identifier) {
+ return std::all_of(identifier.begin(), identifier.end(), valid_basic_identifier_char);
+ }
+ constexpr std::string_view extract_basic_identifier_prefix(std::string_view identifier) {
+ size_t len = 0;
+ while (len < identifier.size() && valid_basic_identifier_char(identifier[len])) {
+ ++len;
+ }
+ return { identifier.data(), len };
+ }
+
+ /*
+ * Base class for objects with a non-empty string identifier. Uniquely named instances of a type derived from this class
+ * can be entered into an IdentifierRegistry instance.
+ */
+ class HasIdentifier {
+ const std::string PROPERTY(identifier);
+
+ protected:
+ HasIdentifier(std::string_view new_identifier): identifier { new_identifier } {
+ assert(!identifier.empty());
+ }
+
+ public:
+ HasIdentifier(HasIdentifier const&) = delete;
+ HasIdentifier(HasIdentifier&&) = default;
+ HasIdentifier& operator=(HasIdentifier const&) = delete;
+ HasIdentifier& operator=(HasIdentifier&&) = delete;
+ };
+
+ inline std::ostream& operator<<(std::ostream& stream, HasIdentifier const& obj) {
+ return stream << obj.get_identifier();
+ }
+ inline std::ostream& operator<<(std::ostream& stream, HasIdentifier const* obj) {
+ return obj != nullptr ? stream << *obj : stream << "<NULL>";
+ }
+
+ /*
+ * Base class for objects with associated colour information.
+ */
+ template<IsColour ColourT>
+ class _HasColour {
+ const ColourT PROPERTY(colour);
+
+ protected:
+ _HasColour(ColourT new_colour, bool cannot_be_null): colour { new_colour } {
+ assert(!cannot_be_null || !colour.is_null());
+ }
+
+ public:
+ _HasColour(_HasColour const&) = delete;
+ _HasColour(_HasColour&&) = default;
+ _HasColour& operator=(_HasColour const&) = delete;
+ _HasColour& operator=(_HasColour&&) = delete;
+ };
+
+ /*
+ * Base class for objects with a unique string identifier and associated colour information.
+ */
+ template<IsColour ColourT>
+ class _HasIdentifierAndColour : public HasIdentifier, public _HasColour<ColourT> {
+ protected:
+ _HasIdentifierAndColour(std::string_view new_identifier, ColourT new_colour, bool cannot_be_null)
+ : HasIdentifier { new_identifier }, _HasColour<ColourT> { new_colour, cannot_be_null } {}
+
+ public:
+ _HasIdentifierAndColour(_HasIdentifierAndColour const&) = delete;
+ _HasIdentifierAndColour(_HasIdentifierAndColour&&) = default;
+ _HasIdentifierAndColour& operator=(_HasIdentifierAndColour const&) = delete;
+ _HasIdentifierAndColour& operator=(_HasIdentifierAndColour&&) = delete;
+ };
+
+ using HasIdentifierAndColour = _HasIdentifierAndColour<colour_t>;
+ using HasIdentifierAndAlphaColour = _HasIdentifierAndColour<colour_argb_t>;
+}
diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp
index 53a68a5..04198b0 100644
--- a/src/openvic-simulation/types/IdentifierRegistry.hpp
+++ b/src/openvic-simulation/types/IdentifierRegistry.hpp
@@ -1,93 +1,14 @@
#pragma once
-#include <cassert>
#include <vector>
#include "openvic-simulation/dataloader/NodeTools.hpp"
#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
+#include "openvic-simulation/types/HasIdentifier.hpp"
#include "openvic-simulation/utility/Getters.hpp"
#include "openvic-simulation/utility/Logger.hpp"
namespace OpenVic {
-
- constexpr bool valid_basic_identifier_char(char c) {
- return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || c == '_';
- }
- constexpr bool valid_basic_identifier(std::string_view identifier) {
- return std::all_of(identifier.begin(), identifier.end(), valid_basic_identifier_char);
- }
- constexpr std::string_view extract_basic_identifier_prefix(std::string_view identifier) {
- size_t len = 0;
- while (len < identifier.size() && valid_basic_identifier_char(identifier[len])) {
- ++len;
- }
- return { identifier.data(), len };
- }
-
- /*
- * Base class for objects with a non-empty string identifier. Uniquely named instances of a type derived from this class
- * can be entered into an IdentifierRegistry instance.
- */
- class HasIdentifier {
- const std::string PROPERTY(identifier);
-
- protected:
- HasIdentifier(std::string_view new_identifier): identifier { new_identifier } {
- assert(!identifier.empty());
- }
-
- public:
- HasIdentifier(HasIdentifier const&) = delete;
- HasIdentifier(HasIdentifier&&) = default;
- HasIdentifier& operator=(HasIdentifier const&) = delete;
- HasIdentifier& operator=(HasIdentifier&&) = delete;
- };
-
- inline std::ostream& operator<<(std::ostream& stream, HasIdentifier const& obj) {
- return stream << obj.get_identifier();
- }
- inline std::ostream& operator<<(std::ostream& stream, HasIdentifier const* obj) {
- return obj != nullptr ? stream << *obj : stream << "<NULL>";
- }
-
- /*
- * Base class for objects with associated colour information.
- */
- template<IsColour ColourT>
- class _HasColour {
- const ColourT PROPERTY(colour);
-
- protected:
- _HasColour(ColourT new_colour, bool cannot_be_null): colour { new_colour } {
- assert(!cannot_be_null || !colour.is_null());
- }
-
- public:
- _HasColour(_HasColour const&) = delete;
- _HasColour(_HasColour&&) = default;
- _HasColour& operator=(_HasColour const&) = delete;
- _HasColour& operator=(_HasColour&&) = delete;
- };
-
- /*
- * Base class for objects with a unique string identifier and associated colour information.
- */
- template<IsColour ColourT>
- class _HasIdentifierAndColour : public HasIdentifier, public _HasColour<ColourT> {
- protected:
- _HasIdentifierAndColour(std::string_view new_identifier, ColourT new_colour, bool cannot_be_null)
- : HasIdentifier { new_identifier }, _HasColour<ColourT> { new_colour, cannot_be_null } {}
-
- public:
- _HasIdentifierAndColour(_HasIdentifierAndColour const&) = delete;
- _HasIdentifierAndColour(_HasIdentifierAndColour&&) = default;
- _HasIdentifierAndColour& operator=(_HasIdentifierAndColour const&) = delete;
- _HasIdentifierAndColour& operator=(_HasIdentifierAndColour&&) = delete;
- };
-
- using HasIdentifierAndColour = _HasIdentifierAndColour<colour_t>;
- using HasIdentifierAndAlphaColour = _HasIdentifierAndColour<colour_argb_t>;
-
/* Callbacks for trying to add duplicate keys via UniqueKeyRegistry::add_item */
static bool duplicate_fail_callback(std::string_view registry_name, std::string_view duplicate_identifier) {
Logger::error(
@@ -199,9 +120,17 @@ namespace OpenVic {
Logger::error("Failed to reserve space for ", size, " items in ", name, " registry - already locked!");
} else {
items.reserve(size);
+ identifier_index_map.reserve(size);
}
}
+ static NodeTools::KeyValueCallback auto key_value_invalid_callback(std::string_view name) {
+ return [name](std::string_view key, ast::NodeCPtr) {
+ Logger::error("Invalid ", name, ": ", key);
+ return false;
+ };
+ }
+
#define GETTERS(CONST) \
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); \
@@ -235,12 +164,12 @@ namespace OpenVic {
) CONST { \
return NodeTools::expect_identifier(expect_item_str(callback, warn)); \
} \
- NodeTools::NodeCallback auto expect_item_dictionary_and_default( \
- NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback, \
- NodeTools::KeyValueCallback auto default_callback \
+ NodeTools::NodeCallback auto expect_item_assign_and_default( \
+ NodeTools::KeyValueCallback auto default_callback, \
+ NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
) CONST { \
- return NodeTools::expect_dictionary( \
- [this, callback, default_callback](std::string_view key, ast::NodeCPtr value) -> bool { \
+ return NodeTools::expect_assign( \
+ [this, default_callback, callback](std::string_view key, ast::NodeCPtr value) -> bool { \
value_type CONST* item = get_item_by_identifier(key); \
if (item != nullptr) { \
return callback(*item, value); \
@@ -250,14 +179,70 @@ namespace OpenVic {
} \
); \
} \
+ NodeTools::NodeCallback auto expect_item_assign( \
+ NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
+ ) CONST { \
+ return expect_item_assign_and_default(key_value_invalid_callback(name), callback); \
+ } \
+ NodeTools::NodeCallback auto expect_item_dictionary_and_length_and_default( \
+ NodeTools::LengthCallback auto length_callback, \
+ NodeTools::KeyValueCallback auto default_callback, \
+ NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
+ ) CONST { \
+ return NodeTools::expect_list_and_length( \
+ length_callback, expect_item_assign_and_default(default_callback, callback) \
+ ); \
+ } \
+ NodeTools::NodeCallback auto expect_item_dictionary_and_length( \
+ NodeTools::LengthCallback auto length_callback, \
+ NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
+ ) CONST { \
+ return expect_item_dictionary_and_length_and_default( \
+ length_callback, \
+ key_value_invalid_callback(name), \
+ callback \
+ ); \
+ } \
+ NodeTools::NodeCallback auto expect_item_dictionary_and_default( \
+ NodeTools::KeyValueCallback auto default_callback, \
+ NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
+ ) CONST { \
+ return expect_item_dictionary_and_length_and_default( \
+ NodeTools::default_length_callback, \
+ default_callback, \
+ callback \
+ ); \
+ } \
NodeTools::NodeCallback auto expect_item_dictionary( \
NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
) CONST { \
- return expect_item_dictionary_and_default( \
- callback, [this](std::string_view key, ast::NodeCPtr) -> bool { \
- Logger::error("Invalid ", name, ": ", key); \
- return false; \
- } \
+ return expect_item_dictionary_and_length_and_default( \
+ NodeTools::default_length_callback, \
+ key_value_invalid_callback(name), \
+ callback \
+ ); \
+ } \
+ template<NodeTools::Reservable T> \
+ NodeTools::NodeCallback auto expect_item_dictionary_reserve_length_and_default( \
+ T& t, \
+ NodeTools::KeyValueCallback auto default_callback, \
+ NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
+ ) CONST { \
+ return expect_item_dictionary_and_length_and_default( \
+ NodeTools::reserve_length_callback(t), \
+ default_callback, \
+ callback \
+ ); \
+ } \
+ template<NodeTools::Reservable T> \
+ NodeTools::NodeCallback auto expect_item_dictionary_reserve_length( \
+ T& t, \
+ NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
+ ) CONST { \
+ return expect_item_dictionary_and_length_and_default( \
+ NodeTools::reserve_length_callback(t), \
+ key_value_invalid_callback(name), \
+ callback \
); \
}
@@ -432,15 +417,48 @@ private:
) const_kw { \
return registry.expect_item_identifier(callback, warn); \
} \
+ NodeTools::NodeCallback auto expect_##singular##_assign_and_default( \
+ NodeTools::KeyValueCallback auto default_callback, \
+ NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
+ ) const_kw { \
+ return registry.expect_item_assign_and_default(default_callback, callback); \
+ } \
+ NodeTools::NodeCallback auto expect_##singular##_assign( \
+ NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
+ ) const_kw { \
+ return registry.expect_item_assign(callback); \
+ } \
+ NodeTools::NodeCallback auto expect_##singular##_dictionary_and_length_and_default( \
+ NodeTools::LengthCallback auto length_callback, \
+ NodeTools::KeyValueCallback auto default_callback, \
+ NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
+ ) const_kw { \
+ return registry.expect_item_dictionary_and_length_and_default(length_callback, default_callback, callback); \
+ } \
NodeTools::NodeCallback auto expect_##singular##_dictionary_and_default( \
- NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback, \
- NodeTools::KeyValueCallback auto default_callback \
+ NodeTools::KeyValueCallback auto default_callback, \
+ NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
) const_kw { \
- return registry.expect_item_dictionary_and_default(callback, default_callback); \
+ return registry.expect_item_dictionary_and_default(default_callback, callback); \
} \
NodeTools::NodeCallback auto expect_##singular##_dictionary( \
NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
) const_kw { \
return registry.expect_item_dictionary(callback); \
+ } \
+ template<NodeTools::Reservable T> \
+ NodeTools::NodeCallback auto expect_##singular##_dictionary_reserve_length_and_default( \
+ T& t, \
+ NodeTools::KeyValueCallback auto default_callback, \
+ NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
+ ) const_kw { \
+ return registry.expect_item_dictionary_reserve_length_and_default(t, default_callback, callback); \
+ } \
+ template<NodeTools::Reservable T> \
+ NodeTools::NodeCallback auto expect_##singular##_dictionary_reserve_length( \
+ T& t, \
+ NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
+ ) const_kw { \
+ return registry.expect_item_dictionary_reserve_length(t, callback); \
}
}
diff --git a/src/openvic-simulation/types/OrderedContainers.hpp b/src/openvic-simulation/types/OrderedContainers.hpp
index 1df9b10..e9f8717 100644
--- a/src/openvic-simulation/types/OrderedContainers.hpp
+++ b/src/openvic-simulation/types/OrderedContainers.hpp
@@ -146,7 +146,7 @@ namespace OpenVic {
template<class Key, class T, class Allocator = std::allocator<std::pair<Key, T>>, class IndexType = std::uint_least32_t>
using case_insensitive_deque_ordered_map =
deque_ordered_map<Key, T, case_insensitive_string_hash, case_insensitive_string_equal, Allocator, IndexType>;
-
+
template<class Key, class T, class Allocator = std::allocator<std::pair<Key, T>>, class IndexType = std::uint_least32_t>
using case_insensitive_ordered_map = case_insensitive_vector_ordered_map<Key, T, Allocator, IndexType>;