aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author hop311 <hop3114@gmail.com>2024-06-04 00:39:34 +0200
committer hop311 <hop3114@gmail.com>2024-06-06 19:39:35 +0200
commit37cdd775ac738b2a1264e32471385376e5a34f3a (patch)
treef3a9a107f1bd4b6b6d8035a96ac659bcc15f176b
parente286cfef29d7c431ba33cd77283e838e6fba05d2 (diff)
Province const/mutable separation + State cleanupconst-mutable
-rw-r--r--src/openvic-simulation/GameManager.cpp92
-rw-r--r--src/openvic-simulation/country/CountryInstance.cpp2
-rw-r--r--src/openvic-simulation/country/CountryInstance.hpp29
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp8
-rw-r--r--src/openvic-simulation/dataloader/NodeTools.hpp4
-rw-r--r--src/openvic-simulation/diplomacy/CountryRelation.cpp1
-rw-r--r--src/openvic-simulation/history/CountryHistory.cpp6
-rw-r--r--src/openvic-simulation/history/CountryHistory.hpp34
-rw-r--r--src/openvic-simulation/history/DiplomaticHistory.cpp203
-rw-r--r--src/openvic-simulation/history/DiplomaticHistory.hpp37
-rw-r--r--src/openvic-simulation/history/Period.cpp6
-rw-r--r--src/openvic-simulation/history/Period.hpp4
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.cpp32
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.hpp44
-rw-r--r--src/openvic-simulation/map/Map.cpp317
-rw-r--r--src/openvic-simulation/map/Map.hpp87
-rw-r--r--src/openvic-simulation/map/Province.cpp380
-rw-r--r--src/openvic-simulation/map/ProvinceDefinition.cpp183
-rw-r--r--src/openvic-simulation/map/ProvinceDefinition.hpp (renamed from src/openvic-simulation/map/Province.hpp)101
-rw-r--r--src/openvic-simulation/map/ProvinceInstance.cpp213
-rw-r--r--src/openvic-simulation/map/ProvinceInstance.hpp91
-rw-r--r--src/openvic-simulation/map/Region.cpp33
-rw-r--r--src/openvic-simulation/map/Region.hpp36
-rw-r--r--src/openvic-simulation/map/State.cpp117
-rw-r--r--src/openvic-simulation/map/State.hpp61
-rw-r--r--src/openvic-simulation/military/Deployment.cpp27
-rw-r--r--src/openvic-simulation/military/Deployment.hpp29
-rw-r--r--src/openvic-simulation/military/UnitInstance.cpp13
-rw-r--r--src/openvic-simulation/military/UnitInstance.hpp28
-rw-r--r--src/openvic-simulation/pop/Pop.hpp6
-rw-r--r--src/openvic-simulation/scripts/Condition.cpp4
31 files changed, 1312 insertions, 916 deletions
diff --git a/src/openvic-simulation/GameManager.cpp b/src/openvic-simulation/GameManager.cpp
index 94d9c62..3f8220c 100644
--- a/src/openvic-simulation/GameManager.cpp
+++ b/src/openvic-simulation/GameManager.cpp
@@ -73,8 +73,7 @@ bool GameManager::load_bookmark(Bookmark const* new_bookmark) {
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);
+ ret &= map.get_state_manager().generate_states(map);
ret &= country_instance_manager.generate_country_instances(country_manager);
ret &= country_instance_manager.apply_history_to_countries(
@@ -86,7 +85,7 @@ bool GameManager::load_bookmark(Bookmark const* new_bookmark) {
bool GameManager::expand_selected_province_building(size_t building_index) {
set_gamestate_needs_update();
- Province* province = map.get_selected_province();
+ ProvinceInstance* province = map.get_selected_province();
if (province == nullptr) {
Logger::error("Cannot expand building index ", building_index, " - no province selected!");
return false;
@@ -105,13 +104,23 @@ static constexpr colour_argb_t DEFAULT_COLOUR_WHITE = (0xFFFFFF_argb).with_alpha
* national focus, RGO, population density, sphere of influence, ranking and migration. */
static constexpr colour_argb_t DEFAULT_COLOUR_GREY = (0x7F7F7F_argb).with_alpha(ALPHA_VALUE);
-template<IsColour ColourT = colour_t, std::derived_from<_HasColour<ColourT>> T>
-static constexpr auto get_colour_mapmode(T const*(Province::*get_item)() const) {
- return [get_item](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
- T const* item = (province.*get_item)();
+template<utility::is_derived_from_specialization_of<_HasColour> T, typename P>
+requires(std::same_as<P, ProvinceDefinition> || std::same_as<P, ProvinceInstance>)
+static constexpr auto get_colour_mapmode(T const*(P::*get_item)() const) {
+ return [get_item](Map const& map, ProvinceInstance const& province) -> Mapmode::base_stripe_t {
+ ProvinceDefinition const& province_definition = province.get_province_definition();
+
+ T const* item = [&province, &province_definition, get_item]() -> T const* {
+ if constexpr (std::same_as<P, ProvinceDefinition>) {
+ return (province_definition.*get_item)();
+ } else {
+ return (province.*get_item)();
+ }
+ }();
+
if (item != nullptr) {
return colour_argb_t { item->get_colour(), ALPHA_VALUE };
- } else if (!province.is_water()) {
+ } else if (!province_definition.is_water()) {
return DEFAULT_COLOUR_WHITE;
} else {
return colour_argb_t::null();
@@ -119,7 +128,7 @@ static constexpr auto get_colour_mapmode(T const*(Province::*get_item)() const)
};
}
-template<IsColour ColourT = colour_t, std::derived_from<_HasColour<ColourT>> T>
+template<utility::is_derived_from_specialization_of<_HasColour> T>
static constexpr Mapmode::base_stripe_t shaded_mapmode(fixed_point_map_t<T const*> const& map) {
const std::pair<fixed_point_map_const_iterator_t<T const*>, fixed_point_map_const_iterator_t<T const*>> largest =
get_largest_two_items(map);
@@ -137,9 +146,9 @@ static constexpr Mapmode::base_stripe_t shaded_mapmode(fixed_point_map_t<T const
return colour_argb_t::null();
}
-template<IsColour ColourT = colour_t, std::derived_from<_HasColour<ColourT>> T>
-static constexpr auto shaded_mapmode(fixed_point_map_t<T const*> const&(Province::*get_map)() const) {
- return [get_map](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
+template<utility::is_derived_from_specialization_of<_HasColour> T>
+static constexpr auto shaded_mapmode(fixed_point_map_t<T const*> const&(ProvinceInstance::*get_map)() const) {
+ return [get_map](Map const& map, ProvinceInstance const& province) -> Mapmode::base_stripe_t {
return shaded_mapmode((province.*get_map)());
};
}
@@ -151,42 +160,43 @@ bool GameManager::load_hardcoded_defines() {
const std::vector<mapmode_t> mapmodes {
{
"mapmode_terrain",
- [](Map const&, Province const& province) -> Mapmode::base_stripe_t {
+ [](Map const&, ProvinceInstance const& province) -> Mapmode::base_stripe_t {
return colour_argb_t::null();
}
},
{
- "mapmode_political", get_colour_mapmode(&Province::get_owner)
+ "mapmode_political", get_colour_mapmode(&ProvinceInstance::get_owner)
},
{
/* TEST MAPMODE, TO BE REMOVED */
"mapmode_province",
- [](Map const&, Province const& province) -> Mapmode::base_stripe_t {
- return colour_argb_t { province.get_colour(), ALPHA_VALUE };
+ [](Map const&, ProvinceInstance const& province) -> Mapmode::base_stripe_t {
+ return colour_argb_t { province.get_province_definition().get_colour(), ALPHA_VALUE };
}
},
{
- "mapmode_region", get_colour_mapmode(&Province::get_region)
+ "mapmode_region", get_colour_mapmode(&ProvinceDefinition::get_region)
},
{
/* TEST MAPMODE, TO BE REMOVED */
"mapmode_index",
- [](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
- const colour_argb_t::value_type f =
- colour_argb_t::colour_traits::component_from_fraction(province.get_index(), map.get_province_count() + 1);
+ [](Map const& map, ProvinceInstance const& province) -> Mapmode::base_stripe_t {
+ const colour_argb_t::value_type f = colour_argb_t::colour_traits::component_from_fraction(
+ province.get_province_definition().get_index(), map.get_province_definition_count() + 1
+ );
return colour_argb_t::fill_as(f).with_alpha(ALPHA_VALUE);
}
},
{
/* Non-vanilla mapmode, still of use in game. */
- "mapmode_terrain_type", get_colour_mapmode(&Province::get_terrain_type)
+ "mapmode_terrain_type", get_colour_mapmode(&ProvinceInstance::get_terrain_type)
},
{
- "mapmode_rgo", get_colour_mapmode(&Province::get_rgo)
+ "mapmode_rgo", get_colour_mapmode(&ProvinceInstance::get_rgo)
},
{
"mapmode_infrastructure",
- [](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
+ [](Map const& map, ProvinceInstance const& province) -> Mapmode::base_stripe_t {
BuildingInstance const* railroad = province.get_building_by_identifier("railroad");
if (railroad != nullptr) {
const colour_argb_t::value_type val = colour_argb_t::colour_traits::component_from_fraction(
@@ -206,11 +216,11 @@ bool GameManager::load_hardcoded_defines() {
},
{
"mapmode_population",
- [](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
+ [](Map const& map, ProvinceInstance const& province) -> Mapmode::base_stripe_t {
// TODO - explore non-linear scaling to have more variation among non-massive provinces
// TODO - when selecting a province, only show the population of provinces controlled (or owned?)
// by the same country, relative to the most populous province in that set of provinces
- if (!province.is_water()) {
+ if (!province.get_province_definition().is_water()) {
const colour_argb_t::value_type val = colour_argb_t::colour_traits::component_from_fraction(
province.get_total_population(), map.get_highest_province_population() + 1, 0.1f, 1.0f
);
@@ -221,26 +231,34 @@ bool GameManager::load_hardcoded_defines() {
}
},
{
- "mapmode_culture", shaded_mapmode(&Province::get_culture_distribution)
+ "mapmode_culture", shaded_mapmode(&ProvinceInstance::get_culture_distribution)
},
{
/* Non-vanilla mapmode, still of use in game. */
- "mapmode_religion", shaded_mapmode(&Province::get_religion_distribution)
+ "mapmode_religion", shaded_mapmode(&ProvinceInstance::get_religion_distribution)
},
{
/* TEST MAPMODE, TO BE REMOVED */
- "mapmode_adjacencies", [](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
- Province const* selected_province = map.get_selected_province();
+ "mapmode_adjacencies", [](Map const& map, ProvinceInstance const& province) -> Mapmode::base_stripe_t {
+ ProvinceInstance const* selected_province = map.get_selected_province();
+
if (selected_province != nullptr) {
+ ProvinceDefinition const& selected_province_definition = selected_province->get_province_definition();
+
if (selected_province == &province) {
return (0xFFFFFF_argb).with_alpha(ALPHA_VALUE);
}
+
+ ProvinceDefinition const* province_definition = &province.get_province_definition();
+
colour_argb_t base = colour_argb_t::null(), stripe = colour_argb_t::null();
- Province::adjacency_t const* adj = selected_province->get_adjacency_to(&province);
+ ProvinceDefinition::adjacency_t const* adj =
+ selected_province_definition.get_adjacency_to(province_definition);
+
if (adj != nullptr) {
colour_argb_t::integer_type base_int;
switch (adj->get_type()) {
- using enum Province::adjacency_t::type_t;
+ using enum ProvinceDefinition::adjacency_t::type_t;
case LAND: base_int = 0x00FF00; break;
case WATER: base_int = 0x0000FF; break;
case COASTAL: base_int = 0xF9D199; break;
@@ -252,20 +270,24 @@ bool GameManager::load_hardcoded_defines() {
base = colour_argb_t::from_integer(base_int).with_alpha(ALPHA_VALUE);
stripe = base;
}
- if (selected_province->has_adjacency_going_through(&province)) {
+
+ if (selected_province_definition.has_adjacency_going_through(province_definition)) {
stripe = (0xFFFF00_argb).with_alpha(ALPHA_VALUE);
}
return { base, stripe };
}
+
return colour_argb_t::null();
}
},
{
- "mapmode_port", [](Map const& map, Province const& province) -> Mapmode::base_stripe_t {
- if (province.has_port()) {
+ "mapmode_port", [](Map const& map, ProvinceInstance const& province) -> Mapmode::base_stripe_t {
+ ProvinceDefinition const& province_definition = province.get_province_definition();
+
+ if (province_definition.has_port()) {
return (0xFFFFFF_argb).with_alpha(ALPHA_VALUE);
- } else if (!province.is_water()) {
+ } else if (!province_definition.is_water()) {
return (0x333333_argb).with_alpha(ALPHA_VALUE);
} else {
return colour_argb_t::null();
diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp
index b7b818e..58e5232 100644
--- a/src/openvic-simulation/country/CountryInstance.cpp
+++ b/src/openvic-simulation/country/CountryInstance.cpp
@@ -1,5 +1,7 @@
#include "CountryInstance.hpp"
+#include "openvic-simulation/country/Country.hpp"
+#include "openvic-simulation/history/CountryHistory.hpp"
#include "openvic-simulation/military/UnitInstance.hpp"
using namespace OpenVic;
diff --git a/src/openvic-simulation/country/CountryInstance.hpp b/src/openvic-simulation/country/CountryInstance.hpp
index 7efd930..33cee61 100644
--- a/src/openvic-simulation/country/CountryInstance.hpp
+++ b/src/openvic-simulation/country/CountryInstance.hpp
@@ -1,12 +1,22 @@
#pragma once
-#include "openvic-simulation/country/Country.hpp"
-#include "openvic-simulation/history/CountryHistory.hpp"
-#include "openvic-simulation/map/Province.hpp"
+#include <vector>
+
+#include "openvic-simulation/types/Date.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
#include "openvic-simulation/utility/Getters.hpp"
namespace OpenVic {
- struct UnitInstanceManager;
+ struct Country;
+ struct Culture;
+ struct Religion;
+ struct CountryParty;
+ struct Ideology;
+ struct ProvinceDefinition;
+ struct GovernmentType;
+ struct NationalValue;
+ struct Reform;
+ struct CountryHistoryEntry;
/* Representation of an existing country that is currently in-game. */
struct CountryInstance {
@@ -19,7 +29,9 @@ namespace OpenVic {
CountryParty const* PROPERTY_RW(ruling_party);
Date PROPERTY_RW(last_election);
fixed_point_map_t<Ideology const*> PROPERTY(upper_house);
- Province const* PROPERTY_RW(capital);
+ // TODO - should this be ProvinceInstance and/or non-const pointer?
+ // Currently ProvinceDefinition as that's what CountryHistoryEntry has (loaded prior to ProvinceInstance generation)
+ ProvinceDefinition const* PROPERTY_RW(capital);
GovernmentType const* PROPERTY_RW(government_type);
fixed_point_t PROPERTY_RW(plurality);
NationalValue const* PROPERTY_RW(national_value);
@@ -44,6 +56,11 @@ namespace OpenVic {
bool apply_history_to_country(CountryHistoryEntry const* entry);
};
+ struct CountryManager;
+ struct CountryHistoryManager;
+ struct UnitInstanceManager;
+ struct Map;
+
struct CountryInstanceManager {
private:
std::vector<CountryInstance> PROPERTY(country_instances);
@@ -55,4 +72,4 @@ namespace OpenVic {
CountryHistoryManager const& history_manager, Date date, UnitInstanceManager& unit_instance_manager, Map& map
);
};
-} // namespace OpenVic
+}
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp
index f99417f..ee0eaf4 100644
--- a/src/openvic-simulation/dataloader/Dataloader.cpp
+++ b/src/openvic-simulation/dataloader/Dataloader.cpp
@@ -562,11 +562,13 @@ bool Dataloader::_load_history(GameManager& game_manager, bool unused_history_fi
ret &= apply_to_files(
province_history_files,
- [this, &game_manager, &province_history_manager, &map, unused_history_file_warnings](fs::path const& file) -> bool {
+ [this, &game_manager, &province_history_manager, &map, unused_history_file_warnings](
+ fs::path const& file
+ ) -> bool {
const std::string filename = file.stem().string();
const std::string_view province_id = extract_basic_identifier_prefix(filename);
- Province const* province = map.get_province_by_identifier(province_id);
+ ProvinceDefinition const* province = map.get_province_definition_by_identifier(province_id);
if (province == nullptr) {
if (unused_history_file_warnings) {
Logger::warning("Found history file for non-existent province: ", province_id);
@@ -709,7 +711,7 @@ bool Dataloader::_load_map_dir(GameManager& game_manager) const {
bool ret = expect_dictionary_keys(
"max_provinces", ONE_EXACTLY,
- expect_uint<Province::index_t>(std::bind_front(&Map::set_max_provinces, &map)),
+ expect_uint<ProvinceDefinition::index_t>(std::bind_front(&Map::set_max_provinces, &map)),
"sea_starts", ONE_EXACTLY,
expect_list_reserve_length(
water_province_identifiers, expect_identifier(vector_callback(water_province_identifiers))
diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp
index 0bb4d5b..92682e7 100644
--- a/src/openvic-simulation/dataloader/NodeTools.hpp
+++ b/src/openvic-simulation/dataloader/NodeTools.hpp
@@ -473,8 +473,8 @@ namespace OpenVic {
}
template<typename T>
- Callback<T const&> auto vector_callback_pointer(std::vector<T const*>& vec) {
- return [&vec](T const& val) -> bool {
+ Callback<T&> auto vector_callback_pointer(std::vector<T*>& vec) {
+ return [&vec](T& val) -> bool {
vec.emplace_back(&val);
return true;
};
diff --git a/src/openvic-simulation/diplomacy/CountryRelation.cpp b/src/openvic-simulation/diplomacy/CountryRelation.cpp
index d07739c..2e058ab 100644
--- a/src/openvic-simulation/diplomacy/CountryRelation.cpp
+++ b/src/openvic-simulation/diplomacy/CountryRelation.cpp
@@ -2,6 +2,7 @@
#include <cassert>
+#include "openvic-simulation/country/Country.hpp"
#include "openvic-simulation/country/CountryInstance.hpp"
#include "openvic-simulation/utility/ErrorMacros.hpp"
diff --git a/src/openvic-simulation/history/CountryHistory.cpp b/src/openvic-simulation/history/CountryHistory.cpp
index 1bd3dd0..90fe995 100644
--- a/src/openvic-simulation/history/CountryHistory.cpp
+++ b/src/openvic-simulation/history/CountryHistory.cpp
@@ -68,7 +68,7 @@ bool CountryHistoryMap::_load_history_entry(
);
},
"capital", ZERO_OR_ONE,
- game_manager.get_map().expect_province_identifier(assign_variable_callback_pointer_opt(entry.capital)),
+ game_manager.get_map().expect_province_definition_identifier(assign_variable_callback_pointer_opt(entry.capital)),
"primary_culture", ZERO_OR_ONE,
culture_manager.expect_culture_identifier(assign_variable_callback_pointer_opt(entry.primary_culture)),
"culture", ZERO_OR_MORE, culture_manager.expect_culture_identifier(
@@ -148,7 +148,9 @@ bool CountryHistoryMap::_load_history_entry(
/* If the first government type is null, the "government" section will have already output
* an error, so no need to output another one here. */
if (government_type != nullptr && flag_override_government_type != nullptr) {
- ret &= map_callback(entry.government_flag_overrides, government_type)(flag_override_government_type);
+ ret &= map_callback(
+ entry.government_flag_overrides, government_type)(flag_override_government_type
+ );
}
return ret;
} else {
diff --git a/src/openvic-simulation/history/CountryHistory.hpp b/src/openvic-simulation/history/CountryHistory.hpp
index 1c1b7f1..b183ea8 100644
--- a/src/openvic-simulation/history/CountryHistory.hpp
+++ b/src/openvic-simulation/history/CountryHistory.hpp
@@ -1,25 +1,29 @@
#pragma once
#include <optional>
+#include <vector>
-#include "openvic-simulation/country/Country.hpp"
#include "openvic-simulation/history/HistoryMap.hpp"
-#include "openvic-simulation/map/Province.hpp"
-#include "openvic-simulation/military/Deployment.hpp"
-#include "openvic-simulation/misc/Decision.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/pop/Culture.hpp"
-#include "openvic-simulation/pop/Religion.hpp"
-#include "openvic-simulation/research/Invention.hpp"
-#include "openvic-simulation/research/Technology.hpp"
#include "openvic-simulation/types/Date.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
#include "openvic-simulation/types/OrderedContainers.hpp"
namespace OpenVic {
struct CountryHistoryMap;
+ struct Country;
+ struct Culture;
+ struct Religion;
+ struct CountryParty;
+ struct Ideology;
+ struct ProvinceDefinition;
+ struct GovernmentType;
+ struct NationalValue;
+ struct Reform;
+ struct Deployment;
+ struct TechnologySchool;
+ struct Technology;
+ struct Invention;
+ struct Decision;
struct CountryHistoryEntry : HistoryEntry {
friend struct CountryHistoryMap;
@@ -33,7 +37,7 @@ namespace OpenVic {
std::optional<CountryParty const*> PROPERTY(ruling_party);
std::optional<Date> PROPERTY(last_election);
fixed_point_map_t<Ideology const*> PROPERTY(upper_house);
- std::optional<Province const*> PROPERTY(capital);
+ std::optional<ProvinceDefinition const*> PROPERTY(capital);
std::optional<GovernmentType const*> PROPERTY(government_type);
std::optional<fixed_point_t> PROPERTY(plurality);
std::optional<NationalValue const*> PROPERTY(national_value);
@@ -59,6 +63,8 @@ namespace OpenVic {
CountryHistoryEntry(Country const& new_country, Date new_date);
};
+ class Dataloader;
+ struct DeploymentManager;
struct CountryHistoryManager;
struct CountryHistoryMap : HistoryMap<CountryHistoryEntry, Dataloader const&, DeploymentManager&> {
@@ -96,4 +102,4 @@ namespace OpenVic {
);
};
-} // namespace OpenVic
+}
diff --git a/src/openvic-simulation/history/DiplomaticHistory.cpp b/src/openvic-simulation/history/DiplomaticHistory.cpp
index 22ee765..f56b3dc 100644
--- a/src/openvic-simulation/history/DiplomaticHistory.cpp
+++ b/src/openvic-simulation/history/DiplomaticHistory.cpp
@@ -1,8 +1,6 @@
#include "DiplomaticHistory.hpp"
#include "openvic-simulation/GameManager.hpp"
-#include "openvic-simulation/dataloader/NodeTools.hpp"
-#include "openvic-simulation/history/Period.hpp"
using namespace OpenVic;
using namespace OpenVic::NodeTools;
@@ -13,8 +11,9 @@ WarHistory::added_wargoal_t::added_wargoal_t(
Country const* new_receiver,
WargoalType const* new_wargoal,
std::optional<Country const*> new_third_party,
- std::optional<Province const*> new_target
-) : added { new_added }, actor { new_actor }, receiver { new_receiver }, wargoal { new_wargoal }, third_party { new_third_party }, target { new_target } {}
+ std::optional<ProvinceDefinition const*> new_target
+) : added { new_added }, actor { new_actor }, receiver { new_receiver }, wargoal { new_wargoal },
+ third_party { new_third_party }, target { new_target } {}
WarHistory::war_participant_t::war_participant_t(
Country const* new_country,
@@ -26,7 +25,8 @@ WarHistory::WarHistory(
std::vector<war_participant_t>&& new_attackers,
std::vector<war_participant_t>&& new_defenders,
std::vector<added_wargoal_t>&& new_wargoals
-) : war_name { new_war_name }, attackers { std::move(new_attackers) }, defenders { std::move(new_defenders) }, wargoals { std::move(new_wargoals) } {}
+) : war_name { new_war_name }, attackers { std::move(new_attackers) }, defenders { std::move(new_defenders) },
+ wargoals { std::move(new_wargoals) } {}
AllianceHistory::AllianceHistory(
Country const* new_first,
@@ -56,7 +56,9 @@ void DiplomaticHistoryManager::reserve_more_wars(size_t size) {
}
void DiplomaticHistoryManager::lock_diplomatic_history() {
- Logger::info("Locked diplomacy history registry after registering ", alliances.size() + subjects.size() + wars.size(), " items");
+ Logger::info(
+ "Locked diplomacy history registry after registering ", alliances.size() + subjects.size() + wars.size(), " items"
+ );
locked = true;
}
@@ -66,7 +68,7 @@ bool DiplomaticHistoryManager::is_locked() const {
std::vector<AllianceHistory const*> DiplomaticHistoryManager::get_alliances(Date date) const {
std::vector<AllianceHistory const*> ret {};
- for (const auto& alliance : alliances) {
+ for (auto const& alliance : alliances) {
if (alliance.period.is_date_in_period(date)) {
ret.push_back(&alliance);
}
@@ -76,7 +78,7 @@ std::vector<AllianceHistory const*> DiplomaticHistoryManager::get_alliances(Date
std::vector<ReparationsHistory const*> DiplomaticHistoryManager::get_reparations(Date date) const {
std::vector<ReparationsHistory const*> ret {};
- for (const auto& reparation : reparations) {
+ for (auto const& reparation : reparations) {
if (reparation.period.is_date_in_period(date)) {
ret.push_back(&reparation);
}
@@ -86,7 +88,7 @@ std::vector<ReparationsHistory const*> DiplomaticHistoryManager::get_reparations
std::vector<SubjectHistory const*> DiplomaticHistoryManager::get_subjects(Date date) const {
std::vector<SubjectHistory const*> ret {};
- for (const auto& subject : subjects) {
+ for (auto const& subject : subjects) {
if (subject.period.is_date_in_period(date)) {
ret.push_back(&subject);
}
@@ -96,9 +98,9 @@ std::vector<SubjectHistory const*> DiplomaticHistoryManager::get_subjects(Date d
std::vector<WarHistory const*> DiplomaticHistoryManager::get_wars(Date date) const {
std::vector<WarHistory const*> ret;
- for (const auto& war : wars) {
+ for (auto const& war : wars) {
Date start {};
- for (const auto& wargoal : war.wargoals) {
+ for (auto const& wargoal : war.wargoals) {
if (wargoal.added < start) start = wargoal.added;
}
if (start >= date) ret.push_back(&war);
@@ -115,8 +117,10 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file(CountryManager const&
std::optional<Date> end {};
bool ret = expect_dictionary_keys(
- "first", ONE_EXACTLY, country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(first)),
- "second", ONE_EXACTLY, country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(second)),
+ "first", ONE_EXACTLY,
+ country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(first)),
+ "second", ONE_EXACTLY,
+ country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(second)),
"start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)),
"end_date", ZERO_OR_ONE, expect_date_identifier_or_string(assign_variable_callback(end))
)(node);
@@ -131,8 +135,10 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file(CountryManager const&
std::optional<Date> end {};
bool ret = expect_dictionary_keys(
- "first", ONE_EXACTLY, country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(overlord)),
- "second", ONE_EXACTLY, country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(subject)),
+ "first", ONE_EXACTLY,
+ country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(overlord)),
+ "second", ONE_EXACTLY,
+ country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(subject)),
"start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)),
"end_date", ZERO_OR_ONE, expect_date_identifier_or_string(assign_variable_callback(end))
)(node);
@@ -147,8 +153,10 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file(CountryManager const&
std::optional<Date> end {};
bool ret = expect_dictionary_keys(
- "first", ONE_EXACTLY, country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(overlord)),
- "second", ONE_EXACTLY, country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(subject)),
+ "first", ONE_EXACTLY,
+ country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(overlord)),
+ "second", ONE_EXACTLY,
+ country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(subject)),
"start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)),
"end_date", ZERO_OR_ONE, expect_date_identifier_or_string(assign_variable_callback(end))
)(node);
@@ -163,8 +171,10 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file(CountryManager const&
std::optional<Date> end {};
bool ret = expect_dictionary_keys(
- "first", ONE_EXACTLY, country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(overlord)),
- "second", ONE_EXACTLY, country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(subject)),
+ "first", ONE_EXACTLY,
+ country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(overlord)),
+ "second", ONE_EXACTLY,
+ country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(subject)),
"start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)),
"end_date", ZERO_OR_ONE, expect_date_identifier_or_string(assign_variable_callback(end))
)(node);
@@ -179,8 +189,10 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file(CountryManager const&
std::optional<Date> end {};
bool ret = expect_dictionary_keys(
- "first", ONE_EXACTLY, country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(receiver)),
- "second", ONE_EXACTLY, country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(sender)),
+ "first", ONE_EXACTLY,
+ country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(receiver)),
+ "second", ONE_EXACTLY,
+ country_manager.expect_country_identifier_or_string(assign_variable_callback_pointer(sender)),
"start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)),
"end_date", ZERO_OR_ONE, expect_date_identifier_or_string(assign_variable_callback(end))
)(node);
@@ -199,88 +211,133 @@ bool DiplomaticHistoryManager::load_war_history_file(GameManager const& game_man
Date current_date {};
bool ret = expect_dictionary_keys_and_default(
- [&game_manager, &attackers, &defenders, &wargoals, &current_date, &name](std::string_view key, ast::NodeCPtr node) -> bool {
+ [&game_manager, &attackers, &defenders, &wargoals, &current_date, &name](
+ std::string_view key, ast::NodeCPtr node
+ ) -> bool {
bool ret = expect_date_str(assign_variable_callback(current_date))(key);
+
ret &= expect_dictionary_keys(
- "add_attacker", ZERO_OR_MORE, game_manager.get_country_manager().expect_country_identifier([&attackers, &current_date, &name](Country const& country) -> bool {
- for (const auto& attacker : attackers) {
- if (attacker.get_country() == &country) {
- Logger::error("In history of war ", name, " at date ", current_date.to_string(), ": Attempted to add attacking country ", attacker.get_country()->get_identifier(), " which is already present!");
- return false;
+ "add_attacker", ZERO_OR_MORE, game_manager.get_country_manager().expect_country_identifier(
+ [&attackers, &current_date, &name](Country const& country) -> bool {
+ for (auto const& attacker : attackers) {
+ if (attacker.get_country() == &country) {
+ Logger::error(
+ "In history of war ", name, " at date ", current_date.to_string(),
+ ": Attempted to add attacking country ", attacker.get_country()->get_identifier(),
+ " which is already present!"
+ );
+ return false;
+ }
}
- }
- attackers.push_back({ &country, { current_date, {} } });
- return true;
- }),
- "add_defender", ZERO_OR_MORE, game_manager.get_country_manager().expect_country_identifier([&defenders, &current_date, &name](Country const& country) -> bool {
- for (const auto& defender : defenders) {
- if (defender.get_country() == &country) {
- Logger::error("In history of war ", name, " at date ", current_date.to_string(), ": Attempted to add defending country ", defender.get_country()->get_identifier(), " which is already present!");
- return false;
- }
+ attackers.push_back({ &country, { current_date, {} } });
+ return true;
}
-
- defenders.push_back({ &country, { current_date, {} } });
- return true;
- }),
- "rem_attacker", ZERO_OR_MORE, game_manager.get_country_manager().expect_country_identifier([&attackers, &current_date, &name](Country const& country) -> bool {
- WarHistory::war_participant_t* participant_to_remove = nullptr;
-
- for (auto& attacker : attackers) {
- if (attacker.country == &country) {
- participant_to_remove = &attacker;
- break;
+ ),
+ "add_defender", ZERO_OR_MORE, game_manager.get_country_manager().expect_country_identifier(
+ [&defenders, &current_date, &name](Country const& country) -> bool {
+ for (auto const& defender : defenders) {
+ if (defender.get_country() == &country) {
+ Logger::error(
+ "In history of war ", name, " at date ", current_date.to_string(),
+ ": Attempted to add defending country ", defender.get_country()->get_identifier(),
+ " which is already present!"
+ );
+ return false;
+ }
}
- }
- if (participant_to_remove == nullptr) {
- Logger::warning("In history of war ", name, " at date ", current_date.to_string(), ": Attempted to remove attacking country ", country.get_identifier(), " which was not present!");
+ defenders.push_back({ &country, { current_date, {} } });
return true;
}
+ ),
+ "rem_attacker", ZERO_OR_MORE, game_manager.get_country_manager().expect_country_identifier(
+ [&attackers, &current_date, &name](Country const& country) -> bool {
+ WarHistory::war_participant_t* participant_to_remove = nullptr;
+
+ for (auto& attacker : attackers) {
+ if (attacker.country == &country) {
+ participant_to_remove = &attacker;
+ break;
+ }
+ }
- return participant_to_remove->period.try_set_end(current_date);
- }),
- "rem_defender", ZERO_OR_MORE, game_manager.get_country_manager().expect_country_identifier([&defenders, &current_date, &name](Country const& country) -> bool {
- WarHistory::war_participant_t* participant_to_remove = nullptr;
-
- for (auto& defender : defenders) {
- if (defender.country == &country) {
- participant_to_remove = &defender;
- break;
+ if (participant_to_remove == nullptr) {
+ Logger::warning(
+ "In history of war ", name, " at date ", current_date.to_string(),
+ ": Attempted to remove attacking country ", country.get_identifier(),
+ " which was not present!"
+ );
+ return true;
}
- }
- if (participant_to_remove == nullptr) {
- Logger::warning("In history of war ", name, " at date ", current_date.to_string(), ": Attempted to remove attacking country ", country.get_identifier(), " which was not present!");
- return true;
+ return participant_to_remove->period.try_set_end(current_date);
}
+ ),
+ "rem_defender", ZERO_OR_MORE, game_manager.get_country_manager().expect_country_identifier(
+ [&defenders, &current_date, &name](Country const& country) -> bool {
+ WarHistory::war_participant_t* participant_to_remove = nullptr;
+
+ for (auto& defender : defenders) {
+ if (defender.country == &country) {
+ participant_to_remove = &defender;
+ break;
+ }
+ }
- return participant_to_remove->period.try_set_end(current_date);
- }),
+ if (participant_to_remove == nullptr) {
+ Logger::warning(
+ "In history of war ", name, " at date ", current_date.to_string(),
+ ": Attempted to remove attacking country ", country.get_identifier(),
+ " which was not present!"
+ );
+ return true;
+ }
+
+ return participant_to_remove->period.try_set_end(current_date);
+ }
+ ),
"war_goal", ZERO_OR_MORE, [&game_manager, &wargoals, &current_date](ast::NodeCPtr value) -> bool {
Country const* actor = nullptr;
Country const* receiver = nullptr;
WargoalType const* type = nullptr;
std::optional<Country const*> third_party {};
- std::optional<Province const*> target {};
+ std::optional<ProvinceDefinition const*> target {};
bool ret = expect_dictionary_keys(
- "actor", ONE_EXACTLY, game_manager.get_country_manager().expect_country_identifier(assign_variable_callback_pointer(actor)),
- "receiver", ONE_EXACTLY, game_manager.get_country_manager().expect_country_identifier(assign_variable_callback_pointer(receiver)),
- "casus_belli", ONE_EXACTLY, game_manager.get_military_manager().get_wargoal_type_manager().expect_wargoal_type_identifier(assign_variable_callback_pointer(type)),
- "country", ZERO_OR_ONE, game_manager.get_country_manager().expect_country_identifier(assign_variable_callback_pointer(*third_party)),
- "state_province_id", ZERO_OR_ONE, game_manager.get_map().expect_province_identifier(assign_variable_callback_pointer(*target))
+ "actor", ONE_EXACTLY,
+ game_manager.get_country_manager().expect_country_identifier(
+ assign_variable_callback_pointer(actor)
+ ),
+ "receiver", ONE_EXACTLY,
+ game_manager.get_country_manager().expect_country_identifier(
+ assign_variable_callback_pointer(receiver)
+ ),
+ "casus_belli", ONE_EXACTLY,
+ game_manager.get_military_manager().get_wargoal_type_manager().expect_wargoal_type_identifier(
+ assign_variable_callback_pointer(type)
+ ),
+ "country", ZERO_OR_ONE,
+ game_manager.get_country_manager().expect_country_identifier(
+ assign_variable_callback_pointer(*third_party)
+ ),
+ "state_province_id", ZERO_OR_ONE,
+ game_manager.get_map().expect_province_definition_identifier(
+ assign_variable_callback_pointer(*target)
+ )
)(value);
+
wargoals.push_back({ current_date, actor, receiver, type, third_party, target });
return ret;
}
)(node);
+
return ret;
},
"name", ZERO_OR_ONE, expect_string(assign_variable_callback(name))
)(root);
wars.push_back({ name, std::move(attackers), std::move(defenders), std::move(wargoals) });
+
return ret;
-} \ No newline at end of file
+}
diff --git a/src/openvic-simulation/history/DiplomaticHistory.hpp b/src/openvic-simulation/history/DiplomaticHistory.hpp
index 35ba6fb..7ae5114 100644
--- a/src/openvic-simulation/history/DiplomaticHistory.hpp
+++ b/src/openvic-simulation/history/DiplomaticHistory.hpp
@@ -1,15 +1,18 @@
#pragma once
-#include <vector>
#include <optional>
+#include <vector>
-#include "openvic-simulation/country/Country.hpp"
-#include "openvic-simulation/military/Wargoal.hpp"
-#include "openvic-simulation/map/Province.hpp"
+#include "openvic-simulation/dataloader/NodeTools.hpp"
#include "openvic-simulation/history/Period.hpp"
+#include "openvic-simulation/types/Date.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
namespace OpenVic {
struct DiplomaticHistoryManager;
+ struct Country;
+ struct WargoalType;
+ struct ProvinceDefinition;
struct WarHistory {
friend struct DiplomaticHistoryManager;
@@ -22,10 +25,15 @@ namespace OpenVic {
Country const* PROPERTY(actor);
Country const* PROPERTY(receiver);
WargoalType const* PROPERTY(wargoal);
+
+ // TODO - could these just be nullptr when unset rather than using optionals?
std::optional<Country const*> PROPERTY(third_party);
- std::optional<Province const*> PROPERTY(target);
+ std::optional<ProvinceDefinition const*> PROPERTY(target);
- added_wargoal_t(Date new_added, Country const* new_actor, Country const* new_receiver, WargoalType const* new_wargoal, std::optional<Country const*> new_third_party, std::optional<Province const*> new_target);
+ added_wargoal_t(
+ Date new_added, Country const* new_actor, Country const* new_receiver, WargoalType const* new_wargoal,
+ std::optional<Country const*> new_third_party, std::optional<ProvinceDefinition const*> new_target
+ );
};
struct war_participant_t {
@@ -39,12 +47,17 @@ namespace OpenVic {
};
private:
- std::string PROPERTY(war_name); // edge cases where this is empty/undef for some reason, probably need to just generate war names like usual for that.
+ /* Edge cases where this is empty/undef for some reason,
+ * probably need to just generate war names like usual for that. */
+ std::string PROPERTY(war_name);
std::vector<war_participant_t> PROPERTY(attackers);
std::vector<war_participant_t> PROPERTY(defenders);
std::vector<added_wargoal_t> PROPERTY(wargoals);
- WarHistory(std::string_view new_war_name, std::vector<war_participant_t>&& new_attackers, std::vector<war_participant_t>&& new_defenders, std::vector<added_wargoal_t>&& new_wargoals);
+ WarHistory(
+ std::string_view new_war_name, std::vector<war_participant_t>&& new_attackers,
+ std::vector<war_participant_t>&& new_defenders, std::vector<added_wargoal_t>&& new_wargoals
+ );
};
struct AllianceHistory {
@@ -87,6 +100,9 @@ namespace OpenVic {
SubjectHistory(Country const* new_overlord, Country const* new_subject, const type_t new_type, const Period period);
};
+ struct CountryManager;
+ struct GameManager;
+
struct DiplomaticHistoryManager {
private:
std::vector<AllianceHistory> alliances;
@@ -105,10 +121,11 @@ namespace OpenVic {
std::vector<AllianceHistory const*> get_alliances(Date date) const;
std::vector<ReparationsHistory const*> get_reparations(Date date) const;
std::vector<SubjectHistory const*> get_subjects(Date date) const;
- /* Returns all wars that begin before date. NOTE: Some wargoals may be added or countries may join after date, should be checked for by functions that use get_wars() */
+ /* Returns all wars that begin before date. NOTE: Some wargoals may be added or countries may join after date,
+ * should be checked for by functions that use get_wars() */
std::vector<WarHistory const*> get_wars(Date date) const;
bool load_diplomacy_history_file(CountryManager const& country_manager, ast::NodeCPtr root);
bool load_war_history_file(GameManager const& game_manager, ast::NodeCPtr root);
};
-} // namespace OpenVic \ No newline at end of file
+}
diff --git a/src/openvic-simulation/history/Period.cpp b/src/openvic-simulation/history/Period.cpp
index 37758a1..2c6589c 100644
--- a/src/openvic-simulation/history/Period.cpp
+++ b/src/openvic-simulation/history/Period.cpp
@@ -1,4 +1,6 @@
-#include "openvic-simulation/history/Period.hpp"
+#include "Period.hpp"
+
+#include "openvic-simulation/utility/Logger.hpp"
using namespace OpenVic;
@@ -24,4 +26,4 @@ bool Period::try_set_end(const Date date) {
end_date = date;
return true;
-} \ No newline at end of file
+}
diff --git a/src/openvic-simulation/history/Period.hpp b/src/openvic-simulation/history/Period.hpp
index c788be9..d8b5ade 100644
--- a/src/openvic-simulation/history/Period.hpp
+++ b/src/openvic-simulation/history/Period.hpp
@@ -1,8 +1,8 @@
#pragma once
#include <optional>
+
#include "openvic-simulation/types/Date.hpp"
-#include "openvic-simulation/utility/Logger.hpp"
namespace OpenVic {
struct Period {
@@ -15,4 +15,4 @@ namespace OpenVic {
bool is_date_in_period(const Date date) const;
bool try_set_end(const Date date);
};
-} \ No newline at end of file
+}
diff --git a/src/openvic-simulation/history/ProvinceHistory.cpp b/src/openvic-simulation/history/ProvinceHistory.cpp
index c22567b..645cf8d 100644
--- a/src/openvic-simulation/history/ProvinceHistory.cpp
+++ b/src/openvic-simulation/history/ProvinceHistory.cpp
@@ -1,15 +1,15 @@
#include "ProvinceHistory.hpp"
#include "openvic-simulation/GameManager.hpp"
-#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/map/ProvinceDefinition.hpp"
using namespace OpenVic;
using namespace OpenVic::NodeTools;
-ProvinceHistoryEntry::ProvinceHistoryEntry(Province const& new_province, Date new_date)
+ProvinceHistoryEntry::ProvinceHistoryEntry(ProvinceDefinition const& new_province, Date new_date)
: HistoryEntry { new_date }, province { new_province } {}
-ProvinceHistoryMap::ProvinceHistoryMap(Province const& new_province) : province { new_province } {}
+ProvinceHistoryMap::ProvinceHistoryMap(ProvinceDefinition const& new_province) : province { new_province } {}
std::unique_ptr<ProvinceHistoryEntry> ProvinceHistoryMap::_make_entry(Date date) const {
return std::unique_ptr<ProvinceHistoryEntry> { new ProvinceHistoryEntry { province, date } };
@@ -24,8 +24,8 @@ bool ProvinceHistoryMap::_load_history_entry(
IdeologyManager const& ideology_manager = game_manager.get_politics_manager().get_ideology_manager();
TerrainTypeManager const& terrain_type_manager = game_manager.get_map().get_terrain_type_manager();
- using enum Province::colony_status_t;
- static const string_map_t<Province::colony_status_t> colony_status_map {
+ using enum ProvinceInstance::colony_status_t;
+ static const string_map_t<ProvinceInstance::colony_status_t> colony_status_map {
{ "0", STATE }, { "1", PROTECTORATE }, { "2", COLONY }
};
@@ -66,7 +66,7 @@ bool ProvinceHistoryMap::_load_history_entry(
expect_identifier(expect_mapped_string(colony_status_map, assign_variable_callback(entry.colonial))),
"is_slave", ZERO_OR_ONE, expect_bool(assign_variable_callback(entry.slave)),
"trade_goods", ZERO_OR_ONE, good_manager.expect_good_identifier(assign_variable_callback_pointer_opt(entry.rgo)),
- "life_rating", ZERO_OR_ONE, expect_uint<Province::life_rating_t>(assign_variable_callback(entry.life_rating)),
+ "life_rating", ZERO_OR_ONE, expect_uint<ProvinceInstance::life_rating_t>(assign_variable_callback(entry.life_rating)),
"terrain", ZERO_OR_ONE, terrain_type_manager.expect_terrain_type_identifier(
assign_variable_callback_pointer_opt(entry.terrain_type)
),
@@ -101,8 +101,8 @@ bool ProvinceHistoryMap::_load_history_entry(
ret &= map_callback(entry.state_buildings, building_type)(level);
} else {
Logger::error(
- "Attempted to add province building \"", building_type, "\" to state building list of province history for ",
- entry.get_province()
+ "Attempted to add province building \"", building_type,
+ "\" to state building list of province history for ", entry.get_province()
);
ret = false;
}
@@ -121,7 +121,9 @@ void ProvinceHistoryManager::reserve_more_province_histories(size_t size) {
}
void ProvinceHistoryManager::lock_province_histories(Map const& map, bool detailed_errors) {
- std::vector<bool> province_checklist(map.get_province_count());
+ std::vector<ProvinceDefinition> const& provinces = map.get_province_definitions();
+
+ std::vector<bool> province_checklist(provinces.size());
for (decltype(province_histories)::value_type const& entry : province_histories) {
province_checklist[entry.first->get_index() - 1] = true;
}
@@ -129,7 +131,7 @@ void ProvinceHistoryManager::lock_province_histories(Map const& map, bool detail
size_t missing = 0;
for (size_t idx = 0; idx < province_checklist.size(); ++idx) {
if (!province_checklist[idx]) {
- Province const& province = *map.get_province_by_index(idx + 1);
+ ProvinceDefinition const& province = provinces[idx];
if (!province.is_water()) {
if (detailed_errors) {
Logger::warning("Province history missing for province: ", province.get_identifier());
@@ -150,7 +152,7 @@ bool ProvinceHistoryManager::is_locked() const {
return locked;
}
-ProvinceHistoryMap const* ProvinceHistoryManager::get_province_history(Province const* province) const {
+ProvinceHistoryMap const* ProvinceHistoryManager::get_province_history(ProvinceDefinition const* province) const {
if (province == nullptr) {
Logger::error("Attempted to access history of null province");
return nullptr;
@@ -164,7 +166,7 @@ ProvinceHistoryMap const* ProvinceHistoryManager::get_province_history(Province
}
}
-ProvinceHistoryMap* ProvinceHistoryManager::_get_or_make_province_history(Province const& province) {
+ProvinceHistoryMap* ProvinceHistoryManager::_get_or_make_province_history(ProvinceDefinition const& province) {
decltype(province_histories)::iterator it = province_histories.find(&province);
if (it == province_histories.end()) {
const std::pair<decltype(province_histories)::iterator, bool> result =
@@ -180,7 +182,7 @@ ProvinceHistoryMap* ProvinceHistoryManager::_get_or_make_province_history(Provin
}
bool ProvinceHistoryManager::load_province_history_file(
- GameManager const& game_manager, Province const& province, ast::NodeCPtr root
+ GameManager const& game_manager, ProvinceDefinition const& province, ast::NodeCPtr root
) {
if (locked) {
Logger::error(
@@ -229,8 +231,8 @@ bool ProvinceHistoryManager::load_pop_history_file(
Logger::error("Attempted to load pop history file after province history registry was locked!");
return false;
}
- return game_manager.get_map().expect_province_dictionary(
- [this, &game_manager, date, non_integer_size](Province const& province, ast::NodeCPtr node) -> bool {
+ return game_manager.get_map().expect_province_definition_dictionary(
+ [this, &game_manager, date, non_integer_size](ProvinceDefinition const& province, ast::NodeCPtr node) -> bool {
ProvinceHistoryMap* province_history = _get_or_make_province_history(province);
if (province_history != nullptr) {
return province_history->_load_province_pop_history(game_manager, date, node, non_integer_size);
diff --git a/src/openvic-simulation/history/ProvinceHistory.hpp b/src/openvic-simulation/history/ProvinceHistory.hpp
index 7611907..27d744d 100644
--- a/src/openvic-simulation/history/ProvinceHistory.hpp
+++ b/src/openvic-simulation/history/ProvinceHistory.hpp
@@ -1,39 +1,49 @@
#pragma once
+#include <optional>
#include <vector>
-#include "openvic-simulation/country/Country.hpp"
#include "openvic-simulation/economy/BuildingType.hpp"
-#include "openvic-simulation/economy/Good.hpp"
#include "openvic-simulation/history/HistoryMap.hpp"
-#include "openvic-simulation/map/Province.hpp"
-#include "openvic-simulation/map/TerrainType.hpp"
+#include "openvic-simulation/map/ProvinceInstance.hpp"
+#include "openvic-simulation/pop/Pop.hpp"
+#include "openvic-simulation/types/Date.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
#include "openvic-simulation/types/OrderedContainers.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
namespace OpenVic {
struct ProvinceHistoryMap;
+ struct ProvinceDefinition;
+ struct Country;
+ struct Good;
+ struct TerrainType;
+ struct Ideology;
+ struct GameManager;
struct ProvinceHistoryEntry : HistoryEntry {
friend struct ProvinceHistoryMap;
private:
- Province const& PROPERTY(province);
+ ProvinceDefinition const& PROPERTY(province);
std::optional<Country const*> PROPERTY(owner);
std::optional<Country const*> PROPERTY(controller);
- std::optional<Province::colony_status_t> PROPERTY(colonial);
+ std::optional<ProvinceInstance::colony_status_t> PROPERTY(colonial);
std::optional<bool> PROPERTY(slave);
std::vector<Country const*> PROPERTY(add_cores);
std::vector<Country const*> PROPERTY(remove_cores);
std::optional<Good const*> PROPERTY(rgo);
- std::optional<Province::life_rating_t> PROPERTY(life_rating);
+ std::optional<ProvinceInstance::life_rating_t> PROPERTY(life_rating);
std::optional<TerrainType const*> PROPERTY(terrain_type);
ordered_map<BuildingType const*, BuildingType::level_t> PROPERTY(province_buildings);
ordered_map<BuildingType const*, BuildingType::level_t> PROPERTY(state_buildings);
fixed_point_map_t<Ideology const*> PROPERTY(party_loyalties);
+
+ // TODO - use minimal pop representation (size, type, culture, religion, consciousness, militancy, rebel type)
std::vector<Pop> PROPERTY(pops);
- ProvinceHistoryEntry(Province const& new_province, Date new_date);
+ ProvinceHistoryEntry(ProvinceDefinition const& new_province, Date new_date);
bool _load_province_pop_history(GameManager const& game_manager, ast::NodeCPtr root, bool *non_integer_size);
};
@@ -44,10 +54,10 @@ namespace OpenVic {
friend struct ProvinceHistoryManager;
private:
- Province const& PROPERTY(province);
+ ProvinceDefinition const& PROPERTY(province);
protected:
- ProvinceHistoryMap(Province const& new_province);
+ ProvinceHistoryMap(ProvinceDefinition const& new_province);
std::unique_ptr<ProvinceHistoryEntry> _make_entry(Date date) const override;
bool _load_history_entry(GameManager const& game_manager, ProvinceHistoryEntry& entry, ast::NodeCPtr root) override;
@@ -58,12 +68,14 @@ namespace OpenVic {
);
};
+ struct Map;
+
struct ProvinceHistoryManager {
private:
- ordered_map<Province const*, ProvinceHistoryMap> province_histories;
+ ordered_map<ProvinceDefinition const*, ProvinceHistoryMap> province_histories;
bool locked = false;
- ProvinceHistoryMap* _get_or_make_province_history(Province const& province);
+ ProvinceHistoryMap* _get_or_make_province_history(ProvinceDefinition const& province);
public:
ProvinceHistoryManager() = default;
@@ -72,9 +84,11 @@ namespace OpenVic {
void lock_province_histories(Map const& map, bool detailed_errors);
bool is_locked() const;
- ProvinceHistoryMap const* get_province_history(Province const* province) const;
+ ProvinceHistoryMap const* get_province_history(ProvinceDefinition const* province) const;
- bool load_province_history_file(GameManager const& game_manager, Province const& province, ast::NodeCPtr root);
+ bool load_province_history_file(
+ GameManager const& game_manager, ProvinceDefinition const& province, ast::NodeCPtr root
+ );
bool load_pop_history_file(GameManager const& game_manager, Date date, ast::NodeCPtr root, bool *non_integer_size);
};
-} // namespace OpenVic
+}
diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp
index afbcf62..8f6471e 100644
--- a/src/openvic-simulation/map/Map.cpp
+++ b/src/openvic-simulation/map/Map.cpp
@@ -21,24 +21,24 @@ Mapmode::Mapmode(
}
const Mapmode Mapmode::ERROR_MAPMODE {
- "mapmode_error", 0, [](Map const& map, Province const& province) -> base_stripe_t {
+ "mapmode_error", 0, [](Map const& map, ProvinceInstance const& province) -> base_stripe_t {
return { 0xFFFF0000_argb, colour_argb_t::null() };
}
};
-Mapmode::base_stripe_t Mapmode::get_base_stripe_colours(Map const& map, Province const& province) const {
+Mapmode::base_stripe_t Mapmode::get_base_stripe_colours(Map const& map, ProvinceInstance const& province) const {
return colour_func ? colour_func(map, province) : colour_argb_t::null();
}
Map::Map()
- : dims { 0, 0 }, max_provinces { Province::MAX_INDEX }, selected_province { nullptr },
+ : dims { 0, 0 }, max_provinces { ProvinceDefinition::MAX_INDEX }, selected_province { nullptr },
highest_province_population { 0 }, total_map_population { 0 } {}
-bool Map::add_province(std::string_view identifier, colour_t colour) {
- if (provinces.size() >= max_provinces) {
+bool Map::add_province_definition(std::string_view identifier, colour_t colour) {
+ if (province_definitions.size() >= max_provinces) {
Logger::error(
"The map's province list is full - maximum number of provinces is ", max_provinces, " (this can be at most ",
- Province::MAX_INDEX, ")"
+ ProvinceDefinition::MAX_INDEX, ")"
);
return false;
}
@@ -56,19 +56,40 @@ bool Map::add_province(std::string_view identifier, colour_t colour) {
Logger::error("Invalid province colour for ", identifier, " - null! (", colour, ")");
return false;
}
- Province new_province { identifier, colour, static_cast<Province::index_t>(provinces.size() + 1) };
- const Province::index_t index = get_index_from_colour(colour);
- if (index != Province::NULL_INDEX) {
+ ProvinceDefinition new_province {
+ identifier, colour, static_cast<ProvinceDefinition::index_t>(province_definitions.size() + 1)
+ };
+ const ProvinceDefinition::index_t index = get_index_from_colour(colour);
+ if (index != ProvinceDefinition::NULL_INDEX) {
Logger::error(
- "Duplicate province colours: ", get_province_by_index(index)->to_string(), " and ", new_province.to_string()
+ "Duplicate province colours: ", get_province_definition_by_index(index)->to_string(), " and ",
+ new_province.to_string()
);
return false;
}
colour_index_map[new_province.get_colour()] = new_province.get_index();
- return provinces.add_item(std::move(new_province));
+ return province_definitions.add_item(std::move(new_province));
+}
+
+ProvinceInstance* Map::get_province_instance_from_const(ProvinceDefinition const* province) {
+ if (province != nullptr) {
+ return get_province_instance_by_index(province->get_index());
+ } else {
+ return nullptr;
+ }
}
-Province::distance_t Map::calculate_distance_between(Province const& from, Province const& to) const {
+ProvinceInstance const* Map::get_province_instance_from_const(ProvinceDefinition const* province) const {
+ if (province != nullptr) {
+ return get_province_instance_by_index(province->get_index());
+ } else {
+ return nullptr;
+ }
+}
+
+ProvinceDefinition::distance_t Map::calculate_distance_between(
+ ProvinceDefinition const& from, ProvinceDefinition const& to
+) const {
const fvec2_t to_pos = to.get_unit_position();
const fvec2_t from_pos = from.get_unit_position();
@@ -83,11 +104,11 @@ Province::distance_t Map::calculate_distance_between(Province const& from, Provi
return fvec2_t { min_x, to_pos.y - from_pos.y }.length_squared().sqrt();
}
-using adjacency_t = Province::adjacency_t;
+using adjacency_t = ProvinceDefinition::adjacency_t;
/* This is called for all adjacent pixel pairs and returns whether or not a new adjacency was add,
* hence the lack of error messages in the false return cases. */
-bool Map::add_standard_adjacency(Province& from, Province& to) const {
+bool Map::add_standard_adjacency(ProvinceDefinition& from, ProvinceDefinition& to) const {
if (from == to) {
return false;
}
@@ -99,7 +120,7 @@ bool Map::add_standard_adjacency(Province& from, Province& to) const {
return false;
}
- const Province::distance_t distance = calculate_distance_between(from, to);
+ const ProvinceDefinition::distance_t distance = calculate_distance_between(from, to);
using enum adjacency_t::type_t;
@@ -127,7 +148,8 @@ bool Map::add_standard_adjacency(Province& from, Province& to) const {
}
bool Map::add_special_adjacency(
- Province& from, Province& to, adjacency_t::type_t type, Province const* through, adjacency_t::data_t data
+ ProvinceDefinition& from, ProvinceDefinition& to, adjacency_t::type_t type, ProvinceDefinition const* through,
+ adjacency_t::data_t data
) const {
if (from == to) {
Logger::error("Trying to add ", adjacency_t::get_type_name(type), " adjacency from province ", from, " to itself!");
@@ -196,9 +218,11 @@ bool Map::add_special_adjacency(
data = adjacency_t::NO_CANAL;
}
- const Province::distance_t distance = calculate_distance_between(from, to);
+ const ProvinceDefinition::distance_t distance = calculate_distance_between(from, to);
- const auto add_adjacency = [distance, type, through, data](Province& from, Province const& to) -> bool {
+ const auto add_adjacency = [distance, type, through, data](
+ ProvinceDefinition& from, ProvinceDefinition const& to
+ ) -> bool {
const std::vector<adjacency_t>::iterator existing_adjacency = std::find_if(
from.adjacencies.begin(), from.adjacencies.end(),
[&to](adjacency_t const& adj) -> bool { return adj.get_to() == &to; }
@@ -256,11 +280,17 @@ bool Map::set_water_province(std::string_view identifier) {
Logger::error("The map's water provinces have already been locked!");
return false;
}
- Province* province = get_province_by_identifier(identifier);
+
+ ProvinceDefinition* province = get_province_definition_by_identifier(identifier);
+
if (province == nullptr) {
Logger::error("Unrecognised water province identifier: ", identifier);
return false;
}
+ if (province->has_region()) {
+ Logger::error("Province ", identifier, " cannot be water as it belongs to region \"", province->get_region(), "\"");
+ return false;
+ }
if (province->is_water()) {
Logger::warning("Province ", identifier, " is already a water province!");
return true;
@@ -292,25 +322,39 @@ void Map::lock_water_provinces() {
Logger::info("Locked water provinces after registering ", water_provinces.size());
}
-bool Map::add_region(std::string_view identifier, Region::provinces_t const& provinces, colour_t colour) {
+bool Map::add_region(std::string_view identifier, std::vector<ProvinceDefinition const*>&& provinces, colour_t colour) {
if (identifier.empty()) {
Logger::error("Invalid region identifier - empty!");
return false;
}
- if (provinces.empty()) {
- Logger::warning("No valid provinces in list for ", identifier);
- return true;
- }
- const bool meta = std::any_of(provinces.begin(), provinces.end(), std::bind_front(&Province::get_has_region));
+ bool ret = true;
+
+ std::erase_if(provinces, [identifier, &ret](ProvinceDefinition const* province) -> bool {
+ if (province->is_water()) {
+ Logger::error(
+ "Province ", province->get_identifier(), " cannot be added to region \"", identifier,
+ "\" as it is a water province!"
+ );
+ ret = false;
+ return true;
+ } else {
+ return false;
+ }
+ });
+
+ const bool meta = provinces.empty() || std::any_of(
+ provinces.begin(), provinces.end(), std::bind_front(&ProvinceDefinition::has_region)
+ );
Region region { identifier, colour, meta };
- bool ret = region.add_provinces(provinces);
+ ret &= region.add_provinces(provinces);
region.lock();
if (regions.add_item(std::move(region))) {
if (!meta) {
- for (Province const* province : provinces) {
- remove_province_const(province)->has_region = true;
+ Region const& last_region = regions.get_items().back();
+ for (ProvinceDefinition const* province : last_region.get_provinces()) {
+ remove_province_definition_const(province)->region = &last_region;
}
}
} else {
@@ -319,38 +363,38 @@ bool Map::add_region(std::string_view identifier, Region::provinces_t const& pro
return ret;
}
-Province::index_t Map::get_index_from_colour(colour_t colour) const {
+ProvinceDefinition::index_t Map::get_index_from_colour(colour_t colour) const {
const colour_index_map_t::const_iterator it = colour_index_map.find(colour);
if (it != colour_index_map.end()) {
return it->second;
}
- return Province::NULL_INDEX;
+ return ProvinceDefinition::NULL_INDEX;
}
-Province::index_t Map::get_province_index_at(ivec2_t pos) const {
+ProvinceDefinition::index_t Map::get_province_index_at(ivec2_t pos) const {
if (pos.nonnegative() && pos.less_than(dims)) {
return province_shape_image[get_pixel_index_from_pos(pos)].index;
}
- return Province::NULL_INDEX;
+ return ProvinceDefinition::NULL_INDEX;
}
-Province* Map::get_province_at(ivec2_t pos) {
- return get_province_by_index(get_province_index_at(pos));
+ProvinceDefinition* Map::get_province_definition_at(ivec2_t pos) {
+ return get_province_definition_by_index(get_province_index_at(pos));
}
-Province const* Map::get_province_at(ivec2_t pos) const {
- return get_province_by_index(get_province_index_at(pos));
+ProvinceDefinition const* Map::get_province_definition_at(ivec2_t pos) const {
+ return get_province_definition_by_index(get_province_index_at(pos));
}
-bool Map::set_max_provinces(Province::index_t new_max_provinces) {
- if (new_max_provinces <= Province::NULL_INDEX) {
+bool Map::set_max_provinces(ProvinceDefinition::index_t new_max_provinces) {
+ if (new_max_provinces <= ProvinceDefinition::NULL_INDEX) {
Logger::error(
"Trying to set max province count to an invalid value ", new_max_provinces, " (must be greater than ",
- Province::NULL_INDEX, ")"
+ ProvinceDefinition::NULL_INDEX, ")"
);
return false;
}
- if (!provinces.empty() || provinces.is_locked()) {
+ if (!province_definitions.empty() || province_definitions.is_locked()) {
Logger::error(
"Trying to set max province count to ", new_max_provinces, " after provinces have already been added and/or locked"
);
@@ -360,25 +404,27 @@ bool Map::set_max_provinces(Province::index_t new_max_provinces) {
return true;
}
-void Map::set_selected_province(Province::index_t index) {
- if (index == Province::NULL_INDEX) {
+void Map::set_selected_province(ProvinceDefinition::index_t index) {
+ if (index == ProvinceDefinition::NULL_INDEX) {
selected_province = nullptr;
} else {
- selected_province = get_province_by_index(index);
+ selected_province = get_province_instance_by_index(index);
if (selected_province == nullptr) {
Logger::error(
- "Trying to set selected province to an invalid index ", index, " (max index is ", get_province_count(), ")"
+ "Trying to set selected province to an invalid index ", index, " (max index is ",
+ get_province_instance_count(), ")"
);
}
}
}
-Province* Map::get_selected_province() {
+ProvinceInstance* Map::get_selected_province() {
return selected_province;
}
-Province::index_t Map::get_selected_province_index() const {
- return selected_province != nullptr ? selected_province->get_index() : Province::NULL_INDEX;
+ProvinceDefinition::index_t Map::get_selected_province_index() const {
+ return selected_province != nullptr ? selected_province->get_province_definition().get_index()
+ : ProvinceDefinition::NULL_INDEX;
}
bool Map::add_mapmode(std::string_view identifier, Mapmode::colour_func_t colour_func) {
@@ -398,6 +444,7 @@ bool Map::generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) cons
Logger::error("Mapmode colour target pointer is null!");
return false;
}
+
bool ret = true;
Mapmode const* mapmode = mapmodes.get_item_by_index(index);
if (mapmode == nullptr) {
@@ -410,47 +457,58 @@ bool Map::generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) cons
}
mapmode = &Mapmode::ERROR_MAPMODE;
}
- // Skip past Province::NULL_INDEX
- for (size_t i = 0; i < sizeof(Mapmode::base_stripe_t); ++i) {
- *target++ = 0;
- }
- for (Province const& province : provinces.get_items()) {
- const Mapmode::base_stripe_t base_stripe = mapmode->get_base_stripe_colours(*this, province);
- colour_argb_t const& base_colour = base_stripe.base_colour;
- colour_argb_t const& stripe_colour = base_stripe.stripe_colour;
- *target++ = base_colour.red;
- *target++ = base_colour.green;
- *target++ = base_colour.blue;
- *target++ = base_colour.alpha;
+ Mapmode::base_stripe_t* target_stripes = reinterpret_cast<Mapmode::base_stripe_t*>(target);
+
+ target_stripes[ProvinceDefinition::NULL_INDEX] = colour_argb_t::null();
- *target++ = stripe_colour.red;
- *target++ = stripe_colour.green;
- *target++ = stripe_colour.blue;
- *target++ = stripe_colour.alpha;
+ if (province_instances_are_locked()) {
+ for (ProvinceInstance const& province : province_instances.get_items()) {
+ target_stripes[province.get_province_definition().get_index()] = mapmode->get_base_stripe_colours(*this, province);
+ }
+ } else {
+ for (size_t index = ProvinceDefinition::NULL_INDEX + 1; index <= get_province_definition_count(); ++index) {
+ target_stripes[index] = colour_argb_t::null();
+ }
}
+
return ret;
}
-void Map::update_highest_province_population() {
- highest_province_population = 0;
- for (Province const& province : provinces.get_items()) {
- highest_province_population = std::max(highest_province_population, province.get_total_population());
+bool Map::reset(BuildingTypeManager const& building_type_manager) {
+ if (!province_definitions_are_locked()) {
+ Logger::error("Cannot reset map - province consts are not locked!");
+ return false;
}
-}
-void Map::update_total_map_population() {
- total_map_population = 0;
- for (Province const& province : provinces.get_items()) {
- total_map_population += province.get_total_population();
+ bool ret = true;
+
+ // TODO - ensure all references to old ProvinceInstances are safely cleared
+ state_manager.reset();
+ selected_province = nullptr;
+
+ province_instances.reset();
+
+ province_instances.reserve(province_definitions.size());
+
+ for (ProvinceDefinition const& province : province_definitions.get_items()) {
+ ret &= province_instances.add_item({ province });
}
-}
-bool Map::reset(BuildingTypeManager const& building_type_manager) {
- bool ret = true;
- for (Province& province : provinces.get_items()) {
+ province_instances.lock();
+
+ for (ProvinceInstance& province : province_instances.get_items()) {
ret &= province.reset(building_type_manager);
}
+
+ if (get_province_instance_count() != get_province_definition_count()) {
+ Logger::error(
+ "ProvinceInstance count (", get_province_instance_count(), ") does not match ProvinceDefinition count (",
+ get_province_definition_count(), ")!"
+ );
+ return false;
+ }
+
return ret;
}
@@ -460,9 +518,10 @@ bool Map::apply_history_to_provinces(
) {
bool ret = true;
- for (Province& province : provinces.get_items()) {
- if (!province.is_water()) {
- ProvinceHistoryMap const* history_map = history_manager.get_province_history(&province);
+ for (ProvinceInstance& province : province_instances.get_items()) {
+ ProvinceDefinition const& province_definition = province.get_province_definition();
+ if (!province_definition.is_water()) {
+ ProvinceHistoryMap const* history_map = history_manager.get_province_history(&province_definition);
if (history_map != nullptr) {
ProvinceHistoryEntry const* pop_history_entry = nullptr;
@@ -488,15 +547,28 @@ bool Map::apply_history_to_provinces(
}
void Map::update_gamestate(Date today) {
- for (Province& province : provinces.get_items()) {
+ for (ProvinceInstance& province : province_instances.get_items()) {
province.update_gamestate(today);
}
- update_highest_province_population();
- update_total_map_population();
+ state_manager.update_gamestate();
+
+ // Update population stats
+ highest_province_population = 0;
+ total_map_population = 0;
+
+ for (ProvinceInstance const& province : province_instances.get_items()) {
+ const Pop::pop_size_t province_population = province.get_total_population();
+
+ if (highest_province_population < province_population) {
+ highest_province_population = province_population;
+ }
+
+ total_map_population += province_population;
+ }
}
void Map::tick(Date today) {
- for (Province& province : provinces.get_items()) {
+ for (ProvinceInstance& province : province_instances.get_items()) {
province.tick(today);
}
}
@@ -555,7 +627,7 @@ bool Map::load_province_definitions(std::vector<LineObject> const& lines) {
return false;
}
- reserve_more_provinces(lines.size() - 1);
+ reserve_more_province_definitions(lines.size() - 1);
bool ret = true;
std::for_each(lines.begin() + 1, lines.end(), [this, &ret](LineObject const& line) -> void {
@@ -566,19 +638,21 @@ bool Map::load_province_definitions(std::vector<LineObject> const& lines) {
Logger::error("Error reading colour in province definition: ", line);
ret = false;
}
- ret &= add_province(identifier, colour);
+ ret &= add_province_definition(identifier, colour);
}
});
- lock_provinces();
+ lock_province_definitions();
return ret;
}
bool Map::load_province_positions(BuildingTypeManager const& building_type_manager, ast::NodeCPtr root) {
- return expect_province_dictionary([this, &building_type_manager](Province& province, ast::NodeCPtr node) -> bool {
- return province.load_positions(*this, building_type_manager, node);
- })(root);
+ return expect_province_definition_dictionary(
+ [this, &building_type_manager](ProvinceDefinition& province, ast::NodeCPtr node) -> bool {
+ return province.load_positions(*this, building_type_manager, node);
+ }
+ )(root);
}
bool Map::load_region_colours(ast::NodeCPtr root, std::vector<colour_t>& colours) {
@@ -597,25 +671,20 @@ bool Map::load_region_file(ast::NodeCPtr root, std::vector<colour_t> const& colo
const bool ret = expect_dictionary_reserve_length(
regions,
[this, &colours](std::string_view region_identifier, ast::NodeCPtr region_node) -> bool {
- Region::provinces_t provinces;
+ std::vector<ProvinceDefinition const*> provinces;
+
bool ret = expect_list_reserve_length(
- provinces, expect_province_identifier(vector_callback_pointer(provinces))
+ provinces, expect_province_definition_identifier(vector_callback_pointer(provinces))
)(region_node);
- ret &= add_region(region_identifier, provinces, colours[regions.size() % colours.size()]);
+
+ ret &= add_region(region_identifier, std::move(provinces), colours[regions.size() % colours.size()]);
+
return ret;
}
)(root);
lock_regions();
- for (Region const& region : regions.get_items()) {
- if (!region.meta) {
- for (Province const* province : region.get_provinces()) {
- remove_province_const(province)->region = &region;
- }
- }
- }
-
return ret;
}
@@ -629,7 +698,7 @@ static constexpr colour_t colour_at(uint8_t const* colour_data, int32_t idx) {
}
bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain_path, bool detailed_errors) {
- if (!provinces.is_locked()) {
+ if (!province_definitions_are_locked()) {
Logger::error("Province index image cannot be generated until after provinces are locked!");
return false;
}
@@ -680,19 +749,19 @@ bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain
uint8_t const* province_data = province_bmp.get_pixel_data().data();
uint8_t const* terrain_data = terrain_bmp.get_pixel_data().data();
- std::vector<fixed_point_map_t<TerrainType const*>> terrain_type_pixels_list(provinces.size());
+ std::vector<fixed_point_map_t<TerrainType const*>> terrain_type_pixels_list(province_definitions.size());
bool ret = true;
ordered_set<colour_t> unrecognised_province_colours;
- std::vector<fixed_point_t> pixels_per_province(provinces.size());
- std::vector<fvec2_t> pixel_position_sum_per_province(provinces.size());
+ std::vector<fixed_point_t> pixels_per_province(province_definitions.size());
+ std::vector<fvec2_t> pixel_position_sum_per_province(province_definitions.size());
for (ivec2_t pos {}; pos.y < get_height(); ++pos.y) {
for (pos.x = 0; pos.x < get_width(); ++pos.x) {
const size_t pixel_index = get_pixel_index_from_pos(pos);
const colour_t province_colour = colour_at(province_data, pixel_index);
- Province::index_t province_index = Province::NULL_INDEX;
+ ProvinceDefinition::index_t province_index = ProvinceDefinition::NULL_INDEX;
if (pos.x > 0) {
const size_t jdx = pixel_index - 1;
@@ -712,7 +781,7 @@ bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain
province_index = get_index_from_colour(province_colour);
- if (province_index == Province::NULL_INDEX && !unrecognised_province_colours.contains(province_colour)) {
+ if (province_index == ProvinceDefinition::NULL_INDEX && !unrecognised_province_colours.contains(province_colour)) {
unrecognised_province_colours.insert(province_colour);
if (detailed_errors) {
Logger::warning(
@@ -724,8 +793,8 @@ bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain
index_found:
province_shape_image[pixel_index].index = province_index;
- if (province_index != Province::NULL_INDEX) {
- const Province::index_t array_index = province_index - 1;
+ if (province_index != ProvinceDefinition::NULL_INDEX) {
+ const ProvinceDefinition::index_t array_index = province_index - 1;
pixels_per_province[array_index]++;
pixel_position_sum_per_province[array_index] += static_cast<fvec2_t>(pos);
}
@@ -733,7 +802,7 @@ bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain
const TerrainTypeMapping::index_t terrain = terrain_data[pixel_index];
TerrainTypeMapping const* mapping = terrain_type_manager.get_terrain_type_mapping_for(terrain);
if (mapping != nullptr) {
- if (province_index != Province::NULL_INDEX) {
+ if (province_index != ProvinceDefinition::NULL_INDEX) {
terrain_type_pixels_list[province_index - 1][&mapping->get_type()]++;
}
if (mapping->get_has_texture() && terrain < terrain_type_manager.get_terrain_texture_limit()) {
@@ -752,8 +821,8 @@ bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain
}
size_t missing = 0;
- for (size_t array_index = 0; array_index < provinces.size(); ++array_index) {
- Province* province = provinces.get_item_by_index(array_index);
+ for (size_t array_index = 0; array_index < province_definitions.size(); ++array_index) {
+ ProvinceDefinition* province = province_definitions.get_item_by_index(array_index);
fixed_point_map_t<TerrainType const*> const& terrain_type_pixels = terrain_type_pixels_list[array_index];
const fixed_point_map_const_iterator_t<TerrainType const*> largest = get_largest_item(terrain_type_pixels);
@@ -784,8 +853,8 @@ bool Map::load_map_images(fs::path const& province_path, fs::path const& terrain
bool Map::_generate_standard_province_adjacencies() {
bool changed = false;
- const auto generate_adjacency = [this](Province* current, ivec2_t pos) -> bool {
- Province* neighbour = get_province_at(pos);
+ const auto generate_adjacency = [this](ProvinceDefinition* current, ivec2_t pos) -> bool {
+ ProvinceDefinition* neighbour = get_province_definition_at(pos);
if (neighbour != nullptr) {
return add_standard_adjacency(*current, *neighbour);
}
@@ -794,7 +863,7 @@ bool Map::_generate_standard_province_adjacencies() {
for (ivec2_t pos {}; pos.y < get_height(); ++pos.y) {
for (pos.x = 0; pos.x < get_width(); ++pos.x) {
- Province* cur = get_province_at(pos);
+ ProvinceDefinition* cur = get_province_definition_at(pos);
if (cur != nullptr) {
changed |= generate_adjacency(cur, { (pos.x + 1) % get_width(), pos.y });
@@ -822,7 +891,7 @@ bool Map::generate_and_load_province_adjacencies(std::vector<LineObject> const&
if (from_str.empty() || from_str.front() == '#') {
return;
}
- Province* const from = get_province_by_identifier(from_str);
+ ProvinceDefinition* const from = get_province_definition_by_identifier(from_str);
if (from == nullptr) {
Logger::error("Unrecognised adjacency from province identifier: \"", from_str, "\"");
ret = false;
@@ -830,7 +899,7 @@ bool Map::generate_and_load_province_adjacencies(std::vector<LineObject> const&
}
const std::string_view to_str = adjacency.get_value_for(1);
- Province* const to = get_province_by_identifier(to_str);
+ ProvinceDefinition* const to = get_province_definition_by_identifier(to_str);
if (to == nullptr) {
Logger::error("Unrecognised adjacency to province identifier: \"", to_str, "\"");
ret = false;
@@ -850,7 +919,7 @@ bool Map::generate_and_load_province_adjacencies(std::vector<LineObject> const&
}
const adjacency_t::type_t type = it->second;
- Province const* const through = get_province_by_identifier(adjacency.get_value_for(3));
+ ProvinceDefinition const* const through = get_province_definition_by_identifier(adjacency.get_value_for(3));
const std::string_view data_str = adjacency.get_value_for(4);
bool successful = false;
@@ -884,8 +953,8 @@ bool Map::load_climate_file(ModifierManager const& modifier_manager, ast::NodeCP
ret &= modifier_manager.expect_modifier_value(move_variable_callback(values))(node);
ret &= climates.add_item({ identifier, std::move(values) });
} else {
- ret &= expect_list_reserve_length(*cur_climate, expect_province_identifier(
- [cur_climate, &identifier](Province& province) {
+ ret &= expect_list_reserve_length(*cur_climate, expect_province_definition_identifier(
+ [cur_climate, &identifier](ProvinceDefinition& province) {
if (province.climate != cur_climate) {
cur_climate->add_province(&province);
if (province.climate != nullptr) {
@@ -931,10 +1000,10 @@ bool Map::load_continent_file(ModifierManager const& modifier_manager, ast::Node
}
ModifierValue values;
- ProvinceSetModifier::provinces_t prov_list;
+ std::vector<ProvinceDefinition const*> prov_list;
bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(values),
- "provinces", ONE_EXACTLY, expect_list_reserve_length(prov_list, expect_province_identifier(
- [&prov_list](Province const& province) -> bool {
+ "provinces", ONE_EXACTLY, expect_list_reserve_length(prov_list, expect_province_definition_identifier(
+ [&prov_list](ProvinceDefinition const& province) -> bool {
if (province.continent == nullptr) {
prov_list.emplace_back(&province);
} else {
@@ -951,8 +1020,8 @@ bool Map::load_continent_file(ModifierManager const& modifier_manager, ast::Node
if (continents.add_item(std::move(continent))) {
Continent const& moved_continent = continents.get_items().back();
- for (Province const* prov : moved_continent.get_provinces()) {
- remove_province_const(prov)->continent = &moved_continent;
+ for (ProvinceDefinition const* prov : moved_continent.get_provinces()) {
+ remove_province_definition_const(prov)->continent = &moved_continent;
}
} else {
ret = false;
diff --git a/src/openvic-simulation/map/Map.hpp b/src/openvic-simulation/map/Map.hpp
index 2a3f224..d42b3fb 100644
--- a/src/openvic-simulation/map/Map.hpp
+++ b/src/openvic-simulation/map/Map.hpp
@@ -5,7 +5,8 @@
#include <openvic-dataloader/csv/LineObject.hpp>
-#include "openvic-simulation/map/Province.hpp"
+#include "openvic-simulation/map/ProvinceDefinition.hpp"
+#include "openvic-simulation/map/ProvinceInstance.hpp"
#include "openvic-simulation/map/Region.hpp"
#include "openvic-simulation/map/State.hpp"
#include "openvic-simulation/map/TerrainType.hpp"
@@ -27,7 +28,7 @@ namespace OpenVic {
: base_colour { base }, stripe_colour { stripe } {}
constexpr base_stripe_t(colour_argb_t both) : base_stripe_t { both, both } {}
};
- using colour_func_t = std::function<base_stripe_t(Map const&, Province const&)>;
+ using colour_func_t = std::function<base_stripe_t(Map const&, ProvinceInstance const&)>;
using index_t = size_t;
private:
@@ -41,7 +42,7 @@ namespace OpenVic {
Mapmode(Mapmode&&) = default;
- base_stripe_t get_base_stripe_colours(Map const& map, Province const& province) const;
+ base_stripe_t get_base_stripe_colours(Map const& map, ProvinceInstance const& province) const;
};
struct GoodManager;
@@ -54,14 +55,15 @@ namespace OpenVic {
#pragma pack(push, 1)
/* Used to represent tightly packed 3-byte integer pixel information. */
struct shape_pixel_t {
- Province::index_t index;
+ ProvinceDefinition::index_t index;
TerrainTypeMapping::index_t terrain;
};
#pragma pack(pop)
private:
- using colour_index_map_t = ordered_map<colour_t, Province::index_t>;
+ using colour_index_map_t = ordered_map<colour_t, ProvinceDefinition::index_t>;
- IdentifierRegistry<Province> IDENTIFIER_REGISTRY_CUSTOM_INDEX_OFFSET(province, 1);
+ IdentifierRegistry<ProvinceDefinition> IDENTIFIER_REGISTRY_CUSTOM_INDEX_OFFSET(province_definition, 1);
+ IdentifierRegistry<ProvinceInstance> IDENTIFIER_REGISTRY_CUSTOM_INDEX_OFFSET(province_instance, 1);
IdentifierRegistry<Region> IDENTIFIER_REGISTRY(region);
IdentifierRegistry<Mapmode> IDENTIFIER_REGISTRY(mapmode);
IdentifierRegistry<Climate> IDENTIFIER_REGISTRY(climate);
@@ -73,12 +75,12 @@ namespace OpenVic {
std::vector<shape_pixel_t> PROPERTY(province_shape_image);
colour_index_map_t colour_index_map;
- Province::index_t PROPERTY(max_provinces);
- Province* PROPERTY(selected_province);
+ ProvinceDefinition::index_t PROPERTY(max_provinces);
+ ProvinceInstance* PROPERTY(selected_province); // is it right for this to be mutable? how about using an index instead?
Pop::pop_size_t PROPERTY(highest_province_population);
Pop::pop_size_t PROPERTY(total_map_population);
- Province::index_t get_index_from_colour(colour_t colour) const;
+ ProvinceDefinition::index_t get_index_from_colour(colour_t colour) const;
bool _generate_standard_province_adjacencies();
StateManager PROPERTY_REF(state_manager);
@@ -93,46 +95,60 @@ namespace OpenVic {
inline constexpr int32_t get_width() const { return dims.x; }
inline constexpr int32_t get_height() const { return dims.y; }
- bool add_province(std::string_view identifier, colour_t colour);
- IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS_CUSTOM_INDEX_OFFSET(province, 1);
+ bool add_province_definition(std::string_view identifier, colour_t colour);
- Province::distance_t calculate_distance_between(Province const& from, Province const& to) const;
- bool add_standard_adjacency(Province& from, Province& to) const;
+ private:
+ IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS_CUSTOM_INDEX_OFFSET(province_definition, 1);
+
+ public:
+ IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS_CUSTOM_INDEX_OFFSET(province_instance, 1);
+
+ ProvinceInstance* get_province_instance_from_const(ProvinceDefinition const* province);
+ ProvinceInstance const* get_province_instance_from_const(ProvinceDefinition const* province) const;
+
+ ProvinceDefinition::distance_t calculate_distance_between(
+ ProvinceDefinition const& from, ProvinceDefinition const& to
+ ) const;
+ bool add_standard_adjacency(ProvinceDefinition& from, ProvinceDefinition& to) const;
bool add_special_adjacency(
- Province& from, Province& to, Province::adjacency_t::type_t type, Province const* through,
- Province::adjacency_t::data_t data
+ ProvinceDefinition& from, ProvinceDefinition& to, ProvinceDefinition::adjacency_t::type_t type,
+ ProvinceDefinition const* through, ProvinceDefinition::adjacency_t::data_t data
) const;
- /* This provides a safe way to remove the const qualifier of a Province const*, via a non-const Map.
- * It uses a const_cast (the fastest/simplest solution), but this could also be done without it by looking up the
- * Province* using the Province const*'s index. Requiring a non-const Map ensures that this function can only be
- * used where the Province* could already be accessed by other means, such as the index method, preventing
- * misleading code, or in the worst case undefined behaviour. */
- constexpr Province* remove_province_const(Province const* province) {
- return const_cast<Province*>(province);
- }
-
bool set_water_province(std::string_view identifier);
bool set_water_province_list(std::vector<std::string_view> const& list);
void lock_water_provinces();
- Province::index_t get_province_index_at(ivec2_t pos) const;
- Province* get_province_at(ivec2_t pos);
- Province const* get_province_at(ivec2_t pos) const;
- bool set_max_provinces(Province::index_t new_max_provinces);
- void set_selected_province(Province::index_t index);
- Province* get_selected_province();
- Province::index_t get_selected_province_index() const;
+ ProvinceDefinition::index_t get_province_index_at(ivec2_t pos) const;
- bool add_region(std::string_view identifier, Region::provinces_t const& provinces, colour_t colour);
+ private:
+ ProvinceDefinition* get_province_definition_at(ivec2_t pos);
+
+ /* This provides a safe way to remove the const qualifier of a ProvinceDefinition const*, via a non-const Map.
+ * It uses a const_cast (the fastest/simplest solution), but this could also be done without it by looking up the
+ * ProvinceDefinition* using the ProvinceDefinition const*'s index. Requiring a non-const Map ensures that this
+ * function can only be used where the ProvinceDefinition* could already be accessed by other means, such as the
+ * index method, preventing misleading code, or in the worst case undefined behaviour. */
+ constexpr ProvinceDefinition* remove_province_definition_const(ProvinceDefinition const* province) {
+ return const_cast<ProvinceDefinition*>(province);
+ }
+
+ public:
+ ProvinceDefinition const* get_province_definition_at(ivec2_t pos) const;
+ bool set_max_provinces(ProvinceDefinition::index_t new_max_provinces);
+ void set_selected_province(ProvinceDefinition::index_t index);
+ ProvinceInstance* get_selected_province();
+ ProvinceDefinition::index_t get_selected_province_index() const;
+
+ bool add_region(std::string_view identifier, std::vector<ProvinceDefinition const*>&& provinces, colour_t colour);
bool add_mapmode(std::string_view identifier, Mapmode::colour_func_t colour_func);
/* The mapmode colour image contains of a list of base colours and stripe colours. Each colour is four bytes
* in RGBA format, with the alpha value being used to interpolate with the terrain colour, so A = 0 is fully terrain
* and A = 255 is fully the RGB colour packaged with A. The base and stripe colours for each province are packed
- * together adjacently, so each province's entry is 8 bytes long. The list contains Province::MAX_INDEX + 1 entries,
- * that is the maximum allowed number of provinces plus one for the index-zero "null province". */
+ * together adjacently, so each province's entry is 8 bytes long. The list contains ProvinceDefinition::MAX_INDEX + 1
+ * entries, that is the maximum allowed number of provinces plus one for the index-zero "null province". */
bool generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) const;
bool reset(BuildingTypeManager const& building_type_manager);
@@ -141,9 +157,6 @@ namespace OpenVic {
IssueManager const& issue_manager, Country const& country
);
- void update_highest_province_population();
- void update_total_map_population();
-
void update_gamestate(Date today);
void tick(Date today);
diff --git a/src/openvic-simulation/map/Province.cpp b/src/openvic-simulation/map/Province.cpp
deleted file mode 100644
index d4569ad..0000000
--- a/src/openvic-simulation/map/Province.cpp
+++ /dev/null
@@ -1,380 +0,0 @@
-#include "Province.hpp"
-
-#include "openvic-simulation/history/ProvinceHistory.hpp"
-#include "openvic-simulation/map/Map.hpp"
-#include "openvic-simulation/military/UnitInstance.hpp"
-
-using namespace OpenVic;
-using namespace OpenVic::NodeTools;
-
-Province::Province(
- std::string_view new_identifier, colour_t new_colour, index_t new_index
-) : HasIdentifierAndColour { new_identifier, new_colour, true }, index { new_index }, region { nullptr },
- climate { nullptr }, continent { nullptr }, on_map { false }, has_region { false }, water { false }, coastal { false },
- port { false }, port_adjacent_province { nullptr }, default_terrain_type { nullptr }, positions {},
- terrain_type { nullptr }, life_rating { 0 }, colony_status { colony_status_t::STATE }, state { nullptr },
- owner { nullptr }, controller { nullptr }, slave { false }, crime { nullptr }, rgo { nullptr },
- buildings { "buildings", false }, total_population { 0 } {
- assert(index != NULL_INDEX);
-}
-
-bool Province::operator==(Province const& other) const {
- return this == &other;
-}
-
-std::string Province::to_string() const {
- std::stringstream stream;
- stream << "(#" << std::to_string(index) << ", " << get_identifier() << ", 0x" << get_colour() << ")";
- return stream.str();
-}
-
-bool Province::load_positions(Map const& map, BuildingTypeManager const& building_type_manager, ast::NodeCPtr root) {
- const fixed_point_t map_height = map.get_height();
-
- const bool ret = expect_dictionary_keys(
- "text_position", ZERO_OR_ONE,
- expect_fvec2(flip_y_callback(assign_variable_callback(positions.text_position), map_height)),
- "text_rotation", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(positions.text_rotation)),
- "text_scale", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(positions.text_scale)),
-
- "unit", ZERO_OR_ONE, expect_fvec2(flip_y_callback(assign_variable_callback(positions.unit), map_height)),
- "town", ZERO_OR_ONE, expect_fvec2(flip_y_callback(assign_variable_callback(positions.city), map_height)),
- "city", ZERO_OR_ONE, expect_fvec2(flip_y_callback(assign_variable_callback(positions.city), map_height)),
- "factory", ZERO_OR_ONE, expect_fvec2(flip_y_callback(assign_variable_callback(positions.factory), map_height)),
-
- "building_construction", ZERO_OR_ONE,
- expect_fvec2(flip_y_callback(assign_variable_callback(positions.building_construction), map_height)),
- "military_construction", ZERO_OR_ONE,
- expect_fvec2(flip_y_callback(assign_variable_callback(positions.military_construction), map_height)),
-
- "building_position", ZERO_OR_ONE, building_type_manager.expect_building_type_dictionary_reserve_length(
- positions.building_position,
- [this, map_height](BuildingType const& type, ast::NodeCPtr value) -> bool {
- return expect_fvec2(flip_y_callback(map_callback(positions.building_position, &type), map_height))(value);
- }
- ),
- "building_rotation", ZERO_OR_ONE, building_type_manager.expect_building_type_decimal_map(
- move_variable_callback(positions.building_rotation), std::negate {}
- ),
-
- /* the below are esoteric clausewitz leftovers that either have no impact or whose functionality is lost to time */
- "spawn_railway_track", ZERO_OR_ONE, success_callback,
- "railroad_visibility", ZERO_OR_ONE, success_callback,
- "building_nudge", ZERO_OR_ONE, success_callback
- )(root);
-
- if (coastal) {
- fvec2_t const* port_position = get_building_position(building_type_manager.get_port_building_type());
- if (port_position != nullptr) {
- const fixed_point_t rotation = get_building_rotation(building_type_manager.get_port_building_type());
-
- /* At 0 rotation the port faces west, as rotation increases the port rotates anti-clockwise. */
- const fvec2_t port_dir { -rotation.cos(), rotation.sin() };
- const ivec2_t port_facing_position = static_cast<ivec2_t>(*port_position + port_dir / 4);
-
- Province const* province = map.get_province_at(port_facing_position);
-
- if (province != nullptr) {
- if (province->is_water() && is_adjacent_to(province)) {
- port = true;
- port_adjacent_province = province;
- } else {
- /* Expected provinces with invalid ports: 39, 296, 1047, 1406, 2044 */
- Logger::warning(
- "Invalid port for province ", get_identifier(), ": facing province ", province,
- " which has: water = ", province->is_water(), ", adjacent = ", is_adjacent_to(province)
- );
- }
- } else {
- Logger::warning("Invalid port for province ", get_identifier(), ": facing null province!");
- }
- }
- }
-
- return ret;
-}
-
-fvec2_t Province::get_text_position() const {
- return positions.text_position.value_or(centre);
-}
-
-fixed_point_t Province::get_text_rotation() const {
- return positions.text_rotation.value_or(0);
-}
-
-fixed_point_t Province::get_text_scale() const {
- return positions.text_scale.value_or(1);
-}
-
-bool Province::expand_building(size_t building_index) {
- BuildingInstance* building = buildings.get_item_by_index(building_index);
- if (building == nullptr) {
- Logger::error("Trying to expand non-existent building index ", building_index, " in province ", get_identifier());
- return false;
- }
- return building->expand();
-}
-
-fvec2_t const* Province::get_building_position(BuildingType const* building_type) const {
- if (building_type != nullptr) {
- const decltype(positions.building_position)::const_iterator it = positions.building_position.find(building_type);
-
- if (it != positions.building_position.end()) {
- return &it->second;
- }
- }
- return nullptr;
-}
-
-fixed_point_t Province::get_building_rotation(BuildingType const* building_type) const {
- if (building_type != nullptr) {
- const decltype(positions.building_rotation)::const_iterator it = positions.building_rotation.find(building_type);
-
- if (it != positions.building_rotation.end()) {
- return it->second;
- }
- }
- return 0;
-}
-
-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()) {
- _add_pop(std::move(pop));
- return true;
- } else {
- Logger::error("Trying to add pop to water province ", get_identifier());
- return false;
- }
-}
-
-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) {
- _add_pop(pop);
- }
- return true;
- } else {
- Logger::error("Trying to add pop vector to water province ", get_identifier());
- return false;
- }
-}
-
-size_t Province::get_pop_count() const {
- return pops.size();
-}
-
-/* REQUIREMENTS:
- * MAP-65, MAP-68, MAP-70, MAP-234
- */
-void Province::update_pops() {
- total_population = 0;
- pop_type_distribution.clear();
- ideology_distribution.clear();
- culture_distribution.clear();
- religion_distribution.clear();
- for (Pop const& pop : pops) {
- total_population += pop.get_size();
- pop_type_distribution[&pop.get_type()] += pop.get_size();
- ideology_distribution += pop.get_ideologies();
- culture_distribution[&pop.get_culture()] += pop.get_size();
- religion_distribution[&pop.get_religion()] += pop.get_size();
- }
-}
-
-void Province::update_gamestate(Date today) {
- for (BuildingInstance& building : buildings.get_items()) {
- building.update_gamestate(today);
- }
- update_pops();
-}
-
-void Province::tick(Date today) {
- for (BuildingInstance& building : buildings.get_items()) {
- building.tick(today);
- }
-}
-
-Province::adjacency_t::adjacency_t(
- Province const* new_to, distance_t new_distance, type_t new_type, Province const* new_through, data_t new_data
-) : to { new_to }, distance { new_distance }, type { new_type }, through { new_through }, data { new_data } {}
-
-std::string_view Province::adjacency_t::get_type_name(type_t type) {
- switch (type) {
- case type_t::LAND: return "Land";
- case type_t::WATER: return "Water";
- case type_t::COASTAL: return "Coastal";
- case type_t::IMPASSABLE: return "Impassable";
- case type_t::STRAIT: return "Strait";
- case type_t::CANAL: return "Canal";
- default: return "Invalid Adjacency Type";
- }
-}
-
-Province::adjacency_t const* Province::get_adjacency_to(Province const* province) const {
- const std::vector<adjacency_t>::const_iterator it = std::find_if(adjacencies.begin(), adjacencies.end(),
- [province](adjacency_t const& adj) -> bool { return adj.get_to() == province; }
- );
- if (it != adjacencies.end()) {
- return &*it;
- } else {
- return nullptr;
- }
-}
-
-bool Province::is_adjacent_to(Province const* province) const {
- return province != nullptr && std::any_of(adjacencies.begin(), adjacencies.end(),
- [province](adjacency_t const& adj) -> bool { return adj.get_to() == province; }
- );
-}
-
-std::vector<Province::adjacency_t const*> Province::get_adjacencies_going_through(Province const* province) const {
- std::vector<adjacency_t const*> ret;
- for (adjacency_t const& adj : adjacencies) {
- if (adj.get_through() == province) {
- ret.push_back(&adj);
- }
- }
- return ret;
-}
-
-bool Province::has_adjacency_going_through(Province const* province) const {
- return province != nullptr && std::any_of(adjacencies.begin(), adjacencies.end(),
- [province](adjacency_t const& adj) -> bool { return adj.get_through() == province; }
- );
-}
-
-fvec2_t Province::get_unit_position() const {
- return positions.unit.value_or(centre);
-}
-
-bool Province::add_army(ArmyInstance& army) {
- if (armies.emplace(&army).second) {
- return true;
- } else {
- Logger::error("Trying to add already-existing army ", army.get_name(), " to province ", get_identifier());
- return false;
- }
-}
-
-bool Province::remove_army(ArmyInstance& army) {
- if (armies.erase(&army) > 0) {
- return true;
- } else {
- Logger::error("Trying to remove non-existent army ", army.get_name(), " from province ", get_identifier());
- return false;
- }
-}
-
-bool Province::add_navy(NavyInstance& navy) {
- if (navies.emplace(&navy).second) {
- return true;
- } else {
- Logger::error("Trying to add already-existing navy ", navy.get_name(), " to province ", get_identifier());
- return false;
- }
-}
-
-bool Province::remove_navy(NavyInstance& navy) {
- if (navies.erase(&navy) > 0) {
- return true;
- } else {
- Logger::error("Trying to remove non-existent navy ", navy.get_name(), " from province ", get_identifier());
- return false;
- }
-}
-
-bool Province::reset(BuildingTypeManager const& building_type_manager) {
- terrain_type = default_terrain_type;
- life_rating = 0;
- colony_status = colony_status_t::STATE;
- state = nullptr;
- owner = nullptr;
- controller = nullptr;
- cores.clear();
- slave = false;
- crime = nullptr;
- rgo = nullptr;
-
- buildings.reset();
- bool ret = true;
- if (!is_water()) {
- if (building_type_manager.building_types_are_locked()) {
- for (BuildingType const* building_type : building_type_manager.get_province_building_types()) {
- ret &= buildings.add_item({ *building_type });
- }
- } else {
- Logger::error("Cannot generate buildings until building types are locked!");
- ret = false;
- }
- }
- lock_buildings();
-
- pops.clear();
- update_pops();
-
- return ret;
-}
-
-bool Province::apply_history_to_province(ProvinceHistoryEntry const* entry) {
- if (entry == nullptr) {
- Logger::error("Trying to apply null province history to ", get_identifier());
- return false;
- }
- if (entry->get_life_rating()) life_rating = *entry->get_life_rating();
- if (entry->get_colonial()) colony_status = *entry->get_colonial();
- if (entry->get_rgo()) rgo = *entry->get_rgo();
- if (entry->get_terrain_type()) terrain_type = *entry->get_terrain_type();
- if (entry->get_owner()) owner = *entry->get_owner();
- if (entry->get_controller()) controller = *entry->get_controller();
- if (entry->get_slave()) slave = *entry->get_slave();
- for (Country const* core : entry->get_remove_cores()) {
- const typename decltype(cores)::iterator existing_core = std::find(cores.begin(), cores.end(), core);
- if (existing_core != cores.end()) {
- cores.erase(existing_core);
- } else {
- Logger::warning(
- "Trying to remove non-existent core ", core->get_identifier(), " from province ", get_identifier()
- );
- }
- }
- for (Country const* core : entry->get_add_cores()) {
- const typename decltype(cores)::iterator existing_core = std::find(cores.begin(), cores.end(), core);
- if (existing_core == cores.end()) {
- cores.push_back(core);
- } else {
- Logger::warning(
- "Trying to add already-existing core ", core->get_identifier(), " to province ", get_identifier()
- );
- }
- }
- bool ret = true;
- for (auto const& [building, level] : entry->get_province_buildings()) {
- BuildingInstance* existing_entry = buildings.get_item_by_identifier(building->get_identifier());
- if (existing_entry != nullptr) {
- existing_entry->set_level(level);
- } else {
- Logger::error(
- "Trying to set level of non-existent province building ", building->get_identifier(), " to ", level,
- " in province ", get_identifier()
- );
- ret = false;
- }
- }
- // TODO: load state buildings
- // 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/ProvinceDefinition.cpp b/src/openvic-simulation/map/ProvinceDefinition.cpp
new file mode 100644
index 0000000..bb8ad59
--- /dev/null
+++ b/src/openvic-simulation/map/ProvinceDefinition.cpp
@@ -0,0 +1,183 @@
+#include "ProvinceDefinition.hpp"
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/economy/BuildingType.hpp"
+#include "openvic-simulation/map/Map.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+
+ProvinceDefinition::ProvinceDefinition(
+ std::string_view new_identifier, colour_t new_colour, index_t new_index
+) : HasIdentifierAndColour { new_identifier, new_colour, true }, index { new_index }, region { nullptr },
+ climate { nullptr }, continent { nullptr }, on_map { false }, water { false }, coastal { false },
+ port { false }, port_adjacent_province { nullptr }, default_terrain_type { nullptr }, adjacencies {}, centre {},
+ positions {} {
+ assert(index != NULL_INDEX);
+}
+
+bool ProvinceDefinition::operator==(ProvinceDefinition const& other) const {
+ return this == &other;
+}
+
+std::string ProvinceDefinition::to_string() const {
+ std::stringstream stream;
+ stream << "(#" << std::to_string(index) << ", " << get_identifier() << ", 0x" << get_colour() << ")";
+ return stream.str();
+}
+
+bool ProvinceDefinition::load_positions(Map const& map, BuildingTypeManager const& building_type_manager, ast::NodeCPtr root) {
+ const fixed_point_t map_height = map.get_height();
+
+ const bool ret = expect_dictionary_keys(
+ "text_position", ZERO_OR_ONE,
+ expect_fvec2(flip_y_callback(assign_variable_callback(positions.text_position), map_height)),
+ "text_rotation", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(positions.text_rotation)),
+ "text_scale", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(positions.text_scale)),
+
+ "unit", ZERO_OR_ONE, expect_fvec2(flip_y_callback(assign_variable_callback(positions.unit), map_height)),
+ "town", ZERO_OR_ONE, expect_fvec2(flip_y_callback(assign_variable_callback(positions.city), map_height)),
+ "city", ZERO_OR_ONE, expect_fvec2(flip_y_callback(assign_variable_callback(positions.city), map_height)),
+ "factory", ZERO_OR_ONE, expect_fvec2(flip_y_callback(assign_variable_callback(positions.factory), map_height)),
+
+ "building_construction", ZERO_OR_ONE,
+ expect_fvec2(flip_y_callback(assign_variable_callback(positions.building_construction), map_height)),
+ "military_construction", ZERO_OR_ONE,
+ expect_fvec2(flip_y_callback(assign_variable_callback(positions.military_construction), map_height)),
+
+ "building_position", ZERO_OR_ONE, building_type_manager.expect_building_type_dictionary_reserve_length(
+ positions.building_position,
+ [this, map_height](BuildingType const& type, ast::NodeCPtr value) -> bool {
+ return expect_fvec2(flip_y_callback(map_callback(positions.building_position, &type), map_height))(value);
+ }
+ ),
+ "building_rotation", ZERO_OR_ONE, building_type_manager.expect_building_type_decimal_map(
+ move_variable_callback(positions.building_rotation), std::negate {}
+ ),
+
+ /* the below are esoteric clausewitz leftovers that either have no impact or whose functionality is lost to time */
+ "spawn_railway_track", ZERO_OR_ONE, success_callback,
+ "railroad_visibility", ZERO_OR_ONE, success_callback,
+ "building_nudge", ZERO_OR_ONE, success_callback
+ )(root);
+
+ if (coastal) {
+ fvec2_t const* port_position = get_building_position(building_type_manager.get_port_building_type());
+ if (port_position != nullptr) {
+ const fixed_point_t rotation = get_building_rotation(building_type_manager.get_port_building_type());
+
+ /* At 0 rotation the port faces west, as rotation increases the port rotates anti-clockwise. */
+ const fvec2_t port_dir { -rotation.cos(), rotation.sin() };
+ const ivec2_t port_facing_position = static_cast<ivec2_t>(*port_position + port_dir / 4);
+
+ ProvinceDefinition const* province = map.get_province_definition_at(port_facing_position);
+
+ if (province != nullptr) {
+ if (province->is_water() && is_adjacent_to(province)) {
+ port = true;
+ port_adjacent_province = province;
+ } else {
+ /* Expected provinces with invalid ports: 39, 296, 1047, 1406, 2044 */
+ Logger::warning(
+ "Invalid port for province ", get_identifier(), ": facing province ", province,
+ " which has: water = ", province->is_water(), ", adjacent = ", is_adjacent_to(province)
+ );
+ }
+ } else {
+ Logger::warning("Invalid port for province ", get_identifier(), ": facing null province!");
+ }
+ }
+ }
+
+ return ret;
+}
+
+fvec2_t ProvinceDefinition::get_text_position() const {
+ return positions.text_position.value_or(centre);
+}
+
+fixed_point_t ProvinceDefinition::get_text_rotation() const {
+ return positions.text_rotation.value_or(0);
+}
+
+fixed_point_t ProvinceDefinition::get_text_scale() const {
+ return positions.text_scale.value_or(1);
+}
+
+fvec2_t const* ProvinceDefinition::get_building_position(BuildingType const* building_type) const {
+ if (building_type != nullptr) {
+ const decltype(positions.building_position)::const_iterator it = positions.building_position.find(building_type);
+
+ if (it != positions.building_position.end()) {
+ return &it->second;
+ }
+ }
+ return nullptr;
+}
+
+fixed_point_t ProvinceDefinition::get_building_rotation(BuildingType const* building_type) const {
+ if (building_type != nullptr) {
+ const decltype(positions.building_rotation)::const_iterator it = positions.building_rotation.find(building_type);
+
+ if (it != positions.building_rotation.end()) {
+ return it->second;
+ }
+ }
+ return 0;
+}
+
+ProvinceDefinition::adjacency_t::adjacency_t(
+ ProvinceDefinition const* new_to, distance_t new_distance, type_t new_type, ProvinceDefinition const* new_through,
+ data_t new_data
+) : to { new_to }, distance { new_distance }, type { new_type }, through { new_through }, data { new_data } {}
+
+std::string_view ProvinceDefinition::adjacency_t::get_type_name(type_t type) {
+ switch (type) {
+ case type_t::LAND: return "Land";
+ case type_t::WATER: return "Water";
+ case type_t::COASTAL: return "Coastal";
+ case type_t::IMPASSABLE: return "Impassable";
+ case type_t::STRAIT: return "Strait";
+ case type_t::CANAL: return "Canal";
+ default: return "Invalid Adjacency Type";
+ }
+}
+
+ProvinceDefinition::adjacency_t const* ProvinceDefinition::get_adjacency_to(ProvinceDefinition const* province) const {
+ const std::vector<adjacency_t>::const_iterator it = std::find_if(adjacencies.begin(), adjacencies.end(),
+ [province](adjacency_t const& adj) -> bool { return adj.get_to() == province; }
+ );
+ if (it != adjacencies.end()) {
+ return &*it;
+ } else {
+ return nullptr;
+ }
+}
+
+bool ProvinceDefinition::is_adjacent_to(ProvinceDefinition const* province) const {
+ return province != nullptr && std::any_of(adjacencies.begin(), adjacencies.end(),
+ [province](adjacency_t const& adj) -> bool { return adj.get_to() == province; }
+ );
+}
+
+std::vector<ProvinceDefinition::adjacency_t const*> ProvinceDefinition::get_adjacencies_going_through(
+ ProvinceDefinition const* province
+) const {
+ std::vector<adjacency_t const*> ret;
+ for (adjacency_t const& adj : adjacencies) {
+ if (adj.get_through() == province) {
+ ret.push_back(&adj);
+ }
+ }
+ return ret;
+}
+
+bool ProvinceDefinition::has_adjacency_going_through(ProvinceDefinition const* province) const {
+ return province != nullptr && std::any_of(adjacencies.begin(), adjacencies.end(),
+ [province](adjacency_t const& adj) -> bool { return adj.get_through() == province; }
+ );
+}
+
+fvec2_t ProvinceDefinition::get_unit_position() const {
+ return positions.unit.value_or(centre);
+}
diff --git a/src/openvic-simulation/map/Province.hpp b/src/openvic-simulation/map/ProvinceDefinition.hpp
index bfbeab2..a4076fe 100644
--- a/src/openvic-simulation/map/Province.hpp
+++ b/src/openvic-simulation/map/ProvinceDefinition.hpp
@@ -1,38 +1,34 @@
#pragma once
-#include "openvic-simulation/country/Country.hpp"
-#include "openvic-simulation/economy/BuildingInstance.hpp"
-#include "openvic-simulation/politics/Ideology.hpp"
-#include "openvic-simulation/pop/Pop.hpp"
+#include <optional>
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
+#include "openvic-simulation/types/HasIdentifier.hpp"
#include "openvic-simulation/types/OrderedContainers.hpp"
+#include "openvic-simulation/types/Vector.hpp"
namespace OpenVic {
+
struct Map;
struct Region;
- struct State;
- struct Crime;
- struct Good;
struct TerrainType;
- struct TerrainTypeMapping;
- struct ProvinceHistoryEntry;
struct ProvinceSetModifier;
using Climate = ProvinceSetModifier;
using Continent = ProvinceSetModifier;
- struct ArmyInstance;
- struct NavyInstance;
+ struct BuildingType;
+ struct BuildingTypeManager;
/* REQUIREMENTS:
* MAP-5, MAP-7, MAP-8, MAP-43, MAP-47
* POP-22
*/
- struct Province : HasIdentifierAndColour {
+ struct ProvinceDefinition : HasIdentifierAndColour {
friend struct Map;
using index_t = uint16_t;
- using life_rating_t = int8_t;
- using distance_t = fixed_point_t;
-
- enum struct colony_status_t : uint8_t { STATE, PROTECTORATE, COLONY };
+ using distance_t = fixed_point_t; // should this go inside adjacency_t?
struct adjacency_t {
using data_t = uint8_t;
@@ -51,15 +47,16 @@ namespace OpenVic {
static std::string_view get_type_name(type_t type);
private:
- Province const* PROPERTY(to);
- Province const* PROPERTY(through);
+ ProvinceDefinition const* PROPERTY(to);
+ ProvinceDefinition const* PROPERTY(through);
distance_t PROPERTY(distance);
type_t PROPERTY(type);
data_t PROPERTY(data); // represents canal index, 0 for non-canal adjacencies
public:
adjacency_t(
- Province const* new_to, distance_t new_distance, type_t new_type, Province const* new_through, data_t new_data
+ ProvinceDefinition const* new_to, distance_t new_distance, type_t new_type,
+ ProvinceDefinition const* new_through, data_t new_data
);
adjacency_t(adjacency_t const&) = delete;
adjacency_t(adjacency_t&&) = default;
@@ -92,11 +89,10 @@ namespace OpenVic {
Climate const* PROPERTY(climate);
Continent const* PROPERTY(continent);
bool PROPERTY(on_map);
- bool PROPERTY(has_region);
bool PROPERTY_CUSTOM_PREFIX(water, is);
bool PROPERTY_CUSTOM_PREFIX(coastal, is);
bool PROPERTY_CUSTOM_PREFIX(port, has);
- Province const* PROPERTY(port_adjacent_province);
+ ProvinceDefinition const* PROPERTY(port_adjacent_province);
/* Terrain type calculated from terrain image */
TerrainType const* PROPERTY(default_terrain_type);
@@ -105,39 +101,18 @@ namespace OpenVic {
fvec2_t PROPERTY(centre);
province_positions_t positions;
- /* Mutable attributes (reset before loading history) */
- TerrainType const* PROPERTY(terrain_type);
- life_rating_t PROPERTY(life_rating);
- colony_status_t PROPERTY(colony_status);
- State const* PROPERTY_RW(state);
- Country const* PROPERTY(owner);
- Country const* PROPERTY(controller);
- std::vector<Country const*> PROPERTY(cores);
- bool PROPERTY(slave);
- Crime const* PROPERTY_RW(crime);
- // TODO - change this into a factory-like structure
- Good const* PROPERTY(rgo);
- IdentifierRegistry<BuildingInstance> IDENTIFIER_REGISTRY(building);
- ordered_set<ArmyInstance*> PROPERTY(armies);
- ordered_set<NavyInstance*> PROPERTY(navies);
-
- std::vector<Pop> PROPERTY(pops);
- Pop::pop_size_t PROPERTY(total_population);
- fixed_point_map_t<PopType const*> PROPERTY(pop_type_distribution);
- fixed_point_map_t<Ideology const*> PROPERTY(ideology_distribution);
- fixed_point_map_t<Culture const*> PROPERTY(culture_distribution);
- fixed_point_map_t<Religion const*> PROPERTY(religion_distribution);
-
- Province(std::string_view new_identifier, colour_t new_colour, index_t new_index);
-
- void _add_pop(Pop pop);
+ ProvinceDefinition(std::string_view new_identifier, colour_t new_colour, index_t new_index);
public:
- Province(Province&&) = default;
+ ProvinceDefinition(ProvinceDefinition&&) = default;
- bool operator==(Province const& other) const;
+ bool operator==(ProvinceDefinition const& other) const;
std::string to_string() const;
+ inline constexpr bool has_region() const {
+ return region != nullptr;
+ }
+
/* The positions' y coordinates need to be inverted. */
bool load_positions(Map const& map, BuildingTypeManager const& building_type_manager, ast::NodeCPtr root);
@@ -145,35 +120,15 @@ namespace OpenVic {
fixed_point_t get_text_rotation() const;
fixed_point_t get_text_scale() const;
- bool expand_building(size_t building_index);
/* This returns a pointer to the position of the specified building type, or nullptr if none exists. */
fvec2_t const* get_building_position(BuildingType const* building_type) const;
fixed_point_t get_building_rotation(BuildingType const* building_type) const;
- bool add_pop(Pop&& pop);
- bool add_pop_vec(std::vector<Pop> const& pop_vec);
- size_t get_pop_count() const;
- void update_pops();
-
- void update_gamestate(Date today);
- void tick(Date today);
-
- adjacency_t const* get_adjacency_to(Province const* province) const;
- bool is_adjacent_to(Province const* province) const;
- std::vector<adjacency_t const*> get_adjacencies_going_through(Province const* province) const;
- bool has_adjacency_going_through(Province const* province) const;
+ adjacency_t const* get_adjacency_to(ProvinceDefinition const* province) const;
+ bool is_adjacent_to(ProvinceDefinition const* province) const;
+ std::vector<adjacency_t const*> get_adjacencies_going_through(ProvinceDefinition const* province) const;
+ bool has_adjacency_going_through(ProvinceDefinition const* province) const;
fvec2_t get_unit_position() const;
- bool add_army(ArmyInstance& army);
- bool remove_army(ArmyInstance& army);
- bool add_navy(NavyInstance& navy);
- bool remove_navy(NavyInstance& navy);
-
- 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/map/ProvinceInstance.cpp b/src/openvic-simulation/map/ProvinceInstance.cpp
new file mode 100644
index 0000000..ba52280
--- /dev/null
+++ b/src/openvic-simulation/map/ProvinceInstance.cpp
@@ -0,0 +1,213 @@
+#include "ProvinceInstance.hpp"
+
+#include "openvic-simulation/country/Country.hpp"
+#include "openvic-simulation/history/ProvinceHistory.hpp"
+#include "openvic-simulation/map/ProvinceDefinition.hpp"
+#include "openvic-simulation/military/UnitInstance.hpp"
+
+using namespace OpenVic;
+
+ProvinceInstance::ProvinceInstance(ProvinceDefinition const& new_province_definition)
+ : HasIdentifier { new_province_definition.get_identifier() }, province_definition { new_province_definition },
+ terrain_type { nullptr }, life_rating { 0 }, colony_status { colony_status_t::STATE }, state { nullptr },
+ owner { nullptr }, controller { nullptr }, cores {}, slave { false }, crime { nullptr }, rgo { nullptr },
+ buildings { "buildings", false }, armies {}, navies {}, pops {}, total_population { 0 }, pop_type_distribution {},
+ ideology_distribution {}, culture_distribution {}, religion_distribution {} {}
+
+bool ProvinceInstance::expand_building(size_t building_index) {
+ BuildingInstance* building = buildings.get_item_by_index(building_index);
+ if (building == nullptr) {
+ Logger::error("Trying to expand non-existent building index ", building_index, " in province ", get_identifier());
+ return false;
+ }
+ return building->expand();
+}
+
+void ProvinceInstance::_add_pop(Pop pop) {
+ pop.set_location(this);
+ pops.push_back(std::move(pop));
+}
+
+bool ProvinceInstance::add_pop(Pop&& pop) {
+ if (!province_definition.is_water()) {
+ _add_pop(std::move(pop));
+ return true;
+ } else {
+ Logger::error("Trying to add pop to water province ", get_identifier());
+ return false;
+ }
+}
+
+bool ProvinceInstance::add_pop_vec(std::vector<Pop> const& pop_vec) {
+ if (!province_definition.is_water()) {
+ reserve_more(pops, pop_vec.size());
+ for (Pop const& pop : pop_vec) {
+ _add_pop(pop);
+ }
+ return true;
+ } else {
+ Logger::error("Trying to add pop vector to water province ", get_identifier());
+ return false;
+ }
+}
+
+size_t ProvinceInstance::get_pop_count() const {
+ return pops.size();
+}
+
+/* REQUIREMENTS:
+ * MAP-65, MAP-68, MAP-70, MAP-234
+ */
+void ProvinceInstance::_update_pops() {
+ total_population = 0;
+ pop_type_distribution.clear();
+ ideology_distribution.clear();
+ culture_distribution.clear();
+ religion_distribution.clear();
+ for (Pop const& pop : pops) {
+ total_population += pop.get_size();
+ pop_type_distribution[&pop.get_type()] += pop.get_size();
+ ideology_distribution += pop.get_ideologies();
+ culture_distribution[&pop.get_culture()] += pop.get_size();
+ religion_distribution[&pop.get_religion()] += pop.get_size();
+ }
+}
+
+void ProvinceInstance::update_gamestate(Date today) {
+ for (BuildingInstance& building : buildings.get_items()) {
+ building.update_gamestate(today);
+ }
+ _update_pops();
+}
+
+void ProvinceInstance::tick(Date today) {
+ for (BuildingInstance& building : buildings.get_items()) {
+ building.tick(today);
+ }
+}
+
+bool ProvinceInstance::add_army(ArmyInstance& army) {
+ if (armies.emplace(&army).second) {
+ return true;
+ } else {
+ Logger::error("Trying to add already-existing army ", army.get_name(), " to province ", get_identifier());
+ return false;
+ }
+}
+
+bool ProvinceInstance::remove_army(ArmyInstance& army) {
+ if (armies.erase(&army) > 0) {
+ return true;
+ } else {
+ Logger::error("Trying to remove non-existent army ", army.get_name(), " from province ", get_identifier());
+ return false;
+ }
+}
+
+bool ProvinceInstance::add_navy(NavyInstance& navy) {
+ if (navies.emplace(&navy).second) {
+ return true;
+ } else {
+ Logger::error("Trying to add already-existing navy ", navy.get_name(), " to province ", get_identifier());
+ return false;
+ }
+}
+
+bool ProvinceInstance::remove_navy(NavyInstance& navy) {
+ if (navies.erase(&navy) > 0) {
+ return true;
+ } else {
+ Logger::error("Trying to remove non-existent navy ", navy.get_name(), " from province ", get_identifier());
+ return false;
+ }
+}
+
+bool ProvinceInstance::reset(BuildingTypeManager const& building_type_manager) {
+ terrain_type = province_definition.get_default_terrain_type();
+ life_rating = 0;
+ colony_status = colony_status_t::STATE;
+ state = nullptr;
+ owner = nullptr;
+ controller = nullptr;
+ cores.clear();
+ slave = false;
+ crime = nullptr;
+ rgo = nullptr;
+
+ buildings.reset();
+ bool ret = true;
+ if (!province_definition.is_water()) {
+ if (building_type_manager.building_types_are_locked()) {
+ for (BuildingType const* building_type : building_type_manager.get_province_building_types()) {
+ ret &= buildings.add_item({ *building_type });
+ }
+ } else {
+ Logger::error("Cannot generate buildings until building types are locked!");
+ ret = false;
+ }
+ }
+ lock_buildings();
+
+ pops.clear();
+ _update_pops();
+
+ return ret;
+}
+
+bool ProvinceInstance::apply_history_to_province(ProvinceHistoryEntry const* entry) {
+ if (entry == nullptr) {
+ Logger::error("Trying to apply null province history to ", get_identifier());
+ return false;
+ }
+ if (entry->get_life_rating()) life_rating = *entry->get_life_rating();
+ if (entry->get_colonial()) colony_status = *entry->get_colonial();
+ if (entry->get_rgo()) rgo = *entry->get_rgo();
+ if (entry->get_terrain_type()) terrain_type = *entry->get_terrain_type();
+ if (entry->get_owner()) owner = *entry->get_owner();
+ if (entry->get_controller()) controller = *entry->get_controller();
+ if (entry->get_slave()) slave = *entry->get_slave();
+ for (Country const* core : entry->get_remove_cores()) {
+ const typename decltype(cores)::iterator existing_core = std::find(cores.begin(), cores.end(), core);
+ if (existing_core != cores.end()) {
+ cores.erase(existing_core);
+ } else {
+ Logger::warning(
+ "Trying to remove non-existent core ", core->get_identifier(), " from province ", get_identifier()
+ );
+ }
+ }
+ for (Country const* core : entry->get_add_cores()) {
+ const typename decltype(cores)::iterator existing_core = std::find(cores.begin(), cores.end(), core);
+ if (existing_core == cores.end()) {
+ cores.push_back(core);
+ } else {
+ Logger::warning(
+ "Trying to add already-existing core ", core->get_identifier(), " to province ", get_identifier()
+ );
+ }
+ }
+ bool ret = true;
+ for (auto const& [building, level] : entry->get_province_buildings()) {
+ BuildingInstance* existing_entry = buildings.get_item_by_identifier(building->get_identifier());
+ if (existing_entry != nullptr) {
+ existing_entry->set_level(level);
+ } else {
+ Logger::error(
+ "Trying to set level of non-existent province building ", building->get_identifier(), " to ", level,
+ " in province ", get_identifier()
+ );
+ ret = false;
+ }
+ }
+ // TODO: load state buildings
+ // TODO: party loyalties for each POP when implemented on POP side
+ return ret;
+}
+
+void ProvinceInstance::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/ProvinceInstance.hpp b/src/openvic-simulation/map/ProvinceInstance.hpp
new file mode 100644
index 0000000..2dbc4e3
--- /dev/null
+++ b/src/openvic-simulation/map/ProvinceInstance.hpp
@@ -0,0 +1,91 @@
+#pragma once
+
+#include "openvic-simulation/economy/BuildingInstance.hpp"
+#include "openvic-simulation/pop/Pop.hpp"
+#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
+#include "openvic-simulation/types/HasIdentifier.hpp"
+#include "openvic-simulation/types/OrderedContainers.hpp"
+
+namespace OpenVic {
+ struct ProvinceDefinition;
+ struct TerrainType;
+ struct State;
+ struct Country;
+ struct Crime;
+ struct Good;
+ struct ArmyInstance;
+ struct NavyInstance;
+ struct Ideology;
+ struct Culture;
+ struct Religion;
+ struct BuildingTypeManager;
+ struct ProvinceHistoryEntry;
+ struct IdeologyManager;
+ struct IssueManager;
+
+ struct ProvinceInstance : HasIdentifier {
+ friend struct Map;
+
+ using life_rating_t = int8_t;
+
+ enum struct colony_status_t : uint8_t { STATE, PROTECTORATE, COLONY };
+
+ ProvinceDefinition const& PROPERTY(province_definition);
+
+ /* Mutable attributes (reset before loading history) */
+ TerrainType const* PROPERTY(terrain_type);
+ life_rating_t PROPERTY(life_rating);
+ colony_status_t PROPERTY(colony_status);
+ State const* PROPERTY_RW(state);
+ Country const* PROPERTY(owner);
+ Country const* PROPERTY(controller);
+ std::vector<Country const*> PROPERTY(cores);
+ bool PROPERTY(slave);
+ Crime const* PROPERTY_RW(crime);
+ // TODO - change this into a factory-like structure
+ Good const* PROPERTY(rgo);
+ IdentifierRegistry<BuildingInstance> IDENTIFIER_REGISTRY(building);
+ ordered_set<ArmyInstance*> PROPERTY(armies);
+ ordered_set<NavyInstance*> PROPERTY(navies);
+
+ std::vector<Pop> PROPERTY(pops);
+ Pop::pop_size_t PROPERTY(total_population);
+ fixed_point_map_t<PopType const*> PROPERTY(pop_type_distribution);
+ fixed_point_map_t<Ideology const*> PROPERTY(ideology_distribution);
+ fixed_point_map_t<Culture const*> PROPERTY(culture_distribution);
+ fixed_point_map_t<Religion const*> PROPERTY(religion_distribution);
+
+ ProvinceInstance(ProvinceDefinition const& new_province_definition);
+
+ void _add_pop(Pop pop);
+ void _update_pops();
+
+ public:
+ ProvinceInstance(ProvinceInstance&&) = default;
+
+ inline constexpr operator ProvinceDefinition const&() const {
+ return province_definition;
+ }
+
+ bool expand_building(size_t building_index);
+
+ bool add_pop(Pop&& pop);
+ bool add_pop_vec(std::vector<Pop> const& pop_vec);
+ size_t get_pop_count() const;
+
+ void update_gamestate(Date today);
+ void tick(Date today);
+
+ bool add_army(ArmyInstance& army);
+ bool remove_army(ArmyInstance& army);
+ bool add_navy(NavyInstance& navy);
+ bool remove_navy(NavyInstance& navy);
+
+ 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/map/Region.cpp b/src/openvic-simulation/map/Region.cpp
index 9b31d0f..89dab20 100644
--- a/src/openvic-simulation/map/Region.cpp
+++ b/src/openvic-simulation/map/Region.cpp
@@ -1,10 +1,11 @@
#include "Region.hpp"
+#include "openvic-simulation/map/ProvinceDefinition.hpp"
#include "openvic-simulation/types/Colour.hpp"
using namespace OpenVic;
-bool ProvinceSet::add_province(Province const* province) {
+bool ProvinceSet::add_province(ProvinceDefinition const* province) {
if (locked) {
Logger::error("Cannot add province to province set - locked!");
return false;
@@ -21,15 +22,7 @@ bool ProvinceSet::add_province(Province const* province) {
return true;
}
-bool ProvinceSet::add_provinces(provinces_t const& new_provinces) {
- bool ret = true;
- for (Province const* province : new_provinces) {
- ret &= add_province(province);
- }
- return ret;
-}
-
-bool ProvinceSet::remove_province(Province const* province) {
+bool ProvinceSet::remove_province(ProvinceDefinition const* province) {
if (locked) {
Logger::error("Cannot remove province from province set - locked!");
return false;
@@ -38,7 +31,7 @@ bool ProvinceSet::remove_province(Province const* province) {
Logger::error("Cannot remove province from province set - null province!");
return false;
}
- const provinces_t::const_iterator it = std::find(provinces.begin(), provinces.end(), province);
+ const decltype(provinces)::const_iterator it = std::find(provinces.begin(), provinces.end(), province);
if (it == provinces.end()) {
Logger::warning("Cannot remove province ", province->get_identifier(), " from province set - already not in the set!");
return false;
@@ -87,22 +80,8 @@ void ProvinceSet::reserve_more(size_t size) {
OpenVic::reserve_more(*this, size);
}
-bool ProvinceSet::contains_province(Province const* province) const {
- return province && std::find(provinces.begin(), provinces.end(), province) != provinces.end();
-}
-
-ProvinceSet::provinces_t const& ProvinceSet::get_provinces() const {
- return provinces;
-}
-
-Pop::pop_size_t ProvinceSet::calculate_total_population() const {
- Pop::pop_size_t total_population = 0;
-
- for (Province const* province : provinces) {
- total_population += province->get_total_population();
- }
-
- return total_population;
+bool ProvinceSet::contains_province(ProvinceDefinition const* province) const {
+ return province != nullptr && std::find(provinces.begin(), provinces.end(), province) != provinces.end();
}
ProvinceSetModifier::ProvinceSetModifier(std::string_view new_identifier, ModifierValue&& new_values)
diff --git a/src/openvic-simulation/map/Region.hpp b/src/openvic-simulation/map/Region.hpp
index f12e14a..f532400 100644
--- a/src/openvic-simulation/map/Region.hpp
+++ b/src/openvic-simulation/map/Region.hpp
@@ -1,22 +1,40 @@
#pragma once
-#include "openvic-simulation/map/Province.hpp"
+#include <ranges>
+#include <string_view>
+#include <vector>
+
+#include "openvic-simulation/misc/Modifier.hpp"
namespace OpenVic {
- struct ProvinceSet {
- using provinces_t = std::vector<Province const*>;
+ struct ProvinceDefinition;
+ struct ProvinceSet {
private:
- provinces_t provinces;
+ std::vector<ProvinceDefinition const*> PROPERTY(provinces);
bool locked = false;
public:
/* Returns true if the province is successfully added, false if not (including if it's already in the set). */
- bool add_province(Province const* province);
- bool add_provinces(provinces_t const& new_provinces);
+ bool add_province(ProvinceDefinition const* province);
+
+ template<std::ranges::sized_range Container>
+ requires std::convertible_to<std::ranges::range_value_t<Container>, ProvinceDefinition const*>
+ bool add_provinces(Container const& new_provinces) {
+ reserve_more(new_provinces.size());
+
+ bool ret = true;
+
+ for (ProvinceDefinition const* province : new_provinces) {
+ ret &= add_province(province);
+ }
+
+ return ret;
+ }
+
/* Returns true if the province is successfully removed, false if not (including if it's not in the set). */
- bool remove_province(Province const* province);
+ bool remove_province(ProvinceDefinition const* province);
void lock(bool log = false);
bool is_locked() const;
void reset();
@@ -24,9 +42,7 @@ namespace OpenVic {
size_t size() const;
void reserve(size_t size);
void reserve_more(size_t size);
- bool contains_province(Province const* province) const;
- provinces_t const& get_provinces() const;
- Pop::pop_size_t calculate_total_population() const;
+ bool contains_province(ProvinceDefinition const* province) const;
};
struct ProvinceSetModifier : Modifier, ProvinceSet {
diff --git a/src/openvic-simulation/map/State.cpp b/src/openvic-simulation/map/State.cpp
index c1f802d..1c49ed7 100644
--- a/src/openvic-simulation/map/State.cpp
+++ b/src/openvic-simulation/map/State.cpp
@@ -1,68 +1,131 @@
#include "State.hpp"
+#include "openvic-simulation/country/Country.hpp"
#include "openvic-simulation/map/Map.hpp"
+#include "openvic-simulation/map/ProvinceInstance.hpp"
+#include "openvic-simulation/map/Region.hpp"
using namespace OpenVic;
State::State(
- Country const* owner, Province const* capital, Region::provinces_t&& provinces, Province::colony_status_t colony_status
-) : owner { owner }, capital { capital }, provinces { std::move(provinces) }, colony_status { colony_status } {}
+ StateSet const& new_state_set, Country const* owner, ProvinceInstance* capital, std::vector<ProvinceInstance*>&& provinces,
+ ProvinceInstance::colony_status_t colony_status
+) : state_set { new_state_set }, owner { owner }, capital { capital }, provinces { std::move(provinces) },
+ colony_status { colony_status } {}
+
+void State::update_gamestate() {
+ total_population = 0;
+
+ for (ProvinceInstance const* province : provinces) {
+ total_population += province->get_total_population();
+ }
+}
/* Whether two provinces in the same region should be grouped into the same state or not.
* (Assumes both provinces non-null.) */
-static bool provinces_belong_in_same_state(Province const* lhs, Province const* rhs) {
+static bool provinces_belong_in_same_state(ProvinceInstance const* lhs, ProvinceInstance const* rhs) {
return lhs->get_owner() == rhs->get_owner() && lhs->get_colony_status() == rhs->get_colony_status();
}
-StateSet::StateSet(Map& map, Region const& new_region) : region { new_region } {
+StateSet::StateSet(Region const& new_region) : region { new_region }, states {} {}
+
+size_t StateSet::get_state_count() const {
+ return states.size();
+}
+
+void StateSet::update_gamestate() {
+ for (State& state : states) {
+ state.update_gamestate();
+ }
+}
+
+bool StateManager::add_state_set(Map& map, Region const& region) {
if (region.get_meta()) {
- Logger::error("Cannot use meta region as state template!");
+ Logger::error("Cannot use meta region \"", region.get_identifier(), "\" as state template!");
+ return false;
+ }
+
+ if (region.empty()) {
+ Logger::error("Cannot use empty region \"", region.get_identifier(), "\" as state template!");
+ return false;
}
- std::vector<Region::provinces_t> temp_provinces;
+ std::vector<std::vector<ProvinceInstance*>> temp_provinces;
+
+ for (ProvinceDefinition const* province : region.get_provinces()) {
+
+ ProvinceInstance* province_instance = map.get_province_instance_from_const(province);
- for (Province const* province : region.get_provinces()) {
// add to existing state if shared owner & status...
- for (Region::provinces_t& provinces : temp_provinces) {
- if (provinces_belong_in_same_state(provinces[0], province)) {
- provinces.push_back(province);
+ for (std::vector<ProvinceInstance*>& provinces : temp_provinces) {
+ if (provinces_belong_in_same_state(provinces.front(), province_instance)) {
+ provinces.push_back(province_instance);
// jump to the end of the outer loop, skipping the new state code
goto loop_end;
}
}
+
// ...otherwise start a new state
- temp_provinces.push_back({ province });
+ temp_provinces.push_back({ province_instance });
+
loop_end:;
/* Either the province was added to an existing state and the program jumped to here,
* or it was used to create a new state and the program arrived here normally. */
}
- for (Region::provinces_t& provinces : temp_provinces) {
- states.emplace_back(
+ state_sets.push_back({ region });
+
+ StateSet& state_set = state_sets.back();
+
+ // Reserve space for the maximum number of states (one per province)
+ state_set.states.reserve(region.size());
+
+ for (std::vector<ProvinceInstance*>& provinces : temp_provinces) {
+ ProvinceInstance* capital = provinces.front();
+
+ state_set.states.push_back(
/* TODO: capital province logic */
- provinces[0]->get_owner(), provinces[0], std::move(provinces), provinces[0]->get_colony_status()
+ { state_set, capital->get_owner(), capital, std::move(provinces), capital->get_colony_status() }
);
- }
- // Go back and assign each new state to its provinces.
- for (State const& state : states) {
- for (Province const* province : state.get_provinces()) {
- map.remove_province_const(province)->set_state(&state);
+ State const& state = state_set.states.back();
+
+ for (ProvinceInstance* province : state.get_provinces()) {
+ province->set_state(&state);
}
}
-}
-StateSet::states_t& StateSet::get_states() {
- return states;
+ return true;
}
-void StateManager::generate_states(Map& map) {
- regions.clear();
- regions.reserve(map.get_region_count());
+bool StateManager::generate_states(Map& map) {
+ state_sets.clear();
+ state_sets.reserve(map.get_region_count());
+
+ bool ret = true;
+ size_t state_count = 0;
+
for (Region const& region : map.get_regions()) {
if (!region.get_meta()) {
- regions.emplace_back(map, region);
+ if (add_state_set(map, region)) {
+ state_count += state_sets.back().get_state_count();
+ } else {
+ ret = false;
+ }
}
}
- Logger::info("Generated states.");
+
+ Logger::info("Generated ", state_count, " states across ", state_sets.size(), " state sets.");
+
+ return ret;
+}
+
+void StateManager::reset() {
+ state_sets.clear();
+}
+
+void StateManager::update_gamestate() {
+ for (StateSet& state_set : state_sets) {
+ state_set.update_gamestate();
+ }
}
diff --git a/src/openvic-simulation/map/State.hpp b/src/openvic-simulation/map/State.hpp
index bae83f7..e030a0b 100644
--- a/src/openvic-simulation/map/State.hpp
+++ b/src/openvic-simulation/map/State.hpp
@@ -1,48 +1,75 @@
#pragma once
-#include "openvic-simulation/map/Province.hpp"
-#include "openvic-simulation/map/Region.hpp"
-#include "openvic-simulation/country/Country.hpp"
+#include <vector>
-#include <deque>
+#include "openvic-simulation/map/ProvinceInstance.hpp"
+#include "openvic-simulation/pop/Pop.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
namespace OpenVic {
+ struct StateManager;
+ struct StateSet;
+ struct Country;
+ struct ProvinceInstance;
+
struct State {
+ friend struct StateManager;
+
private:
- Country const* PROPERTY_RW(owner);
- Province const* PROPERTY_RW(capital);
- Region::provinces_t PROPERTY(provinces);
- Province::colony_status_t PROPERTY_RW(colony_status);
+ StateSet const& PROPERTY(state_set);
+ Country const* PROPERTY(owner);
+ ProvinceInstance* PROPERTY(capital);
+ std::vector<ProvinceInstance*> PROPERTY(provinces);
+ ProvinceInstance::colony_status_t PROPERTY(colony_status);
+
+ Pop::pop_size_t PROPERTY(total_population);
- public:
State(
- Country const* owner, Province const* capital, Region::provinces_t&& provinces,
- Province::colony_status_t colony_status
+ StateSet const& new_state_set, Country const* owner, ProvinceInstance* capital,
+ std::vector<ProvinceInstance*>&& provinces, ProvinceInstance::colony_status_t colony_status
);
+
+ public:
+ void update_gamestate();
};
+ struct Region;
+
struct StateSet {
- using states_t = std::deque<State>;
+ friend struct StateManager;
+
+ // TODO - use a container that supports adding and removing items without invalidating pointers
+ using states_t = std::vector<State>;
private:
Region const& PROPERTY(region);
states_t PROPERTY(states);
+ StateSet(Region const& new_region);
+
public:
- StateSet(Map& map, Region const& new_region);
+ size_t get_state_count() const;
- states_t& get_states();
+ void update_gamestate();
};
+ struct Map;
+
/* Contains all current states.*/
struct StateManager {
private:
- std::vector<StateSet> PROPERTY(regions);
+ std::vector<StateSet> PROPERTY(state_sets);
+
+ bool add_state_set(Map& map, Region const& region);
public:
/* Creates states from current province gamestate & regions, sets province state value.
* After this function, the `regions` property is unmanaged and must be carefully updated and
* validated by functions that modify it. */
- void generate_states(Map& map);
+ bool generate_states(Map& map);
+
+ void reset();
+
+ void update_gamestate();
};
-} // namespace OpenVic
+}
diff --git a/src/openvic-simulation/military/Deployment.cpp b/src/openvic-simulation/military/Deployment.cpp
index 1f8b820..4550108 100644
--- a/src/openvic-simulation/military/Deployment.cpp
+++ b/src/openvic-simulation/military/Deployment.cpp
@@ -5,18 +5,19 @@
using namespace OpenVic;
using namespace OpenVic::NodeTools;
-RegimentDeployment::RegimentDeployment(std::string_view new_name, RegimentType const& new_type, Province const* new_home)
- : name { new_name }, type { new_type }, home { new_home } {}
+RegimentDeployment::RegimentDeployment(
+ std::string_view new_name, RegimentType const& new_type, ProvinceDefinition const* new_home
+) : name { new_name }, type { new_type }, home { new_home } {}
ShipDeployment::ShipDeployment(std::string_view new_name, ShipType const& new_type)
: name { new_name }, type { new_type } {}
ArmyDeployment::ArmyDeployment(
- std::string_view new_name, Province const* new_location, std::vector<RegimentDeployment>&& new_regiments
+ std::string_view new_name, ProvinceDefinition const* new_location, std::vector<RegimentDeployment>&& new_regiments
) : name { new_name }, location { new_location }, regiments { std::move(new_regiments) } {}
NavyDeployment::NavyDeployment(
- std::string_view new_name, Province const* new_location, std::vector<ShipDeployment>&& new_ships
+ std::string_view new_name, ProvinceDefinition const* new_location, std::vector<ShipDeployment>&& new_ships
) : name { new_name }, location { new_location }, ships { std::move(new_ships) } {}
Deployment::Deployment(
@@ -120,24 +121,25 @@ bool DeploymentManager::load_oob_file(
},
"army", ZERO_OR_MORE, [&armies, &game_manager](ast::NodeCPtr node) -> bool {
std::string_view army_name {};
- Province const* army_location = nullptr;
+ ProvinceDefinition const* army_location = nullptr;
std::vector<RegimentDeployment> army_regiments {};
const bool ret = expect_dictionary_keys(
"name", ONE_EXACTLY, expect_string(assign_variable_callback(army_name)),
- "location", ONE_EXACTLY,
- game_manager.get_map().expect_province_identifier(assign_variable_callback_pointer(army_location)),
+ "location", ONE_EXACTLY, game_manager.get_map().expect_province_definition_identifier(
+ assign_variable_callback_pointer(army_location)
+ ),
"regiment", ONE_OR_MORE, [&game_manager, &army_regiments](ast::NodeCPtr node) -> bool {
std::string_view regiment_name {};
RegimentType const* regiment_type = nullptr;
- Province const* regiment_home = nullptr;
+ ProvinceDefinition const* regiment_home = nullptr;
const bool ret = expect_dictionary_keys(
"name", ONE_EXACTLY, expect_string(assign_variable_callback(regiment_name)),
"type", ONE_EXACTLY, game_manager.get_military_manager().get_unit_type_manager()
.expect_regiment_type_identifier(assign_variable_callback_pointer(regiment_type)),
"home", ZERO_OR_ONE, game_manager.get_map()
- .expect_province_identifier(assign_variable_callback_pointer(regiment_home))
+ .expect_province_definition_identifier(assign_variable_callback_pointer(regiment_home))
)(node);
if (regiment_home == nullptr) {
@@ -163,13 +165,14 @@ bool DeploymentManager::load_oob_file(
},
"navy", ZERO_OR_MORE, [&navies, &game_manager](ast::NodeCPtr node) -> bool {
std::string_view navy_name {};
- Province const* navy_location = nullptr;
+ ProvinceDefinition const* navy_location = nullptr;
std::vector<ShipDeployment> navy_ships {};
const bool ret = expect_dictionary_keys(
"name", ONE_EXACTLY, expect_string(assign_variable_callback(navy_name)),
- "location", ONE_EXACTLY,
- game_manager.get_map().expect_province_identifier(assign_variable_callback_pointer(navy_location)),
+ "location", ONE_EXACTLY, game_manager.get_map().expect_province_definition_identifier(
+ assign_variable_callback_pointer(navy_location)
+ ),
"ship", ONE_OR_MORE, [&game_manager, &navy_ships](ast::NodeCPtr node) -> bool {
std::string_view ship_name {};
ShipType const* ship_type = nullptr;
diff --git a/src/openvic-simulation/military/Deployment.hpp b/src/openvic-simulation/military/Deployment.hpp
index 8966397..6f4c21f 100644
--- a/src/openvic-simulation/military/Deployment.hpp
+++ b/src/openvic-simulation/military/Deployment.hpp
@@ -4,26 +4,30 @@
#include <string_view>
#include <vector>
-#include "openvic-simulation/dataloader/Dataloader.hpp"
-#include "openvic-simulation/map/Province.hpp"
#include "openvic-simulation/military/Leader.hpp"
-#include "openvic-simulation/military/UnitType.hpp"
+#include "openvic-simulation/types/HasIdentifier.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
namespace OpenVic {
+ struct ProvinceDefinition;
+ struct RegimentType;
+
struct RegimentDeployment {
friend struct DeploymentManager;
private:
std::string PROPERTY(name);
RegimentType const& PROPERTY(type);
- Province const* PROPERTY(home);
+ ProvinceDefinition const* PROPERTY(home);
- RegimentDeployment(std::string_view new_name, RegimentType const& new_type, Province const* new_home);
+ RegimentDeployment(std::string_view new_name, RegimentType const& new_type, ProvinceDefinition const* new_home);
public:
RegimentDeployment(RegimentDeployment&&) = default;
};
+ struct ShipType;
+
struct ShipDeployment {
friend struct DeploymentManager;
@@ -42,11 +46,11 @@ namespace OpenVic {
private:
std::string PROPERTY(name);
- Province const* PROPERTY(location);
+ ProvinceDefinition const* PROPERTY(location);
std::vector<RegimentDeployment> PROPERTY(regiments);
ArmyDeployment(
- std::string_view new_name, Province const* new_location, std::vector<RegimentDeployment>&& new_regiments
+ std::string_view new_name, ProvinceDefinition const* new_location, std::vector<RegimentDeployment>&& new_regiments
);
public:
@@ -58,10 +62,12 @@ namespace OpenVic {
private:
std::string PROPERTY(name);
- Province const* PROPERTY(location);
+ ProvinceDefinition const* PROPERTY(location);
std::vector<ShipDeployment> PROPERTY(ships);
- NavyDeployment(std::string_view new_name, Province const* new_location, std::vector<ShipDeployment>&& new_ships);
+ NavyDeployment(
+ std::string_view new_name, ProvinceDefinition const* new_location, std::vector<ShipDeployment>&& new_ships
+ );
public:
NavyDeployment(NavyDeployment&&) = default;
@@ -84,6 +90,9 @@ namespace OpenVic {
Deployment(Deployment&&) = default;
};
+ struct GameManager;
+ class Dataloader;
+
struct DeploymentManager {
private:
IdentifierRegistry<Deployment> IDENTIFIER_REGISTRY(deployment);
@@ -102,4 +111,4 @@ namespace OpenVic {
size_t get_missing_oob_file_count() const;
};
-} // namespace OpenVic
+}
diff --git a/src/openvic-simulation/military/UnitInstance.cpp b/src/openvic-simulation/military/UnitInstance.cpp
index fcb9e3b..1cd0813 100644
--- a/src/openvic-simulation/military/UnitInstance.cpp
+++ b/src/openvic-simulation/military/UnitInstance.cpp
@@ -4,7 +4,8 @@
#include "openvic-simulation/country/CountryInstance.hpp"
#include "openvic-simulation/map/Map.hpp"
-#include "openvic-simulation/military/UnitType.hpp"
+#include "openvic-simulation/map/ProvinceInstance.hpp"
+#include "openvic-simulation/military/Deployment.hpp"
using namespace OpenVic;
@@ -17,7 +18,7 @@ ShipInstance::ShipInstance(std::string_view new_name, ShipType const& new_ship_t
MovementInfo::MovementInfo() : path {}, movement_progress {} {}
//TODO: pathfinding logic
-MovementInfo::MovementInfo(Province const* starting_province, Province const* target_province)
+MovementInfo::MovementInfo(ProvinceInstance const* starting_province, ProvinceInstance const* target_province)
: path { starting_province, target_province }, movement_progress { 0 } {}
ArmyInstance::ArmyInstance(
@@ -27,7 +28,7 @@ ArmyInstance::ArmyInstance(
CountryInstance* new_country
) : UnitInstanceGroup { new_name, UnitType::branch_t::LAND, std::move(new_units), new_leader, new_country } {}
-void ArmyInstance::set_position(Province* new_position) {
+void ArmyInstance::set_position(ProvinceInstance* new_position) {
if (position != new_position) {
if (position != nullptr) {
position->remove_army(*this);
@@ -46,7 +47,7 @@ NavyInstance::NavyInstance(
CountryInstance* new_country
) : UnitInstanceGroup { new_name, UnitType::branch_t::NAVAL, std::move(new_units), new_leader, new_country } {}
-void NavyInstance::set_position(Province* new_position) {
+void NavyInstance::set_position(ProvinceInstance* new_position) {
if (position != new_position) {
if (position != nullptr) {
position->remove_navy(*this);
@@ -116,7 +117,7 @@ bool UnitInstanceManager::generate_army(Map& map, CountryInstance& country, Army
armies.push_back({ army_deployment.get_name(), std::move(army_regiments), nullptr, &country });
- armies.back().set_position(map.remove_province_const(army_deployment.get_location()));
+ armies.back().set_position(map.get_province_instance_from_const(army_deployment.get_location()));
return ret;
}
@@ -162,7 +163,7 @@ bool UnitInstanceManager::generate_navy(Map& map, CountryInstance& country, Navy
navies.push_back({ navy_deployment.get_name(), std::move(navy_ships), nullptr, &country });
- navies.back().set_position(map.remove_province_const(navy_deployment.get_location()));
+ navies.back().set_position(map.get_province_instance_from_const(navy_deployment.get_location()));
return ret;
}
diff --git a/src/openvic-simulation/military/UnitInstance.hpp b/src/openvic-simulation/military/UnitInstance.hpp
index e3d541a..a3a53d0 100644
--- a/src/openvic-simulation/military/UnitInstance.hpp
+++ b/src/openvic-simulation/military/UnitInstance.hpp
@@ -1,14 +1,14 @@
#pragma once
#include <concepts>
+#include <string>
#include <string_view>
#include <vector>
-#include "openvic-simulation/map/Province.hpp"
-#include "openvic-simulation/military/Deployment.hpp"
#include "openvic-simulation/military/Leader.hpp"
#include "openvic-simulation/military/UnitType.hpp"
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
namespace OpenVic {
template<std::derived_from<UnitType> T>
@@ -37,6 +37,8 @@ namespace OpenVic {
}
};
+ struct Pop;
+
struct RegimentInstance : UnitInstance<RegimentType> {
friend struct UnitInstanceManager;
@@ -59,14 +61,17 @@ namespace OpenVic {
ShipInstance(ShipInstance&&) = default;
};
+ struct ProvinceInstance;
+
struct MovementInfo {
private:
- std::vector<Province const*> PROPERTY(path);
+ std::vector<ProvinceInstance const*> PROPERTY(path);
fixed_point_t PROPERTY(movement_progress);
public:
MovementInfo();
- MovementInfo(Province const* starting_province, Province const* target_province); // contains/calls pathfinding logic
+ // contains/calls pathfinding logic
+ MovementInfo(ProvinceInstance const* starting_province, ProvinceInstance const* target_province);
};
struct CountryInstance;
@@ -82,7 +87,7 @@ namespace OpenVic {
MovementInfo PROPERTY_REF(movement_info);
protected:
- Province* PROPERTY_ACCESS(position, protected);
+ ProvinceInstance* PROPERTY_ACCESS(position, protected);
CountryInstance* PROPERTY_ACCESS(country, protected);
UnitInstanceGroup(
@@ -140,7 +145,7 @@ namespace OpenVic {
)->first;
}
- virtual void set_position(Province* new_position) = 0;
+ virtual void set_position(ProvinceInstance* new_position) = 0;
};
struct ArmyInstance : UnitInstanceGroup<RegimentInstance> {
@@ -157,7 +162,7 @@ namespace OpenVic {
public:
ArmyInstance(ArmyInstance&&) = default;
- void set_position(Province* new_position) override;
+ void set_position(ProvinceInstance* new_position) override;
};
struct NavyInstance : UnitInstanceGroup<ShipInstance> {
@@ -176,9 +181,16 @@ namespace OpenVic {
public:
NavyInstance(NavyInstance&&) = default;
- void set_position(Province* new_position) override;
+ void set_position(ProvinceInstance* new_position) override;
};
+ struct RegimentDeployment;
+ struct ShipDeployment;
+ struct Map;
+ struct ArmyDeployment;
+ struct NavyDeployment;
+ struct Deployment;
+
struct UnitInstanceManager {
private:
std::deque<RegimentInstance> PROPERTY(regiments);
diff --git a/src/openvic-simulation/pop/Pop.hpp b/src/openvic-simulation/pop/Pop.hpp
index fe1867f..7fc7456 100644
--- a/src/openvic-simulation/pop/Pop.hpp
+++ b/src/openvic-simulation/pop/Pop.hpp
@@ -23,7 +23,7 @@ namespace OpenVic {
struct IdeologyManager;
struct Issue;
struct IssueManager;
- struct Province;
+ struct ProvinceInstance;
struct CountryParty;
/* REQUIREMENTS:
@@ -41,7 +41,7 @@ namespace OpenVic {
Culture const& PROPERTY(culture);
Religion const& PROPERTY(religion);
pop_size_t PROPERTY(size);
- Province const* PROPERTY_RW(location);
+ ProvinceInstance const* PROPERTY_RW(location);
/* Last day's size change by source. */
pop_size_t PROPERTY(total_change);
@@ -237,8 +237,6 @@ namespace OpenVic {
return stream << ']';
}
- struct Province;
-
struct PopManager {
private:
/* Using strata/stratas instead of stratum/strata to avoid confusion. */
diff --git a/src/openvic-simulation/scripts/Condition.cpp b/src/openvic-simulation/scripts/Condition.cpp
index aab8d93..5bf4067 100644
--- a/src/openvic-simulation/scripts/Condition.cpp
+++ b/src/openvic-simulation/scripts/Condition.cpp
@@ -370,7 +370,7 @@ bool ConditionManager::setup_conditions(GameManager const& game_manager) {
);
import_identifiers(
- game_manager.get_map().get_province_identifiers(),
+ game_manager.get_map().get_province_definition_identifiers(),
GROUP,
COUNTRY,
PROVINCE,
@@ -485,7 +485,7 @@ callback_t<std::string_view> ConditionManager::expect_parse_identifier(
EXPECT_CALL_PLACEHOLDER(COUNTRY_FLAG);
EXPECT_CALL_PLACEHOLDER(PROVINCE_FLAG);
EXPECT_CALL(COUNTRY_TAG, country, game_manager.get_country_manager(), "THIS", "FROM", "OWNER");
- EXPECT_CALL(PROVINCE_ID, province, game_manager.get_map(), "THIS", "FROM");
+ EXPECT_CALL(PROVINCE_ID, province_definition, game_manager.get_map(), "THIS", "FROM");
EXPECT_CALL(REGION, region, game_manager.get_map());
EXPECT_CALL(IDEOLOGY, ideology, game_manager.get_politics_manager().get_ideology_manager());
EXPECT_CALL(REFORM_GROUP, reform_group, game_manager.get_politics_manager().get_issue_manager());