diff options
-rw-r--r-- | src/openvic-simulation/dataloader/Dataloader.cpp | 2 | ||||
-rw-r--r-- | src/openvic-simulation/economy/GoodDefinition.cpp | 11 | ||||
-rw-r--r-- | src/openvic-simulation/economy/production/ProductionType.cpp | 2 | ||||
-rw-r--r-- | src/openvic-simulation/military/Wargoal.cpp | 6 | ||||
-rw-r--r-- | src/openvic-simulation/misc/Event.cpp | 8 | ||||
-rw-r--r-- | src/openvic-simulation/scripts/Condition.cpp | 1038 | ||||
-rw-r--r-- | src/openvic-simulation/scripts/Condition.hpp | 45 | ||||
-rw-r--r-- | src/openvic-simulation/types/fixed_point/FixedPoint.hpp | 100 |
8 files changed, 808 insertions, 404 deletions
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index 0ffc00f..2b438c7 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -1110,7 +1110,7 @@ bool Dataloader::load_defines(DefinitionManager& definition_manager) { ret = false; } - // ret &= parse_scripts(definition_manager); + ret &= parse_scripts(definition_manager); free_cache(); diff --git a/src/openvic-simulation/economy/GoodDefinition.cpp b/src/openvic-simulation/economy/GoodDefinition.cpp index ba5aff8..5440b94 100644 --- a/src/openvic-simulation/economy/GoodDefinition.cpp +++ b/src/openvic-simulation/economy/GoodDefinition.cpp @@ -90,6 +90,7 @@ bool GoodDefinitionManager::load_goods_file(ast::NodeCPtr root) { } bool GoodDefinitionManager::generate_modifiers(ModifierManager& modifier_manager) const { + constexpr bool has_no_effect = true; using enum ModifierEffect::format_t; using enum ModifierEffect::target_t; @@ -116,11 +117,11 @@ bool GoodDefinitionManager::generate_modifiers(ModifierManager& modifier_manager const auto good_modifier = [&modifier_manager, &ret, &good_identifier]( ModifierEffect const*& effect_cache, std::string_view name, bool is_positive_good, - std::string_view localisation_key + std::string_view localisation_key, bool has_no_effect = false ) -> void { ret &= modifier_manager.register_technology_modifier_effect( effect_cache, ModifierManager::get_flat_identifier(name, good_identifier), is_positive_good, - PROPORTION_DECIMAL, localisation_key + PROPORTION_DECIMAL, localisation_key, has_no_effect ); }; @@ -132,15 +133,15 @@ bool GoodDefinitionManager::generate_modifiers(ModifierManager& modifier_manager good_modifier( this_good_effects.artisan_goods_input, "artisan_goods_input", false, - make_production_localisation_suffix("TECH_INPUT") + make_production_localisation_suffix("TECH_INPUT"), has_no_effect ); good_modifier( this_good_effects.artisan_goods_output, "artisan_goods_output", true, - make_production_localisation_suffix("TECH_OUTPUT") + make_production_localisation_suffix("TECH_OUTPUT"), has_no_effect ); good_modifier( this_good_effects.artisan_goods_throughput, "artisan_goods_throughput", true, - make_production_localisation_suffix("TECH_THROUGHPUT") + make_production_localisation_suffix("TECH_THROUGHPUT"), has_no_effect ); good_modifier( this_good_effects.factory_goods_input, "factory_goods_input", false, diff --git a/src/openvic-simulation/economy/production/ProductionType.cpp b/src/openvic-simulation/economy/production/ProductionType.cpp index 033026d..2e75291 100644 --- a/src/openvic-simulation/economy/production/ProductionType.cpp +++ b/src/openvic-simulation/economy/production/ProductionType.cpp @@ -273,7 +273,7 @@ bool ProductionTypeManager::load_production_types_file( "bonus", ZERO_OR_MORE, [&bonuses](ast::NodeCPtr bonus_node) -> bool { using enum scope_type_t; - ConditionScript trigger { STATE, NO_SCOPE, NO_SCOPE }; + ConditionScript trigger { PROVINCE, NO_SCOPE, NO_SCOPE }; fixed_point_t bonus_value {}; const bool ret = expect_dictionary_keys( diff --git a/src/openvic-simulation/military/Wargoal.cpp b/src/openvic-simulation/military/Wargoal.cpp index ce6b153..a465722 100644 --- a/src/openvic-simulation/military/Wargoal.cpp +++ b/src/openvic-simulation/military/Wargoal.cpp @@ -97,9 +97,9 @@ bool WargoalTypeManager::load_wargoal_file(ovdl::v2script::Parser const& parser) WargoalType::peace_modifiers_t modifiers; ConditionScript can_use { COUNTRY, COUNTRY, COUNTRY }; ConditionScript is_valid { COUNTRY, COUNTRY, COUNTRY }; - ConditionScript allowed_states { STATE, COUNTRY, COUNTRY }; - ConditionScript allowed_substate_regions { STATE, COUNTRY, COUNTRY }; - ConditionScript allowed_states_in_crisis { STATE, COUNTRY, COUNTRY }; + ConditionScript allowed_states { PROVINCE, COUNTRY, COUNTRY }; + ConditionScript allowed_substate_regions { PROVINCE, COUNTRY, COUNTRY }; + ConditionScript allowed_states_in_crisis { PROVINCE, COUNTRY, COUNTRY }; ConditionScript allowed_countries { COUNTRY, COUNTRY, COUNTRY }; EffectScript on_add, on_po_accepted; //country as default scope for both diff --git a/src/openvic-simulation/misc/Event.cpp b/src/openvic-simulation/misc/Event.cpp index 64b1f64..7f57ccc 100644 --- a/src/openvic-simulation/misc/Event.cpp +++ b/src/openvic-simulation/misc/Event.cpp @@ -140,8 +140,8 @@ bool EventManager::load_event_file(IssueManager const& issue_manager, ast::NodeC bool triggered_only = false, major = false, fire_only_once = false, allows_multiple_instances = false, news = false, election = false; IssueGroup const* election_issue_group = nullptr; - ConditionScript trigger { initial_scope, initial_scope, NO_SCOPE }; - ConditionalWeight mean_time_to_happen { initial_scope, initial_scope, NO_SCOPE }; + ConditionScript trigger { initial_scope, COUNTRY, NO_SCOPE }; + ConditionalWeight mean_time_to_happen { initial_scope, COUNTRY, NO_SCOPE }; EffectScript immediate; std::vector<Event::EventOption> options; @@ -167,8 +167,8 @@ bool EventManager::load_event_file(IssueManager const& issue_manager, ast::NodeC EffectScript effect; ConditionalWeight ai_chance { initial_scope, - initial_scope, - COUNTRY | PROVINCE // TODO - decide which to use? + COUNTRY, + COUNTRY }; bool ret = expect_dictionary_keys_and_default( diff --git a/src/openvic-simulation/scripts/Condition.cpp b/src/openvic-simulation/scripts/Condition.cpp index ea565a7..47f63bd 100644 --- a/src/openvic-simulation/scripts/Condition.cpp +++ b/src/openvic-simulation/scripts/Condition.cpp @@ -10,6 +10,7 @@ using namespace OpenVic::NodeTools; using no_argument_t = ConditionNode::no_argument_t; using this_argument_t = ConditionNode::this_argument_t; using from_argument_t = ConditionNode::from_argument_t; +using special_argument_t = ConditionNode::special_argument_t; using integer_t = ConditionNode::integer_t; using argument_t = ConditionNode::argument_t; @@ -19,6 +20,11 @@ using scope_t = ConditionNode::scope_t; static constexpr std::string_view THIS_KEYWORD = "THIS"; static constexpr std::string_view FROM_KEYWORD = "FROM"; +// Used for this_culture_union +static constexpr const char this_union_keyword[] = "this_union"; +// Used for controlled_by +static constexpr const char owner_keyword[] = "owner"; + ConditionNode::ConditionNode( Condition const* new_condition, argument_t&& new_argument @@ -39,6 +45,126 @@ bool ConditionNode::execute( ); } +struct print_condition_node_visitor_t { + std::ostream& stream; + size_t indent = 0; + static constexpr size_t indent_width = 2; + Condition const* last_condition = nullptr; + + void print(ConditionNode const& node) { + last_condition = node.get_condition(); + stream << last_condition << " = "; + std::visit(*this, node.get_argument()); + } + void print_newline_indent() { + stream << "\n" << std::setw(indent * indent_width) << ""; + } + template<typename P1, typename P2> + void print_pair( + std::string_view first_key, std::string_view second_key, std::pair<P1, P2> const& values + ) { + stream << "{"; + indent++; + print_newline_indent(); + stream << first_key << " = " << values.first; + print_newline_indent(); + stream << second_key << " = " << values.second; + indent--; + print_newline_indent(); + stream << "}"; + } + void operator()(no_argument_t const& arg) { + stream << "<NO_ARGUMENT>"; + } + void operator()(this_argument_t const& arg) { + stream << THIS_KEYWORD; + } + void operator()(from_argument_t const& arg) { + stream << FROM_KEYWORD; + } + void operator()(special_argument_t const& arg) { + const std::string_view identifier = + last_condition != nullptr ? last_condition->get_identifier() : std::string_view {}; + if (identifier == "this_culture_union") { + stream << this_union_keyword; + } else if (identifier == "controlled_by") { + stream << owner_keyword; + } else { + stream << "<SPECIAL_ARGUMENT>"; + } + } + void operator()(std::vector<ConditionNode> const& arg) { + stream << "{"; + + if (!arg.empty()) { + indent++; + + for (ConditionNode const& child : arg) { + print_newline_indent(); + print(child); + } + + indent--; + print_newline_indent(); + } + + stream << "}"; + } + void operator()(bool const& arg) { + stream << (arg ? "yes" : "no"); + } + void operator()(std::pair<PopType const*, fixed_point_t> const& arg) { + print_pair("type", "value", arg); + } + void operator()(std::pair<bool, bool> const& arg) { + print_pair( + "in_whole_capital_state", "limit_to_world_greatest_level", + std::pair { arg.first ? "yes" : "no", arg.second ? "yes" : "no" } + ); + } + void operator()(std::pair<Ideology const*, fixed_point_t> const& arg) { + print_pair("ideology", "value", arg); + } + void operator()(std::vector<PopType const*> const& arg) { + stream << "{"; + + if (!arg.empty()) { + indent++; + + for (PopType const* pop_type : arg) { + print_newline_indent(); + stream << "worker = " << pop_type; + } + + indent--; + print_newline_indent(); + } + + stream << "}"; + } + void operator()(std::pair<CountryDefinition const*, fixed_point_t> const& arg) { + print_pair("who", "value", arg); + } + void operator()(std::pair<this_argument_t, fixed_point_t> const& arg) { + print_pair("who", "value", std::pair { THIS_KEYWORD, arg.second }); + } + void operator()(std::pair<from_argument_t, fixed_point_t> const& arg) { + print_pair("who", "value", std::pair { FROM_KEYWORD, arg.second }); + } + void operator()(std::pair<std::string, fixed_point_t> const& arg) { + print_pair("which", "value", arg); + } + void operator()(auto const& arg) { + stream << arg; + } +}; + +std::ostream& OpenVic::operator<<(std::ostream& stream, ConditionNode const& node) { + print_condition_node_visitor_t { stream }.print(node); + + return stream; +} + Condition::Condition( std::string_view new_identifier, parse_callback_t&& new_parse_callback, @@ -199,9 +325,63 @@ bool ConditionManager::_parse_condition_node_list_callback( return ret; } +/* Callback for conditions with a special case as well as a regular value type: + * - special_case_triggered(condition, definition_manager, callback, str, ret) + * - str is the condition's value parsed as an identifier or string + * - special_case_triggered is the bool return value which determines whether to return ret or continue with the regular + * value parsing */ +using special_callback_t = bool (*)( + Condition const&, DefinitionManager const&, callback_t<argument_t&&>, std::string_view, bool& +); + +static bool _parse_condition_node_special_callback_bool( + Condition const& condition, DefinitionManager const& definition_manager, callback_t<argument_t&&> callback, + std::string_view str, bool& ret +) { + if (StringUtils::strings_equal_case_insensitive(str, "yes")) { + ret = callback(true); + return true; + } + + if (StringUtils::strings_equal_case_insensitive(str, "no")) { + ret = callback(false); + return true; + } + + return false; +} + +template<char const* KEYWORD> +static bool _parse_condition_node_special_callback_keyword( + Condition const& condition, DefinitionManager const& definition_manager, callback_t<argument_t&&> callback, + std::string_view str, bool& ret +) { + if (StringUtils::strings_equal_case_insensitive(str, KEYWORD)) { + ret = callback(special_argument_t {}); + return true; + } + + return false; +} + +static bool _parse_condition_node_special_callback_country( + Condition const& condition, DefinitionManager const& definition_manager, callback_t<argument_t&&> callback, + std::string_view str, bool& ret +) { + CountryDefinition const* country = + definition_manager.get_country_definition_manager().get_country_definition_by_identifier(str); + + if (country != nullptr) { + ret = callback(country); + return true; + } + + return false; +} + // ALLOWED_SCOPES is a bitfield indicating valid values of current_scope, as well as whether the value is allowed to be // THIS or FROM corresponding to the special argument types this_argument_t and from_argument_t respectively. -template<typename T, scope_type_t ALLOWED_SCOPES = scope_type_t::ALL_SCOPES> +template<typename T, scope_type_t ALLOWED_SCOPES = scope_type_t::ALL_SCOPES, special_callback_t SPECIAL_CALLBACK = nullptr> static bool _parse_condition_node_value_callback( Condition const& condition, DefinitionManager const& definition_manager, scope_type_t current_scope, scope_type_t this_scope, scope_type_t from_scope, ast::NodeCPtr node, callback_t<argument_t&&> callback @@ -215,9 +395,16 @@ static bool _parse_condition_node_value_callback( std::same_as<T, CountryDefinition const*> || std::same_as<T, ProvinceDefinition const*> || std::same_as<T, GoodDefinition const*> || std::same_as<T, Continent const*> || std::same_as<T, BuildingType const*> || std::same_as<T, Issue const*> || std::same_as<T, WargoalType const*> || std::same_as<T, PopType const*> || - std::same_as<T, Culture const*> || std::same_as<T, Religion const*> || std::same_as<T, GovernmentType const*> || - std::same_as<T, Ideology const*> || std::same_as<T, Reform const*> || std::same_as<T, NationalValue const*> || - std::same_as<T, Invention const*> || std::same_as<T, TechnologySchool const*> + std::same_as<T, CultureGroup const*> || std::same_as<T, Culture const*> || std::same_as<T, Religion const*> || + std::same_as<T, GovernmentType const*> || std::same_as<T, Ideology const*> || std::same_as<T, Reform const*> || + std::same_as<T, NationalValue const*> || std::same_as<T, Invention const*> || + std::same_as<T, TechnologySchool const*> || std::same_as<T, Crime const*> || std::same_as<T, Region const*> || + std::same_as<T, TerrainType const*> || std::same_as<T, Strata const*> || + + // Multi-value arguments + std::same_as<T, std::pair<PopType const*, fixed_point_t>> || std::same_as<T, std::pair<bool, bool>> || + std::same_as<T, std::pair<Ideology const*, fixed_point_t>> || std::same_as<T, std::vector<PopType const*>> || + std::same_as<T, std::pair<std::string, fixed_point_t>> ); using enum scope_type_t; @@ -230,18 +417,14 @@ static bool _parse_condition_node_value_callback( return false; } - bool ret = true; - // All possible value types can also be interpreted as an identifier or string, so we shouldn't get any unwanted error // messages if the value is a regular value rather than THIS or FROM. In fact if expect_identifier_or_string returns false // when checking for THIS or FROM then we can be confident that it would also return false when parsing a regular value. - if constexpr (share_scope_type(ALLOWED_SCOPES, THIS | FROM)) { + if constexpr (share_scope_type(ALLOWED_SCOPES, THIS | FROM) || SPECIAL_CALLBACK != nullptr) { std::string_view str; - ret &= expect_identifier_or_string(assign_variable_callback(str))(node); - - if (!ret) { + if (!expect_identifier_or_string(assign_variable_callback(str))(node)) { Logger::error( "Error parsing condition \"", condition.get_identifier(), "\": failed to parse identifier or string when checking for THIS and/or FROM condition argument!" @@ -251,19 +434,25 @@ static bool _parse_condition_node_value_callback( if constexpr (share_scope_type(ALLOWED_SCOPES, THIS)) { if (StringUtils::strings_equal_case_insensitive(str, THIS_KEYWORD)) { - ret &= callback(this_argument_t {}); - return ret; + return callback(this_argument_t {}); } } if constexpr (share_scope_type(ALLOWED_SCOPES, FROM)) { if (StringUtils::strings_equal_case_insensitive(str, FROM_KEYWORD)) { - ret &= callback(from_argument_t {}); + return callback(from_argument_t {}); + } + } + + if constexpr (SPECIAL_CALLBACK != nullptr) { + bool ret = true; + if ((*SPECIAL_CALLBACK)(condition, definition_manager, callback, str, ret)) { return ret; } } } + bool ret = true; T value {}; if constexpr (std::same_as<T, bool>) { @@ -307,6 +496,10 @@ static bool _parse_condition_node_value_callback( ret = definition_manager.get_pop_manager().expect_pop_type_identifier_or_string( assign_variable_callback_pointer(value) )(node); + } else if constexpr (std::same_as<T, CultureGroup const*>) { + ret = definition_manager.get_pop_manager().get_culture_manager().expect_culture_group_identifier_or_string( + assign_variable_callback_pointer(value) + )(node); } else if constexpr (std::same_as<T, Culture const*>) { ret = definition_manager.get_pop_manager().get_culture_manager().expect_culture_identifier_or_string( assign_variable_callback_pointer(value) @@ -336,6 +529,53 @@ static bool _parse_condition_node_value_callback( ret = definition_manager.get_research_manager().get_technology_manager().expect_technology_school_identifier_or_string( assign_variable_callback_pointer(value) )(node); + } else if constexpr (std::same_as<T, Crime const*>) { + ret = definition_manager.get_crime_manager().expect_crime_modifier_identifier_or_string( + assign_variable_callback_pointer(value) + )(node); + } else if constexpr (std::same_as<T, Region const*>) { + ret = definition_manager.get_map_definition().expect_region_identifier_or_string( + assign_variable_callback_pointer(value) + )(node); + } else if constexpr (std::same_as<T, TerrainType const*>) { + ret = definition_manager.get_map_definition().get_terrain_type_manager().expect_terrain_type_identifier_or_string( + assign_variable_callback_pointer(value) + )(node); + } else if constexpr (std::same_as<T, Strata const*>) { + ret = definition_manager.get_pop_manager().expect_strata_identifier_or_string( + assign_variable_callback_pointer(value) + )(node); + } else if constexpr (std::same_as<T, std::pair<PopType const*, fixed_point_t>>) { + ret = expect_dictionary_keys( + "type", ONE_EXACTLY, definition_manager.get_pop_manager().expect_pop_type_identifier_or_string( + assign_variable_callback_pointer(value.first) + ), + "value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(value.second)) + )(node); + } else if constexpr (std::same_as<T, std::pair<bool, bool>>) { + ret = expect_dictionary_keys( + "in_whole_capital_state", ONE_EXACTLY, assign_variable_callback(value.first), + "limit_to_world_greatest_level", ONE_EXACTLY, assign_variable_callback(value.second) + )(node); + } else if constexpr (std::same_as<T, std::pair<Ideology const*, fixed_point_t>>) { + ret = expect_dictionary_keys( + "ideology", ONE_EXACTLY, + definition_manager.get_politics_manager().get_ideology_manager().expect_ideology_identifier_or_string( + assign_variable_callback_pointer(value.first) + ), + "value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(value.second)) + )(node); + } else if constexpr (std::same_as<T, std::vector<PopType const*>>) { + ret = expect_dictionary_keys( + "worker", ONE_OR_MORE, definition_manager.get_pop_manager().expect_pop_type_identifier_or_string( + vector_callback_pointer(value) + ) + )(node); + } else if constexpr (std::same_as<T, std::pair<std::string, fixed_point_t>>) { + ret = expect_dictionary_keys( + "which", ONE_EXACTLY, expect_identifier_or_string(assign_variable_callback_string(value.first)), + "value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(value.second)) + )(node); } if (ret) { @@ -345,6 +585,52 @@ static bool _parse_condition_node_value_callback( return ret; } +static bool _parse_condition_node_who_value_callback( + Condition const& condition, DefinitionManager const& definition_manager, scope_type_t current_scope, + scope_type_t this_scope, scope_type_t from_scope, ast::NodeCPtr node, callback_t<argument_t&&> callback +) { + using enum scope_type_t; + + if (!share_scope_type(current_scope, COUNTRY)) { + Logger::error( + "Error parsing condition \"", condition.get_identifier(), + "\": scope mismatch - expected ", COUNTRY, ", got ", current_scope + ); + return false; + } + + std::string_view str; + fixed_point_t value; + + if ( + expect_dictionary_keys( + "who", ONE_EXACTLY, expect_identifier_or_string(assign_variable_callback(str)), + "value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(value)) + )(node) + ) { + if (StringUtils::strings_equal_case_insensitive(str, THIS_KEYWORD)) { + return callback(std::pair { this_argument_t {}, value }); + } + + if (StringUtils::strings_equal_case_insensitive(str, FROM_KEYWORD)) { + return callback(std::pair { from_argument_t {}, value }); + } + + CountryDefinition const* country = + definition_manager.get_country_definition_manager().get_country_definition_by_identifier(str); + + if (country != nullptr) { + return callback(std::pair { country, value }); + } + + Logger::error( + "Error parsing condition \"", condition.get_identifier(), "\": unknown country \"", str, "\"" + ); + } + + return false; +} + // EXECUTE CALLBACK HELPERS static constexpr bool _execute_condition_node_unimplemented( @@ -766,7 +1052,12 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana } ) ); - // ret &= add_condition("independence", GROUP, COUNTRY, COUNTRY); //only from rebels! + // Only from RebelType demands_enforced_trigger, changes scope to the country getting independence + ret &= add_condition( + "independence", + _parse_condition_node_list_callback<COUNTRY>, + _execute_condition_node_unimplemented + ); /* Trigger Country Scopes */ static const auto get_core_scopes = @@ -880,7 +1171,7 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana ); ret &= add_condition( "any_state", - _parse_condition_node_list_callback<STATE, COUNTRY>, + _parse_condition_node_list_callback<PROVINCE, COUNTRY>, _execute_condition_node_unimplemented ); ret &= add_condition( @@ -999,7 +1290,7 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana ); ret &= add_condition( "state_scope", - _parse_condition_node_list_callback<STATE, PROVINCE>, + _parse_condition_node_list_callback<PROVINCE, PROVINCE>, _execute_condition_node_unimplemented ); @@ -1306,23 +1597,12 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana ); ret &= add_condition( "can_build_fort_in_capital", - /* TODO - complex: - * - used at COUNTRY scope, specifically in westernisation reform on_execute trigger conditions - * - value is a dictionary with two entries: - * - in_whole_capital_state = <bool> - * - yes = build in all provinces in capital state - * - no = just in main capital province - * - limit_to_world_greatest_level = <bool> - * - yes = build at level of world's greatest fort (greatest researched or greatest built?) - * - no = either build level 1 or highest level this country can build (in practice 1 as the country will only - * just have gotten the first fort tech, should be tested in other scenarios) */ - _parse_condition_node_unimplemented, + _parse_condition_node_value_callback<std::pair<bool, bool>, COUNTRY>, _execute_condition_node_unimplemented ); ret &= add_condition( "can_build_railway_in_capital", - // TODO - same complex structure as can_build_fort_in_capital, with two dictionary entries - _parse_condition_node_unimplemented, + _parse_condition_node_value_callback<std::pair<bool, bool>, COUNTRY>, _execute_condition_node_unimplemented ); ret &= add_condition( @@ -1361,7 +1641,6 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana ); ret &= add_condition( "check_variable", - //COMPLEX, COUNTRY, NO_SCOPE, NO_IDENTIFIER, VARIABLE /* TODO - complex: * - does this have any scope restrictions, and does it affect scope in any way? The wiki warns that this doesn't * work from province scope. @@ -1374,7 +1653,7 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana * - The number to compare the current variable value against. Returns true if the variable has been previously * set and has a value greater than or equal to the number. * - Can values be negative? Can they be non-integers? How big can they get? */ - _parse_condition_node_unimplemented, + _parse_condition_node_value_callback<std::pair<std::string, fixed_point_t>, COUNTRY>, _execute_condition_node_unimplemented ); ret &= add_condition( @@ -1479,18 +1758,6 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana _parse_condition_node_value_callback<bool>, _execute_condition_node_unimplemented ); - /* -culture -Syntax: - -culture = [culture name] -Use: -Province Scope Effects: Returns true if there is a majority of the specified culture in the specified province. -POP Scope Effects: Warning! Only returns true if there is a majority of the specified culture in the POP's province. -To check if the POP itself has the culture, use "has_pop_culture" instead. - - - */ ret &= add_condition( "culture", /* TODO - wiki says this can also be used at PROVINCE scope, and even at POP scope it checks that the majority @@ -1498,7 +1765,7 @@ To check if the POP itself has the culture, use "has_pop_culture" instead. * has_pop_culture should be used to check a specific pop's culture. The tooltips aren't very clear, with * "culture = <culture>" showing up as "Culture is <culture>" and "has_pop_culture = <culture>" showing up as * "<Pop type plural> in <province> have <culture>". */ - _parse_condition_node_value_callback<Culture const*, PROVINCE | POP>, + _parse_condition_node_value_callback<Culture const*, PROVINCE | POP | THIS | FROM>, _execute_condition_node_unimplemented ); ret &= add_condition( @@ -1531,23 +1798,9 @@ To check if the POP itself has the culture, use "has_pop_culture" instead. ) ) ); -/* -diplomatic_influence -Syntax: - -diplomatic_influence = { - who = [THIS/FROM/TAG] - value = x -} -Use: -Returns true if country has more than x diplomatic influence in the country in scope. - -*/ - /* TODO - complex: - * - */ ret &= add_condition( "diplomatic_influence", - _parse_condition_node_unimplemented, + _parse_condition_node_who_value_callback, _execute_condition_node_unimplemented ); ret &= add_condition( @@ -1560,18 +1813,11 @@ Returns true if country has more than x diplomatic influence in the country in s _parse_condition_node_value_callback<bool, COUNTRY>, _execute_condition_node_unimplemented ); - /* -exists -Syntax: - -exists = [tag] -Use: -Returns true if the specified country exists. May also be used with [yes/no] to determine if the country in scope actually exists. - */ ret &= add_condition( - "exists",// IDENTIFIER | BOOLEAN, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG - // bool or tag or THIS or FROM - _parse_condition_node_unimplemented, + "exists", + _parse_condition_node_value_callback< + CountryDefinition const*, COUNTRY | THIS | FROM, _parse_condition_node_special_callback_bool + >, _execute_condition_node_unimplemented ); ret &= add_condition( @@ -1623,7 +1869,7 @@ Returns true if the specified country exists. May also be used with [yes/no] to "has_country_modifier", // TODO - which modifiers work here? just country event (+ specially handled debt statics)? // - should this be parsed into a Modifier const* or kept as a std::string? - _parse_condition_node_unimplemented, + _parse_condition_node_value_callback<std::string, COUNTRY>, _execute_condition_node_unimplemented ); ret &= add_condition( @@ -1651,12 +1897,12 @@ Returns true if the specified country exists. May also be used with [yes/no] to ); ret &= add_condition( "has_pop_culture", - _parse_condition_node_value_callback<Culture const*, POP>, + _parse_condition_node_value_callback<Culture const*, POP | THIS | FROM>, _execute_condition_node_unimplemented ); ret &= add_condition( "has_pop_religion", - _parse_condition_node_value_callback<Religion const*, POP>, + _parse_condition_node_value_callback<Religion const*, POP | THIS | FROM>, _execute_condition_node_unimplemented ); ret &= add_condition( @@ -1675,7 +1921,7 @@ Returns true if the specified country exists. May also be used with [yes/no] to _execute_condition_node_unimplemented ); // "ideology = <ideology>"" doesn't seem to work as a country condition? - // ret &= add_condition("ideology", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, IDEOLOGY); + // NOT FOUND - ret &= add_condition("ideology", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, IDEOLOGY); ret &= add_condition( "industrial_score", // This doesn't seem to work with regular country identifiers, they're treated as 0 @@ -1715,8 +1961,13 @@ Returns true if the specified country exists. May also be used with [yes/no] to _parse_condition_node_value_callback<bool, COUNTRY>, _execute_condition_node_unimplemented ); - // is_cultural_union can take bools and country identifiers, probably also THIS and FROM - // ret &= add_condition("is_cultural_union", IDENTIFIER | BOOLEAN, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG); + ret &= add_condition( + "is_cultural_union", + _parse_condition_node_value_callback< + CountryDefinition const*, COUNTRY | THIS | FROM, _parse_condition_node_special_callback_bool + >, + _execute_condition_node_unimplemented + ); ret &= add_condition( "is_disarmed", _parse_condition_node_value_callback<bool, COUNTRY>, @@ -1729,16 +1980,24 @@ Returns true if the specified country exists. May also be used with [yes/no] to ); ret &= add_condition( "is_colonial", - _parse_condition_node_value_callback<bool, STATE>, + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "is_core", + // TODO - ensure ProvinceDefinition const* can only be used at COUNTRY scope and CountryDefinition const* at PROVINCE scope + _parse_condition_node_value_callback< + ProvinceDefinition const*, COUNTRY | PROVINCE | THIS | FROM, _parse_condition_node_special_callback_country + >, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "is_culture_group", + _parse_condition_node_value_callback< + CultureGroup const*, COUNTRY | POP | THIS | FROM, _parse_condition_node_special_callback_country + >, _execute_condition_node_unimplemented ); - /* is_core can be used: - * - at COUNTRY scope with a province identifier (maybe THIS or FROM too) - * - at PROVINCE scope with a country identifier or THIS or FROM - */ - // ret &= add_condition("is_core", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG | PROVINCE_ID); - // is_culture_group can be used at COUNTRY or POP scope with a culture, country, THIS or FROM - // ret &= add_condition("is_culture_group", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, COUNTRY_TAG | CULTURE_GROUP); ret &= add_condition( "is_ideology_enabled", // The wiki says this can only be used at COUNTRY and PROVINCE scopes but I see no reason why it can't be global @@ -1811,11 +2070,6 @@ Returns true if the specified country exists. May also be used with [yes/no] to _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, _execute_condition_node_unimplemented ); - // 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", _parse_condition_node_value_callback<CountryDefinition const*, COUNTRY | THIS | FROM>, @@ -1944,11 +2198,6 @@ Returns true if the specified country exists. May also be used with [yes/no] to _parse_condition_node_value_callback<fixed_point_t, PROVINCE>, _execute_condition_node_unimplemented ); - // 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", _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, @@ -1984,18 +2233,14 @@ Returns true if the specified country exists. May also be used with [yes/no] to _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, _execute_condition_node_unimplemented ); -/* -relation -Syntax: - -relation = { who = [tag/this/from] value = x } -Use: -Returns true if the specified country has a relation value equal to x or higher with the specified country. -*/ - // ret &= add_condition("relation", COMPLEX, COUNTRY); + ret &= add_condition( + "relation", + _parse_condition_node_who_value_callback, + _execute_condition_node_unimplemented + ); ret &= add_condition( "religion", - _parse_condition_node_value_callback<Religion const*, POP>, + _parse_condition_node_value_callback<Religion const*, POP | THIS | FROM>, _execute_condition_node_unimplemented ); ret &= add_condition( @@ -2008,11 +2253,7 @@ Returns true if the specified country has a relation value equal to x or higher _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, _execute_condition_node_unimplemented ); - // 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); + // Doesn't appear in vanilla or test mods // ret &= add_condition("rich_tax_above_poor", BOOLEAN, COUNTRY); ret &= add_condition( "ruling_party", @@ -2048,7 +2289,7 @@ Returns true if the specified country has a relation value equal to x or higher ); ret &= add_condition( "tag", - _parse_condition_node_value_callback<CountryDefinition const*, COUNTRY>, + _parse_condition_node_value_callback<CountryDefinition const*, COUNTRY | THIS | FROM>, _execute_condition_node_unimplemented ); ret &= add_condition( @@ -2056,15 +2297,13 @@ Returns true if the specified country has a relation value equal to x or higher _parse_condition_node_value_callback<TechnologySchool const*, COUNTRY>, _execute_condition_node_unimplemented ); -/* -this_culture_union *HOD ONLY* -Syntax: - -this_culture_union = [country tag] / THIS / FROM / this_union -Use: -Returns true if the nation specified has the same cultural union as the country in scope. -*/ - // ret &= add_condition("this_culture_union", IDENTIFIER, COUNTRY, NO_SCOPE, NO_IDENTIFIER, CULTURE_UNION); + ret &= add_condition( + "this_culture_union", + _parse_condition_node_value_callback< + CountryDefinition const*, COUNTRY | THIS | FROM, _parse_condition_node_special_callback_keyword<this_union_keyword> + >, + _execute_condition_node_unimplemented + ); ret &= add_condition( "total_amount_of_divisions", _parse_condition_node_value_callback<integer_t, COUNTRY>, @@ -2094,6 +2333,11 @@ Returns true if the nation specified has the same cultural union as the country // Doesn't show up or work in allow decision tooltips // ret &= add_condition("total_sunk_by_us", INTEGER, COUNTRY); ret &= add_condition( + "treasury", + _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( "truce_with", _parse_condition_node_value_callback<CountryDefinition const*, COUNTRY | THIS | FROM>, _execute_condition_node_unimplemented @@ -2110,19 +2354,11 @@ Returns true if the nation specified has the same cultural union as the country _parse_condition_node_value_callback<bool, COUNTRY>, _execute_condition_node_unimplemented ); -/* -upper_house -Syntax: - -upper_house = { - ideology = name - value = 0.x - } -where value is a fraction 0.0 to 1.0, so value 0.4 = 40% has that ideology -Use: -Returns true if the country's upper house has the required characteristics -*/ - // ret &= add_condition("upper_house", COMPLEX, COUNTRY); + ret &= add_condition( + "upper_house", + _parse_condition_node_value_callback<std::pair<Ideology const*, fixed_point_t>, COUNTRY>, + _execute_condition_node_unimplemented + ); ret &= add_condition( "vassal_of", _parse_condition_node_value_callback<CountryDefinition const*, COUNTRY | THIS | FROM>, @@ -2150,88 +2386,316 @@ Returns true if the country's upper house has the required characteristics ); /* State Scope Conditions */ - // 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, 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, 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); + ret &= add_condition( + "controlled_by", + _parse_condition_node_value_callback< + CountryDefinition const*, PROVINCE | THIS | FROM, _parse_condition_node_special_callback_keyword<owner_keyword> + >, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "empty", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "flashpoint_tension", + _parse_condition_node_value_callback<fixed_point_t, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "has_building", + _parse_condition_node_value_callback< + BuildingType const*, PROVINCE, + []( + Condition const& condition, DefinitionManager const& definition_manager, callback_t<argument_t&&> callback, + std::string_view str, bool& ret + ) -> bool { + if ( + definition_manager.get_economy_manager().get_building_type_manager().get_building_type_types() + .contains(str) + ) { + ret = callback(std::string { str }); + return true; + } + + return false; + } + >, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "has_factories", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "has_flashpoint", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "is_slave", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "owned_by", + _parse_condition_node_value_callback<CountryDefinition const*, PROVINCE | THIS | FROM>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "trade_goods_in_state", + _parse_condition_node_value_callback<GoodDefinition const*, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "work_available", + _parse_condition_node_value_callback<std::vector<PopType const*>, PROVINCE>, + _execute_condition_node_unimplemented + ); /* 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, NO_IDENTIFIER, COUNTRY_TAG); + ret &= add_condition( + "can_build_factory", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "controlled_by_rebels", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "country_units_in_province", + _parse_condition_node_value_callback<CountryDefinition const*, PROVINCE | THIS | FROM>, + _execute_condition_node_unimplemented + ); + // Doesn't appear in vanilla or any test mods // 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_crime", + _parse_condition_node_value_callback<Crime const*, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "has_culture_core", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "has_empty_adjacent_province", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + // Doesn't appear in vanilla or any test mods // 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, NO_IDENTIFIER, PROVINCE_FLAG); - // ret &= add_condition("has_province_modifier", IDENTIFIER, PROVINCE, NO_SCOPE, NO_IDENTIFIER, PROVINCE_EVENT_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, 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, 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, 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); + ret &= add_condition( + "has_national_minority", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "has_province_flag", + _parse_condition_node_value_callback<std::string, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "has_province_modifier", + // TODO - parse as Modifier const*? Depends what types of modifiers can go here + _parse_condition_node_value_callback<std::string, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "has_recent_imigration", // paradox typo + _parse_condition_node_value_callback<integer_t, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "is_blockaded", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "is_accepted_culture", + _parse_condition_node_value_callback< + CountryDefinition const*, PROVINCE | POP | THIS | FROM, _parse_condition_node_special_callback_bool + >, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "is_capital", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "is_coastal", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "is_overseas", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "is_primary_culture", + _parse_condition_node_value_callback< + CountryDefinition const*, PROVINCE | POP | THIS | FROM, _parse_condition_node_special_callback_bool + >, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "is_state_capital", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "is_state_religion", + _parse_condition_node_value_callback<bool, PROVINCE | POP>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "life_rating", + _parse_condition_node_value_callback<fixed_point_t, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "minorities", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "port", + _parse_condition_node_value_callback<bool, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "province_control_days", + _parse_condition_node_value_callback<integer_t, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "province_id", + _parse_condition_node_value_callback<ProvinceDefinition const*, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "region", + _parse_condition_node_value_callback<Region const*, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "state_id", + _parse_condition_node_value_callback<ProvinceDefinition const*, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "terrain", + _parse_condition_node_value_callback<TerrainType const*, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "trade_goods", + _parse_condition_node_value_callback<GoodDefinition const*, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "unemployment_by_type", + _parse_condition_node_value_callback<std::pair<PopType const*, fixed_point_t>, PROVINCE>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "units_in_province", + _parse_condition_node_value_callback<integer_t, PROVINCE>, + _execute_condition_node_unimplemented + ); /* 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( + "agree_with_ruling_party", + _parse_condition_node_value_callback<fixed_point_t, POP>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "cash_reserves", + _parse_condition_node_value_callback<fixed_point_t, POP>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "life_needs", + _parse_condition_node_value_callback<fixed_point_t, POP>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "everyday_needs", + _parse_condition_node_value_callback<fixed_point_t, POP>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "luxury_needs", + _parse_condition_node_value_callback<fixed_point_t, POP>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "political_movement", + _parse_condition_node_value_callback<bool, POP>, + _execute_condition_node_unimplemented + ); + // Doesn't appear in vanilla or any test mods // 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, 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_type_t scope, - // scope_type_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( - // identifier, value_type, scope, scope_change, - // key_identifier_type, value_identifier_type - // ); - // } - // }; + ret &= add_condition( + "pop_type", + _parse_condition_node_value_callback<PopType const*, POP>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "social_movement", + _parse_condition_node_value_callback<bool, POP>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "strata", + _parse_condition_node_value_callback<Strata const*, POP>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + "type", + _parse_condition_node_value_callback<PopType const*, POP>, + _execute_condition_node_unimplemented + ); + + for (Strata const& strata : definition_manager.get_pop_manager().get_stratas()) { + const std::string_view identifier = strata.get_identifier(); + + ret &= add_condition( + StringUtils::append_string_views(identifier, "_tax"), + _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + StringUtils::append_string_views(identifier, "_strata_life_needs"), + _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + StringUtils::append_string_views(identifier, "_strata_everyday_needs"), + _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + StringUtils::append_string_views(identifier, "_strata_luxury_needs"), + _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, + _execute_condition_node_unimplemented + ); + ret &= add_condition( + StringUtils::append_string_views(identifier, "_strata_militancy"), + _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, + _execute_condition_node_unimplemented + ); + } /* Scopes from other registries */ - // import_identifiers( - // definition_manager.get_country_definition_manager().get_country_definition_identifiers(), - // GROUP, - // COUNTRY, - // COUNTRY, - // COUNTRY_TAG, - // NO_IDENTIFIER - // ); for (CountryDefinition const& country : definition_manager.get_country_definition_manager().get_country_definitions()) { ret &= add_condition( country.get_identifier(), @@ -2247,23 +2711,32 @@ Returns true if the country's upper house has the required characteristics ); } - // import_identifiers( - // definition_manager.get_map_definition().get_region_identifiers(), - // GROUP, - // COUNTRY, - // STATE, - // REGION, - // NO_IDENTIFIER - // ); - - // import_identifiers( - // definition_manager.get_map_definition().get_province_definition_identifiers(), - // GROUP, - // COUNTRY, - // PROVINCE, - // PROVINCE_ID, - // NO_IDENTIFIER - // ); + for (Region const& region : definition_manager.get_map_definition().get_regions()) { + ret &= add_condition( + region.get_identifier(), + _parse_condition_node_list_callback<PROVINCE>, + _execute_condition_node_list_multi_scope_callback<expect_true, require_all>( + [®ion]( + Condition const& condition, InstanceManager const& instance_manager, scope_t const& current_scope, + scope_t const& this_scope, scope_t const& from_scope + ) -> std::vector<scope_t> { + std::vector<ProvinceDefinition const*> const& region_provinces = region.get_provinces(); + + std::vector<scope_t> region_province_scopes; + region_province_scopes.reserve(region_provinces.size()); + + for (ProvinceDefinition const* province : region_provinces) { + region_province_scopes.push_back( + &instance_manager.get_map_instance().get_province_instance_from_definition(*province) + ); + } + + return region_province_scopes; + } + ) + ); + } + for (ProvinceDefinition const& province : definition_manager.get_map_definition().get_province_definitions()) { ret &= add_condition( province.get_identifier(), @@ -2280,41 +2753,29 @@ Returns true if the country's upper house has the required characteristics } /* Conditions from other registries */ - // import_identifiers( - // definition_manager.get_politics_manager().get_ideology_manager().get_ideology_identifiers(), - // REAL, - // COUNTRY, - // NO_SCOPE, - // IDEOLOGY, - // NO_IDENTIFIER - // ); - - // import_identifiers( - // definition_manager.get_politics_manager().get_issue_manager().get_reform_group_identifiers(), - // IDENTIFIER, - // COUNTRY, - // NO_SCOPE, - // REFORM_GROUP, - // REFORM - // ); - - // import_identifiers( - // definition_manager.get_politics_manager().get_issue_manager().get_reform_identifiers(), - // REAL, - // COUNTRY, - // NO_SCOPE, - // REFORM, - // NO_IDENTIFIER - // ); - - // import_identifiers( - // definition_manager.get_politics_manager().get_issue_manager().get_issue_identifiers(), - // REAL, - // COUNTRY, - // NO_SCOPE, - // ISSUE, - // NO_IDENTIFIER - // ); + for (Ideology const& ideology : definition_manager.get_politics_manager().get_ideology_manager().get_ideologies()) { + ret &= add_condition( + ideology.get_identifier(), + _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, + _execute_condition_node_unimplemented + ); + } + + for (ReformGroup const& reform_group : definition_manager.get_politics_manager().get_issue_manager().get_reform_groups()) { + ret &= add_condition( + reform_group.get_identifier(), + _parse_condition_node_value_callback<Reform const*, COUNTRY>, + _execute_condition_node_unimplemented + ); + } + + for (Reform const& reform : definition_manager.get_politics_manager().get_issue_manager().get_reforms()) { + ret &= add_condition( + reform.get_identifier(), + _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, + _execute_condition_node_unimplemented + ); + } for (IssueGroup const& issue_group : definition_manager.get_politics_manager().get_issue_manager().get_issue_groups()) { ret &= add_condition( @@ -2339,32 +2800,43 @@ Returns true if the country's upper house has the required characteristics ); } - // import_identifiers( - // definition_manager.get_pop_manager().get_pop_type_identifiers(), - // REAL, - // COUNTRY, - // NO_SCOPE, - // POP_TYPE, - // NO_IDENTIFIER - // ); - - // import_identifiers( - // definition_manager.get_research_manager().get_technology_manager().get_technology_identifiers(), - // BOOLEAN_INT, - // COUNTRY, - // NO_SCOPE, - // TECHNOLOGY, - // NO_IDENTIFIER - // ); - - // import_identifiers( - // definition_manager.get_economy_manager().get_good_definition_manager().get_good_definition_identifiers(), - // INTEGER, - // COUNTRY, - // NO_SCOPE, - // TRADE_GOOD, - // NO_IDENTIFIER - // ); + for (Issue const& issue : definition_manager.get_politics_manager().get_issue_manager().get_issues()) { + ret &= add_condition( + issue.get_identifier(), + _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, + _execute_condition_node_unimplemented + ); + } + + for (PopType const& pop_type : definition_manager.get_pop_manager().get_pop_types()) { + ret &= add_condition( + pop_type.get_identifier(), + _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, + _execute_condition_node_unimplemented + ); + } + + for ( + Technology const& technology : definition_manager.get_research_manager().get_technology_manager().get_technologies() + ) { + ret &= add_condition( + technology.get_identifier(), + // TODO - Could convert integer to bool? + _parse_condition_node_value_callback<integer_t, COUNTRY>, + _execute_condition_node_unimplemented + ); + } + + for ( + GoodDefinition const& good : + definition_manager.get_economy_manager().get_good_definition_manager().get_good_definitions() + ) { + ret &= add_condition( + good.get_identifier(), + _parse_condition_node_value_callback<fixed_point_t, COUNTRY>, + _execute_condition_node_unimplemented + ); + } if ( add_condition( diff --git a/src/openvic-simulation/scripts/Condition.hpp b/src/openvic-simulation/scripts/Condition.hpp index 0acdcc3..78d1b6d 100644 --- a/src/openvic-simulation/scripts/Condition.hpp +++ b/src/openvic-simulation/scripts/Condition.hpp @@ -59,12 +59,11 @@ namespace OpenVic { NO_SCOPE = 0, POP = 1 << 0, PROVINCE = 1 << 1, - STATE = 1 << 2, - COUNTRY = 1 << 3, - THIS = 1 << 4, // Indicator bit for scope switching ("use the THIS scope", not a scope in and of itself) - FROM = 1 << 5, // Indicator bit for scope switching ("use the FROM scope", not a scope in and of itself) - FULL_SCOPE_MASK = (1 << 6) - 1, // All possible scope bits (including THIS and FROM) - ALL_SCOPES = POP | PROVINCE | STATE | COUNTRY // All real scopes (without THIS and FROM) + COUNTRY = 1 << 2, + THIS = 1 << 3, // Indicator bit for scope switching ("use the THIS scope", not a scope in and of itself) + FROM = 1 << 4, // Indicator bit for scope switching ("use the FROM scope", not a scope in and of itself) + FULL_SCOPE_MASK = (1 << 5) - 1, // All possible scope bits (including THIS and FROM) + ALL_SCOPES = POP | PROVINCE | COUNTRY // All real scopes (without THIS and FROM) }; /* Allows enum types to be used with bitwise operators. */ @@ -96,10 +95,9 @@ namespace OpenVic { stream << '['; - BUILD_STRING(COUNTRY); - BUILD_STRING(STATE); - BUILD_STRING(PROVINCE); BUILD_STRING(POP); + BUILD_STRING(PROVINCE); + BUILD_STRING(COUNTRY); BUILD_STRING(THIS); BUILD_STRING(FROM); @@ -116,7 +114,6 @@ namespace OpenVic { struct ConditionScript; struct CountryDefinition; struct CountryInstance; - struct State; struct ProvinceDefinition; struct ProvinceInstance; struct Pop; @@ -127,6 +124,7 @@ namespace OpenVic { struct Issue; struct WargoalType; struct PopType; + struct CultureGroup; struct Culture; struct Religion; struct GovernmentType; @@ -135,6 +133,10 @@ namespace OpenVic { struct NationalValue; struct Invention; struct TechnologySchool; + struct Crime; + struct Region; + struct TerrainType; + struct Strata; struct Condition; struct DefinitionManager; struct InstanceManager; @@ -149,20 +151,29 @@ namespace OpenVic { struct no_argument_t {}; struct this_argument_t {}; struct from_argument_t {}; + struct special_argument_t {}; using integer_t = int64_t; using argument_t = std::variant< // No argument no_argument_t, // Script reference arguments this_argument_t, from_argument_t, + // Special argument + special_argument_t, // List argument std::vector<ConditionNode>, // Value arguments bool, std::string, integer_t, fixed_point_t, // Game object arguments CountryDefinition const*, ProvinceDefinition const*, GoodDefinition const*, Continent const*, BuildingType const*, - Issue const*, WargoalType const*, PopType const*, Culture const*, Religion const*, GovernmentType const*, - Ideology const*, Reform const*, NationalValue const*, Invention const*, TechnologySchool const* + Issue const*, WargoalType const*, PopType const*, CultureGroup const*, Culture const*, Religion const*, + GovernmentType const*, Ideology const*, Reform const*, NationalValue const*, Invention const*, + TechnologySchool const*, Crime const*, Region const*, TerrainType const*, Strata const*, + // Multi-value arguments + std::pair<PopType const*, fixed_point_t>, std::pair<bool, bool>, std::pair<Ideology const*, fixed_point_t>, + std::vector<PopType const*>, std::pair<CountryDefinition const*, fixed_point_t>, + std::pair<this_argument_t, fixed_point_t>, std::pair<from_argument_t, fixed_point_t>, + std::pair<std::string, fixed_point_t> >; static constexpr bool is_this_argument(argument_t const& argument) { @@ -173,11 +184,14 @@ namespace OpenVic { return std::holds_alternative<from_argument_t>(argument); } + static constexpr bool is_special_argument(argument_t const& argument) { + return std::holds_alternative<special_argument_t>(argument); + } + struct no_scope_t {}; using scope_t = std::variant< no_scope_t, CountryInstance const*, - State const*, // Should State scope exist, or should it just be a list of provinces? ProvinceInstance const*, Pop const* >; @@ -208,6 +222,8 @@ namespace OpenVic { ) const; }; + std::ostream& operator<<(std::ostream& stream, ConditionNode const& node); + struct Condition : HasIdentifier { friend struct ConditionManager; @@ -279,6 +295,9 @@ namespace OpenVic { bool setup_conditions(DefinitionManager const& definition_manager); + // TODO - way to call with a state as the starting scope (or rather the list of provinces making up a state) + // For: ProductionType bonus trigger, WargoalType allowed_states, allowed_substate_regions and allowed_states_in_crisis + NodeTools::node_callback_t expect_condition_script( DefinitionManager const& definition_manager, scope_type_t initial_scope, scope_type_t this_scope, scope_type_t from_scope, NodeTools::callback_t<ConditionNode&&> callback diff --git a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp index 7752226..bc74d1c 100644 --- a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp +++ b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp @@ -38,6 +38,11 @@ namespace OpenVic { #include "openvic-simulation/types/fixed_point/FixedPointLUT_sin.hpp" static_assert(SIN_LUT_PRECISION == PRECISION); + + // Doesn't account for sign, so -n.abc -> 1 - 0.abc + constexpr fixed_point_t get_frac() const { + return value & FRAC_MASK; + } public: constexpr fixed_point_t() : value { 0 } {} @@ -74,110 +79,22 @@ namespace OpenVic { return 2; } - static constexpr fixed_point_t _3() { - return 3; - } - static constexpr fixed_point_t _4() { return 4; } - static constexpr fixed_point_t _5() { - return 5; - } - - static constexpr fixed_point_t _6() { - return 6; - } - - static constexpr fixed_point_t _7() { - return 7; - } - - static constexpr fixed_point_t _8() { - return 8; - } - - static constexpr fixed_point_t _9() { - return 9; - } - - static constexpr fixed_point_t _10() { - return 10; - } - - static constexpr fixed_point_t _50() { - return 50; - } - static constexpr fixed_point_t _100() { return 100; } - static constexpr fixed_point_t _200() { - return 200; - } - - static constexpr fixed_point_t _0_01() { - return _1() / _100(); - } - - static constexpr fixed_point_t _0_02() { - return _0_01() * 2; - } - - static constexpr fixed_point_t _0_03() { - return _0_01() * 3; - } - - static constexpr fixed_point_t _0_04() { - return _0_01() * 4; - } - - static constexpr fixed_point_t _0_05() { - return _0_01() * 5; - } - - static constexpr fixed_point_t _0_10() { - return _1() / 10; - } - static constexpr fixed_point_t _0_20() { - return _0_10() * 2; - } - - static constexpr fixed_point_t _0_25() { - return _1() / 4; - } - - static constexpr fixed_point_t _0_33() { - return _1() / 3; + return _1() / 5; } static constexpr fixed_point_t _0_50() { return _1() / 2; } - static constexpr fixed_point_t _0_75() { - return _1() - _0_25(); - } - - static constexpr fixed_point_t _0_95() { - return _1() - _0_05(); - } - - static constexpr fixed_point_t _0_99() { - return _1() - _0_01(); - } - - static constexpr fixed_point_t _1_01() { - return _1() + _0_01(); - } - - static constexpr fixed_point_t _1_10() { - return _1() + _0_10(); - } - static constexpr fixed_point_t _1_50() { return _1() + _0_50(); } @@ -253,11 +170,6 @@ namespace OpenVic { : 0; } - // Doesn't account for sign, so -n.abc -> 1 - 0.abc - constexpr fixed_point_t get_frac() const { - return value & FRAC_MASK; - } - constexpr bool is_integer() const { return get_frac() == 0; } |