aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation
diff options
context:
space:
mode:
author hop311 <hop3114@gmail.com>2024-09-07 00:13:47 +0200
committer hop311 <hop3114@gmail.com>2024-09-09 19:25:27 +0200
commitd67cd2d08fe2859809e35b93f5a8358c48a3705e (patch)
treee3f5b453affdb38e5a0c08513c404de652fce738 /src/openvic-simulation
parent16349d6cad05497f983b1da123b6284ecfddd638 (diff)
Calculate country military power (still needs modifiers + soldier pop supported regiment count)ranking
Diffstat (limited to 'src/openvic-simulation')
-rw-r--r--src/openvic-simulation/InstanceManager.cpp10
-rw-r--r--src/openvic-simulation/country/CountryInstance.cpp163
-rw-r--r--src/openvic-simulation/country/CountryInstance.hpp37
-rw-r--r--src/openvic-simulation/map/MapInstance.cpp4
-rw-r--r--src/openvic-simulation/map/MapInstance.hpp2
-rw-r--r--src/openvic-simulation/map/ProvinceInstance.cpp29
-rw-r--r--src/openvic-simulation/map/ProvinceInstance.hpp6
-rw-r--r--src/openvic-simulation/map/State.cpp6
-rw-r--r--src/openvic-simulation/map/State.hpp2
-rw-r--r--src/openvic-simulation/military/UnitInstance.cpp4
-rw-r--r--src/openvic-simulation/military/UnitInstance.hpp5
-rw-r--r--src/openvic-simulation/military/UnitInstanceGroup.cpp7
-rw-r--r--src/openvic-simulation/military/UnitType.cpp24
-rw-r--r--src/openvic-simulation/military/UnitType.hpp15
-rw-r--r--src/openvic-simulation/misc/Define.cpp16
-rw-r--r--src/openvic-simulation/misc/Define.hpp8
-rw-r--r--src/openvic-simulation/pop/Pop.cpp21
-rw-r--r--src/openvic-simulation/pop/Pop.hpp9
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<UnitType::branch_t::NAV
template bool CountryInstance::remove_leader(LeaderBranched<UnitType::branch_t::LAND> const*);
template bool CountryInstance::remove_leader(LeaderBranched<UnitType::branch_t::NAVAL> const*);
+template<UnitType::branch_t Branch>
+void CountryInstance::unlock_unit_type(UnitTypeBranched<Branch> const& unit_type) {
+ IndexedMap<UnitTypeBranched<Branch>, bool>& unlocked_unit_types = get_unlocked_unit_types<Branch>();
+
+ 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<UnitType::branch_t::LAND> const&);
+template void CountryInstance::unlock_unit_type(UnitTypeBranched<UnitType::branch_t::NAVAL> 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<CountryDefinition const*> 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<General> PROPERTY(generals);
plf::colony<Admiral> PROPERTY(admirals);
ordered_set<ArmyInstance*> PROPERTY(armies);
ordered_set<NavyInstance*> 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<RegimentType, bool> PROPERTY(unlocked_regiment_types);
+ RegimentType::allowed_cultures_t PROPERTY(allowed_regiment_cultures);
+ IndexedMap<ShipType, bool> 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<UnitType::branch_t Branch>
bool remove_leader(LeaderBranched<Branch> const* leader);
+ template<UnitType::branch_t Branch>
+ void unlock_unit_type(UnitTypeBranched<Branch> 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<CountryDefinition const*> 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<Ideology, fixed_point_t> PROPERTY(ideology_distribution);
fixed_point_map_t<Culture const*> PROPERTY(culture_distribution);
fixed_point_map_t<Religion const*> 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<PopBase> 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<UnitType::branch_t Branch>
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<UnitType::branch_t::LAND>;
template struct OpenVic::UnitInstance<UnitType::branch_t::NAVAL>;
UnitInstanceBranched<UnitType::branch_t::LAND>::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<UnitType::branch_t::NAVAL>::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<Branch>().insert(
[&unit_deployment]() -> UnitInstanceBranched<Branch> {
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<LAND>::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<uint32_t>(allowed_cultures), " for culture ",
+ culture.get_identifier(), " and country ", country.get_identifier()
+ );
+ return false;
+ }
+}
+
UnitTypeBranched<LAND>::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::branch_t::LAND> : 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 {