diff options
author | hop311 <hop3114@gmail.com> | 2024-09-06 23:58:20 +0200 |
---|---|---|
committer | hop311 <hop3114@gmail.com> | 2024-09-08 18:24:57 +0200 |
commit | b5407c8794c4626d010bd0856a146095daa1042d (patch) | |
tree | 19baa8e48c1cf6d2d3b0c152b47f16daa9745a21 /src/openvic-simulation/country/CountryInstance.cpp | |
parent | dd65fa7dd431264caa08d083cb3a94922a4084d5 (diff) |
Add country ranking system + great/secondary powers
Diffstat (limited to 'src/openvic-simulation/country/CountryInstance.cpp')
-rw-r--r-- | src/openvic-simulation/country/CountryInstance.cpp | 186 |
1 files changed, 167 insertions, 19 deletions
diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp index 3c2e7bb..2c7ff70 100644 --- a/src/openvic-simulation/country/CountryInstance.cpp +++ b/src/openvic-simulation/country/CountryInstance.cpp @@ -3,12 +3,15 @@ #include "openvic-simulation/country/CountryDefinition.hpp" #include "openvic-simulation/history/CountryHistory.hpp" #include "openvic-simulation/map/MapInstance.hpp" +#include "openvic-simulation/misc/Define.hpp" #include "openvic-simulation/politics/Ideology.hpp" #include "openvic-simulation/research/Invention.hpp" #include "openvic-simulation/research/Technology.hpp" using namespace OpenVic; +using enum CountryInstance::country_status_t; + static constexpr colour_t ERROR_COLOUR = colour_t::from_integer(0xFF0000); CountryInstance::CountryInstance( @@ -23,14 +26,19 @@ CountryInstance::CountryInstance( colour { ERROR_COLOUR }, capital { nullptr }, country_flags {}, - civilised { false }, releasable_vassal { true }, + country_status { COUNTRY_STATUS_UNCIVILISED }, + lose_great_power_date {}, + total_score { 0 }, + total_rank { 0 }, owned_provinces {}, controlled_provinces {}, core_provinces {}, states {}, /* Production */ + industrial_power { 0 }, + industrial_rank { 0 }, /* Budget */ cash_stockpile { 0 }, @@ -73,16 +81,13 @@ CountryInstance::CountryInstance( /* Trade */ /* Diplomacy */ - total_rank { 0 }, prestige { 0 }, prestige_rank { 0 }, - industrial_power { 0 }, - industrial_rank { 0 }, - military_power { 0 }, - military_rank { 0 }, diplomatic_points { 0 }, /* Military */ + military_power { 0 }, + military_rank { 0 }, generals {}, admirals {}, armies {}, @@ -99,6 +104,26 @@ std::string_view CountryInstance::get_identifier() const { return country_definition->get_identifier(); } +bool CountryInstance::exists() const { + return !owned_provinces.empty(); +} + +bool CountryInstance::is_civilised() const { + return country_status <= COUNTRY_STATUS_CIVILISED; +} + +bool CountryInstance::can_colonise() const { + return country_status <= COUNTRY_STATUS_SECONDARY_POWER; +} + +bool CountryInstance::is_great_power() const { + return country_status == COUNTRY_STATUS_GREAT_POWER; +} + +bool CountryInstance::is_secondary_power() const { + return country_status == COUNTRY_STATUS_SECONDARY_POWER; +} + bool CountryInstance::set_country_flag(std::string_view flag, bool warn) { if (flag.empty()) { Logger::error("Attempted to set empty country flag for country ", get_identifier()); @@ -273,7 +298,9 @@ bool CountryInstance::apply_history_to_country(CountryHistoryEntry const* entry, set_optional(government_type, entry->get_government_type()); set_optional(plurality, entry->get_plurality()); set_optional(national_value, entry->get_national_value()); - set_optional(civilised, entry->is_civilised()); + 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); @@ -360,7 +387,7 @@ void CountryInstance::_update_trade() { } void CountryInstance::_update_diplomacy() { - // TODO - update prestige, industrial_power, military_power (ranks will be updated after all countries have calculated their scores) + // TODO - add prestige from modifiers // TODO - update diplomatic points and colonial power } @@ -383,6 +410,18 @@ void CountryInstance::_update_military() { } void CountryInstance::update_gamestate() { + // Order of updates might need to be changed/functions split up to account for dependencies + _update_production(); + _update_budget(); + _update_technology(); + _update_politics(); + _update_population(); + _update_trade(); + _update_diplomacy(); + _update_military(); + + total_score = prestige + industrial_power + military_power; + if (country_definition != nullptr) { const CountryDefinition::government_colour_map_t::const_iterator it = country_definition->get_alternative_colours().find(government_type); @@ -405,22 +444,129 @@ void CountryInstance::update_gamestate() { } else { flag_government_type = nullptr; } - - // Order of updates might need to be changed/functions split up to account for dependencies - _update_production(); - _update_budget(); - _update_technology(); - _update_politics(); - _update_population(); - _update_trade(); - _update_diplomacy(); - _update_military(); } void CountryInstance::tick() { } +void CountryInstanceManager::update_rankings(Date today, DefineManager const& define_manager) { + total_ranking.clear(); + + for (CountryInstance& country : country_instances.get_items()) { + if (country.exists()) { + total_ranking.push_back(&country); + } + } + + prestige_ranking = total_ranking; + industrial_power_ranking = total_ranking; + military_power_ranking = total_ranking; + + std::sort( + total_ranking.begin(), total_ranking.end(), + [](CountryInstance const* a, CountryInstance const* b) -> bool { + const bool a_civilised = a->is_civilised(); + const bool b_civilised = b->is_civilised(); + return a_civilised != b_civilised ? a_civilised : a->get_total_score() > b->get_total_score(); + } + ); + std::sort( + prestige_ranking.begin(), prestige_ranking.end(), + [](CountryInstance const* a, CountryInstance const* b) -> bool { + return a->get_prestige() > b->get_prestige(); + } + ); + std::sort( + industrial_power_ranking.begin(), industrial_power_ranking.end(), + [](CountryInstance const* a, CountryInstance const* b) -> bool { + return a->get_industrial_power() > b->get_industrial_power(); + } + ); + std::sort( + military_power_ranking.begin(), military_power_ranking.end(), + [](CountryInstance const* a, CountryInstance const* b) -> bool { + return a->get_military_power() > b->get_military_power(); + } + ); + + for (size_t index = 0; index < total_ranking.size(); ++index) { + const size_t rank = index + 1; + total_ranking[index]->total_rank = rank; + prestige_ranking[index]->prestige_rank = rank; + industrial_power_ranking[index]->industrial_rank = rank; + military_power_ranking[index]->military_rank = rank; + } + + const size_t max_great_power_rank = define_manager.get_great_power_rank(); + const size_t max_secondary_power_rank = define_manager.get_secondary_power_rank(); + const Timespan lose_great_power_grace_days = define_manager.get_lose_great_power_grace_days(); + + // Demote great powers who have been below the max great power rank for longer than the demotion grace period and + // remove them from the list. We don't just demote them all and clear the list as when rebuilding we'd need to look + // ahead for countries below the max great power rank but still within the demotion grace period. + for (CountryInstance* great_power : great_powers) { + if (great_power->get_total_rank() > max_great_power_rank && great_power->get_lose_great_power_date() < today) { + great_power->country_status = COUNTRY_STATUS_CIVILISED; + } + } + std::erase_if(great_powers, [](CountryInstance const* country) -> bool { + return country->get_country_status() != COUNTRY_STATUS_GREAT_POWER; + }); + + // Demote all secondary powers and clear the list. We will rebuilt the whole list from scratch, so there's no need to + // keep countries which are still above the max secondary power rank (they might become great powers instead anyway). + for (CountryInstance* secondary_power : secondary_powers) { + secondary_power->country_status = COUNTRY_STATUS_CIVILISED; + } + secondary_powers.clear(); + + // Calculate the maximum number of countries eligible for great or secondary power status. This accounts for the + // possibility of the max secondary power rank being higher than the max great power rank or both being zero, just + // in case someone wants to experiment with only having secondary powers when some great power slots are filled by + // countries in the demotion grace period, or having no great or secondary powers at all. + const size_t max_power_index = std::clamp(max_secondary_power_rank, max_great_power_rank, total_ranking.size()); + + for (size_t index = 0; index < max_power_index; index++) { + CountryInstance* country = total_ranking[index]; + + if (!country->is_civilised()) { + // All further countries are civilised and so ineligible for great or secondary power status. + break; + } + + if (country->is_great_power()) { + // The country already has great power status and is in the great powers list. + continue; + } + + if (great_powers.size() < max_great_power_rank && country->get_total_rank() <= max_great_power_rank) { + // The country is eligible for great power status and there are still slots available, + // so it is promoted and added to the list. + country->country_status = COUNTRY_STATUS_GREAT_POWER; + great_powers.push_back(country); + } else if (country->get_total_rank() <= max_secondary_power_rank) { + // The country is eligible for secondary power status and so is promoted and added to the list. + country->country_status = COUNTRY_STATUS_SECONDARY_POWER; + secondary_powers.push_back(country); + } + } + + // Sort the great powers list by total rank, as pre-existing great powers may have changed rank order and new great + // powers will have beeen added to the end of the list regardless of rank. + std::sort(great_powers.begin(), great_powers.end(), [](CountryInstance const* a, CountryInstance const* b) -> bool { + return a->get_total_rank() < b->get_total_rank(); + }); + + // Update the lose great power date for all great powers which are above the max great power rank. + const Date new_lose_great_power_date = today + lose_great_power_grace_days; + for (CountryInstance* great_power : great_powers) { + if (great_power->get_total_rank() <= max_great_power_rank) { + great_power->lose_great_power_date = new_lose_great_power_date; + } + } +} + CountryInstance& CountryInstanceManager::get_country_instance_from_definition(CountryDefinition const& country) { return country_instances.get_items()[country.get_index()]; } @@ -485,10 +631,12 @@ bool CountryInstanceManager::apply_history_to_countries( return ret; } -void CountryInstanceManager::update_gamestate() { +void CountryInstanceManager::update_gamestate(Date today, DefineManager const& define_manager) { for (CountryInstance& country : country_instances.get_items()) { country.update_gamestate(); } + + update_rankings(today, define_manager); } void CountryInstanceManager::tick() { |