aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/scripts/Condition.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation/scripts/Condition.cpp')
-rw-r--r--src/openvic-simulation/scripts/Condition.cpp753
1 files changed, 753 insertions, 0 deletions
diff --git a/src/openvic-simulation/scripts/Condition.cpp b/src/openvic-simulation/scripts/Condition.cpp
new file mode 100644
index 0000000..73b3606
--- /dev/null
+++ b/src/openvic-simulation/scripts/Condition.cpp
@@ -0,0 +1,753 @@
+#include "Condition.hpp"
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/GameManager.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+
+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,
+ identifier_type_t new_value_identifier_type
+) : HasIdentifier { new_identifier }, value_type { new_value_type }, scope { new_scope },
+ scope_change { new_scope_change }, key_identifier_type { new_key_identifier_type },
+ value_identifier_type { new_value_identifier_type } {}
+
+ConditionNode::ConditionNode(
+ Condition const* new_condition, value_t&& new_value, bool new_valid,
+ HasIdentifier const* new_condition_key_item,
+ HasIdentifier const* new_condition_value_item
+) : condition { new_condition }, value { std::move(new_value) }, valid { new_valid },
+ condition_key_item { new_condition_key_item }, condition_value_item { new_condition_key_item } {}
+
+bool ConditionManager::add_condition(
+ std::string_view identifier, value_type_t value_type, scope_t scope, scope_t scope_change,
+ identifier_type_t key_identifier_type, identifier_type_t value_identifier_type
+) {
+ if (identifier.empty()) {
+ Logger::error("Invalid condition identifier - empty!");
+ return false;
+ }
+
+ if (value_type == value_type_t::NO_TYPE || value_type > value_type_t::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) {
+ 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) {
+ 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) {
+ Logger::warning("Condition ", identifier, " specified an identifier type, but doesn't have an identifier!");
+ }
+ }
+
+ return conditions.add_item({
+ identifier,
+ value_type,
+ scope,
+ scope_change,
+ key_identifier_type,
+ value_identifier_type
+ });
+}
+
+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);
+ ret &= add_condition("independence", GROUP, COUNTRY, COUNTRY); //only from rebels!
+
+ /* Trigger Country Scopes */
+ ret &= add_condition("all_core", GROUP, COUNTRY, PROVINCE);
+ ret &= add_condition("any_core", GROUP, COUNTRY, PROVINCE);
+ ret &= add_condition("any_greater_power", GROUP, COUNTRY, COUNTRY);
+ ret &= add_condition("any_neighbor_country", GROUP, COUNTRY, COUNTRY);
+ ret &= add_condition("any_owned_province", GROUP, COUNTRY, PROVINCE);
+ ret &= add_condition("any_pop", GROUP, COUNTRY, POP);
+ ret &= add_condition("any_sphere_member", GROUP, COUNTRY, COUNTRY);
+ ret &= add_condition("any_state", GROUP, COUNTRY, STATE);
+ ret &= add_condition("any_substate", GROUP, COUNTRY, COUNTRY);
+ ret &= add_condition("capital_scope", GROUP, COUNTRY, PROVINCE);
+ ret &= add_condition("country", GROUP, COUNTRY, COUNTRY);
+ ret &= add_condition("cultural_union", GROUP, COUNTRY, COUNTRY);
+ ret &= add_condition("overlord", GROUP, COUNTRY, COUNTRY);
+ ret &= add_condition("owner", GROUP, COUNTRY, COUNTRY);
+ ret &= add_condition("sphere_owner", GROUP, COUNTRY, COUNTRY);
+ ret &= add_condition("war_countries", GROUP, COUNTRY, COUNTRY);
+
+ /* Trigger State Scopes */
+ ret &= add_condition("any_neighbor_province", GROUP, STATE, PROVINCE);
+
+ /* Trigger Province Scopes */
+ ret &= add_condition("controller", GROUP, PROVINCE, COUNTRY);
+ ret &= add_condition("state_scope", GROUP, PROVINCE, STATE);
+
+ /* Trigger Pop Scopes */
+ ret &= add_condition("location", GROUP, POP, PROVINCE);
+
+ /* Special Conditions */
+ ret &= add_condition("AND", GROUP, COUNTRY);
+ ret &= add_condition("OR", GROUP, COUNTRY);
+ ret &= add_condition("NOT", GROUP, COUNTRY);
+
+ /* 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("is_canal_enabled", INTEGER, COUNTRY);
+ ret &= add_condition("always", BOOLEAN, COUNTRY);
+ ret &= add_condition("world_wars_enabled", BOOLEAN, COUNTRY);
+
+ /* 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("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("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_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("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("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_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("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("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("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_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("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_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_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_secondary_power", BOOLEAN, COUNTRY);
+ ret &= add_condition("is_sphere_leader_of", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
+ ret &= add_condition("is_substate", BOOLEAN, COUNTRY);
+ ret &= add_condition("is_vassal", BOOLEAN, COUNTRY);
+ ret &= add_condition("literacy", REAL, COUNTRY);
+ ret &= add_condition("lost_national", REAL, COUNTRY);
+ ret &= add_condition("middle_strata_militancy", REAL, COUNTRY);
+ ret &= add_condition("middle_strata_everyday_needs", REAL, COUNTRY);
+ 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("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("national_provinces_occupied", REAL, COUNTRY);
+ ret &= add_condition("neighbour", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, 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);
+ ret &= add_condition("num_of_revolts", INTEGER, COUNTRY);
+ ret &= add_condition("number_of_states", INTEGER, COUNTRY);
+ 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("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_militancy", REAL, COUNTRY);
+ ret &= add_condition("poor_strata_militancy", REAL, COUNTRY);
+ ret &= add_condition("poor_strata_everyday_needs", REAL, COUNTRY);
+ ret &= add_condition("poor_strata_life_needs", REAL, COUNTRY);
+ 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("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("revanchism", REAL, COUNTRY);
+ ret &= add_condition("revolt_percentage", REAL, COUNTRY);
+ ret &= add_condition("rich_strata_militancy", REAL, COUNTRY);
+ ret &= add_condition("rich_strata_everyday_needs", REAL, COUNTRY);
+ ret &= add_condition("rich_strata_life_needs", REAL, COUNTRY);
+ 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("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("total_amount_of_divisions", INTEGER, COUNTRY);
+ ret &= add_condition("total_amount_of_ships", INTEGER, COUNTRY);
+ ret &= add_condition("total_defensives", INTEGER, COUNTRY);
+ ret &= add_condition("total_num_of_ports", INTEGER, COUNTRY);
+ ret &= add_condition("total_of_ours_sunk", INTEGER, COUNTRY);
+ 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("treasury", REAL, COUNTRY);
+ ret &= add_condition("truce_with", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, 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("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_score", REAL, COUNTRY);
+ ret &= add_condition("war_with", IDENTIFIER, COUNTRY, NO_SCOPE, NONE, COUNTRY_TAG);
+
+ /* State Scope Conditions */
+ ret &= add_condition("controlled_by", IDENTIFIER, STATE, NO_SCOPE, NONE, 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_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("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("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_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_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_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("unemployment_by_type", COMPLEX, PROVINCE);
+ ret &= add_condition("units_in_province", INTEGER, PROVINCE);
+
+ /* Pop Scope Conditions */
+ ret &= add_condition("agree_with_ruling_party", REAL, POP);
+ ret &= add_condition("cash_reserves", REAL, POP);
+ ret &= add_condition("everyday_needs", REAL, POP);
+ 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("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);
+
+ 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
+ ) -> void {
+ for (std::string_view const& identifier : identifiers) {
+ ret &= add_condition(
+ identifier, value_type, scope, scope_change,
+ key_identifier_type, value_identifier_type
+ );
+ }
+ };
+
+ /* Scopes from other registries */
+ import_identifiers(
+ game_manager.get_country_manager().get_country_identifiers(),
+ GROUP,
+ COUNTRY,
+ COUNTRY,
+ COUNTRY_TAG,
+ NONE
+ );
+
+ import_identifiers(
+ game_manager.get_map().get_region_identifiers(),
+ GROUP,
+ COUNTRY,
+ STATE,
+ REGION,
+ NONE
+ );
+
+ import_identifiers(
+ game_manager.get_map().get_province_identifiers(),
+ GROUP,
+ COUNTRY,
+ PROVINCE,
+ PROVINCE_ID,
+ NONE
+ );
+
+ /* Conditions from other registries */
+ import_identifiers(
+ game_manager.get_politics_manager().get_ideology_manager().get_ideology_identifiers(),
+ REAL,
+ COUNTRY,
+ NO_SCOPE,
+ IDEOLOGY,
+ NONE
+ );
+
+ import_identifiers(
+ game_manager.get_politics_manager().get_issue_manager().get_reform_group_identifiers(),
+ IDENTIFIER,
+ COUNTRY,
+ NO_SCOPE,
+ REFORM_GROUP,
+ REFORM
+ );
+
+ import_identifiers(
+ game_manager.get_politics_manager().get_issue_manager().get_reform_identifiers(),
+ REAL,
+ COUNTRY,
+ NO_SCOPE,
+ REFORM,
+ NONE
+ );
+
+ import_identifiers(
+ game_manager.get_politics_manager().get_issue_manager().get_issue_identifiers(),
+ REAL,
+ COUNTRY,
+ NO_SCOPE,
+ ISSUE,
+ NONE
+ );
+
+ import_identifiers(
+ game_manager.get_pop_manager().get_pop_type_identifiers(),
+ REAL,
+ COUNTRY,
+ NO_SCOPE,
+ POP_TYPE,
+ NONE
+ );
+
+ import_identifiers(
+ game_manager.get_research_manager().get_technology_manager().get_technology_identifiers(),
+ BOOLEAN_INT,
+ COUNTRY,
+ NO_SCOPE,
+ TECHNOLOGY,
+ NONE
+ );
+
+ import_identifiers(
+ game_manager.get_economy_manager().get_good_manager().get_good_identifiers(),
+ INTEGER,
+ COUNTRY,
+ NO_SCOPE,
+ TRADE_GOOD,
+ NONE
+ );
+
+ lock_conditions();
+
+ static constexpr std::string_view condition_root_identifier = "AND";
+ root_condition = get_condition_by_identifier(condition_root_identifier);
+
+ if (root_condition == nullptr) {
+ Logger::error("Failed to find root condition: ", condition_root_identifier);
+ ret = false;
+ }
+
+ return ret;
+}
+
+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;
+
+ #define EXPECT_CALL(type, name, manager, ...) \
+ if (share_identifier_type(identifier_type, type)) { \
+ identified = manager.get_##name##_by_identifier(identifier); \
+ if (identified != nullptr) { \
+ return callback(identified); \
+ } __VA_OPT__(else { \
+ /* TODO: the set is just a placeholder for actual logic */ \
+ static const case_insensitive_string_set_t chances { __VA_ARGS__ }; \
+ if (chances.contains(identifier)) { \
+ return true; \
+ } \
+ }) \
+ }
+
+ //TODO: placeholder for not implemented stuff
+ #define EXPECT_CALL_PLACEHOLDER(type) \
+ if (share_identifier_type(identifier_type, type)) return true;
+
+ EXPECT_CALL_PLACEHOLDER(VARIABLE);
+ EXPECT_CALL_PLACEHOLDER(GLOBAL_FLAG);
+ EXPECT_CALL_PLACEHOLDER(COUNTRY_FLAG);
+ EXPECT_CALL_PLACEHOLDER(PROVINCE_FLAG);
+ EXPECT_CALL(COUNTRY_TAG, country, game_manager.get_country_manager(), "THIS", "FROM", "OWNER");
+ EXPECT_CALL(PROVINCE_ID, province, game_manager.get_map(), "THIS", "FROM");
+ EXPECT_CALL(REGION, region, game_manager.get_map());
+ EXPECT_CALL(IDEOLOGY, ideology, game_manager.get_politics_manager().get_ideology_manager());
+ EXPECT_CALL(REFORM_GROUP, reform_group, game_manager.get_politics_manager().get_issue_manager());
+ EXPECT_CALL(REFORM, reform, game_manager.get_politics_manager().get_issue_manager());
+ EXPECT_CALL(ISSUE, issue, game_manager.get_politics_manager().get_issue_manager());
+ EXPECT_CALL(POP_TYPE, pop_type, game_manager.get_pop_manager());
+ EXPECT_CALL(POP_STRATA, strata, game_manager.get_pop_manager());
+ EXPECT_CALL(TECHNOLOGY, technology, game_manager.get_research_manager().get_technology_manager());
+ EXPECT_CALL(INVENTION, invention, game_manager.get_research_manager().get_invention_manager());
+ EXPECT_CALL(TECH_SCHOOL, technology_school, game_manager.get_research_manager().get_technology_manager());
+ EXPECT_CALL(CULTURE, culture, game_manager.get_pop_manager().get_culture_manager(), "THIS", "FROM");
+ EXPECT_CALL(CULTURE_GROUP, culture_group, game_manager.get_pop_manager().get_culture_manager());
+ EXPECT_CALL(RELIGION, religion, game_manager.get_pop_manager().get_religion_manager(), "THIS", "FROM");
+ EXPECT_CALL(TRADE_GOOD, good, game_manager.get_economy_manager().get_good_manager());
+ EXPECT_CALL(BUILDING, building_type, game_manager.get_economy_manager().get_building_type_manager(), "FACTORY");
+ EXPECT_CALL(CASUS_BELLI, wargoal_type, game_manager.get_military_manager().get_wargoal_type_manager());
+ EXPECT_CALL(GOVERNMENT_TYPE, government_type, game_manager.get_politics_manager().get_government_type_manager());
+ EXPECT_CALL(MODIFIER, event_modifier, game_manager.get_modifier_manager());
+ EXPECT_CALL(MODIFIER, triggered_modifier, game_manager.get_modifier_manager());
+ EXPECT_CALL(MODIFIER, static_modifier, game_manager.get_modifier_manager());
+ EXPECT_CALL(NATIONAL_VALUE, national_value, game_manager.get_politics_manager().get_national_value_manager());
+ EXPECT_CALL(CULTURE_UNION, country, game_manager.get_country_manager(), "THIS", "FROM", "THIS_UNION");
+ EXPECT_CALL(CONTINENT, continent, game_manager.get_map());
+ EXPECT_CALL(CRIME, crime_modifier, game_manager.get_crime_manager());
+ EXPECT_CALL(TERRAIN, terrain_type, game_manager.get_map().get_terrain_type_manager());
+
+ #undef EXPECT_CALL
+ #undef EXPECT_CALL_PLACEHOLDER
+
+ return false;
+ };
+}
+
+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 {
+ bool ret = false;
+ ConditionNode::value_t value;
+
+ const std::string_view identifier = condition.get_identifier();
+ const value_type_t value_type = condition.get_value_type();
+ const scope_t scope = condition.get_scope();
+ const scope_t scope_change = condition.get_scope_change();
+ const identifier_type_t key_identifier_type = condition.get_key_identifier_type();
+ const identifier_type_t value_identifier_type = condition.get_value_identifier_type();
+
+ HasIdentifier const* value_item = nullptr;
+
+ const auto get_identifiable = [this, &game_manager](
+ identifier_type_t item_type, std::string_view id, bool log
+ ) -> HasIdentifier const* {
+ HasIdentifier const* keyval = nullptr;
+ bool ret = expect_parse_identifier(
+ game_manager,
+ item_type,
+ assign_variable_callback(keyval)
+ )(id);
+ if (log && !ret) {
+ Logger::error(
+ "Invalid identifier ", id,
+ " expected to have type ", get_identifier_type_string(item_type),
+ " found during condition node parsing!"
+ );
+ }
+ return keyval;
+ };
+
+ if (!ret && share_value_type(value_type, 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 };
+ value_item = get_identifiable(
+ value_identifier_type,
+ value_identifier,
+ value_type == IDENTIFIER // don't log if there's a fallback
+ );
+ ret |= value_item != nullptr;
+ }
+ }
+
+ if (!ret && share_value_type(value_type, STRING)) {
+ std::string_view value_identifier;
+ bool local_ret = expect_identifier_or_string(
+ assign_variable_callback(value_identifier)
+ )(node);
+ ret |= local_ret;
+ if (local_ret) {
+ value = ConditionNode::string_t { value_identifier };
+ }
+ }
+
+ ret |= (!ret && share_value_type(value_type, BOOLEAN))
+ && expect_bool(assign_variable_callback(value))(node);
+ ret |= (!ret && share_value_type(value_type, BOOLEAN_INT))
+ && expect_int_bool(assign_variable_callback(value))(node);
+ ret |= (!ret && share_value_type(value_type, INTEGER))
+ && expect_uint64(assign_variable_callback(value))(node);
+ ret |= (!ret && share_value_type(value_type, REAL))
+ && expect_fixed_point(assign_variable_callback(value))(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 }; \
+ }
+
+ 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))
+ )(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 }
+ } else if (identifier == "diplomatic_influence") {
+ EXPECT_PAIR(who, value); // { who = [THIS/FROM/TAG] value = x }
+ } else if (identifier == "relation") {
+ EXPECT_PAIR(who, value); // { who = [tag/this/from] value = x }
+ } else if (identifier == "unemployment_by_type") {
+ EXPECT_PAIR(type, value); // {type = [poptype] value = x }
+ } else if (identifier == "upper_house") {
+ EXPECT_PAIR(ideology, value); // { ideology = name value = 0.x }
+ } else if (identifier == "work_available") {
+ // { worker = [type] }
+ std::string_view worker;
+ ret |= expect_dictionary_keys(
+ "worker",
+ ONE_EXACTLY,
+ expect_identifier_or_string(assign_variable_callback(worker))
+ )(node);
+ if (ret) {
+ value = ConditionNode::string_t { worker };
+ }
+ } else {
+ Logger::error("Attempted to parse unknown complex condition ", identifier, "!");
+ }
+
+ #undef EXPECT_PAIR
+ }
+
+ if (!ret && share_value_type(value_type, GROUP)) {
+ 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,
+ false,
+ vector_callback(node_list)
+ )(node);
+ value = std::move(node_list);
+ }
+
+ // scope validation
+ scope_t effective_current_scope = cur_scope;
+ if (share_scope(effective_current_scope, scope_t::THIS)) {
+ effective_current_scope = this_scope;
+ } else if (share_scope(effective_current_scope, scope_t::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), "!"
+ );
+ ret = false;
+ }
+
+ // key parsing
+ HasIdentifier const* key_item = nullptr;
+ if (condition.key_identifier_type != identifier_type_t::NONE) {
+ key_item = get_identifiable(key_identifier_type, identifier, true);
+ ret &= key_item != nullptr;
+ }
+
+ if (!ret) {
+ Logger::error("Could not parse condition node ", identifier);
+ }
+
+ ret &= callback({
+ &condition,
+ std::move(value),
+ ret,
+ key_item,
+ value_item
+ });
+
+ return ret;
+ };
+}
+
+/* Default callback for top condition scope. */
+static bool top_scope_fallback(std::string_view id, ast::NodeCPtr node) {
+ /* This is a non-condition key, and so not case-insensitive. */
+ if (id == "factor") {
+ return true;
+ } else {
+ Logger::error("Unknown node \"", id, "\" found while parsing conditions!");
+ return false;
+ }
+};
+
+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
+ ](Condition const& condition, ast::NodeCPtr node) -> bool {
+ return expect_condition_node(
+ game_manager, condition, this_scope, from_scope, cur_scope, callback
+ )(node);
+ };
+
+ bool ret = conditions.expect_item_dictionary_and_default(
+ expect_node, top_scope ? top_scope_fallback : key_value_invalid_callback
+ )(node);
+ if (!ret) {
+ Logger::error("Error parsing condition node:\n", node);
+ }
+ return ret;
+ };
+}
+
+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
+) const {
+ return [this, &game_manager, initial_scope, this_scope, from_scope, callback](ast::NodeCPtr node) -> bool {
+
+ ConditionNode::condition_list_t conds;
+ bool ret = expect_condition_node_list(
+ game_manager,
+ this_scope,
+ from_scope,
+ initial_scope,
+ true,
+ NodeTools::vector_callback(conds)
+ )(node);
+
+ ret &= callback({ root_condition, std::move(conds), true });
+
+ return ret;
+ };
+}