diff options
Diffstat (limited to 'src/openvic-simulation')
-rw-r--r-- | src/openvic-simulation/GameManager.hpp | 11 | ||||
-rw-r--r-- | src/openvic-simulation/dataloader/Dataloader.cpp | 10 | ||||
-rw-r--r-- | src/openvic-simulation/politics/Ideology.cpp | 100 | ||||
-rw-r--r-- | src/openvic-simulation/politics/Ideology.hpp | 55 | ||||
-rw-r--r-- | src/openvic-simulation/politics/Issue.cpp | 145 | ||||
-rw-r--r-- | src/openvic-simulation/politics/Issue.hpp | 89 |
6 files changed, 407 insertions, 3 deletions
diff --git a/src/openvic-simulation/GameManager.hpp b/src/openvic-simulation/GameManager.hpp index d221a99..70d8cf0 100644 --- a/src/openvic-simulation/GameManager.hpp +++ b/src/openvic-simulation/GameManager.hpp @@ -1,8 +1,10 @@ #pragma once -#include "openvic-simulation/GameAdvancementHook.hpp" -#include "openvic-simulation/economy/Good.hpp" -#include "openvic-simulation/map/Map.hpp" +#include "GameAdvancementHook.hpp" +#include "economy/Good.hpp" +#include "map/Map.hpp" +#include "politics/Ideology.hpp" +#include "politics/Issue.hpp" namespace OpenVic { struct GameManager { @@ -12,6 +14,9 @@ namespace OpenVic { BuildingManager building_manager; GoodManager good_manager; PopManager pop_manager; + IdeologyManager ideology_manager; + IssueManager issue_manager; + GameAdvancementHook clock; private: diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index a30983b..d0d9506 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -257,6 +257,8 @@ bool Dataloader::load_defines(GameManager& game_manager) const { static const fs::path graphical_culture_type_file = "common/graphicalculturetype.txt"; static const fs::path culture_file = "common/cultures.txt"; static const fs::path religion_file = "common/religion.txt"; + static const fs::path ideology_file = "common/ideologies.txt"; + static const fs::path issues_file = "common/issues.txt"; static const fs::path map_directory = "map"; bool ret = true; @@ -281,6 +283,14 @@ bool Dataloader::load_defines(GameManager& game_manager) const { Logger::error("Failed to load religions!"); ret = false; } + if (!game_manager.ideology_manager.load_ideology_file(_parse_defines(lookup_file(ideology_file)).get_file_node())) { + Logger::error("Failed to load ideologies!"); + ret = false; + } + if (!game_manager.issue_manager.load_issues_file(_parse_defines(lookup_file(issues_file)).get_file_node())) { + Logger::error("Failed to load issues!"); + ret = false; + } if (!_load_map_dir(game_manager, map_directory)) { Logger::error("Failed to load map!"); ret = false; diff --git a/src/openvic-simulation/politics/Ideology.cpp b/src/openvic-simulation/politics/Ideology.cpp new file mode 100644 index 0000000..43adfaa --- /dev/null +++ b/src/openvic-simulation/politics/Ideology.cpp @@ -0,0 +1,100 @@ +#include "Ideology.hpp" + +using namespace OpenVic; +using namespace OpenVic::NodeTools; + +IdeologyGroup::IdeologyGroup(const std::string_view new_identifier) : HasIdentifier { new_identifier } {} + +Ideology::Ideology(const std::string_view new_identifier, colour_t new_colour, IdeologyGroup const& new_group, bool uncivilised, Date spawn_date) + : HasIdentifierAndColour { new_identifier, new_colour, true, false }, group { new_group }, uncivilised { uncivilised }, + spawn_date { spawn_date } {} + +IdeologyGroup const& Ideology::get_group() const { + return group; +} + +bool Ideology::is_uncivilised() const { + return uncivilised; +} + +Date const& Ideology::get_spawn_date() const { + return spawn_date; +} + +IdeologyManager::IdeologyManager() : ideology_groups { "ideology groups" }, ideologies { "ideologies" } {} + +bool IdeologyManager::add_ideology_group(const std::string_view identifier) { + if (identifier.empty()) { + Logger::error("Invalid ideology group identifier - empty!"); + return false; + } + + return ideology_groups.add_item({ identifier }); +} + +bool IdeologyManager::add_ideology(const std::string_view identifier, colour_t colour, IdeologyGroup const* group, bool uncivilised, Date spawn_date) { + if (identifier.empty()) { + Logger::error("Invalid ideology identifier - empty!"); + return false; + } + + if (colour > MAX_COLOUR_RGB) { + Logger::error("Invalid ideology colour for ", identifier, ": ", colour_to_hex_string(colour)); + return false; + } + + if (group == nullptr) { + Logger::error("Null ideology group for ", identifier); + return false; + } + + return ideologies.add_item({ identifier, colour, *group, uncivilised, spawn_date }); +} + +/* REQUIREMENTS: + * POL-9, POL-10, POL-11, POL-12, POL-13, POL-14, POL-15 +*/ +bool IdeologyManager::load_ideology_file(ast::NodeCPtr root) { + size_t expected_ideologies = 0; + bool ret = expect_dictionary_reserve_length( + ideology_groups, + [this, &expected_ideologies](std::string_view key, ast::NodeCPtr value) -> bool { + bool ret = expect_list_and_length( + [&expected_ideologies](size_t size) -> size_t { + expected_ideologies += size; + return 0; + }, + success_callback + )(value); + ret &= add_ideology_group(key); + return ret; + } + )(root); + lock_ideology_groups(); + + ideologies.reserve(ideologies.size() + expected_ideologies); + ret &= expect_dictionary( + [this](std::string_view ideology_group_key, ast::NodeCPtr ideology_group_value) -> bool { + IdeologyGroup const* ideology_group = get_ideology_group_by_identifier(ideology_group_key); + + return expect_dictionary( + [this, ideology_group](std::string_view key, ast::NodeCPtr value) -> bool { + colour_t colour = NULL_COLOUR; + bool uncivilised = true; + Date spawn_date; + + bool ret = expect_dictionary_keys( + "uncivilized", ZERO_OR_ONE, expect_bool(assign_variable_callback(uncivilised)), + "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), + "date", ZERO_OR_ONE, expect_date(assign_variable_callback(spawn_date)) + )(value); + ret &= add_ideology(key, colour, ideology_group, uncivilised, spawn_date); + return ret; + } + )(ideology_group_value); + } + )(root); + lock_ideologies(); + + return ret; +}
\ No newline at end of file diff --git a/src/openvic-simulation/politics/Ideology.hpp b/src/openvic-simulation/politics/Ideology.hpp new file mode 100644 index 0000000..b72c176 --- /dev/null +++ b/src/openvic-simulation/politics/Ideology.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include "types/Date.hpp" +#include "types/IdentifierRegistry.hpp" +#include "dataloader/NodeTools.hpp" + +namespace OpenVic { + struct IdeologyManager; + + struct IdeologyGroup : HasIdentifier { + friend struct IdeologyManager; + + private: + IdeologyGroup(const std::string_view new_identifier); + + public: + IdeologyGroup(IdeologyGroup&&) = default; + }; + + struct Ideology : HasIdentifierAndColour { + friend struct IdeologyManager; + + private: + IdeologyGroup const& group; + const bool uncivilised; + const Date spawn_date; + + //TODO - willingness to repeal/pass reforms (and its modifiers) + + Ideology(const std::string_view new_identifier, colour_t new_colour, IdeologyGroup const& new_group, bool uncivilised, Date spawn_date); + + public: + Ideology(Ideology&&) = default; + IdeologyGroup const& get_group() const; + bool is_uncivilised() const; + Date const& get_spawn_date() const; + }; + + struct IdeologyManager { + private: + IdentifierRegistry<IdeologyGroup> ideology_groups; + IdentifierRegistry<Ideology> ideologies; + + public: + IdeologyManager(); + + bool add_ideology_group(const std::string_view identifier); + IDENTIFIER_REGISTRY_ACCESSORS(IdeologyGroup, ideology_group) + + bool add_ideology(const std::string_view identifier, colour_t colour, IdeologyGroup const* group, bool uncivilised, Date spawn_date); + IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(Ideology, ideology, ideologies) + + bool load_ideology_file(ast::NodeCPtr root); + }; +}
\ No newline at end of file diff --git a/src/openvic-simulation/politics/Issue.cpp b/src/openvic-simulation/politics/Issue.cpp new file mode 100644 index 0000000..b11b8a0 --- /dev/null +++ b/src/openvic-simulation/politics/Issue.cpp @@ -0,0 +1,145 @@ +#include "Issue.hpp" + +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, IssueType const& new_type, bool ordered) + : HasIdentifier { new_identifier }, type { new_type }, ordered { ordered } {} + +IssueType const& IssueGroup::get_type() const { + return type; +} + +bool IssueGroup::is_ordered() const { + return ordered; +} + +Issue::Issue(const std::string_view new_identifier, IssueGroup const& new_group, size_t ordinal) + : HasIdentifier { new_identifier }, group { new_group }, ordinal { ordinal } {} + +IssueType const& Issue::get_type() const { + return group.get_type(); +} + +IssueGroup const& Issue::get_group() const { + return group; +} + +size_t Issue::get_ordinal() const { + return ordinal; +} + +IssueManager::IssueManager() : issue_types { "issue types" }, issue_groups { "issue groups" }, issues { "issues" } {} + +bool IssueManager::add_issue_type(const std::string_view identifier) { + if (identifier.empty()) { + Logger::error("Invalid issue type identifier - empty!"); + return false; + } + + return issue_types.add_item({ identifier }); +} + +bool IssueManager::add_issue_group(const std::string_view identifier, IssueType const* type, bool ordered) { + if (identifier.empty()) { + Logger::error("Invalid issue group identifier - empty!"); + return false; + } + + if (type == nullptr) { + Logger::error("Null issue type for ", identifier); + return false; + } + + return issue_groups.add_item({ identifier, *type, ordered }); +} + +bool IssueManager::add_issue(const std::string_view identifier, IssueGroup const* group, size_t ordinal) { + 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, ordinal }); +} + +bool IssueManager::_load_issue_group(size_t& expected_issues, const std::string_view identifier, IssueType const* type, ast::NodeCPtr node) { + bool ordered = false; + return expect_dictionary_keys_and_length( + [&expected_issues](size_t size) -> size_t { + expected_issues += size; + return size; + }, ALLOW_OTHER_KEYS, + "next_step_only", ONE_EXACTLY, [&expected_issues, &ordered](ast::NodeCPtr node) -> bool { + expected_issues--; + return expect_bool(assign_variable_callback(ordered))(node); + } + )(node) && add_issue_group(identifier, type, ordered); +} + +bool IssueManager::_load_issue(size_t& ordinal, const std::string_view identifier, IssueGroup const* group, ast::NodeCPtr node) { + //TODO: conditions to allow, policy modifiers, policy rule changes + return add_issue(identifier, group, ordinal); +} + +/* REQUIREMENTS: + * POL-18, POL-19, POL-21, POL-22, POL-23, POL-24, POL-26, POL-27, POL-28, POL-29, POL-31, POL-32, POL-33, + * POL-35, POL-36, POL-37, POL-38, POL-40, POL-41, POL-43, POL-44, POL-45, POL-46, POL-48, POL-49, POL-50, + * POL-51, POL-52, POL-53, POL-55, POL-56, POL-57, POL-59, POL-60, POL-62, POL-63, POL-64, POL-66, POL-67, + * POL-68, POL-69, POL-71, POL-72, POL-73, POL-74, POL-75, POL-77, POL-78, POL-79, POL-80, POL-81, POL-83, + * POL-84, POL-85, POL-86, POL-87, POL-89, POL-90, POL-91, POL-92, POL-93, POL-95, POL-96, POL-97, POL-98, + * 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(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 { + return expect_list_and_length( + [&expected_issue_groups](size_t size) -> size_t { + expected_issue_groups += size; + return 0; + }, success_callback + )(value) && add_issue_type(key); + } + )(root); + lock_issue_types(); + + size_t expected_issues = 0; + issue_groups.reserve(issue_groups.size() + expected_issue_groups); + 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); + } + )(root); + lock_issue_groups(); + + issues.reserve(issues.size() + expected_issues); + 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") return true; + bool ret = _load_issue(ordinal, key, issue_group, value); + ordinal++; + return ret; + })(group_value); + })(type_value); + })(root); + lock_issues(); + + return ret; +}
\ No newline at end of file diff --git a/src/openvic-simulation/politics/Issue.hpp b/src/openvic-simulation/politics/Issue.hpp new file mode 100644 index 0000000..546b3ea --- /dev/null +++ b/src/openvic-simulation/politics/Issue.hpp @@ -0,0 +1,89 @@ +#pragma once + +#include <cstddef> +#include <string_view> +#include "types/IdentifierRegistry.hpp" +#include "dataloader/NodeTools.hpp" + +namespace OpenVic { + struct IssueManager; + + //Issue type (i.e. political_issues) + struct IssueType : HasIdentifier { + friend struct IssueManager; + + private: + IssueType(const std::string_view new_identifier); + + public: + IssueType(IssueType&&) = default; + }; + + //Issue group (i.e. slavery) + struct IssueGroup : HasIdentifier { + friend struct IssueManager; + + private: + IssueType const& type; + const bool ordered; + + IssueGroup(const std::string_view new_identifier, IssueType const& new_type, bool ordered); + + public: + IssueGroup(IssueGroup&&) = default; + IssueType const& get_type() const; + bool is_ordered() const; + }; + + //Issue type (i.e. yes_slavery) + struct Issue : HasIdentifier { + friend struct IssueManager; + + private: + IssueGroup const& group; + const size_t ordinal; //assigned by the parser to allow policy sorting + + //TODO: conditions to allow, policy modifiers, policy rule changes + + Issue(const std::string_view new_identifier, IssueGroup const& new_group, size_t ordinal); + + public: + Issue(Issue&&) = default; + IssueType const& get_type() const; + IssueGroup const& get_group() const; + size_t get_ordinal() const; + }; + + //Issue manager - holds the registries + struct IssueManager { + private: + IdentifierRegistry<IssueType> issue_types; + IdentifierRegistry<IssueGroup> issue_groups; + IdentifierRegistry<Issue> issues; + + 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); + + 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); + IDENTIFIER_REGISTRY_ACCESSORS(IssueGroup, issue_group) + + bool add_issue(const std::string_view identifier, IssueGroup const* group, size_t ordinal); + IDENTIFIER_REGISTRY_ACCESSORS(Issue, issue) + + 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 |