aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/history
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation/history')
-rw-r--r--src/openvic-simulation/history/CountryHistory.cpp11
-rw-r--r--src/openvic-simulation/history/CountryHistory.hpp4
-rw-r--r--src/openvic-simulation/history/HistoryManager.hpp3
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.cpp263
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.hpp88
5 files changed, 362 insertions, 7 deletions
diff --git a/src/openvic-simulation/history/CountryHistory.cpp b/src/openvic-simulation/history/CountryHistory.cpp
index b590022..5e91a85 100644
--- a/src/openvic-simulation/history/CountryHistory.cpp
+++ b/src/openvic-simulation/history/CountryHistory.cpp
@@ -185,7 +185,7 @@ inline CountryHistory const* CountryHistoryManager::get_country_history(Country
return get_country_history(country, entry->get_date());
}
-inline bool CountryHistoryManager::_load_country_history_entry(GameManager& game_manager, std::string_view name, OpenVic::Date date, ast::NodeCPtr root) {
+inline bool CountryHistoryManager::_load_country_history_entry(GameManager& game_manager, std::string_view name, Date const& date, ast::NodeCPtr root) {
Province const* capital = nullptr;
Culture const* primary_culture = nullptr;
Religion const* religion = nullptr;
@@ -291,10 +291,10 @@ inline bool CountryHistoryManager::_load_country_history_entry(GameManager& game
return ret;
}
-bool CountryHistoryManager::load_country_history_file(GameManager& game_manager, std::string_view name, Date start_date, ast::NodeCPtr root) {
+bool CountryHistoryManager::load_country_history_file(GameManager& game_manager, std::string_view name, ast::NodeCPtr root) {
if (game_manager.get_country_manager().get_country_by_identifier(name)->is_dynamic_tag()) return true; /* as far as I can tell dynamic countries are hardcoded, broken, and unused */
- bool ret = _load_country_history_entry(game_manager, name, start_date, root);
+ bool ret = _load_country_history_entry(game_manager, name, game_manager.get_define_manager().get_start_date(), root);
ret &= expect_dictionary(
[this, &game_manager, &name](std::string_view key, ast::NodeCPtr value) -> bool {
@@ -302,8 +302,9 @@ bool CountryHistoryManager::load_country_history_file(GameManager& game_manager,
Date entry = Date().from_string(key, &is_date, true);
if (!is_date) return true;
- if (entry > game_manager.get_define_manager().get_end_date()) {
- Logger::error("History entry ", entry.to_string(), " of country ", name, " defined after defined end date ", game_manager.get_define_manager().get_end_date().to_string());
+ Date const& end_date = game_manager.get_define_manager().get_end_date();
+ if (entry > end_date) {
+ Logger::error("History entry ", entry.to_string(), " of country ", name, " defined after defined end date ", end_date.to_string());
return false;
}
diff --git a/src/openvic-simulation/history/CountryHistory.hpp b/src/openvic-simulation/history/CountryHistory.hpp
index a59ebea..56d04c6 100644
--- a/src/openvic-simulation/history/CountryHistory.hpp
+++ b/src/openvic-simulation/history/CountryHistory.hpp
@@ -79,7 +79,7 @@ namespace OpenVic {
std::map<Country const*, std::map<Date, CountryHistory>> country_histories;
bool locked = false;
- inline bool _load_country_history_entry(GameManager& game_manager, std::string_view name, OpenVic::Date date, ast::NodeCPtr root);
+ inline bool _load_country_history_entry(GameManager& game_manager, std::string_view name, Date const& date, ast::NodeCPtr root);
public:
CountryHistoryManager() {}
@@ -114,7 +114,7 @@ namespace OpenVic {
/* Returns history of country at bookmark date. Return can be nullptr if an error occurs. */
inline CountryHistory const* get_country_history(Country const* country, Bookmark const* entry) const;
- bool load_country_history_file(GameManager& game_manager, std::string_view name, Date start_date, ast::NodeCPtr root);
+ bool load_country_history_file(GameManager& game_manager, std::string_view name, ast::NodeCPtr root);
};
} // namespace OpenVic
diff --git a/src/openvic-simulation/history/HistoryManager.hpp b/src/openvic-simulation/history/HistoryManager.hpp
index e0d6877..5782e97 100644
--- a/src/openvic-simulation/history/HistoryManager.hpp
+++ b/src/openvic-simulation/history/HistoryManager.hpp
@@ -2,6 +2,7 @@
#include "openvic-simulation/history/Bookmark.hpp"
#include "openvic-simulation/history/CountryHistory.hpp"
+#include "openvic-simulation/history/ProvinceHistory.hpp"
#include "openvic-simulation/types/IdentifierRegistry.hpp"
namespace OpenVic {
@@ -9,10 +10,12 @@ namespace OpenVic {
private:
BookmarkManager bookmark_manager;
CountryHistoryManager country_manager;
+ ProvinceHistoryManager province_manager;
public:
REF_GETTERS(bookmark_manager)
REF_GETTERS(country_manager)
+ REF_GETTERS(province_manager)
inline bool load_bookmark_file(ast::NodeCPtr root) {
return bookmark_manager.load_bookmark_file(root);
diff --git a/src/openvic-simulation/history/ProvinceHistory.cpp b/src/openvic-simulation/history/ProvinceHistory.cpp
new file mode 100644
index 0000000..469bbfd
--- /dev/null
+++ b/src/openvic-simulation/history/ProvinceHistory.cpp
@@ -0,0 +1,263 @@
+#include "ProvinceHistory.hpp"
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/GameManager.hpp"
+
+using namespace OpenVic;
+using namespace OpenVic::NodeTools;
+
+ProvinceHistory::ProvinceHistory(
+ Country const* new_owner,
+ Country const* new_controller,
+ std::vector<Country const*>&& new_cores,
+ Good const* new_rgo,
+ uint8_t new_life_rating,
+ TerrainType const* new_terrain_type,
+ std::map<Building const*, uint8_t>&& new_buildings,
+ std::map<Ideology const*, uint8_t>&& new_party_loyalties
+) : owner { new_owner },
+ controller { new_controller },
+ cores { std::move(new_cores) },
+ rgo { new_rgo },
+ life_rating { new_life_rating },
+ terrain_type { new_terrain_type },
+ buildings { std::move(new_buildings) },
+ party_loyalties { std::move(new_party_loyalties) } {}
+
+Country const* ProvinceHistory::get_owner() const {
+ return owner;
+}
+
+Country const* ProvinceHistory::get_controller() const {
+ return controller;
+}
+
+const std::vector<Country const*>& ProvinceHistory::get_cores() const {
+ return cores;
+}
+
+bool ProvinceHistory::is_core_of(Country const* country) const {
+ return std::find(cores.begin(), cores.end(), country) != cores.end();
+}
+
+Good const* ProvinceHistory::get_rgo() const {
+ return rgo;
+}
+
+uint8_t ProvinceHistory::get_life_rating() const {
+ return life_rating;
+}
+
+TerrainType const* ProvinceHistory::get_terrain_type() const {
+ return terrain_type;
+}
+
+const std::map<Building const*, uint8_t>& ProvinceHistory::get_buildings() const {
+ return buildings;
+}
+
+const std::map<Ideology const*, uint8_t>& ProvinceHistory::get_party_loyalties() const {
+ return party_loyalties;
+}
+
+bool ProvinceHistoryManager::add_province_history_entry(
+ Province const* province,
+ Date date,
+ Country const* owner,
+ Country const* controller,
+ std::vector<Country const*>&& cores,
+ Good const* rgo,
+ uint8_t life_rating,
+ TerrainType const* terrain_type,
+ std::map<Building const*, uint8_t>&& buildings,
+ std::map<Ideology const*, uint8_t>&& party_loyalties,
+ bool updated_cores,
+ bool updated_buildings,
+ bool updated_loyalties
+) {
+ if (locked) {
+ Logger::error("Cannot add new history entry to province history registry: locked!");
+ return false;
+ }
+
+ /* combine duplicate histories, priority to current (defined later) */
+ auto& province_registry = province_histories[province];
+ const auto existing_entry = province_registry.find(date);
+
+ if (existing_entry != province_registry.end()) {
+ if (owner != nullptr) existing_entry->second.owner = owner;
+ if (controller != nullptr) existing_entry->second.controller = controller;
+ if (updated_cores) existing_entry->second.cores = std::move(cores);
+ if (rgo != nullptr) existing_entry->second.rgo = rgo;
+ if (life_rating > 0) existing_entry->second.life_rating = life_rating;
+ if (terrain_type != nullptr) existing_entry->second.terrain_type = terrain_type;
+ if (updated_buildings) existing_entry->second.buildings = std::move(buildings);
+ if (updated_loyalties) existing_entry->second.party_loyalties = std::move(party_loyalties);
+ } else {
+ province_registry.emplace(date, ProvinceHistory {
+ owner,
+ controller,
+ std::move(cores),
+ rgo,
+ life_rating,
+ terrain_type,
+ std::move(buildings),
+ std::move(party_loyalties)
+ });
+ }
+ return true;
+}
+
+void ProvinceHistoryManager::lock_province_histories() {
+ for (const auto& entry : province_histories) {
+ if (entry.second.size() == 0) {
+ Logger::error("Attempted to lock province histories - province ", entry.first->get_identifier(), " has no history entries!");
+ }
+ }
+ Logger::info("Locked province history registry after registering ", province_histories.size(), " items");
+ locked = true;
+}
+
+bool ProvinceHistoryManager::is_locked() const {
+ return locked;
+}
+
+ProvinceHistory const* ProvinceHistoryManager::get_province_history(Province const* province, Date entry) const {
+ Date closest_entry;
+ auto province_registry = province_histories.find(province);
+
+ if (province_registry == province_histories.end()) {
+ Logger::error("Attempted to access history of undefined province ", province->get_identifier());
+ return nullptr;
+ }
+
+ for (const auto& current : province_registry->second) {
+ if (current.first == entry) return &current.second;
+ if (current.first > entry) continue;
+ if (current.first > closest_entry && current.first < entry) closest_entry = current.first;
+ }
+
+ auto entry_registry = province_registry->second.find(closest_entry);
+ if (entry_registry != province_registry->second.end()) return &entry_registry->second;
+ /* warned about lack of entries earlier, return nullptr */
+ return nullptr;
+}
+
+inline ProvinceHistory const* ProvinceHistoryManager::get_province_history(Province const* province, Bookmark const* bookmark) const {
+ return get_province_history(province, bookmark->get_date());
+}
+
+inline bool ProvinceHistoryManager::_load_province_history_entry(GameManager& game_manager, std::string_view province, Date const& date, ast::NodeCPtr root) {
+ Country const* owner = nullptr;
+ Country const* controller = nullptr;
+ std::vector<Country const*> cores;
+ Good const* rgo;
+ uint8_t life_rating = 0;
+ TerrainType const* terrain_type;
+ std::map<Building const*, uint8_t> buildings;
+ std::map<Ideology const*, uint8_t> party_loyalties;
+
+ bool updated_cores = false;
+ bool updated_buildings = false;
+ bool updated_loyalties = false;
+
+ bool ret = expect_dictionary_keys_and_default(
+ [&game_manager, &buildings, &updated_buildings](std::string_view key, ast::NodeCPtr value) -> bool {
+ // used for province buildings like forts or railroads
+ if (game_manager.get_economy_manager().get_building_manager().has_building_identifier(key)) {
+ Building const* building;
+ uint8_t level;
+
+ bool ret = game_manager.get_economy_manager().get_building_manager().expect_building_str(assign_variable_callback_pointer(building))(key);
+ ret &= expect_uint(assign_variable_callback(level))(value);
+
+ buildings.emplace(building, level);
+ updated_buildings = true;
+ return ret;
+ }
+
+ bool is_date;
+ Date().from_string(key, &is_date, true);
+ if (is_date) return true;
+
+ return key_value_invalid_callback(key, value);
+ },
+ "owner", ZERO_OR_ONE, game_manager.get_country_manager().expect_country_identifier(assign_variable_callback_pointer(owner)),
+ "controller", ZERO_OR_ONE, game_manager.get_country_manager().expect_country_identifier(assign_variable_callback_pointer(controller)),
+ "add_core", ZERO_OR_MORE, [&game_manager, &cores, &updated_cores](ast::NodeCPtr node) -> bool {
+ Country const* core;
+
+ bool ret = game_manager.get_country_manager().expect_country_identifier(assign_variable_callback_pointer(core))(node);
+ cores.push_back(core);
+ updated_cores = true;
+ return ret;
+ },
+ "trade_goods", ZERO_OR_ONE, game_manager.get_economy_manager().get_good_manager().expect_good_identifier(assign_variable_callback_pointer(rgo)),
+ "life_rating", ZERO_OR_ONE, expect_uint(assign_variable_callback(life_rating)),
+ "terrain", ZERO_OR_ONE, game_manager.get_map().get_terrain_type_manager().expect_terrain_type_identifier(assign_variable_callback_pointer(terrain_type)),
+ "party_loyalty", ZERO_OR_MORE, [&game_manager, &party_loyalties, &updated_loyalties](ast::NodeCPtr node) -> bool {
+ Ideology const* ideology;
+ uint8_t amount; // percent I do believe
+
+ bool ret = expect_dictionary_keys(
+ "ideology", ONE_EXACTLY, game_manager.get_politics_manager().get_ideology_manager().expect_ideology_identifier(assign_variable_callback_pointer(ideology)),
+ "loyalty_value", ONE_EXACTLY, expect_uint(assign_variable_callback(amount))
+ )(node);
+ party_loyalties.emplace(ideology, amount);
+ updated_loyalties = true;
+ return ret;
+ },
+ "state_building", ZERO_OR_MORE, [&game_manager, &buildings, &updated_buildings](ast::NodeCPtr node) -> bool {
+ Building const* building;
+ uint8_t level;
+
+ bool ret = expect_dictionary_keys(
+ "level", ONE_EXACTLY, expect_uint(assign_variable_callback(level)),
+ "building", ONE_EXACTLY, game_manager.get_economy_manager().get_building_manager().expect_building_identifier(assign_variable_callback_pointer(building)),
+ "upgrade", ZERO_OR_ONE, success_callback // doesn't appear to have an effect
+ )(node);
+ buildings.emplace(building, level);
+ updated_buildings = true;
+ return ret;
+ }
+ )(root);
+
+ ret &= add_province_history_entry(
+ game_manager.get_map().get_province_by_identifier(province),
+ date,
+ owner,
+ controller,
+ std::move(cores),
+ rgo,
+ life_rating,
+ terrain_type,
+ std::move(buildings),
+ std::move(party_loyalties),
+ updated_cores,
+ updated_buildings,
+ updated_loyalties
+ );
+ return ret;
+}
+
+bool ProvinceHistoryManager::load_province_history_file(GameManager& game_manager, std::string_view name, ast::NodeCPtr root) {
+ bool ret = _load_province_history_entry(game_manager, name, game_manager.get_define_manager().get_start_date(), root);
+
+ ret &= expect_dictionary(
+ [this, &game_manager, &name](std::string_view key, ast::NodeCPtr value) -> bool {
+ bool is_date = false;
+ Date entry = Date().from_string(key, &is_date, true);
+ if (!is_date) return true;
+
+ Date const& end_date = game_manager.get_define_manager().get_end_date();
+ if (entry > end_date) {
+ Logger::error("History entry ", entry.to_string(), " of province ", name, " defined after defined end date ", end_date.to_string());
+ return false;
+ }
+
+ return _load_province_history_entry(game_manager, name, entry, value);
+ }
+ )(root);
+
+ return ret;
+}
diff --git a/src/openvic-simulation/history/ProvinceHistory.hpp b/src/openvic-simulation/history/ProvinceHistory.hpp
new file mode 100644
index 0000000..4094403
--- /dev/null
+++ b/src/openvic-simulation/history/ProvinceHistory.hpp
@@ -0,0 +1,88 @@
+#pragma once
+
+#include <map>
+#include <vector>
+
+#include "openvic-simulation/map/Province.hpp"
+#include "openvic-simulation/map/TerrainType.hpp"
+#include "openvic-simulation/country/Country.hpp"
+#include "openvic-simulation/economy/Good.hpp"
+#include "openvic-simulation/economy/Building.hpp"
+#include "openvic-simulation/history/Bookmark.hpp"
+
+namespace OpenVic {
+ struct ProvinceHistoryManager;
+
+ struct ProvinceHistory {
+ friend struct ProvinceHistoryManager;
+
+ private:
+ Country const* owner;
+ Country const* controller;
+ std::vector<Country const*> cores;
+ Good const* rgo;
+ uint8_t life_rating;
+ TerrainType const* terrain_type;
+ std::map<Building const*, uint8_t> buildings;
+ std::map<Ideology const*, uint8_t> party_loyalties;
+
+ ProvinceHistory(
+ Country const* new_owner,
+ Country const* new_controller,
+ std::vector<Country const*>&& new_cores,
+ Good const* new_rgo,
+ uint8_t new_life_rating,
+ TerrainType const* new_terrain_type,
+ std::map<Building const*, uint8_t>&& new_buildings,
+ std::map<Ideology const*, uint8_t>&& new_party_loyalties
+ );
+
+ public:
+ Country const* get_owner() const;
+ Country const* get_controller() const;
+ const std::vector<Country const*>& get_cores() const;
+ bool is_core_of(Country const* country) const;
+ Good const* get_rgo() const;
+ uint8_t get_life_rating() const;
+ TerrainType const* get_terrain_type() const;
+ const std::map<Building const*, uint8_t>& get_buildings() const;
+ const std::map<Ideology const*, uint8_t>& get_party_loyalties() const;
+ };
+
+ struct ProvinceHistoryManager {
+ private:
+ std::map<Province const*, std::map<Date, ProvinceHistory>> province_histories;
+ bool locked = false;
+
+ inline bool _load_province_history_entry(GameManager& game_manager, std::string_view province, Date const& date, ast::NodeCPtr root);
+
+ public:
+ ProvinceHistoryManager() {}
+
+ bool add_province_history_entry(
+ Province const* province,
+ Date date,
+ Country const* owner,
+ Country const* controller,
+ std::vector<Country const*>&& cores,
+ Good const* rgo,
+ uint8_t life_rating,
+ TerrainType const* terrain_type,
+ std::map<Building const*, uint8_t>&& buildings,
+ std::map<Ideology const*, uint8_t>&& party_loyalties,
+ bool updated_cores,
+ bool updated_buildings,
+ bool updated_loyalties
+ );
+
+ void lock_province_histories();
+ bool is_locked() const;
+
+ /* Returns history of province at date, if date doesn't have an entry returns closest entry before date. Return can be nullptr if an error occurs. */
+ ProvinceHistory const* get_province_history(Province const* province, Date entry) const;
+ /* Returns history of province at bookmark date. Return can be nullptr if an error occurs. */
+ inline ProvinceHistory const* get_province_history(Province const* province, Bookmark const* bookmark) const;
+
+ bool load_province_history_file(GameManager& game_manager, std::string_view name, ast::NodeCPtr root);
+ };
+} // namespace OpenVic