From 37cdd775ac738b2a1264e32471385376e5a34f3a Mon Sep 17 00:00:00 2001 From: hop311 Date: Mon, 3 Jun 2024 23:39:34 +0100 Subject: Province const/mutable separation + State cleanup --- src/openvic-simulation/map/ProvinceInstance.cpp | 213 ++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 src/openvic-simulation/map/ProvinceInstance.cpp (limited to 'src/openvic-simulation/map/ProvinceInstance.cpp') 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 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); + } +} -- cgit v1.2.3-56-ga3b1