aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/headless/main.cpp8
-rw-r--r--src/openvic-simulation/GameManager.cpp28
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp12
-rw-r--r--src/openvic-simulation/dataloader/NodeTools.hpp43
-rw-r--r--src/openvic-simulation/diplomacy/DiplomaticAction.hpp1
-rw-r--r--src/openvic-simulation/economy/BuildingType.cpp12
-rw-r--r--src/openvic-simulation/economy/ProductionType.cpp125
-rw-r--r--src/openvic-simulation/economy/ProductionType.hpp44
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.cpp10
-rw-r--r--src/openvic-simulation/military/Deployment.cpp15
-rw-r--r--src/openvic-simulation/military/Deployment.hpp4
-rw-r--r--src/openvic-simulation/military/Unit.cpp4
-rw-r--r--src/openvic-simulation/military/Wargoal.cpp8
-rw-r--r--src/openvic-simulation/military/Wargoal.hpp52
-rw-r--r--src/openvic-simulation/misc/Event.cpp2
-rw-r--r--src/openvic-simulation/misc/Modifier.cpp16
-rw-r--r--src/openvic-simulation/politics/Rebel.cpp1
-rw-r--r--src/openvic-simulation/pop/Culture.cpp88
-rw-r--r--src/openvic-simulation/pop/Culture.hpp39
-rw-r--r--src/openvic-simulation/pop/Pop.cpp332
-rw-r--r--src/openvic-simulation/pop/Pop.hpp167
-rw-r--r--src/openvic-simulation/research/Invention.cpp1
-rw-r--r--src/openvic-simulation/scripts/Condition.cpp271
-rw-r--r--src/openvic-simulation/scripts/Condition.hpp63
-rw-r--r--src/openvic-simulation/types/Colour.hpp33
-rw-r--r--src/openvic-simulation/types/FunctionRef.hpp17
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.hpp10
-rw-r--r--src/openvic-simulation/utility/Logger.hpp6
-rw-r--r--src/openvic-simulation/utility/StringUtils.hpp2
29 files changed, 949 insertions, 465 deletions
diff --git a/src/headless/main.cpp b/src/headless/main.cpp
index 7f33314..a6c4914 100644
--- a/src/headless/main.cpp
+++ b/src/headless/main.cpp
@@ -131,9 +131,10 @@ int main(int argc, char const* argv[]) {
return -1;
}
}
- Dataloader::path_vector_t roots = { root };
+ Dataloader::path_vector_t roots { root };
while (argn < argc) {
- roots.emplace_back(root / argv[argn++]);
+ static const fs::path mod_directory = "mod";
+ roots.emplace_back(root / mod_directory / argv[argn++]);
}
std::cout << "!!! HEADLESS SIMULATION START !!!" << std::endl;
@@ -144,5 +145,8 @@ int main(int argc, char const* argv[]) {
std::cout << "\nLoad returned: " << (ret ? "SUCCESS" : "FAILURE") << std::endl;
+ std::cout << "\nLogger Summary: Info = " << Logger::get_info_count() << ", Warning = " << Logger::get_warning_count()
+ << ", Error = " << Logger::get_error_count() << std::endl;
+
return ret ? 0 : -1;
}
diff --git a/src/openvic-simulation/GameManager.cpp b/src/openvic-simulation/GameManager.cpp
index 50ec2b2..6435f05 100644
--- a/src/openvic-simulation/GameManager.cpp
+++ b/src/openvic-simulation/GameManager.cpp
@@ -83,13 +83,24 @@ bool GameManager::expand_selected_province_building(size_t building_index) {
return province->expand_building(building_index);
}
-static constexpr colour_argb_t::value_type ALPHA_VALUE = colour_argb_t::colour_traits::alpha_from_float(0.7f);
+static constexpr colour_argb_t::value_type ALPHA_VALUE = colour_argb_t::max_value;
+/* White default colour, used in mapmodes including political, revolt risk and party loyaly. */
+static constexpr colour_argb_t DEFAULT_COLOUR_WHITE = (0xFFFFFF_argb).with_alpha(ALPHA_VALUE);
+/* Grey default colour, used in mapmodes including diplomatic, administrative and colonial, recruitment,
+ * national focus, RGO, population density, sphere of influence, ranking and migration. */
+static constexpr colour_argb_t DEFAULT_COLOUR_GREY = (0x7F7F7F_argb).with_alpha(ALPHA_VALUE);
template<IsColour ColourT = colour_t, std::derived_from<_HasColour<ColourT>> T>
static constexpr auto get_colour_mapmode(T const*(Province::*get_item)() const) {
return [get_item](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
T const* item = (province.*get_item)();
- return item != nullptr ? colour_argb_t { item->get_colour(), ALPHA_VALUE } : colour_argb_t::null();
+ if (item != nullptr) {
+ return colour_argb_t { item->get_colour(), ALPHA_VALUE };
+ } else if (!province.is_water()) {
+ return DEFAULT_COLOUR_WHITE;
+ } else {
+ return colour_argb_t::null();
+ }
};
}
@@ -133,6 +144,7 @@ bool GameManager::load_hardcoded_defines() {
"mapmode_political", get_colour_mapmode(&Province::get_owner)
},
{
+ /* TEST MAPMODE, TO BE REMOVED */
"mapmode_province",
[](Map const&, Province const& province) -> Mapmode::base_stripe_t {
return colour_argb_t { province.get_colour(), ALPHA_VALUE };
@@ -142,6 +154,7 @@ bool GameManager::load_hardcoded_defines() {
"mapmode_region", get_colour_mapmode(&Province::get_region)
},
{
+ /* TEST MAPMODE, TO BE REMOVED */
"mapmode_index",
[](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
const colour_argb_t::value_type f =
@@ -150,6 +163,7 @@ bool GameManager::load_hardcoded_defines() {
}
},
{
+ /* Non-vanilla mapmode, still of use in game. */
"mapmode_terrain_type", get_colour_mapmode(&Province::get_terrain_type)
},
{
@@ -191,9 +205,11 @@ bool GameManager::load_hardcoded_defines() {
"mapmode_culture", shaded_mapmode(&Province::get_culture_distribution)
},
{
+ /* Non-vanilla mapmode, still of use in game. */
"mapmode_religion", shaded_mapmode(&Province::get_religion_distribution)
},
{
+ /* TEST MAPMODE, TO BE REMOVED */
"mapmode_adjacencies", [](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
Province const* selected_province = map.get_selected_province();
if (selected_province != nullptr) {
@@ -228,7 +244,13 @@ bool GameManager::load_hardcoded_defines() {
},
{
"mapmode_port", [](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
- return province.has_port() ? (0xFFFFFF_argb).with_alpha(ALPHA_VALUE) : colour_argb_t::null();
+ if (province.has_port()) {
+ return (0xFFFFFF_argb).with_alpha(ALPHA_VALUE);
+ } else if (!province.is_water()) {
+ return (0x333333_argb).with_alpha(ALPHA_VALUE);
+ } else {
+ return colour_argb_t::null();
+ }
}
}
};
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp
index a3d00cc..6a2a3bb 100644
--- a/src/openvic-simulation/dataloader/Dataloader.cpp
+++ b/src/openvic-simulation/dataloader/Dataloader.cpp
@@ -791,12 +791,6 @@ bool Dataloader::load_defines(GameManager& game_manager) {
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()
- )) {
- 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()
)) {
@@ -928,6 +922,12 @@ bool Dataloader::load_defines(GameManager& game_manager) {
Logger::error("Failed to load countries!");
ret = false;
}
+ if (!game_manager.get_pop_manager().get_culture_manager().load_culture_file(
+ game_manager.get_country_manager(), parse_defines(lookup_file(culture_file)).get_file_node()
+ )) {
+ Logger::error("Failed to load cultures!");
+ ret = false;
+ }
if (!_load_decisions(game_manager)) {
Logger::error("Failde to load decisions!");
ret = false;
diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp
index b3fce16..4b33c6d 100644
--- a/src/openvic-simulation/dataloader/NodeTools.hpp
+++ b/src/openvic-simulation/dataloader/NodeTools.hpp
@@ -356,33 +356,46 @@ namespace OpenVic {
};
}
+ template<typename... Args>
+ bool warn_or_error(bool warn, Args... args) {
+ if (warn) {
+ Logger::warning(args...);
+ return true;
+ } else {
+ Logger::error(args...);
+ return false;
+ }
+ }
+
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, "\"");
+ Callback<T> auto set_callback(tsl::ordered_set<U, SetArgs...>& set, bool warn = false) {
+ return [&set, warn](T val) -> bool {
+ if (set.emplace(std::move(val)).second) {
+ return true;
}
- return true;
+ return warn_or_error(warn, "Duplicate set entry: \"", val, "\"");
};
}
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 {
- if (!set.emplace(&val).second) {
- Logger::warning("Duplicate set entry: \"", &val, "\"");
+ Callback<T const&> auto set_callback_pointer(tsl::ordered_set<T const*, SetArgs...>& set, bool warn = false) {
+ return [&set, warn](T const& val) -> bool {
+ if (set.emplace(&val).second) {
+ return true;
}
- return true;
+ return warn_or_error(warn, "Duplicate set entry: \"", &val, "\"");
};
}
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, "\"");
+ Callback<Value> auto map_callback(
+ tsl::ordered_map<Key const*, Value, MapArgs...>& map, Key const* key, bool warn = false
+ ) {
+ return [&map, key, warn](Value value) -> bool {
+ if (map.emplace(key, std::move(value)).second) {
+ return true;
}
- return true;
+ return warn_or_error(warn, "Duplicate map entry with key: \"", key, "\"");
};
}
}
diff --git a/src/openvic-simulation/diplomacy/DiplomaticAction.hpp b/src/openvic-simulation/diplomacy/DiplomaticAction.hpp
index 3d0cbca..352b16e 100644
--- a/src/openvic-simulation/diplomacy/DiplomaticAction.hpp
+++ b/src/openvic-simulation/diplomacy/DiplomaticAction.hpp
@@ -60,7 +60,6 @@ namespace OpenVic {
using allowed_to_cancel_func = FunctionRef<bool(const Argument&)>;
-
static bool allowed_to_cancel_default(const Argument& argument) {
return true;
}
diff --git a/src/openvic-simulation/economy/BuildingType.cpp b/src/openvic-simulation/economy/BuildingType.cpp
index c9ed410..e06beea 100644
--- a/src/openvic-simulation/economy/BuildingType.cpp
+++ b/src/openvic-simulation/economy/BuildingType.cpp
@@ -97,13 +97,13 @@ bool BuildingTypeManager::load_buildings_file(
lock_building_types();
for (BuildingType const& building_type : building_types.get_items()) {
- std::string max_modifier_prefix = "max_";
- std::string min_modifier_prefix = "min_build_";
- modifier_manager.add_modifier_effect(
- max_modifier_prefix.append(building_type.get_identifier()), true, ModifierEffect::format_t::INT
+ static constexpr std::string_view max_prefix = "max_";
+ static constexpr std::string_view min_prefix = "min_build_";
+ ret &= modifier_manager.add_modifier_effect(
+ StringUtils::append_string_views(max_prefix, building_type.get_identifier()), true, ModifierEffect::format_t::INT
);
- modifier_manager.add_modifier_effect(
- min_modifier_prefix.append(building_type.get_identifier()), false, ModifierEffect::format_t::INT
+ ret &= modifier_manager.add_modifier_effect(
+ StringUtils::append_string_views(min_prefix, building_type.get_identifier()), false, ModifierEffect::format_t::INT
);
if (building_type.is_in_province()) {
diff --git a/src/openvic-simulation/economy/ProductionType.cpp b/src/openvic-simulation/economy/ProductionType.cpp
index 61ec27f..86f3c13 100644
--- a/src/openvic-simulation/economy/ProductionType.cpp
+++ b/src/openvic-simulation/economy/ProductionType.cpp
@@ -4,23 +4,30 @@ using namespace OpenVic;
using namespace OpenVic::NodeTools;
Job::Job(
- PopType const* const new_pop_type, effect_t new_effect_type, fixed_point_t new_effect_multiplier,
+ PopType const* new_pop_type, effect_t new_effect_type, fixed_point_t new_effect_multiplier,
fixed_point_t new_desired_workforce_share
-)
- : pop_type { new_pop_type }, effect_type { new_effect_type }, effect_multiplier { new_effect_multiplier },
- desired_workforce_share { new_desired_workforce_share } {}
+) : pop_type { new_pop_type }, effect_type { new_effect_type }, effect_multiplier { new_effect_multiplier },
+ desired_workforce_share { new_desired_workforce_share } {}
ProductionType::ProductionType(
- std::string_view new_identifier, Job new_owner, std::vector<Job> new_jobs, template_type_t new_template_type,
- Pop::pop_size_t new_base_workforce_size, Good::good_map_t&& new_input_goods, Good const* const new_output_goods,
- fixed_point_t new_base_output_quantity, std::vector<bonus_t>&& new_bonuses, Good::good_map_t&& new_maintenance_requirements,
- bool new_is_coastal, bool new_is_farm, bool new_is_mine
-)
- : HasIdentifier { new_identifier }, owner { new_owner }, jobs { new_jobs }, template_type { new_template_type },
- base_workforce_size { new_base_workforce_size }, input_goods { std::move(new_input_goods) },
- output_goods { new_output_goods }, base_output_quantity { new_base_output_quantity }, bonuses { std::move(new_bonuses) },
- maintenance_requirements { std::move(new_maintenance_requirements) }, coastal { new_is_coastal }, farm { new_is_farm },
- mine { new_is_mine } {}
+ std::string_view new_identifier,
+ std::optional<Job> new_owner,
+ std::vector<Job>&& new_jobs,
+ template_type_t new_template_type,
+ Pop::pop_size_t new_base_workforce_size,
+ Good::good_map_t&& new_input_goods,
+ Good const* new_output_goods,
+ fixed_point_t new_base_output_quantity,
+ std::vector<bonus_t>&& new_bonuses,
+ Good::good_map_t&& new_maintenance_requirements,
+ bool new_is_coastal,
+ bool new_is_farm,
+ bool new_is_mine
+) : HasIdentifier { new_identifier }, owner { new_owner }, jobs { std::move(new_jobs) }, template_type { new_template_type },
+ base_workforce_size { new_base_workforce_size }, input_goods { std::move(new_input_goods) },
+ output_goods { new_output_goods }, base_output_quantity { new_base_output_quantity }, bonuses { std::move(new_bonuses) },
+ maintenance_requirements { std::move(new_maintenance_requirements) }, coastal { new_is_coastal }, farm { new_is_farm },
+ mine { new_is_mine } {}
bool ProductionType::parse_scripts(GameManager const& game_manager) {
bool ret = true;
@@ -33,10 +40,9 @@ bool ProductionType::parse_scripts(GameManager const& game_manager) {
ProductionTypeManager::ProductionTypeManager() : rgo_owner_sprite { 0 } {}
node_callback_t ProductionTypeManager::_expect_job(
- GoodManager const& good_manager, PopManager const& pop_manager, callback_t<Job&&> cb
+ GoodManager const& good_manager, PopManager const& pop_manager, callback_t<Job&&> callback
) {
-
- return [this, &good_manager, &pop_manager, cb](ast::NodeCPtr node) -> bool {
+ return [this, &good_manager, &pop_manager, callback](ast::NodeCPtr node) -> bool {
using enum Job::effect_t;
std::string_view pop_type {};
@@ -54,27 +60,36 @@ node_callback_t ProductionTypeManager::_expect_job(
"amount", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(desired_workforce_share))
)(node);
- PopType const* const found_pop_type = pop_manager.get_pop_type_by_identifier(pop_type);
- return res & cb({ found_pop_type, effect_type, effect_multiplier, desired_workforce_share });
+ PopType const* found_pop_type = pop_manager.get_pop_type_by_identifier(pop_type);
+ return res & callback({ found_pop_type, effect_type, effect_multiplier, desired_workforce_share });
};
}
node_callback_t ProductionTypeManager::_expect_job_list(
- GoodManager const& good_manager, PopManager const& pop_manager, callback_t<std::vector<Job>&&> cb
+ GoodManager const& good_manager, PopManager const& pop_manager, callback_t<std::vector<Job>&&> callback
) {
- return [this, &good_manager, &pop_manager, cb](ast::NodeCPtr node) -> bool {
+ return [this, &good_manager, &pop_manager, callback](ast::NodeCPtr node) -> bool {
std::vector<Job> jobs;
bool ret = expect_list(_expect_job(good_manager, pop_manager, vector_callback(jobs)))(node);
- ret &= cb(std::move(jobs));
+ ret &= callback(std::move(jobs));
return ret;
};
}
bool ProductionTypeManager::add_production_type(
- std::string_view identifier, Job owner, std::vector<Job> jobs, ProductionType::template_type_t template_type,
- Pop::pop_size_t base_workforce_size, Good::good_map_t&& input_goods, Good const* const output_goods,
- fixed_point_t base_output_quantity, std::vector<ProductionType::bonus_t>&& bonuses,
- Good::good_map_t&& maintenance_requirements, bool is_coastal, bool is_farm, bool is_mine
+ std::string_view identifier,
+ std::optional<Job> owner,
+ std::vector<Job>&& jobs,
+ ProductionType::template_type_t template_type,
+ Pop::pop_size_t base_workforce_size,
+ Good::good_map_t&& input_goods,
+ Good const* output_goods,
+ fixed_point_t base_output_quantity,
+ std::vector<ProductionType::bonus_t>&& bonuses,
+ Good::good_map_t&& maintenance_requirements,
+ bool is_coastal,
+ bool is_farm,
+ bool is_mine
) {
if (identifier.empty()) {
Logger::error("Invalid production type identifier - empty!");
@@ -96,13 +111,30 @@ bool ProductionTypeManager::add_production_type(
return false;
}
- if (template_type == ProductionType::template_type_t::ARTISAN) {
- if (owner.get_pop_type() != nullptr || !jobs.empty()) {
- Logger::warning("Artisanal production types don't use owner and employees. Effects are ignored.");
+ using enum ProductionType::template_type_t;
+
+ if (template_type == ARTISAN) {
+ if (owner.has_value()) {
+ Logger::warning(
+ "Artisanal production type ", identifier, " should not have an owner - it is being ignored."
+ );
+ owner.reset();
+ }
+
+ if (!jobs.empty()) {
+ Logger::warning(
+ "Artisanal production type ", identifier, " should not have employees - ", jobs.size(), " are being ignored."
+ );
+ jobs.clear();
}
} else {
- if (owner.get_pop_type() == nullptr) {
- Logger::error("Production type ", identifier, " lacks owner or has an invalid pop type.");
+ if (!owner.has_value()) {
+ Logger::error("Production type ", identifier, " is missing an owner.");
+ return false;
+ }
+
+ if (owner->get_pop_type() == nullptr) {
+ Logger::error("Production type ", identifier, " owner has an invalid pop type.");
return false;
}
@@ -120,12 +152,12 @@ bool ProductionTypeManager::add_production_type(
}
const bool ret = production_types.add_item({
- identifier, owner, jobs, template_type, base_workforce_size, std::move(input_goods),
- output_goods, base_output_quantity, std::move(bonuses), std::move(maintenance_requirements), is_coastal, is_farm, is_mine
+ identifier, owner, std::move(jobs), template_type, base_workforce_size, std::move(input_goods), output_goods,
+ base_output_quantity, std::move(bonuses), std::move(maintenance_requirements), is_coastal, is_farm, is_mine
});
- if (rgo_owner_sprite <= 0 && ret && template_type == ProductionType::template_type_t::RGO && owner.get_pop_type() != nullptr) {
+ if (rgo_owner_sprite <= 0 && ret && template_type == RGO && owner.has_value() && owner->get_pop_type() != nullptr) {
/* Set rgo owner sprite to that of the first RGO owner we find. */
- rgo_owner_sprite = owner.get_pop_type()->get_sprite();
+ rgo_owner_sprite = owner->get_pop_type()->get_sprite();
}
return ret;
}
@@ -135,7 +167,7 @@ bool ProductionTypeManager::load_production_types_file(
) {
size_t expected_types = 0;
- // pass 1: find and store template identifiers
+ /* Pass #1: find and store template identifiers */
ordered_set<std::string_view> templates;
ordered_map<std::string_view, std::string_view> template_target_map;
bool ret = expect_dictionary(
@@ -159,7 +191,7 @@ bool ProductionTypeManager::load_production_types_file(
}
)(root);
- // pass 2: create and populate the template map
+ /* Pass #2: create and populate the template map */
ordered_map<std::string_view, ast::NodeCPtr> template_node_map;
ret &= expect_dictionary(
[this, &expected_types, &templates, &template_node_map](std::string_view key, ast::NodeCPtr value) -> bool {
@@ -171,7 +203,7 @@ bool ProductionTypeManager::load_production_types_file(
}
)(root);
- // pass 3: actually load production types
+ /* Pass #3: actually load production types */
production_types.reserve(production_types.size() + expected_types);
ret &= expect_dictionary(
[this, &good_manager, &pop_manager, &template_target_map, &template_node_map](
@@ -182,13 +214,13 @@ bool ProductionTypeManager::load_production_types_file(
return true;
}
- Job owner {};
+ std::optional<Job> owner;
std::vector<Job> jobs;
ProductionType::template_type_t template_type { FACTORY };
Good const* output_goods = nullptr;
- Pop::pop_size_t base_workforce_size = 0; // 0 is a meaningless value -> unset
+ Pop::pop_size_t base_workforce_size = 0;
Good::good_map_t input_goods, maintenance_requirements;
- fixed_point_t base_output_quantity = 0; // 0 is a meaningless value -> unset
+ fixed_point_t base_output_quantity = 0;
std::vector<ProductionType::bonus_t> bonuses;
bool is_coastal = false, is_farm = false, is_mine = false;
@@ -198,8 +230,8 @@ bool ProductionTypeManager::load_production_types_file(
{ "factory", FACTORY }, { "rgo", RGO }, { "artisan", ARTISAN }
};
- const node_callback_t parse_node = expect_dictionary_keys(
- "template", ZERO_OR_ONE, success_callback,
+ const auto parse_node = expect_dictionary_keys(
+ "template", ZERO_OR_ONE, success_callback, /* Already parsed using expect_key in Pass #1 above. */
"bonus", ZERO_OR_MORE, [&bonuses](ast::NodeCPtr bonus_node) -> bool {
ConditionScript trigger { scope_t::STATE, scope_t::NO_SCOPE, scope_t::NO_SCOPE };
fixed_point_t bonus_value {};
@@ -223,7 +255,7 @@ bool ProductionTypeManager::load_production_types_file(
"mine", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_mine))
);
- // apply template first
+ /* Check if this ProductionType has a template, and if so parse it. */
{
const typename decltype(template_target_map)::const_iterator target_it = template_target_map.find(key);
if (target_it != template_target_map.end()) {
@@ -238,11 +270,12 @@ bool ProductionTypeManager::load_production_types_file(
}
}
+ /* Parse the ProductionType's own entries, over those of its template if necessary. */
ret &= parse_node(node);
ret &= add_production_type(
- key, owner, jobs, template_type, base_workforce_size, std::move(input_goods), output_goods, base_output_quantity, std::move(bonuses),
- std::move(maintenance_requirements), is_coastal, is_farm, is_mine
+ key, owner, std::move(jobs), template_type, base_workforce_size, std::move(input_goods), output_goods,
+ base_output_quantity, std::move(bonuses), std::move(maintenance_requirements), is_coastal, is_farm, is_mine
);
return ret;
}
diff --git a/src/openvic-simulation/economy/ProductionType.hpp b/src/openvic-simulation/economy/ProductionType.hpp
index cc7d44b..3c0bf3f 100644
--- a/src/openvic-simulation/economy/ProductionType.hpp
+++ b/src/openvic-simulation/economy/ProductionType.hpp
@@ -21,7 +21,9 @@ namespace OpenVic {
fixed_point_t PROPERTY(desired_workforce_share);
Job(
- PopType const* new_pop_type, effect_t new_effect_type, fixed_point_t new_effect_multiplier,
+ PopType const* new_pop_type,
+ effect_t new_effect_type,
+ fixed_point_t new_effect_multiplier,
fixed_point_t new_desired_workforce_share
);
@@ -37,7 +39,7 @@ namespace OpenVic {
using bonus_t = std::pair<ConditionScript, fixed_point_t>;
private:
- const Job PROPERTY(owner);
+ const std::optional<Job> PROPERTY(owner);
std::vector<Job> PROPERTY(jobs);
const template_type_t PROPERTY(template_type);
const Pop::pop_size_t PROPERTY(base_workforce_size);
@@ -54,13 +56,23 @@ namespace OpenVic {
const bool PROPERTY_CUSTOM_PREFIX(mine, is);
ProductionType(
- std::string_view new_identifier, Job new_owner, std::vector<Job> new_jobs, template_type_t new_template_type,
- Pop::pop_size_t new_base_workforce_size, Good::good_map_t&& new_input_goods, Good const* new_output_goods,
- fixed_point_t new_base_output_quantity, std::vector<bonus_t>&& new_bonuses, Good::good_map_t&& new_efficiency, bool new_is_coastal,
- bool new_is_farm, bool new_is_mine
+ std::string_view new_identifier,
+ std::optional<Job> new_owner,
+ std::vector<Job>&& new_jobs,
+ template_type_t new_template_type,
+ Pop::pop_size_t new_base_workforce_size,
+ Good::good_map_t&& new_input_goods,
+ Good const* new_output_goods,
+ fixed_point_t new_base_output_quantity,
+ std::vector<bonus_t>&& new_bonuses,
+ Good::good_map_t&& new_maintenance_requirements,
+ bool new_is_coastal,
+ bool new_is_farm,
+ bool new_is_mine
);
bool parse_scripts(GameManager const& game_manager);
+
public:
ProductionType(ProductionType&&) = default;
};
@@ -71,19 +83,29 @@ namespace OpenVic {
PopType::sprite_t PROPERTY(rgo_owner_sprite);
NodeTools::node_callback_t _expect_job(
- GoodManager const& good_manager, PopManager const& pop_manager, NodeTools::callback_t<Job&&> cb
+ GoodManager const& good_manager, PopManager const& pop_manager, NodeTools::callback_t<Job&&> callback
);
NodeTools::node_callback_t _expect_job_list(
- GoodManager const& good_manager, PopManager const& pop_manager, NodeTools::callback_t<std::vector<Job>&&> cb
+ GoodManager const& good_manager, PopManager const& pop_manager, NodeTools::callback_t<std::vector<Job>&&> callback
);
public:
ProductionTypeManager();
bool add_production_type(
- std::string_view identifier, Job owner, std::vector<Job> employees, ProductionType::template_type_t template_type,
- Pop::pop_size_t workforce, Good::good_map_t&& input_goods, Good const* output_goods, fixed_point_t value,
- std::vector<ProductionType::bonus_t>&& bonuses, Good::good_map_t&& efficiency, bool coastal, bool farm, bool mine
+ std::string_view identifier,
+ std::optional<Job> owner,
+ std::vector<Job>&& employees,
+ ProductionType::template_type_t template_type,
+ Pop::pop_size_t workforce,
+ Good::good_map_t&& input_goods,
+ Good const* output_goods,
+ fixed_point_t value,
+ std::vector<ProductionType::bonus_t>&& bonuses,
+ Good::good_map_t&& maintenance_requirements,
+ bool coastal,
+ bool farm,
+ bool mine
);
bool load_production_types_file(GoodManager const& good_manager, PopManager const& pop_manager, ast::NodeCPtr root);
diff --git a/src/openvic-simulation/history/ProvinceHistory.cpp b/src/openvic-simulation/history/ProvinceHistory.cpp
index 4117450..fd174a3 100644
--- a/src/openvic-simulation/history/ProvinceHistory.cpp
+++ b/src/openvic-simulation/history/ProvinceHistory.cpp
@@ -36,7 +36,11 @@ bool ProvinceHistoryMap::_load_history_entry(
BuildingType const* building_type = building_type_manager.get_building_type_by_identifier(key);
if (building_type != nullptr) {
if (building_type->is_in_province()) {
- return expect_uint<BuildingType::level_t>(map_callback(entry.province_buildings, building_type))(value);
+ return expect_uint<BuildingType::level_t>(
+ /* This is set to warn to prevent vanilla from always having errors because
+ * of a duplicate railroad entry in the 1861.1.1 history of Manchester (278). */
+ map_callback(entry.province_buildings, building_type, true)
+ )(value);
} else {
Logger::error(
"Attempted to add state building \"", building_type, "\" at top scope of province history for ",
@@ -68,7 +72,7 @@ bool ProvinceHistoryMap::_load_history_entry(
),
"party_loyalty", ZERO_OR_MORE, [&ideology_manager, &entry](ast::NodeCPtr node) -> bool {
Ideology const* ideology = nullptr;
- fixed_point_t amount = 0; // percent I do believe
+ fixed_point_t amount = 0; /* PERCENTAGE_DECIMAL */
bool ret = expect_dictionary_keys(
"ideology", ONE_EXACTLY, ideology_manager.expect_ideology_identifier(
@@ -90,7 +94,7 @@ bool ProvinceHistoryMap::_load_history_entry(
"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
+ "upgrade", ZERO_OR_ONE, success_callback /* Doesn't appear to have an effect */
)(node);
if (building_type != nullptr) {
if (!building_type->is_in_province()) {
diff --git a/src/openvic-simulation/military/Deployment.cpp b/src/openvic-simulation/military/Deployment.cpp
index da860ad..d4a092b 100644
--- a/src/openvic-simulation/military/Deployment.cpp
+++ b/src/openvic-simulation/military/Deployment.cpp
@@ -7,9 +7,9 @@ using namespace OpenVic::NodeTools;
Leader::Leader(
std::string_view new_name, Unit::type_t new_type, Date new_date, LeaderTrait const* new_personality,
- LeaderTrait const* new_background, fixed_point_t new_prestige
+ LeaderTrait const* new_background, fixed_point_t new_prestige, std::string_view new_picture
) : name { new_name }, type { new_type }, date { new_date }, personality { new_personality }, background { new_background },
- prestige { new_prestige } {}
+ prestige { new_prestige }, picture { new_picture } {}
Regiment::Regiment(std::string_view new_name, Unit const* new_type, Province const* new_home)
: name { new_name }, type { new_type }, home { new_home } {}
@@ -76,9 +76,10 @@ bool DeploymentManager::load_oob_file(
LeaderTrait const* leader_personality = nullptr;
LeaderTrait const* leader_background = nullptr;
fixed_point_t leader_prestige = 0;
+ std::string_view picture {};
bool ret = expect_dictionary_keys(
- "name", ONE_EXACTLY, expect_string(assign_variable_callback(leader_name)),
+ "name", ONE_EXACTLY, expect_identifier_or_string(assign_variable_callback(leader_name)),
"date", ONE_EXACTLY, expect_identifier_or_string(expect_date_str(assign_variable_callback(leader_date))),
"type", ONE_EXACTLY, expect_identifier(UnitManager::expect_type_str(assign_variable_callback(leader_type))),
"personality", ONE_EXACTLY, game_manager.get_military_manager().get_leader_trait_manager()
@@ -86,7 +87,7 @@ bool DeploymentManager::load_oob_file(
"background", ONE_EXACTLY, game_manager.get_military_manager().get_leader_trait_manager()
.expect_leader_trait_identifier(assign_variable_callback_pointer(leader_background)),
"prestige", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(leader_prestige)),
- "picture", ZERO_OR_ONE, success_callback
+ "picture", ZERO_OR_ONE, expect_identifier_or_string(assign_variable_callback(picture))
)(node);
if (!leader_personality->is_personality_trait()) {
@@ -104,7 +105,7 @@ bool DeploymentManager::load_oob_file(
ret = false;
}
leaders.emplace_back(
- leader_name, leader_type, leader_date, leader_personality, leader_background, leader_prestige
+ leader_name, leader_type, leader_date, leader_personality, leader_background, leader_prestige, picture
);
return ret;
},
@@ -134,7 +135,7 @@ bool DeploymentManager::load_oob_file(
army_regiments.emplace_back(regiment_name, regiment_type, regiment_home);
return ret;
},
- /* another paradox gem, tested in game and they don't lead the army or even show up */
+ /* Another paradox gem, tested in game and they don't lead the army or even show up */
"leader", ZERO_OR_MORE, success_callback
)(node);
armies.emplace_back(army_name, army_location, std::move(army_regiments));
@@ -160,7 +161,7 @@ bool DeploymentManager::load_oob_file(
navy_ships.emplace_back(ship_name, ship_type);
return ret;
},
- /* another paradox gem, tested in game and they don't lead the army or even show up */
+ /* Another paradox gem, tested in game and they don't lead the army or even show up */
"leader", ZERO_OR_MORE, success_callback
)(node);
navies.emplace_back(navy_name, navy_location, std::move(navy_ships));
diff --git a/src/openvic-simulation/military/Deployment.hpp b/src/openvic-simulation/military/Deployment.hpp
index 2aef314..a952823 100644
--- a/src/openvic-simulation/military/Deployment.hpp
+++ b/src/openvic-simulation/military/Deployment.hpp
@@ -1,6 +1,5 @@
#pragma once
-#include <filesystem>
#include <string>
#include <string_view>
#include <vector>
@@ -22,11 +21,12 @@ namespace OpenVic {
LeaderTrait const* PROPERTY(personality);
LeaderTrait const* PROPERTY(background);
fixed_point_t PROPERTY(prestige);
+ std::string PROPERTY(picture);
public:
Leader(
std::string_view new_name, Unit::type_t new_type, Date new_date, LeaderTrait const* new_personality,
- LeaderTrait const* new_background, fixed_point_t new_prestige
+ LeaderTrait const* new_background, fixed_point_t new_prestige, std::string_view new_picture
);
};
diff --git a/src/openvic-simulation/military/Unit.cpp b/src/openvic-simulation/military/Unit.cpp
index 9981c86..d0f6435 100644
--- a/src/openvic-simulation/military/Unit.cpp
+++ b/src/openvic-simulation/military/Unit.cpp
@@ -104,10 +104,10 @@ bool UnitManager::load_unit_file(GoodManager const& good_manager, ast::NodeCPtr
}
key_map_t key_map;
- // shared
+ /* Shared dictionary entries */
ret &= add_key_map_entries(key_map,
"icon", ONE_EXACTLY, expect_uint(assign_variable_callback(icon)),
- "type", ONE_EXACTLY, success_callback,
+ "type", ONE_EXACTLY, success_callback, /* Already loaded above using expect_key */
"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)),
diff --git a/src/openvic-simulation/military/Wargoal.cpp b/src/openvic-simulation/military/Wargoal.cpp
index 6351ce3..4045fa5 100644
--- a/src/openvic-simulation/military/Wargoal.cpp
+++ b/src/openvic-simulation/military/Wargoal.cpp
@@ -41,7 +41,7 @@ bool WargoalTypeManager::add_wargoal_type(
std::string_view identifier, std::string_view war_name, Timespan available_length,
Timespan truce_length, WargoalType::sprite_t sprite_index, bool triggered_only, bool civil_war,
bool constructing, bool crisis, bool great_war_obligatory, bool mutual, bool all_allowed_states,
- bool always, WargoalType::peace_modifiers_t&& modifiers, peace_options_t peace_options,
+ bool always, WargoalType::peace_modifiers_t&& modifiers, WargoalType::peace_options_t peace_options,
ConditionScript&& can_use, ConditionScript&& is_valid, ConditionScript&& allowed_states,
ConditionScript&& allowed_substate_regions, ConditionScript&& allowed_states_in_crisis,
ConditionScript&& allowed_countries, EffectScript&& on_add, EffectScript&& on_po_accepted
@@ -75,14 +75,14 @@ bool WargoalTypeManager::load_wargoal_file(ast::NodeCPtr root) {
return true;
}
- using enum peace_options_t;
+ using enum WargoalType::peace_options_t;
std::string_view war_name;
Timespan available {}, truce {};
WargoalType::sprite_t sprite_index = 0;
bool triggered_only = false, civil_war = false, constructing = true, crisis = true, great_war_obligatory = false,
mutual = false, all_allowed_states = false, always = false;
- peace_options_t peace_options = NO_PEACE_OPTIONS;
+ WargoalType::peace_options_t peace_options = NO_PEACE_OPTIONS;
WargoalType::peace_modifiers_t modifiers;
ConditionScript can_use { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::COUNTRY };
ConditionScript is_valid { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::COUNTRY };
@@ -92,7 +92,7 @@ bool WargoalTypeManager::load_wargoal_file(ast::NodeCPtr root) {
ConditionScript allowed_countries { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::COUNTRY };
EffectScript on_add, on_po_accepted; //country as default scope for both
- const auto expect_peace_option = [&peace_options](peace_options_t peace_option) -> node_callback_t {
+ const auto expect_peace_option = [&peace_options](WargoalType::peace_options_t peace_option) -> node_callback_t {
return expect_bool([&peace_options, peace_option](bool val) -> bool {
if (val) {
peace_options |= peace_option;
diff --git a/src/openvic-simulation/military/Wargoal.hpp b/src/openvic-simulation/military/Wargoal.hpp
index a4f2e7c..d9d51f6 100644
--- a/src/openvic-simulation/military/Wargoal.hpp
+++ b/src/openvic-simulation/military/Wargoal.hpp
@@ -1,6 +1,5 @@
#pragma once
-#include "openvic-simulation/misc/Modifier.hpp"
#include "openvic-simulation/scripts/ConditionScript.hpp"
#include "openvic-simulation/scripts/EffectScript.hpp"
#include "openvic-simulation/types/EnumBitfield.hpp"
@@ -10,35 +9,12 @@
namespace OpenVic {
struct WargoalTypeManager;
- enum class peace_options_t : uint32_t {
- NO_PEACE_OPTIONS = 0,
- PO_ANNEX = 1 << 0,
- PO_DEMAND_STATE = 1 << 1,
- PO_COLONY = 1 << 2,
- PO_ADD_TO_SPHERE = 1 << 3,
- PO_DISARMAMENT = 1 << 4,
- PO_REMOVE_FORTS = 1 << 5,
- PO_REMOVE_NAVAL_BASES = 1 << 6,
- PO_REPARATIONS = 1 << 7,
- PO_REPAY_DEBT = 1 << 8,
- PO_REMOVE_PRESTIGE = 1 << 9,
- PO_MAKE_PUPPET = 1 << 10,
- PO_RELEASE_PUPPET = 1 << 11,
- PO_STATUS_QUO = 1 << 12,
- PO_INSTALL_COMMUNISM = 1 << 13,
- PO_REMOVE_COMMUNISM = 1 << 14,
- PO_REMOVE_CORES = 1 << 15, // only usable with ANNEX, DEMAND_STATE, or TRANSFER_PROVINCES
- PO_TRANSFER_PROVINCES = 1 << 16,
- PO_CLEAR_UNION_SPHERE = 1 << 17
- };
- template<> struct enable_bitfield<peace_options_t> : std::true_type{};
-
struct WargoalType : HasIdentifier {
friend struct WargoalTypeManager;
using sprite_t = uint8_t;
- enum class PEACE_MODIFIERS {
+ enum class PEACE_MODIFIERS : uint8_t {
BADBOY_FACTOR,
PRESTIGE_FACTOR,
PEACE_COST_FACTOR,
@@ -54,6 +30,28 @@ namespace OpenVic {
};
using peace_modifiers_t = fixed_point_map_t<PEACE_MODIFIERS>;
+ enum class peace_options_t : uint32_t {
+ NO_PEACE_OPTIONS = 0,
+ PO_ANNEX = 1 << 0,
+ PO_DEMAND_STATE = 1 << 1,
+ PO_COLONY = 1 << 2,
+ PO_ADD_TO_SPHERE = 1 << 3,
+ PO_DISARMAMENT = 1 << 4,
+ PO_REMOVE_FORTS = 1 << 5,
+ PO_REMOVE_NAVAL_BASES = 1 << 6,
+ PO_REPARATIONS = 1 << 7,
+ PO_REPAY_DEBT = 1 << 8,
+ PO_REMOVE_PRESTIGE = 1 << 9,
+ PO_MAKE_PUPPET = 1 << 10,
+ PO_RELEASE_PUPPET = 1 << 11,
+ PO_STATUS_QUO = 1 << 12,
+ PO_INSTALL_COMMUNISM = 1 << 13,
+ PO_REMOVE_COMMUNISM = 1 << 14,
+ PO_REMOVE_CORES = 1 << 15, // only usable with ANNEX, DEMAND_STATE, or TRANSFER_PROVINCES
+ PO_TRANSFER_PROVINCES = 1 << 16,
+ PO_CLEAR_UNION_SPHERE = 1 << 17
+ };
+
private:
std::string PROPERTY(war_name);
const Timespan PROPERTY(available_length);
@@ -94,6 +92,8 @@ namespace OpenVic {
WargoalType(WargoalType&&) = default;
};
+ template<> struct enable_bitfield<WargoalType::peace_options_t> : std::true_type{};
+
struct WargoalTypeManager {
private:
IdentifierRegistry<WargoalType> IDENTIFIER_REGISTRY(wargoal_type);
@@ -104,7 +104,7 @@ namespace OpenVic {
std::string_view identifier, std::string_view war_name, Timespan available_length,
Timespan truce_length, WargoalType::sprite_t sprite_index, bool triggered_only, bool civil_war,
bool constructing, bool crisis, bool great_war_obligatory, bool mutual, bool all_allowed_states,
- bool always, WargoalType::peace_modifiers_t&& modifiers, peace_options_t peace_options,
+ bool always, WargoalType::peace_modifiers_t&& modifiers, WargoalType::peace_options_t peace_options,
ConditionScript&& can_use, ConditionScript&& is_valid, ConditionScript&& allowed_states,
ConditionScript&& allowed_substate_regions, ConditionScript&& allowed_states_in_crisis,
ConditionScript&& allowed_countries, EffectScript&& on_add, EffectScript&& on_po_accepted
diff --git a/src/openvic-simulation/misc/Event.cpp b/src/openvic-simulation/misc/Event.cpp
index d6750c1..1796799 100644
--- a/src/openvic-simulation/misc/Event.cpp
+++ b/src/openvic-simulation/misc/Event.cpp
@@ -169,7 +169,7 @@ bool EventManager::load_event_file(IssueManager const& issue_manager, ast::NodeC
};
bool ret = expect_dictionary_keys_and_default(
- key_value_success_callback,
+ key_value_success_callback, /* Option effects, passed to the EffectScript below */
"name", ONE_EXACTLY, expect_identifier_or_string(assign_variable_callback(name)),
"ai_chance", ZERO_OR_ONE, ai_chance.expect_conditional_weight(ConditionalWeight::FACTOR)
)(node);
diff --git a/src/openvic-simulation/misc/Modifier.cpp b/src/openvic-simulation/misc/Modifier.cpp
index 6f6deda..e73d0e3 100644
--- a/src/openvic-simulation/misc/Modifier.cpp
+++ b/src/openvic-simulation/misc/Modifier.cpp
@@ -366,10 +366,10 @@ bool ModifierManager::parse_scripts(GameManager const& game_manager) {
key_value_callback_t ModifierManager::_modifier_effect_callback(
ModifierValue& modifier, key_value_callback_t default_callback, ModifierEffectValidator auto effect_validator
) const {
- const auto add_modifier_cb = [this, &modifier,
- effect_validator](ModifierEffect const* effect, ast::NodeCPtr value) -> bool {
+ const auto add_modifier_cb = [this, &modifier, effect_validator](
+ ModifierEffect const* effect, ast::NodeCPtr value
+ ) -> bool {
if (effect_validator(*effect)) {
-
static const case_insensitive_string_set_t no_effect_modifiers {
"boost_strongest_party", "poor_savings_modifier", "local_artisan_input", "local_artisan_throughput",
"local_artisan_output", "artisan_input", "artisan_throughput", "artisan_output",
@@ -385,8 +385,9 @@ key_value_callback_t ModifierManager::_modifier_effect_callback(
}
};
- const auto add_flattened_modifier_cb =
- [this, add_modifier_cb](std::string_view prefix, std::string_view key, ast::NodeCPtr value) -> bool {
+ const auto add_flattened_modifier_cb = [this, add_modifier_cb](
+ std::string_view prefix, std::string_view key, ast::NodeCPtr value
+ ) -> bool {
const std::string flat_identifier = get_flat_identifier(prefix, key);
ModifierEffect const* effect = get_modifier_effect_by_identifier(flat_identifier);
if (effect != nullptr) {
@@ -397,7 +398,9 @@ key_value_callback_t ModifierManager::_modifier_effect_callback(
}
};
- return [this, default_callback, add_modifier_cb, add_flattened_modifier_cb](std::string_view key, ast::NodeCPtr value) -> bool {
+ return [this, default_callback, add_modifier_cb, add_flattened_modifier_cb](
+ std::string_view key, ast::NodeCPtr value
+ ) -> bool {
ModifierEffect const* effect = get_modifier_effect_by_identifier(key);
if (effect != nullptr && value->is_type<ast::IdentifierNode>()) {
return add_modifier_cb(effect, value);
@@ -437,6 +440,7 @@ node_callback_t ModifierManager::expect_validated_modifier_value_and_default(
return ret;
};
}
+
node_callback_t ModifierManager::expect_validated_modifier_value(
callback_t<ModifierValue&&> modifier_callback, ModifierEffectValidator auto effect_validator
) const {
diff --git a/src/openvic-simulation/politics/Rebel.cpp b/src/openvic-simulation/politics/Rebel.cpp
index 4bf5ecb..2f39bee 100644
--- a/src/openvic-simulation/politics/Rebel.cpp
+++ b/src/openvic-simulation/politics/Rebel.cpp
@@ -4,7 +4,6 @@
#include "openvic-simulation/misc/Modifier.hpp"
-
using namespace OpenVic;
using namespace OpenVic::NodeTools;
diff --git a/src/openvic-simulation/pop/Culture.cpp b/src/openvic-simulation/pop/Culture.cpp
index 2cd6005..53273f5 100644
--- a/src/openvic-simulation/pop/Culture.cpp
+++ b/src/openvic-simulation/pop/Culture.cpp
@@ -1,5 +1,6 @@
#include "Culture.hpp"
+#include "openvic-simulation/country/Country.hpp"
#include "openvic-simulation/dataloader/NodeTools.hpp"
#include "openvic-simulation/types/Colour.hpp"
@@ -10,15 +11,16 @@ GraphicalCultureType::GraphicalCultureType(std::string_view new_identifier) : Ha
CultureGroup::CultureGroup(
std::string_view new_identifier, std::string_view new_leader, GraphicalCultureType const& new_unit_graphical_culture_type,
- bool new_is_overseas
+ bool new_is_overseas, Country const* new_union_country
) : HasIdentifier { new_identifier }, leader { new_leader }, unit_graphical_culture_type { new_unit_graphical_culture_type },
- is_overseas { new_is_overseas } {}
+ is_overseas { new_is_overseas }, union_country { new_union_country } {}
Culture::Culture(
- std::string_view new_identifier, colour_t new_colour, CultureGroup const& new_group,
- name_list_t&& new_first_names, name_list_t&& new_last_names
+ std::string_view new_identifier, colour_t new_colour, CultureGroup const& new_group, name_list_t&& new_first_names,
+ name_list_t&& new_last_names, fixed_point_t new_radicalism, Country const* new_primary_country
) : HasIdentifierAndColour { new_identifier, new_colour, false }, group { new_group },
- first_names { std::move(new_first_names) }, last_names { std::move(new_last_names) } {}
+ first_names { std::move(new_first_names) }, last_names { std::move(new_last_names) }, radicalism { new_radicalism },
+ primary_country { new_primary_country } {}
bool CultureManager::add_graphical_culture_type(std::string_view identifier) {
if (identifier.empty()) {
@@ -29,7 +31,8 @@ bool CultureManager::add_graphical_culture_type(std::string_view identifier) {
}
bool CultureManager::add_culture_group(
- std::string_view identifier, std::string_view leader, GraphicalCultureType const* graphical_culture_type, bool is_overseas
+ std::string_view identifier, std::string_view leader, GraphicalCultureType const* graphical_culture_type, bool is_overseas,
+ Country const* union_country
) {
if (!graphical_culture_types.is_locked()) {
Logger::error("Cannot register culture groups until graphical culture types are locked!");
@@ -47,12 +50,12 @@ bool CultureManager::add_culture_group(
Logger::error("Null graphical culture type for ", identifier);
return false;
}
- return culture_groups.add_item({ identifier, leader, *graphical_culture_type, is_overseas });
+ return culture_groups.add_item({ identifier, leader, *graphical_culture_type, is_overseas, union_country });
}
bool CultureManager::add_culture(
std::string_view identifier, colour_t colour, CultureGroup const& group, name_list_t&& first_names,
- name_list_t&& last_names
+ name_list_t&& last_names, fixed_point_t radicalism, Country const* primary_country
) {
if (!culture_groups.is_locked()) {
Logger::error("Cannot register cultures until culture groups are locked!");
@@ -62,7 +65,12 @@ bool CultureManager::add_culture(
Logger::error("Invalid culture identifier - empty!");
return false;
}
- return cultures.add_item({ identifier, colour, group, std::move(first_names), std::move(last_names) });
+
+ // TODO - check radicalism range
+
+ return cultures.add_item({
+ identifier, colour, group, std::move(first_names), std::move(last_names), radicalism, primary_country
+ });
}
bool CultureManager::load_graphical_culture_type_file(ast::NodeCPtr root) {
@@ -74,41 +82,46 @@ bool CultureManager::load_graphical_culture_type_file(ast::NodeCPtr root) {
}
bool CultureManager::_load_culture_group(
- size_t& total_expected_cultures, GraphicalCultureType const* default_unit_graphical_culture_type,
- std::string_view culture_group_key, ast::NodeCPtr culture_group_node
+ CountryManager const& country_manager, size_t& total_expected_cultures,
+ GraphicalCultureType const* default_unit_graphical_culture_type, std::string_view culture_group_key,
+ ast::NodeCPtr culture_group_node
) {
-
- std::string_view leader;
+ std::string_view leader {};
GraphicalCultureType const* unit_graphical_culture_type = default_unit_graphical_culture_type;
bool is_overseas = true;
+ Country const* union_country = nullptr;
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_graphical_culture_type_identifier(assign_variable_callback_pointer(unit_graphical_culture_type)),
- "union", ZERO_OR_ONE, success_callback,
+ "union", ZERO_OR_ONE, country_manager.expect_country_identifier(assign_variable_callback_pointer(union_country)),
"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);
+ ret &= add_culture_group(culture_group_key, leader, unit_graphical_culture_type, is_overseas, union_country);
return ret;
}
bool CultureManager::_load_culture(
- CultureGroup const& culture_group, std::string_view culture_key, ast::NodeCPtr culture_node
+ CountryManager const& country_manager, CultureGroup const& culture_group, std::string_view culture_key,
+ ast::NodeCPtr culture_node
) {
-
colour_t colour = colour_t::null();
- name_list_t first_names, last_names;
+ name_list_t first_names {}, last_names {};
+ fixed_point_t radicalism = 0;
+ Country const* primary_country = nullptr;
bool ret = expect_dictionary_keys(
"color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)),
"first_names", ONE_EXACTLY, name_list_callback(move_variable_callback(first_names)),
"last_names", ONE_EXACTLY, name_list_callback(move_variable_callback(last_names)),
- "radicalism", ZERO_OR_ONE, success_callback,
- "primary", ZERO_OR_ONE, success_callback
+ "radicalism", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(radicalism)),
+ "primary", ZERO_OR_ONE, country_manager.expect_country_identifier(assign_variable_callback_pointer(primary_country))
)(culture_node);
- ret &= add_culture(culture_key, colour, culture_group, std::move(first_names), std::move(last_names));
+ ret &= add_culture(
+ culture_key, colour, culture_group, std::move(first_names), std::move(last_names), radicalism, primary_country
+ );
return ret;
}
@@ -132,7 +145,7 @@ bool CultureManager::_load_culture(
* POP-267, POP-268, POP-269, POP-270, POP-271, POP-272, POP-273, POP-274, POP-275, POP-276, POP-277, POP-278, POP-279,
* POP-280, POP-281, POP-282, POP-283, POP-284
*/
-bool CultureManager::load_culture_file(ast::NodeCPtr root) {
+bool CultureManager::load_culture_file(CountryManager const& country_manager, ast::NodeCPtr root) {
if (!graphical_culture_types.is_locked()) {
Logger::error("Cannot load culture groups until graphical culture types are locked!");
return false;
@@ -147,23 +160,30 @@ bool CultureManager::load_culture_file(ast::NodeCPtr root) {
size_t total_expected_cultures = 0;
bool ret = expect_dictionary_reserve_length(culture_groups,
- [this, default_unit_graphical_culture_type, &total_expected_cultures](
- std::string_view key, ast::NodeCPtr value) -> bool {
- return _load_culture_group(total_expected_cultures, default_unit_graphical_culture_type, key, value);
+ [this, &country_manager, default_unit_graphical_culture_type, &total_expected_cultures](
+ std::string_view key, ast::NodeCPtr value
+ ) -> bool {
+ return _load_culture_group(
+ country_manager, total_expected_cultures, default_unit_graphical_culture_type, key, value
+ );
}
)(root);
lock_culture_groups();
cultures.reserve(cultures.size() + total_expected_cultures);
- ret &= expect_culture_group_dictionary([this](CultureGroup const& culture_group, ast::NodeCPtr culture_group_value) -> bool {
- return expect_dictionary([this, &culture_group](std::string_view key, ast::NodeCPtr value) -> bool {
- static const string_set_t reserved_keys = { "leader", "unit", "union", "is_overseas" };
- if (reserved_keys.contains(key)) {
- return true;
- }
- return _load_culture(culture_group, key, value);
- })(culture_group_value);
- })(root);
+ ret &= expect_culture_group_dictionary(
+ [this, &country_manager](CultureGroup const& culture_group, ast::NodeCPtr culture_group_value) -> bool {
+ return expect_dictionary(
+ [this, &country_manager, &culture_group](std::string_view key, ast::NodeCPtr value) -> bool {
+ static const string_set_t reserved_keys = { "leader", "unit", "union", "is_overseas" };
+ if (reserved_keys.contains(key)) {
+ return true;
+ }
+ return _load_culture(country_manager, culture_group, key, value);
+ }
+ )(culture_group_value);
+ }
+ )(root);
lock_cultures();
return ret;
}
diff --git a/src/openvic-simulation/pop/Culture.hpp b/src/openvic-simulation/pop/Culture.hpp
index c8dfe7a..8807123 100644
--- a/src/openvic-simulation/pop/Culture.hpp
+++ b/src/openvic-simulation/pop/Culture.hpp
@@ -5,6 +5,8 @@
namespace OpenVic {
struct CultureManager;
+ struct Country;
+ struct CountryManager;
struct GraphicalCultureType : HasIdentifier {
friend struct CultureManager;
@@ -20,15 +22,14 @@ namespace OpenVic {
friend struct CultureManager;
private:
- const std::string PROPERTY(leader);
+ std::string PROPERTY(leader);
GraphicalCultureType const& PROPERTY(unit_graphical_culture_type);
- const bool PROPERTY(is_overseas);
-
- // TODO - union tag
+ bool PROPERTY(is_overseas);
+ Country const* PROPERTY(union_country);
CultureGroup(
std::string_view new_identifier, std::string_view new_leader,
- GraphicalCultureType const& new_unit_graphical_culture_type, bool new_is_overseas
+ GraphicalCultureType const& new_unit_graphical_culture_type, bool new_is_overseas, Country const* new_union_country
);
public:
@@ -40,14 +41,14 @@ namespace OpenVic {
private:
CultureGroup const& PROPERTY(group);
- const name_list_t PROPERTY(first_names);
- const name_list_t PROPERTY(last_names);
-
- // TODO - radicalism, primary tag
+ name_list_t PROPERTY(first_names);
+ name_list_t PROPERTY(last_names);
+ fixed_point_t PROPERTY(radicalism);
+ Country const* PROPERTY(primary_country);
Culture(
- std::string_view new_identifier, colour_t new_colour, CultureGroup const& new_group,
- name_list_t&& new_first_names, name_list_t&& new_last_names
+ std::string_view new_identifier, colour_t new_colour, CultureGroup const& new_group, name_list_t&& new_first_names,
+ name_list_t&& new_last_names, fixed_point_t new_radicalism, Country const* new_primary_country
);
public:
@@ -61,25 +62,29 @@ namespace OpenVic {
IdentifierRegistry<Culture> IDENTIFIER_REGISTRY(culture);
bool _load_culture_group(
- size_t& total_expected_cultures, GraphicalCultureType const* default_unit_graphical_culture_type,
- std::string_view culture_group_key, ast::NodeCPtr culture_group_node
+ CountryManager const& country_manager, size_t& total_expected_cultures,
+ GraphicalCultureType const* default_unit_graphical_culture_type, std::string_view culture_group_key,
+ ast::NodeCPtr culture_group_node
+ );
+ bool _load_culture(
+ CountryManager const& country_manager, CultureGroup const& culture_group, std::string_view culture_key,
+ ast::NodeCPtr node
);
- bool _load_culture(CultureGroup const& culture_group, std::string_view culture_key, ast::NodeCPtr node);
public:
bool add_graphical_culture_type(std::string_view identifier);
bool add_culture_group(
std::string_view identifier, std::string_view leader, GraphicalCultureType const* graphical_culture_type,
- bool is_overseas
+ bool is_overseas, Country const* union_country
);
bool add_culture(
std::string_view identifier, colour_t colour, CultureGroup const& group, name_list_t&& first_names,
- name_list_t&& last_names
+ name_list_t&& last_names, fixed_point_t radicalism, Country const* primary_country
);
bool load_graphical_culture_type_file(ast::NodeCPtr root);
- bool load_culture_file(ast::NodeCPtr root);
+ bool load_culture_file(CountryManager const& country_manager, ast::NodeCPtr root);
};
}
diff --git a/src/openvic-simulation/pop/Pop.cpp b/src/openvic-simulation/pop/Pop.cpp
index 5afcb18..d422038 100644
--- a/src/openvic-simulation/pop/Pop.cpp
+++ b/src/openvic-simulation/pop/Pop.cpp
@@ -1,5 +1,6 @@
#include "Pop.hpp"
+#include "openvic-simulation/military/Unit.hpp"
#include "openvic-simulation/politics/Ideology.hpp"
#include "openvic-simulation/politics/Issue.hpp"
#include "openvic-simulation/politics/Rebel.hpp"
@@ -8,12 +9,28 @@
using namespace OpenVic;
using namespace OpenVic::NodeTools;
+using enum PopType::income_type_t;
+
Pop::Pop(
- PopType const& new_type, Culture const& new_culture, Religion const& new_religion, pop_size_t new_size,
- fixed_point_t new_militancy, fixed_point_t new_consciousness, RebelType const* new_rebel_type
-) : type { new_type }, culture { new_culture }, religion { new_religion }, size { new_size }, num_grown { 0 },
- num_promoted { 0 }, num_demoted { 0 }, num_migrated_internal { 0 }, num_migrated_external { 0 },
- num_migrated_colonial { 0 }, militancy { new_militancy }, consciousness { new_consciousness },
+ PopType const& new_type,
+ Culture const& new_culture,
+ Religion const& new_religion,
+ pop_size_t new_size,
+ fixed_point_t new_militancy,
+ fixed_point_t new_consciousness,
+ RebelType const* new_rebel_type
+) : type { new_type },
+ culture { new_culture },
+ religion { new_religion },
+ size { new_size },
+ num_grown { 0 },
+ num_promoted { 0 },
+ num_demoted { 0 },
+ num_migrated_internal { 0 },
+ num_migrated_external { 0 },
+ num_migrated_colonial { 0 },
+ militancy { new_militancy },
+ consciousness { new_consciousness },
rebel_type { new_rebel_type } {
assert(size > 0);
}
@@ -21,25 +38,75 @@ Pop::Pop(
Strata::Strata(std::string_view new_identifier) : HasIdentifier { new_identifier } {}
PopType::PopType(
- std::string_view new_identifier, colour_t new_colour, Strata const& new_strata, sprite_t new_sprite,
- Good::good_map_t&& new_life_needs, Good::good_map_t&& new_everyday_needs, Good::good_map_t&& new_luxury_needs,
- rebel_units_t&& new_rebel_units, Pop::pop_size_t new_max_size, Pop::pop_size_t new_merge_max_size,
- bool new_state_capital_only, bool new_demote_migrant, bool new_is_artisan, bool new_allowed_to_vote, bool new_is_slave,
- bool new_can_be_recruited, bool new_can_reduce_consciousness, bool new_administrative_efficiency, bool new_can_build,
- bool new_factory, bool new_can_work_factory, bool new_unemployment, ConditionalWeight&& new_country_migration_target,
- ConditionalWeight&& new_migration_target, poptype_weight_map_t&& new_promote_to, ideology_weight_map_t&& new_ideologies,
+ std::string_view new_identifier,
+ colour_t new_colour,
+ Strata const& new_strata,
+ sprite_t new_sprite,
+ Good::good_map_t&& new_life_needs,
+ Good::good_map_t&& new_everyday_needs,
+ Good::good_map_t&& new_luxury_needs,
+ income_type_t new_life_needs_income_types,
+ income_type_t new_everyday_needs_income_types,
+ income_type_t new_luxury_needs_income_types,
+ rebel_units_t&& new_rebel_units,
+ Pop::pop_size_t new_max_size,
+ Pop::pop_size_t new_merge_max_size,
+ bool new_state_capital_only,
+ bool new_demote_migrant,
+ bool new_is_artisan,
+ bool new_allowed_to_vote,
+ bool new_is_slave,
+ bool new_can_be_recruited,
+ bool new_can_reduce_consciousness,
+ bool new_administrative_efficiency,
+ bool new_can_invest,
+ bool new_factory,
+ bool new_can_work_factory,
+ bool new_unemployment,
+ fixed_point_t new_research_points,
+ fixed_point_t new_leadership_points,
+ fixed_point_t new_research_leadership_optimum,
+ fixed_point_t new_state_administration_multiplier,
+ PopType const* new_equivalent,
+ ConditionalWeight&& new_country_migration_target,
+ ConditionalWeight&& new_migration_target,
+ poptype_weight_map_t&& new_promote_to,
+ ideology_weight_map_t&& new_ideologies,
issue_weight_map_t&& new_issues
-) : HasIdentifierAndColour { new_identifier, new_colour, false }, strata { new_strata }, sprite { new_sprite },
- life_needs { std::move(new_life_needs) }, everyday_needs { std::move(new_everyday_needs) },
- luxury_needs { std::move(new_luxury_needs) }, rebel_units { std::move(new_rebel_units) }, max_size { new_max_size },
- merge_max_size { new_merge_max_size }, state_capital_only { new_state_capital_only },
- demote_migrant { new_demote_migrant }, is_artisan { new_is_artisan }, allowed_to_vote { new_allowed_to_vote },
- is_slave { new_is_slave }, can_be_recruited { new_can_be_recruited },
- can_reduce_consciousness { new_can_reduce_consciousness }, administrative_efficiency { new_administrative_efficiency },
- can_build { new_can_build }, factory { new_factory }, can_work_factory { new_can_work_factory },
- unemployment { new_unemployment }, country_migration_target { std::move(new_country_migration_target) },
- migration_target { std::move(new_migration_target) }, promote_to { std::move(new_promote_to) },
- ideologies { std::move(new_ideologies) }, issues { std::move(new_issues) } {
+) : HasIdentifierAndColour { new_identifier, new_colour, false },
+ strata { new_strata },
+ sprite { new_sprite },
+ life_needs { std::move(new_life_needs) },
+ everyday_needs { std::move(new_everyday_needs) },
+ luxury_needs { std::move(new_luxury_needs) },
+ life_needs_income_types { std::move(new_life_needs_income_types) },
+ everyday_needs_income_types { std::move(new_everyday_needs_income_types) },
+ luxury_needs_income_types { std::move(new_luxury_needs_income_types) },
+ rebel_units { std::move(new_rebel_units) },
+ max_size { new_max_size },
+ merge_max_size { new_merge_max_size },
+ state_capital_only { new_state_capital_only },
+ demote_migrant { new_demote_migrant },
+ is_artisan { new_is_artisan },
+ allowed_to_vote { new_allowed_to_vote },
+ is_slave { new_is_slave },
+ can_be_recruited { new_can_be_recruited },
+ can_reduce_consciousness { new_can_reduce_consciousness },
+ administrative_efficiency { new_administrative_efficiency },
+ can_invest { new_can_invest },
+ factory { new_factory },
+ can_work_factory { new_can_work_factory },
+ unemployment { new_unemployment },
+ research_points { new_research_points },
+ leadership_points { new_leadership_points },
+ research_leadership_optimum { new_research_leadership_optimum },
+ state_administration_multiplier { new_state_administration_multiplier },
+ equivalent { new_equivalent },
+ country_migration_target { std::move(new_country_migration_target) },
+ migration_target { std::move(new_migration_target) },
+ promote_to { std::move(new_promote_to) },
+ ideologies { std::move(new_ideologies) },
+ issues { std::move(new_issues) } {
assert(sprite > 0);
assert(max_size >= 0);
assert(merge_max_size >= 0);
@@ -80,13 +147,41 @@ bool PopManager::add_strata(std::string_view identifier) {
}
bool PopManager::add_pop_type(
- std::string_view identifier, colour_t colour, Strata const* strata, PopType::sprite_t sprite,
- Good::good_map_t&& life_needs, Good::good_map_t&& everyday_needs, Good::good_map_t&& luxury_needs,
- PopType::rebel_units_t&& rebel_units, Pop::pop_size_t max_size, Pop::pop_size_t merge_max_size, bool state_capital_only,
- bool demote_migrant, bool is_artisan, bool allowed_to_vote, bool is_slave, bool can_be_recruited,
- bool can_reduce_consciousness, bool administrative_efficiency, bool can_build, bool factory, bool can_work_factory,
- bool unemployment, ConditionalWeight&& country_migration_target, ConditionalWeight&& migration_target,
- ast::NodeCPtr promote_to_node, PopType::ideology_weight_map_t&& ideologies, ast::NodeCPtr issues_node
+ std::string_view identifier,
+ colour_t colour,
+ Strata const* strata,
+ PopType::sprite_t sprite,
+ Good::good_map_t&& life_needs,
+ Good::good_map_t&& everyday_needs,
+ Good::good_map_t&& luxury_needs,
+ PopType::income_type_t life_needs_income_types,
+ PopType::income_type_t everyday_needs_income_types,
+ PopType::income_type_t luxury_needs_income_types,
+ PopType::rebel_units_t&& rebel_units,
+ Pop::pop_size_t max_size,
+ Pop::pop_size_t merge_max_size,
+ bool state_capital_only,
+ bool demote_migrant,
+ bool is_artisan,
+ bool allowed_to_vote,
+ bool is_slave,
+ bool can_be_recruited,
+ bool can_reduce_consciousness,
+ bool administrative_efficiency,
+ bool can_invest,
+ bool factory,
+ bool can_work_factory,
+ bool unemployment,
+ fixed_point_t research_points,
+ fixed_point_t leadership_points,
+ fixed_point_t research_leadership_optimum,
+ fixed_point_t state_administration_multiplier,
+ ast::NodeCPtr equivalent,
+ ConditionalWeight&& country_migration_target,
+ ConditionalWeight&& migration_target,
+ ast::NodeCPtr promote_to_node,
+ PopType::ideology_weight_map_t&& ideologies,
+ ast::NodeCPtr issues_node
) {
if (identifier.empty()) {
Logger::error("Invalid pop type identifier - empty!");
@@ -97,27 +192,76 @@ bool PopManager::add_pop_type(
return false;
}
if (sprite <= 0) {
- Logger::error("Invalid pop type sprite index for ", identifier, ": ", sprite);
+ Logger::error("Invalid pop type sprite index for ", identifier, ": ", sprite, " (must be positive)");
+ return false;
+ }
+ if (max_size <= 0) {
+ Logger::error("Invalid pop type max size for ", identifier, ": ", max_size, " (must be positive)");
return false;
}
- if (max_size < 0) {
- Logger::error("Invalid pop type max size for ", identifier, ": ", max_size);
+ if (merge_max_size <= 0) {
+ Logger::error("Invalid pop type merge max size for ", identifier, ": ", merge_max_size, " (must be positive)");
return false;
}
- if (merge_max_size < 0) {
- Logger::error("Invalid pop type merge max size for ", identifier, ": ", merge_max_size);
+
+ if (research_leadership_optimum < 0) {
+ Logger::error(
+ "Invalid pop type research/leadership optimum for ", identifier, ": ", research_leadership_optimum,
+ " (cannot be negative)"
+ );
return false;
}
+ if ((research_points != 0 || leadership_points != 0) != (research_leadership_optimum > 0)) {
+ Logger::error(
+ "Invalid pop type research/leadership points and optimum for ", identifier, ": research = ", research_points,
+ ", leadership = ", leadership_points, ", optimum = ", research_leadership_optimum,
+ " (optimum is positive if and only if at least one of research and leadership is non-zero)"
+ );
+ return false;
+ }
+
const bool ret = pop_types.add_item({
- identifier, colour, *strata, sprite, std::move(life_needs), std::move(everyday_needs),
- std::move(luxury_needs), std::move(rebel_units), max_size, merge_max_size, state_capital_only,
- demote_migrant, is_artisan, allowed_to_vote, is_slave, can_be_recruited, can_reduce_consciousness,
- administrative_efficiency, can_build, factory, can_work_factory, unemployment, std::move(country_migration_target),
- std::move(migration_target), {}, std::move(ideologies), {}
+ identifier,
+ colour,
+ *strata,
+ sprite,
+ std::move(life_needs),
+ std::move(everyday_needs),
+ std::move(luxury_needs),
+ life_needs_income_types,
+ everyday_needs_income_types,
+ luxury_needs_income_types,
+ std::move(rebel_units),
+ max_size,
+ merge_max_size,
+ state_capital_only,
+ demote_migrant,
+ is_artisan,
+ allowed_to_vote,
+ is_slave,
+ can_be_recruited,
+ can_reduce_consciousness,
+ administrative_efficiency,
+ can_invest,
+ factory,
+ can_work_factory,
+ unemployment,
+ research_points,
+ leadership_points,
+ research_leadership_optimum,
+ state_administration_multiplier,
+ nullptr,
+ std::move(country_migration_target),
+ std::move(migration_target),
+ {},
+ std::move(ideologies),
+ {}
});
+
if (ret) {
- delayed_parse_promote_to_and_issues_nodes.emplace_back(promote_to_node, issues_node);
+ delayed_parse_nodes.emplace_back(equivalent, promote_to_node, issues_node);
}
+
if (slave_sprite <= 0 && ret && is_slave) {
/* Set slave sprite to that of the first is_slave pop type we find. */
slave_sprite = sprite;
@@ -132,6 +276,29 @@ bool PopManager::add_pop_type(
void PopManager::reserve_pop_types(size_t count) {
stratas.reserve(stratas.size() + count);
pop_types.reserve(pop_types.size() + count);
+ delayed_parse_nodes.reserve(delayed_parse_nodes.size() + count);
+}
+
+static NodeCallback auto expect_needs_income(PopType::income_type_t& types) {
+ static const string_map_t<PopType::income_type_t> income_type_map {
+ { "administration", ADMINISTRATION },
+ { "education", EDUCATION },
+ { "military", MILITARY },
+ { "reforms", REFORMS }
+ };
+ return expect_dictionary_keys(
+ "type", ONE_OR_MORE, expect_identifier(expect_mapped_string(income_type_map,
+ [&types](PopType::income_type_t type) -> bool {
+ if (!share_income_type(types, type)) {
+ types |= type;
+ return true;
+ }
+ Logger::error("Duplicate income type ", type, " in pop type income types!");
+ return false;
+ }
+ )),
+ "weight", ZERO_OR_ONE, success_callback /* Has no effect in game */
+ );
}
/* REQUIREMENTS:
@@ -145,11 +312,16 @@ bool PopManager::load_pop_type_file(
Strata const* strata = nullptr;
PopType::sprite_t sprite = 0;
Good::good_map_t life_needs, everyday_needs, luxury_needs;
+ PopType::income_type_t life_needs_income_types = NO_INCOME_TYPE, everyday_needs_income_types = NO_INCOME_TYPE,
+ luxury_needs_income_types = NO_INCOME_TYPE;
PopType::rebel_units_t rebel_units;
+ Pop::pop_size_t max_size = Pop::MAX_SIZE, merge_max_size = Pop::MAX_SIZE;
bool state_capital_only = false, demote_migrant = false, is_artisan = false, allowed_to_vote = true, is_slave = false,
- can_be_recruited = false, can_reduce_consciousness = false, administrative_efficiency = false, can_build = false,
+ can_be_recruited = false, can_reduce_consciousness = false, administrative_efficiency = false, can_invest = false,
factory = false, can_work_factory = false, unemployment = false;
- Pop::pop_size_t max_size = 0, merge_max_size = 0;
+ fixed_point_t research_points = 0, leadership_points = 0, research_leadership_optimum = 0,
+ state_administration_multiplier = 0;
+ ast::NodeCPtr equivalent = nullptr;
ConditionalWeight country_migration_target { scope_t::COUNTRY, scope_t::POP, scope_t::NO_SCOPE };
ConditionalWeight migration_target { scope_t::PROVINCE, scope_t::POP, scope_t::NO_SCOPE };
ast::NodeCPtr promote_to_node = nullptr;
@@ -176,18 +348,18 @@ bool PopManager::load_pop_type_file(
}
),
"state_capital_only", ZERO_OR_ONE, expect_bool(assign_variable_callback(state_capital_only)),
- "research_points", ZERO_OR_ONE, success_callback, // TODO - research points generation
- "research_optimum", ZERO_OR_ONE, success_callback, // TODO - bonus research points generation
+ "research_points", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(research_points)),
+ "research_optimum", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(research_leadership_optimum)),
"rebel", ZERO_OR_ONE, unit_manager.expect_unit_decimal_map(move_variable_callback(rebel_units)),
- "equivalent", ZERO_OR_ONE, success_callback, // TODO - worker convertability
- "leadership", ZERO_OR_ONE, success_callback, // TODO - leadership points generation
+ "equivalent", ZERO_OR_ONE, assign_variable_callback(equivalent),
+ "leadership", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(leadership_points)),
"allowed_to_vote", ZERO_OR_ONE, expect_bool(assign_variable_callback(allowed_to_vote)),
"is_slave", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_slave)),
"can_be_recruited", ZERO_OR_ONE, expect_bool(assign_variable_callback(can_be_recruited)),
"can_reduce_consciousness", ZERO_OR_ONE, expect_bool(assign_variable_callback(can_reduce_consciousness)),
- "life_needs_income", ZERO_OR_ONE, success_callback, // TODO - incomes from national budget
- "everyday_needs_income", ZERO_OR_ONE, success_callback,
- "luxury_needs_income", ZERO_OR_ONE, success_callback,
+ "life_needs_income", ZERO_OR_ONE, expect_needs_income(life_needs_income_types),
+ "everyday_needs_income", ZERO_OR_ONE, expect_needs_income(everyday_needs_income_types),
+ "luxury_needs_income", ZERO_OR_ONE, expect_needs_income(luxury_needs_income_types),
"luxury_needs", ZERO_OR_ONE, good_manager.expect_good_decimal_map(move_variable_callback(luxury_needs)),
"everyday_needs", ZERO_OR_ONE, good_manager.expect_good_decimal_map(move_variable_callback(everyday_needs)),
"life_needs", ZERO_OR_ONE, good_manager.expect_good_decimal_map(move_variable_callback(life_needs)),
@@ -206,9 +378,9 @@ bool PopManager::load_pop_type_file(
"issues", ZERO_OR_ONE, assign_variable_callback(issues_node),
"demote_migrant", ZERO_OR_ONE, expect_bool(assign_variable_callback(demote_migrant)),
"administrative_efficiency", ZERO_OR_ONE, expect_bool(assign_variable_callback(administrative_efficiency)),
- "tax_eff", ZERO_OR_ONE, success_callback, // TODO - tax collection modifier
- "can_build", ZERO_OR_ONE, expect_bool(assign_variable_callback(can_build)),
- "factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(factory)),
+ "tax_eff", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(state_administration_multiplier)),
+ "can_build", ZERO_OR_ONE, expect_bool(assign_variable_callback(can_invest)),
+ "factory", ZERO_OR_ONE, expect_bool(assign_variable_callback(factory)), // TODO - work out what this does
"workplace_input", ZERO_OR_ONE, success_callback, // TODO - work out what these do
"workplace_output", ZERO_OR_ONE, success_callback,
"starter_share", ZERO_OR_ONE, success_callback,
@@ -217,10 +389,40 @@ bool PopManager::load_pop_type_file(
)(root);
ret &= add_pop_type(
- filestem, colour, strata, sprite, std::move(life_needs), std::move(everyday_needs), std::move(luxury_needs),
- std::move(rebel_units), max_size, merge_max_size, state_capital_only, demote_migrant, is_artisan, allowed_to_vote,
- is_slave, can_be_recruited, can_reduce_consciousness, administrative_efficiency, can_build, factory, can_work_factory,
- unemployment, std::move(country_migration_target), std::move(migration_target), promote_to_node, std::move(ideologies),
+ filestem,
+ colour,
+ strata,
+ sprite,
+ std::move(life_needs),
+ std::move(everyday_needs),
+ std::move(luxury_needs),
+ life_needs_income_types,
+ everyday_needs_income_types,
+ luxury_needs_income_types,
+ std::move(rebel_units),
+ max_size,
+ merge_max_size,
+ state_capital_only,
+ demote_migrant,
+ is_artisan,
+ allowed_to_vote,
+ is_slave,
+ can_be_recruited,
+ can_reduce_consciousness,
+ administrative_efficiency,
+ can_invest,
+ factory,
+ can_work_factory,
+ unemployment,
+ research_points,
+ leadership_points,
+ research_leadership_optimum,
+ state_administration_multiplier,
+ equivalent,
+ std::move(country_migration_target),
+ std::move(migration_target),
+ promote_to_node,
+ std::move(ideologies),
issues_node
);
return ret;
@@ -228,9 +430,15 @@ bool PopManager::load_pop_type_file(
bool PopManager::load_delayed_parse_pop_type_data(IssueManager const& issue_manager) {
bool ret = true;
- 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];
+ for (size_t index = 0; index < delayed_parse_nodes.size(); ++index) {
+ const auto [equivalent, promote_to_node, issues_node] = delayed_parse_nodes[index];
PopType* pop_type = pop_types.get_item_by_index(index);
+ if (equivalent != nullptr && !expect_pop_type_identifier(
+ assign_variable_callback_pointer(pop_type->equivalent)
+ )(equivalent)) {
+ Logger::error("Errors parsing equivalent pop type for pop type ", pop_type, "!");
+ ret = false;
+ }
if (promote_to_node != nullptr && !expect_pop_type_dictionary_reserve_length(
pop_type->promote_to,
[pop_type](PopType const& type, ast::NodeCPtr node) -> bool {
@@ -244,7 +452,7 @@ bool PopManager::load_delayed_parse_pop_type_data(IssueManager const& issue_mana
return ret;
}
)(promote_to_node)) {
- Logger::error("Errors parsing pop type ", pop_type, " promotion weights!");
+ Logger::error("Errors parsing promotion weights for pop type ", pop_type, "!");
ret = false;
}
if (issues_node != nullptr && !expect_dictionary_reserve_length(
@@ -264,11 +472,11 @@ bool PopManager::load_delayed_parse_pop_type_data(IssueManager const& issue_mana
return ret;
}
)(issues_node)) {
- Logger::error("Errors parsing pop type ", pop_type, " issue weights!");
+ Logger::error("Errors parsing issue weights for pop type ", pop_type, "!");
ret = false;
}
}
- delayed_parse_promote_to_and_issues_nodes.clear();
+ delayed_parse_nodes.clear();
return ret;
}
diff --git a/src/openvic-simulation/pop/Pop.hpp b/src/openvic-simulation/pop/Pop.hpp
index ffef6ea..5a4cebf 100644
--- a/src/openvic-simulation/pop/Pop.hpp
+++ b/src/openvic-simulation/pop/Pop.hpp
@@ -1,16 +1,21 @@
#pragma once
+#include <limits>
+#include <ostream>
+
#include "openvic-simulation/economy/Good.hpp"
-#include "openvic-simulation/military/Unit.hpp"
#include "openvic-simulation/pop/Culture.hpp"
#include "openvic-simulation/pop/Religion.hpp"
#include "openvic-simulation/scripts/ConditionalWeight.hpp"
+#include "openvic-simulation/types/EnumBitfield.hpp"
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
namespace OpenVic {
struct PopManager;
struct PopType;
+ struct Unit;
+ struct UnitManager;
struct RebelType;
struct RebelManager;
struct Ideology;
@@ -26,6 +31,8 @@ namespace OpenVic {
using pop_size_t = int64_t;
+ static constexpr pop_size_t MAX_SIZE = std::numeric_limits<pop_size_t>::max();
+
private:
PopType const& PROPERTY(type);
Culture const& PROPERTY(culture);
@@ -46,8 +53,13 @@ namespace OpenVic {
RebelType const* PROPERTY(rebel_type);
Pop(
- PopType const& new_type, Culture const& new_culture, Religion const& new_religion, pop_size_t new_size,
- fixed_point_t new_militancy, fixed_point_t new_consciousness, RebelType const* new_rebel_type
+ PopType const& new_type,
+ Culture const& new_culture,
+ Religion const& new_religion,
+ pop_size_t new_size,
+ fixed_point_t new_militancy,
+ fixed_point_t new_consciousness,
+ RebelType const* new_rebel_type
);
public:
@@ -73,6 +85,16 @@ namespace OpenVic {
struct PopType : HasIdentifierAndColour {
friend struct PopManager;
+ /* This is a bitfield - PopTypes can have up to one of each income source for each need category. */
+ enum struct income_type_t : uint8_t {
+ NO_INCOME_TYPE = 0,
+ ADMINISTRATION = 1 << 0,
+ EDUCATION = 1 << 1,
+ MILITARY = 1 << 2,
+ REFORMS = 1 << 3,
+ MAX_INCOME_TYPE = (1 << 4) - 1
+ };
+
using sprite_t = uint8_t;
using rebel_units_t = fixed_point_map_t<Unit const*>;
using poptype_weight_map_t = ordered_map<PopType const*, ConditionalWeight>;
@@ -85,6 +107,9 @@ namespace OpenVic {
Good::good_map_t PROPERTY(life_needs);
Good::good_map_t PROPERTY(everyday_needs);
Good::good_map_t PROPERTY(luxury_needs);
+ income_type_t PROPERTY(life_needs_income_types);
+ income_type_t PROPERTY(everyday_needs_income_types);
+ income_type_t PROPERTY(luxury_needs_income_types);
rebel_units_t PROPERTY(rebel_units);
const Pop::pop_size_t PROPERTY(max_size);
const Pop::pop_size_t PROPERTY(merge_max_size);
@@ -96,10 +121,15 @@ namespace OpenVic {
const bool PROPERTY(can_be_recruited);
const bool PROPERTY(can_reduce_consciousness);
const bool PROPERTY(administrative_efficiency);
- const bool PROPERTY(can_build);
+ const bool PROPERTY(can_invest);
const bool PROPERTY(factory);
const bool PROPERTY(can_work_factory);
const bool PROPERTY(unemployment);
+ const fixed_point_t PROPERTY(research_points);
+ const fixed_point_t PROPERTY(leadership_points);
+ const fixed_point_t PROPERTY(research_leadership_optimum);
+ const fixed_point_t PROPERTY(state_administration_multiplier);
+ PopType const* PROPERTY(equivalent);
ConditionalWeight PROPERTY(country_migration_target); /* Scope - country, THIS - pop */
ConditionalWeight PROPERTY(migration_target); /* Scope - province, THIS - pop */
@@ -108,14 +138,41 @@ namespace OpenVic {
issue_weight_map_t PROPERTY(issues); /* Scope - province, THIS - country (?) */
PopType(
- std::string_view new_identifier, colour_t new_colour, Strata const& new_strata, sprite_t new_sprite,
- Good::good_map_t&& new_life_needs, Good::good_map_t&& new_everyday_needs, Good::good_map_t&& new_luxury_needs,
- rebel_units_t&& new_rebel_units, Pop::pop_size_t new_max_size, Pop::pop_size_t new_merge_max_size,
- bool new_state_capital_only, bool new_demote_migrant, bool new_is_artisan, bool new_allowed_to_vote,
- bool new_is_slave, bool new_can_be_recruited, bool new_can_reduce_consciousness,
- bool new_administrative_efficiency, bool new_can_build, bool new_factory, bool new_can_work_factory,
- bool new_unemployment, ConditionalWeight&& new_country_migration_target, ConditionalWeight&& new_migration_target,
- poptype_weight_map_t&& new_promote_to, ideology_weight_map_t&& new_ideologies, issue_weight_map_t&& new_issues
+ std::string_view new_identifier,
+ colour_t new_colour,
+ Strata const& new_strata,
+ sprite_t new_sprite,
+ Good::good_map_t&& new_life_needs,
+ Good::good_map_t&& new_everyday_needs,
+ Good::good_map_t&& new_luxury_needs,
+ income_type_t new_life_needs_income_types,
+ income_type_t new_everyday_needs_income_types,
+ income_type_t new_luxury_needs_income_types,
+ rebel_units_t&& new_rebel_units,
+ Pop::pop_size_t new_max_size,
+ Pop::pop_size_t new_merge_max_size,
+ bool new_state_capital_only,
+ bool new_demote_migrant,
+ bool new_is_artisan,
+ bool new_allowed_to_vote,
+ bool new_is_slave,
+ bool new_can_be_recruited,
+ bool new_can_reduce_consciousness,
+ bool new_administrative_efficiency,
+ bool new_can_invest,
+ bool new_factory,
+ bool new_can_work_factory,
+ bool new_unemployment,
+ fixed_point_t new_research_points,
+ fixed_point_t new_leadership_points,
+ fixed_point_t new_research_leadership_optimum,
+ fixed_point_t new_state_administration_multiplier,
+ PopType const* new_equivalent,
+ ConditionalWeight&& new_country_migration_target,
+ ConditionalWeight&& new_migration_target,
+ poptype_weight_map_t&& new_promote_to,
+ ideology_weight_map_t&& new_ideologies,
+ issue_weight_map_t&& new_issues
);
bool parse_scripts(GameManager const& game_manager);
@@ -124,6 +181,40 @@ namespace OpenVic {
PopType(PopType&&) = default;
};
+ template<> struct enable_bitfield<PopType::income_type_t> : std::true_type {};
+
+ /* This returns true if at least one income type is shared by both arguments. */
+ constexpr inline bool share_income_type(PopType::income_type_t lhs, PopType::income_type_t rhs) {
+ return (lhs & rhs) != PopType::income_type_t::NO_INCOME_TYPE;
+ }
+
+ inline std::ostream& operator<<(std::ostream& stream, PopType::income_type_t income_type) {
+ using enum PopType::income_type_t;
+ if (income_type == NO_INCOME_TYPE) {
+ return stream << "[NO_INCOME_TYPE]";
+ }
+ bool type_found = false;
+ stream << '[';
+#define BUILD_STRING(entry) \
+ if (share_income_type(income_type, entry)) { \
+ if (type_found) { \
+ stream << " | "; \
+ } else { \
+ type_found = true; \
+ } \
+ stream << #entry; \
+ }
+ BUILD_STRING(ADMINISTRATION);
+ BUILD_STRING(EDUCATION);
+ BUILD_STRING(MILITARY);
+ BUILD_STRING(REFORMS);
+#undef BUILD_STRING
+ if (!type_found) {
+ stream << "INVALID INCOME TYPE";
+ }
+ return stream << ']';
+ }
+
struct Province;
struct PopManager {
@@ -131,11 +222,12 @@ namespace OpenVic {
/* Using strata/stratas instead of stratum/strata to avoid confusion. */
IdentifierRegistry<Strata> IDENTIFIER_REGISTRY(strata);
IdentifierRegistry<PopType> IDENTIFIER_REGISTRY(pop_type);
- /* promote_to can't be parsed until after all PopTypes are registered, and issues requires Issues to be loaded,
- * which themselves depend on pop strata. To get around this, the nodes for these variables are stored here and
- * parsed after both PopTypes and Issues. The nodes will remain valid as PopType files' Parser objects are cached
- * to preserve their condition script nodes until all other defines are loaded and the scripts can be parsed. */
- std::vector<std::pair<ast::NodeCPtr, ast::NodeCPtr>> delayed_parse_promote_to_and_issues_nodes;
+ /* equivalent and promote_to can't be parsed until after all PopTypes are registered, and issues requires Issues
+ * to be loaded, which themselves depend on pop strata. To get around this, the nodes for these variables are stored
+ * here and parsed after both PopTypes and Issues. The nodes will remain valid as PopType files' Parser objects are
+ * cached to preserve their condition script nodes until all other defines are loaded and the scripts can be parsed.
+ * Entries contain: (equivalent, promote_to, issues) */
+ std::vector<std::tuple<ast::NodeCPtr, ast::NodeCPtr, ast::NodeCPtr>> delayed_parse_nodes;
ConditionalWeight PROPERTY(promotion_chance);
ConditionalWeight PROPERTY(demotion_chance);
@@ -157,13 +249,40 @@ namespace OpenVic {
bool add_strata(std::string_view identifier);
bool add_pop_type(
- std::string_view identifier, colour_t new_colour, Strata const* strata, PopType::sprite_t sprite,
- Good::good_map_t&& life_needs, Good::good_map_t&& everyday_needs, Good::good_map_t&& luxury_needs,
- PopType::rebel_units_t&& rebel_units, Pop::pop_size_t max_size, Pop::pop_size_t merge_max_size,
- bool state_capital_only, bool demote_migrant, bool is_artisan, bool allowed_to_vote, bool is_slave,
- bool can_be_recruited, bool can_reduce_consciousness, bool administrative_efficiency, bool can_build, bool factory,
- bool can_work_factory, bool unemployment, ConditionalWeight&& country_migration_target,
- ConditionalWeight&& migration_target, ast::NodeCPtr promote_to_node, PopType::ideology_weight_map_t&& ideologies,
+ std::string_view identifier,
+ colour_t new_colour,
+ Strata const* strata,
+ PopType::sprite_t sprite,
+ Good::good_map_t&& life_needs,
+ Good::good_map_t&& everyday_needs,
+ Good::good_map_t&& luxury_needs,
+ PopType::income_type_t life_needs_income_types,
+ PopType::income_type_t everyday_needs_income_types,
+ PopType::income_type_t luxury_needs_income_types,
+ PopType::rebel_units_t&& rebel_units,
+ Pop::pop_size_t max_size,
+ Pop::pop_size_t merge_max_size,
+ bool state_capital_only,
+ bool demote_migrant,
+ bool is_artisan,
+ bool allowed_to_vote,
+ bool is_slave,
+ bool can_be_recruited,
+ bool can_reduce_consciousness,
+ bool administrative_efficiency,
+ bool can_invest,
+ bool factory,
+ bool can_work_factory,
+ bool unemployment,
+ fixed_point_t research_points,
+ fixed_point_t leadership_points,
+ fixed_point_t research_leadership_optimum,
+ fixed_point_t state_administration_multiplier,
+ ast::NodeCPtr equivalent,
+ ConditionalWeight&& country_migration_target,
+ ConditionalWeight&& migration_target,
+ ast::NodeCPtr promote_to_node,
+ PopType::ideology_weight_map_t&& ideologies,
ast::NodeCPtr issues_node
);
diff --git a/src/openvic-simulation/research/Invention.cpp b/src/openvic-simulation/research/Invention.cpp
index 92bf059..792dcba 100644
--- a/src/openvic-simulation/research/Invention.cpp
+++ b/src/openvic-simulation/research/Invention.cpp
@@ -2,6 +2,7 @@
#include "openvic-simulation/economy/BuildingType.hpp"
#include "openvic-simulation/map/Crime.hpp"
+#include "openvic-simulation/military/Unit.hpp"
using namespace OpenVic;
using namespace OpenVic::NodeTools;
diff --git a/src/openvic-simulation/scripts/Condition.cpp b/src/openvic-simulation/scripts/Condition.cpp
index ce18824..045649b 100644
--- a/src/openvic-simulation/scripts/Condition.cpp
+++ b/src/openvic-simulation/scripts/Condition.cpp
@@ -6,6 +6,10 @@
using namespace OpenVic;
using namespace OpenVic::NodeTools;
+using enum value_type_t;
+using enum scope_t;
+using enum identifier_type_t;
+
Condition::Condition(
std::string_view new_identifier, value_type_t new_value_type, scope_t new_scope,
scope_t new_scope_change, identifier_type_t new_key_identifier_type,
@@ -30,23 +34,23 @@ bool ConditionManager::add_condition(
return false;
}
- if (value_type == value_type_t::NO_TYPE || value_type > value_type_t::MAX_VALUE) {
+ if (value_type == NO_TYPE || value_type > MAX_VALUE) {
Logger::error("Condition ", identifier, " has invalid value type: ", static_cast<uint64_t>(value_type));
return false;
}
- if (scope == scope_t::NO_SCOPE || scope > scope_t::MAX_SCOPE) {
+ if (scope == NO_SCOPE || scope > MAX_SCOPE) {
Logger::error("Condition ", identifier, " has invalid scope: ", static_cast<uint64_t>(scope));
return false;
}
- if (share_value_type(value_type, value_type_t::IDENTIFIER) && value_identifier_type == identifier_type_t::NONE) {
+ if (share_value_type(value_type, IDENTIFIER) && value_identifier_type == NO_IDENTIFIER) {
Logger::error("Condition ", identifier, " has no identifier type!");
return false;
}
// don't perform the check for complex types
- if (!share_value_type(value_type, value_type_t::COMPLEX)) {
- if (!share_value_type(value_type, value_type_t::IDENTIFIER) && value_identifier_type != identifier_type_t::NONE) {
+ if (!share_value_type(value_type, COMPLEX)) {
+ if (!share_value_type(value_type, IDENTIFIER) && value_identifier_type != NO_IDENTIFIER) {
Logger::warning("Condition ", identifier, " specified an identifier type, but doesn't have an identifier!");
}
}
@@ -64,10 +68,6 @@ bool ConditionManager::add_condition(
bool ConditionManager::setup_conditions(GameManager const& game_manager) {
bool ret = true;
- using enum value_type_t;
- using enum scope_t;
- using enum identifier_type_t;
-
/* Special Scopes */
ret &= add_condition("THIS", GROUP, COUNTRY, THIS);
ret &= add_condition("FROM", GROUP, COUNTRY, FROM);
@@ -109,7 +109,7 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
/* Global Conditions */
ret &= add_condition("year", INTEGER, COUNTRY);
ret &= add_condition("month", INTEGER, COUNTRY);
- ret &= add_condition("has_global_flag", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, GLOBAL_FLAG);
+ ret &= add_condition("has_global_flag", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, GLOBAL_FLAG);
ret &= add_condition("is_canal_enabled", INTEGER, COUNTRY);
ret &= add_condition("always", BOOLEAN, COUNTRY);
ret &= add_condition("world_wars_enabled", BOOLEAN, COUNTRY);
@@ -117,76 +117,76 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
/* Country Scope Conditions */
ret &= add_condition("administration_spending", REAL, COUNTRY);
ret &= add_condition("ai", BOOLEAN, COUNTRY);
- ret &= add_condition("alliance_with", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
+ ret &= add_condition("alliance_with", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
ret &= add_condition("average_consciousness", REAL, COUNTRY);
ret &= add_condition("average_militancy", REAL, COUNTRY);
ret &= add_condition("badboy", REAL, COUNTRY);
- ret &= add_condition("big_producer", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, TRADE_GOOD);
+ ret &= add_condition("big_producer", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, TRADE_GOOD);
ret &= add_condition("blockade", REAL, COUNTRY);
ret &= add_condition("brigades_compare", REAL, COUNTRY);
- ret &= add_condition("can_build_factory_in_capital_state", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, BUILDING);
+ ret &= add_condition("can_build_factory_in_capital_state", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, BUILDING);
ret &= add_condition("can_build_fort_in_capital", COMPLEX, COUNTRY);
ret &= add_condition("can_build_railway_in_capital", COMPLEX, COUNTRY);
ret &= add_condition("can_nationalize", BOOLEAN, COUNTRY);
ret &= add_condition("can_create_vassals", BOOLEAN, COUNTRY);
- ret &= add_condition("capital", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, PROVINCE_ID);
- ret &= add_condition("casus_belli", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("check_variable", COMPLEX, COUNTRY, NO_SCOPE, NONE, VARIABLE);
- ret &= add_condition("citizenship_policy", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, ISSUE);
+ ret &= add_condition("capital", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, PROVINCE_ID);
+ ret &= add_condition("casus_belli", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("check_variable", COMPLEX, COUNTRY, NO_SCOPE, NO_IDENTIFIER, VARIABLE);
+ ret &= add_condition("citizenship_policy", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, ISSUE);
ret &= add_condition("civilization_progress", REAL, COUNTRY);
ret &= add_condition("civilized", BOOLEAN, COUNTRY);
ret &= add_condition("colonial_nation", BOOLEAN, COUNTRY);
ret &= add_condition("consciousness", REAL, COUNTRY);
ret &= add_condition("constructing_cb_progress", REAL, COUNTRY);
- ret &= add_condition("constructing_cb_type", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, CASUS_BELLI);
- ret &= add_condition("continent", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, CONTINENT);
- ret &= add_condition("controls", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, PROVINCE_ID);
+ ret &= add_condition("constructing_cb_type", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, CASUS_BELLI);
+ ret &= add_condition("continent", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, CONTINENT);
+ ret &= add_condition("controls", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, PROVINCE_ID);
ret &= add_condition("crime_fighting", REAL, COUNTRY);
ret &= add_condition("crime_higher_than_education", BOOLEAN, COUNTRY);
ret &= add_condition("crisis_exist", BOOLEAN, COUNTRY);
- ret &= add_condition("culture", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, CULTURE);
+ ret &= add_condition("culture", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, CULTURE);
ret &= add_condition("culture_has_union_tag", BOOLEAN, COUNTRY);
ret &= add_condition("diplomatic_influence", COMPLEX, COUNTRY);
- ret &= add_condition("economic_policy", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, ISSUE);
+ ret &= add_condition("economic_policy", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, ISSUE);
ret &= add_condition("education_spending", REAL, COUNTRY);
ret &= add_condition("election", BOOLEAN, COUNTRY);
- ret &= add_condition("exists", IDENTIFIER | BOOLEAN, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("government", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, GOVERNMENT_TYPE);
+ ret &= add_condition("exists", IDENTIFIER | BOOLEAN, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("government", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, GOVERNMENT_TYPE);
ret &= add_condition("great_wars_enabled", BOOLEAN, COUNTRY);
- ret &= add_condition("have_core_in", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("has_country_flag", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_FLAG);
- ret &= add_condition("has_country_modifier", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, MODIFIER);
+ ret &= add_condition("have_core_in", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("has_country_flag", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_FLAG);
+ ret &= add_condition("has_country_modifier", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, MODIFIER);
ret &= add_condition("has_cultural_sphere", BOOLEAN, COUNTRY);
ret &= add_condition("has_leader", STRING, COUNTRY);
- ret &= add_condition("has_pop_culture", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, CULTURE);
- ret &= add_condition("has_pop_religion", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, RELIGION);
- ret &= add_condition("has_pop_type", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, POP_TYPE);
+ ret &= add_condition("has_pop_culture", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, CULTURE);
+ ret &= add_condition("has_pop_religion", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, RELIGION);
+ ret &= add_condition("has_pop_type", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, POP_TYPE);
ret &= add_condition("has_recently_lost_war", BOOLEAN, COUNTRY);
ret &= add_condition("has_unclaimed_cores", BOOLEAN, COUNTRY);
- ret &= add_condition("ideology", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, IDEOLOGY);
- ret &= add_condition("industrial_score", REAL | IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("in_sphere", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("in_default", IDENTIFIER | BOOLEAN, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("invention", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, INVENTION);
+ ret &= add_condition("ideology", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, IDEOLOGY);
+ ret &= add_condition("industrial_score", REAL | IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("in_sphere", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("in_default", IDENTIFIER | BOOLEAN, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("invention", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, INVENTION);
ret &= add_condition("involved_in_crisis", BOOLEAN, COUNTRY);
ret &= add_condition("is_claim_crisis", BOOLEAN, COUNTRY);
ret &= add_condition("is_colonial_crisis", BOOLEAN, COUNTRY);
- ret &= add_condition("is_cultural_union", IDENTIFIER | BOOLEAN, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
+ ret &= add_condition("is_cultural_union", IDENTIFIER | BOOLEAN, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
ret &= add_condition("is_disarmed", BOOLEAN, COUNTRY);
ret &= add_condition("is_greater_power", BOOLEAN, COUNTRY);
ret &= add_condition("is_colonial", BOOLEAN, STATE);
- ret &= add_condition("is_core", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG | PROVINCE_ID);
- ret &= add_condition("is_culture_group", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG | CULTURE_GROUP);
- ret &= add_condition("is_ideology_enabled", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, IDEOLOGY);
+ ret &= add_condition("is_core", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG | PROVINCE_ID);
+ ret &= add_condition("is_culture_group", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG | CULTURE_GROUP);
+ ret &= add_condition("is_ideology_enabled", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, IDEOLOGY);
ret &= add_condition("is_independant", BOOLEAN, COUNTRY); //paradox typo
ret &= add_condition("is_liberation_crisis", BOOLEAN, COUNTRY);
ret &= add_condition("is_mobilised", BOOLEAN, COUNTRY);
- ret &= add_condition("is_next_reform", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, REFORM);
- ret &= add_condition("is_our_vassal", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("is_possible_vassal", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("is_releasable_vassal", IDENTIFIER | BOOLEAN, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
+ ret &= add_condition("is_next_reform", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, REFORM);
+ ret &= add_condition("is_our_vassal", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("is_possible_vassal", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("is_releasable_vassal", IDENTIFIER | BOOLEAN, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
ret &= add_condition("is_secondary_power", BOOLEAN, COUNTRY);
- ret &= add_condition("is_sphere_leader_of", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
+ ret &= add_condition("is_sphere_leader_of", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
ret &= add_condition("is_substate", BOOLEAN, COUNTRY);
ret &= add_condition("is_vassal", BOOLEAN, COUNTRY);
ret &= add_condition("literacy", REAL, COUNTRY);
@@ -196,14 +196,14 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
ret &= add_condition("middle_strata_life_needs", REAL, COUNTRY);
ret &= add_condition("middle_strata_luxury_needs", REAL, COUNTRY);
ret &= add_condition("middle_tax", REAL, COUNTRY);
- ret &= add_condition("military_access", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("military_score", REAL | IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
+ ret &= add_condition("military_access", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("military_score", REAL | IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
ret &= add_condition("militancy", REAL, COUNTRY);
ret &= add_condition("military_spending", REAL, COUNTRY);
ret &= add_condition("money", REAL, COUNTRY);
- ret &= add_condition("nationalvalue", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, NATIONAL_VALUE);
+ ret &= add_condition("nationalvalue", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, NATIONAL_VALUE);
ret &= add_condition("national_provinces_occupied", REAL, COUNTRY);
- ret &= add_condition("neighbour", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
+ ret &= add_condition("neighbour", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
ret &= add_condition("num_of_allies", INTEGER, COUNTRY);
ret &= add_condition("num_of_cities", INTEGER, COUNTRY);
ret &= add_condition("num_of_ports", INTEGER, COUNTRY);
@@ -212,14 +212,14 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
ret &= add_condition("num_of_substates", INTEGER, COUNTRY);
ret &= add_condition("num_of_vassals", INTEGER, COUNTRY);
ret &= add_condition("num_of_vassals_no_substates", INTEGER, COUNTRY);
- ret &= add_condition("owns", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, PROVINCE_ID);
+ ret &= add_condition("owns", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, PROVINCE_ID);
ret &= add_condition("part_of_sphere", BOOLEAN, COUNTRY);
ret &= add_condition("plurality", REAL, COUNTRY);
ret &= add_condition("political_movement_strength", REAL, COUNTRY);
ret &= add_condition("political_reform_want", REAL, COUNTRY);
- ret &= add_condition("pop_majority_culture", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, CULTURE);
- ret &= add_condition("pop_majority_ideology", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, IDEOLOGY);
- ret &= add_condition("pop_majority_religion", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, RELIGION);
+ ret &= add_condition("pop_majority_culture", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, CULTURE);
+ ret &= add_condition("pop_majority_ideology", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, IDEOLOGY);
+ ret &= add_condition("pop_majority_religion", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, RELIGION);
ret &= add_condition("pop_militancy", REAL, COUNTRY);
ret &= add_condition("poor_strata_militancy", REAL, COUNTRY);
ret &= add_condition("poor_strata_everyday_needs", REAL, COUNTRY);
@@ -227,15 +227,15 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
ret &= add_condition("poor_strata_luxury_needs", REAL, COUNTRY);
ret &= add_condition("poor_tax", REAL, COUNTRY);
ret &= add_condition("prestige", REAL, COUNTRY);
- ret &= add_condition("primary_culture", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, CULTURE);
- ret &= add_condition("accepted_culture", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, CULTURE);
- ret &= add_condition("produces", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, TRADE_GOOD);
+ ret &= add_condition("primary_culture", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, CULTURE);
+ ret &= add_condition("accepted_culture", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, CULTURE);
+ ret &= add_condition("produces", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, TRADE_GOOD);
ret &= add_condition("rank", INTEGER, COUNTRY);
ret &= add_condition("rebel_power_fraction", REAL, COUNTRY);
ret &= add_condition("recruited_percentage", REAL, COUNTRY);
ret &= add_condition("relation", COMPLEX, COUNTRY);
- ret &= add_condition("religion", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, RELIGION);
- ret &= add_condition("religious_policy", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, ISSUE);
+ ret &= add_condition("religion", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, RELIGION);
+ ret &= add_condition("religious_policy", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, ISSUE);
ret &= add_condition("revanchism", REAL, COUNTRY);
ret &= add_condition("revolt_percentage", REAL, COUNTRY);
ret &= add_condition("rich_strata_militancy", REAL, COUNTRY);
@@ -244,16 +244,16 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
ret &= add_condition("rich_strata_luxury_needs", REAL, COUNTRY);
ret &= add_condition("rich_tax", REAL, COUNTRY);
ret &= add_condition("rich_tax_above_poor", BOOLEAN, COUNTRY);
- ret &= add_condition("ruling_party", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("ruling_party_ideology", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, IDEOLOGY);
+ ret &= add_condition("ruling_party", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("ruling_party_ideology", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, IDEOLOGY);
ret &= add_condition("social_movement_strength", REAL, COUNTRY);
ret &= add_condition("social_reform_want", REAL, COUNTRY);
ret &= add_condition("social_spending", REAL, COUNTRY);
- ret &= add_condition("stronger_army_than", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("substate_of", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("tag", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("tech_school", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, TECH_SCHOOL);
- ret &= add_condition("this_culture_union", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, CULTURE_UNION);
+ ret &= add_condition("stronger_army_than", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("substate_of", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("tag", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("tech_school", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, TECH_SCHOOL);
+ ret &= add_condition("this_culture_union", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, CULTURE_UNION);
ret &= add_condition("total_amount_of_divisions", INTEGER, COUNTRY);
ret &= add_condition("total_amount_of_ships", INTEGER, COUNTRY);
ret &= add_condition("total_defensives", INTEGER, COUNTRY);
@@ -262,62 +262,62 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
ret &= add_condition("total_pops", INTEGER, COUNTRY);
ret &= add_condition("total_sea_battles", INTEGER, COUNTRY);
ret &= add_condition("total_sunk_by_us", INTEGER, COUNTRY);
- ret &= add_condition("trade_policy", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, ISSUE);
+ ret &= add_condition("trade_policy", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, ISSUE);
ret &= add_condition("treasury", REAL, COUNTRY);
- ret &= add_condition("truce_with", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
+ ret &= add_condition("truce_with", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
ret &= add_condition("unemployment", REAL, COUNTRY);
ret &= add_condition("unit_has_leader", BOOLEAN, COUNTRY);
ret &= add_condition("unit_in_battle", BOOLEAN, COUNTRY);
ret &= add_condition("upper_house", COMPLEX, COUNTRY);
- ret &= add_condition("vassal_of", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
+ ret &= add_condition("vassal_of", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
ret &= add_condition("war", BOOLEAN, COUNTRY);
ret &= add_condition("war_exhaustion", REAL, COUNTRY);
- ret &= add_condition("war_policy", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, ISSUE);
+ ret &= add_condition("war_policy", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, ISSUE);
ret &= add_condition("war_score", REAL, COUNTRY);
- ret &= add_condition("war_with", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
+ ret &= add_condition("war_with", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
/* State Scope Conditions */
- ret &= add_condition("controlled_by", IDENTIFIER, STATE, NO_SCOPE, NONE, COUNTRY_TAG);
+ ret &= add_condition("controlled_by", IDENTIFIER, STATE, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
ret &= add_condition("empty", BOOLEAN, STATE);
ret &= add_condition("flashpoint_tension", REAL, STATE);
- ret &= add_condition("has_building", IDENTIFIER, STATE, NO_SCOPE, NONE, BUILDING);
+ ret &= add_condition("has_building", IDENTIFIER, STATE, NO_SCOPE, NO_IDENTIFIER, BUILDING);
ret &= add_condition("has_factories", BOOLEAN, STATE);
ret &= add_condition("has_flashpoint", BOOLEAN, STATE);
ret &= add_condition("is_slave", BOOLEAN, STATE);
- ret &= add_condition("owned_by", IDENTIFIER, STATE, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("trade_goods_in_state", IDENTIFIER, STATE, NO_SCOPE, NONE, TRADE_GOOD);
+ ret &= add_condition("owned_by", IDENTIFIER, STATE, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("trade_goods_in_state", IDENTIFIER, STATE, NO_SCOPE, NO_IDENTIFIER, TRADE_GOOD);
ret &= add_condition("work_available", COMPLEX, STATE);
/* Province Scope Conditions */
ret &= add_condition("can_build_factory", BOOLEAN, PROVINCE);
ret &= add_condition("controlled_by_rebels", BOOLEAN, PROVINCE);
- ret &= add_condition("country_units_in_province", IDENTIFIER, PROVINCE, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("country_units_in_state", IDENTIFIER, PROVINCE, NO_SCOPE, NONE, COUNTRY_TAG);
- ret &= add_condition("has_crime", IDENTIFIER, PROVINCE, NO_SCOPE, NONE, CRIME);
+ ret &= add_condition("country_units_in_province", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("country_units_in_state", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
+ ret &= add_condition("has_crime", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, CRIME);
ret &= add_condition("has_culture_core", BOOLEAN, PROVINCE);
ret &= add_condition("has_empty_adjacent_province", BOOLEAN, PROVINCE);
ret &= add_condition("has_empty_adjacent_state", BOOLEAN, PROVINCE);
ret &= add_condition("has_national_minority", BOOLEAN, PROVINCE);
- ret &= add_condition("has_province_flag", IDENTIFIER, PROVINCE, NO_SCOPE, NONE, PROVINCE_FLAG);
- ret &= add_condition("has_province_modifier", IDENTIFIER, PROVINCE, NO_SCOPE, NONE, MODIFIER);
+ ret &= add_condition("has_province_flag", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, PROVINCE_FLAG);
+ ret &= add_condition("has_province_modifier", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, MODIFIER);
ret &= add_condition("has_recent_imigration", INTEGER, PROVINCE); //paradox typo
ret &= add_condition("is_blockaded", BOOLEAN, PROVINCE);
- ret &= add_condition("is_accepted_culture", IDENTIFIER | BOOLEAN, PROVINCE, NO_SCOPE, NONE, COUNTRY_TAG);
+ ret &= add_condition("is_accepted_culture", IDENTIFIER | BOOLEAN, PROVINCE, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
ret &= add_condition("is_capital", BOOLEAN, PROVINCE);
ret &= add_condition("is_coastal", BOOLEAN, PROVINCE);
ret &= add_condition("is_overseas", BOOLEAN, PROVINCE);
- ret &= add_condition("is_primary_culture", IDENTIFIER | BOOLEAN, PROVINCE, NO_SCOPE, NONE, COUNTRY_TAG);
+ ret &= add_condition("is_primary_culture", IDENTIFIER | BOOLEAN, PROVINCE, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG);
ret &= add_condition("is_state_capital", BOOLEAN, PROVINCE);
ret &= add_condition("is_state_religion", BOOLEAN, PROVINCE);
ret &= add_condition("life_rating", REAL, PROVINCE);
ret &= add_condition("minorities", BOOLEAN, PROVINCE);
ret &= add_condition("port", BOOLEAN, PROVINCE);
ret &= add_condition("province_control_days", INTEGER, PROVINCE);
- ret &= add_condition("province_id", IDENTIFIER, PROVINCE, NO_SCOPE, NONE, PROVINCE_ID);
- ret &= add_condition("region", IDENTIFIER, PROVINCE, NO_SCOPE, NONE, REGION);
- ret &= add_condition("state_id", IDENTIFIER, PROVINCE, NO_SCOPE, NONE, PROVINCE_ID);
- ret &= add_condition("terrain", IDENTIFIER, PROVINCE, NO_SCOPE, NONE, TERRAIN);
- ret &= add_condition("trade_goods", IDENTIFIER, PROVINCE, NO_SCOPE, NONE, TRADE_GOOD);
+ ret &= add_condition("province_id", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, PROVINCE_ID);
+ ret &= add_condition("region", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, REGION);
+ ret &= add_condition("state_id", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, PROVINCE_ID);
+ ret &= add_condition("terrain", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, TERRAIN);
+ ret &= add_condition("trade_goods", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, TRADE_GOOD);
ret &= add_condition("unemployment_by_type", COMPLEX, PROVINCE);
ret &= add_condition("units_in_province", INTEGER, PROVINCE);
@@ -328,19 +328,19 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
ret &= add_condition("life_needs", REAL, POP);
ret &= add_condition("luxury_needs", REAL, POP);
ret &= add_condition("political_movement", BOOLEAN, POP);
- ret &= add_condition("pop_majority_issue", IDENTIFIER, POP, NO_SCOPE, NONE, ISSUE);
- ret &= add_condition("pop_type", IDENTIFIER, POP, NO_SCOPE, NONE, POP_TYPE);
+ ret &= add_condition("pop_majority_issue", IDENTIFIER, POP, NO_SCOPE, NO_IDENTIFIER, ISSUE);
+ ret &= add_condition("pop_type", IDENTIFIER, POP, NO_SCOPE, NO_IDENTIFIER, POP_TYPE);
ret &= add_condition("social_movement", BOOLEAN, POP);
- ret &= add_condition("strata", IDENTIFIER, POP, NO_SCOPE, NONE, POP_STRATA);
- ret &= add_condition("type", IDENTIFIER, POP, NO_SCOPE, NONE, POP_TYPE);
+ ret &= add_condition("strata", IDENTIFIER, POP, NO_SCOPE, NO_IDENTIFIER, POP_STRATA);
+ ret &= add_condition("type", IDENTIFIER, POP, NO_SCOPE, NO_IDENTIFIER, POP_TYPE);
const auto import_identifiers = [this, &ret](
std::vector<std::string_view> const& identifiers,
value_type_t value_type,
scope_t scope,
- scope_t scope_change = scope_t::NO_SCOPE,
- identifier_type_t key_identifier_type = identifier_type_t::NONE,
- identifier_type_t value_identifier_type = identifier_type_t::NONE
+ scope_t scope_change = NO_SCOPE,
+ identifier_type_t key_identifier_type = NO_IDENTIFIER,
+ identifier_type_t value_identifier_type = NO_IDENTIFIER
) -> void {
for (std::string_view const& identifier : identifiers) {
ret &= add_condition(
@@ -357,7 +357,7 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
COUNTRY,
COUNTRY,
COUNTRY_TAG,
- NONE
+ NO_IDENTIFIER
);
import_identifiers(
@@ -366,7 +366,7 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
COUNTRY,
STATE,
REGION,
- NONE
+ NO_IDENTIFIER
);
import_identifiers(
@@ -375,7 +375,7 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
COUNTRY,
PROVINCE,
PROVINCE_ID,
- NONE
+ NO_IDENTIFIER
);
/* Conditions from other registries */
@@ -385,7 +385,7 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
COUNTRY,
NO_SCOPE,
IDEOLOGY,
- NONE
+ NO_IDENTIFIER
);
import_identifiers(
@@ -403,7 +403,7 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
COUNTRY,
NO_SCOPE,
REFORM,
- NONE
+ NO_IDENTIFIER
);
import_identifiers(
@@ -412,7 +412,7 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
COUNTRY,
NO_SCOPE,
ISSUE,
- NONE
+ NO_IDENTIFIER
);
import_identifiers(
@@ -421,7 +421,7 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
COUNTRY,
NO_SCOPE,
POP_TYPE,
- NONE
+ NO_IDENTIFIER
);
import_identifiers(
@@ -430,7 +430,7 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
COUNTRY,
NO_SCOPE,
TECHNOLOGY,
- NONE
+ NO_IDENTIFIER
);
import_identifiers(
@@ -439,7 +439,7 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
COUNTRY,
NO_SCOPE,
TRADE_GOOD,
- NONE
+ NO_IDENTIFIER
);
lock_conditions();
@@ -459,7 +459,6 @@ callback_t<std::string_view> ConditionManager::expect_parse_identifier(
GameManager const& game_manager, identifier_type_t identifier_type,
callback_t<HasIdentifier const*> callback
) const {
- using enum identifier_type_t;
return [this, &game_manager, identifier_type, callback](std::string_view identifier) -> bool {
HasIdentifier const* identified = nullptr;
@@ -479,7 +478,7 @@ callback_t<std::string_view> ConditionManager::expect_parse_identifier(
//TODO: placeholder for not implemented stuff
#define EXPECT_CALL_PLACEHOLDER(type) \
- if (share_identifier_type(identifier_type, type)) return true;
+ if (share_identifier_type(identifier_type, type)) { return true; }
EXPECT_CALL_PLACEHOLDER(VARIABLE);
EXPECT_CALL_PLACEHOLDER(GLOBAL_FLAG);
@@ -524,7 +523,6 @@ node_callback_t ConditionManager::expect_condition_node(
GameManager const& game_manager, Condition const& condition, scope_t this_scope,
scope_t from_scope, scope_t cur_scope, callback_t<ConditionNode&&> callback
) const {
- using enum value_type_t;
return [this, &game_manager, &condition, callback, this_scope, from_scope, cur_scope](
ast::NodeCPtr node
) -> bool {
@@ -551,16 +549,14 @@ node_callback_t ConditionManager::expect_condition_node(
)(id);
if (log && !ret) {
Logger::error(
- "Invalid identifier ", id,
- " expected to have type ", get_identifier_type_string(item_type),
- " found during condition node parsing!"
+ "Invalid identifier ", id, " expected to have type ", item_type, " found during condition node parsing!"
);
}
return keyval;
};
if (!ret && share_value_type(value_type, IDENTIFIER)) {
- std::string_view value_identifier;
+ std::string_view value_identifier {};
ret |= expect_identifier_or_string(assign_variable_callback(value_identifier))(node);
if (ret) {
value = ConditionNode::string_t { value_identifier };
@@ -574,7 +570,7 @@ node_callback_t ConditionManager::expect_condition_node(
}
if (!ret && share_value_type(value_type, STRING)) {
- std::string_view value_identifier;
+ std::string_view value_identifier {};
bool local_ret = expect_identifier_or_string(
assign_variable_callback(value_identifier)
)(node);
@@ -595,43 +591,43 @@ node_callback_t ConditionManager::expect_condition_node(
//entries with magic syntax, thanks paradox!
if (!ret && share_value_type(value_type, COMPLEX)) {
- #define EXPECT_PAIR(key, value) \
- std::string_view key; \
- fixed_point_t real_##value; \
- ret |= expect_dictionary_keys( \
- #key, ONE_EXACTLY, expect_identifier_or_string(assign_variable_callback(key)), \
- #value, ONE_EXACTLY, expect_fixed_point(assign_variable_callback(real_##value)) \
- )(node); \
- if (ret) { \
- value = ConditionNode::identifier_real_t { key, real_##value }; \
+ const auto expect_pair = [&ret, &value, node](std::string_view identifier_key, std::string_view value_key) -> void {
+ std::string_view pair_identifier {};
+ fixed_point_t pair_value = 0;
+ ret |= expect_dictionary_keys(
+ identifier_key, ONE_EXACTLY, expect_identifier_or_string(assign_variable_callback(pair_identifier)),
+ value_key, ONE_EXACTLY, expect_fixed_point(assign_variable_callback(pair_value))
+ )(node);
+ if (ret) {
+ value = ConditionNode::identifier_real_t { pair_identifier, pair_value };
}
+ };
if (identifier == "can_build_railway_in_capital" || identifier == "can_build_fort_in_capital") {
bool in_whole_capital_state = false, limit_to_world_greatest_level = false;
ret |= expect_dictionary_keys(
"in_whole_capital_state", ONE_EXACTLY, expect_bool(assign_variable_callback(in_whole_capital_state)),
- "limit_to_world_greatest_level", ONE_EXACTLY, expect_bool(assign_variable_callback(limit_to_world_greatest_level))
+ "limit_to_world_greatest_level", ONE_EXACTLY,
+ expect_bool(assign_variable_callback(limit_to_world_greatest_level))
)(node);
if (ret) {
value = ConditionNode::double_boolean_t { in_whole_capital_state, limit_to_world_greatest_level };
}
} else if (identifier == "check_variable") {
- EXPECT_PAIR(which, value); // { which = [name of variable] value = x }
+ expect_pair("which", "value"); // { which = [name of variable] value = x }
} else if (identifier == "diplomatic_influence") {
- EXPECT_PAIR(who, value); // { who = [THIS/FROM/TAG] value = x }
+ expect_pair("who", "value"); // { who = [THIS/FROM/TAG] value = x }
} else if (identifier == "relation") {
- EXPECT_PAIR(who, value); // { who = [tag/this/from] value = x }
+ expect_pair("who", "value"); // { who = [tag/this/from] value = x }
} else if (identifier == "unemployment_by_type") {
- EXPECT_PAIR(type, value); // {type = [poptype] value = x }
+ expect_pair("type", "value"); // {type = [poptype] value = x }
} else if (identifier == "upper_house") {
- EXPECT_PAIR(ideology, value); // { ideology = name value = 0.x }
+ expect_pair("ideology", "value"); // { ideology = name value = 0.x }
} else if (identifier == "work_available") {
// { worker = [type] }
- std::string_view worker;
+ std::string_view worker {};
ret |= expect_dictionary_keys(
- "worker",
- ONE_EXACTLY,
- expect_identifier_or_string(assign_variable_callback(worker))
+ "worker", ONE_EXACTLY, expect_identifier_or_string(assign_variable_callback(worker))
)(node);
if (ret) {
value = ConditionNode::string_t { worker };
@@ -647,7 +643,7 @@ node_callback_t ConditionManager::expect_condition_node(
ConditionNode::condition_list_t node_list;
ret |= expect_condition_node_list(
game_manager, this_scope, from_scope,
- scope_change == scope_t::NO_SCOPE ? cur_scope : scope_change,
+ scope_change == NO_SCOPE ? cur_scope : scope_change,
false,
vector_callback(node_list)
)(node);
@@ -656,24 +652,23 @@ node_callback_t ConditionManager::expect_condition_node(
// scope validation
scope_t effective_current_scope = cur_scope;
- if (share_scope(effective_current_scope, scope_t::THIS)) {
+ if (share_scope(effective_current_scope, THIS)) {
effective_current_scope = this_scope;
- } else if (share_scope(effective_current_scope, scope_t::FROM)) {
+ } else if (share_scope(effective_current_scope, FROM)) {
effective_current_scope = from_scope;
}
if (!share_scope(scope, effective_current_scope) && effective_current_scope > scope) {
Logger::warning(
- "Condition or scope ", identifier, " was found in wrong scope ",
- get_scope_string(effective_current_scope), ", expected ",
- get_scope_string(scope), "!"
+ "Condition or scope ", identifier, " was found in wrong scope ", effective_current_scope, ", expected ",
+ scope, "!"
);
ret = false;
}
// key parsing
HasIdentifier const* key_item = nullptr;
- if (condition.key_identifier_type != identifier_type_t::NONE) {
+ if (condition.key_identifier_type != NO_IDENTIFIER) {
key_item = get_identifiable(key_identifier_type, identifier, true);
ret &= key_item != nullptr;
}
@@ -709,8 +704,6 @@ node_callback_t ConditionManager::expect_condition_node_list(
GameManager const& game_manager, scope_t this_scope, scope_t from_scope,
scope_t cur_scope, bool top_scope, callback_t<ConditionNode&&> callback
) const {
- using enum value_type_t;
- using enum scope_t;
return [this, &game_manager, callback, this_scope, from_scope, cur_scope, top_scope](ast::NodeCPtr node) -> bool {
const auto expect_node = [
this, &game_manager, callback, this_scope, from_scope, cur_scope
@@ -731,8 +724,8 @@ node_callback_t ConditionManager::expect_condition_node_list(
}
node_callback_t ConditionManager::expect_condition_script(
- GameManager const& game_manager, scope_t initial_scope, scope_t this_scope, scope_t from_scope,
- callback_t<ConditionNode&&> callback
+ GameManager const& game_manager, scope_t initial_scope, scope_t this_scope,
+ scope_t from_scope, callback_t<ConditionNode&&> callback
) const {
return [this, &game_manager, initial_scope, this_scope, from_scope, callback](ast::NodeCPtr node) -> bool {
diff --git a/src/openvic-simulation/scripts/Condition.hpp b/src/openvic-simulation/scripts/Condition.hpp
index 55fe8fc..e239142 100644
--- a/src/openvic-simulation/scripts/Condition.hpp
+++ b/src/openvic-simulation/scripts/Condition.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <ostream>
#include <string_view>
#include <variant>
@@ -23,7 +24,6 @@ namespace OpenVic {
GROUP = 1 << 7,
MAX_VALUE = (1 << 8) - 1
};
- template<> struct enable_bitfield<value_type_t> : std::true_type {};
// Order matters in this enum, for the fallback system to work
// smaller entities must have smaller integers associated!
@@ -37,10 +37,9 @@ namespace OpenVic {
FROM = 1 << 5,
MAX_SCOPE = (1 << 6) - 1
};
- template<> struct enable_bitfield<scope_t> : std::true_type {};
enum class identifier_type_t : uint32_t {
- NONE = 0,
+ NO_IDENTIFIER = 0,
VARIABLE = 1 << 0,
GLOBAL_FLAG = 1 << 1,
COUNTRY_FLAG = 1 << 2,
@@ -71,6 +70,10 @@ namespace OpenVic {
CRIME = 1 << 27,
TERRAIN = 1 << 28,
};
+
+ /* Allows enum types to be used with bitwise operators. */
+ template<> struct enable_bitfield<value_type_t> : std::true_type {};
+ template<> struct enable_bitfield<scope_t> : std::true_type {};
template<> struct enable_bitfield<identifier_type_t> : std::true_type {};
/* Returns true if the values have any bit in common. */
@@ -81,19 +84,28 @@ namespace OpenVic {
return (lhs & rhs) != scope_t::NO_SCOPE;
}
constexpr inline bool share_identifier_type(identifier_type_t lhs, identifier_type_t rhs) {
- return (lhs & rhs) != identifier_type_t::NONE;
+ return (lhs & rhs) != identifier_type_t::NO_IDENTIFIER;
}
-#define _BUILD_STRING(entry, share) if (share(value, entry)) { ret += #entry " | "; }
+#define _BUILD_STRING(entry, share) \
+ if (share(value, entry)) { \
+ if (type_found) { \
+ stream << " | "; \
+ } else { \
+ type_found = true; \
+ } \
+ stream << #entry; \
+ }
#define BUILD_STRING(entry) _BUILD_STRING(entry, share_value_type)
- inline std::string get_value_type_string(value_type_t value) {
+ inline std::ostream& operator<<(std::ostream& stream, value_type_t value) {
using enum value_type_t;
if (value == NO_TYPE) {
- return "[NO_TYPE]";
+ return stream << "[NO_TYPE]";
}
- std::string ret = {};
+ bool type_found = false;
+ stream << '[';
BUILD_STRING(IDENTIFIER);
BUILD_STRING(STRING);
BUILD_STRING(BOOLEAN);
@@ -102,36 +114,44 @@ namespace OpenVic {
BUILD_STRING(REAL);
BUILD_STRING(COMPLEX);
BUILD_STRING(GROUP);
- return "[" + ret.substr(0, ret.length() - 3) + "]";
+ if (!type_found) {
+ stream << "INVALID VALUE TYPE";
+ }
+ return stream << ']';
}
#undef BUILD_STRING
#define BUILD_STRING(entry) _BUILD_STRING(entry, share_scope)
- inline std::string get_scope_string(scope_t value) {
+ inline std::ostream& operator<<(std::ostream& stream, scope_t value) {
using enum scope_t;
if (value == NO_SCOPE) {
- return "[NO_SCOPE]";
+ return stream << "[NO_SCOPE]";
}
- std::string ret = {};
+ bool type_found = false;
+ stream << '[';
BUILD_STRING(COUNTRY);
BUILD_STRING(STATE);
BUILD_STRING(PROVINCE);
BUILD_STRING(POP);
BUILD_STRING(THIS);
BUILD_STRING(FROM);
- return "[" + ret.substr(0, ret.length() - 3) + "]";
+ if (!type_found) {
+ stream << "INVALID SCOPE";
+ }
+ return stream << ']';
}
#undef BUILD_STRING
#define BUILD_STRING(entry) _BUILD_STRING(entry, share_identifier_type)
- inline std::string get_identifier_type_string(identifier_type_t value) {
+ inline std::ostream& operator<<(std::ostream& stream, identifier_type_t value) {
using enum identifier_type_t;
- if (value == NONE) {
- return "[NONE]";
+ if (value == NO_IDENTIFIER) {
+ return stream << "[NO_IDENTIFIER]";
}
- std::string ret = {};
+ bool type_found = false;
+ stream << '[';
BUILD_STRING(VARIABLE);
BUILD_STRING(GLOBAL_FLAG);
BUILD_STRING(COUNTRY_FLAG);
@@ -161,7 +181,10 @@ namespace OpenVic {
BUILD_STRING(CONTINENT);
BUILD_STRING(CRIME);
BUILD_STRING(TERRAIN);
- return "[" + ret.substr(0, ret.length() - 3) + "]";
+ if (!type_found) {
+ stream << "INVALID IDENTIFIER TYPE";
+ }
+ return stream << ']';
}
#undef BUILD_STRING
@@ -224,8 +247,8 @@ namespace OpenVic {
bool add_condition(
std::string_view identifier, value_type_t value_type, scope_t scope,
scope_t scope_change = scope_t::NO_SCOPE,
- identifier_type_t key_identifier_type = identifier_type_t::NONE,
- identifier_type_t value_identifier_type = identifier_type_t::NONE
+ identifier_type_t key_identifier_type = identifier_type_t::NO_IDENTIFIER,
+ identifier_type_t value_identifier_type = identifier_type_t::NO_IDENTIFIER
);
NodeTools::callback_t<std::string_view> expect_parse_identifier(
diff --git a/src/openvic-simulation/types/Colour.hpp b/src/openvic-simulation/types/Colour.hpp
index 38c7b1e..06a6b36 100644
--- a/src/openvic-simulation/types/Colour.hpp
+++ b/src/openvic-simulation/types/Colour.hpp
@@ -147,15 +147,19 @@ namespace OpenVic {
static constexpr basic_colour_t from_integer(integer_type integer) {
if constexpr (colour_traits::has_alpha) {
- return { colour_traits::red_from_integer(integer), colour_traits::green_from_integer(integer),
- colour_traits::blue_from_integer(integer), colour_traits::alpha_from_integer(integer) };
+ return {
+ colour_traits::red_from_integer(integer), colour_traits::green_from_integer(integer),
+ colour_traits::blue_from_integer(integer), colour_traits::alpha_from_integer(integer)
+ };
} else {
assert(
colour_traits::alpha_from_integer(integer) == colour_traits::null ||
colour_traits::alpha_from_integer(integer) == max_value
);
- return { colour_traits::red_from_integer(integer), colour_traits::green_from_integer(integer),
- colour_traits::blue_from_integer(integer) };
+ return {
+ colour_traits::red_from_integer(integer), colour_traits::green_from_integer(integer),
+ colour_traits::blue_from_integer(integer)
+ };
}
}
@@ -163,8 +167,10 @@ namespace OpenVic {
from_floats(float r, float g, float b, float a = colour_traits::alpha_to_float(max_value))
requires(colour_traits::has_alpha)
{
- return { colour_traits::red_from_float(r), colour_traits::green_from_float(g), colour_traits::blue_from_float(b),
- colour_traits::alpha_from_float(a) };
+ return {
+ colour_traits::red_from_float(r), colour_traits::green_from_float(g), colour_traits::blue_from_float(b),
+ colour_traits::alpha_from_float(a)
+ };
}
static constexpr basic_colour_t from_floats(float r, float g, float b)
@@ -192,13 +198,19 @@ namespace OpenVic {
: red(r), green(g), blue(b) {}
template<typename _ColourTraits>
- requires(_ColourTraits::has_alpha && std::same_as<typename _ColourTraits::value_type, value_type> && std::same_as<typename _ColourTraits::integer_type, integer_type>)
+ requires(
+ _ColourTraits::has_alpha && std::same_as<typename _ColourTraits::value_type, value_type> &&
+ std::same_as<typename _ColourTraits::integer_type, integer_type>
+ )
explicit constexpr basic_colour_t(basic_colour_t<value_type, integer_type, _ColourTraits> const& colour)
requires(colour_traits::has_alpha)
: basic_colour_t { colour.red, colour.green, colour.blue, colour.alpha } {}
template<typename _ColourTraits>
- requires(!_ColourTraits::has_alpha && std::same_as<typename _ColourTraits::value_type, value_type> && std::same_as<typename _ColourTraits::integer_type, integer_type>)
+ requires(
+ !_ColourTraits::has_alpha && std::same_as<typename _ColourTraits::value_type, value_type> &&
+ std::same_as<typename _ColourTraits::integer_type, integer_type>
+ )
explicit constexpr basic_colour_t(
basic_colour_t<value_type, integer_type, _ColourTraits> const& colour, value_type a = max_value
)
@@ -206,7 +218,10 @@ namespace OpenVic {
: basic_colour_t { colour.red, colour.green, colour.blue, a } {}
template<typename _ColourTraits>
- requires(std::same_as<typename _ColourTraits::value_type, value_type> && std::same_as<typename _ColourTraits::integer_type, integer_type>)
+ requires(
+ std::same_as<typename _ColourTraits::value_type, value_type> &&
+ std::same_as<typename _ColourTraits::integer_type, integer_type>
+ )
explicit constexpr basic_colour_t(basic_colour_t<value_type, integer_type, _ColourTraits> const& colour)
requires(!colour_traits::has_alpha)
: basic_colour_t { colour.red, colour.green, colour.blue } {}
diff --git a/src/openvic-simulation/types/FunctionRef.hpp b/src/openvic-simulation/types/FunctionRef.hpp
index 1ca5bb7..88f6284 100644
--- a/src/openvic-simulation/types/FunctionRef.hpp
+++ b/src/openvic-simulation/types/FunctionRef.hpp
@@ -39,8 +39,8 @@ namespace OpenVic {
template<bool bNoExcept2, typename Func, typename Ret2, typename... Args2>
struct make_type_erased_function_ptr final {
type_erased_function_ptr<bNoExcept2, Ret2, Args2...> operator()() const& noexcept {
- return [](AnyRef anyref,
- Args2... args) noexcept(bNoExcept2) -> Ret2 { // implicit cast of stateless lambda to function pointer
+ // implicit cast of stateless lambda to function pointer
+ return [](AnyRef anyref, Args2... args) noexcept(bNoExcept2) -> Ret2 {
return std::invoke(
anyref.template get_ref<Func>(), std::forward<Args2>(args)...
); // MAYTHROW unless bNoExcept
@@ -51,8 +51,8 @@ namespace OpenVic {
template<bool bNoExcept2, typename Func, typename... Args2>
struct make_type_erased_function_ptr<bNoExcept2, Func, void, Args2...> final {
type_erased_function_ptr<bNoExcept2, void, Args2...> operator()() const& noexcept {
- return [](AnyRef anyref,
- Args2... args) noexcept(bNoExcept2) { // implicit cast of stateless lambda to function pointer
+ // implicit cast of stateless lambda to function pointer
+ return [](AnyRef anyref, Args2... args) noexcept(bNoExcept2) {
std::invoke(anyref.template get_ref<Func>(), std::forward<Args2>(args)...); // MAYTHROW unless bNoExcept
};
}
@@ -69,7 +69,6 @@ namespace OpenVic {
return m_pfuncTypeErased(m_anyref, std::forward<Args>(args)...); // MAYTHROW unless bNoExcept
}
-
template<typename Derived, typename Base>
struct decayed_derived_from : std::bool_constant<std::derived_from<typename std::decay<Derived>::type, Base>> {
static_assert(std::same_as<std::decay_t<Base>, Base>);
@@ -77,10 +76,10 @@ namespace OpenVic {
template<typename Func>
requires(!decayed_derived_from<Func, FunctionRefBase>::value) &&
- std::invocable<std::remove_reference_t<Func>&, Args...> &&
- (std::convertible_to<
- decltype(std::invoke(std::declval<std::remove_reference_t<Func>&>(), std::declval<Args>()...)), Ret> ||
- std::is_void<Ret>::value)
+ std::invocable<std::remove_reference_t<Func>&, Args...> &&
+ (std::convertible_to<
+ decltype(std::invoke(std::declval<std::remove_reference_t<Func>&>(), std::declval<Args>()...)), Ret
+ > || std::is_void<Ret>::value)
FunctionRefBase(Func&& func) noexcept
: m_pfuncTypeErased(make_type_erased_function_ptr<bNoExcept, std::remove_reference_t<Func>, Ret, Args...> {}()),
m_anyref(as_lvalue(func)) {
diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp
index bbaf52c..251632b 100644
--- a/src/openvic-simulation/types/IdentifierRegistry.hpp
+++ b/src/openvic-simulation/types/IdentifierRegistry.hpp
@@ -232,7 +232,7 @@ namespace OpenVic {
}
}
- constexpr static NodeTools::KeyValueCallback auto key_value_invalid_callback(std::string_view name) {
+ static constexpr 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;
@@ -258,13 +258,7 @@ namespace OpenVic {
if (item != nullptr) { \
return callback(*item); \
} \
- if (!warn) { \
- Logger::error("Invalid ", name, ": ", identifier); \
- return false; \
- } else { \
- Logger::warning("Invalid ", name, ": ", identifier); \
- return true; \
- } \
+ return NodeTools::warn_or_error(warn, "Invalid ", name, ": ", identifier); \
}; \
} \
constexpr NodeTools::NodeCallback auto expect_item_identifier( \
diff --git a/src/openvic-simulation/utility/Logger.hpp b/src/openvic-simulation/utility/Logger.hpp
index 20c7fdd..53decb3 100644
--- a/src/openvic-simulation/utility/Logger.hpp
+++ b/src/openvic-simulation/utility/Logger.hpp
@@ -72,6 +72,7 @@ namespace OpenVic {
struct log_channel_t {
log_func_t func;
log_queue_t queue;
+ size_t message_count;
};
template<typename... Ts>
@@ -90,6 +91,8 @@ namespace OpenVic {
do {
log_channel.func(std::move(log_channel.queue.front()));
log_channel.queue.pop();
+ /* Only count printed messages, so that message_count matches what is seen in the console. */
+ log_channel.message_count++;
} while (!log_channel.queue.empty());
}
}
@@ -103,6 +106,9 @@ public: \
static inline void set_##name##_func(log_func_t log_func) { \
name##_channel.func = log_func; \
} \
+ static inline size_t get_##name##_count() { \
+ return name##_channel.message_count; \
+ } \
template<typename... Ts> \
struct name { \
name(Ts&&... ts, source_location const& location = source_location::current()) { \
diff --git a/src/openvic-simulation/utility/StringUtils.hpp b/src/openvic-simulation/utility/StringUtils.hpp
index 1be818a..e83fbda 100644
--- a/src/openvic-simulation/utility/StringUtils.hpp
+++ b/src/openvic-simulation/utility/StringUtils.hpp
@@ -2,11 +2,11 @@
#include <algorithm>
#include <cctype>
-#include <cstdint>
#include <cstring>
#include <limits>
#include <string>
#include <string_view>
+#include <type_traits>
namespace OpenVic::StringUtils {
/* The constexpr function 'string_to_uint64' will convert a string into a uint64_t integer value.