Skip to content

Commit 68a345c

Browse files
committed
Make fixed_point_t & pop_sum_t compatible
1 parent 84debe8 commit 68a345c

File tree

13 files changed

+245
-205
lines changed

13 files changed

+245
-205
lines changed

src/openvic-simulation/core/template/Concepts.hpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,12 @@ namespace OpenVic {
108108
{ t.get_name() } -> std::same_as<std::string_view>;
109109
};
110110

111+
template<typename T>
112+
concept is_strongly_typed = derived_from_specialization_of<T, type_safe::strong_typedef>;
113+
111114
template<typename T>
112115
concept has_index = requires { typename T::index_t; } &&
113-
derived_from_specialization_of<typename T::index_t, type_safe::strong_typedef> && requires {
116+
is_strongly_typed<typename T::index_t> && requires {
114117
static_cast<std::size_t>(
115118
static_cast<type_safe::underlying_type<decltype(std::declval<T>().index)>>(std::declval<T>().index)
116119
);
@@ -222,11 +225,6 @@ namespace OpenVic {
222225
{ lhs /= rhs } -> std::same_as<Lhs&>;
223226
};
224227

225-
template<typename Lhs, typename A, typename B>
226-
concept mul_add_assignable = requires(Lhs& lhs, const A a, const B b) {
227-
{ lhs += a * b } -> std::same_as<Lhs&>;
228-
};
229-
230228
template<typename Lhs, typename Rhs = Lhs>
231229
concept equalable = requires(Lhs const& lhs, Rhs const& rhs) {
232230
{ lhs == rhs } -> std::convertible_to<bool>;

src/openvic-simulation/country/CountryInstance.cpp

Lines changed: 63 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,18 +1368,24 @@ void CountryInstance::_update_budget() {
13681368
administrative_efficiency_from_administrators.set(fixed_point_t::_1);
13691369
administrator_percentage.set(fixed_point_t::_0);
13701370
} else {
1371-
administrator_percentage.set(fixed_point_t(administrators) / total_non_colonial_population);
1372-
1373-
const fixed_point_t desired_administrators = desired_administrator_percentage.get_untracked() * type_safe::get(total_non_colonial_population);
1374-
const fixed_point_t administrative_efficiency_from_administrators_unclamped = std::min(
1375-
fixed_point_t::mul_div(
1376-
type_safe::get(administrators),
1377-
fixed_point_t::_1 + get_modifier_effect_value(*modifier_effect_cache.get_administrative_efficiency()),
1378-
desired_administrators
1379-
)
1380-
* (fixed_point_t::_1 + get_modifier_effect_value(*modifier_effect_cache.get_administrative_efficiency_modifier())),
1381-
fixed_point_t::_1
1371+
administrator_percentage.set(fixed_point_t::from_fraction(administrators, total_non_colonial_population));
1372+
1373+
const pop_sum_t desired_administrators = fixed_point_t::multiply_truncate(
1374+
total_non_colonial_population,
1375+
desired_administrator_percentage.get_untracked()
13821376
);
1377+
const pop_sum_t effective_administrators = fixed_point_t::multiply_truncate(
1378+
administrators,
1379+
fixed_point_t::_1 + get_modifier_effect_value(*modifier_effect_cache.get_administrative_efficiency())
1380+
);
1381+
const fixed_point_t administrative_efficiency_from_administrators_unclamped =
1382+
desired_administrators == 0
1383+
? fixed_point_t::_1
1384+
: std::min(
1385+
fixed_point_t::from_fraction(effective_administrators, desired_administrators)
1386+
* (fixed_point_t::_1 + get_modifier_effect_value(*modifier_effect_cache.get_administrative_efficiency_modifier())),
1387+
fixed_point_t::_1
1388+
);
13831389

13841390
administrative_efficiency_from_administrators.set(
13851391
game_rules_manager.get_prevent_negative_administration_efficiency()
@@ -1388,36 +1394,42 @@ void CountryInstance::_update_budget() {
13881394
);
13891395
}
13901396

1391-
fixed_point_t projected_administration_spending_unscaled_by_slider_running_total = 0;
1392-
fixed_point_t projected_education_spending_unscaled_by_slider_running_total = 0;
1393-
fixed_point_t projected_military_spending_unscaled_by_slider_running_total = 0;
1394-
fixed_point_t projected_pensions_spending_unscaled_by_slider_running_total = 0;
1395-
fixed_point_t projected_unemployment_subsidies_spending_unscaled_by_slider_running_total = 0;
1397+
int64_t projected_administration_spending_unscaled_by_slider_running_total = 0;
1398+
int64_t projected_education_spending_unscaled_by_slider_running_total = 0;
1399+
int64_t projected_military_spending_unscaled_by_slider_running_total = 0;
1400+
int64_t projected_pensions_spending_unscaled_by_slider_running_total = 0;
1401+
int64_t projected_unemployment_subsidies_spending_unscaled_by_slider_running_total = 0;
13961402

1397-
for (auto const& [pop_type, size] : get_population_by_type()) {
1398-
projected_administration_spending_unscaled_by_slider_running_total += size * administration_salary_base_by_pop_type.at(pop_type).get_untracked();
1399-
projected_education_spending_unscaled_by_slider_running_total += size * education_salary_base_by_pop_type.at(pop_type).get_untracked();
1400-
projected_military_spending_unscaled_by_slider_running_total += size * military_salary_base_by_pop_type.at(pop_type).get_untracked();
1401-
projected_pensions_spending_unscaled_by_slider_running_total += size * calculate_pensions_base(pop_type);
1403+
for (auto const& [pop_type, pop_size] : get_population_by_type()) {
1404+
const int64_t size = type_safe::get(pop_size);
1405+
projected_administration_spending_unscaled_by_slider_running_total += size * administration_salary_base_by_pop_type.at(pop_type).get_untracked().get_raw_value();
1406+
projected_education_spending_unscaled_by_slider_running_total += size * education_salary_base_by_pop_type.at(pop_type).get_untracked().get_raw_value();
1407+
projected_military_spending_unscaled_by_slider_running_total += size * military_salary_base_by_pop_type.at(pop_type).get_untracked().get_raw_value();
1408+
projected_pensions_spending_unscaled_by_slider_running_total += size * calculate_pensions_base(pop_type).get_raw_value();
14021409
projected_unemployment_subsidies_spending_unscaled_by_slider_running_total += type_safe::get(get_unemployed_pops_by_type(pop_type))
1403-
* calculate_unemployment_subsidies_base(pop_type);
1410+
* calculate_unemployment_subsidies_base(pop_type).get_raw_value();
14041411
}
14051412

1406-
projected_administration_spending_unscaled_by_slider.set(
1407-
projected_administration_spending_unscaled_by_slider_running_total / Pop::size_denominator
1408-
);
1409-
projected_education_spending_unscaled_by_slider.set(
1410-
projected_education_spending_unscaled_by_slider_running_total / Pop::size_denominator
1411-
);
1412-
projected_military_spending_unscaled_by_slider.set(
1413-
projected_military_spending_unscaled_by_slider_running_total / Pop::size_denominator
1414-
);
1415-
projected_pensions_spending_unscaled_by_slider.set(
1416-
projected_pensions_spending_unscaled_by_slider_running_total / Pop::size_denominator
1417-
);
1418-
projected_unemployment_subsidies_spending_unscaled_by_slider.set(
1419-
projected_unemployment_subsidies_spending_unscaled_by_slider_running_total / Pop::size_denominator
1420-
);
1413+
projected_administration_spending_unscaled_by_slider.set(fixed_point_t::from_fraction(
1414+
projected_administration_spending_unscaled_by_slider_running_total,
1415+
type_safe::get(Pop::size_denominator)
1416+
));
1417+
projected_education_spending_unscaled_by_slider.set(fixed_point_t::from_fraction(
1418+
projected_education_spending_unscaled_by_slider_running_total,
1419+
type_safe::get(Pop::size_denominator)
1420+
));
1421+
projected_military_spending_unscaled_by_slider.set(fixed_point_t::from_fraction(
1422+
projected_military_spending_unscaled_by_slider_running_total,
1423+
type_safe::get(Pop::size_denominator)
1424+
));
1425+
projected_pensions_spending_unscaled_by_slider.set(fixed_point_t::from_fraction(
1426+
projected_pensions_spending_unscaled_by_slider_running_total,
1427+
type_safe::get(Pop::size_denominator)
1428+
));
1429+
projected_unemployment_subsidies_spending_unscaled_by_slider.set(fixed_point_t::from_fraction(
1430+
projected_unemployment_subsidies_spending_unscaled_by_slider_running_total,
1431+
type_safe::get(Pop::size_denominator)
1432+
));
14211433
}
14221434

14231435
fixed_point_t CountryInstance::calculate_pensions_base(PopType const& pop_type) {
@@ -1499,9 +1511,18 @@ void CountryInstance::_update_population() {
14991511

15001512
for (auto const& [pop_type, pop_size] : get_population_by_type()) {
15011513
if (pop_type.research_leadership_optimum > 0 && pop_size > 0) {
1502-
const fixed_point_t factor = std::min(
1503-
pop_size / (get_total_population() * pop_type.research_leadership_optimum), fixed_point_t::_1
1514+
const pop_sum_t optimum_size = fixed_point_t::multiply_truncate(
1515+
get_total_population(),
1516+
pop_type.research_leadership_optimum
15041517
);
1518+
const fixed_point_t factor = optimum_size == 0
1519+
? fixed_point_t::_1
1520+
: std::min(
1521+
fixed_point_t::from_fraction(
1522+
pop_size,
1523+
optimum_size
1524+
), fixed_point_t::_1
1525+
);
15051526

15061527
if (pop_type.research_points != 0) {
15071528
const fixed_point_t research_points = pop_type.research_points * factor;
@@ -1635,11 +1656,9 @@ void CountryInstance::_update_military() {
16351656
naval_unit_start_experience += get_modifier_effect_value(*modifier_effect_cache.get_naval_unit_start_experience());
16361657

16371658
recruit_time = fixed_point_t::_1 + get_modifier_effect_value(*modifier_effect_cache.get_unit_recruitment_time());
1638-
combat_width = combat_width_t(
1639-
(
1640-
type_safe::get(military_defines.get_base_combat_width())
1641-
+ get_modifier_effect_value(*modifier_effect_cache.get_combat_width_additive())
1642-
).floor<type_safe::underlying_type<combat_width_t>>()
1659+
combat_width = fixed_point_t::multiply_truncate(
1660+
military_defines.get_base_combat_width(),
1661+
get_modifier_effect_value(*modifier_effect_cache.get_combat_width_additive())
16431662
);
16441663
dig_in_cap = get_modifier_effect_value(*modifier_effect_cache.get_dig_in_cap()).floor<int32_t>();
16451664
military_tactics = military_defines.get_base_military_tactics() +

src/openvic-simulation/economy/production/ArtisanalProducer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ std::optional<fixed_point_t> ArtisanalProducer::estimate_production_type_score(
479479
fixed_point_t ArtisanalProducer::calculate_production_type_score(
480480
const fixed_point_t revenue,
481481
const fixed_point_t costs,
482-
const pop_sum_t workforce
482+
const pop_size_t workforce
483483
) {
484484
if (costs >= revenue) {
485485
return 0;
@@ -494,7 +494,7 @@ fixed_point_t ArtisanalProducer::calculate_production_type_score(
494494
k * fixed_point_t::mul_div(costs, costs, revenue)
495495
-(1+k)*costs
496496
+ revenue
497-
) * Pop::size_denominator / workforce; //factor out pop size without making values too small
497+
).mul_div(Pop::size_denominator, workforce); //factor out pop size without making values too small
498498
}
499499

500500
ProductionType const* ArtisanalProducer::pick_production_type(

src/openvic-simulation/economy/production/ArtisanalProducer.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ namespace OpenVic {
2323
struct ProvinceInstance;
2424
struct RandomU32;
2525
struct pop_size_t;
26-
struct pop_sum_t;
2726

2827
struct ArtisanalProducer {
2928
private:
@@ -49,7 +48,7 @@ namespace OpenVic {
4948
static fixed_point_t calculate_production_type_score(
5049
const fixed_point_t revenue,
5150
const fixed_point_t costs,
52-
const pop_sum_t workforce
51+
const pop_size_t workforce
5352
);
5453

5554
public:

src/openvic-simulation/economy/production/ProductionType.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ ProductionType::ProductionType(
2929
const std::optional<Job> new_owner,
3030
memory::vector<Job>&& new_jobs,
3131
const template_type_t new_template_type,
32-
const pop_sum_t new_base_workforce_size,
32+
const pop_size_t new_base_workforce_size,
3333
fixed_point_map_t<GoodDefinition const*>&& new_input_goods,
3434
GoodDefinition const& new_output_good,
3535
const fixed_point_t new_base_output_quantity,
@@ -140,7 +140,7 @@ bool ProductionTypeManager::add_production_type(
140140
std::optional<Job> owner,
141141
memory::vector<Job>&& jobs,
142142
const ProductionType::template_type_t template_type,
143-
const pop_sum_t base_workforce_size,
143+
const pop_size_t base_workforce_size,
144144
fixed_point_map_t<GoodDefinition const*>&& input_goods,
145145
GoodDefinition const* const output_good,
146146
const fixed_point_t base_output_quantity,
@@ -328,7 +328,7 @@ bool ProductionTypeManager::load_production_types_file(
328328
memory::vector<Job> jobs;
329329
ProductionType::template_type_t template_type { FACTORY };
330330
GoodDefinition const* output_good = nullptr;
331-
pop_sum_t base_workforce_size = 0;
331+
pop_size_t base_workforce_size = 0;
332332
fixed_point_map_t<GoodDefinition const*> input_goods, maintenance_requirements;
333333
fixed_point_t base_output_quantity = 0;
334334
memory::vector<ProductionType::bonus_t> bonuses;

src/openvic-simulation/economy/production/ProductionType.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include "openvic-simulation/types/IdentifierRegistry.hpp"
77
#include "openvic-simulation/types/IndexedFlatMap.hpp"
88
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
9-
#include "openvic-simulation/population/PopSum.hpp"
9+
#include "openvic-simulation/population/PopSize.hpp"
1010
#include "openvic-simulation/types/PopSprite.hpp"
1111
#include "openvic-simulation/utility/Containers.hpp"
1212

@@ -65,7 +65,7 @@ namespace OpenVic {
6565
public:
6666
GoodDefinition const& output_good;
6767
const template_type_t template_type;
68-
const pop_sum_t base_workforce_size;
68+
const pop_size_t base_workforce_size;
6969
const fixed_point_t base_output_quantity;
7070

7171
ProductionType(
@@ -74,7 +74,7 @@ namespace OpenVic {
7474
const std::optional<Job> new_owner,
7575
memory::vector<Job>&& new_jobs,
7676
const template_type_t new_template_type,
77-
const pop_sum_t new_base_workforce_size,
77+
const pop_size_t new_base_workforce_size,
7878
fixed_point_map_t<GoodDefinition const*>&& new_input_goods,
7979
GoodDefinition const& new_output_good,
8080
const fixed_point_t new_base_output_quantity,
@@ -123,7 +123,7 @@ namespace OpenVic {
123123
std::optional<Job> owner,
124124
memory::vector<Job>&& jobs,
125125
const ProductionType::template_type_t template_type,
126-
const pop_sum_t base_workforce_size,
126+
const pop_size_t base_workforce_size,
127127
fixed_point_map_t<GoodDefinition const*>&& input_goods,
128128
GoodDefinition const* const output_good,
129129
const fixed_point_t base_output_quantity,

src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ ResourceGatheringOperation::ResourceGatheringOperation(
4444
0, {}
4545
} {}
4646

47-
pop_sum_t ResourceGatheringOperation::get_employee_count_per_type_cache(PopType const& key) const {
47+
pop_size_t ResourceGatheringOperation::get_employee_count_per_type_cache(PopType const& key) const {
4848
return employee_count_per_type_cache.at(key);
4949
}
5050

@@ -73,11 +73,19 @@ void ResourceGatheringOperation::initialise_rgo_size_multiplier() {
7373
}
7474

7575
const fixed_point_t size_modifier = calculate_size_modifier();
76-
const fixed_point_t base_workforce_size = type_safe::get(production_type.base_workforce_size);
76+
const pop_size_t base_workforce_size = production_type.base_workforce_size;
7777
if (size_modifier == 0) {
7878
size_multiplier = 0;
7979
} else {
80-
size_multiplier = ((total_worker_count_in_province / (size_modifier * base_workforce_size)).ceil() * fixed_point_t::_1_50).floor();
80+
size_multiplier = (
81+
(
82+
fixed_point_t::from_fraction<pop_sum_t>(
83+
total_worker_count_in_province,
84+
base_workforce_size
85+
) / size_modifier
86+
).ceil()
87+
* fixed_point_t::_1_50
88+
).floor();
8189
}
8290

8391
max_employee_count_cache = (size_modifier * size_multiplier * base_workforce_size).floor<type_safe::underlying_type<pop_size_t>>();
@@ -189,8 +197,7 @@ void ResourceGatheringOperation::hire() {
189197
proportion_to_hire = 1;
190198
} else {
191199
//hire all pops proportionally
192-
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);
193-
proportion_to_hire = max_worker_count_real / available_worker_count_real;
200+
proportion_to_hire = fixed_point_t::from_fraction<pop_sum_t>(max_employee_count_cache, available_worker_count);
194201
}
195202

196203
std::span<const Job> jobs = production_type.get_jobs();
@@ -248,10 +255,16 @@ fixed_point_t ResourceGatheringOperation::produce() {
248255
if (total_owner_count_in_state_cache > 0) {
249256
switch (owner_job.get_effect_type()) {
250257
case Job::effect_t::OUTPUT:
251-
output_multiplier += owner_job.get_effect_multiplier() * total_owner_count_in_state_cache / state_population;
258+
output_multiplier += owner_job.get_effect_multiplier().mul_div(
259+
total_owner_count_in_state_cache,
260+
state_population
261+
);
252262
break;
253263
case Job::effect_t::THROUGHPUT:
254-
throughput_multiplier += owner_job.get_effect_multiplier() * total_owner_count_in_state_cache / state_population;
264+
throughput_multiplier += owner_job.get_effect_multiplier().mul_div(
265+
total_owner_count_in_state_cache,
266+
state_population
267+
);
255268
break;
256269
default:
257270
spdlog::error_s("Invalid job effect in RGO {}", production_type);
@@ -307,18 +320,18 @@ fixed_point_t ResourceGatheringOperation::produce() {
307320
}
308321

309322
const fixed_point_t effect_multiplier = job.get_effect_multiplier();
310-
fixed_point_t relative_to_workforce =
311-
fixed_point_t(employees_of_type) / fixed_point_t(max_employee_count_cache);
312323
const fixed_point_t amount = job.get_amount();
313-
if (effect_multiplier != fixed_point_t::_1 && relative_to_workforce > amount) {
314-
relative_to_workforce = amount;
315-
}
324+
const fixed_point_t effect = effect_multiplier != fixed_point_t::_1
325+
&& fixed_point_t::from_fraction(employees_of_type, max_employee_count_cache) > amount
326+
? effect_multiplier * amount //special Vic2 logic
327+
: effect_multiplier.mul_div(employees_of_type, max_employee_count_cache);
328+
316329
switch (job.get_effect_type()) {
317330
case Job::effect_t::OUTPUT:
318-
output_from_workers += effect_multiplier * relative_to_workforce;
331+
output_from_workers += effect;
319332
break;
320333
case Job::effect_t::THROUGHPUT:
321-
throughput_from_workers += effect_multiplier * relative_to_workforce;
334+
throughput_from_workers += effect;
322335
break;
323336
default:
324337
spdlog::error_s("Invalid job effect in RGO {}", production_type);
@@ -382,14 +395,14 @@ void ResourceGatheringOperation::pay_employees(memory::vector<fixed_point_t>& re
382395
fixed_point_t::_1 - total_minimum_wage / revenue_left
383396
);
384397
const fixed_point_t owner_share = std::min(
385-
fixed_point_t::_2 * total_owner_count_in_state_cache / total_worker_count_in_province_cache,
398+
fixed_point_t::from_fraction(2 * total_owner_count_in_state_cache, total_worker_count_in_province_cache),
386399
upper_limit
387400
);
388401

389402
for (Pop* owner_pop_ptr : *owner_pops_cache_nullable) {
390403
Pop& owner_pop = *owner_pop_ptr;
391404
const fixed_point_t income_for_this_pop = std::max(
392-
revenue_left * (owner_share * owner_pop.get_size()) / total_owner_count_in_state_cache,
405+
revenue_left * owner_share.mul_div<pop_sum_t>(owner_pop.get_size(), total_owner_count_in_state_cache),
393406
fixed_point_t::epsilon //revenue > 0 is already checked, so rounding up
394407
);
395408
owner_pop.add_rgo_owner_income(income_for_this_pop);
@@ -405,7 +418,7 @@ void ResourceGatheringOperation::pay_employees(memory::vector<fixed_point_t>& re
405418
memory::vector<fixed_point_t>& incomes = reusable_vector;
406419
incomes.resize(employees.size());
407420

408-
pop_sum_t count_workers_to_be_paid = total_paid_employees_count_cache;
421+
pop_size_t count_workers_to_be_paid = total_paid_employees_count_cache;
409422
for (size_t i = 0; i < employees.size(); i++) {
410423
Employee& employee = employees[i];
411424
Pop& employee_pop = employee.get_pop();
@@ -427,7 +440,7 @@ void ResourceGatheringOperation::pay_employees(memory::vector<fixed_point_t>& re
427440

428441
const pop_size_t employee_size = employee.get_size();
429442
const fixed_point_t income_for_this_pop = std::max(
430-
revenue_left * employee_size / count_workers_to_be_paid,
443+
revenue_left.mul_div(employee_size, count_workers_to_be_paid),
431444
fixed_point_t::epsilon //revenue > 0 is already checked, so rounding up
432445
);
433446

0 commit comments

Comments
 (0)