From 08eb9c4b73f94296479ec498a7c0bf6bf18f6144 Mon Sep 17 00:00:00 2001 From: zaaarf Date: Sat, 23 Sep 2023 15:01:36 +0200 Subject: feat: separated once more Issue and Reform --- src/openvic-simulation/politics/Issue.cpp | 171 +++++++++++++++++++++--------- src/openvic-simulation/politics/Issue.hpp | 112 ++++++++++++------- 2 files changed, 194 insertions(+), 89 deletions(-) diff --git a/src/openvic-simulation/politics/Issue.cpp b/src/openvic-simulation/politics/Issue.cpp index 8ee01ea..926eade 100644 --- a/src/openvic-simulation/politics/Issue.cpp +++ b/src/openvic-simulation/politics/Issue.cpp @@ -3,50 +3,84 @@ using namespace OpenVic; using namespace OpenVic::NodeTools; -IssueType::IssueType(const std::string_view new_identifier) : HasIdentifier { new_identifier } {} +IssueGroup::IssueGroup(const std::string_view new_identifier) : HasIdentifier { new_identifier } {} -IssueGroup::IssueGroup(const std::string_view new_identifier, IssueType const& new_type, bool new_ordered, bool new_administrative) - : HasIdentifier { new_identifier }, type { new_type }, ordered { new_ordered }, administrative { new_administrative } {} +Issue::Issue(const std::string_view identifier, IssueGroup const& group) + : HasIdentifier { identifier }, group { group } {} -IssueType const& IssueGroup::get_type() const { +IssueGroup const& Issue::get_group() const { + return group; +} + +ReformType::ReformType(const std::string_view new_identifier, bool uncivilised) + : HasIdentifier { new_identifier }, uncivilised { uncivilised } {} + +ReformGroup::ReformGroup(const std::string_view identifier, ReformType const& type, bool ordered, bool administrative) + : IssueGroup { identifier }, type { type }, ordered { ordered }, administrative { administrative } {} + +ReformType const& ReformGroup::get_type() const { return type; } -bool IssueGroup::is_ordered() const { +bool ReformGroup::is_ordered() const { return ordered; } -bool IssueGroup::is_administrative() const { +bool ReformGroup::is_administrative() const { return administrative; } -Issue::Issue(const std::string_view new_identifier, IssueGroup const& new_group, size_t ordinal) - : HasIdentifier { new_identifier }, group { new_group }, ordinal { ordinal } {} +Reform::Reform(const std::string_view identifier, ReformGroup const& group, size_t ordinal) + : Issue { identifier, group }, ordinal { ordinal }, reform_group { group } {} -IssueType const& Issue::get_type() const { - return group.get_type(); +ReformGroup const& Reform::get_reform_group() const { + return reform_group; } -IssueGroup const& Issue::get_group() const { - return group; +ReformType const& Reform::get_type() const { + return get_reform_group().get_type(); } -size_t Issue::get_ordinal() const { +size_t Reform::get_ordinal() const { return ordinal; } -IssueManager::IssueManager() : issue_types { "issue types" }, issue_groups { "issue groups" }, issues { "issues" } {} +IssueManager::IssueManager() : issue_groups { "issue groups" }, issues { "issues" }, + reform_types { "reform types" }, reform_groups { "reform groups" }, reforms { "reforms" } {} + +bool IssueManager::add_issue_group(const std::string_view identifier) { + if (identifier.empty()) { + Logger::error("Invalid issue group identifier - empty!"); + return false; + } -bool IssueManager::add_issue_type(const std::string_view identifier) { + return issue_groups.add_item({ identifier }); +} + +bool IssueManager::add_issue(const std::string_view identifier, IssueGroup const* group) { + if (identifier.empty()) { + Logger::error("Invalid issue identifier - empty!"); + return false; + } + + if (group == nullptr) { + Logger::error("Null issue group for ", identifier); + return false; + } + + return issues.add_item({ identifier, *group }); +} + +bool IssueManager::add_reform_type(const std::string_view identifier, bool uncivilised) { if (identifier.empty()) { Logger::error("Invalid issue type identifier - empty!"); return false; } - return issue_types.add_item({ identifier }); + return reform_types.add_item({ identifier, uncivilised }); } -bool IssueManager::add_issue_group(const std::string_view identifier, IssueType const* type, bool ordered, bool administrative) { +bool IssueManager::add_reform_group(const std::string_view identifier, ReformType const* type, bool ordered, bool administrative) { if (identifier.empty()) { Logger::error("Invalid issue group identifier - empty!"); return false; @@ -57,10 +91,10 @@ bool IssueManager::add_issue_group(const std::string_view identifier, IssueType return false; } - return issue_groups.add_item({ identifier, *type, ordered, administrative }); + return reform_groups.add_item({ identifier, *type, ordered, administrative }); } -bool IssueManager::add_issue(const std::string_view identifier, IssueGroup const* group, size_t ordinal) { +bool IssueManager::add_reform(const std::string_view identifier, ReformGroup const* group, size_t ordinal) { if (identifier.empty()) { Logger::error("Invalid issue identifier - empty!"); return false; @@ -71,26 +105,38 @@ bool IssueManager::add_issue(const std::string_view identifier, IssueGroup const return false; } - return issues.add_item({ identifier, *group, ordinal }); + return reforms.add_item({ identifier, *group, ordinal }); } -bool IssueManager::_load_issue_group(size_t& expected_issues, const std::string_view identifier, IssueType const* type, ast::NodeCPtr node) { +bool IssueManager::_load_issue_group(size_t& expected_issues, const std::string_view identifier, ast::NodeCPtr node) { + return expect_length([&expected_issues](size_t size) -> size_t { + expected_issues += size; + return size; + })(node) & add_issue_group(identifier); +} + +bool IssueManager::_load_issue(const std::string_view identifier, IssueGroup const* group, ast::NodeCPtr node) { + //TODO: policy modifiers, policy rule changes + return add_issue(identifier, group); +} + +bool IssueManager::_load_reform_group(size_t& expected_reforms, const std::string_view identifier, ReformType const* type, ast::NodeCPtr node) { bool ordered = false, administrative = false; bool ret = expect_dictionary_keys_and_length( - [&expected_issues](size_t size) -> size_t { - expected_issues += size; + [&expected_reforms](size_t size) -> size_t { + expected_reforms += size; return size; }, ALLOW_OTHER_KEYS, - "next_step_only", ZERO_OR_ONE, decrement_callback(expected_issues, expect_bool(assign_variable_callback(ordered))), - "administrative", ZERO_OR_ONE, decrement_callback(expected_issues, expect_bool(assign_variable_callback(administrative))) + "next_step_only", ZERO_OR_ONE, decrement_callback(expected_reforms, expect_bool(assign_variable_callback(ordered))), + "administrative", ZERO_OR_ONE, decrement_callback(expected_reforms, expect_bool(assign_variable_callback(administrative))) )(node); - ret &= add_issue_group(identifier, type, ordered, administrative); + ret &= add_reform_group(identifier, type, ordered, administrative); return ret; } -bool IssueManager::_load_issue(size_t& ordinal, const std::string_view identifier, IssueGroup const* group, ast::NodeCPtr node) { +bool IssueManager::_load_reform(size_t& ordinal, const std::string_view identifier, ReformGroup const* group, ast::NodeCPtr node) { //TODO: conditions to allow, policy modifiers, policy rule changes - return add_issue(identifier, group, ordinal); + return add_reform(identifier, group, ordinal); } /* REQUIREMENTS: @@ -104,43 +150,66 @@ bool IssueManager::_load_issue(size_t& ordinal, const std::string_view identifie */ bool IssueManager::load_issues_file(ast::NodeCPtr root) { size_t expected_issue_groups = 0; - bool ret = expect_dictionary_reserve_length(issue_types, - [this, &expected_issue_groups](std::string_view key, ast::NodeCPtr value) -> bool { - bool ret = expect_length(add_variable_callback(expected_issue_groups))(value); - ret &= add_issue_type(key); - return ret; + size_t expected_reform_groups = 0; + bool ret = expect_dictionary_reserve_length(reform_types, + [this, &expected_issue_groups, &expected_reform_groups](std::string_view key, ast::NodeCPtr value) -> bool { + if (key == "party_issues") + return expect_length(add_variable_callback(expected_issue_groups))(value); + else return expect_length(add_variable_callback(expected_reform_groups))(value) & add_reform_type( + key, key == "economic_reforms" || "education_reforms" || "military_reforms"); } )(root); - lock_issue_types(); + lock_reform_types(); - size_t expected_issues = 0; issue_groups.reserve(issue_groups.size() + expected_issue_groups); + reform_groups.reserve(reform_groups.size() + expected_reform_groups); + + size_t expected_issues = 0; + size_t expected_reforms = 0; ret &= expect_dictionary_reserve_length(issue_groups, - [this, &expected_issues](std::string_view type_key, ast::NodeCPtr type_value) -> bool { - IssueType const* issue_type = get_issue_type_by_identifier(type_key); - return expect_dictionary( - [this, issue_type, &expected_issues](std::string_view key, ast::NodeCPtr value) -> bool { - return _load_issue_group(expected_issues, key, issue_type, value); - } - )(type_value); + [this, &expected_issues, &expected_reforms](std::string_view type_key, ast::NodeCPtr type_value) -> bool { + if (type_key == "party_issues") { + 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); + } + )(type_value); + } } )(root); lock_issue_groups(); + lock_reform_groups(); issues.reserve(issues.size() + expected_issues); + reforms.reserve(reforms.size() + expected_reforms); + ret &= expect_dictionary([this](std::string_view type_key, ast::NodeCPtr type_value) -> bool { - return expect_dictionary([this](std::string_view group_key, ast::NodeCPtr group_value) -> bool { - IssueGroup const* issue_group = get_issue_group_by_identifier(group_key); - size_t ordinal = 0; - return expect_dictionary([this, issue_group, &ordinal](std::string_view key, ast::NodeCPtr value) -> bool { - if (key == "next_step_only" || key == "administrative") return true; - bool ret = _load_issue(ordinal, key, issue_group, value); - ordinal++; - return ret; - })(group_value); + return expect_dictionary([this, type_key](std::string_view group_key, ast::NodeCPtr group_value) -> bool { + if (type_key == "party_issues") { + IssueGroup const* issue_group = get_issue_group_by_identifier(group_key); + return expect_dictionary([this, issue_group](std::string_view key, ast::NodeCPtr value) -> bool { + bool ret = _load_issue(key, issue_group, value); + return ret; + })(group_value); + } else { + ReformGroup const* reform_group = get_reform_group_by_identifier(group_key); + size_t ordinal = 0; + return expect_dictionary([this, reform_group, &ordinal](std::string_view key, ast::NodeCPtr value) -> bool { + if (key == "next_step_only" || key == "administrative") return true; + bool ret = _load_reform(ordinal, key, reform_group, value); + ordinal++; + return ret; + })(group_value); + } })(type_value); })(root); lock_issues(); + lock_reforms(); return ret; } \ No newline at end of file diff --git a/src/openvic-simulation/politics/Issue.hpp b/src/openvic-simulation/politics/Issue.hpp index f002f45..4b096ee 100644 --- a/src/openvic-simulation/politics/Issue.hpp +++ b/src/openvic-simulation/politics/Issue.hpp @@ -2,89 +2,125 @@ #include #include -#include "types/IdentifierRegistry.hpp" -#include "dataloader/NodeTools.hpp" +#include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/dataloader/NodeTools.hpp" +#include "openvic-dataloader/v2script/AbstractSyntaxTree.hpp" namespace OpenVic { struct IssueManager; - //Issue type (i.e. political_issues) - struct IssueType : HasIdentifier { + //Issue group (i.e. trade_policy) + struct IssueGroup : HasIdentifier { + friend struct IssueManager; + + protected: + IssueGroup(const std::string_view identifier); + + public: + IssueGroup(IssueGroup&&) = default; + }; + + //Issue (i.e. protectionism) + struct Issue : HasIdentifier { + friend struct IssueManager; + + private: + IssueGroup const& group; + + //TODO: policy modifiers, policy rule changes + + protected: + Issue(const std::string_view identifier, IssueGroup const& group); + + public: + Issue(Issue&&) = default; + IssueGroup const& get_group() const; + }; + + //Reform type (i.e. political_issues) + struct ReformType : HasIdentifier { friend struct IssueManager; private: - IssueType(const std::string_view new_identifier); + bool uncivilised; //whether this group is available to non-westernised countries + //in vanilla education, military and economic reforms are hardcoded to true and the rest to false + + ReformType(const std::string_view new_identifier, bool uncivilised); public: - IssueType(IssueType&&) = default; + ReformType(ReformType&&) = default; }; - //Issue group (i.e. slavery) - struct IssueGroup : HasIdentifier { + //Reform group (i.e. slavery) + struct ReformGroup : IssueGroup { friend struct IssueManager; private: - IssueType const& type; - const bool ordered, administrative; + ReformType const& type; + const bool ordered; //next_step_only + const bool administrative; - IssueGroup(const std::string_view new_identifier, IssueType const& new_type, bool new_ordered, bool new_administrative); + ReformGroup(const std::string_view identifier, ReformType const& type, bool ordered, bool administrative); public: - IssueGroup(IssueGroup&&) = default; - IssueType const& get_type() const; + ReformGroup(ReformGroup&&) = default; + ReformType const& get_type() const; bool is_ordered() const; bool is_administrative() const; }; - //Issue type (i.e. yes_slavery) - struct Issue : HasIdentifier { + //Reform (i.e. yes_slavery) + struct Reform : Issue { friend struct IssueManager; private: - IssueGroup const& group; + ReformGroup const& reform_group; //stores an already casted reference const size_t ordinal; //assigned by the parser to allow policy sorting - //TODO: conditions to allow, policy modifiers, policy rule changes + Reform(const std::string_view new_identifier, ReformGroup const& group, size_t ordinal); - Issue(const std::string_view new_identifier, IssueGroup const& new_group, size_t ordinal); + //TODO: conditions to allow, public: - Issue(Issue&&) = default; - IssueType const& get_type() const; - IssueGroup const& get_group() const; + Reform(Reform&&) = default; + ReformGroup const& get_reform_group() const; + ReformType const& get_type() const; size_t get_ordinal() const; }; //Issue manager - holds the registries struct IssueManager { private: - IdentifierRegistry issue_types; IdentifierRegistry issue_groups; IdentifierRegistry issues; + IdentifierRegistry reform_types; + IdentifierRegistry reform_groups; + IdentifierRegistry reforms; - bool _load_issue_group(size_t& expected_issues, const std::string_view identifier, IssueType const* type, ast::NodeCPtr node); - bool _load_issue(size_t& ordinal, const std::string_view identifier, IssueGroup const* group, ast::NodeCPtr node); + bool _load_issue_group(size_t& expected_issues, const std::string_view identifier, ast::NodeCPtr node); + bool _load_issue(const std::string_view identifier, IssueGroup const* group, ast::NodeCPtr node); + bool _load_reform_group(size_t& expected_reforms, const std::string_view identifier, ReformType const* type, + ast::NodeCPtr node); + bool _load_reform(size_t& ordinal, const std::string_view identifier, ReformGroup const* group, ast::NodeCPtr node); public: IssueManager(); - - bool add_issue_type(const std::string_view identifier); - IDENTIFIER_REGISTRY_ACCESSORS(IssueType, issue_type) - bool add_issue_group(const std::string_view identifier, IssueType const* type, bool ordered, bool administrative); + bool add_issue_group(const std::string_view identifier); IDENTIFIER_REGISTRY_ACCESSORS(IssueGroup, issue_group) - bool add_issue(const std::string_view identifier, IssueGroup const* group, size_t ordinal); + bool add_issue(const std::string_view identifier, IssueGroup const* group); IDENTIFIER_REGISTRY_ACCESSORS(Issue, issue) + bool add_reform_type(const std::string_view identifier, bool uncivilised); + IDENTIFIER_REGISTRY_ACCESSORS(ReformType, reform_type) + + bool add_reform_group(const std::string_view identifier, ReformType const* type, bool ordered, bool administrative); + IDENTIFIER_REGISTRY_ACCESSORS(ReformGroup, reform_group) + + bool add_reform(const std::string_view identifier, ReformGroup const* group, size_t ordinal); + IDENTIFIER_REGISTRY_ACCESSORS(Reform, reform) + bool load_issues_file(ast::NodeCPtr root); }; -} - -/* A NOTE ON PARTY ISSUES - * It's worth noting that party_issues is a special type of issue, of similar structure but used in a different - * way. Party issues can never have an "allow" condition and are always unordered. Even if a mod was to specify - * those clauses, OV2's behaviour should be to simply disregard them, as they are meaningless to the context of - * party issues. - * Conversely, every attempt to read the list of reform types should skip over "party_issues". -*/ \ No newline at end of file +} \ No newline at end of file -- cgit v1.2.3-56-ga3b1