From d67cd2d08fe2859809e35b93f5a8358c48a3705e Mon Sep 17 00:00:00 2001 From: hop311 Date: Fri, 6 Sep 2024 23:13:47 +0100 Subject: Calculate country military power (still needs modifiers + soldier pop supported regiment count) --- src/openvic-simulation/InstanceManager.cpp | 10 +- src/openvic-simulation/country/CountryInstance.cpp | 163 +++++++++++++++++++-- src/openvic-simulation/country/CountryInstance.hpp | 37 ++++- src/openvic-simulation/map/MapInstance.cpp | 4 +- src/openvic-simulation/map/MapInstance.hpp | 2 +- src/openvic-simulation/map/ProvinceInstance.cpp | 29 +++- src/openvic-simulation/map/ProvinceInstance.hpp | 6 +- src/openvic-simulation/map/State.cpp | 6 +- src/openvic-simulation/map/State.hpp | 2 + src/openvic-simulation/military/UnitInstance.cpp | 4 +- src/openvic-simulation/military/UnitInstance.hpp | 5 +- .../military/UnitInstanceGroup.cpp | 7 +- src/openvic-simulation/military/UnitType.cpp | 24 +++ src/openvic-simulation/military/UnitType.hpp | 15 +- src/openvic-simulation/misc/Define.cpp | 16 +- src/openvic-simulation/misc/Define.hpp | 8 + src/openvic-simulation/pop/Pop.cpp | 21 ++- src/openvic-simulation/pop/Pop.hpp | 9 ++ 18 files changed, 328 insertions(+), 40 deletions(-) diff --git a/src/openvic-simulation/InstanceManager.cpp b/src/openvic-simulation/InstanceManager.cpp index 6f5ee4a..bcae82b 100644 --- a/src/openvic-simulation/InstanceManager.cpp +++ b/src/openvic-simulation/InstanceManager.cpp @@ -40,8 +40,10 @@ void InstanceManager::update_gamestate() { Logger::info("Update: ", today); // Update gamestate... - map_instance.update_gamestate(today); - country_instance_manager.update_gamestate(today, definition_manager.get_define_manager()); + map_instance.update_gamestate(today, definition_manager.get_define_manager()); + country_instance_manager.update_gamestate( + today, definition_manager.get_define_manager(), definition_manager.get_military_manager().get_unit_type_manager() + ); gamestate_updated(); gamestate_needs_update = false; @@ -81,7 +83,9 @@ bool InstanceManager::setup() { definition_manager.get_research_manager().get_invention_manager().get_inventions(), definition_manager.get_politics_manager().get_ideology_manager().get_ideologies(), definition_manager.get_politics_manager().get_government_type_manager().get_government_types(), - definition_manager.get_pop_manager().get_pop_types() + definition_manager.get_pop_manager().get_pop_types(), + definition_manager.get_military_manager().get_unit_type_manager().get_regiment_types(), + definition_manager.get_military_manager().get_unit_type_manager().get_ship_types() ); game_instance_setup = true; diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp index 5ba8782..4fab010 100644 --- a/src/openvic-simulation/country/CountryInstance.cpp +++ b/src/openvic-simulation/country/CountryInstance.cpp @@ -20,7 +20,9 @@ CountryInstance::CountryInstance( decltype(inventions)::keys_t const& invention_keys, decltype(upper_house)::keys_t const& ideology_keys, decltype(government_flag_overrides)::keys_t const& government_type_keys, - decltype(pop_type_distribution)::keys_t const& pop_type_keys + decltype(pop_type_distribution)::keys_t const& pop_type_keys, + decltype(unlocked_regiment_types)::keys_t const& unlocked_regiment_types_keys, + decltype(unlocked_ship_types)::keys_t const& unlocked_ship_types_keys ) : /* Main attributes */ country_definition { new_country_definition }, colour { ERROR_COLOUR }, @@ -90,18 +92,43 @@ CountryInstance::CountryInstance( /* Military */ military_power { 0 }, + military_power_from_land { 0 }, + military_power_from_sea { 0 }, + military_power_from_leaders { 0 }, military_rank { 0 }, generals {}, admirals {}, armies {}, navies {}, regiment_count { 0 }, - mobilisation_regiment_potential { 0 }, + max_supported_regiment_count { 0 }, + mobilisation_potential_regiment_count { 0 }, + mobilisation_max_regiment_count { 0 }, + mobilisation_impact { 0 }, + supply_consumption { 1 }, ship_count { 0 }, total_consumed_ship_supply { 0 }, max_ship_supply { 0 }, leadership_points { 0 }, - war_exhaustion { 0 } {} + war_exhaustion { 0 }, + mobilised { false }, + disarmed { false }, + unlocked_regiment_types { &unlocked_regiment_types_keys }, + allowed_regiment_cultures { RegimentType::allowed_cultures_t::NO_CULTURES }, + unlocked_ship_types { &unlocked_ship_types_keys } { + + for (RegimentType const& regiment_type : *unlocked_regiment_types.get_keys()) { + if (regiment_type.is_active()) { + unlock_unit_type(regiment_type); + } + } + + for (ShipType const& ship_type : *unlocked_ship_types.get_keys()) { + if (ship_type.is_active()) { + unlock_unit_type(ship_type); + } + } +} std::string_view CountryInstance::get_identifier() const { return country_definition->get_identifier(); @@ -273,6 +300,44 @@ template void CountryInstance::add_leader(LeaderBranched const*); template bool CountryInstance::remove_leader(LeaderBranched const*); +template +void CountryInstance::unlock_unit_type(UnitTypeBranched const& unit_type) { + IndexedMap, bool>& unlocked_unit_types = get_unlocked_unit_types(); + + decltype(unlocked_regiment_types)::value_ref_t unlock_value = unlocked_unit_types[unit_type]; + + if (unlock_value) { + Logger::warning( + "Attempted to unlock already-unlocked unit type \"", unit_type.get_identifier(), + "\" for country ", get_identifier() + ); + return; + } + + unlock_value = true; + + if constexpr (Branch == UnitType::branch_t::LAND) { + allowed_regiment_cultures = RegimentType::allowed_cultures_get_most_permissive( + allowed_regiment_cultures, unit_type.get_allowed_cultures() + ); + } +} + +template void CountryInstance::unlock_unit_type(UnitTypeBranched const&); +template void CountryInstance::unlock_unit_type(UnitTypeBranched const&); + +bool CountryInstance::is_primary_culture(Culture const& culture) const { + return &culture == primary_culture; +} + +bool CountryInstance::is_accepted_culture(Culture const& culture) const { + return accepted_cultures.contains(&culture); +} + +bool CountryInstance::is_primary_or_accepted_culture(Culture const& culture) const { + return is_primary_culture(culture) || is_accepted_culture(culture); +} + void CountryInstance::apply_foreign_investments( fixed_point_map_t const& investments, CountryInstanceManager const& country_instance_manager ) { @@ -401,7 +466,7 @@ void CountryInstance::_update_population() { national_militancy = 0; pop_type_distribution.clear(); - for (auto const& state : states) { + for (State const* state : states) { total_population += state->get_total_population(); // TODO - change casting if Pop::pop_size_t changes type @@ -431,7 +496,7 @@ void CountryInstance::_update_diplomacy() { // TODO - update diplomatic points and colonial power } -void CountryInstance::_update_military() { +void CountryInstance::_update_military(DefineManager const& define_manager, UnitTypeManager const& unit_type_manager) { regiment_count = 0; for (ArmyInstance const* army : armies) { @@ -446,10 +511,79 @@ void CountryInstance::_update_military() { total_consumed_ship_supply += navy->get_total_consumed_supply(); } - // TODO - update mobilisation_regiment_potential, max_ship_supply, leadership_points, war_exhaustion + // Calculate military power from land, sea, and leaders + + size_t deployed_non_mobilised_regiments = 0; + for (ArmyInstance const* army : armies) { + for (RegimentInstance const* regiment : army->get_units()) { + if (!regiment->is_mobilised()) { + deployed_non_mobilised_regiments++; + } + } + } + + max_supported_regiment_count = 0; + for (State const* state : states) { + max_supported_regiment_count += state->get_max_supported_regiments(); + } + + // TODO - apply country/tech modifiers to supply consumption + supply_consumption = 1; + + const size_t regular_army_size = std::min(4 * deployed_non_mobilised_regiments, max_supported_regiment_count); + + fixed_point_t sum_of_regiment_type_stats = 0; + for (RegimentType const& regiment_type : unit_type_manager.get_regiment_types()) { + // TODO - apply country/tech modifiers to regiment stats + sum_of_regiment_type_stats += ( + regiment_type.get_attack() + regiment_type.get_defence() /*+ land_attack_modifier + land_defense_modifier*/ + ) * regiment_type.get_discipline(); + } + + military_power_from_land = supply_consumption * fixed_point_t::parse(regular_army_size) * sum_of_regiment_type_stats + / fixed_point_t::parse(7 * (1 + unit_type_manager.get_regiment_type_count())); + + if (disarmed) { + military_power_from_land *= define_manager.get_disarmed_penalty(); + } + + military_power_from_sea = 0; + for (NavyInstance const* navy : navies) { + for (ShipInstance const* ship : navy->get_units()) { + ShipType const& ship_type = ship->get_unit_type(); + + if (ship_type.is_capital()) { + + // TODO - include gun power and hull modifiers + naval attack and defense modifiers + + military_power_from_sea += (ship_type.get_gun_power() /*+ naval_attack_modifier*/) + * (ship_type.get_hull() /* + naval_defense_modifier*/); + } + } + } + military_power_from_sea /= 250; + + military_power_from_leaders = fixed_point_t::parse( + std::min(generals.size() + admirals.size(), deployed_non_mobilised_regiments) + ); + + military_power = military_power_from_land + military_power_from_sea + military_power_from_leaders; + + // Mobilisation calculations + mobilisation_impact = 0; // TODO - apply ruling party's war policy + + mobilisation_max_regiment_count = + ((fixed_point_t::_1() + mobilisation_impact) * fixed_point_t::parse(regiment_count)).to_int64_t(); + + mobilisation_potential_regiment_count = 0; // TODO - calculate max regiments from poor citizens + if (mobilisation_potential_regiment_count > mobilisation_max_regiment_count) { + mobilisation_potential_regiment_count = mobilisation_max_regiment_count; + } + + // TODO - update max_ship_supply, leadership_points, war_exhaustion } -void CountryInstance::update_gamestate(DefineManager const& define_manager) { +void CountryInstance::update_gamestate(DefineManager const& define_manager, UnitTypeManager const& unit_type_manager) { // Order of updates might need to be changed/functions split up to account for dependencies _update_production(define_manager); _update_budget(); @@ -458,7 +592,7 @@ void CountryInstance::update_gamestate(DefineManager const& define_manager) { _update_population(); _update_trade(); _update_diplomacy(); - _update_military(); + _update_military(define_manager, unit_type_manager); total_score = prestige + industrial_power + military_power; @@ -621,13 +755,16 @@ bool CountryInstanceManager::generate_country_instances( decltype(CountryInstance::inventions)::keys_t const& invention_keys, decltype(CountryInstance::upper_house)::keys_t const& ideology_keys, decltype(CountryInstance::government_flag_overrides)::keys_t const& government_type_keys, - decltype(CountryInstance::pop_type_distribution)::keys_t const& pop_type_keys + decltype(CountryInstance::pop_type_distribution)::keys_t const& pop_type_keys, + decltype(CountryInstance::unlocked_regiment_types)::keys_t const& unlocked_regiment_types_keys, + decltype(CountryInstance::unlocked_ship_types)::keys_t const& unlocked_ship_types_keys ) { reserve_more(country_instances, country_definition_manager.get_country_definition_count()); for (CountryDefinition const& country_definition : country_definition_manager.get_country_definitions()) { country_instances.add_item({ - &country_definition, technology_keys, invention_keys, ideology_keys, government_type_keys, pop_type_keys + &country_definition, technology_keys, invention_keys, ideology_keys, government_type_keys, pop_type_keys, + unlocked_regiment_types_keys, unlocked_ship_types_keys }); } @@ -676,9 +813,11 @@ bool CountryInstanceManager::apply_history_to_countries( return ret; } -void CountryInstanceManager::update_gamestate(Date today, DefineManager const& define_manager) { +void CountryInstanceManager::update_gamestate( + Date today, DefineManager const& define_manager, UnitTypeManager const& unit_type_manager +) { for (CountryInstance& country : country_instances.get_items()) { - country.update_gamestate(define_manager); + country.update_gamestate(define_manager, unit_type_manager); } update_rankings(today, define_manager); diff --git a/src/openvic-simulation/country/CountryInstance.hpp b/src/openvic-simulation/country/CountryInstance.hpp index 0e8d493..c43f0cd 100644 --- a/src/openvic-simulation/country/CountryInstance.hpp +++ b/src/openvic-simulation/country/CountryInstance.hpp @@ -136,21 +136,34 @@ namespace OpenVic { /* Military */ fixed_point_t PROPERTY(military_power); + fixed_point_t PROPERTY(military_power_from_land); + fixed_point_t PROPERTY(military_power_from_sea); + fixed_point_t PROPERTY(military_power_from_leaders); size_t PROPERTY(military_rank); plf::colony PROPERTY(generals); plf::colony PROPERTY(admirals); ordered_set PROPERTY(armies); ordered_set PROPERTY(navies); size_t PROPERTY(regiment_count); - size_t PROPERTY(mobilisation_regiment_potential); + size_t PROPERTY(max_supported_regiment_count); + size_t PROPERTY(mobilisation_potential_regiment_count); + size_t PROPERTY(mobilisation_max_regiment_count); + fixed_point_t PROPERTY(mobilisation_impact); + fixed_point_t PROPERTY(supply_consumption); size_t PROPERTY(ship_count); fixed_point_t PROPERTY(total_consumed_ship_supply); fixed_point_t PROPERTY(max_ship_supply); fixed_point_t PROPERTY(leadership_points); fixed_point_t PROPERTY(war_exhaustion); + bool PROPERTY_CUSTOM_PREFIX(mobilised, is); + bool PROPERTY_CUSTOM_PREFIX(disarmed, is); + IndexedMap PROPERTY(unlocked_regiment_types); + RegimentType::allowed_cultures_t PROPERTY(allowed_regiment_cultures); + IndexedMap PROPERTY(unlocked_ship_types); UNIT_BRANCHED_GETTER(get_unit_instance_groups, armies, navies); UNIT_BRANCHED_GETTER(get_leaders, generals, admirals); + UNIT_BRANCHED_GETTER(get_unlocked_unit_types, unlocked_regiment_types, unlocked_ship_types); CountryInstance( CountryDefinition const* new_country_definition, @@ -158,7 +171,9 @@ namespace OpenVic { decltype(inventions)::keys_t const& invention_keys, decltype(upper_house)::keys_t const& ideology_keys, decltype(government_flag_overrides)::keys_t const& government_type_keys, - decltype(pop_type_distribution)::keys_t const& pop_type_keys + decltype(pop_type_distribution)::keys_t const& pop_type_keys, + decltype(unlocked_regiment_types)::keys_t const& unlocked_regiment_types_keys, + decltype(unlocked_ship_types)::keys_t const& unlocked_ship_types_keys ); public: @@ -198,6 +213,14 @@ namespace OpenVic { template bool remove_leader(LeaderBranched const* leader); + template + void unlock_unit_type(UnitTypeBranched const& unit_type); + + bool is_primary_culture(Culture const& culture) const; + // This only checks the accepted cultures list, ignoring the primary culture. + bool is_accepted_culture(Culture const& culture) const; + bool is_primary_or_accepted_culture(Culture const& culture) const; + // 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, @@ -216,11 +239,11 @@ namespace OpenVic { void _update_population(); void _update_trade(); void _update_diplomacy(); - void _update_military(); + void _update_military(DefineManager const& define_manager, UnitTypeManager const& unit_type_manager); public: - void update_gamestate(DefineManager const& define_manager); + void update_gamestate(DefineManager const& define_manager, UnitTypeManager const& unit_type_manager); void tick(); }; @@ -252,7 +275,9 @@ namespace OpenVic { decltype(CountryInstance::inventions)::keys_t const& invention_keys, decltype(CountryInstance::upper_house)::keys_t const& ideology_keys, decltype(CountryInstance::government_flag_overrides)::keys_t const& government_type_keys, - decltype(CountryInstance::pop_type_distribution)::keys_t const& pop_type_keys + decltype(CountryInstance::pop_type_distribution)::keys_t const& pop_type_keys, + decltype(CountryInstance::unlocked_regiment_types)::keys_t const& unlocked_regiment_types_keys, + decltype(CountryInstance::unlocked_ship_types)::keys_t const& unlocked_ship_types_keys ); bool apply_history_to_countries( @@ -260,7 +285,7 @@ namespace OpenVic { MapInstance& map_instance ); - void update_gamestate(Date today, DefineManager const& define_manager); + void update_gamestate(Date today, DefineManager const& define_manager, UnitTypeManager const& unit_type_manager); void tick(); }; } diff --git a/src/openvic-simulation/map/MapInstance.cpp b/src/openvic-simulation/map/MapInstance.cpp index ea174eb..0ce8cea 100644 --- a/src/openvic-simulation/map/MapInstance.cpp +++ b/src/openvic-simulation/map/MapInstance.cpp @@ -118,9 +118,9 @@ bool MapInstance::apply_history_to_provinces( return ret; } -void MapInstance::update_gamestate(Date today) { +void MapInstance::update_gamestate(Date today, DefineManager const& define_manager) { for (ProvinceInstance& province : province_instances.get_items()) { - province.update_gamestate(today); + province.update_gamestate(today, define_manager); } state_manager.update_gamestate(); diff --git a/src/openvic-simulation/map/MapInstance.hpp b/src/openvic-simulation/map/MapInstance.hpp index d2d9a26..99c13d3 100644 --- a/src/openvic-simulation/map/MapInstance.hpp +++ b/src/openvic-simulation/map/MapInstance.hpp @@ -52,7 +52,7 @@ namespace OpenVic { IssueManager const& issue_manager ); - void update_gamestate(Date today); + void update_gamestate(Date today, DefineManager const& define_manager); void tick(Date today); }; } diff --git a/src/openvic-simulation/map/ProvinceInstance.cpp b/src/openvic-simulation/map/ProvinceInstance.cpp index f95ee21..06b3f1e 100644 --- a/src/openvic-simulation/map/ProvinceInstance.cpp +++ b/src/openvic-simulation/map/ProvinceInstance.cpp @@ -4,6 +4,7 @@ #include "openvic-simulation/history/ProvinceHistory.hpp" #include "openvic-simulation/map/ProvinceDefinition.hpp" #include "openvic-simulation/military/UnitInstanceGroup.hpp" +#include "openvic-simulation/misc/Define.hpp" #include "openvic-simulation/politics/Ideology.hpp" using namespace OpenVic; @@ -31,7 +32,8 @@ ProvinceInstance::ProvinceInstance( pop_type_distribution { &pop_type_keys }, ideology_distribution { &ideology_keys }, culture_distribution {}, - religion_distribution {} {} + religion_distribution {}, + max_supported_regiments { 0 } {} bool ProvinceInstance::set_owner(CountryInstance* new_owner) { bool ret = true; @@ -92,6 +94,10 @@ bool ProvinceInstance::remove_core(CountryInstance& core_to_remove) { } } +bool ProvinceInstance::is_owner_core() const { + return owner != nullptr && cores.contains(owner); +} + bool ProvinceInstance::expand_building(size_t building_index) { BuildingInstance* building = buildings.get_item_by_index(building_index); if (building == nullptr) { @@ -136,7 +142,7 @@ size_t ProvinceInstance::get_pop_count() const { /* REQUIREMENTS: * MAP-65, MAP-68, MAP-70, MAP-234 */ -void ProvinceInstance::_update_pops() { +void ProvinceInstance::_update_pops(DefineManager const& define_manager) { total_population = 0; average_literacy = 0; average_consciousness = 0; @@ -147,7 +153,18 @@ void ProvinceInstance::_update_pops() { culture_distribution.clear(); religion_distribution.clear(); - for (Pop const& pop : pops) { + max_supported_regiments = 0; + + using enum colony_status_t; + + const fixed_point_t pop_size_per_regiment_multiplier = + colony_status == PROTECTORATE ? define_manager.get_pop_size_per_regiment_protectorate_multiplier() + : colony_status == COLONY ? define_manager.get_pop_size_per_regiment_colony_multiplier() + : is_owner_core() ? fixed_point_t::_1() : define_manager.get_pop_size_per_regiment_non_core_multiplier(); + + for (Pop& pop : pops) { + pop.update_gamestate(define_manager, owner, pop_size_per_regiment_multiplier); + total_population += pop.get_size(); average_literacy += pop.get_literacy(); average_consciousness += pop.get_consciousness(); @@ -157,6 +174,8 @@ void ProvinceInstance::_update_pops() { ideology_distribution += pop.get_ideologies(); culture_distribution[&pop.get_culture()] += pop.get_size(); religion_distribution[&pop.get_religion()] += pop.get_size(); + + max_supported_regiments += pop.get_max_supported_regiments(); } if (total_population > 0) { @@ -166,11 +185,11 @@ void ProvinceInstance::_update_pops() { } } -void ProvinceInstance::update_gamestate(Date today) { +void ProvinceInstance::update_gamestate(Date today, DefineManager const& define_manager) { for (BuildingInstance& building : buildings.get_items()) { building.update_gamestate(today); } - _update_pops(); + _update_pops(define_manager); } void ProvinceInstance::tick(Date today) { diff --git a/src/openvic-simulation/map/ProvinceInstance.hpp b/src/openvic-simulation/map/ProvinceInstance.hpp index 7ba35cd..fa0be98 100644 --- a/src/openvic-simulation/map/ProvinceInstance.hpp +++ b/src/openvic-simulation/map/ProvinceInstance.hpp @@ -88,6 +88,7 @@ namespace OpenVic { IndexedMap PROPERTY(ideology_distribution); fixed_point_map_t PROPERTY(culture_distribution); fixed_point_map_t PROPERTY(religion_distribution); + size_t PROPERTY(max_supported_regiments); ProvinceInstance( ProvinceDefinition const& new_province_definition, decltype(pop_type_distribution)::keys_t const& pop_type_keys, @@ -95,7 +96,7 @@ namespace OpenVic { ); void _add_pop(Pop&& pop); - void _update_pops(); + void _update_pops(DefineManager const& define_manager); public: ProvinceInstance(ProvinceInstance&&) = default; @@ -115,6 +116,7 @@ namespace OpenVic { bool set_controller(CountryInstance* new_controller); bool add_core(CountryInstance& new_core); bool remove_core(CountryInstance& core_to_remove); + bool is_owner_core() const; bool expand_building(size_t building_index); @@ -122,7 +124,7 @@ namespace OpenVic { bool add_pop_vec(std::vector const& pop_vec); size_t get_pop_count() const; - void update_gamestate(Date today); + void update_gamestate(Date today, DefineManager const& define_manager); void tick(Date today); template diff --git a/src/openvic-simulation/map/State.cpp b/src/openvic-simulation/map/State.cpp index 90cbace..020b6f1 100644 --- a/src/openvic-simulation/map/State.cpp +++ b/src/openvic-simulation/map/State.cpp @@ -22,7 +22,8 @@ State::State( provinces { std::move(new_provinces) }, colony_status { new_colony_status }, pop_type_distribution { &pop_type_keys }, - industrial_power { 0 } {} + industrial_power { 0 }, + max_supported_regiments { 0 } {} std::string State::get_identifier() const { return StringUtils::append_string_views( @@ -37,6 +38,7 @@ void State::update_gamestate() { average_consciousness = 0; average_militancy = 0; pop_type_distribution.clear(); + max_supported_regiments = 0; for (ProvinceInstance const* province : provinces) { total_population += province->get_total_population(); @@ -48,6 +50,8 @@ void State::update_gamestate() { average_militancy += province->get_average_militancy() * province_population; pop_type_distribution += province->get_pop_type_distribution(); + + max_supported_regiments += province->get_max_supported_regiments(); } if (total_population > 0) { diff --git a/src/openvic-simulation/map/State.hpp b/src/openvic-simulation/map/State.hpp index 6035e10..596206a 100644 --- a/src/openvic-simulation/map/State.hpp +++ b/src/openvic-simulation/map/State.hpp @@ -33,6 +33,8 @@ namespace OpenVic { fixed_point_t PROPERTY(industrial_power); + size_t PROPERTY(max_supported_regiments); + State( StateSet const& new_state_set, CountryInstance* new_owner, diff --git a/src/openvic-simulation/military/UnitInstance.cpp b/src/openvic-simulation/military/UnitInstance.cpp index d9f12b9..7c6488d 100644 --- a/src/openvic-simulation/military/UnitInstance.cpp +++ b/src/openvic-simulation/military/UnitInstance.cpp @@ -19,8 +19,8 @@ template struct OpenVic::UnitInstance; template struct OpenVic::UnitInstance; UnitInstanceBranched::UnitInstanceBranched( - std::string_view new_name, RegimentType const& new_regiment_type, Pop* new_pop -) : UnitInstance { new_name, new_regiment_type }, pop { new_pop } {} + std::string_view new_name, RegimentType const& new_regiment_type, Pop* new_pop, bool new_mobilised +) : UnitInstance { new_name, new_regiment_type }, pop { new_pop }, mobilised { new_mobilised } {} UnitInstanceBranched::UnitInstanceBranched( std::string_view new_name, ShipType const& new_ship_type diff --git a/src/openvic-simulation/military/UnitInstance.hpp b/src/openvic-simulation/military/UnitInstance.hpp index 5ff4503..ffbd37f 100644 --- a/src/openvic-simulation/military/UnitInstance.hpp +++ b/src/openvic-simulation/military/UnitInstance.hpp @@ -41,8 +41,11 @@ namespace OpenVic { private: Pop* PROPERTY(pop); + bool PROPERTY_CUSTOM_PREFIX(mobilised, is); - UnitInstanceBranched(std::string_view new_name, RegimentType const& new_regiment_type, Pop* new_pop); + UnitInstanceBranched( + std::string_view new_name, RegimentType const& new_regiment_type, Pop* new_pop, bool new_mobilised) + ; public: UnitInstanceBranched(UnitInstanceBranched&&) = default; diff --git a/src/openvic-simulation/military/UnitInstanceGroup.cpp b/src/openvic-simulation/military/UnitInstanceGroup.cpp index 65ecf5b..09206e3 100644 --- a/src/openvic-simulation/military/UnitInstanceGroup.cpp +++ b/src/openvic-simulation/military/UnitInstanceGroup.cpp @@ -172,8 +172,11 @@ bool UnitInstanceManager::generate_unit_instance( unit_instance = &*get_unit_instances().insert( [&unit_deployment]() -> UnitInstanceBranched { if constexpr (Branch == UnitType::branch_t::LAND) { - // TODO - get pop from Province unit_deployment.get_home() - return { unit_deployment.get_name(), unit_deployment.get_type(), nullptr }; + return { + unit_deployment.get_name(), unit_deployment.get_type(), + nullptr, // TODO - get pop from Province unit_deployment.get_home() + false // Not mobilised + }; } else if constexpr (Branch == UnitType::branch_t::NAVAL) { return { unit_deployment.get_name(), unit_deployment.get_type() }; } diff --git a/src/openvic-simulation/military/UnitType.cpp b/src/openvic-simulation/military/UnitType.cpp index 11f7221..d4ffbee 100644 --- a/src/openvic-simulation/military/UnitType.cpp +++ b/src/openvic-simulation/military/UnitType.cpp @@ -1,5 +1,6 @@ #include "UnitType.hpp" +#include "openvic-simulation/country/CountryInstance.hpp" #include "openvic-simulation/map/TerrainType.hpp" using namespace OpenVic; @@ -30,6 +31,29 @@ UnitType::UnitType( supply_cost { std::move(unit_args.supply_cost) }, terrain_modifiers { std::move(unit_args.terrain_modifiers) } {} +bool UnitTypeBranched::allowed_cultures_check_culture_in_country( + allowed_cultures_t allowed_cultures, Culture const& culture, CountryInstance const& country +) { + using enum allowed_cultures_t; + + switch (allowed_cultures) { + case ALL_CULTURES: + return true; + case ACCEPTED_CULTURES: + return country.is_primary_or_accepted_culture(culture); + case PRIMARY_CULTURE: + return country.is_primary_culture(culture); + case NO_CULTURES: + return false; + default: + Logger::error( + "Unknown allowed cultures value ", static_cast(allowed_cultures), " for culture ", + culture.get_identifier(), " and country ", country.get_identifier() + ); + return false; + } +} + UnitTypeBranched::UnitTypeBranched( std::string_view new_identifier, unit_type_args_t& unit_args, regiment_type_args_t const& regiment_type_args ) : UnitType { new_identifier, LAND, unit_args }, diff --git a/src/openvic-simulation/military/UnitType.hpp b/src/openvic-simulation/military/UnitType.hpp index 6bd7392..6bbaca7 100644 --- a/src/openvic-simulation/military/UnitType.hpp +++ b/src/openvic-simulation/military/UnitType.hpp @@ -15,6 +15,8 @@ namespace OpenVic { struct TerrainType; struct TerrainTypeManager; + struct Culture; + struct CountryInstance; struct UnitType : HasIdentifier { using icon_t = uint32_t; @@ -94,7 +96,18 @@ namespace OpenVic { struct UnitTypeBranched : UnitType { friend struct UnitTypeManager; - enum struct allowed_cultures_t { ALL_CULTURES, ACCEPTED_CULTURES, PRIMARY_CULTURE }; + // Each value is a subset of its predecessor, so smaller values contain larger values + enum struct allowed_cultures_t { ALL_CULTURES, ACCEPTED_CULTURES, PRIMARY_CULTURE, NO_CULTURES }; + + constexpr static allowed_cultures_t allowed_cultures_get_most_permissive( + allowed_cultures_t lhs, allowed_cultures_t rhs + ) { + return std::min(lhs, rhs); + } + + static bool allowed_cultures_check_culture_in_country( + allowed_cultures_t allowed_cultures, Culture const& culture, CountryInstance const& country + ); struct regiment_type_args_t { allowed_cultures_t allowed_cultures = allowed_cultures_t::ALL_CULTURES; diff --git a/src/openvic-simulation/misc/Define.cpp b/src/openvic-simulation/misc/Define.cpp index 015ebaa..c28aab0 100644 --- a/src/openvic-simulation/misc/Define.cpp +++ b/src/openvic-simulation/misc/Define.cpp @@ -156,13 +156,19 @@ DefineManager::DefineManager() great_power_rank { 8 }, lose_great_power_grace_days { Timespan::from_years(1) }, secondary_power_rank { 16 }, - country_investment_industrial_score_factor { 1 } + country_investment_industrial_score_factor { 1 }, // Economy // Military + pop_size_per_regiment { 1000 }, + min_pop_size_for_regiment { 1000 }, + pop_size_per_regiment_protectorate_multiplier { 1 }, + pop_size_per_regiment_colony_multiplier { 1 }, + pop_size_per_regiment_non_core_multiplier { 1 }, // Diplomacy + disarmed_penalty { 0 } // Pops @@ -243,8 +249,16 @@ bool DefineManager::load_defines_file(ast::NodeCPtr root) { // Economy // Military + ret &= load_define(pop_size_per_regiment, Military, "POP_SIZE_PER_REGIMENT"); + ret &= load_define(min_pop_size_for_regiment, Military, "POP_MIN_SIZE_FOR_REGIMENT"); + ret &= load_define( + pop_size_per_regiment_protectorate_multiplier, Military, "POP_MIN_SIZE_FOR_REGIMENT_PROTECTORATE_MULTIPLIER" + ); + ret &= load_define(pop_size_per_regiment_colony_multiplier, Military, "POP_MIN_SIZE_FOR_REGIMENT_COLONY_MULTIPLIER"); + ret &= load_define(pop_size_per_regiment_non_core_multiplier, Military, "POP_MIN_SIZE_FOR_REGIMENT_NONCORE_MULTIPLIER"); // Diplomacy + ret &= load_define(disarmed_penalty, Diplomacy, "DISARMAMENT_ARMY_HIT"); // Pops diff --git a/src/openvic-simulation/misc/Define.hpp b/src/openvic-simulation/misc/Define.hpp index a64636b..064883c 100644 --- a/src/openvic-simulation/misc/Define.hpp +++ b/src/openvic-simulation/misc/Define.hpp @@ -1,5 +1,6 @@ #pragma once +#include "openvic-simulation/pop/Pop.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" @@ -49,8 +50,15 @@ namespace OpenVic { // Economy // Military + Pop::pop_size_t PROPERTY(pop_size_per_regiment); // POP_SIZE_PER_REGIMENT + Pop::pop_size_t PROPERTY(min_pop_size_for_regiment); // POP_MIN_SIZE_FOR_REGIMENT + // POP_MIN_SIZE_FOR_REGIMENT_PROTECTORATE_MULTIPLIER + fixed_point_t PROPERTY(pop_size_per_regiment_protectorate_multiplier); + fixed_point_t PROPERTY(pop_size_per_regiment_colony_multiplier); // POP_MIN_SIZE_FOR_REGIMENT_COLONY_MULTIPLIER + fixed_point_t PROPERTY(pop_size_per_regiment_non_core_multiplier); // POP_MIN_SIZE_FOR_REGIMENT_NONCORE_MULTIPLIER // Diplomacy + fixed_point_t PROPERTY(disarmed_penalty); // DISARMAMENT_ARMY_HIT // Pops diff --git a/src/openvic-simulation/pop/Pop.cpp b/src/openvic-simulation/pop/Pop.cpp index 6dd0d1f..9221485 100644 --- a/src/openvic-simulation/pop/Pop.cpp +++ b/src/openvic-simulation/pop/Pop.cpp @@ -4,6 +4,7 @@ #include "openvic-simulation/country/CountryInstance.hpp" #include "openvic-simulation/map/ProvinceInstance.hpp" #include "openvic-simulation/military/UnitType.hpp" +#include "openvic-simulation/misc/Define.hpp" #include "openvic-simulation/politics/Ideology.hpp" #include "openvic-simulation/politics/Issue.hpp" #include "openvic-simulation/politics/Rebel.hpp" @@ -40,7 +41,8 @@ Pop::Pop(PopBase const& pop_base, decltype(ideologies)::keys_t const& ideology_k savings { 0 }, life_needs_fulfilled { 0 }, everyday_needs_fulfilled { 0 }, - luxury_needs_fulfilled { 0 } {} + luxury_needs_fulfilled { 0 }, + max_supported_regiments { 0 } {} void Pop::setup_pop_test_values(IssueManager const& issue_manager) { /* Returns +/- range% of size. */ @@ -125,6 +127,23 @@ void Pop::set_location(ProvinceInstance const& new_location) { } } +void Pop::update_gamestate( + DefineManager const& define_manager, CountryInstance const* owner, fixed_point_t const& pop_size_per_regiment_multiplier +) { + if (type.get_can_be_recruited()) { + if ( + size < define_manager.get_min_pop_size_for_regiment() || owner == nullptr || + !RegimentType::allowed_cultures_check_culture_in_country(owner->get_allowed_regiment_cultures(), culture, *owner) + ) { + max_supported_regiments = 0; + } else { + max_supported_regiments = (fixed_point_t::parse(size) / ( + fixed_point_t::parse(define_manager.get_pop_size_per_regiment()) * pop_size_per_regiment_multiplier + )).to_int64_t() + 1; + } + } +} + Strata::Strata(std::string_view new_identifier) : HasIdentifier { new_identifier } {} PopType::PopType( diff --git a/src/openvic-simulation/pop/Pop.hpp b/src/openvic-simulation/pop/Pop.hpp index c74840f..e8cab42 100644 --- a/src/openvic-simulation/pop/Pop.hpp +++ b/src/openvic-simulation/pop/Pop.hpp @@ -26,6 +26,8 @@ namespace OpenVic { struct IssueManager; struct ProvinceInstance; struct CountryParty; + struct DefineManager; + struct CountryInstance; struct PopBase { friend struct PopManager; @@ -82,6 +84,8 @@ namespace OpenVic { fixed_point_t PROPERTY(everyday_needs_fulfilled); fixed_point_t PROPERTY(luxury_needs_fulfilled); + size_t PROPERTY(max_supported_regiments); + Pop(PopBase const& pop_base, decltype(ideologies)::keys_t const& ideology_keys); public: @@ -93,6 +97,11 @@ namespace OpenVic { void setup_pop_test_values(IssueManager const& issue_manager); void set_location(ProvinceInstance const& new_location); + + void update_gamestate( + DefineManager const& define_manager, CountryInstance const* owner, + fixed_point_t const& pop_size_per_regiment_multiplier + ); }; struct Strata : HasIdentifier { -- cgit v1.2.3-56-ga3b1