Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@
[submodule "deps/type_safe"]
path = deps/type_safe
url = https://github.com/foonathan/type_safe
[submodule "deps/int128"]
path = deps/int128
url = https://github.com/cppalliance/int128
9 changes: 9 additions & 0 deletions deps/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,14 @@ def build_type_safe(env):
env.exposed_includes += env.type_safe["INCPATH"]


def build_int128(env):
include_path = "int128/include"
env.int128 = {}
env.int128["INCPATH"] = [env.Dir(include_path)]
env.Append(CPPPATH=env.int128["INCPATH"])
env.exposed_includes += env.int128["INCPATH"]


def link_tbb(env):
import sys

Expand All @@ -271,4 +279,5 @@ build_memory(env)
build_spdlog(env)
build_xoshiro(env)
build_type_safe(env)
build_int128(env)
link_tbb(env)
1 change: 1 addition & 0 deletions deps/int128
Submodule int128 added at ea0f85
11 changes: 7 additions & 4 deletions src/openvic-simulation/core/template/Concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,12 @@ namespace OpenVic {
{ t.get_name() } -> std::same_as<std::string_view>;
};

template<typename T>
concept is_strongly_typed = derived_from_specialization_of<T, type_safe::strong_typedef>;

template<typename T>
concept has_index = requires { typename T::index_t; } &&
derived_from_specialization_of<typename T::index_t, type_safe::strong_typedef> && requires {
is_strongly_typed<typename T::index_t> && requires {
static_cast<std::size_t>(
static_cast<type_safe::underlying_type<decltype(std::declval<T>().index)>>(std::declval<T>().index)
);
Expand Down Expand Up @@ -222,8 +225,8 @@ namespace OpenVic {
{ lhs /= rhs } -> std::same_as<Lhs&>;
};

template<typename Lhs, typename A, typename B>
concept mul_add_assignable = requires(Lhs& lhs, const A a, const B b) {
{ lhs += a * b } -> std::same_as<Lhs&>;
template<typename Lhs, typename Rhs = Lhs>
concept equalable = requires(Lhs const& lhs, Rhs const& rhs) {
{ lhs == rhs } -> std::convertible_to<bool>;
};
}
122 changes: 71 additions & 51 deletions src/openvic-simulation/country/CountryInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
#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/population/PopSum.hpp"
#include "openvic-simulation/types/UnitBranchType.hpp"
#include "openvic-simulation/utility/Containers.hpp"
#include "openvic-simulation/utility/Logger.hpp"
Expand Down Expand Up @@ -1341,8 +1342,8 @@ void CountryInstance::_update_budget() {
OpenVic immediately updates both.
*/

pop_size_t total_non_colonial_population = 0;
pop_size_t administrators = 0;
pop_sum_t total_non_colonial_population = 0;
pop_sum_t administrators = 0;
for (State const* const state_ptr : states) {
if (state_ptr == nullptr) {
continue;
Expand All @@ -1353,7 +1354,7 @@ void CountryInstance::_update_budget() {
continue;
}

IndexedFlatMap<PopType, pop_size_t> const& state_population_by_type = state.get_population_by_type();
IndexedFlatMap<PopType, pop_sum_t> const& state_population_by_type = state.get_population_by_type();

for (auto const& [pop_type, size] : state_population_by_type) {
if (pop_type.is_administrator) {
Expand All @@ -1367,18 +1368,24 @@ void CountryInstance::_update_budget() {
administrative_efficiency_from_administrators.set(fixed_point_t::_1);
administrator_percentage.set(fixed_point_t::_0);
} else {
administrator_percentage.set(fixed_point_t(administrators) / total_non_colonial_population);

const fixed_point_t desired_administrators = desired_administrator_percentage.get_untracked() * total_non_colonial_population;
const fixed_point_t administrative_efficiency_from_administrators_unclamped = std::min(
fixed_point_t::mul_div(
administrators,
fixed_point_t::_1 + get_modifier_effect_value(*modifier_effect_cache.get_administrative_efficiency()),
desired_administrators
)
* (fixed_point_t::_1 + get_modifier_effect_value(*modifier_effect_cache.get_administrative_efficiency_modifier())),
fixed_point_t::_1
administrator_percentage.set(fixed_point_t::from_fraction(administrators, total_non_colonial_population));

const pop_sum_t desired_administrators = fixed_point_t::multiply_truncate(
total_non_colonial_population,
desired_administrator_percentage.get_untracked()
);
const pop_sum_t effective_administrators = fixed_point_t::multiply_truncate(
administrators,
fixed_point_t::_1 + get_modifier_effect_value(*modifier_effect_cache.get_administrative_efficiency())
);
const fixed_point_t administrative_efficiency_from_administrators_unclamped =
desired_administrators == 0
? fixed_point_t::_1
: std::min(
fixed_point_t::from_fraction(effective_administrators, desired_administrators)
* (fixed_point_t::_1 + get_modifier_effect_value(*modifier_effect_cache.get_administrative_efficiency_modifier())),
fixed_point_t::_1
);

administrative_efficiency_from_administrators.set(
game_rules_manager.get_prevent_negative_administration_efficiency()
Expand All @@ -1387,36 +1394,42 @@ void CountryInstance::_update_budget() {
);
}

fixed_point_t projected_administration_spending_unscaled_by_slider_running_total = 0;
fixed_point_t projected_education_spending_unscaled_by_slider_running_total = 0;
fixed_point_t projected_military_spending_unscaled_by_slider_running_total = 0;
fixed_point_t projected_pensions_spending_unscaled_by_slider_running_total = 0;
fixed_point_t projected_unemployment_subsidies_spending_unscaled_by_slider_running_total = 0;
int64_t projected_administration_spending_unscaled_by_slider_running_total = 0;
int64_t projected_education_spending_unscaled_by_slider_running_total = 0;
int64_t projected_military_spending_unscaled_by_slider_running_total = 0;
int64_t projected_pensions_spending_unscaled_by_slider_running_total = 0;
int64_t projected_unemployment_subsidies_spending_unscaled_by_slider_running_total = 0;

for (auto const& [pop_type, size] : get_population_by_type()) {
projected_administration_spending_unscaled_by_slider_running_total += size * administration_salary_base_by_pop_type.at(pop_type).get_untracked();
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)
* calculate_unemployment_subsidies_base(pop_type);
}

projected_administration_spending_unscaled_by_slider.set(
projected_administration_spending_unscaled_by_slider_running_total / Pop::size_denominator
);
projected_education_spending_unscaled_by_slider.set(
projected_education_spending_unscaled_by_slider_running_total / Pop::size_denominator
);
projected_military_spending_unscaled_by_slider.set(
projected_military_spending_unscaled_by_slider_running_total / Pop::size_denominator
);
projected_pensions_spending_unscaled_by_slider.set(
projected_pensions_spending_unscaled_by_slider_running_total / Pop::size_denominator
);
projected_unemployment_subsidies_spending_unscaled_by_slider.set(
projected_unemployment_subsidies_spending_unscaled_by_slider_running_total / Pop::size_denominator
);
for (auto const& [pop_type, pop_size] : get_population_by_type()) {
const int64_t size = type_safe::get(pop_size);
projected_administration_spending_unscaled_by_slider_running_total += size * administration_salary_base_by_pop_type.at(pop_type).get_untracked().get_raw_value();
projected_education_spending_unscaled_by_slider_running_total += size * education_salary_base_by_pop_type.at(pop_type).get_untracked().get_raw_value();
projected_military_spending_unscaled_by_slider_running_total += size * military_salary_base_by_pop_type.at(pop_type).get_untracked().get_raw_value();
projected_pensions_spending_unscaled_by_slider_running_total += size * calculate_pensions_base(pop_type).get_raw_value();
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).get_raw_value();
}

projected_administration_spending_unscaled_by_slider.set(fixed_point_t::from_fraction(
projected_administration_spending_unscaled_by_slider_running_total,
type_safe::get(Pop::size_denominator)
));
projected_education_spending_unscaled_by_slider.set(fixed_point_t::from_fraction(
projected_education_spending_unscaled_by_slider_running_total,
type_safe::get(Pop::size_denominator)
));
projected_military_spending_unscaled_by_slider.set(fixed_point_t::from_fraction(
projected_military_spending_unscaled_by_slider_running_total,
type_safe::get(Pop::size_denominator)
));
projected_pensions_spending_unscaled_by_slider.set(fixed_point_t::from_fraction(
projected_pensions_spending_unscaled_by_slider_running_total,
type_safe::get(Pop::size_denominator)
));
projected_unemployment_subsidies_spending_unscaled_by_slider.set(fixed_point_t::from_fraction(
projected_unemployment_subsidies_spending_unscaled_by_slider_running_total,
type_safe::get(Pop::size_denominator)
));
}

fixed_point_t CountryInstance::calculate_pensions_base(PopType const& pop_type) {
Expand Down Expand Up @@ -1498,9 +1511,18 @@ void CountryInstance::_update_population() {

for (auto const& [pop_type, pop_size] : get_population_by_type()) {
if (pop_type.research_leadership_optimum > 0 && pop_size > 0) {
const fixed_point_t factor = std::min(
pop_size / (get_total_population() * pop_type.research_leadership_optimum), fixed_point_t::_1
const pop_sum_t optimum_size = fixed_point_t::multiply_truncate(
get_total_population(),
pop_type.research_leadership_optimum
);
const fixed_point_t factor = optimum_size == 0
? fixed_point_t::_1
: std::min(
fixed_point_t::from_fraction(
pop_size,
optimum_size
), fixed_point_t::_1
);

if (pop_type.research_points != 0) {
const fixed_point_t research_points = pop_type.research_points * factor;
Expand Down Expand Up @@ -1634,11 +1656,9 @@ void CountryInstance::_update_military() {
naval_unit_start_experience += get_modifier_effect_value(*modifier_effect_cache.get_naval_unit_start_experience());

recruit_time = fixed_point_t::_1 + get_modifier_effect_value(*modifier_effect_cache.get_unit_recruitment_time());
combat_width = combat_width_t(
(
type_safe::get(military_defines.get_base_combat_width())
+ get_modifier_effect_value(*modifier_effect_cache.get_combat_width_additive())
).floor<type_safe::underlying_type<combat_width_t>>()
combat_width = fixed_point_t::multiply_truncate(
military_defines.get_base_combat_width(),
get_modifier_effect_value(*modifier_effect_cache.get_combat_width_additive())
);
dig_in_cap = get_modifier_effect_value(*modifier_effect_cache.get_dig_in_cap()).floor<int32_t>();
military_tactics = military_defines.get_base_military_tactics() +
Expand Down
4 changes: 2 additions & 2 deletions src/openvic-simulation/dataloader/Dataloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,11 @@ string_set_t Dataloader::lookup_dirs_in_dir(std::string_view path) const {
return ret;
}

template<std::derived_from<detail::BasicParser> Parser, bool (*parse_func)(Parser&)>
template<std::derived_from<ovdl::detail::BasicParser> Parser, bool (*parse_func)(Parser&)>
static Parser _run_ovdl_parser(fs::path const& path) {
Parser parser;
memory::string buffer;
auto error_log_stream = detail::make_callback_stream<char>(
auto error_log_stream = ovdl::detail::make_callback_stream<char>(
[](void const* s, std::streamsize n, void* user_data) -> std::streamsize {
if (s != nullptr && n > 0 && user_data != nullptr) {
static_cast<memory::string*>(user_data)->append(static_cast<char const*>(s), n);
Expand Down
52 changes: 40 additions & 12 deletions src/openvic-simulation/dataloader/NodeTools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,21 +199,49 @@ using namespace std::string_view_literals;
return expect_uint(callback, base);
}

template<derived_from_specialization_of<type_safe::strong_typedef> T, typename AsT = type_safe::underlying_type<T>>
NodeCallback auto expect_strong_typedef(callback_t<T>& callback, int base = 10) {
if constexpr (std::unsigned_integral<AsT>) {
return expect_uint64(
[callback](uint64_t val) mutable -> bool {
if (val <= static_cast<uint64_t>(std::numeric_limits<AsT>::max())) {
return callback(T(val));
}
spdlog::error_s(
"Invalid uint: {} (valid range: [0, {}])", val,
static_cast<uint64_t>(std::numeric_limits<AsT>::max())
);
return false;
},
base
);
} else {
return expect_int64(
[callback](int64_t val) mutable -> bool {
if (val >= static_cast<int64_t>(std::numeric_limits<AsT>::min()) &&
val <= static_cast<int64_t>(std::numeric_limits<AsT>::max())) {
return callback(T(val));
}
spdlog::error_s(
"Invalid int: {} (valid range: [{}, {}])", val,
static_cast<int64_t>(std::numeric_limits<AsT>::min()),
static_cast<int64_t>(std::numeric_limits<AsT>::max())
);
return false;
},
base
);
}
}
template<derived_from_specialization_of<type_safe::strong_typedef> T, typename AsT = type_safe::underlying_type<T>>
NodeCallback auto expect_strong_typedef(callback_t<T>&& callback, int base = 10) {
return expect_strong_typedef<T, AsT>(callback, base);
}

template<derived_from_specialization_of<type_safe::strong_typedef> T>
requires std::unsigned_integral<type_safe::underlying_type<T>>
NodeCallback auto expect_index(callback_t<T>& callback, int base = 10) {
using underlying_type = type_safe::underlying_type<T>;

return expect_uint64([callback](uint64_t val) mutable -> bool {
if (val <= static_cast<uint64_t>(std::numeric_limits<underlying_type>::max())) {
return callback(T(val));
}
spdlog::error_s(
"Invalid uint: {} (valid range: [0, {}])",
val, static_cast<uint64_t>(std::numeric_limits<underlying_type>::max())
);
return false;
}, base);
return expect_strong_typedef<T>(callback, base);
}
template<derived_from_specialization_of<type_safe::strong_typedef> T>
requires std::unsigned_integral<type_safe::underlying_type<T>>
Expand Down
11 changes: 3 additions & 8 deletions src/openvic-simulation/defines/MilitaryDefines.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include "MilitaryDefines.hpp"

#include <cstdint>

#include "openvic-simulation/military/CombatWidth.hpp"

#include <type_safe/strong_typedef.hpp>
Expand All @@ -20,12 +18,9 @@ node_callback_t MilitaryDefines::expect_defines() {
"DIG_IN_INCREASE_EACH_DAYS", ONE_EXACTLY, expect_days(assign_variable_callback(dig_in_increase_each_days)),
"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_int<int8_t>([this](int8_t val)->bool{
base_combat_width = combat_width_t(static_cast<type_safe::underlying_type<combat_width_t>>(val));
return true;
}),
"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)),
"BASE_COMBAT_WIDTH", ONE_EXACTLY, expect_strong_typedef<combat_width_t>(assign_variable_callback(base_combat_width)),
"POP_MIN_SIZE_FOR_REGIMENT", ONE_EXACTLY, expect_strong_typedef<pop_size_t>(assign_variable_callback(min_pop_size_for_regiment)),
"POP_SIZE_PER_REGIMENT", ONE_EXACTLY, expect_strong_typedef<pop_size_t>(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)),
Expand Down
2 changes: 1 addition & 1 deletion src/openvic-simulation/defines/MilitaryDefines.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "openvic-simulation/military/CombatWidth.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 {
Expand Down
4 changes: 2 additions & 2 deletions src/openvic-simulation/defines/PopsDefines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<pop_sum_t>(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<pop_sum_t>(assign_variable_callback(large_population_influence_penalty_chunk))
);
}
6 changes: 3 additions & 3 deletions src/openvic-simulation/defines/PopsDefines.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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/PopSum.hpp"
#include "openvic-simulation/types/ProvinceLifeRating.hpp"
#include "openvic-simulation/utility/Getters.hpp"

Expand Down Expand Up @@ -71,8 +71,8 @@ namespace OpenVic {
fixed_point_t PROPERTY(nationalist_movement_mil_cap);
fixed_point_t PROPERTY(movement_support_uh_factor);
fixed_point_t PROPERTY(rebel_occupation_strength_bonus);
pop_size_t PROPERTY(large_population_limit, 0);
pop_size_t PROPERTY(large_population_influence_penalty_chunk, 0);
pop_sum_t PROPERTY(large_population_limit, 0);
pop_sum_t PROPERTY(large_population_influence_penalty_chunk, 0);

PopsDefines();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,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;
Expand Down Expand Up @@ -494,7 +494,7 @@ fixed_point_t ArtisanalProducer::calculate_production_type_score(
k * fixed_point_t::mul_div(costs, costs, revenue)
-(1+k)*costs
+ revenue
) * Pop::size_denominator / workforce; //factor out pop size without making values too small
).mul_div(Pop::size_denominator, workforce); //factor out pop size without making values too small
}

ProductionType const* ArtisanalProducer::pick_production_type(
Expand Down
Loading