From 721577e1210c8e9a526b69c77b0bddb098fd5d1e Mon Sep 17 00:00:00 2001 From: hop311 Date: Mon, 18 Mar 2024 19:30:27 +0000 Subject: Add Issue/Reform/Party colours + improve loading --- src/openvic-simulation/politics/Issue.cpp | 133 ++++++++++++++++++++++++------ 1 file changed, 108 insertions(+), 25 deletions(-) (limited to 'src/openvic-simulation/politics/Issue.cpp') diff --git a/src/openvic-simulation/politics/Issue.cpp b/src/openvic-simulation/politics/Issue.cpp index d8fe52e..8e0907a 100644 --- a/src/openvic-simulation/politics/Issue.cpp +++ b/src/openvic-simulation/politics/Issue.cpp @@ -5,9 +5,11 @@ using namespace OpenVic::NodeTools; IssueGroup::IssueGroup(std::string_view new_identifier) : HasIdentifier { new_identifier } {} -Issue::Issue(std::string_view new_identifier, ModifierValue&& new_values, IssueGroup const& new_group, RuleSet&& new_rules, bool new_jingoism) - : Modifier { new_identifier, std::move(new_values), 0 }, group { new_group }, rules { std::move(new_rules) }, - jingoism { new_jingoism } {} +Issue::Issue( + std::string_view new_identifier, colour_t new_colour, ModifierValue&& new_values, IssueGroup const& new_group, + RuleSet&& new_rules, bool new_jingoism +) : HasIdentifierAndColour { new_identifier, new_colour, false }, ModifierValue { std::move(new_values) }, + group { new_group }, rules { std::move(new_rules) }, jingoism { new_jingoism } {} ReformType::ReformType(std::string_view new_identifier, bool new_uncivilised) : HasIdentifier { new_identifier }, uncivilised { new_uncivilised } {} @@ -16,10 +18,10 @@ ReformGroup::ReformGroup(std::string_view new_identifier, ReformType const& new_ : IssueGroup { new_identifier }, type { new_type }, ordered { new_ordered }, administrative { new_administrative } {} Reform::Reform( - std::string_view new_identifier, ModifierValue&& new_values, ReformGroup const& new_group, size_t new_ordinal, - RuleSet&& new_rules, tech_cost_t new_technology_cost, ConditionScript&& new_allow, + std::string_view new_identifier, colour_t new_colour, ModifierValue&& new_values, ReformGroup const& new_group, + size_t new_ordinal, RuleSet&& new_rules, tech_cost_t new_technology_cost, ConditionScript&& new_allow, ConditionScript&& new_on_execute_trigger, EffectScript&& new_on_execute_effect -) : Issue { new_identifier, std::move(new_values), new_group, std::move(new_rules), false }, ordinal { new_ordinal }, +) : Issue { new_identifier, new_colour, std::move(new_values), new_group, std::move(new_rules), false }, ordinal { new_ordinal }, reform_group { new_group }, technology_cost { new_technology_cost }, allow { std::move(new_allow) }, on_execute_trigger { std::move(new_on_execute_trigger) }, on_execute_effect { std::move(new_on_execute_effect) } {} @@ -41,7 +43,8 @@ bool IssueManager::add_issue_group(std::string_view identifier) { } bool IssueManager::add_issue( - std::string_view identifier, ModifierValue&& values, IssueGroup const* group, RuleSet&& rules, bool jingoism + std::string_view identifier, colour_t new_colour, ModifierValue&& values, IssueGroup const* group, RuleSet&& rules, + bool jingoism ) { if (identifier.empty()) { Logger::error("Invalid issue identifier - empty!"); @@ -53,7 +56,7 @@ bool IssueManager::add_issue( return false; } - return issues.add_item({ identifier, std::move(values), *group, std::move(rules), jingoism }); + return issues.add_item({ identifier, new_colour, std::move(values), *group, std::move(rules), jingoism }); } bool IssueManager::add_reform_type(std::string_view identifier, bool uncivilised) { @@ -80,8 +83,8 @@ bool IssueManager::add_reform_group(std::string_view identifier, ReformType cons } bool IssueManager::add_reform( - std::string_view identifier, ModifierValue&& values, ReformGroup const* group, size_t ordinal, RuleSet&& rules, - Reform::tech_cost_t technology_cost, ConditionScript&& allow, ConditionScript&& on_execute_trigger, + std::string_view identifier, colour_t new_colour, ModifierValue&& values, ReformGroup const* group, size_t ordinal, + RuleSet&& rules, Reform::tech_cost_t technology_cost, ConditionScript&& allow, ConditionScript&& on_execute_trigger, EffectScript&& on_execute_effect ) { if (identifier.empty()) { @@ -114,7 +117,7 @@ bool IssueManager::add_reform( } return reforms.add_item({ - identifier, std::move(values), *group, ordinal, std::move(rules), technology_cost, std::move(allow), + identifier, new_colour, std::move(values), *group, ordinal, std::move(rules), technology_cost, std::move(allow), std::move(on_execute_trigger), std::move(on_execute_effect) }); } @@ -124,6 +127,40 @@ bool IssueManager::_load_issue_group(size_t& expected_issues, std::string_view i & add_issue_group(identifier); } +/* Each colour is made up of these components in some order: + * - 0 + * - floor(max_value * 0.99) = 252 + * - floor(max_value * i / 60) = floor(4.25 * i) for some i in [0, 60) */ + +static constexpr colour_t::value_type dim_colour_component = 0; +static constexpr colour_t::value_type bright_colour_component = static_cast(colour_t::max_value) * 99 / 100; + +/* Prime factor to scatter [0, 60) */ +static constexpr size_t scattering_prime = 4057; +static constexpr size_t varying_colour_denominator = 60; + +/* 3! = 3 (choices for 0) * 2 (choices for 252) * 1 (choices for 4.25 * i) */ +static constexpr size_t colour_pattern_period = 6; + +static constexpr std::array dim_colour_indices { 0, 1, 2, 0, 1, 2 }; +static constexpr std::array bright_colour_indices { 1, 2, 0, 2, 0, 1 }; +static constexpr std::array varying_colour_indices { 2, 0, 1, 1, 2, 0 }; + +static constexpr colour_t create_issue_reform_colour(size_t index) { + colour_t ret {}; + + const size_t periodic_index = index % colour_pattern_period; + + ret[dim_colour_indices[periodic_index]] = dim_colour_component; + + ret[bright_colour_indices[periodic_index]] = bright_colour_component; + + ret[varying_colour_indices[periodic_index]] = static_cast(colour_t::max_value) + * ((index * scattering_prime) % varying_colour_denominator) / varying_colour_denominator; + + return ret; +} + bool IssueManager::_load_issue( ModifierManager const& modifier_manager, RuleManager const& rule_manager, std::string_view identifier, IssueGroup const* group, ast::NodeCPtr node @@ -135,7 +172,10 @@ bool IssueManager::_load_issue( "is_jingoism", ZERO_OR_ONE, expect_bool(assign_variable_callback(jingoism)), "rules", ZERO_OR_ONE, rule_manager.expect_rule_set(move_variable_callback(rules)) )(node); - ret &= add_issue(identifier, std::move(values), group, std::move(rules), jingoism); + ret &= add_issue( + identifier, create_issue_reform_colour(get_issue_count() + get_reform_count()), std::move(values), group, + std::move(rules), jingoism + ); return ret; } @@ -173,8 +213,8 @@ bool IssueManager::_load_reform( ) )(node); ret &= add_reform( - identifier, std::move(values), group, ordinal, std::move(rules), technology_cost, std::move(allow), - std::move(on_execute_trigger), std::move(on_execute_effect) + identifier, create_issue_reform_colour(get_issue_count() + get_reform_count()), std::move(values), group, ordinal, + std::move(rules), technology_cost, std::move(allow), std::move(on_execute_trigger), std::move(on_execute_effect) ); return ret; } @@ -188,18 +228,33 @@ bool IssueManager::_load_reform( * POL-99, POL-101, POL-102, POL-103, POL-104, POL-105, POL-107, POL-108, POL-109, POL-110, POL-111, POL-113, * POL-113, POL-114, POL-115, POL-116 */ -bool IssueManager::load_issues_file(ModifierManager const& modifier_manager, RuleManager const& rule_manager, ast::NodeCPtr root) { +bool IssueManager::load_issues_file( + ModifierManager const& modifier_manager, RuleManager const& rule_manager, ast::NodeCPtr root +) { + bool party_issues_found = false; size_t expected_issue_groups = 0; size_t expected_reform_groups = 0; + + /* Reserve space for issue and reform groups and reserve space for and load reform types. */ bool ret = expect_dictionary_reserve_length( reform_types, - [this, &expected_issue_groups, &expected_reform_groups](std::string_view key, ast::NodeCPtr value) -> bool { + [this, &party_issues_found, &expected_issue_groups, &expected_reform_groups]( + std::string_view key, ast::NodeCPtr value + ) -> bool { if (key == "party_issues") { + if (party_issues_found) { + /* Error emitted here allowing later passes to return true with no error message. */ + Logger::error("Duplicate party issues found!"); + return false; + } + party_issues_found = true; + return expect_length(add_variable_callback(expected_issue_groups))(value); } else { static const string_set_t uncivilised_reform_groups { "economic_reforms", "education_reforms", "military_reforms" }; + return expect_length(add_variable_callback(expected_reform_groups))(value) & add_reform_type(key, uncivilised_reform_groups.contains(key)); } @@ -210,16 +265,27 @@ bool IssueManager::load_issues_file(ModifierManager const& modifier_manager, Rul reserve_more_issue_groups(expected_issue_groups); reserve_more_reform_groups(expected_reform_groups); + party_issues_found = false; size_t expected_issues = 0; size_t expected_reforms = 0; + + /* Load issue and reform groups. */ ret &= expect_dictionary( - [this, &expected_issues, &expected_reforms](std::string_view type_key, ast::NodeCPtr type_value) -> bool { + [this, &party_issues_found, &expected_issues, &expected_reforms]( + std::string_view type_key, ast::NodeCPtr type_value + ) -> bool { if (type_key == "party_issues") { + if (party_issues_found) { + return true; /* Error will have been emitted in first pass. */ + } + party_issues_found = true; + return expect_dictionary([this, &expected_issues](std::string_view key, ast::NodeCPtr value) -> bool { return _load_issue_group(expected_issues, key, value); })(type_value); } else { ReformType const* reform_type = get_reform_type_by_identifier(type_key); + return expect_dictionary( [this, reform_type, &expected_reforms](std::string_view key, ast::NodeCPtr value) -> bool { return _load_reform_group(expected_reforms, key, reform_type, value); @@ -234,31 +300,48 @@ bool IssueManager::load_issues_file(ModifierManager const& modifier_manager, Rul reserve_more_issues(expected_issues); reserve_more_reforms(expected_reforms); + party_issues_found = false; + + /* Load issues and reforms. */ ret &= expect_dictionary( - [this, &modifier_manager, &rule_manager](std::string_view type_key, ast::NodeCPtr type_value) -> bool { - return expect_dictionary([this, &modifier_manager, &rule_manager, type_key]( - std::string_view group_key, ast::NodeCPtr group_value - ) -> bool { - if (type_key == "party_issues") { + [this, &party_issues_found, &modifier_manager, &rule_manager]( + std::string_view type_key, ast::NodeCPtr type_value + ) -> bool { + if (type_key == "party_issues") { + if (party_issues_found) { + return true; + } + party_issues_found = true; + + return expect_dictionary([this, &modifier_manager, &rule_manager]( + std::string_view group_key, ast::NodeCPtr group_value + ) -> bool { IssueGroup const* issue_group = get_issue_group_by_identifier(group_key); + return expect_dictionary([this, &modifier_manager, &rule_manager, issue_group]( std::string_view key, ast::NodeCPtr value ) -> bool { return _load_issue(modifier_manager, rule_manager, key, issue_group, value); })(group_value); - } else { + })(type_value); + } else { + return expect_dictionary([this, &party_issues_found, &modifier_manager, &rule_manager]( + std::string_view group_key, ast::NodeCPtr group_value + ) -> bool { ReformGroup const* reform_group = get_reform_group_by_identifier(group_key); size_t ordinal = 0; + return expect_dictionary([this, &modifier_manager, &rule_manager, reform_group, &ordinal]( std::string_view key, ast::NodeCPtr value ) -> bool { if (key == "next_step_only" || key == "administrative") { return true; } + return _load_reform(modifier_manager, rule_manager, ordinal++, key, reform_group, value); })(group_value); - } - })(type_value); + })(type_value); + } } )(root); lock_issues(); -- cgit v1.2.3-56-ga3b1