aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/openvic-simulation/GameManager.cpp5
-rw-r--r--src/openvic-simulation/country/Country.cpp20
-rw-r--r--src/openvic-simulation/country/Country.hpp22
-rw-r--r--src/openvic-simulation/interface/GUI.cpp4
-rw-r--r--src/openvic-simulation/interface/GUI.hpp3
-rw-r--r--src/openvic-simulation/map/Map.cpp13
-rw-r--r--src/openvic-simulation/map/Map.hpp5
-rw-r--r--src/openvic-simulation/map/Province.cpp19
-rw-r--r--src/openvic-simulation/map/Province.hpp6
-rw-r--r--src/openvic-simulation/politics/Issue.cpp133
-rw-r--r--src/openvic-simulation/politics/Issue.hpp16
-rw-r--r--src/openvic-simulation/pop/Pop.cpp84
-rw-r--r--src/openvic-simulation/pop/Pop.hpp21
-rw-r--r--src/openvic-simulation/types/fixed_point/FixedPoint.hpp4
-rw-r--r--src/openvic-simulation/types/fixed_point/FixedPointMap.hpp128
15 files changed, 412 insertions, 71 deletions
diff --git a/src/openvic-simulation/GameManager.cpp b/src/openvic-simulation/GameManager.cpp
index a4cb5f4..bb807c9 100644
--- a/src/openvic-simulation/GameManager.cpp
+++ b/src/openvic-simulation/GameManager.cpp
@@ -63,7 +63,10 @@ bool GameManager::load_bookmark(Bookmark const* new_bookmark) {
Logger::warning("Bookmark date ", bookmark->get_date(), " is not in the game's time period!");
}
today = bookmark->get_date();
- ret &= map.apply_history_to_provinces(history_manager.get_province_manager(), today);
+ ret &= map.apply_history_to_provinces(
+ history_manager.get_province_manager(), today, politics_manager.get_ideology_manager(),
+ politics_manager.get_issue_manager(), *country_manager.get_country_by_identifier("ENG")
+ );
map.get_state_manager().generate_states(map);
// TODO - apply country history
return ret;
diff --git a/src/openvic-simulation/country/Country.cpp b/src/openvic-simulation/country/Country.cpp
index 604e11f..5ec4aee 100644
--- a/src/openvic-simulation/country/Country.cpp
+++ b/src/openvic-simulation/country/Country.cpp
@@ -20,36 +20,36 @@ using namespace OpenVic::NodeTools;
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) } {}
+) : HasIdentifierAndColour { new_identifier, new_ideology.get_colour(), false }, start_date { new_start_date },
+ end_date { new_end_date }, ideology { new_ideology }, policies { std::move(new_policies) } {}
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,
+ IdentifierRegistry<CountryParty>&& new_parties,
+ unit_names_map_t&& new_unit_names,
bool new_dynamic_tag,
government_colour_map_t&& new_alternative_colours,
colour_t new_primary_unit_colour,
colour_t new_secondary_unit_colour,
colour_t new_tertiary_unit_colour
-) : HasIdentifierAndColour {
- new_identifier, new_colour, false },
+) : HasIdentifierAndColour {
+ new_identifier, new_colour, false },
graphical_culture { new_graphical_culture },
- parties { std::move(new_parties) },
- unit_names { std::move(new_unit_names) },
+ parties { std::move(new_parties) },
+ unit_names { std::move(new_unit_names) },
dynamic_tag { new_dynamic_tag },
alternative_colours { std::move(new_alternative_colours) },
primary_unit_colour { new_primary_unit_colour },
secondary_unit_colour { new_secondary_unit_colour },
- tertiary_unit_colour { new_tertiary_unit_colour }
+ tertiary_unit_colour { new_tertiary_unit_colour }
{}
bool CountryManager::add_country(
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,
+ Country::government_colour_map_t&& alternative_colours,
colour_t primary_unit_colour, colour_t secondary_unit_colour, colour_t tertiary_unit_colour
) {
if (identifier.empty()) {
diff --git a/src/openvic-simulation/country/Country.hpp b/src/openvic-simulation/country/Country.hpp
index f115489..ea8f732 100644
--- a/src/openvic-simulation/country/Country.hpp
+++ b/src/openvic-simulation/country/Country.hpp
@@ -1,11 +1,6 @@
#pragma once
-#include <filesystem>
-#include <memory>
-#include <string>
#include <string_view>
-#include <type_traits>
-#include <vector>
#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp>
@@ -14,10 +9,8 @@
#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"
#include "openvic-simulation/types/Date.hpp"
#include "openvic-simulation/types/IdentifierRegistry.hpp"
@@ -27,7 +20,7 @@ namespace OpenVic {
struct GameManager;
struct CountryManager;
- struct CountryParty : HasIdentifier {
+ struct CountryParty : HasIdentifierAndColour {
friend struct CountryManager;
using policy_map_t = ordered_map<IssueGroup const*, Issue const*>;
@@ -36,7 +29,7 @@ namespace OpenVic {
const Date PROPERTY(start_date);
const Date PROPERTY(end_date);
Ideology const& PROPERTY(ideology);
- const policy_map_t PROPERTY(policies);
+ policy_map_t PROPERTY(policies);
CountryParty(
std::string_view new_identifier, Date new_start_date, Date new_end_date, Ideology const& new_ideology,
@@ -57,12 +50,11 @@ namespace OpenVic {
private:
GraphicalCultureType const& PROPERTY(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.
- */
+ * which causes a compile error as the copy constructor has been deleted. */
IdentifierRegistry<CountryParty> IDENTIFIER_REGISTRY_CUSTOM_PLURAL(party, parties);
- const unit_names_map_t PROPERTY(unit_names);
+ unit_names_map_t PROPERTY(unit_names);
const bool PROPERTY_CUSTOM_PREFIX(dynamic_tag, is);
- const government_colour_map_t PROPERTY(alternative_colours);
+ government_colour_map_t PROPERTY(alternative_colours);
colour_t PROPERTY(primary_unit_colour);
colour_t PROPERTY(secondary_unit_colour);
colour_t PROPERTY(tertiary_unit_colour);
@@ -71,7 +63,7 @@ namespace OpenVic {
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,
+ government_colour_map_t&& new_alternative_colours,
colour_t new_primary_unit_colour, colour_t new_secondary_unit_colour, colour_t new_tertiary_unit_colour
);
@@ -93,7 +85,7 @@ namespace OpenVic {
bool add_country(
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,
+ Country::government_colour_map_t&& alternative_colours,
colour_t primary_unit_colour, colour_t secondary_unit_colour, colour_t tertiary_unit_colour
);
diff --git a/src/openvic-simulation/interface/GUI.cpp b/src/openvic-simulation/interface/GUI.cpp
index ae4cf0e..9acb72c 100644
--- a/src/openvic-simulation/interface/GUI.cpp
+++ b/src/openvic-simulation/interface/GUI.cpp
@@ -174,7 +174,7 @@ bool AlignedElement::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_ma
return ret;
}
-Text::Text() : text {}, font { nullptr }, max_size {} {}
+Text::Text() : text {}, font { nullptr }, max_size {}, border_size {} {}
bool Text::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) {
bool ret = AlignedElement::_fill_key_map(key_map, ui_manager);
@@ -183,8 +183,8 @@ bool Text::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManag
"font", ONE_EXACTLY, ui_manager.expect_font_string(assign_variable_callback_pointer(font)),
"maxWidth", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(max_size.x)),
"maxHeight", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(max_size.y)),
+ "borderSize", ZERO_OR_ONE, expect_fvec2(assign_variable_callback(border_size)),
- "borderSize", ZERO_OR_ONE, success_callback,
"fixedsize", ZERO_OR_ONE, success_callback,
"allwaystransparent", ZERO_OR_ONE, success_callback,
diff --git a/src/openvic-simulation/interface/GUI.hpp b/src/openvic-simulation/interface/GUI.hpp
index 7551d1a..d839188 100644
--- a/src/openvic-simulation/interface/GUI.hpp
+++ b/src/openvic-simulation/interface/GUI.hpp
@@ -202,8 +202,9 @@ namespace OpenVic::GUI {
std::string PROPERTY(text);
GFX::Font const* PROPERTY(font);
fvec2_t PROPERTY(max_size); /* Defines keys: maxWidth, maxHeight */
+ fvec2_t PROPERTY(border_size);
- // TODO - borderSize, fixedsize, textureFile
+ // TODO - fixedsize, textureFile
protected:
Text();
diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp
index f87246f..81a599e 100644
--- a/src/openvic-simulation/map/Map.cpp
+++ b/src/openvic-simulation/map/Map.cpp
@@ -446,25 +446,36 @@ bool Map::reset(BuildingTypeManager const& building_type_manager) {
return ret;
}
-bool Map::apply_history_to_provinces(ProvinceHistoryManager const& history_manager, Date date) {
+bool Map::apply_history_to_provinces(
+ ProvinceHistoryManager const& history_manager, Date date, IdeologyManager const& ideology_manager,
+ IssueManager const& issue_manager, Country const& country
+) {
bool ret = true;
+
for (Province& province : provinces.get_items()) {
if (!province.is_water()) {
ProvinceHistoryMap const* history_map = history_manager.get_province_history(&province);
+
if (history_map != nullptr) {
ProvinceHistoryEntry const* pop_history_entry = nullptr;
+
for (ProvinceHistoryEntry const* entry : history_map->get_entries_up_to(date)) {
province.apply_history_to_province(entry);
+
if (!entry->get_pops().empty()) {
pop_history_entry = entry;
}
}
+
if (pop_history_entry != nullptr) {
province.add_pop_vec(pop_history_entry->get_pops());
+
+ province.setup_pop_test_values(ideology_manager, issue_manager, country);
}
}
}
}
+
return ret;
}
diff --git a/src/openvic-simulation/map/Map.hpp b/src/openvic-simulation/map/Map.hpp
index e2c4bd6..807945a 100644
--- a/src/openvic-simulation/map/Map.hpp
+++ b/src/openvic-simulation/map/Map.hpp
@@ -128,7 +128,10 @@ namespace OpenVic {
bool generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) const;
bool reset(BuildingTypeManager const& building_type_manager);
- bool apply_history_to_provinces(ProvinceHistoryManager const& history_manager, Date date);
+ bool apply_history_to_provinces(
+ ProvinceHistoryManager const& history_manager, Date date, IdeologyManager const& ideology_manager,
+ IssueManager const& issue_manager, Country const& country
+ );
void update_highest_province_population();
void update_total_map_population();
diff --git a/src/openvic-simulation/map/Province.cpp b/src/openvic-simulation/map/Province.cpp
index 94c8dcb..d1183f5 100644
--- a/src/openvic-simulation/map/Province.cpp
+++ b/src/openvic-simulation/map/Province.cpp
@@ -65,9 +65,14 @@ bool Province::expand_building(size_t building_index) {
return building->expand();
}
+void Province::_add_pop(Pop pop) {
+ pop.set_location(this);
+ pops.push_back(std::move(pop));
+}
+
bool Province::add_pop(Pop&& pop) {
if (!is_water()) {
- pops.push_back(std::move(pop));
+ _add_pop(std::move(pop));
return true;
} else {
Logger::error("Trying to add pop to water province ", get_identifier());
@@ -79,7 +84,7 @@ bool Province::add_pop_vec(std::vector<Pop> const& pop_vec) {
if (!is_water()) {
reserve_more(pops, pop_vec.size());
for (Pop const& pop : pop_vec) {
- pops.push_back(pop);
+ _add_pop(pop);
}
return true;
} else {
@@ -104,7 +109,7 @@ void Province::update_pops() {
for (Pop const& pop : pops) {
total_population += pop.get_size();
pop_type_distribution[&pop.get_type()] += pop.get_size();
- //ideology_distribution[&pop.get_???()] += pop.get_size();
+ ideology_distribution += pop.get_ideologies();
culture_distribution[&pop.get_culture()] += pop.get_size();
religion_distribution[&pop.get_religion()] += pop.get_size();
}
@@ -257,3 +262,11 @@ bool Province::apply_history_to_province(ProvinceHistoryEntry const* entry) {
// TODO: party loyalties for each POP when implemented on POP side
return ret;
}
+
+void Province::setup_pop_test_values(
+ IdeologyManager const& ideology_manager, IssueManager const& issue_manager, Country const& country
+) {
+ for (Pop& pop : pops) {
+ pop.setup_pop_test_values(ideology_manager, issue_manager, country);
+ }
+}
diff --git a/src/openvic-simulation/map/Province.hpp b/src/openvic-simulation/map/Province.hpp
index 1df5676..476ecc9 100644
--- a/src/openvic-simulation/map/Province.hpp
+++ b/src/openvic-simulation/map/Province.hpp
@@ -128,6 +128,8 @@ namespace OpenVic {
Province(std::string_view new_identifier, colour_t new_colour, index_t new_index);
+ void _add_pop(Pop pop);
+
public:
Province(Province&&) = default;
@@ -155,5 +157,9 @@ namespace OpenVic {
bool reset(BuildingTypeManager const& building_type_manager);
bool apply_history_to_province(ProvinceHistoryEntry const* entry);
+
+ void setup_pop_test_values(
+ IdeologyManager const& ideology_manager, IssueManager const& issue_manager, Country const& country
+ );
};
}
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<uint32_t>(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<size_t, colour_pattern_period> dim_colour_indices { 0, 1, 2, 0, 1, 2 };
+static constexpr std::array<size_t, colour_pattern_period> bright_colour_indices { 1, 2, 0, 2, 0, 1 };
+static constexpr std::array<size_t, colour_pattern_period> 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<size_t>(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();
diff --git a/src/openvic-simulation/politics/Issue.hpp b/src/openvic-simulation/politics/Issue.hpp
index b836e6f..68302bd 100644
--- a/src/openvic-simulation/politics/Issue.hpp
+++ b/src/openvic-simulation/politics/Issue.hpp
@@ -1,6 +1,5 @@
#pragma once
-#include "openvic-simulation/dataloader/NodeTools.hpp"
#include "openvic-simulation/misc/Modifier.hpp"
#include "openvic-simulation/politics/Rule.hpp"
#include "openvic-simulation/scripts/ConditionScript.hpp"
@@ -22,7 +21,7 @@ namespace OpenVic {
};
// Issue (i.e. protectionism)
- struct Issue : Modifier {
+ struct Issue : HasIdentifierAndColour, ModifierValue {
friend struct IssueManager;
private:
@@ -32,7 +31,7 @@ namespace OpenVic {
protected:
Issue(
- std::string_view new_identifier, ModifierValue&& new_values, IssueGroup const& new_group,
+ std::string_view new_identifier, colour_t new_colour, ModifierValue&& new_values, IssueGroup const& new_group,
RuleSet&& new_rules, bool new_jingoism
);
@@ -83,8 +82,8 @@ namespace OpenVic {
EffectScript PROPERTY(on_execute_effect);
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
);
@@ -119,13 +118,14 @@ namespace OpenVic {
public:
bool add_issue_group(std::string_view identifier);
bool 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
);
bool add_reform_type(std::string_view identifier, bool uncivilised);
bool add_reform_group(std::string_view identifier, ReformType const* type, bool ordered, bool administrative);
bool 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
);
bool load_issues_file(ModifierManager const& modifier_manager, RuleManager const& rule_manager, ast::NodeCPtr root);
diff --git a/src/openvic-simulation/pop/Pop.cpp b/src/openvic-simulation/pop/Pop.cpp
index 21aede8..2490ef9 100644
--- a/src/openvic-simulation/pop/Pop.cpp
+++ b/src/openvic-simulation/pop/Pop.cpp
@@ -1,5 +1,6 @@
#include "Pop.hpp"
+#include "openvic-simulation/country/Country.hpp"
#include "openvic-simulation/military/UnitType.hpp"
#include "openvic-simulation/politics/Ideology.hpp"
#include "openvic-simulation/politics/Issue.hpp"
@@ -23,6 +24,8 @@ Pop::Pop(
culture { new_culture },
religion { new_religion },
size { new_size },
+ location { nullptr },
+ total_change { 0 },
num_grown { 0 },
num_promoted { 0 },
num_demoted { 0 },
@@ -31,10 +34,89 @@ Pop::Pop(
num_migrated_colonial { 0 },
militancy { new_militancy },
consciousness { new_consciousness },
- rebel_type { new_rebel_type } {
+ rebel_type { new_rebel_type },
+ ideologies {},
+ issues {},
+ votes {},
+ unemployment { 0 },
+ cash { 0 },
+ income { 0 },
+ expenses { 0 },
+ savings { 0 },
+ life_needs_fulfilled { 0 },
+ everyday_needs_fulfilled { 0 },
+ luxury_needs_fulfilled { 0 } {
assert(size > 0);
}
+void Pop::setup_pop_test_values(
+ IdeologyManager const& ideology_manager, IssueManager const& issue_manager, Country const& country
+) {
+ /* Returns +/- range% of size. */
+ const auto test_size = [this](int32_t range) -> pop_size_t {
+ return size * ((rand() % (2 * range + 1)) - range) / 100;
+ };
+
+ num_grown = test_size(5);
+ num_promoted = test_size(1);
+ num_demoted = test_size(1);
+ num_migrated_internal = test_size(3);
+ num_migrated_external = test_size(1);
+ num_migrated_colonial = test_size(2);
+
+ total_change =
+ num_grown + num_promoted + num_demoted + num_migrated_internal + num_migrated_external + num_migrated_colonial;
+
+ /* Generates a number between 0 and max (inclusive) and sets map[&key] to it if it's at least min. */
+ auto test_weight =
+ []<typename T, std::derived_from<T> U>(
+ fixed_point_map_t<T const*>& map, U const& key, int32_t min, int32_t max
+ ) -> void {
+ const int32_t value = rand() % (max + 1);
+ if (value >= min) {
+ map.emplace(&key, value);
+ }
+ };
+
+ /* All entries equally weighted for testing. */
+ ideologies.clear();
+ for (Ideology const& ideology : ideology_manager.get_ideologies()) {
+ test_weight(ideologies, ideology, 1, 5);
+ }
+ normalise_fixed_point_map(ideologies);
+
+ issues.clear();
+ for (Issue const& issue : issue_manager.get_issues()) {
+ test_weight(issues, issue, 3, 6);
+ }
+ for (Reform const& reform : issue_manager.get_reforms()) {
+ if (!reform.get_reform_group().get_type().is_uncivilised()) {
+ test_weight(issues, reform, 3, 6);
+ }
+ }
+ normalise_fixed_point_map(issues);
+
+ votes.clear();
+ for (CountryParty const& party : country.get_parties()) {
+ test_weight(votes, party, 4, 10);
+ }
+ normalise_fixed_point_map(votes);
+
+ /* Returns a fixed point between 0 and max. */
+ const auto test_range = [](fixed_point_t max = 1) -> fixed_point_t {
+ return (rand() % 256) * max / 256;
+ };
+
+ unemployment = test_range();
+ cash = test_range(20);
+ income = test_range(5);
+ expenses = test_range(5);
+ savings = test_range(15);
+ life_needs_fulfilled = test_range();
+ everyday_needs_fulfilled = test_range();
+ luxury_needs_fulfilled = test_range();
+}
+
Strata::Strata(std::string_view new_identifier) : HasIdentifier { new_identifier } {}
PopType::PopType(
diff --git a/src/openvic-simulation/pop/Pop.hpp b/src/openvic-simulation/pop/Pop.hpp
index c4e369f..fe1867f 100644
--- a/src/openvic-simulation/pop/Pop.hpp
+++ b/src/openvic-simulation/pop/Pop.hpp
@@ -23,6 +23,8 @@ namespace OpenVic {
struct IdeologyManager;
struct Issue;
struct IssueManager;
+ struct Province;
+ struct CountryParty;
/* REQUIREMENTS:
* POP-18, POP-19, POP-20, POP-21, POP-34, POP-35, POP-36, POP-37
@@ -39,8 +41,10 @@ namespace OpenVic {
Culture const& PROPERTY(culture);
Religion const& PROPERTY(religion);
pop_size_t PROPERTY(size);
+ Province const* PROPERTY_RW(location);
/* Last day's size change by source. */
+ pop_size_t PROPERTY(total_change);
pop_size_t PROPERTY(num_grown);
pop_size_t PROPERTY(num_promoted); // TODO - detailed promotion/demotion info (what to)
pop_size_t PROPERTY(num_demoted);
@@ -53,6 +57,19 @@ namespace OpenVic {
fixed_point_t PROPERTY(literacy);
RebelType const* PROPERTY(rebel_type);
+ fixed_point_map_t<Ideology const*> PROPERTY(ideologies);
+ fixed_point_map_t<Issue const*> PROPERTY(issues);
+ fixed_point_map_t<CountryParty const*> PROPERTY(votes);
+
+ fixed_point_t PROPERTY(unemployment);
+ fixed_point_t PROPERTY(cash);
+ fixed_point_t PROPERTY(income);
+ fixed_point_t PROPERTY(expenses);
+ fixed_point_t PROPERTY(savings);
+ fixed_point_t PROPERTY(life_needs_fulfilled);
+ fixed_point_t PROPERTY(everyday_needs_fulfilled);
+ fixed_point_t PROPERTY(luxury_needs_fulfilled);
+
Pop(
PopType const& new_type,
Culture const& new_culture,
@@ -68,6 +85,10 @@ namespace OpenVic {
Pop(Pop&&) = default;
Pop& operator=(Pop const&) = delete;
Pop& operator=(Pop&&) = delete;
+
+ void setup_pop_test_values(
+ IdeologyManager const& ideology_manager, IssueManager const& issue_manager, Country const& country
+ );
};
struct Strata : HasIdentifier {
diff --git a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp
index 95d2759..9ad7966 100644
--- a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp
+++ b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp
@@ -658,6 +658,10 @@ namespace OpenVic {
return static_cast<int64_t>(lhs) << PRECISION != rhs.value;
}
+ constexpr friend std::strong_ordering operator<=>(fixed_point_t const& lhs, fixed_point_t const& rhs) {
+ return lhs.value <=> rhs.value;
+ }
+
private:
static constexpr fixed_point_t parse_integer(char const* str, char const* const end, bool* successful) {
int64_t parsed_value = StringUtils::string_to_int64(str, end, successful, 10);
diff --git a/src/openvic-simulation/types/fixed_point/FixedPointMap.hpp b/src/openvic-simulation/types/fixed_point/FixedPointMap.hpp
index 1904fec..5df537a 100644
--- a/src/openvic-simulation/types/fixed_point/FixedPointMap.hpp
+++ b/src/openvic-simulation/types/fixed_point/FixedPointMap.hpp
@@ -14,20 +14,140 @@ namespace OpenVic {
template<typename T>
using fixed_point_map_const_iterator_t = typename fixed_point_map_t<T>::const_iterator;
+ template<typename T, std::derived_from<T> U>
+ constexpr fixed_point_map_t<T const*>& cast_map(fixed_point_map_t<U const*>& map) {
+ return *reinterpret_cast<fixed_point_map_t<T const*>*>(&map);
+ }
+
+ template<typename T, std::derived_from<T> U>
+ constexpr fixed_point_map_t<T const*> const& cast_map(fixed_point_map_t<U const*> const& map) {
+ return *reinterpret_cast<fixed_point_map_t<T const*> const*>(&map);
+ }
+
+ template<typename T>
+ constexpr fixed_point_map_t<T>& operator+=(fixed_point_map_t<T>& lhs, fixed_point_map_t<T> const& rhs) {
+ for (auto const& [key, value] : rhs) {
+ lhs[key] += value;
+ }
+
+ return lhs;
+ }
+
+ template<typename T>
+ constexpr fixed_point_map_t<T> operator+(fixed_point_map_t<T> const& lhs, fixed_point_map_t<T> const& rhs) {
+ fixed_point_map_t<T> result = lhs;
+
+ result += rhs;
+
+ return result;
+ }
+
+ template<typename T>
+ constexpr fixed_point_map_t<T>& operator*=(fixed_point_map_t<T>& lhs, fixed_point_t rhs) {
+ for (auto [key, value] : mutable_iterator(lhs)) {
+ value *= rhs;
+ }
+
+ return lhs;
+ }
+
+ template<typename T>
+ constexpr fixed_point_map_t<T> operator*(fixed_point_map_t<T> const& lhs, fixed_point_t rhs) {
+ fixed_point_map_t<T> result = lhs;
+
+ result *= rhs;
+
+ return result;
+ }
+
+ template<typename T>
+ constexpr fixed_point_map_t<T> operator*(fixed_point_t lhs, fixed_point_map_t<T> const& rhs) {
+ return rhs * lhs;
+ }
+
+ template<typename T>
+ constexpr fixed_point_map_t<T>& operator/=(fixed_point_map_t<T>& lhs, fixed_point_t rhs) {
+ for (auto [key, value] : mutable_iterator(lhs)) {
+ value /= rhs;
+ }
+
+ return lhs;
+ }
+
+ template<typename T>
+ constexpr fixed_point_map_t<T> operator/(fixed_point_map_t<T> const& lhs, fixed_point_t rhs) {
+ fixed_point_map_t<T> result = lhs;
+
+ result /= rhs;
+
+ return result;
+ }
+
+ /* Assumes arguments are sorted with keys ascending. Result is determined by the
+ * first non-equal keys or values found starting from the back of the maps. */
+ template<typename T>
+ constexpr bool sorted_fixed_map_less_than(fixed_point_map_t<T> const& lhs, fixed_point_map_t<T> const& rhs) {
+
+ typename fixed_point_map_t<T>::const_reverse_iterator lit, rit;
+
+ for (lit = lhs.rcbegin(), rit = rhs.rcbegin(); lit != lhs.rcend() && rit != rhs.rcend(); lit++, rit++) {
+
+ const std::strong_ordering key_cmp = lit->first <=> rit->first;
+
+ if (key_cmp != std::strong_ordering::equal) {
+ return key_cmp == std::strong_ordering::less;
+ }
+
+ const std::strong_ordering value_cmp = lit->second <=> rit->second;
+
+ if (value_cmp != std::strong_ordering::equal) {
+ return value_cmp == std::strong_ordering::less;
+ }
+
+ }
+
+ return rit != rhs.rcend();
+ }
+
template<typename T>
constexpr fixed_point_t get_total(fixed_point_map_t<T> const& map) {
fixed_point_t total = 0;
+
for (auto const& [key, value] : map) {
total += value;
}
+
return total;
}
template<typename T>
+ constexpr void normalise_fixed_point_map(fixed_point_map_t<T>& map) {
+ const fixed_point_t total = get_total(map);
+
+ if (total > 0) {
+ map /= total;
+ }
+ }
+
+ template<typename T>
+ constexpr void rescale_fixed_point_map(fixed_point_map_t<T>& map, fixed_point_t new_total) {
+ const fixed_point_t total = get_total(map);
+
+ if (total > 0) {
+ for (auto [key, value] : mutable_iterator(map)) {
+ value *= new_total;
+ value /= total;
+ }
+ }
+ }
+
+ template<typename T>
constexpr fixed_point_map_const_iterator_t<T> get_largest_item(fixed_point_map_t<T> const& map) {
- constexpr auto pred = [](fixed_point_map_value_t<T> a, fixed_point_map_value_t<T> b) -> bool {
- return a.second < b.second;
- };
+ constexpr auto pred =
+ [](fixed_point_map_value_t<T> const& lhs, fixed_point_map_value_t<T> const& rhs) -> bool {
+ return lhs.second < rhs.second;
+ };
+
return std::max_element(map.begin(), map.end(), pred);
}
@@ -36,6 +156,7 @@ namespace OpenVic {
fixed_point_map_t<T> const& map
) {
fixed_point_map_const_iterator_t<T> largest = map.end(), second_largest = map.end();
+
for (fixed_point_map_const_iterator_t<T> it = map.begin(); it != map.end(); ++it) {
if (largest == map.end() || it->second > largest->second) {
second_largest = largest;
@@ -44,6 +165,7 @@ namespace OpenVic {
second_largest = it;
}
}
+
return std::make_pair(std::move(largest), std::move(second_largest));
}
}