aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation')
-rw-r--r--src/openvic-simulation/GameManager.hpp11
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp10
-rw-r--r--src/openvic-simulation/politics/Ideology.cpp100
-rw-r--r--src/openvic-simulation/politics/Ideology.hpp55
-rw-r--r--src/openvic-simulation/politics/Issue.cpp145
-rw-r--r--src/openvic-simulation/politics/Issue.hpp89
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