From 16349d6cad05497f983b1da123b6284ecfddd638 Mon Sep 17 00:00:00 2001 From: hop311 Date: Fri, 6 Sep 2024 23:07:27 +0100 Subject: Calculate country industrial power (states still need factory data) --- src/openvic-simulation/country/CountryInstance.cpp | 133 ++++++++++++++------- src/openvic-simulation/country/CountryInstance.hpp | 17 ++- src/openvic-simulation/history/CountryHistory.cpp | 4 + src/openvic-simulation/history/HistoryMap.hpp | 27 +++-- src/openvic-simulation/history/ProvinceHistory.cpp | 6 +- src/openvic-simulation/map/MapInstance.cpp | 10 +- src/openvic-simulation/map/ProvinceInstance.cpp | 33 +++-- src/openvic-simulation/map/ProvinceInstance.hpp | 2 +- src/openvic-simulation/map/State.cpp | 26 +++- src/openvic-simulation/map/State.hpp | 9 +- src/openvic-simulation/misc/Define.cpp | 4 +- src/openvic-simulation/misc/Define.hpp | 1 + 12 files changed, 180 insertions(+), 92 deletions(-) diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp index 2c7ff70..5ba8782 100644 --- a/src/openvic-simulation/country/CountryInstance.cpp +++ b/src/openvic-simulation/country/CountryInstance.cpp @@ -38,7 +38,10 @@ CountryInstance::CountryInstance( /* Production */ industrial_power { 0 }, + industrial_power_from_states {}, + industrial_power_from_investments {}, industrial_rank { 0 }, + foreign_investments {}, /* Budget */ cash_stockpile { 0 }, @@ -270,12 +273,17 @@ template void CountryInstance::add_leader(LeaderBranched const*); template bool CountryInstance::remove_leader(LeaderBranched const*); -bool CountryInstance::apply_history_to_country(CountryHistoryEntry const* entry, MapInstance& map_instance) { - if (entry == nullptr) { - Logger::error("Trying to apply null country history to ", get_identifier()); - return false; +void CountryInstance::apply_foreign_investments( + fixed_point_map_t const& investments, CountryInstanceManager const& country_instance_manager +) { + for (auto const& [country, money_invested] : investments) { + foreign_investments[&country_instance_manager.get_country_instance_from_definition(*country)] = money_invested; } +} +bool CountryInstance::apply_history_to_country( + CountryHistoryEntry const& entry, MapInstance& map_instance, CountryInstanceManager const& country_instance_manager +) { constexpr auto set_optional = [](T& target, std::optional const& source) { if (source) { target = *source; @@ -284,62 +292,94 @@ bool CountryInstance::apply_history_to_country(CountryHistoryEntry const* entry, bool ret = true; - set_optional(primary_culture, entry->get_primary_culture()); - for (Culture const* culture : entry->get_accepted_cultures()) { + set_optional(primary_culture, entry.get_primary_culture()); + for (Culture const* culture : entry.get_accepted_cultures()) { ret &= add_accepted_culture(*culture); } - set_optional(religion, entry->get_religion()); - set_optional(ruling_party, entry->get_ruling_party()); - set_optional(last_election, entry->get_last_election()); - ret &= upper_house.copy(entry->get_upper_house()); - if (entry->get_capital()) { - capital = &map_instance.get_province_instance_from_definition(**entry->get_capital()); - } - set_optional(government_type, entry->get_government_type()); - set_optional(plurality, entry->get_plurality()); - set_optional(national_value, entry->get_national_value()); - if (entry->is_civilised()) { - country_status = *entry->is_civilised() ? COUNTRY_STATUS_CIVILISED : COUNTRY_STATUS_UNCIVILISED; - } - set_optional(prestige, entry->get_prestige()); - for (Reform const* reform : entry->get_reforms()) { + set_optional(religion, entry.get_religion()); + set_optional(ruling_party, entry.get_ruling_party()); + set_optional(last_election, entry.get_last_election()); + ret &= upper_house.copy(entry.get_upper_house()); + if (entry.get_capital()) { + capital = &map_instance.get_province_instance_from_definition(**entry.get_capital()); + } + set_optional(government_type, entry.get_government_type()); + set_optional(plurality, entry.get_plurality()); + set_optional(national_value, entry.get_national_value()); + if (entry.is_civilised()) { + country_status = *entry.is_civilised() ? COUNTRY_STATUS_CIVILISED : COUNTRY_STATUS_UNCIVILISED; + } + set_optional(prestige, entry.get_prestige()); + for (Reform const* reform : entry.get_reforms()) { ret &= add_reform(reform); } - set_optional(tech_school, entry->get_tech_school()); + set_optional(tech_school, entry.get_tech_school()); constexpr auto set_bool_map_to_indexed_map = [](IndexedMap& target, ordered_map source) { for (auto const& [key, value] : source) { target[*key] = value; } }; - set_bool_map_to_indexed_map(technologies, entry->get_technologies()); - set_bool_map_to_indexed_map(inventions, entry->get_inventions()); - // entry->get_foreign_investment(); + set_bool_map_to_indexed_map(technologies, entry.get_technologies()); + set_bool_map_to_indexed_map(inventions, entry.get_inventions()); + apply_foreign_investments(entry.get_foreign_investment(), country_instance_manager); // These need to be applied to pops - // entry->get_consciousness(); - // entry->get_nonstate_consciousness(); - // entry->get_literacy(); - // entry->get_nonstate_culture_literacy(); - - set_optional(releasable_vassal, entry->is_releasable_vassal()); - // entry->get_colonial_points(); - for (std::string const& flag : entry->get_country_flags()) { + // entry.get_consciousness(); + // entry.get_nonstate_consciousness(); + // entry.get_literacy(); + // entry.get_nonstate_culture_literacy(); + + set_optional(releasable_vassal, entry.is_releasable_vassal()); + // entry.get_colonial_points(); + for (std::string const& flag : entry.get_country_flags()) { ret &= set_country_flag(flag, true); } - for (std::string const& flag : entry->get_global_flags()) { + for (std::string const& flag : entry.get_global_flags()) { // TODO - set global flag } - government_flag_overrides.write_non_empty_values(entry->get_government_flag_overrides()); - for (Decision const* decision : entry->get_decisions()) { + government_flag_overrides.write_non_empty_values(entry.get_government_flag_overrides()); + for (Decision const* decision : entry.get_decisions()) { // TODO - take decision } return ret; } -void CountryInstance::_update_production() { +void CountryInstance::_update_production(DefineManager const& define_manager) { + // Calculate industrial power from states and foreign investments + industrial_power = 0; + industrial_power_from_states.clear(); + industrial_power_from_investments.clear(); + + for (State const* state : states) { + const fixed_point_t state_industrial_power = state->get_industrial_power(); + if (state_industrial_power != 0) { + industrial_power += state_industrial_power; + industrial_power_from_states.emplace_back(state, state_industrial_power); + } + } + + for (auto const& [country, money_invested] : foreign_investments) { + if (country->exists()) { + const fixed_point_t investment_industrial_power = + money_invested * define_manager.get_country_investment_industrial_score_factor() / 100; + if (investment_industrial_power != 0) { + industrial_power += investment_industrial_power; + industrial_power_from_investments.emplace_back(country, investment_industrial_power); + } + } + } + + std::sort( + industrial_power_from_states.begin(), industrial_power_from_states.end(), + [](auto const& a, auto const& b) -> bool { return a.second > b.second; } + ); + std::sort( + industrial_power_from_investments.begin(), industrial_power_from_investments.end(), + [](auto const& a, auto const& b) -> bool { return a.second > b.second; } + ); } void CountryInstance::_update_budget() { @@ -409,9 +449,9 @@ void CountryInstance::_update_military() { // TODO - update mobilisation_regiment_potential, max_ship_supply, leadership_points, war_exhaustion } -void CountryInstance::update_gamestate() { +void CountryInstance::update_gamestate(DefineManager const& define_manager) { // Order of updates might need to be changed/functions split up to account for dependencies - _update_production(); + _update_production(define_manager); _update_budget(); _update_technology(); _update_politics(); @@ -608,11 +648,16 @@ bool CountryInstanceManager::apply_history_to_countries( if (history_map != nullptr) { CountryHistoryEntry const* oob_history_entry = nullptr; - for (CountryHistoryEntry const* entry : history_map->get_entries_up_to(date)) { - ret &= country_instance.apply_history_to_country(entry, map_instance); + for (auto const& [entry_date, entry] : history_map->get_entries()) { + if (entry_date <= date) { + ret &= country_instance.apply_history_to_country(*entry, map_instance, *this); - if (entry->get_inital_oob()) { - oob_history_entry = entry; + if (entry->get_inital_oob()) { + oob_history_entry = entry.get(); + } + } else { + // All foreign investments are applied regardless of the bookmark's date + country_instance.apply_foreign_investments(entry->get_foreign_investment(), *this); } } @@ -633,7 +678,7 @@ bool CountryInstanceManager::apply_history_to_countries( void CountryInstanceManager::update_gamestate(Date today, DefineManager const& define_manager) { for (CountryInstance& country : country_instances.get_items()) { - country.update_gamestate(); + country.update_gamestate(define_manager); } update_rankings(today, define_manager); diff --git a/src/openvic-simulation/country/CountryInstance.hpp b/src/openvic-simulation/country/CountryInstance.hpp index 3622e29..0e8d493 100644 --- a/src/openvic-simulation/country/CountryInstance.hpp +++ b/src/openvic-simulation/country/CountryInstance.hpp @@ -75,7 +75,10 @@ namespace OpenVic { /* Production */ fixed_point_t PROPERTY(industrial_power); + std::vector> PROPERTY(industrial_power_from_states); + std::vector> PROPERTY(industrial_power_from_investments); size_t PROPERTY(industrial_rank); + fixed_point_map_t PROPERTY(foreign_investments); // TODO - total amount of each good produced /* Budget */ @@ -195,10 +198,18 @@ namespace OpenVic { template bool remove_leader(LeaderBranched const* leader); - bool apply_history_to_country(CountryHistoryEntry const* entry, MapInstance& map_instance); + // Sets the investment of each country in the map (rather than adding to them), leaving the rest unchanged. + void apply_foreign_investments( + fixed_point_map_t const& investments, + CountryInstanceManager const& country_instance_manager + ); + + bool apply_history_to_country( + CountryHistoryEntry const& entry, MapInstance& map_instance, CountryInstanceManager const& country_instance_manager + ); private: - void _update_production(); + void _update_production(DefineManager const& define_manager); void _update_budget(); void _update_technology(); void _update_politics(); @@ -209,7 +220,7 @@ namespace OpenVic { public: - void update_gamestate(); + void update_gamestate(DefineManager const& define_manager); void tick(); }; diff --git a/src/openvic-simulation/history/CountryHistory.cpp b/src/openvic-simulation/history/CountryHistory.cpp index 145d26b..04f6292 100644 --- a/src/openvic-simulation/history/CountryHistory.cpp +++ b/src/openvic-simulation/history/CountryHistory.cpp @@ -191,6 +191,10 @@ void CountryHistoryManager::reserve_more_country_histories(size_t size) { } void CountryHistoryManager::lock_country_histories() { + for (auto [country, history_map] : mutable_iterator(country_histories)) { + history_map.sort_entries(); + } + Logger::info("Locked country history registry after registering ", country_histories.size(), " items"); locked = true; } diff --git a/src/openvic-simulation/history/HistoryMap.hpp b/src/openvic-simulation/history/HistoryMap.hpp index 1d6ec03..b062b0f 100644 --- a/src/openvic-simulation/history/HistoryMap.hpp +++ b/src/openvic-simulation/history/HistoryMap.hpp @@ -104,6 +104,20 @@ namespace OpenVic { } public: + void sort_entries() { + std::vector keys; + keys.reserve(entries.size()); + for (typename decltype(entries)::value_type const& entry : entries) { + keys.push_back(entry.first); + } + std::sort(keys.begin(), keys.end()); + ordered_map> new_entries; + for (Date const& key : keys) { + new_entries.emplace(key, std::move(entries[key])); + } + entries = std::move(new_entries); + } + /* Returns history entry at specific date, if date doesn't have an entry returns nullptr. */ entry_type const* get_entry(Date date) const { typename decltype(entries)::const_iterator it = entries.find(date); @@ -112,18 +126,5 @@ namespace OpenVic { } return nullptr; } - /* Returns history entries up to date as an ordered list of entries. */ - std::vector get_entries_up_to(Date end) const { - std::vector ret; - for (typename decltype(entries)::value_type const& entry : entries) { - if (entry.first <= end) { - ret.push_back(entry.second.get()); - } - } - std::sort(ret.begin(), ret.end(), [](entry_type const* lhs, entry_type const* rhs) -> bool { - return lhs->get_date() < rhs->get_date(); - }); - return ret; - } }; } diff --git a/src/openvic-simulation/history/ProvinceHistory.cpp b/src/openvic-simulation/history/ProvinceHistory.cpp index ca0bf4e..ef8793b 100644 --- a/src/openvic-simulation/history/ProvinceHistory.cpp +++ b/src/openvic-simulation/history/ProvinceHistory.cpp @@ -157,8 +157,10 @@ void ProvinceHistoryManager::lock_province_histories(MapDefinition const& map_de std::vector const& provinces = map_definition.get_province_definitions(); std::vector province_checklist(provinces.size()); - for (decltype(province_histories)::value_type const& entry : province_histories) { - province_checklist[entry.first->get_index() - 1] = true; + for (auto [province, history_map] : mutable_iterator(province_histories)) { + province_checklist[province->get_index() - 1] = true; + + history_map.sort_entries(); } size_t missing = 0; diff --git a/src/openvic-simulation/map/MapInstance.cpp b/src/openvic-simulation/map/MapInstance.cpp index 56b3642..ea174eb 100644 --- a/src/openvic-simulation/map/MapInstance.cpp +++ b/src/openvic-simulation/map/MapInstance.cpp @@ -94,11 +94,15 @@ bool MapInstance::apply_history_to_provinces( if (history_map != nullptr) { ProvinceHistoryEntry const* pop_history_entry = nullptr; - for (ProvinceHistoryEntry const* entry : history_map->get_entries_up_to(date)) { - province.apply_history_to_province(entry, country_manager); + for (auto const& [entry_date, entry] : history_map->get_entries()) { + if (entry_date > date) { + break; + } + + province.apply_history_to_province(*entry, country_manager); if (!entry->get_pops().empty()) { - pop_history_entry = entry; + pop_history_entry = entry.get(); } } diff --git a/src/openvic-simulation/map/ProvinceInstance.cpp b/src/openvic-simulation/map/ProvinceInstance.cpp index ee20590..f95ee21 100644 --- a/src/openvic-simulation/map/ProvinceInstance.cpp +++ b/src/openvic-simulation/map/ProvinceInstance.cpp @@ -236,12 +236,7 @@ bool ProvinceInstance::setup(BuildingTypeManager const& building_type_manager) { return ret; } -bool ProvinceInstance::apply_history_to_province(ProvinceHistoryEntry const* entry, CountryInstanceManager& country_manager) { - if (entry == nullptr) { - Logger::error("Trying to apply null province history to ", get_identifier()); - return false; - } - +bool ProvinceInstance::apply_history_to_province(ProvinceHistoryEntry const& entry, CountryInstanceManager& country_manager) { bool ret = true; constexpr auto set_optional = [](T& target, std::optional const& source) { @@ -250,25 +245,25 @@ bool ProvinceInstance::apply_history_to_province(ProvinceHistoryEntry const* ent } }; - if (entry->get_owner()) { - ret &= set_owner(&country_manager.get_country_instance_from_definition(**entry->get_owner())); + if (entry.get_owner()) { + ret &= set_owner(&country_manager.get_country_instance_from_definition(**entry.get_owner())); } - if (entry->get_controller()) { - ret &= set_controller(&country_manager.get_country_instance_from_definition(**entry->get_controller())); + if (entry.get_controller()) { + ret &= set_controller(&country_manager.get_country_instance_from_definition(**entry.get_controller())); } - set_optional(colony_status, entry->get_colonial()); - set_optional(slave, entry->get_slave()); - for (auto const& [country, add] : entry->get_cores()) { + set_optional(colony_status, entry.get_colonial()); + set_optional(slave, entry.get_slave()); + for (auto const& [country, add] : entry.get_cores()) { if (add) { ret &= add_core(country_manager.get_country_instance_from_definition(*country)); } else { ret &= remove_core(country_manager.get_country_instance_from_definition(*country)); } } - set_optional(rgo, entry->get_rgo()); - set_optional(life_rating, entry->get_life_rating()); - set_optional(terrain_type, entry->get_terrain_type()); - for (auto const& [building, level] : entry->get_province_buildings()) { + set_optional(rgo, entry.get_rgo()); + set_optional(life_rating, entry.get_life_rating()); + set_optional(terrain_type, entry.get_terrain_type()); + 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); @@ -280,8 +275,8 @@ bool ProvinceInstance::apply_history_to_province(ProvinceHistoryEntry const* ent ret = false; } } - // TODO: load state buildings - entry->get_state_buildings() - // TODO: party loyalties for each POP when implemented on POP side - entry->get_party_loyalties() + // TODO: load state buildings - entry.get_state_buildings() + // TODO: party loyalties for each POP when implemented on POP side - entry.get_party_loyalties() return ret; } diff --git a/src/openvic-simulation/map/ProvinceInstance.hpp b/src/openvic-simulation/map/ProvinceInstance.hpp index 048ac3b..7ba35cd 100644 --- a/src/openvic-simulation/map/ProvinceInstance.hpp +++ b/src/openvic-simulation/map/ProvinceInstance.hpp @@ -131,7 +131,7 @@ namespace OpenVic { bool remove_unit_instance_group(UnitInstanceGroup& group); bool setup(BuildingTypeManager const& building_type_manager); - bool apply_history_to_province(ProvinceHistoryEntry const* entry, CountryInstanceManager& country_manager); + bool apply_history_to_province(ProvinceHistoryEntry const& entry, CountryInstanceManager& country_manager); void setup_pop_test_values(IssueManager const& issue_manager); }; diff --git a/src/openvic-simulation/map/State.cpp b/src/openvic-simulation/map/State.cpp index 68f2f43..90cbace 100644 --- a/src/openvic-simulation/map/State.cpp +++ b/src/openvic-simulation/map/State.cpp @@ -10,11 +10,19 @@ using namespace OpenVic; State::State( - StateSet const& new_state_set, CountryInstance* owner, ProvinceInstance* capital, - std::vector&& provinces, ProvinceInstance::colony_status_t colony_status, + StateSet const& new_state_set, + CountryInstance* new_owner, + ProvinceInstance* new_capital, + std::vector&& new_provinces, + ProvinceInstance::colony_status_t new_colony_status, decltype(pop_type_distribution)::keys_t const& pop_type_keys -) : state_set { new_state_set }, owner { owner }, capital { capital }, provinces { std::move(provinces) }, - colony_status { colony_status }, pop_type_distribution { &pop_type_keys } {} +) : state_set { new_state_set }, + owner { new_owner }, + capital { new_capital }, + provinces { std::move(new_provinces) }, + colony_status { new_colony_status }, + pop_type_distribution { &pop_type_keys }, + industrial_power { 0 } {} std::string State::get_identifier() const { return StringUtils::append_string_views( @@ -47,6 +55,16 @@ void State::update_gamestate() { average_consciousness /= total_population; average_militancy /= total_population; } + + // TODO - use actual values when State has factory data + const int32_t total_factory_levels_in_state = 0; + const int32_t potential_workforce_in_state = 0; // sum of worker pops, regardless of employment + const int32_t potential_employment_in_state = 0; // sum of (factory level * production method base_workforce_size) + + industrial_power = total_factory_levels_in_state * std::clamp( + (fixed_point_t { potential_workforce_in_state } / 100).floor() * 400 / potential_employment_in_state, + fixed_point_t::_0_20(), fixed_point_t::_4() + ); } /* Whether two provinces in the same region should be grouped into the same state or not. diff --git a/src/openvic-simulation/map/State.hpp b/src/openvic-simulation/map/State.hpp index 44b1947..6035e10 100644 --- a/src/openvic-simulation/map/State.hpp +++ b/src/openvic-simulation/map/State.hpp @@ -31,9 +31,14 @@ namespace OpenVic { fixed_point_t PROPERTY(average_militancy); IndexedMap PROPERTY(pop_type_distribution); + fixed_point_t PROPERTY(industrial_power); + State( - StateSet const& new_state_set, CountryInstance* owner, ProvinceInstance* capital, - std::vector&& provinces, ProvinceInstance::colony_status_t colony_status, + StateSet const& new_state_set, + CountryInstance* new_owner, + ProvinceInstance* new_capital, + std::vector&& new_provinces, + ProvinceInstance::colony_status_t new_colony_status, decltype(pop_type_distribution)::keys_t const& pop_type_keys ); diff --git a/src/openvic-simulation/misc/Define.cpp b/src/openvic-simulation/misc/Define.cpp index 2437954..015ebaa 100644 --- a/src/openvic-simulation/misc/Define.cpp +++ b/src/openvic-simulation/misc/Define.cpp @@ -155,7 +155,8 @@ DefineManager::DefineManager() // Country great_power_rank { 8 }, lose_great_power_grace_days { Timespan::from_years(1) }, - secondary_power_rank { 16 } + secondary_power_rank { 16 }, + country_investment_industrial_score_factor { 1 } // Economy @@ -237,6 +238,7 @@ bool DefineManager::load_defines_file(ast::NodeCPtr root) { ret &= load_define(great_power_rank, Country, "GREAT_NATIONS_COUNT"); ret &= load_define_days(lose_great_power_grace_days, Country, "GREATNESS_DAYS"); ret &= load_define(secondary_power_rank, Country, "COLONIAL_RANK"); + ret &= load_define(country_investment_industrial_score_factor, Country, "INVESTMENT_SCORE_FACTOR"); // Economy diff --git a/src/openvic-simulation/misc/Define.hpp b/src/openvic-simulation/misc/Define.hpp index 4e63105..a64636b 100644 --- a/src/openvic-simulation/misc/Define.hpp +++ b/src/openvic-simulation/misc/Define.hpp @@ -44,6 +44,7 @@ namespace OpenVic { size_t PROPERTY(great_power_rank); // GREAT_NATIONS_COUNT Timespan PROPERTY(lose_great_power_grace_days); // GREATNESS_DAYS size_t PROPERTY(secondary_power_rank); // COLONIAL_RANK + fixed_point_t PROPERTY(country_investment_industrial_score_factor); // INVESTMENT_SCORE_FACTOR // Economy -- cgit v1.2.3-56-ga3b1