From f8b5c233cc11533aa98bc67a7ba0449138505e5b Mon Sep 17 00:00:00 2001 From: Spartan322 Date: Fri, 5 Dec 2025 15:08:56 -0500 Subject: [PATCH] Refactor pop_size_t to be type-safe Move pop_size_t to population/PopSize.hpp Add equalable to Concepts.hpp Add expect_strong_typedef to NodeTools.hpp Add `&& equalable` requirement to IndexedFlatMap's divide_assign_handle_zero --- .../core/template/Concepts.hpp | 5 ++ .../country/CountryInstance.cpp | 12 ++-- .../dataloader/NodeTools.hpp | 52 ++++++++++---- .../defines/MilitaryDefines.cpp | 4 +- .../defines/MilitaryDefines.hpp | 2 +- .../defines/PopsDefines.cpp | 4 +- .../defines/PopsDefines.hpp | 2 +- .../economy/production/ArtisanalProducer.cpp | 4 +- .../economy/production/ArtisanalProducer.hpp | 2 +- .../economy/production/Employee.hpp | 2 +- .../economy/production/FactoryProducer.hpp | 2 +- .../economy/production/ProductionType.cpp | 2 +- .../economy/production/ProductionType.hpp | 2 +- .../production/ResourceGatheringOperation.cpp | 14 ++-- .../production/ResourceGatheringOperation.hpp | 2 +- src/openvic-simulation/map/Mapmode.cpp | 4 +- src/openvic-simulation/population/Pop.cpp | 12 ++-- src/openvic-simulation/population/Pop.hpp | 6 +- .../population/PopManager.cpp | 9 ++- src/openvic-simulation/population/PopSize.hpp | 71 +++++++++++++++++++ src/openvic-simulation/population/PopType.hpp | 2 +- .../population/PopsAggregate.cpp | 8 ++- .../population/PopsAggregate.hpp | 2 +- .../types/IndexedFlatMap.hpp | 4 +- src/openvic-simulation/types/PopSize.hpp | 7 -- 25 files changed, 171 insertions(+), 65 deletions(-) create mode 100644 src/openvic-simulation/population/PopSize.hpp delete mode 100644 src/openvic-simulation/types/PopSize.hpp diff --git a/src/openvic-simulation/core/template/Concepts.hpp b/src/openvic-simulation/core/template/Concepts.hpp index 3f1209a29..743dc157a 100644 --- a/src/openvic-simulation/core/template/Concepts.hpp +++ b/src/openvic-simulation/core/template/Concepts.hpp @@ -223,4 +223,9 @@ namespace OpenVic { concept mul_add_assignable = requires(Lhs& lhs, const A a, const B b) { { lhs += a * b } -> std::same_as; }; + + template + concept equalable = requires(Lhs const& lhs, Rhs const& rhs) { + { lhs == rhs } -> std::convertible_to; + }; } diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp index bc9efe003..b4e15899d 100644 --- a/src/openvic-simulation/country/CountryInstance.cpp +++ b/src/openvic-simulation/country/CountryInstance.cpp @@ -42,7 +42,7 @@ #include "openvic-simulation/types/Date.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" #include "openvic-simulation/types/IndexedFlatMap.hpp" -#include "openvic-simulation/types/PopSize.hpp" +#include "openvic-simulation/population/PopSize.hpp" #include "openvic-simulation/types/UnitBranchType.hpp" #include "openvic-simulation/utility/Containers.hpp" #include "openvic-simulation/utility/Logger.hpp" @@ -1365,13 +1365,13 @@ void CountryInstance::_update_budget() { if (total_non_colonial_population == 0) { administrative_efficiency_from_administrators.set(fixed_point_t::_1); administrator_percentage.set(fixed_point_t::_0); - } else { - administrator_percentage.set(fixed_point_t::parse(administrators) / total_non_colonial_population); + } else { + administrator_percentage.set(fixed_point_t::parse(type_safe::get(administrators)) / type_safe::get(total_non_colonial_population)); - const fixed_point_t desired_administrators = desired_administrator_percentage.get_untracked() * total_non_colonial_population; + const fixed_point_t desired_administrators = desired_administrator_percentage.get_untracked() * type_safe::get(total_non_colonial_population); const fixed_point_t administrative_efficiency_from_administrators_unclamped = std::min( fixed_point_t::mul_div( - administrators, + type_safe::get(administrators), fixed_point_t::_1 + get_modifier_effect_value(*modifier_effect_cache.get_administrative_efficiency()), desired_administrators ) @@ -1397,7 +1397,7 @@ void CountryInstance::_update_budget() { projected_education_spending_unscaled_by_slider_running_total += size * education_salary_base_by_pop_type.at(pop_type).get_untracked(); projected_military_spending_unscaled_by_slider_running_total += size * military_salary_base_by_pop_type.at(pop_type).get_untracked(); projected_pensions_spending_unscaled_by_slider_running_total += size * calculate_pensions_base(pop_type); - projected_unemployment_subsidies_spending_unscaled_by_slider_running_total += get_unemployed_pops_by_type(pop_type) + projected_unemployment_subsidies_spending_unscaled_by_slider_running_total += type_safe::get(get_unemployed_pops_by_type(pop_type)) * calculate_unemployment_subsidies_base(pop_type); } diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp index b2e0b15df..1ab1a890f 100644 --- a/src/openvic-simulation/dataloader/NodeTools.hpp +++ b/src/openvic-simulation/dataloader/NodeTools.hpp @@ -199,21 +199,49 @@ using namespace std::string_view_literals; return expect_uint(callback, base); } + template T, typename AsT = type_safe::underlying_type> + NodeCallback auto expect_strong_typedef(callback_t& callback, int base = 10) { + if constexpr (std::unsigned_integral) { + return expect_uint64( + [callback](uint64_t val) mutable -> bool { + if (val <= static_cast(std::numeric_limits::max())) { + return callback(T(val)); + } + spdlog::error_s( + "Invalid uint: {} (valid range: [0, {}])", val, + static_cast(std::numeric_limits::max()) + ); + return false; + }, + base + ); + } else { + return expect_int64( + [callback](int64_t val) mutable -> bool { + if (val >= static_cast(std::numeric_limits::min()) && + val <= static_cast(std::numeric_limits::max())) { + return callback(T(val)); + } + spdlog::error_s( + "Invalid int: {} (valid range: [{}, {}])", val, + static_cast(std::numeric_limits::min()), + static_cast(std::numeric_limits::max()) + ); + return false; + }, + base + ); + } + } + template T, typename AsT = type_safe::underlying_type> + NodeCallback auto expect_strong_typedef(callback_t&& callback, int base = 10) { + return expect_strong_typedef(callback, base); + } + template T> requires std::unsigned_integral> NodeCallback auto expect_index(callback_t& callback, int base = 10) { - using underlying_type = type_safe::underlying_type; - - return expect_uint64([callback](uint64_t val) mutable -> bool { - if (val <= static_cast(std::numeric_limits::max())) { - return callback(T(val)); - } - spdlog::error_s( - "Invalid uint: {} (valid range: [0, {}])", - val, static_cast(std::numeric_limits::max()) - ); - return false; - }, base); + return expect_strong_typedef(callback, base); } template T> requires std::unsigned_integral> diff --git a/src/openvic-simulation/defines/MilitaryDefines.cpp b/src/openvic-simulation/defines/MilitaryDefines.cpp index 2f2d935a4..7b683eba4 100644 --- a/src/openvic-simulation/defines/MilitaryDefines.cpp +++ b/src/openvic-simulation/defines/MilitaryDefines.cpp @@ -15,8 +15,8 @@ node_callback_t MilitaryDefines::expect_defines() { "REINFORCE_SPEED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(reinforce_speed)), "COMBAT_DIFFICULTY_IMPACT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(combat_difficulty_impact)), "BASE_COMBAT_WIDTH", ONE_EXACTLY, expect_uint(assign_variable_callback(base_combat_width)), - "POP_MIN_SIZE_FOR_REGIMENT", ONE_EXACTLY, expect_uint(assign_variable_callback(min_pop_size_for_regiment)), - "POP_SIZE_PER_REGIMENT", ONE_EXACTLY, expect_uint(assign_variable_callback(pop_size_per_regiment)), + "POP_MIN_SIZE_FOR_REGIMENT", ONE_EXACTLY, expect_strong_typedef(assign_variable_callback(min_pop_size_for_regiment)), + "POP_SIZE_PER_REGIMENT", ONE_EXACTLY, expect_strong_typedef(assign_variable_callback(pop_size_per_regiment)), "SOLDIER_TO_POP_DAMAGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(soldier_to_pop_damage)), "LAND_SPEED_MODIFIER", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(land_speed_modifier)), "NAVAL_SPEED_MODIFIER", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(naval_speed_modifier)), diff --git a/src/openvic-simulation/defines/MilitaryDefines.hpp b/src/openvic-simulation/defines/MilitaryDefines.hpp index a44ae68c4..e27925b42 100644 --- a/src/openvic-simulation/defines/MilitaryDefines.hpp +++ b/src/openvic-simulation/defines/MilitaryDefines.hpp @@ -3,7 +3,7 @@ #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/types/Date.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" -#include "openvic-simulation/types/PopSize.hpp" +#include "openvic-simulation/population/PopSize.hpp" #include "openvic-simulation/utility/Getters.hpp" namespace OpenVic { diff --git a/src/openvic-simulation/defines/PopsDefines.cpp b/src/openvic-simulation/defines/PopsDefines.cpp index ea7064af4..0f09a1dfd 100644 --- a/src/openvic-simulation/defines/PopsDefines.cpp +++ b/src/openvic-simulation/defines/PopsDefines.cpp @@ -75,8 +75,8 @@ node_callback_t PopsDefines::expect_defines() { "MOVEMENT_SUPPORT_UH_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(movement_support_uh_factor)), "REBEL_OCCUPATION_STRENGTH_BONUS", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(rebel_occupation_strength_bonus)), - "LARGE_POPULATION_LIMIT", ONE_EXACTLY, expect_uint(assign_variable_callback(large_population_limit)), + "LARGE_POPULATION_LIMIT", ONE_EXACTLY, expect_strong_typedef(assign_variable_callback(large_population_limit)), "LARGE_POPULATION_INFLUENCE_PENALTY_CHUNK", ONE_EXACTLY, - expect_uint(assign_variable_callback(large_population_influence_penalty_chunk)) + expect_strong_typedef(assign_variable_callback(large_population_influence_penalty_chunk)) ); } diff --git a/src/openvic-simulation/defines/PopsDefines.hpp b/src/openvic-simulation/defines/PopsDefines.hpp index 0ed9cfbac..60c94cd87 100644 --- a/src/openvic-simulation/defines/PopsDefines.hpp +++ b/src/openvic-simulation/defines/PopsDefines.hpp @@ -2,7 +2,7 @@ #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" -#include "openvic-simulation/types/PopSize.hpp" +#include "openvic-simulation/population/PopSize.hpp" #include "openvic-simulation/types/ProvinceLifeRating.hpp" #include "openvic-simulation/utility/Getters.hpp" diff --git a/src/openvic-simulation/economy/production/ArtisanalProducer.cpp b/src/openvic-simulation/economy/production/ArtisanalProducer.cpp index de599c415..1b977b48f 100644 --- a/src/openvic-simulation/economy/production/ArtisanalProducer.cpp +++ b/src/openvic-simulation/economy/production/ArtisanalProducer.cpp @@ -71,8 +71,8 @@ void ArtisanalProducer::artisan_tick_handler::calculate_inputs( //throughput scalar, the minimum of stockpile / base_desired_quantity //inputs_bought_fraction uses base_desired_quantity as population size is cancelled in the production and input calculations. const pop_size_t pop_size = pop.get_size(); - fixed_point_t inputs_bought_numerator = pop_size, - inputs_bought_denominator = production_type.base_workforce_size, + fixed_point_t inputs_bought_numerator = type_safe::get(pop_size), + inputs_bought_denominator = type_safe::get(production_type.base_workforce_size), inputs_bought_fraction_v = inputs_bought_numerator / inputs_bought_denominator; distinct_goods_to_buy = 0; diff --git a/src/openvic-simulation/economy/production/ArtisanalProducer.hpp b/src/openvic-simulation/economy/production/ArtisanalProducer.hpp index a62c66a7f..a45e0446a 100644 --- a/src/openvic-simulation/economy/production/ArtisanalProducer.hpp +++ b/src/openvic-simulation/economy/production/ArtisanalProducer.hpp @@ -6,7 +6,6 @@ #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" #include "openvic-simulation/types/fixed_point/FixedPointMap.hpp" #include "openvic-simulation/types/fixed_point/Fraction.hpp" -#include "openvic-simulation/types/PopSize.hpp" #include "openvic-simulation/utility/Getters.hpp" namespace OpenVic { @@ -22,6 +21,7 @@ namespace OpenVic { struct ProductionType; struct ProvinceInstance; struct RandomU32; + struct pop_size_t; struct ArtisanalProducer { private: diff --git a/src/openvic-simulation/economy/production/Employee.hpp b/src/openvic-simulation/economy/production/Employee.hpp index a8d5b73c5..1d6208f6a 100644 --- a/src/openvic-simulation/economy/production/Employee.hpp +++ b/src/openvic-simulation/economy/production/Employee.hpp @@ -1,7 +1,7 @@ #pragma once #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" -#include "openvic-simulation/types/PopSize.hpp" +#include "openvic-simulation/population/PopSize.hpp" namespace OpenVic { struct CountryInstance; diff --git a/src/openvic-simulation/economy/production/FactoryProducer.hpp b/src/openvic-simulation/economy/production/FactoryProducer.hpp index 829996f6f..380419e9a 100644 --- a/src/openvic-simulation/economy/production/FactoryProducer.hpp +++ b/src/openvic-simulation/economy/production/FactoryProducer.hpp @@ -5,7 +5,7 @@ #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" #include "openvic-simulation/types/fixed_point/FixedPointMap.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" -#include "openvic-simulation/types/PopSize.hpp" +#include "openvic-simulation/population/PopSize.hpp" #include "openvic-simulation/utility/Getters.hpp" namespace OpenVic { diff --git a/src/openvic-simulation/economy/production/ProductionType.cpp b/src/openvic-simulation/economy/production/ProductionType.cpp index d9bd08e83..3626209e5 100644 --- a/src/openvic-simulation/economy/production/ProductionType.cpp +++ b/src/openvic-simulation/economy/production/ProductionType.cpp @@ -360,7 +360,7 @@ bool ProductionTypeManager::load_production_types_file( "employees", ZERO_OR_ONE, _expect_job_list(good_definition_manager, pop_manager, move_variable_callback(jobs)), "type", ZERO_OR_ONE, expect_identifier(expect_mapped_string(template_type_map, assign_variable_callback(template_type))), - "workforce", ZERO_OR_ONE, expect_uint(assign_variable_callback(base_workforce_size)), + "workforce", ZERO_OR_ONE, expect_strong_typedef(assign_variable_callback(base_workforce_size)), "input_goods", ZERO_OR_ONE, good_definition_manager.expect_good_definition_decimal_map(move_variable_callback(input_goods)), "output_goods", ZERO_OR_ONE, diff --git a/src/openvic-simulation/economy/production/ProductionType.hpp b/src/openvic-simulation/economy/production/ProductionType.hpp index 3a6e2dbf0..67bffaa2b 100644 --- a/src/openvic-simulation/economy/production/ProductionType.hpp +++ b/src/openvic-simulation/economy/production/ProductionType.hpp @@ -6,7 +6,7 @@ #include "openvic-simulation/types/IdentifierRegistry.hpp" #include "openvic-simulation/types/IndexedFlatMap.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" -#include "openvic-simulation/types/PopSize.hpp" +#include "openvic-simulation/population/PopSize.hpp" #include "openvic-simulation/types/PopSprite.hpp" #include "openvic-simulation/utility/Containers.hpp" diff --git a/src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp b/src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp index 2a189a9e0..6496c47b4 100644 --- a/src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp +++ b/src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp @@ -12,11 +12,13 @@ #include "openvic-simulation/population/Pop.hpp" #include "openvic-simulation/population/PopType.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" -#include "openvic-simulation/types/PopSize.hpp" +#include "openvic-simulation/population/PopSize.hpp" #include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/utility/Logger.hpp" #include "openvic-simulation/utility/Containers.hpp" +#include + using namespace OpenVic; ResourceGatheringOperation::ResourceGatheringOperation( @@ -71,14 +73,14 @@ void ResourceGatheringOperation::initialise_rgo_size_multiplier() { } const fixed_point_t size_modifier = calculate_size_modifier(); - const fixed_point_t base_workforce_size = production_type.base_workforce_size; + const fixed_point_t base_workforce_size = type_safe::get(production_type.base_workforce_size); if (size_modifier == 0) { size_multiplier = 0; } else { size_multiplier = ((total_worker_count_in_province / (size_modifier * base_workforce_size)).ceil() * fixed_point_t::_1_50).floor(); } - max_employee_count_cache = (size_modifier * size_multiplier * base_workforce_size).floor(); + max_employee_count_cache = (size_modifier * size_multiplier * base_workforce_size).floor>(); } fixed_point_t ResourceGatheringOperation::calculate_size_modifier() const { @@ -187,7 +189,7 @@ void ResourceGatheringOperation::hire() { proportion_to_hire = 1; } else { //hire all pops proportionally - const fixed_point_t max_worker_count_real = max_employee_count_cache, available_worker_count_real = available_worker_count; + const fixed_point_t max_worker_count_real = type_safe::get(max_employee_count_cache), available_worker_count_real = type_safe::get(available_worker_count); proportion_to_hire = max_worker_count_real / available_worker_count_real; } @@ -197,7 +199,7 @@ void ResourceGatheringOperation::hire() { for (Job const& job : jobs) { PopType const* const job_pop_type = job.get_pop_type(); if (job_pop_type && *job_pop_type == pop_type) { - const pop_size_t pop_size_to_hire = static_cast((proportion_to_hire * pop.get_size()).floor()); + const pop_size_t pop_size_to_hire = (proportion_to_hire * pop.get_size()).floor>(); if (pop_size_to_hire <= 0) { continue; } @@ -306,7 +308,7 @@ fixed_point_t ResourceGatheringOperation::produce() { const fixed_point_t effect_multiplier = job.get_effect_multiplier(); fixed_point_t relative_to_workforce = - fixed_point_t::parse(employees_of_type) / fixed_point_t::parse(max_employee_count_cache); + fixed_point_t::parse(type_safe::get(employees_of_type)) / fixed_point_t::parse(type_safe::get(max_employee_count_cache)); const fixed_point_t amount = job.get_amount(); if (effect_multiplier != fixed_point_t::_1 && relative_to_workforce > amount) { relative_to_workforce = amount; diff --git a/src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp b/src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp index d4ea3a3b3..4d0368d87 100644 --- a/src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp +++ b/src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp @@ -3,7 +3,7 @@ #include "openvic-simulation/economy/production/Employee.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" #include "openvic-simulation/types/IndexedFlatMap.hpp" -#include "openvic-simulation/types/PopSize.hpp" +#include "openvic-simulation/population/PopSize.hpp" #include "openvic-simulation/utility/Getters.hpp" #include "openvic-simulation/utility/Containers.hpp" diff --git a/src/openvic-simulation/map/Mapmode.cpp b/src/openvic-simulation/map/Mapmode.cpp index 85ea5a7cf..22c9cbf46 100644 --- a/src/openvic-simulation/map/Mapmode.cpp +++ b/src/openvic-simulation/map/Mapmode.cpp @@ -14,7 +14,7 @@ #include "openvic-simulation/population/Culture.hpp" #include "openvic-simulation/population/Religion.hpp" #include "openvic-simulation/types/OrderedContainersMath.hpp" -#include "openvic-simulation/types/PopSize.hpp" +#include "openvic-simulation/population/PopSize.hpp" using namespace OpenVic; using namespace OpenVic::colour_literals; @@ -266,7 +266,7 @@ bool MapmodeManager::setup_mapmodes(MapDefinition const& map_definition) { // by the same country, relative to the most populous province in that set of provinces if (!province.province_definition.is_water()) { const colour_argb_t::value_type val = colour_argb_t::colour_traits::component_from_fraction( - province.get_total_population(), map_instance.get_highest_province_population() + 1, 0.1f, 1.0f + type_safe::get(province.get_total_population()), type_safe::get(map_instance.get_highest_province_population()) + 1, 0.1f, 1.0f ); return colour_argb_t { 0, val, 0, ALPHA_VALUE }; } else { diff --git a/src/openvic-simulation/population/Pop.cpp b/src/openvic-simulation/population/Pop.cpp index 3a6a8d59f..921f09730 100644 --- a/src/openvic-simulation/population/Pop.cpp +++ b/src/openvic-simulation/population/Pop.cpp @@ -73,7 +73,7 @@ fixed_point_t Pop::get_unemployment_fraction() const { if (!type->can_be_unemployed) { return 0; } - return fixed_point_t::parse(get_unemployed()) / size; + return fixed_point_t::parse(type_safe::get(get_unemployed())) / size; } void Pop::setup_pop_test_values(IssueManager const& issue_manager) { @@ -120,7 +120,7 @@ void Pop::setup_pop_test_values(IssueManager const& issue_manager) { for (Ideology const& ideology : supporter_equivalents_by_ideology.get_keys()) { test_weight_indexed(supporter_equivalents_by_ideology, ideology, 1, 5); } - supporter_equivalents_by_ideology.rescale(size); + supporter_equivalents_by_ideology.rescale(type_safe::get(size)); supporter_equivalents_by_issue.clear(); for (BaseIssue const& issue : issue_manager.get_party_policies()) { @@ -131,14 +131,14 @@ void Pop::setup_pop_test_values(IssueManager const& issue_manager) { test_weight_ordered(supporter_equivalents_by_issue, reform, 3, 6); } } - rescale_fixed_point_map(supporter_equivalents_by_issue, size); + rescale_fixed_point_map(supporter_equivalents_by_issue, type_safe::get(size)); if (!vote_equivalents_by_party.empty()) { for (auto& [party, value] : vote_equivalents_by_party) { vote_equivalents_by_party[party] = 0; test_weight_ordered(vote_equivalents_by_party, party, 4, 10); } - rescale_fixed_point_map(vote_equivalents_by_party, size); + rescale_fixed_point_map(vote_equivalents_by_party, type_safe::get(size)); } /* Returns a fixed point between 0 and max. */ @@ -255,8 +255,8 @@ void Pop::update_gamestate( ) { max_supported_regiments = 0; } else { - max_supported_regiments = (fixed_point_t::parse(size) / ( - fixed_point_t::parse(military_defines.get_pop_size_per_regiment()) * pop_size_per_regiment_multiplier + max_supported_regiments = (fixed_point_t::parse(type_safe::get(size)) / ( + fixed_point_t::parse(type_safe::get(military_defines.get_pop_size_per_regiment())) * pop_size_per_regiment_multiplier )).floor() + 1; } } diff --git a/src/openvic-simulation/population/Pop.hpp b/src/openvic-simulation/population/Pop.hpp index be0565a37..a39c2b45a 100644 --- a/src/openvic-simulation/population/Pop.hpp +++ b/src/openvic-simulation/population/Pop.hpp @@ -6,11 +6,13 @@ #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" #include "openvic-simulation/types/fixed_point/FixedPointMap.hpp" #include "openvic-simulation/types/IndexedFlatMap.hpp" -#include "openvic-simulation/types/PopSize.hpp" +#include "openvic-simulation/population/PopSize.hpp" #include "openvic-simulation/types/UnitBranchType.hpp" #include "openvic-simulation/utility/Containers.hpp" #include "openvic-simulation/core/portable/ForwardableSpan.hpp" +#include + namespace OpenVic { struct BaseIssue; struct BuyResult; @@ -83,7 +85,7 @@ namespace OpenVic { return static_cast(allowed) <= static_cast(status); } - static constexpr pop_size_t MAX_SIZE = std::numeric_limits::max(); + static constexpr pop_size_t MAX_SIZE = std::numeric_limits>::max(); private: MarketInstance& market_instance; diff --git a/src/openvic-simulation/population/PopManager.cpp b/src/openvic-simulation/population/PopManager.cpp index 6b5b0f45b..3a54d3ff2 100644 --- a/src/openvic-simulation/population/PopManager.cpp +++ b/src/openvic-simulation/population/PopManager.cpp @@ -11,6 +11,9 @@ #include "openvic-simulation/modifier/ModifierManager.hpp" #include "openvic-simulation/core/FormatValidate.hpp" #include "openvic-simulation/utility/Logger.hpp" +#include "openvic-simulation/population/PopSize.hpp" + +#include using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -279,8 +282,8 @@ bool PopManager::load_pop_type_file( "sprite", ONE_EXACTLY, expect_uint(assign_variable_callback(sprite)), "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), "is_artisan", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_artisan)), - "max_size", ZERO_OR_ONE, expect_uint(assign_variable_callback(max_size)), - "merge_max_size", ZERO_OR_ONE, expect_uint(assign_variable_callback(merge_max_size)), + "max_size", ZERO_OR_ONE, expect_strong_typedef(assign_variable_callback(max_size)), + "merge_max_size", ZERO_OR_ONE, expect_strong_typedef(assign_variable_callback(merge_max_size)), "strata", ONE_EXACTLY, stratas.expect_item_identifier(assign_variable_callback_pointer(strata)), "state_capital_only", ZERO_OR_ONE, expect_bool(assign_variable_callback(state_capital_only)), "research_points", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(research_points)), @@ -472,7 +475,7 @@ bool PopManager::load_pop_bases_into_vector( return true; } - if (culture != nullptr && religion != nullptr && size >= 1 && size <= std::numeric_limits::max()) { + if (culture != nullptr && religion != nullptr && size >= 1 && size <= std::numeric_limits>::max()) { vec.emplace_back(PopBase { type, *culture, *religion, size.floor(), militancy, consciousness, rebel_type }); } else { spdlog::warn_s( diff --git a/src/openvic-simulation/population/PopSize.hpp b/src/openvic-simulation/population/PopSize.hpp new file mode 100644 index 000000000..d9d106925 --- /dev/null +++ b/src/openvic-simulation/population/PopSize.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include + +#include +#include + +#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" + +#include + +namespace OpenVic { + struct pop_size_t : type_safe::strong_typedef, + type_safe::strong_typedef_op::equality_comparison, + type_safe::strong_typedef_op::relational_comparison, + type_safe::strong_typedef_op::integer_arithmetic, + type_safe::strong_typedef_op::mixed_addition, + type_safe::strong_typedef_op::mixed_subtraction, + type_safe::strong_typedef_op::mixed_relational_comparison, + type_safe::strong_typedef_op::mixed_equality_comparison { + using strong_typedef::strong_typedef; + constexpr pop_size_t(std::same_as auto value) : strong_typedef(value) {} + + using ov_return_by_value = void; + + friend inline constexpr fixed_point_t operator*(const pop_size_t lhs, const std::same_as auto rhs) { + return type_safe::get(lhs) * rhs; + } + + friend inline constexpr fixed_point_t operator*(const std::same_as auto lhs, const pop_size_t rhs) { + return lhs * type_safe::get(rhs); + } + + friend inline constexpr fixed_point_t& operator*=(std::same_as auto lhs, const pop_size_t rhs) { + lhs *= type_safe::get(rhs); + return lhs; + } + + friend inline constexpr fixed_point_t operator/(const pop_size_t lhs, const std::same_as auto rhs) { + return type_safe::get(lhs) / rhs; + } + + friend inline constexpr fixed_point_t operator/(const std::same_as auto lhs, const pop_size_t rhs) { + return lhs / type_safe::get(rhs); + } + + friend inline constexpr fixed_point_t& operator/=(std::same_as auto lhs, const pop_size_t rhs) { + lhs /= type_safe::get(rhs); + return lhs; + } + + friend inline constexpr bool operator==(const std::same_as auto lhs, const pop_size_t rhs) { + return lhs == type_safe::get(rhs); + } + + friend inline constexpr auto operator<=>(const std::same_as auto lhs, const pop_size_t rhs) { + return lhs <=> type_safe::get(rhs); + } + + friend inline constexpr auto operator<=>(const pop_size_t lhs, const pop_size_t rhs) { + return type_safe::get(lhs) <=> type_safe::get(rhs); + } + }; +} + +template<> +struct fmt::formatter : fmt::formatter { + fmt::format_context::iterator format(OpenVic::pop_size_t value, fmt::format_context& ctx) const { + return fmt::formatter::format(type_safe::get(value), ctx); + } +}; diff --git a/src/openvic-simulation/population/PopType.hpp b/src/openvic-simulation/population/PopType.hpp index a2a5c79b6..dd9073c20 100644 --- a/src/openvic-simulation/population/PopType.hpp +++ b/src/openvic-simulation/population/PopType.hpp @@ -6,7 +6,7 @@ #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/IndexedFlatMap.hpp" -#include "openvic-simulation/types/PopSize.hpp" +#include "openvic-simulation/population/PopSize.hpp" #include "openvic-simulation/types/PopSprite.hpp" #include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/utility/Containers.hpp" diff --git a/src/openvic-simulation/population/PopsAggregate.cpp b/src/openvic-simulation/population/PopsAggregate.cpp index 646942704..2a660b316 100644 --- a/src/openvic-simulation/population/PopsAggregate.cpp +++ b/src/openvic-simulation/population/PopsAggregate.cpp @@ -8,6 +8,8 @@ #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" #include "openvic-simulation/types/OrderedContainersMath.hpp" +#include + using namespace OpenVic; PopsAggregate::PopsAggregate( decltype(population_by_strata)::keys_span_type strata_keys, @@ -51,7 +53,7 @@ fixed_point_t PopsAggregate::get_population_by_culture(Culture const& culture) c const decltype(population_by_culture)::const_iterator it = population_by_culture.find(&culture); if (it != population_by_culture.end()) { - return it->second; + return type_safe::get(it->second); } else { return 0; } @@ -60,7 +62,7 @@ fixed_point_t PopsAggregate::get_population_by_religion(Religion const& religion const decltype(population_by_religion)::const_iterator it = population_by_religion.find(&religion); if (it != population_by_religion.end()) { - return it->second; + return type_safe::get(it->second); } else { return 0; } @@ -111,7 +113,7 @@ void PopsAggregate::add_pops_aggregate(PopsAggregate& part) { _yesterdays_import_value_running_total += part.get_yesterdays_import_value_untracked(); // TODO - change casting if pop_size_t changes type - const fixed_point_t part_population = fixed_point_t::parse(part.get_total_population()); + const fixed_point_t part_population = fixed_point_t::parse(type_safe::get(part.get_total_population())); average_literacy += part.get_average_literacy() * part_population; average_consciousness += part.get_average_consciousness() * part_population; average_militancy += part.get_average_militancy() * part_population; diff --git a/src/openvic-simulation/population/PopsAggregate.hpp b/src/openvic-simulation/population/PopsAggregate.hpp index 65f9af0a8..1a9615954 100644 --- a/src/openvic-simulation/population/PopsAggregate.hpp +++ b/src/openvic-simulation/population/PopsAggregate.hpp @@ -4,7 +4,7 @@ #include "openvic-simulation/types/fixed_point/FixedPointMap.hpp" #include "openvic-simulation/types/IndexedFlatMap.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" -#include "openvic-simulation/types/PopSize.hpp" +#include "openvic-simulation/population/PopSize.hpp" #include "openvic-simulation/utility/Getters.hpp" #include "openvic-simulation/utility/reactive/MutableState.hpp" diff --git a/src/openvic-simulation/types/IndexedFlatMap.hpp b/src/openvic-simulation/types/IndexedFlatMap.hpp index 1ea92be65..31584e0df 100644 --- a/src/openvic-simulation/types/IndexedFlatMap.hpp +++ b/src/openvic-simulation/types/IndexedFlatMap.hpp @@ -851,7 +851,7 @@ namespace OpenVic { template IndexedFlatMap& operator/=(IndexedFlatMap const& other) - requires divide_assignable { + requires divide_assignable && equalable { static_assert(has_index); if (!check_subset_span_match(other)) { return *this; @@ -877,7 +877,7 @@ namespace OpenVic { IndexedFlatMap& divide_assign_handle_zero( IndexedFlatMap const& other, fu2::function handle_div_by_zero - ) requires divide_assignable { + ) requires divide_assignable && equalable { static_assert(has_index); if (!check_subset_span_match(other)) { return *this; diff --git a/src/openvic-simulation/types/PopSize.hpp b/src/openvic-simulation/types/PopSize.hpp deleted file mode 100644 index 6e00eeb04..000000000 --- a/src/openvic-simulation/types/PopSize.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -namespace OpenVic { - using pop_size_t = int32_t; -} \ No newline at end of file