aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/country
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation/country')
-rw-r--r--src/openvic-simulation/country/Country.cpp296
-rw-r--r--src/openvic-simulation/country/Country.hpp89
2 files changed, 216 insertions, 169 deletions
diff --git a/src/openvic-simulation/country/Country.cpp b/src/openvic-simulation/country/Country.cpp
index fc867d3..6ad13ee 100644
--- a/src/openvic-simulation/country/Country.cpp
+++ b/src/openvic-simulation/country/Country.cpp
@@ -21,180 +21,222 @@
using namespace OpenVic;
using namespace OpenVic::NodeTools;
-std::string_view CountryParty::get_name() const {
- return name;
-}
+CountryParty::CountryParty(
+ std::string_view new_identifier, Date new_start_date, Date new_end_date, Ideology const& new_ideology,
+ policy_map_t&& new_policies
+) : HasIdentifier { new_identifier }, start_date { new_start_date }, end_date { new_end_date }, ideology { new_ideology },
+ policies { std::move(new_policies) } {}
-const Date& CountryParty::get_start_date() const {
+Date CountryParty::get_start_date() const {
return start_date;
}
-const Date& CountryParty::get_end_date() const {
+Date CountryParty::get_end_date() const {
return end_date;
}
-const Ideology& CountryParty::get_ideology() const {
+Ideology const& CountryParty::get_ideology() const {
return ideology;
}
-const std::vector<const Issue*>& CountryParty::get_policies() const {
+CountryParty::policy_map_t const& CountryParty::get_policies() const {
return policies;
}
-CountryParty::CountryParty(
- std::string_view new_name, Date new_start_date, Date new_end_date, const Ideology& new_ideology,
- std::vector<const Issue*>&& new_policies
-) : name { new_name }, start_date { new_start_date }, end_date { new_end_date }, ideology { new_ideology },
- policies { std::move(new_policies) } {}
-
-std::string_view UnitNames::get_identifier() const {
- return identifier;
-}
-
-const std::vector<std::string>& UnitNames::get_names() const {
- return names;
-}
-
-UnitNames::UnitNames(std::string_view new_identifier, std::vector<std::string>&& new_names)
- : identifier { new_identifier }, names { std::move(new_names) } {}
+Country::Country(
+ std::string_view new_identifier, colour_t new_colour, GraphicalCultureType const& new_graphical_culture,
+ IdentifierRegistry<CountryParty>&& new_parties, unit_names_map_t&& new_unit_names, bool new_dynamic_tag,
+ government_colour_map_t&& new_alternative_colours
+) : HasIdentifierAndColour { new_identifier, new_colour, false, false }, graphical_culture { new_graphical_culture },
+ parties { std::move(new_parties) }, unit_names { std::move(new_unit_names) }, dynamic_tag { new_dynamic_tag },
+ alternative_colours { std::move(new_alternative_colours) } {}
-const GraphicalCultureType& Country::get_graphical_culture() const {
+GraphicalCultureType const& Country::get_graphical_culture() const {
return graphical_culture;
}
-const std::vector<CountryParty>& Country::get_parties() const {
- return parties;
-}
-
-const std::vector<UnitNames>& Country::get_unit_names() const {
+Country::unit_names_map_t const& Country::get_unit_names() const {
return unit_names;
}
-const std::map<const GovernmentType*, colour_t>& Country::get_alternative_colours() const {
- return alternative_colours;
-}
-
-const bool Country::is_dynamic_tag() const {
+bool Country::is_dynamic_tag() const {
return dynamic_tag;
}
-Country::Country(
- std::string_view new_identifier, colour_t new_color, const GraphicalCultureType& new_graphical_culture,
- std::vector<CountryParty>&& new_parties, std::vector<UnitNames>&& new_unit_names, bool new_dynamic_tag,
- std::map<const GovernmentType*, colour_t>&& new_alternative_colours
-) : HasIdentifierAndColour(new_identifier, new_color, false, false), graphical_culture { new_graphical_culture },
- parties { std::move(new_parties) }, unit_names { std::move(new_unit_names) }, dynamic_tag { new_dynamic_tag },
- alternative_colours { std::move(new_alternative_colours) } {}
+Country::government_colour_map_t const& Country::get_alternative_colours() const {
+ return alternative_colours;
+}
CountryManager::CountryManager() : countries { "countries" } {}
bool CountryManager::add_country(
- std::string_view identifier, colour_t color, const GraphicalCultureType& graphical_culture,
- std::vector<CountryParty>&& parties, std::vector<UnitNames>&& unit_names, bool dynamic_tag,
- std::map<const GovernmentType*, colour_t>&& alternative_colours
+ std::string_view identifier, colour_t colour, GraphicalCultureType const* graphical_culture,
+ IdentifierRegistry<CountryParty>&& parties, Country::unit_names_map_t&& unit_names, bool dynamic_tag,
+ Country::government_colour_map_t&& alternative_colours
) {
if (identifier.empty()) {
+ Logger::error("Invalid country identifier - empty!");
+ return false;
+ }
+ if (!valid_basic_identifier(identifier)) {
+ Logger::error(
+ "Invalid country identifier: ", identifier, " (can only contain alphanumeric characters and underscores)"
+ );
+ return false;
+ }
+ if (colour > MAX_COLOUR_RGB) {
+ Logger::error("Invalid country colour for ", identifier, ": ", colour_to_hex_string(colour));
+ return false;
+ }
+ if (graphical_culture == nullptr) {
+ Logger::error("Null graphical culture for country ", identifier);
return false;
}
return countries.add_item({
- identifier, color, graphical_culture, std::move(parties), std::move(unit_names),
- dynamic_tag, std::move(alternative_colours)
+ identifier, colour, *graphical_culture, std::move(parties), std::move(unit_names), dynamic_tag,
+ std::move(alternative_colours)
});
}
-bool CountryManager::load_country_data_file(
- GameManager& game_manager, std::string_view name, bool is_dynamic, ast::NodeCPtr root
-) {
- colour_t color;
- const GraphicalCultureType* graphical_culture;
- std::vector<CountryParty> country_parties;
- std::vector<UnitNames> unit_names;
- std::map<const GovernmentType*, colour_t> alternative_colours;
-
- bool ret = expect_dictionary_keys_and_default(
- [&game_manager, &alternative_colours, &name](std::string_view key, ast::NodeCPtr value) -> bool {
- const GovernmentType* colour_gov_type;
- bool ret = game_manager.get_politics_manager().get_government_type_manager()
- .expect_government_type_str(assign_variable_callback_pointer(colour_gov_type))(key);
-
- if (!ret) {
- return false;
- }
-
- colour_t alternative_colour;
- ret &= expect_colour(assign_variable_callback(alternative_colour))(value);
-
- if (!ret) {
- return false;
- }
-
- return alternative_colours.emplace(std::move(colour_gov_type), std::move(alternative_colour)).second;
- },
- "color", ONE_EXACTLY, expect_colour(assign_variable_callback(color)),
- "graphical_culture", ONE_EXACTLY, expect_identifier_or_string(
- [&game_manager, &graphical_culture, &name](std::string_view value) -> bool {
- graphical_culture = game_manager.get_pop_manager().get_culture_manager()
- .get_graphical_culture_type_by_identifier(value);
- if (graphical_culture == nullptr) {
- Logger::error("When loading country ", name, ", specified graphical culture ", value,
- " is invalid!\nCheck that CultureManager has loaded before CountryManager.");
- }
-
- return graphical_culture != nullptr;
+bool CountryManager::load_countries(GameManager const& game_manager, Dataloader const& dataloader, ast::NodeCPtr root) {
+ static constexpr std::string_view common_dir = "common/";
+ bool is_dynamic = false;
+
+ const bool ret = expect_dictionary_reserve_length(
+ countries,
+ [this, &game_manager, &is_dynamic, &dataloader](std::string_view key, ast::NodeCPtr value) -> bool {
+ if (key == "dynamic_tags") {
+ return expect_bool([&is_dynamic](bool val) -> bool {
+ if (val == is_dynamic) {
+ Logger::warning("Redundant \"is_dynamic\", already ", val ? "true" : "false");
+ } else {
+ if (is_dynamic) {
+ Logger::warning("Changing \"is_dynamic\" back to false");
+ }
+ is_dynamic = val;
+ }
+ return true;
+ })(value);
}
- ),
- "party", ZERO_OR_MORE, [&game_manager, &country_parties, &name](ast::NodeCPtr value) -> bool {
- std::string_view party_name;
- Date start_date, end_date;
- const Ideology* ideology;
- std::vector<const Issue*> policies;
-
- bool ret = expect_dictionary_keys_and_default(
- [&game_manager, &policies](std::string_view key, ast::NodeCPtr value) -> bool {
- const Issue* policy;
- bool ret = expect_identifier_or_string(
- game_manager.get_politics_manager().get_issue_manager().expect_issue_str(
- assign_variable_callback_pointer(policy)
- )
- )(value);
-
- if (ret && policy->get_group().get_identifier() == key) {
- policies.push_back(policy);
+ if (expect_string(
+ [this, &game_manager, is_dynamic, &dataloader, &key](std::string_view filepath) -> bool {
+ if (load_country_data_file(
+ game_manager, key, is_dynamic,
+ Dataloader::parse_defines(
+ dataloader.lookup_file(StringUtils::append_string_views(common_dir, filepath))
+ ).get_file_node()
+ )) {
return true;
}
-
+ Logger::error("Failed to load country data file: ", filepath);
return false;
- },
- "name", ONE_EXACTLY, expect_identifier_or_string(assign_variable_callback(party_name)),
- "start_date", ONE_EXACTLY, expect_date(assign_variable_callback(start_date)),
- "end_date", ONE_EXACTLY, expect_date(assign_variable_callback(end_date)),
- "ideology", ONE_EXACTLY, expect_identifier_or_string(game_manager.get_politics_manager()
- .get_ideology_manager().expect_ideology_str(assign_variable_callback_pointer(ideology)))
- )(value);
+ }
+ )(value)) {
+ return true;
+ }
+ Logger::error("Failed to load country: ", key);
+ return false;
+ }
+ )(root);
+ lock_countries();
+ return ret;
+}
- country_parties.push_back({ party_name, start_date, end_date, *ideology, std::move(policies) });
+node_callback_t CountryManager::load_country_party(
+ PoliticsManager const& politics_manager, IdentifierRegistry<CountryParty>& country_parties
+) const {
+ return [&politics_manager, &country_parties](ast::NodeCPtr value) -> bool {
+ std::string_view party_name;
+ Date start_date, end_date;
+ Ideology const* ideology;
+ CountryParty::policy_map_t policies;
+
+ bool ret = expect_dictionary_keys_and_default(
+ [&politics_manager, &policies, &party_name](std::string_view key, ast::NodeCPtr value) -> bool {
+ return politics_manager.get_issue_manager().expect_issue_group_str(
+ [&politics_manager, &policies, value, &party_name](IssueGroup const& group) -> bool {
+ if (policies.contains(&group)) {
+ Logger::error("Country party ", party_name, " has duplicate entry for ", group.get_identifier());
+ return false;
+ }
+ return politics_manager.get_issue_manager().expect_issue_identifier(
+ [&policies, &group](Issue const& issue) -> bool {
+ if (&issue.get_group() == &group) {
+ policies.emplace(&group, &issue);
+ return true;
+ }
+ // TODO - change this back to error/false once TGC no longer has this issue
+ Logger::warning("Invalid policy ", issue.get_identifier(), ", group is ",
+ issue.get_group().get_identifier(), " when ", group.get_identifier(), " was expected");
+ return true;
+ }
+ )(value);
+ }
+ )(key);
+ },
+ "name", ONE_EXACTLY, expect_string(assign_variable_callback(party_name)),
+ "start_date", ONE_EXACTLY, expect_date(assign_variable_callback(start_date)),
+ "end_date", ONE_EXACTLY, expect_date(assign_variable_callback(end_date)),
+ "ideology", ONE_EXACTLY,
+ politics_manager.get_ideology_manager().expect_ideology_identifier(assign_variable_callback_pointer(ideology))
+ )(value);
+
+ ret &= country_parties.add_item(
+ { party_name, start_date, end_date, *ideology, std::move(policies) }, duplicate_warning_callback
+ );
+
+ return ret;
+ };
+}
- return ret;
+bool CountryManager::load_country_data_file(
+ GameManager const& game_manager, std::string_view name, bool is_dynamic, ast::NodeCPtr root
+) {
+ colour_t colour;
+ GraphicalCultureType const* graphical_culture;
+ IdentifierRegistry<CountryParty> parties { "country parties" };
+ Country::unit_names_map_t unit_names;
+ Country::government_colour_map_t alternative_colours;
+ bool ret = expect_dictionary_keys_and_default(
+ [&game_manager, &alternative_colours, &name](std::string_view key, ast::NodeCPtr value) -> bool {
+ return game_manager.get_politics_manager().get_government_type_manager().expect_government_type_str(
+ [&alternative_colours, &name, &value](GovernmentType const& government_type) -> bool {
+ if (alternative_colours.contains(&government_type)) {
+ Logger::error(
+ "Country ", name, " has duplicate entry for ", government_type.get_identifier(),
+ " alternative colour"
+ );
+ return false;
+ }
+ return expect_colour([&alternative_colours, &government_type](colour_t colour) -> bool {
+ return alternative_colours.emplace(&government_type, std::move(colour)).second;
+ })(value);
+ }
+ )(key);
},
- "unit_names", ZERO_OR_ONE, expect_dictionary([&unit_names](std::string_view key, ast::NodeCPtr value) -> bool {
- std::vector<std::string> names;
-
- bool ret = expect_list(expect_identifier_or_string(
- [&names](std::string_view value) -> bool {
- names.push_back(std::string(value));
- return true;
+ "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)),
+ "graphical_culture", ONE_EXACTLY,
+ game_manager.get_pop_manager().get_culture_manager().expect_graphical_culture_type_identifier(
+ assign_variable_callback_pointer(graphical_culture)
+ ),
+ "party", ZERO_OR_MORE, load_country_party(game_manager.get_politics_manager(), parties),
+ "unit_names", ZERO_OR_ONE,
+ game_manager.get_military_manager().get_unit_manager().expect_unit_dictionary(
+ [&unit_names, &name](Unit const& unit, ast::NodeCPtr value) -> bool {
+ if (unit_names.contains(&unit)) {
+ Logger::error("Country ", name, " has duplicate entry for ", unit.get_identifier(), " name list");
+ return false;
+ }
+ return name_list_callback([&unit_names, &unit](std::vector<std::string>&& list) -> bool {
+ return unit_names.emplace(&unit, std::move(list)).second;
+ })(value);
}
- ))(value);
-
- unit_names.push_back({ key, std::move(names) });
-
- return ret;
- })
+ )
)(root);
ret &= add_country(
- name, color, *graphical_culture, std::move(country_parties), std::move(unit_names), is_dynamic,
+ name, colour, graphical_culture, std::move(parties), std::move(unit_names), is_dynamic,
std::move(alternative_colours)
);
return ret;
diff --git a/src/openvic-simulation/country/Country.hpp b/src/openvic-simulation/country/Country.hpp
index 66ce2e6..50cca04 100644
--- a/src/openvic-simulation/country/Country.hpp
+++ b/src/openvic-simulation/country/Country.hpp
@@ -5,17 +5,18 @@
#include <string>
#include <string_view>
#include <type_traits>
-#include <unordered_map>
#include <vector>
#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp>
#include "openvic-simulation/dataloader/Dataloader.hpp"
#include "openvic-simulation/map/Province.hpp"
+#include "openvic-simulation/military/Unit.hpp"
#include "openvic-simulation/politics/Government.hpp"
#include "openvic-simulation/politics/Ideology.hpp"
#include "openvic-simulation/politics/Issue.hpp"
#include "openvic-simulation/politics/NationalValue.hpp"
+#include "openvic-simulation/politics/PoliticsManager.hpp"
#include "openvic-simulation/pop/Culture.hpp"
#include "openvic-simulation/pop/Religion.hpp"
#include "openvic-simulation/types/Colour.hpp"
@@ -26,81 +27,85 @@ namespace OpenVic {
struct GameManager;
struct CountryManager;
- struct CountryParty {
+ struct CountryParty : HasIdentifier {
friend struct CountryManager;
+ using policy_map_t = std::map<IssueGroup const*, Issue const*>;
+
private:
- const std::string name;
const Date start_date;
const Date end_date;
- const Ideology& ideology;
- const std::vector<Issue const*> policies;
+ Ideology const& ideology;
+ const policy_map_t policies;
CountryParty(
- std::string_view new_name, Date new_start_date, Date new_end_date, const Ideology& new_ideology,
- std::vector<const Issue*>&& new_policies
+ std::string_view new_identifier, Date new_start_date, Date new_end_date, Ideology const& new_ideology,
+ policy_map_t&& new_policies
);
public:
- std::string_view get_name() const;
- const Date& get_start_date() const;
- const Date& get_end_date() const;
- const Ideology& get_ideology() const;
- const std::vector<const Issue*>& get_policies() const;
- };
-
- struct UnitNames {
- friend struct CountryManager;
-
- private:
- const std::string identifier;
- const std::vector<std::string> names;
-
- UnitNames(std::string_view new_identifier, std::vector<std::string>&& new_names);
+ CountryParty(CountryParty&&) = default;
- public:
- std::string_view get_identifier() const;
- const std::vector<std::string>& get_names() const;
+ Date get_start_date() const;
+ Date get_end_date() const;
+ Ideology const& get_ideology() const;
+ policy_map_t const& get_policies() const;
};
struct Country : HasIdentifierAndColour {
friend struct CountryManager;
+ using unit_names_map_t = std::map<Unit const*, std::vector<std::string>>;
+ using government_colour_map_t = std::map<GovernmentType const*, colour_t>;
+
private:
- const GraphicalCultureType& graphical_culture;
- const std::vector<CountryParty> parties;
- const std::vector<UnitNames> unit_names;
+ GraphicalCultureType const& graphical_culture;
+ /* Not const to allow elements to be moved, otherwise a copy is forced
+ * which causes a compile error as the copy constructor has been deleted.
+ */
+ IdentifierRegistry<CountryParty> parties;
+ const unit_names_map_t unit_names;
const bool dynamic_tag;
- const std::map<const GovernmentType*, colour_t> alternative_colours;
+ const government_colour_map_t alternative_colours;
Country(
- std::string_view new_identifier, colour_t new_color, const GraphicalCultureType& new_graphical_culture,
- std::vector<CountryParty>&& new_parties, std::vector<UnitNames>&& new_unit_names, const bool new_dynamic_tag,
- std::map<const GovernmentType*, colour_t>&& new_alternative_colours
+ std::string_view new_identifier, colour_t new_colour, GraphicalCultureType const& new_graphical_culture,
+ IdentifierRegistry<CountryParty>&& new_parties, unit_names_map_t&& new_unit_names, bool new_dynamic_tag,
+ government_colour_map_t&& new_alternative_colours
);
public:
- const GraphicalCultureType& get_graphical_culture() const;
- const std::vector<CountryParty>& get_parties() const;
- const std::vector<UnitNames>& get_unit_names() const;
- const bool is_dynamic_tag() const;
- const std::map<const GovernmentType*, colour_t>& get_alternative_colours() const;
+ Country(Country&&) = default;
+
+ IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(party, parties)
+
+ GraphicalCultureType const& get_graphical_culture() const;
+ unit_names_map_t const& get_unit_names() const;
+ bool is_dynamic_tag() const;
+ government_colour_map_t const& get_alternative_colours() const;
};
struct CountryManager {
private:
IdentifierRegistry<Country> countries;
+ NodeTools::node_callback_t load_country_party(
+ PoliticsManager const& politics_manager, IdentifierRegistry<CountryParty>& country_parties
+ ) const;
+
public:
CountryManager();
bool add_country(
- std::string_view identifier, colour_t color, const GraphicalCultureType& graphical_culture,
- std::vector<CountryParty>&& parties, std::vector<UnitNames>&& unit_names, bool dynamic_tag,
- std::map<const GovernmentType*, colour_t>&& alternative_colours
+ std::string_view identifier, colour_t colour, GraphicalCultureType const* graphical_culture,
+ IdentifierRegistry<CountryParty>&& parties, Country::unit_names_map_t&& unit_names, bool dynamic_tag,
+ Country::government_colour_map_t&& alternative_colours
);
- IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(country, countries);
+ IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(country, countries)
- bool load_country_data_file(GameManager& game_manager, std::string_view name, bool is_dynamic, ast::NodeCPtr root);
+ bool load_countries(GameManager const& game_manager, Dataloader const& dataloader, ast::NodeCPtr root);
+ bool load_country_data_file(
+ GameManager const& game_manager, std::string_view name, bool is_dynamic, ast::NodeCPtr root
+ );
};
}