Project Alice
Loading...
Searching...
No Matches
economy.cpp
Go to the documentation of this file.
1#include "economy.hpp"
3#include "demographics.hpp"
4#include "dcon_generated.hpp"
5#include "ai.hpp"
6#include "system_state.hpp"
7#include "prng.hpp"
8#include "math_fns.hpp"
11#include "triggers.hpp"
12
13namespace economy {
14
15enum class economy_reason {
17};
18
19void register_demand(sys::state& state, dcon::nation_id n, dcon::commodity_id commodity_type, float amount, economy_reason reason) {
20 state.world.nation_get_real_demand(n, commodity_type) += amount;
21 state.world.commodity_get_demand_by_category(commodity_type, (int)reason) += amount;
22 assert(std::isfinite(state.world.nation_get_real_demand(n, commodity_type)));
23}
24
25void register_intermediate_demand(sys::state& state, dcon::nation_id n, dcon::commodity_id commodity_type, float amount, economy_reason reason) {
26 register_demand(state, n, commodity_type, amount, reason);
27 state.world.nation_get_intermediate_demand(n, commodity_type) += amount;
28
29 float price = state.world.commodity_get_current_price(commodity_type);
30 float sat = state.world.nation_get_demand_satisfaction(n, commodity_type);
31
32 state.world.nation_get_gdp(n) -= amount * price * sat;
33}
34
35// it's registered as a demand separately
36void register_construction_demand(sys::state& state, dcon::nation_id n, dcon::commodity_id commodity_type, float amount) {
37 state.world.nation_get_construction_demand(n, commodity_type) += amount;
38}
39
40void register_domestic_supply(sys::state& state, dcon::nation_id n, dcon::commodity_id commodity_type, float amount, economy_reason reason) {
41 state.world.nation_get_domestic_market_pool(n, commodity_type) += amount;
42 state.world.nation_get_gdp(n) += amount * state.world.commodity_get_current_price(commodity_type);
43}
44
45template void for_each_new_factory<std::function<void(new_factory)>>(sys::state&, dcon::state_instance_id, std::function<void(new_factory)>&&);
46template void for_each_upgraded_factory<std::function<void(upgraded_factory)>>(sys::state&, dcon::state_instance_id, std::function<void(upgraded_factory)>&&);
47
48bool can_take_loans(sys::state& state, dcon::nation_id n) {
49 if(!state.world.nation_get_is_player_controlled(n) || !state.world.nation_get_is_debt_spending(n))
50 return false;
51
52 /*
53 A country cannot borrow if it is less than define:BANKRUPTCY_EXTERNAL_LOAN_YEARS since their last bankruptcy.
54 */
55 auto last_br = state.world.nation_get_bankrupt_until(n);
56 if(last_br && state.current_date < last_br)
57 return false;
58
59 return true;
60}
61
62float interest_payment(sys::state& state, dcon::nation_id n) {
63 /*
64 Every day, a nation must pay its creditors. It must pay national-modifier-to-loan-interest x debt-amount x interest-to-debt-holder-rate / 30
65 When a nation takes a loan, the interest-to-debt-holder-rate is set at nation-taking-the-loan-technology-loan-interest-modifier + define:LOAN_BASE_INTEREST, with a minimum of 0.01.
66 */
67 auto debt = state.world.nation_get_stockpiles(n, money);
68 if(debt >= 0)
69 return 0.0f;
70
71 return -debt * std::max(0.01f, (state.world.nation_get_modifier_values(n, sys::national_mod_offsets::loan_interest) + 1.0f) * state.defines.loan_base_interest) / 30.0f;
72}
73float max_loan(sys::state& state, dcon::nation_id n) {
74 /*
75 There is an income cap to how much may be borrowed, namely: define:MAX_LOAN_CAP_FROM_BANKS x (national-modifier-to-max-loan-amount + 1) x national-tax-base.
76 */
77 auto mod = (state.world.nation_get_modifier_values(n, sys::national_mod_offsets::max_loan_modifier) + 1.0f);
78 auto total_tax_base = state.world.nation_get_total_rich_income(n) + state.world.nation_get_total_middle_income(n) + state.world.nation_get_total_poor_income(n);
79 return std::max(0.0f, total_tax_base * mod);
80}
81
83 return (state.current_date.value >> 4) % price_history_length;
84}
86 return ((state.current_date.value >> 4) + price_history_length - 1) % price_history_length;
87}
88
90 auto date = state.current_date.to_ymd(state.start_date);
91 return (date.year * 4 + date.month / 3) % gdp_history_length;
92}
94 auto date = state.current_date.to_ymd(state.start_date);
95 return ((date.year * 4 + date.month / 3) + gdp_history_length - 1) % gdp_history_length;
96}
97
98float ideal_pound_conversion_rate(sys::state& state, dcon::nation_id n) {
99 return state.world.nation_get_life_needs_costs(n, state.culture_definitions.primary_factory_worker)
100 + 0.1f * state.world.nation_get_everyday_needs_costs(n, state.culture_definitions.primary_factory_worker);
101}
102
103float gdp_adjusted(sys::state& state, dcon::nation_id n) {
104 float raw = state.world.nation_get_gdp(n);
105 float ideal_pound = ideal_pound_conversion_rate(state, n);
106 return raw / ideal_pound;
107}
108
109float full_spending_cost(sys::state& state, dcon::nation_id n);
113
114float commodity_daily_production_amount(sys::state& state, dcon::commodity_id c) {
115 return state.world.commodity_get_total_production(c);
116}
117
118float stockpile_commodity_daily_increase(sys::state& state, dcon::commodity_id c, dcon::nation_id n) {
119 // TODO
120 return 0.f;
121}
122
123float global_market_commodity_daily_increase(sys::state& state, dcon::commodity_id c) {
124 // TODO
125 return 0.f;
126}
127
128bool has_factory(sys::state const& state, dcon::state_instance_id si) {
129 auto sdef = state.world.state_instance_get_definition(si);
130 auto owner = state.world.state_instance_get_nation_from_state_ownership(si);
131 auto crng = state.world.state_instance_get_state_building_construction(si);
132 if(crng.begin() != crng.end())
133 return true;
134
135 for(auto p : state.world.state_definition_get_abstract_state_membership(sdef)) {
136 if(p.get_province().get_nation_from_province_ownership() == owner) {
137 auto rng = p.get_province().get_factory_location();
138 if(rng.begin() != rng.end())
139 return true;
140 }
141 }
142 return false;
143}
144
145
146
148 state.world.nation_resize_artisan_distribution(state.world.commodity_size());
149 state.world.nation_resize_artisan_actual_production(state.world.commodity_size());
150
151 auto const csize = state.world.commodity_size();
152
153 for(auto n : state.world.in_nation) {
154 for(uint32_t i = 1; i < csize; ++i) {
155 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(i) };
156 auto kf = state.world.commodity_get_key_factory(cid);
157
158 if(state.world.commodity_get_artisan_output_amount(cid) > 0.0f && (state.world.commodity_get_is_available_from_start(cid) || (kf && state.world.nation_get_active_building(n, kf)))) {
159
160 n.set_artisan_distribution(cid, 0.f);
161 }
162 }
163 }
164}
165
166void initialize_needs_weights(sys::state& state, dcon::nation_id n) {
167 {
168 state.world.for_each_commodity([&](dcon::commodity_id c) {
169 auto kf = state.world.commodity_get_key_factory(c);
170 if(state.world.commodity_get_is_life_need(c) && (state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf)))) {
171 auto& w = state.world.nation_get_life_needs_weights(n, c);
172 w = 1.f;
173 }
174 });
175 }
176 {
177 state.world.for_each_commodity([&](dcon::commodity_id c) {
178 auto kf = state.world.commodity_get_key_factory(c);
179 if(state.world.commodity_get_is_everyday_need(c) && (state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf)))) {
180 auto& w = state.world.nation_get_everyday_needs_weights(n, c);
181 w = 1.f;
182 }
183 });
184 }
185 {
186 state.world.for_each_commodity([&](dcon::commodity_id c) {
187 auto kf = state.world.commodity_get_key_factory(c);
188 if(state.world.commodity_get_is_luxury_need(c) && (state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf)))) {
189 auto& w = state.world.nation_get_luxury_needs_weights(n, c);
190 w = 1.f;
191 }
192 });
193 }
194}
195
196float need_weight(sys::state& state, dcon::nation_id n, dcon::commodity_id c) {
197 return 1.0f / math::sqrt(std::max(state.world.commodity_get_current_price(c), 0.001f));
198}
199
200void rebalance_needs_weights(sys::state& state, dcon::nation_id n) {
201 {
202 float total_weights = 0.0f;
203 uint32_t count = 0;
204
205 state.world.for_each_commodity([&](dcon::commodity_id c) {
206 auto kf = state.world.commodity_get_key_factory(c);
207 if(state.world.commodity_get_is_life_need(c) && (state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf)))) {
208 auto weight = need_weight(state, n, c);
209 total_weights += weight;
210 count++;
211 }
212 });
213
214 state.world.for_each_commodity([&](dcon::commodity_id c) {
215 auto kf = state.world.commodity_get_key_factory(c);
216 if(state.world.commodity_get_is_life_need(c) && (state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf)))) {
217 auto weight = need_weight(state, n, c);
218 auto ideal_weighting = weight / total_weights * count;
219 auto& w = state.world.nation_get_life_needs_weights(n, c);
220 w = ideal_weighting * state.defines.alice_need_drift_speed + w * (1.0f - state.defines.alice_need_drift_speed);
221
222 assert(std::isfinite(w));
223 assert(w <= count + 0.01f);
224 }
225 });
226 }
227
228 {
229 float total_weights = 0.0f;
230 uint32_t count = 0;
231
232 state.world.for_each_commodity([&](dcon::commodity_id c) {
233 auto kf = state.world.commodity_get_key_factory(c);
234 if(state.world.commodity_get_is_everyday_need(c) && (state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf)))) {
235 auto weight = need_weight(state, n, c);
236 total_weights += weight;
237 count++;
238 }
239 });
240
241 state.world.for_each_commodity([&](dcon::commodity_id c) {
242 auto kf = state.world.commodity_get_key_factory(c);
243 if(state.world.commodity_get_is_everyday_need(c) && (state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf)))) {
244 auto weight = need_weight(state, n, c);
245 auto ideal_weighting = weight / total_weights * count;
246 auto& w = state.world.nation_get_everyday_needs_weights(n, c);
247 w = ideal_weighting * state.defines.alice_need_drift_speed + w * (1.0f - state.defines.alice_need_drift_speed);
248
249 assert(std::isfinite(w));
250 assert(w <= count + 0.01f);
251 }
252 });
253 }
254
255 {
256 float total_weights = 0.0f;
257 uint32_t count = 0;
258
259 state.world.for_each_commodity([&](dcon::commodity_id c) {
260 auto kf = state.world.commodity_get_key_factory(c);
261 if(state.world.commodity_get_is_luxury_need(c) && (state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf)))) {
262 auto weight = need_weight(state, n, c);
263 total_weights += weight;
264 count++;
265 }
266 });
267
268 state.world.for_each_commodity([&](dcon::commodity_id c) {
269 auto kf = state.world.commodity_get_key_factory(c);
270 if(state.world.commodity_get_is_luxury_need(c) && (state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf)))) {
271 auto weight = need_weight(state, n, c);
272 auto ideal_weighting = weight / total_weights * count;
273 auto& w = state.world.nation_get_luxury_needs_weights(n, c);
274 w = ideal_weighting * state.defines.alice_need_drift_speed + w * (1.0f - state.defines.alice_need_drift_speed);
275
276 assert(std::isfinite(w));
277 assert(w <= count + 0.01f);
278 }
279 });
280 }
281}
282
283
285 sys::state& state,
286 std::vector<float>& buffer_commodities,
287 std::vector<float>& buffer_ingredients,
288 std::vector<float>& buffer_weights
289) {
290 state.world.for_each_commodity([&](dcon::commodity_id c) {
291 float amount = buffer_commodities[c.index()];
292
293 if(state.world.commodity_get_rgo_amount(c) > 0.f) {
294 buffer_ingredients[c.index()] += amount;
295 } else {
296 //calculate input vectors weights:
297 std::vector<float> weights;
298 float total_weight = 0.f;
299 float non_zero_count = 0.f;
300
301 state.world.for_each_factory_type([&](dcon::factory_type_id t) {
302 auto o = state.world.factory_type_get_output(t);
303 if(o == c) {
304 auto& inputs = state.world.factory_type_get_inputs(t);
305
306 float weight_current = 0;
307
308 for(uint32_t i = 0; i < economy::commodity_set::set_size; ++i) {
309 if(inputs.commodity_type[i]) {
310 float weight_input = buffer_weights[inputs.commodity_type[i].index()];
311 total_weight += weight_input;
312 weight_current += weight_input;
313 } else {
314 break;
315 }
316 }
317
318 if(weight_current > 0.f)
319 non_zero_count++;
320
321 weights.push_back(weight_current);
322 }
323 });
324
325 if(total_weight == 0) {
326 for(size_t i = 0; i < weights.size(); i++) {
327 weights[i] = 1.f;
328 total_weight++;
329 }
330 } else {
331 float average_weight = total_weight / non_zero_count;
332 for(size_t i = 0; i < weights.size(); i++) {
333 if(weights[i] == 0.f) {
334 weights[i] = average_weight;
335 total_weight += average_weight;
336 }
337 }
338 }
339
340 //now we have weights and can use them for transformation of output into ingredients:
341 size_t index = 0;
342
343 state.world.for_each_factory_type([&](dcon::factory_type_id t) {
344 auto o = state.world.factory_type_get_output(t);
345 if(o == c) {
346 auto& inputs = state.world.factory_type_get_inputs(t);
347 float output_power = state.world.factory_type_get_output_amount(t);
348
349 float weight_current = weights[index] / total_weight;
350 index++;
351
352 for(uint32_t i = 0; i < economy::commodity_set::set_size; ++i) {
353 if(inputs.commodity_type[i]) {
354
355 buffer_ingredients[inputs.commodity_type[i].index()] += inputs.commodity_amounts[i] * amount / output_power * weight_current;
356
357 float weight_input = buffer_weights[inputs.commodity_type[i].index()];
358 total_weight += weight_input;
359 weight_current += weight_input;
360 } else {
361 break;
362 }
363 }
364 }
365 });
366 }
367 });
368}
369
371 // economic updates without construction
372#ifdef NDEBUG
373 for(uint32_t i = 0; i < 365; i++) {
374#else
375 for(uint32_t i = 0; i < 20; i++) {
376#endif
379 daily_update(state, false);
380 ai::update_budget(state);
381 }
382}
383
384bool has_building(sys::state const& state, dcon::state_instance_id si, dcon::factory_type_id fac) {
385 auto sdef = state.world.state_instance_get_definition(si);
386 auto owner = state.world.state_instance_get_nation_from_state_ownership(si);
387 for(auto p : state.world.state_definition_get_abstract_state_membership(sdef)) {
388 if(p.get_province().get_nation_from_province_ownership() == owner) {
389 for(auto b : p.get_province().get_factory_location()) {
390 if(b.get_factory().get_building_type() == fac)
391 return true;
392 }
393 }
394 }
395 return false;
396}
397
398bool is_bankrupt_debtor_to(sys::state& state, dcon::nation_id debt_holder, dcon::nation_id debtor) {
399 return state.world.nation_get_is_bankrupt(debt_holder) &&
400 state.world.unilateral_relationship_get_owns_debt_of(
401 state.world.get_unilateral_relationship_by_unilateral_pair(debtor, debt_holder)) > 0.1f;
402}
403
404bool nation_is_constructing_factories(sys::state& state, dcon::nation_id n) {
405 auto rng = state.world.nation_get_state_building_construction(n);
406 return rng.begin() != rng.end();
407}
408bool nation_has_closed_factories(sys::state& state, dcon::nation_id n) { // TODO - should be "good" now
409 auto nation_fat = dcon::fatten(state.world, n);
410 for(auto prov_owner : nation_fat.get_province_ownership()) {
411 auto prov = prov_owner.get_province();
412 for(auto factloc : prov.get_factory_location()) {
413 auto scale = factloc.get_factory().get_production_scale();
414 if(scale < factory_closed_threshold) {
415 return true;
416 }
417 }
418 }
419 return false;
420}
421
422float base_artisan_profit(sys::state& state, dcon::nation_id n, dcon::commodity_id c) {
423 auto const& inputs = state.world.commodity_get_artisan_inputs(c);
424 float input_total = 0.0f;
425 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
426 if(inputs.commodity_type[i]) {
427 input_total += inputs.commodity_amounts[i] * state.world.commodity_get_current_price(inputs.commodity_type[i]);
428 } else {
429 break;
430 }
431 }
432
433 float output_total = state.world.commodity_get_artisan_output_amount(c) * state.world.commodity_get_current_price(c);
434
435 float input_multiplier = std::max(0.1f, state.defines.alice_inputs_base_factor_artisans + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::artisan_input));
436 float output_multiplier = std::max(0.1f, state.defines.alice_output_base_factor_artisans + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::artisan_output));
437
438 return output_total * output_multiplier - input_multiplier * input_total;
439}
440float artisan_scale_limit(sys::state& state, dcon::nation_id n, dcon::commodity_id c) {
441 float least = 1.0f;
442 auto const& inputs = state.world.commodity_get_artisan_inputs(c);
443 float input_total = 0.0f;
444 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
445 if(inputs.commodity_type[i]) {
446 least = std::min(least, state.world.nation_get_demand_satisfaction(n, inputs.commodity_type[i]));
447 } else {
448 break;
449 }
450 }
451 return least;
452}
453
454bool valid_artisan_good(sys::state& state, dcon::nation_id n, dcon::commodity_id cid) {
455 auto kf = state.world.commodity_get_key_factory(cid);
456 return (
457 state.world.commodity_get_artisan_output_amount(cid) > 0.0f
458 && (
459 state.world.commodity_get_is_available_from_start(cid)
460 || (
461 kf && state.world.nation_get_active_building(n, kf)
462 )
463 )
464 );
465}
466
467inline constexpr float ln_2 = 0.30103f;
468
469//crude approximation of exp
471 if(f < -128.f) {
472 return 0.f;
473 }
474
475 f = f / 128.f;
476 f = 1 + f + f * f / 2 + f * f * f / 6;
477
478 f = f * f; // 2
479 f = f * f; // 4
480 f = f * f; // 8
481 f = f * f; // 16
482 f = f * f; // 32
483 f = f * f; // 64
484 f = f * f; // 128
485
486 return f;
487}
488
489float get_artisans_multiplier(sys::state& state, dcon::nation_id n) {
490 float multiplier = 0.000001f * state.world.nation_get_everyday_needs_costs(n, state.culture_definitions.artisans);
491 return 1.f / (multiplier + 1.f);
492}
493
494constexpr float artisan_baseline_score = 5.f;
495
496float max_artisan_score(sys::state& state, dcon::nation_id n, float multiplier) {
497 auto const csize = state.world.commodity_size();
498
499 float baseline = artisan_baseline_score / multiplier;
500 float max_score = std::numeric_limits<float>::lowest();
501
502 for(uint32_t i = 1; i < csize; ++i) {
503 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(i) };
504 float score = state.world.nation_get_artisan_distribution(n, cid);
505 if(score > max_score) {
506 max_score = score;
507 }
508 }
509 if(baseline > max_score) {
510 max_score = baseline;
511 }
512
513 return max_score;
514}
515
516float total_artisan_exp_score(sys::state& state, dcon::nation_id n, float multiplier, float max_score) {
517 auto const csize = state.world.commodity_size();
518
519 float total = 0.f;
520 float baseline = artisan_baseline_score / multiplier;
521
522 // crude approximation of softmax
523 for(uint32_t i = 1; i < csize; ++i) {
524 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(i) };
525 float score = state.world.nation_get_artisan_distribution(n, cid);
526 float dist = pseudo_exp_for_negative((score - max_score) * multiplier);
527 total += dist;
528 }
529 total += pseudo_exp_for_negative((baseline - max_score) * multiplier);
530
531 return total;
532}
533
535 sys::state& state,
536 dcon::nation_id n,
537 dcon::commodity_id c,
538 float max_score,
539 float total_score,
540 float multiplier
541) {
542 float score = state.world.nation_get_artisan_distribution(n, c);
543 return pseudo_exp_for_negative((score - max_score) * multiplier) / (total_score + 0.001f);
544}
545
546float get_artisan_distribution_slow(sys::state& state, dcon::nation_id n, dcon::commodity_id c) {
547 auto const csize = state.world.commodity_size();
548
549 float multiplier = get_artisans_multiplier(state, n);
550 float max_score = max_artisan_score(state, n, multiplier);
551 float total_score = total_artisan_exp_score(state, n, multiplier, max_score);
552
553 return get_artisan_distribution_fast(state, n, c, max_score, total_score, multiplier);
554}
555
556void adjust_artisan_balance(sys::state& state, dcon::nation_id n) {
557 auto const csize = state.world.commodity_size();
558 float distribution_drift_speed = 0.0001f;
559
560 std::vector<float> current_distribution;
561 std::vector<float> profits;
562 profits.resize(csize + 1);
563
564 float mult = get_artisans_multiplier(state, n);
565
566 for(uint32_t i = 1; i < csize; ++i) {
567 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(i) };
568 if(valid_artisan_good(state, n, cid)) {
569 auto profit = base_artisan_profit(state, n, cid);
570 //if(profit < 0.f) {
571 // profit = profit * 10000.f;
572 //}
573 profits[cid.index()] = profit;
574 } else {
575 profits[cid.index()] = -256.f / mult / distribution_drift_speed * 10.f;
576 }
577 }
578
579 float multiplier = get_artisans_multiplier(state, n);
580 float max_score = max_artisan_score(state, n, multiplier);
581 float total_score = total_artisan_exp_score(state, n, multiplier, max_score);
582
583 for(uint32_t i = 1; i < csize; ++i) {
584 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(i) };
585 auto& w = state.world.nation_get_artisan_distribution(n, cid);
586 auto last_distribution = get_artisan_distribution_fast(state, n, cid, max_score, total_score, multiplier);
587 auto output = state.world.commodity_get_artisan_output_amount(cid);
588 auto next_score = w * 0.8f + distribution_drift_speed * profits[cid.index()] * (1 - last_distribution) / output;
589 w = next_score;
590 }
591}
592
593void initialize(sys::state& state) {
595
596 state.world.for_each_commodity([&](dcon::commodity_id c) {
597 auto fc = fatten(state.world, c);
598 fc.set_current_price(fc.get_cost());
599 fc.set_total_consumption(0.0f);
600 fc.set_total_production(0.0f);
601 fc.set_total_real_demand(0.0f);
602
603 for(int i = 0; i < 8; i++) {
604 fc.set_demand_by_category(i, 0.f);
605 }
606
607 for(uint32_t i = 0; i < price_history_length; ++i) {
608 fc.set_price_record(i, fc.get_cost());
609 }
610 // fc.set_global_market_pool();
611 });
612
613 auto savings_buffer = state.world.pop_type_make_vectorizable_float_buffer();
614 state.world.for_each_pop_type([&](dcon::pop_type_id t) {
615 auto ft = fatten(state.world, t);
616 state.world.for_each_commodity([&](dcon::commodity_id c) {
617 savings_buffer.get(t) += state.world.commodity_get_is_available_from_start(c)
618 ? state.world.commodity_get_cost(c) * ft.get_life_needs(c) + 0.5f * state.world.commodity_get_cost(c) * ft.get_everyday_needs(c)
619 : 0.0f;
620 });
621 auto strata = (ft.get_strata() * 2) + 1;
622 savings_buffer.get(t) *= strata;
623 });
624
625 state.world.for_each_pop([&](dcon::pop_id p) {
626 auto fp = fatten(state.world, p);
627 pop_demographics::set_life_needs(state, p, 1.0f);
630 fp.set_savings(savings_buffer.get(fp.get_poptype()) * fp.get_size() / state.defines.alice_needs_scaling_factor);
631 });
632
633 state.world.for_each_factory([&](dcon::factory_id f) {
634 auto ff = fatten(state.world, f);
635 ff.set_production_scale(1.0f);
636 });
637
638 // learn some weights for rgo from initial territories:
639 auto csize = state.world.commodity_size();
640 std::vector<std::vector<float>> per_climate_distribution_buffer(state.world.modifier_size() + 1, std::vector<float>(csize + 1, 0.f));
641 std::vector<std::vector<float>> per_terrain_distribution_buffer(state.world.modifier_size() + 1, std::vector<float>(csize + 1, 0.f));
642 std::vector<std::vector<float>> per_continent_distribution_buffer(state.world.modifier_size() + 1, std::vector<float>(csize + 1, 0.f));
643
644 // init the map for climates
645 province::for_each_land_province(state, [&](dcon::province_id p) {
646 auto fp = fatten(state.world, p);
647 dcon::commodity_id main_trade_good = state.world.province_get_rgo(p);
648 if(state.world.commodity_get_money_rgo(main_trade_good)) {
649 return;
650 }
651 dcon::modifier_id climate = fp.get_climate();
652 dcon::modifier_id terrain = fp.get_terrain();
653 dcon::modifier_id continent = fp.get_continent();
654 per_climate_distribution_buffer[climate.value][main_trade_good.value] += 1.f;
655 per_terrain_distribution_buffer[terrain.value][main_trade_good.value] += 1.f;
656 per_continent_distribution_buffer[continent.value][main_trade_good.value] += 1.f;
657 });
658
659 // normalisation
660 for(uint32_t i = 0; i < uint32_t(state.world.modifier_size()); i++) {
661 float climate_sum = 0.f;
662 float terrain_sum = 0.f;
663 float continent_sum = 0.f;
664 for(uint32_t j = 0; j < csize; j++) {
665 climate_sum += per_climate_distribution_buffer[i][j];
666 terrain_sum += per_terrain_distribution_buffer[i][j];
667 continent_sum += per_continent_distribution_buffer[i][j];
668 }
669 for(uint32_t j = 0; j < csize; j++) {
670 per_climate_distribution_buffer[i][j] *= climate_sum == 0.f ? 1.f : 1.f / climate_sum;
671 per_terrain_distribution_buffer[i][j] *= terrain_sum == 0.f ? 1.f : 1.f / terrain_sum;
672 per_continent_distribution_buffer[i][j] *= continent_sum == 0.f ? 1.f : 1.f / continent_sum;
673 }
674 }
675
676 province::for_each_land_province(state, [&](dcon::province_id p) {
677 if(state.world.province_get_rgo_was_set_during_scenario_creation(p)) {
678 return;
679 }
680
681 auto fp = fatten(state.world, p);
682 dcon::modifier_id climate = fp.get_climate();
683 dcon::modifier_id terrain = fp.get_terrain();
684 dcon::modifier_id continent = fp.get_continent();
685
686 dcon::commodity_id main_trade_good = state.world.province_get_rgo(p);
687 bool is_mine = state.world.commodity_get_is_mine(main_trade_good);
688
689 //max size of exploitable land:
690 auto max_rgo_size = std::ceil(2000.f / state.defines.alice_rgo_per_size_employment
691 * state.map_state.map_data.province_area[province::to_map_id(p)]);
692
693 state.world.for_each_commodity([&](dcon::commodity_id c) {
694 fp.set_rgo_employment_per_good(c, 0.f);
695 fp.set_rgo_target_employment_per_good(c, 0.f);
696 });
697
698 // currently exploited land
699 float pop_amount = 0.0f;
700 for(auto pt : state.world.in_pop_type) {
701 if(pt == state.culture_definitions.slaves) {
702 pop_amount += state.world.province_get_demographics(p, demographics::to_key(state, state.culture_definitions.slaves));
703 } else if(pt.get_is_paid_rgo_worker()) {
704 pop_amount += state.world.province_get_demographics(p, demographics::to_key(state, pt));
705 }
706 }
707
708 auto size_at_the_start_of_the_game = std::ceil(pop_amount / state.defines.alice_rgo_per_size_employment);
709 auto real_size = std::min(size_at_the_start_of_the_game * 1.5f, max_rgo_size);
710
711 assert(std::isfinite(real_size));
712 fp.set_rgo_size(real_size);
713
714 static std::vector<float> true_distribution;
715 true_distribution.resize(state.world.commodity_size());
716
717 float total = 0.f;
718 state.world.for_each_commodity([&](dcon::commodity_id c) {
719 float climate_d = per_climate_distribution_buffer[climate.value][c.value];
720 float terrain_d = per_terrain_distribution_buffer[terrain.value][c.value];
721 float continent_d = per_continent_distribution_buffer[continent.value][c.value];
722 float current = (climate_d + terrain_d) * (climate_d + terrain_d) * continent_d;
723 true_distribution[c.index()] = current;
724 total += current;
725 });
726
727 // remove continental restriction if failed:
728 if(total == 0.f) {
729 state.world.for_each_commodity([&](dcon::commodity_id c) {
730 float climate_d = per_climate_distribution_buffer[climate.value][c.value];
731 float terrain_d = per_terrain_distribution_buffer[terrain.value][c.value];
732 float current = (climate_d + terrain_d) * (climate_d + terrain_d);
733 true_distribution[c.index()] = current;
734 total += current;
735 });
736 }
737
738 // make it into uniform distrubution on available goods then...
739 if(total == 0.f) {
740 state.world.for_each_commodity([&](dcon::commodity_id c) {
741 if(state.world.commodity_get_money_rgo(c)) {
742 return;
743 }
744 if(!state.world.commodity_get_is_available_from_start(c)) {
745 return;
746 }
747 float current = 1.f;
748 true_distribution[c.index()] = current;
749 total += current;
750 });
751 }
752
753 state.world.for_each_commodity([&](dcon::commodity_id c) {
754 assert(std::isfinite(total));
755 // if everything had failed for some reason, then assume 0 distribution: main rgo is still active
756 if(total == 0.f) {
757 true_distribution[c.index()] = 0.f;
758 } else {
759 true_distribution[c.index()] /= total;
760 }
761 });
762
763 // distribution of rgo land per good
764 state.world.for_each_commodity([&](dcon::commodity_id c) {
765 auto fc = fatten(state.world, c);
766 assert(std::isfinite(true_distribution[c.index()]));
767 state.world.province_get_rgo_max_size_per_good(fp, c) += real_size * true_distribution[c.index()];
768 });
769 });
770
771 state.world.for_each_nation([&](dcon::nation_id n) {
772 initialize_needs_weights(state, n);
773
774 auto fn = fatten(state.world, n);
775 fn.set_administrative_spending(int8_t(80));
776 fn.set_military_spending(int8_t(60));
777 fn.set_education_spending(int8_t(100));
778 fn.set_social_spending(int8_t(100));
779 fn.set_land_spending(int8_t(100));
780 fn.set_naval_spending(int8_t(100));
781 fn.set_construction_spending(int8_t(100));
782 fn.set_overseas_spending(int8_t(100));
783
784 fn.set_poor_tax(int8_t(75));
785 fn.set_middle_tax(int8_t(75));
786 fn.set_rich_tax(int8_t(75));
787
788 fn.set_spending_level(1.0f);
789
790 state.world.for_each_commodity([&](dcon::commodity_id c) {
791 state.world.nation_set_demand_satisfaction(n, c, 1.0f);
792 state.world.nation_set_direct_demand_satisfaction(n, c, 0.0f);
793 // set domestic market pool
794 });
795 });
796
799
803
804 state.world.for_each_nation([&](dcon::nation_id n) { populate_effective_prices(state, n); });
805 state.world.for_each_nation([&](dcon::nation_id n) {
806 state.world.nation_set_stockpiles(n, money, 2.0f * full_spending_cost(state, n));
807 });
808}
809
810float sphere_leader_share_factor(sys::state& state, dcon::nation_id sphere_leader, dcon::nation_id sphere_member) {
811 /*
812 Share factor : If the nation is a civ and is a secondary power start with define : SECOND_RANK_BASE_SHARE_FACTOR, and
813 otherwise start with define : CIV_BASE_SHARE_FACTOR.Also calculate the sphere owner's foreign investment in the nation as a
814 fraction of the total foreign investment in the nation (I believe that this is treated as zero if there is no foreign
815 investment at all). The share factor is (1 - base share factor) x sphere owner investment fraction + base share factor. For
816 uncivs, the share factor is simply equal to define:UNCIV_BASE_SHARE_FACTOR (so 1, by default). If a nation isn't in a sphere,
817 we let the share factor be 0 if it needs to be used in any other calculation.
818 */
819 if(state.world.nation_get_is_civilized(sphere_member)) {
820 float base = state.world.nation_get_rank(sphere_member) <= state.defines.colonial_rank
821 ? state.defines.second_rank_base_share_factor
822 : state.defines.civ_base_share_factor;
823 auto const ul = state.world.get_unilateral_relationship_by_unilateral_pair(sphere_member, sphere_leader);
824 float sl_investment = state.world.unilateral_relationship_get_foreign_investment(ul);
825 float total_investment = nations::get_foreign_investment(state, sphere_member);
826 float investment_fraction = total_investment > 0.0001f ? sl_investment / total_investment : 0.0f;
827 return base + (1.0f - base) * investment_fraction;
828 } else {
829 return state.defines.unciv_base_share_factor;
830 }
831}
832
833void absorb_sphere_member_production(sys::state& state, dcon::nation_id n) {
834 for(auto gp : state.world.nation_get_gp_relationship_as_great_power(n)) {
836 // - Each sphere member has its domestic x its-share-factor (see above) of its base supply and demand added to its
837 // sphere leader's domestic supply and demand (this does not affect global supply and demand)
838
839 auto t = gp.get_influence_target();
840 float share = sphere_leader_share_factor(state, n, t);
841 state.world.for_each_commodity([&](dcon::commodity_id c) {
842 state.world.nation_get_domestic_market_pool(n, c) += share * state.world.nation_get_domestic_market_pool(t, c);
843 });
844 }
845 }
846}
847
848void give_sphere_leader_production(sys::state& state, dcon::nation_id n) {
849 if(auto sl = state.world.nation_get_in_sphere_of(n); sl) {
850 //- Every nation in a sphere (after the above has been calculated for the entire sphere) has their effective domestic
851 // supply set
852 // to (1 - its-share-factor) x original-domestic-supply + sphere-leader's-domestic supply
853
854 float share = sphere_leader_share_factor(state, sl, n);
855 state.world.for_each_commodity(
856 [&](dcon::commodity_id c) { state.world.nation_get_domestic_market_pool(n, c) *= (1.0f - share); });
857 }
858}
859
860float effective_tariff_rate(sys::state& state, dcon::nation_id n) {
861 auto tariff_efficiency = std::max(0.0f, nations::tariff_efficiency(state, n));
862 auto r = tariff_efficiency * float(state.world.nation_get_tariffs(n)) / 100.0f;
863 return std::max(r, 0.0f);
864}
865
866float global_market_price_multiplier(sys::state& state, dcon::nation_id n) {
867 auto central_ports = state.world.nation_get_central_ports(n);
868 if(central_ports > 0) {
869 return effective_tariff_rate(state, n)
870 + float(state.world.nation_get_central_blockaded(n)) / float(central_ports)
871 + 1.0f;
872 } else {
873 return effective_tariff_rate(state, n) + 1.0f;
874 }
875}
876
878 state.world.for_each_factory([&](dcon::factory_id f) {
879 auto fac_type = fatten(state.world, state.world.factory_get_building_type(f));
880 float sum = 1.0f;
881 auto prov = state.world.factory_get_province_from_factory_location(f);
882 auto pstate = state.world.province_get_state_membership(prov);
883 auto powner = state.world.province_get_nation_from_province_ownership(prov);
884
885 if(powner && pstate) {
886 if(auto mod_a = fac_type.get_bonus_1_trigger();
887 mod_a && trigger::evaluate(state, mod_a, trigger::to_generic(pstate), trigger::to_generic(powner), 0)) {
888 sum -= fac_type.get_bonus_1_amount();
889 }
890 if(auto mod_b = fac_type.get_bonus_2_trigger();
891 mod_b && trigger::evaluate(state, mod_b, trigger::to_generic(pstate), trigger::to_generic(powner), 0)) {
892 sum -= fac_type.get_bonus_2_amount();
893 }
894 if(auto mod_c = fac_type.get_bonus_3_trigger();
895 mod_c && trigger::evaluate(state, mod_c, trigger::to_generic(pstate), trigger::to_generic(powner), 0)) {
896 sum -= fac_type.get_bonus_3_amount();
897 }
898 }
899
900 state.world.factory_set_triggered_modifiers(f, sum);
901 });
902}
903
904float subsistence_size(sys::state const& state, dcon::province_id p) {
905 auto rgo_ownership = state.world.province_get_landowners_share(p) + state.world.province_get_capitalists_share(p);
906 return state.world.province_get_rgo_size(p) * (1.f - rgo_ownership) * 2.0f;
907}
908
909float rgo_effective_size(sys::state const& state, dcon::nation_id n, dcon::province_id p, dcon::commodity_id c) {
910 bool is_mine = state.world.commodity_get_is_mine(c);
911
912 float base = 0.f;
913 auto rgo = state.world.province_get_rgo(p);
914 if(rgo == c) {
915 // set main rgo size to a fixed number for now: allow modders to replace it later per province basis...
916 base = state.defines.alice_base_rgo_employment_bonus / state.defines.alice_rgo_per_size_employment;
917 }
918
919 // - We calculate its effective size which is its base size x (technology-bonus-to-specific-rgo-good-size +
920 // technology-general-farm-or-mine-size-bonus + provincial-mine-or-farm-size-modifier + 1)
921 auto rgo_ownership = state.world.province_get_landowners_share(p) + state.world.province_get_capitalists_share(p);
922 auto sz = state.world.province_get_rgo_max_size_per_good(p, c) * rgo_ownership + base;
923 auto pmod = state.world.province_get_modifier_values(p, is_mine ? sys::provincial_mod_offsets::mine_rgo_size : sys::provincial_mod_offsets::farm_rgo_size);
924 auto nmod = state.world.nation_get_modifier_values(n, is_mine ? sys::national_mod_offsets::mine_rgo_size : sys::national_mod_offsets::farm_rgo_size);
925 auto specific_pmod = state.world.nation_get_rgo_size(n, c);
926 auto bonus = pmod + nmod + specific_pmod + 1.0f;
927
928 return std::max(sz * bonus, 0.00f);
929}
930
931float rgo_total_effective_size(sys::state & state, dcon::nation_id n, dcon::province_id p) {
932 float total = 0.f;
933 state.world.for_each_commodity([&](dcon::commodity_id c) {
934 total += rgo_effective_size(state, n, p, c);
935 });
936 return total;
937}
938
939float subsistence_max_pseudoemployment(sys::state& state, dcon::nation_id n, dcon::province_id p) {
940 return state.defines.alice_rgo_per_size_employment * subsistence_size(state, p) * 1.1f;
941}
942
943float rgo_total_employment(sys::state & state, dcon::nation_id n, dcon::province_id p) {
944 float total = 0.f;
945 state.world.for_each_commodity([&](dcon::commodity_id c) {
946 total += state.world.province_get_rgo_employment_per_good(p, c);
947 });
948 return total;
949}
950
951float rgo_max_employment(sys::state & state, dcon::nation_id n, dcon::province_id p, dcon::commodity_id c) {
952 return state.defines.alice_rgo_per_size_employment * rgo_effective_size(state, n, p, c);
953}
954
955float rgo_total_max_employment(sys::state& state, dcon::nation_id n, dcon::province_id p) {
956 float total = 0.f;
957 state.world.for_each_commodity([&](dcon::commodity_id c) {
958 total += rgo_max_employment(state, n, p, c);
959 });
960 return total;
961}
962
964 state.world.execute_parallel_over_province([&](auto ids) {
965 auto max_subsistence = ve::apply([&](dcon::province_id p) {
966 return subsistence_max_pseudoemployment(state, state.world.province_get_nation_from_province_ownership(p), p);
967 }, ids);
968
969 auto employment = state.world.province_get_subsistence_employment(ids);
970 auto saturation = employment / (4.f + max_subsistence);
971 auto saturation_score = 1.f / (saturation + 1.f);
972
973 auto quality = (ve::to_float(state.world.province_get_life_rating(ids)) - 10.f) / 10.f;
974 quality = ve::max(quality, 0.f) + 0.01f;
975 auto score = (subsistence_factor * quality) + subsistence_score_life;
976 score = (score * saturation_score);
977 state.world.province_set_subsistence_score(ids, score);
978 });
979}
980
981float adjusted_subsistence_score(sys::state& state, dcon::province_id p) {
982 return state.world.province_get_subsistence_score(p)
983 * state.world.province_get_subsistence_employment(p)
984 / (state.world.province_get_demographics(p, demographics::total) + 1.f);
985}
986
988 state.world.execute_parallel_over_province([&](auto ids) {
989 auto local_states = state.world.province_get_state_membership(ids);
990 auto weight_aristocracy =
991 state.world.state_instance_get_demographics(local_states, demographics::to_key(state, state.culture_definitions.aristocrat)) * 200.f
992 + state.world.state_instance_get_demographics(local_states, demographics::to_key(state, state.culture_definitions.slaves));
993 auto weight_capitalists =
994 state.world.state_instance_get_demographics(local_states, demographics::to_key(state, state.culture_definitions.capitalists)) * 200.f;
995 auto weight_population =
996 state.world.state_instance_get_demographics(local_states, demographics::to_key(state, state.culture_definitions.farmers))
997 + state.world.state_instance_get_demographics(local_states, demographics::to_key(state, state.culture_definitions.laborers));
998 auto total = weight_aristocracy + weight_capitalists + weight_population + 1.0f;
999 state.world.province_set_landowners_share(ids, weight_aristocracy / total);
1000 state.world.province_set_capitalists_share(ids, weight_capitalists / total);
1001 });
1002}
1003
1004int32_t factory_priority(sys::state const& state, dcon::factory_id f) {
1005 return (state.world.factory_get_priority_low(f) ? 1 : 0) + (state.world.factory_get_priority_high(f) ? 2 : 0);
1006}
1007void set_factory_priority(sys::state& state, dcon::factory_id f, int32_t priority) {
1008 state.world.factory_set_priority_high(f, priority >= 2);
1009 state.world.factory_set_priority_low(f, (priority & 1) != 0);
1010}
1011bool factory_is_profitable(sys::state const& state, dcon::factory_id f) {
1012 return state.world.factory_get_unprofitable(f) == false || state.world.factory_get_subsidized(f);
1013}
1014
1016 float profit = 0.0f;
1017 dcon::commodity_id c;
1018};
1019
1021 int32_t last = state.province_definitions.first_sea_province.index();
1022
1023 concurrency::parallel_for(0, last, [&](int32_t for_index) {
1024 //province::for_each_land_province(state, [&](dcon::province_id p) {
1025 dcon::province_id p{ dcon::province_id::value_base_t(for_index) };
1026
1027 auto owner = state.world.province_get_nation_from_province_ownership(p);
1028 auto current_employment = 0.f;
1029 state.world.for_each_commodity([&](dcon::commodity_id c) {
1030 current_employment += state.world.province_get_rgo_employment_per_good(p, c);
1031 });
1032 current_employment += state.world.province_get_subsistence_employment(p);
1033
1034 bool is_mine = state.world.commodity_get_is_mine(state.world.province_get_rgo(p));
1035 float worker_pool = 0.0f;
1036 for(auto wt : state.culture_definitions.rgo_workers) {
1037 worker_pool += state.world.province_get_demographics(p, demographics::to_key(state, wt));
1038 }
1039 float slave_pool = state.world.province_get_demographics(p, demographics::to_key(state, state.culture_definitions.slaves));
1040 float labor_pool = worker_pool + slave_pool;
1041
1042 float total_population = state.world.province_get_demographics(p, demographics::total);
1043
1044 labor_pool = std::min(labor_pool, total_population);
1045
1046 // update rgo employment per good:
1047
1048 //sorting goods by profitability
1049 //static std::vector<dcon::commodity_id> ordered_rgo_goods;
1050
1051 commodity_profit_holder ordered_list[126];
1052 assert(state.world.commodity_size() <= 126);
1053
1054 //ordered_rgo_goods.clear();
1055
1056 uint32_t used_indices = 0;
1057 state.world.for_each_commodity([&](dcon::commodity_id c) {
1058 if(rgo_max_employment(state, owner, p, c) > 0.f) {
1059 ordered_list[used_indices].c = c;
1060 ordered_list[used_indices].profit = rgo_expected_worker_norm_profit(state, p, owner, c);
1061 ++used_indices;
1062 } else {
1063 state.world.province_set_rgo_employment_per_good(p, c, 0.f);
1064 }
1065 });
1066
1067 std::sort(ordered_list, ordered_list + used_indices, [&](commodity_profit_holder const& a, commodity_profit_holder const& b) {
1068 return (a.profit > b.profit);
1069 });
1070
1071 // distributing workers in almost the same way as factories:
1072 float speed = 0.20f;
1073
1074 float total_workforce = labor_pool;
1075 float max_employment_total = 0.f;
1076 float total_employed = 0.f;
1077
1078 for(uint32_t i = 0; i < used_indices; ++i) {
1079 auto c = ordered_list[i].c;
1080 float max_employment = rgo_max_employment(state, owner, p, c);
1081 max_employment_total += max_employment;
1082 float target_workforce = std::min(state.world.province_get_rgo_target_employment_per_good(p, c), total_workforce);
1083
1084 float current_workforce = state.world.province_get_rgo_employment_per_good(p, c);
1085 float new_employment = std::min(current_workforce * (1 - speed) + target_workforce * speed, total_workforce);
1086 total_workforce -= new_employment;
1087
1088 new_employment = std::clamp(new_employment, 0.f, max_employment);
1089 total_employed += new_employment;
1090
1091 state.world.province_set_rgo_employment_per_good(p, c, new_employment);
1092 }
1093
1094 float subsistence = std::min(subsistence_max_pseudoemployment(state, owner, p), total_workforce);
1095 total_workforce -= subsistence;
1096 total_employed += subsistence;
1097
1098 state.world.province_set_subsistence_employment(p, subsistence);
1099
1100 assert(total_employed <= total_population + 1.f);
1101
1102 float employment_ratio = 0.f;
1103 if(max_employment_total > 1.f) {
1104 employment_ratio = total_employed / (max_employment_total + 1.f);
1105 } else {
1106 employment_ratio = 1.f;
1107 }
1108 state.world.province_set_rgo_employment(p, employment_ratio);
1109
1110 auto slave_fraction = (slave_pool > current_employment) ? current_employment / slave_pool : 1.0f;
1111 auto free_fraction = std::max(0.0f, (worker_pool > current_employment - slave_pool) ? (current_employment - slave_pool) / std::max(worker_pool, 0.01f) : 1.0f);
1112
1113 for(auto pop : state.world.province_get_pop_location(p)) {
1114 auto pt = pop.get_pop().get_poptype();
1115 if(pt == state.culture_definitions.slaves) {
1116 pop_demographics::set_raw_employment(state, pop.get_pop(), slave_fraction);
1117 } else if(pt.get_is_paid_rgo_worker()) {
1118 pop_demographics::set_raw_employment(state, pop.get_pop(), free_fraction);
1119 }
1120 }
1121 });
1122}
1123
1124float factory_max_employment(sys::state const& state, dcon::factory_id f) {
1125 return state.defines.alice_factory_per_level_employment * state.world.factory_get_level(f);
1126}
1127
1128float factory_primary_employment(sys::state const& state, dcon::factory_id f) {
1129 auto primary_employment = state.world.factory_get_primary_employment(f);
1130 return factory_max_employment(state, f) * (state.economy_definitions.craftsmen_fraction * primary_employment);
1131}
1132float factory_secondary_employment(sys::state const& state, dcon::factory_id f) {
1133 auto secondary_employment = state.world.factory_get_secondary_employment(f);
1134 return factory_max_employment(state, f) * ((1 - state.economy_definitions.craftsmen_fraction) * secondary_employment);
1135}
1136float factory_total_employment(sys::state const& state, dcon::factory_id f) {
1137 // TODO: Document this, also is this a stub?
1138 auto primary_employment = state.world.factory_get_primary_employment(f);
1139 auto secondary_employment = state.world.factory_get_secondary_employment(f);
1140 return factory_max_employment(state, f) * (state.economy_definitions.craftsmen_fraction * primary_employment + (1 -state.economy_definitions.craftsmen_fraction) * secondary_employment);
1141}
1142
1144 state.world.for_each_state_instance([&](dcon::state_instance_id si) {
1145 float primary_pool = state.world.state_instance_get_demographics(si,
1146 demographics::to_key(state, state.culture_definitions.primary_factory_worker));
1147 float secondary_pool = state.world.state_instance_get_demographics(si,
1148 demographics::to_key(state, state.culture_definitions.secondary_factory_worker));
1149
1150 static std::vector<dcon::factory_id> ordered_factories;
1151 ordered_factories.clear();
1152
1153 province::for_each_province_in_state_instance(state, si, [&](dcon::province_id p) {
1154 for(auto fac : state.world.province_get_factory_location(p)) {
1155 ordered_factories.push_back(fac.get_factory());
1156 }
1157 });
1158
1159 std::sort(ordered_factories.begin(), ordered_factories.end(), [&](dcon::factory_id a, dcon::factory_id b) {
1160 if(factory_is_profitable(state, a) != factory_is_profitable(state, b)) {
1161 return factory_is_profitable(state, a);
1162 }
1163 if(factory_priority(state, a) != factory_priority(state, b)) {
1164 return factory_priority(state, a) > factory_priority(state, b);
1165 }
1166 return a.index() < b.index();
1167 });
1168
1169 float employment_shift_speed = 0.001f;
1170
1171 float primary_pool_copy = primary_pool;
1172 float secondary_pool_copy = secondary_pool;
1173 for(uint32_t index = 0; index < ordered_factories.size();) {
1174 uint32_t next_index = index;
1175
1176 float total_workforce = 0.0f;
1177 for(; next_index < ordered_factories.size(); ++next_index) {
1178 if(
1179 factory_is_profitable(state, ordered_factories[index])
1180 !=
1181 factory_is_profitable(state, ordered_factories[next_index])
1182 ||
1183 factory_priority(state, ordered_factories[index])
1184 !=
1185 factory_priority(state, ordered_factories[next_index])
1186 ) {
1187 break;
1188 }
1189 total_workforce += factory_max_employment(state, ordered_factories[next_index]) *
1190 state.world.factory_get_production_scale(ordered_factories[next_index]);
1191 }
1192
1193 {
1194 float type_share = state.economy_definitions.craftsmen_fraction * total_workforce;
1195 float scale = primary_pool_copy >= type_share ? 1.0f : primary_pool_copy / type_share;
1196 primary_pool_copy = std::max(0.0f, primary_pool_copy - type_share);
1197
1198
1199 for(uint32_t i = index; i < next_index; ++i) {
1200 float old_employment = state.world.factory_get_primary_employment(ordered_factories[i]);
1201 float new_employment =
1202 old_employment * (1.f - employment_shift_speed)
1203 + scale * state.world.factory_get_production_scale(ordered_factories[i]) * employment_shift_speed;
1204
1205 state.world.factory_set_primary_employment(
1206 ordered_factories[i],
1207 new_employment
1208 );
1209 }
1210 }
1211 {
1212 float type_share = (1.0f - state.economy_definitions.craftsmen_fraction) * total_workforce;
1213 float scale = secondary_pool_copy >= type_share ? 1.0f : secondary_pool_copy / type_share;
1214 secondary_pool_copy = std::max(0.0f, secondary_pool_copy - type_share);
1215
1216 for(uint32_t i = index; i < next_index; ++i) {
1217
1218 float old_employment = state.world.factory_get_secondary_employment(ordered_factories[i]);
1219 float new_employment =
1220 old_employment * (1.f - employment_shift_speed)
1221 + scale * state.world.factory_get_production_scale(ordered_factories[i]) * employment_shift_speed;
1222
1223 state.world.factory_set_secondary_employment(
1224 ordered_factories[i],
1225 new_employment
1226 );
1227 }
1228 }
1229
1230 index = next_index;
1231 }
1232
1233 float prim_employment = 1.0f - (primary_pool > 0 ? primary_pool_copy / primary_pool : 0.0f);
1234 float sec_employment = 1.0f - (secondary_pool > 0 ? secondary_pool_copy / secondary_pool : 0.0f);
1235
1236 province::for_each_province_in_state_instance(state, si, [&](dcon::province_id p) {
1237 for(auto pop : state.world.province_get_pop_location(p)) {
1238 if(pop.get_pop().get_poptype() == state.culture_definitions.primary_factory_worker) {
1239 pop_demographics::set_raw_employment(state, pop.get_pop(), prim_employment);
1240 } else if(pop.get_pop().get_poptype() == state.culture_definitions.secondary_factory_worker) {
1241 pop_demographics::set_raw_employment(state, pop.get_pop(), sec_employment);
1242 }
1243 }
1244 });
1245 });
1246}
1247
1248/*
1249*
1250- Each factory has an input, output, and throughput multipliers.
1251- These are computed from the employees present. Input and output are 1 + employee effects, throughput starts at 0
1252- The input multiplier is also multiplied by (1 + sum-of-any-triggered-modifiers-for-the-factory) x
12530v(national-mobilization-impact)
1254- Note: overseas is repurposed to administration of colonies
1255- Owner fraction is calculated from the fraction of owners in the state to total state population in the state (with some cap --
12565%?)
1257- For each pop type employed, we calculate the ratio of number-of-pop-employed-of-a-type / (base-workforce x level) to the optimal
1258fraction defined for the production type (capping it at 1). That ratio x the-employee-effect-amount is then added into the
1259input/output/throughput modifier for the factory.
1260- Then, for input/output/throughput we sum up national and provincial modifiers to general factory input/output/throughput are
1261added, plus technology modifiers to its specific output commodity, add one to the sum, and then multiply the
1262input/output/throughput modifier from the workforce by it.
1263
1264- The target input consumption scale is: input-multiplier x throughput-multiplier x factory level
1265- The actual consumption scale is limited by the input commodities sitting in the stockpile (i.e. input-consumption-scale x
1266input-quantity must be less than the amount in the stockpile)
1267- A similar process is done for efficiency inputs, except the consumption of efficiency inputs is
1268(national-factory-maintenance-modifier + 1) x input-multiplier x throughput-multiplier x factory level
1269- Finally, we get the efficiency-adjusted consumption scale by multiplying the base consumption scale by (0.75 + 0.25 x the
1270efficiency consumption scale)
1271
1272*/
1273
1274float factory_full_production_quantity(sys::state const& state, dcon::factory_id f, dcon::nation_id n,
1275 float mobilization_impact) {
1276 auto fac = fatten(state.world, f);
1277 auto fac_type = fac.get_building_type();
1278
1279 /*
1280 float total_state_pop = std::max(0.01f, state.world.state_instance_get_demographics(s, demographics::total));
1281 float owner_fraction = std::min(0.05f, state.world.state_instance_get_demographics(s, demographics::to_key(state,
1282 state.culture_definitions.capitalists)) / total_state_pop); float input_multiplier = fac.get_triggered_modifiers() * (1.0f +
1283 owner_fraction * -2.5f);
1284 */
1285
1286 float throughput_multiplier = (state.world.nation_get_factory_goods_throughput(n, fac_type.get_output()) + 1.0f);
1287 float output_multiplier = state.world.nation_get_factory_goods_output(n, fac_type.get_output())
1288 + 1.0f
1289 + fac.get_secondary_employment()
1290 * (1.0f - state.economy_definitions.craftsmen_fraction)
1291 * 1.5f
1292 * 2.f; // additional multiplier to give advantage to "old industrial giants" which have a bunch of clerks already
1293
1294 float max_production_scale = fac.get_primary_employment()
1295 * fac.get_level()
1296 * std::max(0.0f, mobilization_impact);
1297
1298 return throughput_multiplier * output_multiplier * max_production_scale;
1299}
1300
1301float rgo_efficiency(sys::state & state, dcon::nation_id n, dcon::province_id p, dcon::commodity_id c) {
1302 bool is_mine = state.world.commodity_get_is_mine(c);
1303
1304 float main_rgo = 1.f;
1305 auto rgo = state.world.province_get_rgo(p);
1306 if(rgo == c) {
1307 main_rgo = state.defines.alice_base_rgo_efficiency_bonus;
1308 }
1309
1310 float base_amount = state.world.commodity_get_rgo_amount(c);
1311 float throughput =
1312 1.0f
1313 + state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::local_rgo_throughput)
1314 + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::rgo_throughput)
1315 + state.world.province_get_modifier_values(p,
1316 is_mine ?
1317 sys::provincial_mod_offsets::mine_rgo_eff
1318 :
1319 sys::provincial_mod_offsets::farm_rgo_eff)
1320 + state.world.nation_get_modifier_values(n,
1321 is_mine ?
1322 sys::national_mod_offsets::mine_rgo_eff
1323 :
1324 sys::national_mod_offsets::farm_rgo_eff);
1325
1326 float saturation = std::clamp(state.world.province_get_rgo_employment_per_good(p, c)
1327 / (rgo_max_employment(state, n, p, c) + 1.f), 0.0f, 1.0f);
1328
1329 float result = base_amount
1330 * main_rgo
1331 * (1.f + 1.0f * (1.f - saturation))
1332 * std::max(0.5f, throughput)
1333 * state.defines.alice_rgo_boost
1334 * std::max(0.5f, (1.0f + state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::local_rgo_output) +
1335 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::rgo_output) +
1336 state.world.nation_get_rgo_goods_output(n, c)));
1337
1338 assert(result >= 0.0f && std::isfinite(result));
1339 return result;
1340}
1341
1342float rgo_full_production_quantity(sys::state & state, dcon::nation_id n, dcon::province_id p, dcon::commodity_id c) {
1343 /*
1344 - We calculate its effective size which is its base size x (technology-bonus-to-specific-rgo-good-size +
1345 technology-general-farm-or-mine-size-bonus + provincial-mine-or-farm-size-modifier + 1)
1346 - We add its production to domestic supply, calculating that amount basically in the same way we do for factories, by
1347 computing RGO-throughput x RGO-output x RGO-size x base-commodity-production-quantity, except that it is affected by different
1348 modifiers.
1349 */
1350 auto eff_size = rgo_effective_size(state, n, p, c);
1351 auto val = eff_size * rgo_efficiency(state, n, p, c);
1352 assert(val >= 0.0f && std::isfinite(val));
1353 return val;
1354}
1355
1357 sys::state& state,
1358 dcon::nation_id n,
1359 dcon::factory_type_fat_id fac_type
1360) {
1361 float min_input_available = 1.0f;
1362 auto& inputs = fac_type.get_inputs();
1363 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
1364 if(inputs.commodity_type[i]) {
1365 min_input_available =
1366 std::min(
1367 min_input_available,
1368 state.world.nation_get_demand_satisfaction(n, inputs.commodity_type[i])
1369 );
1370 } else {
1371 break;
1372 }
1373 }
1374 return min_input_available;
1375}
1376
1377float factory_input_total_cost(sys::state& state, dcon::nation_id n, dcon::factory_type_fat_id fac_type) {
1378 float input_total = 0.0f;
1379 auto& inputs = fac_type.get_inputs();
1380 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
1381 if(inputs.commodity_type[i]) {
1382 input_total += inputs.commodity_amounts[i] * state.world.nation_get_effective_prices(n, inputs.commodity_type[i]);
1383 } else {
1384 break;
1385 }
1386 }
1387 return input_total;
1388}
1389
1390float factory_min_e_input_available(sys::state& state, dcon::nation_id n, dcon::factory_type_fat_id fac_type) {
1391 float min_e_input_available = 1.0f;
1392 auto& e_inputs = fac_type.get_efficiency_inputs();
1393 for(uint32_t i = 0; i < small_commodity_set::set_size; ++i) {
1394 if(e_inputs.commodity_type[i]) {
1395 min_e_input_available =
1396 std::min(
1397 min_e_input_available,
1398 state.world.nation_get_demand_satisfaction(n, e_inputs.commodity_type[i])
1399 );
1400 } else {
1401 break;
1402 }
1403 }
1404
1405 return min_e_input_available;
1406}
1407
1408float factory_e_input_total_cost(sys::state& state, dcon::nation_id n, dcon::factory_type_fat_id fac_type) {
1409 float e_input_total = 0.0f;
1410 auto& e_inputs = fac_type.get_efficiency_inputs();
1411 for(uint32_t i = 0; i < small_commodity_set::set_size; ++i) {
1412 if(e_inputs.commodity_type[i]) {
1413 e_input_total += e_inputs.commodity_amounts[i] * state.world.nation_get_effective_prices(n, e_inputs.commodity_type[i]);
1414 } else {
1415 break;
1416 }
1417 }
1418
1419 return e_input_total;
1420}
1421
1422float nation_factory_input_multiplier(sys::state& state, dcon::nation_id n) {
1423 return std::max(
1424 0.1f,
1425 state.defines.alice_inputs_base_factor
1426 + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_input)
1427 );
1428}
1429float nation_factory_output_multiplier(sys::state& state, dcon::factory_type_id fac_type, dcon::nation_id n) {
1430 auto output = state.world.factory_type_get_output(fac_type);
1431 return state.world.nation_get_factory_goods_output(n, output)
1432 + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_output)
1433 + 1.0f;
1434}
1435
1436float factory_input_multiplier(sys::state& state, dcon::factory_fat_id fac, dcon::nation_id n, dcon::province_id p, dcon::state_instance_id s) {
1437 float total_workers = factory_max_employment(state, fac);
1438 float small_size_effect = 1.f;
1439 float small_bound = state.defines.alice_factory_per_level_employment * 5.f;
1440 if(total_workers < small_bound) {
1441 small_size_effect = 0.5f + total_workers / small_bound * 0.5f;
1442 }
1443
1444 float total_state_pop = std::max(0.01f, state.world.state_instance_get_demographics(s, demographics::total));
1445 float capitalists = state.world.state_instance_get_demographics(s, demographics::to_key(state, state.culture_definitions.capitalists));
1446 float owner_fraction = total_state_pop > 0
1447 ? std::min(
1448 0.05f,
1449 capitalists / total_state_pop)
1450 : 0.0f;
1451
1452 return small_size_effect *
1453 fac.get_triggered_modifiers() *
1454 std::max(
1455 0.1f,
1456 (state.defines.alice_inputs_base_factor
1457 + state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::local_factory_input)
1458 + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_input)
1459 + owner_fraction * -2.5f)
1460 );
1461}
1462
1463float factory_throughput_multiplier(sys::state& state, dcon::factory_type_fat_id fac_type, dcon::nation_id n, dcon::province_id p, dcon::state_instance_id s) {
1464 return state.world.nation_get_factory_goods_throughput(n, fac_type.get_output())
1465 + state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::local_factory_throughput)
1466 + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_throughput)
1467 + 1.0f;
1468}
1469
1470float factory_output_multiplier(sys::state& state, dcon::factory_fat_id fac, dcon::nation_id n, dcon::province_id p) {
1471 auto fac_type = fac.get_building_type();
1472
1473 return state.world.nation_get_factory_goods_output(n, fac_type.get_output())
1474 + state.world.province_get_modifier_values(p, sys::provincial_mod_offsets::local_factory_output)
1475 + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_output)
1476 + fac.get_secondary_employment()
1477 * (1.0f - state.economy_definitions.craftsmen_fraction)
1478 * 1.5f
1479 + 1.0f;
1480}
1481
1482float factory_max_production_scale_non_modified(sys::state& state, dcon::factory_fat_id fac) {
1483 return fac.get_primary_employment()
1484 * fac.get_level();
1485}
1486
1487float factory_max_production_scale(sys::state& state, dcon::factory_fat_id fac, float mobilization_impact, bool occupied) {
1488 return fac.get_primary_employment()
1489 * fac.get_level()
1490 * (occupied ? 0.1f : 1.0f)
1491 * std::max(0.0f, mobilization_impact);
1492}
1493
1494float update_factory_scale(sys::state& state, dcon::factory_fat_id fac, float max_production_scale, float raw_profit, float desired_raw_profit) {
1495 float total_workers = factory_max_employment(state, fac);
1496 float several_workers_scale = 10.f / total_workers;
1497
1498 // we don't want for factories to change "world balance" too much individually
1499 // when relative production is high, we want to reduce our speed
1500 // for example, if relative production is 1.0, then we want to clamp our speed with ~0.01 or something small like this;
1501 // and if relative production is ~0, then clamps are not needed
1502 float relative_production_amount
1503 =
1504 state.world.factory_type_get_output_amount(fac.get_building_type())
1505 / (
1506 state.world.commodity_get_total_production(fac.get_building_type().get_output())
1507 + state.world.commodity_get_total_real_demand(fac.get_building_type().get_output())
1508 + 10.f
1509 );
1510
1511 float relative_modifier = (1 / (relative_production_amount + 0.01f)) / 1000.f;
1512
1513 float effective_production_scale = 0.0f;
1514 if(state.world.factory_get_subsidized(fac)) {
1515 auto new_production_scale = std::min(1.0f, fac.get_production_scale() + several_workers_scale * fac.get_level() * 10.f);
1516 fac.set_production_scale(new_production_scale);
1517 return std::min(new_production_scale * fac.get_level(), max_production_scale);
1518 }
1519
1520 float over_profit_ratio = (raw_profit) / (desired_raw_profit + 0.0001f) - 1.f;
1521 float under_profit_ratio = (desired_raw_profit) / (raw_profit + 0.0001f) - 1.f;
1522
1523 float speed_modifier = (over_profit_ratio - under_profit_ratio);
1524 float speed = production_scale_delta * speed_modifier + several_workers_scale * ((raw_profit - desired_raw_profit > 0.f) ? 1.f : -1.f);
1525
1526 speed = std::clamp(speed, -relative_modifier, relative_modifier);
1527
1528 auto new_production_scale = std::clamp(fac.get_production_scale() + speed, 0.f, 1.f);
1529 fac.set_production_scale(new_production_scale);
1530 return std::min(new_production_scale * fac.get_level(), max_production_scale);
1531}
1532
1533float factory_desired_raw_profit(dcon::factory_fat_id fac, float spendings) {
1534 return spendings * (1.2f + fac.get_secondary_employment() * fac.get_level() / 150.f );
1535}
1536
1537void update_single_factory_consumption(sys::state& state, dcon::factory_id f, dcon::nation_id n, dcon::province_id p, dcon::state_instance_id s, float mobilization_impact, float expected_min_wage, bool occupied) {
1538 auto fac = fatten(state.world, f);
1539 auto fac_type = fac.get_building_type();
1540
1541 assert(fac_type);
1542 assert(fac_type.get_output());
1543 assert(n);
1544 assert(p);
1545 assert(s);
1546
1547 float total_workers = factory_max_employment(state, f);
1548 float several_workers_scale = 10.f / total_workers;
1549 float max_production_scale = factory_max_production_scale(
1550 state,
1551 fac,
1552 mobilization_impact,
1553 occupied
1554 );
1555
1556 float current_workers = total_workers * max_production_scale;
1557
1558 //inputs
1559
1560 float input_total = factory_input_total_cost(state, n, fac_type);
1561 float min_input_available = factory_min_input_available(state, n, fac_type);
1562 float e_input_total = factory_e_input_total_cost(state, n , fac_type);
1563 float min_e_input_available = factory_min_e_input_available(state, n, fac_type);
1564
1565 //modifiers
1566
1567 float input_multiplier = factory_input_multiplier(state, fac, n, p, s);
1568 auto const mfactor = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_maintenance) + 1.0f;
1569 float throughput_multiplier = factory_throughput_multiplier(state, fac_type, n, p, s);
1570 float output_multiplier = factory_output_multiplier(state, fac, n, p);
1571
1572 //this value represents total production if 1 lvl of this factory is filled with workers
1573 float total_production = fac_type.get_output_amount()
1574 * (0.75f + 0.25f * min_e_input_available)
1575 * throughput_multiplier
1576 * output_multiplier
1577 * min_input_available;
1578
1579 //this value represents raw profit if 1 lvl of this factory is filled with workers
1580 float profit =
1581 total_production
1582 * state.world.commodity_get_current_price(fac_type.get_output());
1583
1584 //this value represents spendings if 1 lvl of this factory is filled with workers
1585 float spendings =
1586 expected_min_wage
1587 * (state.defines.alice_factory_per_level_employment / state.defines.alice_needs_scaling_factor)
1588 +
1589 input_multiplier
1590 * throughput_multiplier
1591 * input_total
1592 * min_input_available
1593 +
1594 input_multiplier * mfactor
1595 * e_input_total
1596 * min_e_input_available
1597 * min_input_available;
1598
1599 float desired_profit = factory_desired_raw_profit(fac, spendings);
1600 float max_pure_profit = profit - spendings;
1601 state.world.factory_set_unprofitable(f, !(max_pure_profit > 0.0f));
1602
1603 float effective_production_scale = update_factory_scale(
1604 state,
1605 fac,
1606 max_production_scale,
1607 profit,
1608 desired_profit
1609 );
1610
1611 auto& inputs = fac_type.get_inputs();
1612 auto& e_inputs = fac_type.get_efficiency_inputs();
1613
1614 // register real demand : input_multiplier * throughput_multiplier * level * primary_employment
1615 // also multiply by target production scale... otherwise too much excess demand is generated
1616 // also multiply by something related to minimal satisfied input
1617 // to prevent generation of too much demand on rgos already influenced by a shortage
1618
1619 float input_scale =
1620 input_multiplier
1621 * throughput_multiplier
1622 * effective_production_scale
1623 * (0.1f + min_input_available * 0.9f);
1624
1625 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
1626 if(inputs.commodity_type[i]) {
1628 n,
1629 inputs.commodity_type[i],
1630 input_scale
1631 * inputs.commodity_amounts[i]
1632 , economy_reason::factory
1633 );
1634 } else {
1635 break;
1636 }
1637 }
1638
1639 // and for efficiency inputs
1640 // the consumption of efficiency inputs is (national-factory-maintenance-modifier + 1) x input-multiplier x
1641 // throughput-multiplier x factory level
1642 for(uint32_t i = 0; i < small_commodity_set::set_size; ++i) {
1643 if(e_inputs.commodity_type[i]) {
1645 state,
1646 n,
1647 e_inputs.commodity_type[i],
1648 mfactor
1649 * input_scale
1650 * e_inputs.commodity_amounts[i]
1651 * (0.1f + min_e_input_available * 0.9f)
1652 , economy_reason::factory
1653 );
1654 } else {
1655 break;
1656 }
1657 }
1658
1659 float actual_production = total_production * effective_production_scale;
1660 float pure_profit = max_pure_profit * effective_production_scale;
1661
1662 state.world.factory_set_actual_production(f, actual_production);
1663 state.world.factory_set_full_profit(f, pure_profit);
1664}
1665
1666void update_single_factory_production(sys::state& state, dcon::factory_id f, dcon::nation_id n, float expected_min_wage) {
1667
1668 auto production = state.world.factory_get_actual_production(f);
1669 if(production > 0) {
1670 auto fac = fatten(state.world, f);
1671 auto fac_type = fac.get_building_type();
1672
1673 /*
1674 float min_input = 1.0f;
1675 float min_efficiency_input = 1.0f;
1676 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
1677 if(fac_type.get_inputs().commodity_type[i]) {
1678 min_input = std::min(min_input, state.world.nation_get_demand_satisfaction(n, fac_type.get_inputs().commodity_type[i]));
1679 } else {
1680 break;
1681 }
1682 }
1683
1684 // and for efficiency inputs
1685 for(uint32_t i = 0; i < small_commodity_set::set_size; ++i) {
1686 if(fac_type.get_efficiency_inputs().commodity_type[i]) {
1687 min_efficiency_input = std::min(min_efficiency_input,
1688 state.world.nation_get_demand_satisfaction(n, fac_type.get_efficiency_inputs().commodity_type[i]));
1689 } else {
1690 break;
1691 }
1692 }
1693 */
1694
1695 auto amount = production;
1696 auto money_made = state.world.factory_get_full_profit(f);
1697
1698 state.world.factory_set_actual_production(f, amount);
1699 register_domestic_supply(state, n, fac_type.get_output(), amount, economy_reason::factory);
1700
1701 if(!fac.get_subsidized()) {
1702 state.world.factory_set_full_profit(f, money_made);
1703 } else {
1704 float min_wages =
1705 expected_min_wage
1706 * fac.get_level()
1707 * fac.get_primary_employment()
1708 * (state.defines.alice_factory_per_level_employment / state.defines.alice_needs_scaling_factor);
1709 if(money_made < min_wages) {
1710 auto diff = min_wages - money_made;
1711 if(state.world.nation_get_stockpiles(n, money) > diff || can_take_loans(state, n)) {
1712 state.world.factory_set_full_profit(f, min_wages);
1713 state.world.nation_get_stockpiles(n, money) -= diff;
1714 state.world.nation_get_subsidies_spending(n) += diff;
1715 } else {
1716 state.world.factory_set_full_profit(f, std::max(money_made, 0.0f));
1717 fac.set_subsidized(false);
1718 }
1719 } else {
1720 state.world.factory_set_full_profit(f, money_made);
1721 }
1722 }
1723 } else {
1724 }
1725}
1726
1727rgo_workers_breakdown rgo_relevant_population(sys::state& state, dcon::province_id p, dcon::nation_id n) {
1728 auto relevant_paid_population = 0.f;
1729 for(auto wt : state.culture_definitions.rgo_workers) {
1730 relevant_paid_population += state.world.province_get_demographics(p, demographics::to_key(state, wt));
1731 }
1732 auto slaves = state.world.province_get_demographics(p, demographics::to_employment_key(state, state.culture_definitions.slaves));
1733
1734 rgo_workers_breakdown result = {
1735 .paid_workers = relevant_paid_population,
1736 .slaves = slaves,
1737 .total = relevant_paid_population + slaves
1738 };
1739
1740 return result;
1741}
1742
1743float rgo_desired_worker_norm_profit(sys::state& state, dcon::province_id p, dcon::nation_id n, float min_wage, float total_relevant_population) {
1744 auto current_employment = rgo_total_employment(state, n, p); // maximal amount of workers which rgo could potentially employ
1745
1746 //we assume a "perfect ratio" of 1 aristo per N pops
1747 float perfect_aristos_amount = total_relevant_population / 10000.f;
1748 float perfect_aristos_amount_adjusted = perfect_aristos_amount / state.defines.alice_needs_scaling_factor;
1749 float aristos_desired_cut = perfect_aristos_amount_adjusted * (
1750 state.world.nation_get_everyday_needs_costs(n, state.culture_definitions.aristocrat)
1751 + state.world.nation_get_life_needs_costs(n, state.culture_definitions.aristocrat)
1752 );
1753 float aristo_burden_per_worker = aristos_desired_cut / (total_relevant_population + 1);
1754
1755 float subsistence = adjusted_subsistence_score(state, p);
1756 if (subsistence == 0) subsistence = state.world.province_get_subsistence_score(p);
1757 float subsistence_life = std::clamp(subsistence, 0.f, subsistence_score_life);
1758 subsistence -= subsistence_life;
1759 float subsistence_everyday = std::clamp(subsistence, 0.f, subsistence_score_everyday);
1760 subsistence -= subsistence_everyday;
1761 float subsistence_luxury = std::clamp(subsistence, 0.f, subsistence_score_luxury);
1762
1763 bool is_mine = state.world.commodity_get_is_mine(state.world.province_get_rgo(p));
1764
1765 dcon::pop_type_id pop_type = is_mine ? state.culture_definitions.laborers : state.culture_definitions.farmers;
1766
1767 auto ln_costs = state.world.nation_get_life_needs_costs(n, pop_type);
1768 auto en_costs = state.world.nation_get_everyday_needs_costs(n, pop_type);
1769 auto lx_costs = state.world.nation_get_luxury_needs_costs(n, pop_type);
1770
1771 float subsistence_based_min_wage =
1772 subsistence_life * ln_costs
1773 + subsistence_everyday * en_costs
1774 + subsistence_luxury * ln_costs;
1775
1776 float min_wage_burden_per_worker = (min_wage + subsistence_based_min_wage) / state.defines.alice_needs_scaling_factor;
1777
1778 float desired_profit_by_worker = aristo_burden_per_worker + min_wage_burden_per_worker / (1.f - rgo_owners_cut);
1779
1780 // we want to employ at least someone, so we decrease our desired profits when employment is low
1781 // otherwise everyone works in subsistence and landowners get no money
1782 // not exactly an ideal solution but it works and doesn't create goods or wealth out of thin air
1783 float employment_ratio = current_employment / (total_relevant_population + 1.f);
1784 desired_profit_by_worker = desired_profit_by_worker * employment_ratio; //* employment_ratio;
1785
1786 assert(std::isfinite(desired_profit_by_worker));
1787
1788 return desired_profit_by_worker;
1789
1790 //return (aristos_desired_cut + min_wage / state.defines.alice_needs_scaling_factor * (current_employment + 1));// / total_relevant_population; //* total_relevant_population;
1791}
1792
1793float rgo_expected_worker_norm_profit(sys::state& state, dcon::province_id p, dcon::nation_id n, dcon::commodity_id c) {
1794 auto efficiency = rgo_efficiency(state, n, p, c);
1795 auto current_price = state.world.commodity_get_current_price(c);
1796 auto consumed_ratio = std::min(1.f, (state.world.commodity_get_total_consumption(c) + 0.0001f) / (state.world.commodity_get_total_production(c) + 0.0001f));
1797 if(state.world.commodity_get_money_rgo(c)) {
1798 consumed_ratio = 1.f;
1799 }
1800
1801 return
1802 consumed_ratio
1803 * efficiency
1804 * current_price
1805 / state.defines.alice_rgo_per_size_employment;
1806}
1807
1808float convex_function(float x) {
1809 return 1.f - (1.f - x) * (1.f - x);
1810}
1811
1813 sys::state& state,
1814 dcon::province_id p,
1815 dcon::nation_id n,
1816 float mobilization_impact,
1817 float expected_min_wage,
1818 bool occupied
1819) {
1820 auto rgo_pops = rgo_relevant_population(state, p, n);
1821 float desired_profit = rgo_desired_worker_norm_profit(state, p, n, expected_min_wage, rgo_pops.total);
1822
1823 state.world.for_each_commodity([&](dcon::commodity_id c) {
1824 auto max_production = rgo_full_production_quantity(state, n, p, c);
1825 if(max_production < 0.001f) {
1826 return;
1827 }
1828
1829 auto pops_max = rgo_max_employment(state, n, p, c); // maximal amount of workers which rgo could potentially employ
1830 auto current_employment = state.world.province_get_rgo_employment_per_good(p, c);
1831 float expected_profit = rgo_expected_worker_norm_profit(state, p, n, c);
1832
1833 float market_size = state.world.commodity_get_total_production(c) + state.world.commodity_get_total_real_demand(c);
1834
1835 float positive_speed = (expected_profit + 0.00000001f) / (desired_profit + 0.00000001f) - 1.f;
1836 float negative_speed = (desired_profit + 0.00000001f) / (expected_profit + 0.00000001f) - 1.f;
1837
1838 float change = (positive_speed - negative_speed) / rgo_effective_size(state, n, p, c);
1839
1840 float discrete_step = (((expected_profit - desired_profit) > 0.f) ? 1.f : -1.f) * 20.f;
1841
1842 change = change / max_production * pops_max / 100.f + discrete_step;
1843
1844 //change = std::clamp(change, -relative_modifier, relative_modifier);
1845 assert(std::isfinite(current_employment + change));
1846 auto new_employment = std::clamp(current_employment + change, 0.0f, pops_max);
1847 state.world.province_set_rgo_target_employment_per_good(p, c, new_employment);
1848
1849 // rgos produce all the way down
1850 float employment_ratio = current_employment / pops_max;
1851 assert(max_production * employment_ratio >= 0);
1852 state.world.province_set_rgo_actual_production_per_good(p, c, max_production * employment_ratio);
1853 });
1854}
1855
1856void update_province_rgo_production(sys::state& state, dcon::province_id p, dcon::nation_id n) {
1857 state.world.province_set_rgo_full_profit(p, 0.f);
1858 state.world.for_each_commodity([&](dcon::commodity_id c) {
1859 auto amount = state.world.province_get_rgo_actual_production_per_good(p, c);
1860
1861 register_domestic_supply(state, n, c, amount, economy_reason::rgo);
1862
1863 float profit = amount * state.world.commodity_get_current_price(c);
1864
1865 assert(profit >= 0);
1866
1867 state.world.province_set_rgo_profit_per_good(p, c, profit);
1868 state.world.province_get_rgo_full_profit(p) += profit;
1869
1870 if(state.world.commodity_get_money_rgo(c)) {
1871 assert(std::isfinite(amount * state.defines.gold_to_cash_rate) && amount * state.defines.gold_to_cash_rate >= 0.0f);
1872 state.world.nation_get_stockpiles(n, money) += amount * state.defines.gold_to_cash_rate;
1873 }
1874 });
1875}
1876
1877
1878void update_national_artisan_consumption(sys::state& state, dcon::nation_id n, float expected_min_wage, float mobilization_impact) {
1879 auto const csize = state.world.commodity_size();
1880 auto num_artisans = state.world.nation_get_demographics(n, demographics::to_key(state, state.culture_definitions.artisans));
1881 float total_profit = 0.0f;
1882
1883
1884 float multiplier = get_artisans_multiplier(state, n);
1885 float max_score = max_artisan_score(state, n, multiplier);
1886 float total_score = total_artisan_exp_score(state, n, multiplier, max_score);
1887
1888 for(uint32_t i = 1; i < csize; ++i) {
1889 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(i) };
1890 state.world.nation_set_artisan_actual_production(n, cid, 0.0f);
1891 if(valid_artisan_good(state, n, cid)) {
1892 float input_total = 0.0f;
1893 auto const& inputs = state.world.commodity_get_artisan_inputs(cid);
1894 float min_available = 1.0f;
1895 for(uint32_t j = 0; j < commodity_set::set_size; ++j) {
1896 if(inputs.commodity_type[j]) {
1897 input_total += inputs.commodity_amounts[j] * state.world.nation_get_effective_prices(n, inputs.commodity_type[j]);
1898 min_available = std::min(min_available, state.world.nation_get_demand_satisfaction(n, inputs.commodity_type[j]));
1899 } else {
1900 break;
1901 }
1902 }
1903
1904 float output_total = state.world.commodity_get_artisan_output_amount(cid) * state.world.commodity_get_current_price(cid);
1905
1906 float input_multiplier = std::max(0.1f, state.defines.alice_inputs_base_factor_artisans
1907 + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::artisan_input));
1908 float throughput_multiplier = std::max(0.1f, 1.0f
1909 + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::artisan_throughput));
1910 float output_multiplier = std::max(0.1f, state.defines.alice_output_base_factor_artisans
1911 + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::artisan_output));
1912
1913 float distribution = get_artisan_distribution_fast(state, n, cid, max_score, total_score, multiplier);
1914 float max_production_scale = num_artisans * distribution / 10'000.0f * std::max(0.0f, mobilization_impact);
1915
1916 auto profitability_factor = (output_total * output_multiplier * throughput_multiplier * min_available - input_multiplier * input_total * throughput_multiplier * min_available) / (0.5f * expected_min_wage * (10'000.0f / state.defines.alice_needs_scaling_factor));
1917
1918 bool profitable = (output_total * output_multiplier - input_multiplier * input_total) >= 0.0f;
1919
1920 //if(profitability_factor <= -1.0f) {
1921
1922 //} else {
1923 //profitability_factor = std::clamp(profitability_factor * 0.5f + 0.5f, 0.0f, 1.0f);
1924 for(uint32_t j = 0; j < commodity_set::set_size; ++j) {
1925 if(inputs.commodity_type[j]) {
1927 state,
1928 n,
1929 inputs.commodity_type[j],
1930 input_multiplier * throughput_multiplier * max_production_scale * inputs.commodity_amounts[j] * (0.1f + 0.9f * min_available),
1931 economy_reason::artisan
1932 );
1933 } else {
1934 break;
1935 }
1936 }
1937 state.world.nation_set_artisan_actual_production(n, cid, state.world.commodity_get_artisan_output_amount(cid) * throughput_multiplier * output_multiplier * max_production_scale * min_available);
1938 total_profit += std::max(0.0f, (output_total * output_multiplier - input_multiplier * input_total) * throughput_multiplier * max_production_scale * min_available);
1939 //}
1940 }
1941 }
1942
1943 state.world.nation_set_artisan_profit(n, total_profit);
1944}
1945
1946void update_national_artisan_production(sys::state& state, dcon::nation_id n) {
1947 auto const csize = state.world.commodity_size();
1948 auto num_artisans = state.world.nation_get_demographics(n, demographics::to_key(state, state.culture_definitions.artisans));
1949 float total_profit = 0.0f;
1950
1951 for(uint32_t i = 1; i < csize; ++i) {
1952 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(i) };
1953
1954 if(valid_artisan_good(state, n, cid)) {
1955
1956 auto production = state.world.nation_get_artisan_actual_production(n, cid);
1957 if(production > 0.f) {
1958 auto const& inputs = state.world.commodity_get_artisan_inputs(cid);
1959
1960 float min_input = 1.0f;
1961 for(uint32_t j = 0; j < commodity_set::set_size; ++j) {
1962 if(inputs.commodity_type[j]) {
1963 min_input = std::min(min_input, state.world.nation_get_demand_satisfaction(n, inputs.commodity_type[j]));
1964 } else {
1965 break;
1966 }
1967 }
1968
1969 auto amount = min_input * production;
1970 state.world.nation_set_artisan_actual_production(n, cid, amount);
1971 register_domestic_supply(state, n, cid, amount, economy_reason::artisan);
1972 }
1973 }
1974 }
1975}
1976
1978 uint32_t total_commodities = state.world.commodity_size();
1979 for(uint32_t i = 1; i < total_commodities; ++i) {
1980 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
1981 state.world.execute_serial_over_nation([&](auto ids) { state.world.nation_set_army_demand(ids, cid, 0.0f); });
1982 }
1983
1984 state.world.for_each_regiment([&](dcon::regiment_id r) {
1985 auto reg = fatten(state.world, r);
1986 auto type = state.world.regiment_get_type(r);
1987 auto owner = reg.get_army_from_army_membership().get_controller_from_army_control();
1988 if(owner && type) {
1989 auto o_sc_mod = std::max(0.01f, state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::supply_consumption) + 1.0f);
1990 auto& supply_cost = state.military_definitions.unit_base_definitions[type].supply_cost;
1991 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
1992 if(supply_cost.commodity_type[i]) {
1993 state.world.nation_get_army_demand(owner, supply_cost.commodity_type[i]) +=
1994 supply_cost.commodity_amounts[i] * state.world.nation_get_unit_stats(owner, type).supply_consumption *
1995 o_sc_mod;
1996 } else {
1997 break;
1998 }
1999 }
2000 }
2001 });
2002}
2003
2005 uint32_t total_commodities = state.world.commodity_size();
2006 for(uint32_t i = 1; i < total_commodities; ++i) {
2007 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2008 state.world.execute_serial_over_nation([&](auto ids) { state.world.nation_set_navy_demand(ids, cid, 0.0f); });
2009 }
2010
2011 state.world.for_each_ship([&](dcon::ship_id r) {
2012 auto shp = fatten(state.world, r);
2013 auto type = state.world.ship_get_type(r);
2014 auto owner = shp.get_navy_from_navy_membership().get_controller_from_navy_control();
2015 if(owner && type) {
2016 auto o_sc_mod = std::max(0.01f, state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::supply_consumption) + 1.0f);
2017 auto& supply_cost = state.military_definitions.unit_base_definitions[type].supply_cost;
2018 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2019 if(supply_cost.commodity_type[i]) {
2020 state.world.nation_get_navy_demand(owner, supply_cost.commodity_type[i]) +=
2021 supply_cost.commodity_amounts[i] * state.world.nation_get_unit_stats(owner, type).supply_consumption *
2022 o_sc_mod;
2023 } else {
2024 break;
2025 }
2026 }
2027 }
2028 });
2029}
2030
2031
2032// we want "cheaper per day"(= slower) construction at the start to avoid initial demand bomb
2033// and "more expensive"(=faster) construction at late game
2034inline constexpr float day_1_build_time_modifier_non_factory = 2.f;
2035inline constexpr float day_inf_build_time_modifier_non_factory = 0.5f;
2036inline constexpr float day_1_derivative_non_factory = -0.2f;
2037
2041
2042
2044 float t = math::sqrt((static_cast<float>(state.current_date.value) * 0.01f + 2.f));
2046}
2047
2048inline constexpr float day_1_build_time_modifier_factory = 0.9f;
2049inline constexpr float day_inf_build_time_modifier_factory = 0.75f;
2050inline constexpr float day_1_derivative_factory = -0.01f;
2051
2054inline constexpr float slope_factory = diff_factory * shift_factory;
2055
2056// also we want to speed up factories construction right at the start
2057// as it's the most vulnerable time for them
2058// and we need to establish *some* industrial base for world to develop
2059// their build time should also become faster with time to delay growth bottleneck
2061 float t = math::sqrt((static_cast<float>(state.current_date.value) * 0.01f + 2.f));
2063}
2064
2066 uint32_t total_commodities = state.world.commodity_size();
2067 for(uint32_t i = 1; i < total_commodities; ++i) {
2068 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2069 state.world.execute_serial_over_nation([&](auto ids) { state.world.nation_set_construction_demand(ids, cid, 0.0f); });
2070 }
2071
2072 for(auto lc : state.world.in_province_land_construction) {
2073 auto province = state.world.pop_get_province_from_pop_location(state.world.province_land_construction_get_pop(lc));
2074 auto owner = state.world.province_get_nation_from_province_ownership(province);
2075
2076 float admin_eff = state.world.nation_get_administrative_efficiency(owner);
2077 float admin_cost_factor = 2.0f - admin_eff;
2078
2079 if(owner && state.world.province_get_nation_from_province_control(province) == owner) {
2080
2081 auto& base_cost =
2082 state.military_definitions.unit_base_definitions[state.world.province_land_construction_get_type(lc)].build_cost;
2083 auto& current_purchased = state.world.province_land_construction_get_purchased_goods(lc);
2084 float construction_time = global_non_factory_construction_time_modifier(state) *
2085 float(state.military_definitions.unit_base_definitions[state.world.province_land_construction_get_type(lc)].build_time);
2086
2087 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2088 if(base_cost.commodity_type[i]) {
2089 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * admin_cost_factor)
2090 register_construction_demand(state, owner, base_cost.commodity_type[i], base_cost.commodity_amounts[i] * admin_cost_factor / construction_time);
2091 } else {
2092 break;
2093 }
2094 }
2095 }
2096 }
2097
2098 province::for_each_land_province(state, [&](dcon::province_id p) {
2099 auto owner = state.world.province_get_nation_from_province_ownership(p);
2100 if(!owner || state.world.province_get_nation_from_province_control(p) != owner)
2101 return;
2102 {
2103 auto rng = state.world.province_get_province_naval_construction(p);
2104 if(rng.begin() != rng.end()) {
2105 auto c = *(rng.begin());
2106
2107 float admin_eff = state.world.nation_get_administrative_efficiency(owner);
2108 float admin_cost_factor = 2.0f - admin_eff;
2109
2110 auto& base_cost = state.military_definitions.unit_base_definitions[c.get_type()].build_cost;
2111 auto& current_purchased = c.get_purchased_goods();
2112 float construction_time = global_non_factory_construction_time_modifier(state) *
2113 float(state.military_definitions.unit_base_definitions[c.get_type()].build_time);
2114
2115 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2116 if(base_cost.commodity_type[i]) {
2117 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * admin_cost_factor)
2118 register_construction_demand(state, owner, base_cost.commodity_type[i], base_cost.commodity_amounts[i] * admin_cost_factor / construction_time);
2119 } else {
2120 break;
2121 }
2122 }
2123 }
2124 }
2125 });
2126
2127 for(auto c : state.world.in_province_building_construction) {
2128 auto owner = c.get_nation().id;
2129 if(owner && c.get_province().get_nation_from_province_ownership() == c.get_province().get_nation_from_province_control() && !c.get_is_pop_project()) {
2130 auto t = economy::province_building_type(c.get_type());
2131 auto& base_cost = state.economy_definitions.building_definitions[int32_t(t)].cost;
2132 auto& current_purchased = c.get_purchased_goods();
2133 float construction_time = global_non_factory_construction_time_modifier(state) *
2134 float(state.economy_definitions.building_definitions[int32_t(t)].time);
2135
2136 float admin_eff = state.world.nation_get_administrative_efficiency(owner);
2137 float admin_cost_factor = 2.0f - admin_eff;
2138
2139 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2140 if(base_cost.commodity_type[i]) {
2141 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * admin_cost_factor)
2142 register_construction_demand(state, owner, base_cost.commodity_type[i], base_cost.commodity_amounts[i] * admin_cost_factor / construction_time);
2143 } else {
2144 break;
2145 }
2146 }
2147 }
2148 }
2149
2150 for(auto c : state.world.in_state_building_construction) {
2151 auto owner = c.get_nation().id;
2152 if(owner && !c.get_is_pop_project()) {
2153 auto& base_cost = c.get_type().get_construction_costs();
2154 auto& current_purchased = c.get_purchased_goods();
2155 float construction_time = global_factory_construction_time_modifier(state) *
2156 float(c.get_type().get_construction_time()) * (c.get_is_upgrade() ? 0.5f : 1.0f);
2157 float factory_mod = state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::factory_cost) + 1.0f;
2158
2159 float admin_eff = state.world.nation_get_administrative_efficiency(owner);
2160 float admin_cost_factor = 2.0f - admin_eff;
2161
2162 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2163 if(base_cost.commodity_type[i]) {
2164 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * factory_mod * admin_cost_factor)
2165 register_construction_demand(state, owner, base_cost.commodity_type[i], base_cost.commodity_amounts[i] * factory_mod * admin_cost_factor / construction_time);
2166 } else {
2167 break;
2168 }
2169 }
2170 }
2171 }
2172}
2173
2175 uint32_t total_commodities = state.world.commodity_size();
2176 for(uint32_t i = 1; i < total_commodities; ++i) {
2177 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2178 state.world.execute_serial_over_nation([&](auto ids) { state.world.nation_set_private_construction_demand(ids, cid, 0.0f); });
2179 }
2180
2181 for(auto c : state.world.in_province_building_construction) {
2182 auto owner = c.get_nation().id;
2183 // Rationale for not checking building type: Its an invalid state; should not occur under normal circumstances
2184 if(owner && owner == c.get_province().get_nation_from_province_control() && c.get_is_pop_project()) {
2185 auto t = economy::province_building_type(c.get_type());
2186 auto& base_cost = state.economy_definitions.building_definitions[int32_t(t)].cost;
2187 auto& current_purchased = c.get_purchased_goods();
2188 float construction_time = global_non_factory_construction_time_modifier(state) *
2189 float(state.economy_definitions.building_definitions[int32_t(t)].time);
2190 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2191 if(base_cost.commodity_type[i]) {
2192 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i])
2193 state.world.nation_get_private_construction_demand(owner, base_cost.commodity_type[i]) +=
2194 base_cost.commodity_amounts[i] / construction_time;
2195 } else {
2196 break;
2197 }
2198 }
2199 }
2200 }
2201
2202 for(auto c : state.world.in_state_building_construction) {
2203 auto owner = c.get_nation().id;
2204 if(owner && c.get_is_pop_project()) {
2205 auto& base_cost = c.get_type().get_construction_costs();
2206 auto& current_purchased = c.get_purchased_goods();
2207 float construction_time = global_factory_construction_time_modifier(state) *
2208 float(c.get_type().get_construction_time()) * (c.get_is_upgrade() ? 0.1f : 1.0f);
2209 float factory_mod = (state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::factory_cost) + 1.0f) * std::max(0.1f, state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::factory_owner_cost));
2210
2211 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2212 if(base_cost.commodity_type[i]) {
2213 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * factory_mod)
2214 state.world.nation_get_private_construction_demand(owner, base_cost.commodity_type[i]) +=
2215 base_cost.commodity_amounts[i] * factory_mod / construction_time;
2216 } else {
2217 break;
2218 }
2219 }
2220 }
2221 }
2222}
2223
2224float full_spending_cost(sys::state& state, dcon::nation_id n) {
2225 float total = 0.0f;
2226 float military_total = 0.f;
2227 uint32_t total_commodities = state.world.commodity_size();
2228 float l_spending = float(state.world.nation_get_land_spending(n)) / 100.0f;
2229 float n_spending = float(state.world.nation_get_naval_spending(n)) / 100.0f;
2230 float c_spending = float(state.world.nation_get_construction_spending(n)) / 100.0f;
2231 float o_spending = float(state.world.nation_get_overseas_spending(n)) / 100.f;
2232
2233 for(uint32_t i = 1; i < total_commodities; ++i) {
2234 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2235 auto v = state.world.nation_get_army_demand(n, cid) * l_spending * state.world.nation_get_effective_prices(n, cid);
2236 assert(std::isfinite(v) && v >= 0.0f);
2237 total += v;
2238 military_total += v;
2239 }
2240 for(uint32_t i = 1; i < total_commodities; ++i) {
2241 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2242 auto v = state.world.nation_get_navy_demand(n, cid) * n_spending * state.world.nation_get_effective_prices(n, cid);
2243 assert(std::isfinite(v) && v >= 0.0f);
2244 total += v;
2245 military_total += v;
2246 }
2247 assert(std::isfinite(total) && total >= 0.0f);
2248 state.world.nation_set_maximum_military_costs(n, military_total);
2249
2250 for(uint32_t i = 1; i < total_commodities; ++i) {
2251 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2252 total += state.world.nation_get_construction_demand(n, cid) * c_spending * state.world.nation_get_effective_prices(n, cid);
2253 }
2254 for(uint32_t i = 1; i < total_commodities; ++i) {
2255 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2256 auto difference = state.world.nation_get_stockpile_targets(n, cid) - state.world.nation_get_stockpiles(n, cid);
2257 if(difference > 0 && state.world.nation_get_drawing_on_stockpiles(n, cid) == false) {
2258 total += difference * state.world.nation_get_effective_prices(n, cid);
2259 }
2260 }
2261 assert(std::isfinite(total) && total >= 0.0f);
2262
2263 auto overseas_factor = state.defines.province_overseas_penalty * float(state.world.nation_get_owned_province_count(n) - state.world.nation_get_central_province_count(n));
2264 if(overseas_factor > 0) {
2265 for(uint32_t i = 1; i < total_commodities; ++i) {
2266 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2267 auto kf = state.world.commodity_get_key_factory(cid);
2268 if(state.world.commodity_get_overseas_penalty(cid) && (state.world.commodity_get_is_available_from_start(cid) || (kf && state.world.nation_get_active_building(n, kf)))) {
2269 total += overseas_factor * state.world.nation_get_effective_prices(n, cid) * o_spending;
2270 }
2271 }
2272 }
2273
2274 assert(std::isfinite(total) && total >= 0.0f);
2275 // direct payments to pops
2276
2277 auto const a_spending = float(state.world.nation_get_administrative_spending(n)) / 100.0f * float(state.world.nation_get_administrative_spending(n)) / 100.0f;
2278 auto const s_spending = state.world.nation_get_administrative_efficiency(n) * float(state.world.nation_get_social_spending(n)) / 100.0f;
2279 auto const e_spending = float(state.world.nation_get_education_spending(n)) * float(state.world.nation_get_education_spending(n)) / 100.0f / 100.0f;
2280 auto const m_spending = float(state.world.nation_get_military_spending(n)) * float(state.world.nation_get_military_spending(n)) / 100.0f / 100.f;
2281 auto const p_level = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::pension_level);
2282 auto const unemp_level = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::unemployment_benefit);
2283 auto const di_spending = float(state.world.nation_get_domestic_investment_spending(n)) * float(state.world.nation_get_domestic_investment_spending(n)) / 100.0f / 100.0f;
2284
2285 total += state.defines.alice_domestic_investment_multiplier * di_spending *
2286 (state.world.nation_get_demographics(n, demographics::to_key(state, state.culture_definitions.capitalists))
2287 * state.world.nation_get_luxury_needs_costs(n, state.culture_definitions.capitalists)
2288 + state.world.nation_get_demographics(n, demographics::to_key(state, state.culture_definitions.aristocrat))
2289 * state.world.nation_get_luxury_needs_costs(n, state.culture_definitions.aristocrat))
2290 / state.defines.alice_needs_scaling_factor;
2291
2292 state.world.for_each_pop_type([&](dcon::pop_type_id pt) {
2293 auto adj_pop_of_type = state.world.nation_get_demographics(n, demographics::to_key(state, pt)) / state.defines.alice_needs_scaling_factor;
2294
2295 if(adj_pop_of_type <= 0)
2296 return;
2297
2298 auto ln_type = culture::income_type(state.world.pop_type_get_life_needs_income_type(pt));
2300 total += a_spending * adj_pop_of_type * state.world.nation_get_life_needs_costs(n, pt);
2301 } else if(ln_type == culture::income_type::education) {
2302 total += e_spending * adj_pop_of_type * state.world.nation_get_life_needs_costs(n, pt);
2303 } else if(ln_type == culture::income_type::military) {
2304 total += m_spending * adj_pop_of_type * state.world.nation_get_life_needs_costs(n, pt);
2305 } else { // unemployment, pensions
2306 total += s_spending * adj_pop_of_type * p_level * state.world.nation_get_life_needs_costs(n, pt);
2307 if(state.world.pop_type_get_has_unemployment(pt)) {
2308 auto emp = state.world.nation_get_demographics(n, demographics::to_employment_key(state, pt)) / state.defines.alice_needs_scaling_factor;
2309 total += s_spending * (adj_pop_of_type - emp) * unemp_level * state.world.nation_get_life_needs_costs(n, pt);
2310 }
2311 }
2312
2313 auto en_type = culture::income_type(state.world.pop_type_get_everyday_needs_income_type(pt));
2315 total += a_spending * adj_pop_of_type * state.world.nation_get_everyday_needs_costs(n, pt);
2316 } else if(en_type == culture::income_type::education) {
2317 total += e_spending * adj_pop_of_type * state.world.nation_get_everyday_needs_costs(n, pt);
2318 } else if(en_type == culture::income_type::military) {
2319 total += m_spending * adj_pop_of_type * state.world.nation_get_everyday_needs_costs(n, pt);
2320 }
2321
2322 auto lx_type = culture::income_type(state.world.pop_type_get_luxury_needs_income_type(pt));
2324 total += a_spending * adj_pop_of_type * state.world.nation_get_luxury_needs_costs(n, pt);
2325 } else if(lx_type == culture::income_type::education) {
2326 total += e_spending * adj_pop_of_type * state.world.nation_get_luxury_needs_costs(n, pt);
2327 } else if(lx_type == culture::income_type::military) {
2328 total += m_spending * adj_pop_of_type * state.world.nation_get_luxury_needs_costs(n, pt);
2329 }
2330
2331 assert(std::isfinite(total) && total >= 0.0f);
2332 });
2333
2334 assert(std::isfinite(total) && total >= 0.0f);
2335
2336 return total;
2337}
2338
2339float estimate_stockpile_filling_spending(sys::state& state, dcon::nation_id n) {
2340 float total = 0.0f;
2341 uint32_t total_commodities = state.world.commodity_size();
2342
2343 for(uint32_t i = 1; i < total_commodities; ++i) {
2344 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(i) };
2345 auto difference = state.world.nation_get_stockpile_targets(n, cid) - state.world.nation_get_stockpiles(n, cid);
2346 if(difference > 0 && state.world.nation_get_drawing_on_stockpiles(n, cid) == false) {
2347 total += difference * state.world.commodity_get_current_price(cid) * state.world.nation_get_demand_satisfaction(n, cid);
2348 }
2349 }
2350
2351 return total;
2352}
2353
2354float estimate_overseas_penalty_spending(sys::state& state, dcon::nation_id n) {
2355 float total = 0.0f;
2356
2357 auto overseas_factor = state.defines.province_overseas_penalty * float(state.world.nation_get_owned_province_count(n) - state.world.nation_get_central_province_count(n));
2358 uint32_t total_commodities = state.world.commodity_size();
2359
2360 if(overseas_factor > 0) {
2361 for(uint32_t i = 1; i < total_commodities; ++i) {
2362 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(i) };
2363
2364 auto kf = state.world.commodity_get_key_factory(cid);
2365 if(state.world.commodity_get_overseas_penalty(cid) && (state.world.commodity_get_is_available_from_start(cid) || (kf && state.world.nation_get_active_building(n, kf)))) {
2366 total += overseas_factor * state.world.commodity_get_current_price(cid) * state.world.nation_get_demand_satisfaction(n, cid);
2367 }
2368 }
2369 }
2370
2371 return total;
2372}
2373
2374float full_private_investment_cost(sys::state& state, dcon::nation_id n) {
2375 float total = 0.0f;
2376 uint32_t total_commodities = state.world.commodity_size();
2377 for(uint32_t i = 1; i < total_commodities; ++i) {
2378 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2379 total += state.world.nation_get_private_construction_demand(n, cid) * state.world.nation_get_effective_prices(n, cid);
2380 }
2381 return total;
2382}
2383
2384void update_national_consumption(sys::state& state, dcon::nation_id n, float spending_scale, float private_investment_scale) {
2385 uint32_t total_commodities = state.world.commodity_size();
2386 float l_spending = float(state.world.nation_get_land_spending(n)) / 100.0f;
2387 float n_spending = float(state.world.nation_get_naval_spending(n)) / 100.0f;
2388 float c_spending = float(state.world.nation_get_construction_spending(n)) / 100.0f;
2389 float o_spending = float(state.world.nation_get_overseas_spending(n)) / 100.0f;
2390
2391 for(uint32_t i = 1; i < total_commodities; ++i) {
2392 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2393 register_demand(state, n, cid, state.world.nation_get_army_demand(n, cid) * l_spending * spending_scale, economy_reason::nation);
2394 }
2395 for(uint32_t i = 1; i < total_commodities; ++i) {
2396 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2397 register_demand(state, n, cid, state.world.nation_get_navy_demand(n, cid) * n_spending * spending_scale, economy_reason::nation);
2398 }
2399 for(uint32_t i = 1; i < total_commodities; ++i) {
2400 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2401 register_demand(state, n, cid, state.world.nation_get_construction_demand(n, cid) * c_spending * spending_scale, economy_reason::construction);
2402 }
2403 for(uint32_t i = 1; i < total_commodities; ++i) {
2404 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(i) };
2405 register_demand(state, n, cid, state.world.nation_get_private_construction_demand(n, cid) * private_investment_scale, economy_reason::construction);
2406 }
2407 for(uint32_t i = 1; i < total_commodities; ++i) {
2408 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2409 auto difference = state.world.nation_get_stockpile_targets(n, cid) - state.world.nation_get_stockpiles(n, cid);
2410 if(difference > 0 && state.world.nation_get_drawing_on_stockpiles(n, cid) == false) {
2411 register_demand(state, n, cid, difference * spending_scale, economy_reason::stockpile);
2412 }
2413 }
2414 auto overseas_factor = state.defines.province_overseas_penalty * float(state.world.nation_get_owned_province_count(n) - state.world.nation_get_central_province_count(n));
2415 if(overseas_factor > 0.f) {
2416 for(uint32_t i = 1; i < total_commodities; ++i) {
2417 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
2418 auto kf = state.world.commodity_get_key_factory(cid);
2419 if(state.world.commodity_get_overseas_penalty(cid) && (state.world.commodity_get_is_available_from_start(cid) || (kf && state.world.nation_get_active_building(n, kf)))) {
2420 register_demand(state, n, cid, overseas_factor * spending_scale * o_spending, economy_reason::overseas_penalty);
2421 }
2422 }
2423 }
2424}
2425
2426void update_pop_consumption(sys::state& state, dcon::nation_id n, float base_demand, float invention_factor) {
2427 uint32_t total_commodities = state.world.commodity_size();
2428
2429 static auto ln_demand_vector = state.world.pop_type_make_vectorizable_float_buffer();
2430 state.world.execute_serial_over_pop_type([&](auto ids) { ln_demand_vector.set(ids, ve::fp_vector{}); });
2431 static auto en_demand_vector = state.world.pop_type_make_vectorizable_float_buffer();
2432 state.world.execute_serial_over_pop_type([&](auto ids) { en_demand_vector.set(ids, ve::fp_vector{}); });
2433 static auto lx_demand_vector = state.world.pop_type_make_vectorizable_float_buffer();
2434 state.world.execute_serial_over_pop_type([&](auto ids) { lx_demand_vector.set(ids, ve::fp_vector{}); });
2435
2436 // state.defines.alice_needs_scaling_factor
2437 auto nation_rules = state.world.nation_get_combined_issue_rules(n);
2438 bool nation_allows_investment = state.world.nation_get_is_civilized(n) && (nation_rules & (issue_rule::pop_build_factory | issue_rule::pop_expand_factory)) != 0;
2439 for(auto p : state.world.nation_get_province_ownership(n)) {
2440
2441 float subsistence = adjusted_subsistence_score(state, p.get_province());
2442 float subsistence_life = std::clamp(subsistence, 0.f, subsistence_score_life);
2443 subsistence -= subsistence_life;
2444 float subsistence_everyday = std::clamp(subsistence, 0.f, subsistence_score_everyday);
2445 subsistence -= subsistence_everyday;
2446 float subsistence_luxury = std::clamp(subsistence, 0.f, subsistence_score_luxury);
2447
2448 subsistence_life /= subsistence_score_life;
2449 subsistence_everyday /= subsistence_score_everyday;
2450 subsistence_luxury /= subsistence_score_luxury;
2451
2452 for(auto pl : state.world.province_get_pop_location(p.get_province())) {
2453 auto t = pl.get_pop().get_poptype();
2454 assert(t);
2455 auto total_budget = pl.get_pop().get_savings();
2456 auto total_pop = pl.get_pop().get_size();
2457
2458 //subsistence:
2459
2460 float ln_to_satisfy = std::max(1.f - subsistence_life, 0.f);
2461 float en_to_satisfy = std::max(1.f - subsistence_everyday, 0.f);
2462 float xn_to_satisfy = std::max(1.f - subsistence_luxury, 0.f);
2463
2464 float ln_cost = ln_to_satisfy * state.world.nation_get_life_needs_costs(n, t) * total_pop / state.defines.alice_needs_scaling_factor;
2465 float en_cost = en_to_satisfy * state.world.nation_get_everyday_needs_costs(n, t) * total_pop / state.defines.alice_needs_scaling_factor;
2466 float xn_cost = xn_to_satisfy * state.world.nation_get_luxury_needs_costs(n, t) * total_pop / state.defines.alice_needs_scaling_factor;
2467
2468 float life_needs_fraction = (total_budget >= ln_cost ? ln_to_satisfy : total_budget / ln_cost);
2469 total_budget -= ln_cost;
2470
2471 //eliminate potential negative number before investment
2472 total_budget = std::max(total_budget, 0.f);
2473
2474 //handle investment before everyday goods - they could be very hard to satisfy, depending on a mod:
2475 if(!nation_allows_investment || (t != state.culture_definitions.aristocrat && t != state.culture_definitions.capitalists)) {
2476
2477 } else if(t == state.culture_definitions.capitalists) {
2478 state.world.nation_get_private_investment(n) += total_budget * state.defines.alice_invest_capitalist;
2479 total_budget -= total_budget * state.defines.alice_invest_capitalist;
2480 } else {
2481 state.world.nation_get_private_investment(n) += total_budget * state.defines.alice_invest_aristocrat;
2482 total_budget -= total_budget * state.defines.alice_invest_aristocrat;
2483 }
2484
2485 float everyday_needs_fraction = (total_budget >= en_cost ? en_to_satisfy : std::max(0.0f, total_budget / en_cost));
2486 total_budget -= en_cost;
2487
2488 float luxury_needs_fraction = (total_budget >= xn_cost ? xn_to_satisfy : std::max(0.0f, total_budget / xn_cost));
2489 total_budget -= xn_cost;
2490
2491 // induce demand across all categories
2492 // maybe we need some kind of banking and ability to save up money for future instead of spending them all...
2493
2494 float total_cost = ln_cost + en_cost + xn_cost;
2495
2496 if((total_budget > 0.f)) {
2497 float life_needs_budget = total_budget * state.defines.alice_needs_lf_spend;
2498 float everyday_needs_budget = total_budget * state.defines.alice_needs_ev_spend;
2499 float luxury_needs_budget = total_budget * state.defines.alice_needs_lx_spend;
2500
2501 float induced_life_needs_demand = life_needs_budget / std::max(0.001f, ln_cost);
2502 float induced_everyday_needs_demand = everyday_needs_budget / std::max(0.001f, en_cost);
2503 float induced_luxury_needs_demand = luxury_needs_budget / std::max(0.001f, xn_cost);
2504
2505 life_needs_fraction += induced_life_needs_demand;
2506 everyday_needs_fraction += induced_everyday_needs_demand;
2507 luxury_needs_fraction += induced_luxury_needs_demand;
2508 }
2509
2510 assert(std::isfinite(life_needs_fraction));
2511 assert(std::isfinite(everyday_needs_fraction));
2512 assert(std::isfinite(luxury_needs_fraction));
2513
2514 float old_life = pop_demographics::get_life_needs(state, pl.get_pop());
2515 float old_everyday = pop_demographics::get_everyday_needs(state, pl.get_pop());
2516 float old_luxury = pop_demographics::get_luxury_needs(state, pl.get_pop());
2517
2518 float old_life_to_use_in_demand_calculation = old_life;
2519 float old_everyday_to_use_in_demand_calculation = old_everyday;
2520 float old_luxury_to_use_in_demand_calculation = old_luxury;
2521
2522 float final_life_needs_fraction = life_needs_fraction + subsistence_life;
2523 float final_everyday_needs_fraction = everyday_needs_fraction + subsistence_everyday;
2524 float final_luxury_needs_fraction = luxury_needs_fraction + subsistence_luxury;
2525
2526 //suppose that old satisfaction was calculated for the same local subsistence conditions and find "raw" satisfaction
2527 // old = raw + sub ## first summand is "raw satisfaction"
2528 old_life_to_use_in_demand_calculation = std::clamp(old_life - subsistence_life, 0.f, 1.f);
2529 old_everyday_to_use_in_demand_calculation = std::clamp(old_everyday - subsistence_everyday, 0.f, 1.f);
2530 old_luxury_to_use_in_demand_calculation = std::clamp(old_luxury - subsistence_luxury, 0.f, 1.f);
2531
2532 auto result_life = std::clamp(old_life_to_use_in_demand_calculation * 0.9f + life_needs_fraction * 0.1f, 0.f, 1.f);
2533 auto result_everyday = std::clamp(old_everyday_to_use_in_demand_calculation * 0.9f + everyday_needs_fraction * 0.1f, 0.f, 1.f);
2534 auto result_luxury = std::clamp(old_luxury_to_use_in_demand_calculation * 0.9f + luxury_needs_fraction * 0.1f, 0.f, 1.f);
2535
2536 pop_demographics::set_life_needs(state, pl.get_pop(), std::clamp(old_life * 0.99f + final_life_needs_fraction * 0.01f, 0.f, 1.f));
2537 pop_demographics::set_everyday_needs(state, pl.get_pop(), std::clamp(old_everyday * 0.99f + final_everyday_needs_fraction * 0.01f, 0.f, 1.f));
2538 pop_demographics::set_luxury_needs(state, pl.get_pop(), std::clamp(old_luxury * 0.99f + final_luxury_needs_fraction * 0.01f, 0.f, 1.f));
2539
2540 ln_demand_vector.get(t) += result_life * total_pop / state.defines.alice_needs_scaling_factor;
2541 en_demand_vector.get(t) += result_everyday * total_pop / state.defines.alice_needs_scaling_factor;
2542 lx_demand_vector.get(t) += result_luxury * total_pop / state.defines.alice_needs_scaling_factor;
2543
2544 assert(std::isfinite(ln_demand_vector.get(t)));
2545 assert(std::isfinite(en_demand_vector.get(t)));
2546 assert(std::isfinite(lx_demand_vector.get(t)));
2547 }
2548 }
2549
2550 float ln_mul[] = {state.world.nation_get_modifier_values(n, sys::national_mod_offsets::poor_life_needs) + 1.0f,
2551 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::middle_life_needs) + 1.0f,
2552 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::rich_life_needs) + 1.0f};
2553 float en_mul[] = {state.world.nation_get_modifier_values(n, sys::national_mod_offsets::poor_everyday_needs) + 1.0f,
2554 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::middle_everyday_needs) + 1.0f,
2555 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::rich_everyday_needs) + 1.0f};
2556 float lx_mul[] = {
2557 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::poor_luxury_needs) + 1.0f,
2558 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::middle_luxury_needs) + 1.0f,
2559 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::rich_luxury_needs) + 1.0f,
2560 };
2561
2562 for(uint32_t i = 1; i < total_commodities; ++i) {
2563 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(i) };
2564 auto kf = state.world.commodity_get_key_factory(cid);
2565 if(state.world.commodity_get_is_available_from_start(cid) || (kf && state.world.nation_get_active_building(n, kf))) {
2566 for(const auto t : state.world.in_pop_type) {
2567 auto strata = state.world.pop_type_get_strata(t);
2568 float life_weight = state.world.nation_get_life_needs_weights(n, cid);
2569 float everyday_weight = state.world.nation_get_everyday_needs_weights(n, cid);
2570 float luxury_weight = state.world.nation_get_luxury_needs_weights(n, cid);
2571
2572 float base_life = state.world.pop_type_get_life_needs(t, cid);
2573 float base_everyday = state.world.pop_type_get_everyday_needs(t, cid);
2574 float base_luxury = state.world.pop_type_get_luxury_needs(t, cid);
2575
2576 float dist_life = ln_demand_vector.get(t);
2577 float dist_everyday = en_demand_vector.get(t);
2578 float dist_luxury = lx_demand_vector.get(t);
2579
2580 float demand_life = base_life * dist_life * base_demand * ln_mul[strata] * life_weight * state.defines.alice_lf_needs_scale;
2581 float demand_everyday = base_everyday * dist_everyday * base_demand * invention_factor * en_mul[strata] * everyday_weight * state.defines.alice_ev_needs_scale;
2582 float demand_luxury = base_luxury * dist_luxury * base_demand * invention_factor * lx_mul[strata] * luxury_weight * state.defines.alice_lx_needs_scale;
2583
2584 register_demand(state, n, cid, demand_life, economy_reason::pop);
2585 register_demand(state, n, cid, demand_everyday, economy_reason::pop);
2586 register_demand(state, n, cid, demand_luxury, economy_reason::pop);
2587 }
2588 }
2589 }
2590}
2591
2592void populate_needs_costs(sys::state& state, dcon::nation_id n, float base_demand, float invention_factor) {
2593 /*
2594 - Each pop strata and needs type has its own demand modifier, calculated as follows:
2595 - (national-modifier-to-goods-demand + define:BASE_GOODS_DEMAND) x (national-modifier-to-specific-strata-and-needs-type + 1) x
2596 (define:INVENTION_IMPACT_ON_DEMAND x number-of-unlocked-inventions + 1, but for non-life-needs only)
2597 - Each needs demand is also multiplied by 2 - the nation's administrative efficiency if the pop has education / admin /
2598 military income for that need category
2599 - We calculate an adjusted pop-size as (0.5 + pop-consciousness / define:PDEF_BASE_CON) x (for non-colonial pops: 1 +
2600 national-plurality (as a fraction of 100)) x pop-size
2601 */
2602
2603 uint32_t total_commodities = state.world.commodity_size();
2604
2605 float ln_mul[] = { state.world.nation_get_modifier_values(n, sys::national_mod_offsets::poor_life_needs) + 1.0f,
2606 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::middle_life_needs) + 1.0f,
2607 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::rich_life_needs) + 1.0f };
2608 float en_mul[] = { state.world.nation_get_modifier_values(n, sys::national_mod_offsets::poor_everyday_needs) + 1.0f,
2609 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::middle_everyday_needs) + 1.0f,
2610 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::rich_everyday_needs) + 1.0f };
2611 float lx_mul[] = { state.world.nation_get_modifier_values(n, sys::national_mod_offsets::poor_luxury_needs) + 1.0f,
2612 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::middle_luxury_needs) + 1.0f,
2613 state.world.nation_get_modifier_values(n, sys::national_mod_offsets::rich_luxury_needs) + 1.0f };
2614
2615 for(uint32_t i = 1; i < total_commodities; ++i) {
2616 dcon::commodity_id c{dcon::commodity_id::value_base_t(i)};
2617 auto kf = state.world.commodity_get_key_factory(c);
2618 if(state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf))) {
2619 float effective_price = state.world.nation_get_effective_prices(n, c);
2620 auto ln_weight = state.world.nation_get_life_needs_weights(n, c);
2621 auto en_weight = state.world.nation_get_everyday_needs_weights(n, c);
2622 auto lx_weight = state.world.nation_get_luxury_needs_weights(n, c);
2623
2624 state.world.for_each_pop_type([&](dcon::pop_type_id ids) {
2625 auto ln_base = state.world.pop_type_get_life_needs(ids, c);
2626 auto ln = ln_base * effective_price * base_demand * ln_mul[state.world.pop_type_get_strata(ids)] * ln_weight * state.defines.alice_lf_needs_scale;
2627 state.world.nation_set_life_needs_costs(n, ids, ln + state.world.nation_get_life_needs_costs(n, ids));
2628 auto en_base = state.world.pop_type_get_everyday_needs(ids, c);
2629 auto en = en_base * effective_price * base_demand * invention_factor * en_mul[state.world.pop_type_get_strata(ids)] * en_weight * state.defines.alice_ev_needs_scale;
2630 state.world.nation_set_everyday_needs_costs(n, ids, en + state.world.nation_get_everyday_needs_costs(n, ids));
2631 auto lx_base = state.world.pop_type_get_luxury_needs(ids, c);
2632 auto lx = lx_base * effective_price * base_demand * invention_factor * lx_mul[state.world.pop_type_get_strata(ids)] * lx_weight * state.defines.alice_lx_needs_scale;
2633 state.world.nation_set_luxury_needs_costs(n, ids, lx + state.world.nation_get_luxury_needs_costs(n, ids));
2634 assert(std::isfinite(state.world.nation_get_life_needs_costs(n, ids)) && state.world.nation_get_life_needs_costs(n, ids) >= 0.f);
2635 assert(std::isfinite(state.world.nation_get_everyday_needs_costs(n, ids)) && state.world.nation_get_everyday_needs_costs(n, ids) >= 0.f);
2636 assert(std::isfinite(state.world.nation_get_luxury_needs_costs(n, ids)) && state.world.nation_get_luxury_needs_costs(n, ids) >= 0.f);
2637 });
2638 }
2639 }
2640}
2641
2642void advance_construction(sys::state& state, dcon::nation_id n) {
2643 uint32_t total_commodities = state.world.commodity_size();
2644
2645 float c_spending = state.world.nation_get_spending_level(n) * float(state.world.nation_get_construction_spending(n)) / 100.0f;
2646 float p_spending = state.world.nation_get_private_investment_effective_fraction(n);
2647
2648 float refund_amount = 0.0f;
2649
2650 for(uint32_t i = 1; i < total_commodities; ++i) {
2651 dcon::commodity_id c{dcon::commodity_id::value_base_t(i)};
2652 auto d_sat = state.world.nation_get_demand_satisfaction(n, c);
2653 auto& nat_demand = state.world.nation_get_construction_demand(n, c);
2654 refund_amount += nat_demand * c_spending * (1.0f - d_sat) * state.world.commodity_get_current_price(c);
2655 nat_demand *= c_spending * d_sat;
2656 state.world.nation_get_private_construction_demand(n, c) *= p_spending * d_sat;
2657 }
2658
2659 assert(refund_amount >= 0.0f);
2660 state.world.nation_get_stockpiles(n, economy::money) += refund_amount;
2661
2662 float admin_eff = state.world.nation_get_administrative_efficiency(n);
2663 float admin_cost_factor = 2.0f - admin_eff;
2664
2665 for(auto p : state.world.nation_get_province_ownership(n)) {
2666 if(p.get_province().get_nation_from_province_control() != n)
2667 continue;
2668
2669 for(auto pops : p.get_province().get_pop_location()) {
2670 auto rng = pops.get_pop().get_province_land_construction();
2671 if(rng.begin() != rng.end()) {
2672 auto c = *(rng.begin());
2673 auto& base_cost = state.military_definitions.unit_base_definitions[c.get_type()].build_cost;
2674 auto& current_purchased = c.get_purchased_goods();
2675 float construction_time = global_non_factory_construction_time_modifier(state) * float(state.military_definitions.unit_base_definitions[c.get_type()].build_time);
2676
2677 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2678 if(base_cost.commodity_type[i]) {
2679 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * admin_cost_factor) {
2680 auto amount = base_cost.commodity_amounts[i] / construction_time;
2681 auto& source = state.world.nation_get_construction_demand(n, base_cost.commodity_type[i]);
2682 auto delta = std::max(0.0f, std::min(source, base_cost.commodity_amounts[i] / construction_time));
2683 current_purchased.commodity_amounts[i] += delta;
2684 source -= delta;
2685 }
2686 } else {
2687 break;
2688 }
2689 }
2690 break; // only advance one construction per province
2691 }
2692 }
2693 {
2694 auto rng = p.get_province().get_province_naval_construction();
2695 if(rng.begin() != rng.end()) {
2696 auto c = *(rng.begin());
2697 auto& base_cost = state.military_definitions.unit_base_definitions[c.get_type()].build_cost;
2698 auto& current_purchased = c.get_purchased_goods();
2699 float construction_time = global_non_factory_construction_time_modifier(state) * float(state.military_definitions.unit_base_definitions[c.get_type()].build_time);
2700
2701 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2702 if(base_cost.commodity_type[i]) {
2703 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * admin_cost_factor) {
2704 auto amount = base_cost.commodity_amounts[i] / construction_time;
2705 auto& source = state.world.nation_get_construction_demand(n, base_cost.commodity_type[i]);
2706 auto delta = std::max(0.0f, std::min(source, base_cost.commodity_amounts[i] / construction_time));
2707
2708 current_purchased.commodity_amounts[i] += delta;
2709 source -= delta;
2710 }
2711 } else {
2712 break;
2713 }
2714 }
2715 }
2716 }
2717 }
2718
2719 for(auto c : state.world.nation_get_province_building_construction(n)) {
2720 if(c.get_province().get_nation_from_province_ownership() == c.get_province().get_nation_from_province_control()) {
2721 auto t = economy::province_building_type(c.get_type());
2722 // Rationale for not checking the building type:
2723 // Pop projects created for forts and naval bases should NOT happen in the first place, so checking against them
2724 // is a waste of resources
2725 if(!c.get_is_pop_project()) {
2726 auto& base_cost = state.economy_definitions.building_definitions[int32_t(t)].cost;
2727 auto& current_purchased = c.get_purchased_goods();
2728 float construction_time = global_non_factory_construction_time_modifier(state) * float(state.economy_definitions.building_definitions[int32_t(t)].time);
2729
2730 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2731 if(base_cost.commodity_type[i]) {
2732 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * admin_cost_factor) {
2733 auto amount = base_cost.commodity_amounts[i] / construction_time;
2734 auto& source = state.world.nation_get_construction_demand(n, base_cost.commodity_type[i]);
2735 auto delta = std::max(0.0f, std::min(source, base_cost.commodity_amounts[i] / construction_time));
2736
2737 current_purchased.commodity_amounts[i] += delta;
2738 source -= delta;
2739 }
2740 } else {
2741 break;
2742 }
2743 }
2744 } else if(c.get_is_pop_project()) {
2745 auto& base_cost = state.economy_definitions.building_definitions[int32_t(t)].cost;
2746 auto& current_purchased = c.get_purchased_goods();
2747 float construction_time = global_non_factory_construction_time_modifier(state) * float(state.economy_definitions.building_definitions[int32_t(t)].time);
2748
2749 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2750 if(base_cost.commodity_type[i]) {
2751 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i]) {
2752 auto amount = base_cost.commodity_amounts[i] / construction_time;
2753 auto& source = state.world.nation_get_private_construction_demand(n, base_cost.commodity_type[i]);
2754 auto delta = std::max(0.0f, std::min(source, base_cost.commodity_amounts[i] / construction_time));
2755
2756 current_purchased.commodity_amounts[i] += delta;
2757 source -= delta;
2758 }
2759 } else {
2760 break;
2761 }
2762 }
2763 }
2764 }
2765 }
2766
2767 for(auto c : state.world.nation_get_state_building_construction(n)) {
2768 if(!c.get_is_pop_project()) {
2769 auto& base_cost = c.get_type().get_construction_costs();
2770 auto& current_purchased = c.get_purchased_goods();
2771 float construction_time = global_factory_construction_time_modifier(state) * float(c.get_type().get_construction_time()) * (c.get_is_upgrade() ? 0.1f : 1.0f);
2772 float factory_mod = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_cost) + 1.0f;
2773
2774 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2775 if(base_cost.commodity_type[i]) {
2776 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * factory_mod * admin_cost_factor) {
2777 auto amount = base_cost.commodity_amounts[i] / construction_time;
2778 auto& source = state.world.nation_get_construction_demand(n, base_cost.commodity_type[i]);
2779 auto delta = std::max(0.0f, std::min(source, base_cost.commodity_amounts[i] * factory_mod / construction_time));
2780
2781 current_purchased.commodity_amounts[i] += delta;
2782 source -= delta;
2783 }
2784 } else {
2785 break;
2786 }
2787 }
2788 } else {
2789 auto& base_cost = c.get_type().get_construction_costs();
2790 auto& current_purchased = c.get_purchased_goods();
2791 float construction_time = global_factory_construction_time_modifier(state) * float(c.get_type().get_construction_time()) * (c.get_is_upgrade() ? 0.1f : 1.0f);
2792 float factory_mod = (state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_cost) + 1.0f) *
2793 std::max(0.1f, state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_owner_cost));
2794
2795 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2796 if(base_cost.commodity_type[i]) {
2797 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * factory_mod) {
2798 auto amount = base_cost.commodity_amounts[i] / construction_time;
2799 auto& source = state.world.nation_get_private_construction_demand(n, base_cost.commodity_type[i]);
2800 auto delta = std::max(0.0f, std::min(source, base_cost.commodity_amounts[i] * factory_mod / construction_time));
2801
2802 current_purchased.commodity_amounts[i] += delta;
2803 source -= delta;
2804 }
2805 } else {
2806 break;
2807 }
2808 }
2809 }
2810 }
2811}
2812
2813float pop_min_wage_factor(sys::state& state, dcon::nation_id n) {
2814 return state.world.nation_get_modifier_values(n, sys::national_mod_offsets::minimum_wage);
2815}
2816
2817
2818float pop_farmer_min_wage(sys::state& state, dcon::nation_id n, float min_wage_factor) {
2819 float life = state.world.nation_get_life_needs_costs(n, state.culture_definitions.farmers);
2820 float everyday = state.world.nation_get_everyday_needs_costs(n, state.culture_definitions.farmers);
2821
2822 return min_wage_factor * (life + everyday) * 1.1f;
2823}
2824
2825float pop_laborer_min_wage(sys::state& state, dcon::nation_id n, float min_wage_factor) {
2826 float life = state.world.nation_get_life_needs_costs(n, state.culture_definitions.laborers);
2827 float everyday = state.world.nation_get_everyday_needs_costs(n, state.culture_definitions.laborers);
2828
2829 return min_wage_factor * (life + everyday) * 1.1f;
2830}
2831
2832float pop_factory_min_wage(sys::state& state, dcon::nation_id n, float min_wage_factor) {
2833 float employed = state.world.nation_get_demographics(n, demographics::to_employment_key(state, state.culture_definitions.primary_factory_worker));
2834 float total = state.world.nation_get_demographics(n, demographics::to_key(state, state.culture_definitions.primary_factory_worker));
2835
2836 float unemployement_crisis_measures = 1.f;
2837 if(total > 0.f) {
2838 unemployement_crisis_measures = employed / total;
2839 }
2840
2841 float life = state.world.nation_get_life_needs_costs(n, state.culture_definitions.primary_factory_worker);
2842 float everyday = state.world.nation_get_everyday_needs_costs(n, state.culture_definitions.primary_factory_worker);
2843
2844 return min_wage_factor * (life + everyday) * 1.1f * unemployement_crisis_measures * unemployement_crisis_measures * unemployement_crisis_measures;
2845}
2846
2847void populate_effective_prices(sys::state& state, dcon::nation_id n) {
2848 auto global_price_multiplier = global_market_price_multiplier(state, n);
2849 auto sl = state.world.nation_get_in_sphere_of(n);
2850 if(global_price_multiplier >= 1.0f) { // prefer domestic
2851 state.world.for_each_commodity([&](dcon::commodity_id c) {
2852 auto domestic_supply =
2853 state.world.nation_get_domestic_market_pool(n, c) + (sl ? state.world.nation_get_domestic_market_pool(sl, c) : 0.0f) +
2854 (state.world.nation_get_drawing_on_stockpiles(n, c) ? state.world.nation_get_stockpiles(n, c) : 0.0f);
2855 auto global_supply = state.world.commodity_get_global_market_pool(c);
2856 auto last_demand = state.world.nation_get_real_demand(n, c);
2857 auto base_price = state.world.commodity_get_current_price(c);
2858 if(last_demand <= domestic_supply) {
2859 state.world.nation_set_effective_prices(n, c, base_price);
2860 } else if(last_demand <= domestic_supply + global_supply) {
2861 auto domestic_satisfiable_fraction = domestic_supply / last_demand;
2862 state.world.nation_set_effective_prices(n, c, base_price * domestic_satisfiable_fraction +
2863 base_price * (1.0f - domestic_satisfiable_fraction) * global_price_multiplier);
2864 } else if(domestic_supply + global_supply > 0) {
2865 auto domestic_satisfiable_fraction = domestic_supply / (domestic_supply + global_supply);
2866 state.world.nation_set_effective_prices(n, c, base_price * domestic_satisfiable_fraction +
2867 base_price * (1.0f - domestic_satisfiable_fraction) * global_price_multiplier);
2868 } else {
2869 state.world.nation_set_effective_prices(n, c, base_price * global_price_multiplier);
2870 }
2871 assert(std::isfinite(state.world.nation_get_effective_prices(n, c)));
2872 });
2873 } else { // prefer global
2874 state.world.for_each_commodity([&](dcon::commodity_id c) {
2875 auto domestic_supply =
2876 state.world.nation_get_domestic_market_pool(n, c) + (sl ? state.world.nation_get_domestic_market_pool(sl, c) : 0.0f) +
2877 (state.world.nation_get_drawing_on_stockpiles(n, c) ? state.world.nation_get_stockpiles(n, c) : 0.0f);
2878 auto global_supply = state.world.commodity_get_global_market_pool(c);
2879 auto last_demand = state.world.nation_get_real_demand(n, c);
2880 auto base_price = state.world.commodity_get_current_price(c);
2881 if(last_demand <= global_supply) {
2882 state.world.nation_set_effective_prices(n, c, base_price);
2883 } else if(last_demand <= domestic_supply + global_supply) {
2884 auto global_satisfiable_fraction = global_supply / last_demand;
2885 state.world.nation_set_effective_prices(n, c, base_price * global_satisfiable_fraction * global_price_multiplier +
2886 base_price * (1.0f - global_satisfiable_fraction));
2887 } else if(domestic_supply + global_supply > 0) {
2888 auto global_satisfiable_fraction = global_supply / (domestic_supply + global_supply);
2889 state.world.nation_set_effective_prices(n, c, base_price * global_satisfiable_fraction * global_price_multiplier +
2890 base_price * (1.0f - global_satisfiable_fraction));
2891 } else {
2892 state.world.nation_set_effective_prices(n, c, base_price);
2893 }
2894 assert(std::isfinite(state.world.nation_get_effective_prices(n, c)));
2895 });
2896 }
2897}
2898
2903};
2904
2905profit_distribution distribute_factory_profit(sys::state const & state, dcon::state_instance_const_fat_id s, float min_wage, float total_profit) {
2906 float total_min_to_pworkers =
2907 min_wage * state.world.state_instance_get_demographics(s,
2908 demographics::to_employment_key(state, state.culture_definitions.primary_factory_worker));
2909 float total_min_to_sworkers =
2910 min_wage * state.world.state_instance_get_demographics(s,
2911 demographics::to_employment_key(state, state.culture_definitions.secondary_factory_worker));
2912
2913 float num_pworkers = state.world.state_instance_get_demographics(s,
2914 demographics::to_key(state, state.culture_definitions.primary_factory_worker));
2915 float num_sworkers = state.world.state_instance_get_demographics(s,
2916 demographics::to_key(state, state.culture_definitions.secondary_factory_worker));
2917 float num_owners = state.world.state_instance_get_demographics(s,
2918 demographics::to_key(state, state.culture_definitions.capitalists));
2919
2920 auto per_pworker_profit = 0.0f;
2921 auto per_sworker_profit = 0.0f;
2922 auto per_owner_profit = 0.0f;
2923
2924 if(total_min_to_pworkers + total_min_to_sworkers <= total_profit && num_owners > 0) {
2925 auto surplus = total_profit - (total_min_to_pworkers + total_min_to_sworkers);
2926 per_pworker_profit = num_pworkers > 0 ? (total_min_to_pworkers + surplus * 0.1f) / num_pworkers : 0.0f;
2927 per_sworker_profit = num_sworkers > 0 ? (total_min_to_sworkers + surplus * 0.2f) / num_sworkers : 0.0f;
2928 per_owner_profit = (surplus * 0.7f) / num_owners;
2929 } else if(total_min_to_pworkers + total_min_to_sworkers <= total_profit && num_sworkers > 0) {
2930 auto surplus = total_profit - (total_min_to_pworkers + total_min_to_sworkers);
2931 per_pworker_profit = num_pworkers > 0 ? (total_min_to_pworkers + surplus * 0.5f) / num_pworkers : 0.0f;
2932 per_sworker_profit = num_sworkers > 0 ? (total_min_to_sworkers + surplus * 0.5f) / num_sworkers : 0.0f;
2933 } else if(total_min_to_pworkers + total_min_to_sworkers <= total_profit) {
2934 per_pworker_profit = num_pworkers > 0 ? total_profit / num_pworkers : 0.0f;
2935 } else if(num_pworkers + num_sworkers > 0) {
2936 per_pworker_profit = total_profit / (num_pworkers + num_sworkers);
2937 per_sworker_profit = total_profit / (num_pworkers + num_sworkers);
2938 }
2939
2940
2941 return {
2942 .per_primary_worker = per_pworker_profit,
2943 .per_secondary_worker = per_sworker_profit,
2944 .per_owner = per_owner_profit
2945 };
2946}
2947
2948// this function partly emulates demand generated by nations
2949void emulate_construction_demand(sys::state& state, dcon::nation_id n) {
2950 float base_income =
2951 state.world.nation_get_total_rich_income(n)
2952 + state.world.nation_get_total_middle_income(n)
2953 + state.world.nation_get_total_poor_income(n) * 0.00001f;
2954
2955 // phase 1:
2956 // simulate spending on construction of units
2957 // useful to help the game start with some production of artillery and small arms
2958
2959 float income_to_build_units = base_income * 0.1f;
2960
2961 // we build infantry and artillery:
2962 auto infantry = state.military_definitions.infantry;
2963 auto artillery = state.military_definitions.artillery;
2964
2965 auto& infantry_def = state.military_definitions.unit_base_definitions[infantry];
2966 auto& artillery_def = state.military_definitions.unit_base_definitions[artillery];
2967
2968 float daily_cost = 0.f;
2969
2970 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2971 if(infantry_def.build_cost.commodity_type[i]) {
2972 auto price = state.world.commodity_get_current_price(infantry_def.build_cost.commodity_type[i]);
2973 daily_cost += infantry_def.build_cost.commodity_amounts[i] / infantry_def.build_time * price;
2974 } else {
2975 break;
2976 }
2977 }
2978 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2979 if(infantry_def.build_cost.commodity_type[i]) {
2980 auto price = state.world.commodity_get_current_price(artillery_def.build_cost.commodity_type[i]);
2981 daily_cost += artillery_def.build_cost.commodity_amounts[i] / artillery_def.build_time * price;
2982 } else {
2983 break;
2984 }
2985 }
2986
2987 auto pairs_to_build = income_to_build_units / (daily_cost + 1.f);
2988
2989 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2990 if(infantry_def.build_cost.commodity_type[i]) {
2991 auto daily_amount = infantry_def.build_cost.commodity_amounts[i] / infantry_def.build_time;
2992 register_demand(state, n, infantry_def.build_cost.commodity_type[i], daily_amount * pairs_to_build, economy_reason::construction);
2993 } else {
2994 break;
2995 }
2996 }
2997 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
2998 if(artillery_def.build_cost.commodity_type[i]) {
2999 auto daily_amount = artillery_def.build_cost.commodity_amounts[i] / artillery_def.build_time;
3000 register_demand(state, n, artillery_def.build_cost.commodity_type[i], daily_amount * pairs_to_build, economy_reason::construction);
3001 } else {
3002 break;
3003 }
3004 }
3005
3006 // phase 2:
3007 // simulate spending on construction of factories
3008 // helps with machine tools and cement
3009
3010 float income_to_build_factories = base_income * 0.1f;
3011
3012 // iterate over all factory types available from the start and find "average" daily construction cost:
3013
3014 std::vector<float> per_commodity;
3015 per_commodity.resize(state.world.commodity_size() + 2);
3016
3017 float sum_of_build_times = 0.f;
3018 float cost_factory_set = 0.f;
3019 float count = 0.f;
3020
3021 state.world.for_each_factory_type([&](dcon::factory_type_id factory_type) {
3022 if(!state.world.factory_type_get_is_available_from_start(factory_type)) {
3023 return;
3024 }
3025
3026 auto build_time = state.world.factory_type_get_construction_time(factory_type);
3027 auto& build_cost = state.world.factory_type_get_construction_costs(factory_type);
3028
3029 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
3030 if(build_cost.commodity_type[i]) {
3031 auto price = state.world.commodity_get_current_price(build_cost.commodity_type[i]);
3032 cost_factory_set += price * build_cost.commodity_amounts[i] / build_time;
3033 } else {
3034 break;
3035 }
3036 }
3037 count++;
3038 });
3039
3040
3041 // calculate amount of factory sets we are building:
3042 auto num_of_factory_sets = income_to_build_factories / (cost_factory_set + 1.f);
3043
3044 // emulate construction demand
3045 state.world.for_each_factory_type([&](dcon::factory_type_id factory_type) {
3046 if(!state.world.factory_type_get_is_available_from_start(factory_type)) {
3047 return;
3048 }
3049
3050 auto build_time = state.world.factory_type_get_construction_time(factory_type);
3051 auto& build_cost = state.world.factory_type_get_construction_costs(factory_type);
3052
3053 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
3054 if(build_cost.commodity_type[i]) {
3055 auto amount = build_cost.commodity_amounts[i];
3057 state,
3058 n,
3059 build_cost.commodity_type[i], amount / build_time * num_of_factory_sets,
3060 economy_reason::construction
3061 );
3062 } else {
3063 break;
3064 }
3065 }
3066 count++;
3067 });
3068}
3069
3070void daily_update(sys::state& state, bool initiate_buildings) {
3071
3072 /* initialization parallel block */
3073
3074 concurrency::parallel_for(0, 10, [&](int32_t index) {
3075 switch(index) {
3076 case 0:
3078 break;
3079 case 1:
3081 break;
3082 case 2:
3084 break;
3085 case 3:
3087 break;
3088 case 4:
3090 break;
3091 case 5:
3092 state.world.for_each_pop_type([&](dcon::pop_type_id t) {
3093 state.world.execute_serial_over_nation([&](auto nids) {
3094 state.world.nation_set_everyday_needs_costs(nids, t, ve::fp_vector{});
3095 });
3096 });
3097 break;
3098 case 6:
3099 state.world.for_each_pop_type([&](dcon::pop_type_id t) {
3100 state.world.execute_serial_over_nation([&](auto nids) {
3101 state.world.nation_set_luxury_needs_costs(nids, t, ve::fp_vector{});
3102 });
3103 });
3104 break;
3105 case 7:
3106 state.world.for_each_pop_type([&](dcon::pop_type_id t) {
3107 state.world.execute_serial_over_nation([&](auto nids) {
3108 state.world.nation_set_life_needs_costs(nids, t, ve::fp_vector{});
3109 });
3110 });
3111 break;
3112 case 8:
3113 state.world.execute_serial_over_nation([&](auto ids) {
3114 state.world.nation_set_subsidies_spending(ids, 0.0f);
3115 });
3116 break;
3117 case 9:
3118 state.world.execute_serial_over_nation([&](auto ids) {
3119 auto treasury = state.world.nation_get_stockpiles(ids, economy::money);
3120 state.world.nation_set_last_treasury(ids, treasury);
3121 });
3122 break;
3123 }
3124 });
3125
3126 /* end initialization parallel block */
3127
3128 auto const num_nation = state.world.nation_size();
3129 uint32_t total_commodities = state.world.commodity_size();
3130
3131 /*
3132 update scoring for provinces
3133 */
3134
3135 update_land_ownership(state);
3137
3138 /*
3139 As the day starts, we move production, fractionally, into the sphere leaders domestic production pool,
3140 following the same logic as Victoria 2
3141 */
3142
3143 {
3144 for(uint32_t i = 0; i < 8; i++) {
3145 state.world.for_each_commodity([&](dcon::commodity_id c) {
3146 state.world.commodity_set_demand_by_category(c, i, 0.f);
3147 });
3148 }
3149 }
3150
3151 for(auto n : state.nations_by_rank) {
3152 if(!n) // test for running out of sorted nations
3153 break;
3154 absorb_sphere_member_production(state, n); // no need for redundant checks here
3155 }
3156 for(auto n : state.nations_by_rank) {
3157 if(!n) // test for running out of sorted nations
3158 break;
3159 give_sphere_leader_production(state, n); // no need for redundant checks here
3160 }
3161
3162 for(auto n : state.nations_by_rank) {
3163 if(!n) // test for running out of sorted nations
3164 break;
3165
3166 // reset gdp
3167 state.world.nation_set_gdp(n, 0.f);
3168
3169 /*
3170 ### Calculate effective prices
3171 We will use the real demand from the *previous* day to determine how much of the purchasing will be done from the domestic
3172 and global pools (i.e. what percentage was able to be done from the cheaper pool). We will use that to calculate an
3173 effective price. And then, at the end of the current day, we will see how much of that purchasing actually came from each
3174 pool, etc. Depending on the stability of the simulation, we may, instead of taking the previous day, instead build this
3175 value iteratively as a linear combination of the new day and the previous day.
3176
3177 when purchasing from global supply, prices are multiplied by (the nation's current effective tariff rate + its blockaded
3178 fraction
3179 + 1)
3180 */
3181
3182 populate_effective_prices(state, n);
3183 auto global_price_multiplier = global_market_price_multiplier(state, n);
3184 auto sl = state.world.nation_get_in_sphere_of(n);
3185
3186 float base_demand =
3187 state.defines.base_goods_demand + state.world.nation_get_modifier_values(n, sys::national_mod_offsets::goods_demand);
3188
3189 int32_t num_inventions = 0;
3190 state.world.for_each_invention(
3191 [&](auto iid) { num_inventions += int32_t(state.world.nation_get_active_inventions(n, iid)); });
3192 float invention_factor = float(num_inventions) * state.defines.invention_impact_on_demand + 1.0f;
3193
3194 populate_needs_costs(state, n, base_demand, invention_factor);
3195
3196 float mobilization_impact = state.world.nation_get_is_mobilized(n) ? military::mobilization_impact(state, n) : 1.0f;
3197
3198 auto const min_wage_factor = pop_min_wage_factor(state, n);
3199 float factory_min_wage = pop_factory_min_wage(state, n, min_wage_factor);
3200 float artisan_min_wage = (
3201 1.0f * state.world.nation_get_life_needs_costs(n, state.culture_definitions.artisans)
3202 + 0.5f * state.world.nation_get_everyday_needs_costs(n, state.culture_definitions.artisans));
3203 float farmer_min_wage = pop_farmer_min_wage(state, n, min_wage_factor);
3204 float laborer_min_wage = pop_laborer_min_wage(state, n, min_wage_factor);
3205
3206 // clear real demand
3207 state.world.for_each_commodity([&](dcon::commodity_id c) {
3208 state.world.nation_set_real_demand(n, c, 0.0f);
3209 state.world.nation_set_intermediate_demand(n, c, 0.f);
3210 });
3211
3212 /*
3213 consumption updates
3214 */
3215 auto cap_prov = state.world.nation_get_capital(n);
3216 auto cap_continent = state.world.province_get_continent(cap_prov);
3217 auto cap_region = state.world.province_get_connected_region_id(cap_prov);
3218
3219 update_national_artisan_consumption(state, n, artisan_min_wage, mobilization_impact);
3220
3221 for(auto p : state.world.nation_get_province_ownership(n)) {
3222 for(auto f : state.world.province_get_factory_location(p.get_province())) {
3223 // factory
3224
3226 state,
3227 f.get_factory(),
3228 n,
3229 p.get_province(),
3230 p.get_province().get_state_membership(),
3231 mobilization_impact,
3232 factory_min_wage,
3233 p.get_province().get_nation_from_province_control() != n // is occupied
3234 );
3235 }
3236
3237 // rgo
3238 bool is_mine = state.world.commodity_get_is_mine(state.world.province_get_rgo(p.get_province()));
3239 update_province_rgo_consumption(state, p.get_province(), n, mobilization_impact,
3240 is_mine ? laborer_min_wage : farmer_min_wage, p.get_province().get_nation_from_province_control() != n);
3241 }
3242
3243 update_pop_consumption(state, n, base_demand, invention_factor);
3244
3245 {
3246 // update national spending
3247 //
3248 // step 1: figure out total
3249 float total = full_spending_cost(state, n);
3250
3251 // step 2: limit to actual budget
3252 float budget = 0.0f;
3253 float spending_scale = 0.0f;
3254 if(state.world.nation_get_is_player_controlled(n)) {
3255 auto& sp = state.world.nation_get_stockpiles(n, economy::money);
3256 sp -= interest_payment(state, n);
3257
3258 if(can_take_loans(state, n)) {
3259 budget = total;
3260 spending_scale = 1.0f;
3261 } else {
3262 budget = std::max(0.0f, state.world.nation_get_stockpiles(n, economy::money));
3263 spending_scale = (total < 0.001f || total <= budget) ? 1.0f : budget / total;
3264 }
3265 } else {
3266 budget = std::max(0.0f, state.world.nation_get_stockpiles(n, economy::money));
3267 spending_scale = (total < 0.001f || total <= budget) ? 1.0f : budget / total;
3268 }
3269
3270 assert(spending_scale >= 0);
3271 assert(std::isfinite(spending_scale));
3272 assert(std::isfinite(budget));
3273
3274 state.world.nation_get_stockpiles(n, economy::money) -= std::min(budget, total * spending_scale);
3275 state.world.nation_set_spending_level(n, spending_scale);
3276
3277 float pi_total = full_private_investment_cost(state, n);
3278 float pi_budget = state.world.nation_get_private_investment(n);
3279 auto pi_scale = pi_total <= pi_budget ? 1.0f : pi_budget / pi_total;
3280 state.world.nation_set_private_investment_effective_fraction(n, pi_scale);
3281 state.world.nation_set_private_investment(n, std::max(0.0f, pi_budget - pi_total));
3282
3283 update_national_consumption(state, n, spending_scale, pi_scale);
3284 }
3285
3286 /*
3287 perform actual consumption / purchasing subject to availability
3288 */
3289
3290 for(uint32_t i = 1; i < total_commodities; ++i) {
3291 dcon::commodity_id c{ dcon::commodity_id::value_base_t(i) };
3292
3293 auto dom_pool = state.world.nation_get_domestic_market_pool(n, c);
3294 auto sl_pool = (sl ? state.world.nation_get_domestic_market_pool(sl, c) : 0.0f);
3295 auto sp_pool = (state.world.nation_get_drawing_on_stockpiles(n, c) ? state.world.nation_get_stockpiles(n, c) : 0.0f);
3296 auto wm_pool = state.world.commodity_get_global_market_pool(c);
3297
3298 auto total_supply = dom_pool + sl_pool + sp_pool + wm_pool;
3299
3300 auto rd = state.world.nation_get_real_demand(n, c);
3301 auto old_sat = state.world.nation_get_demand_satisfaction(n, c);
3302 auto new_sat = rd > 0.0001f ? total_supply / rd : total_supply;
3303 auto adj_sat = old_sat * state.defines.alice_sat_delay_factor + new_sat * (1.0f - state.defines.alice_sat_delay_factor);
3304 state.world.nation_set_demand_satisfaction(n, c, std::min(1.0f, adj_sat));
3305 state.world.nation_set_direct_demand_satisfaction(n, c, std::min(1.0f, new_sat));
3306
3307 if(global_price_multiplier >= 1.0f) { // prefer domestic
3308 state.world.nation_set_domestic_market_pool(n, c, std::max(0.0f, dom_pool - rd));
3309 rd = std::max(rd - dom_pool, 0.0f);
3310 if(sl) {
3311 state.world.nation_set_domestic_market_pool(sl, c, std::max(0.0f, sl_pool - rd));
3312 rd = std::max(rd - sl_pool, 0.0f);
3313 }
3314 if(state.world.nation_get_drawing_on_stockpiles(n, c)) {
3315 state.world.nation_set_stockpiles(n, c, std::max(0.0f, sp_pool - rd));
3316 rd = std::max(rd - sp_pool, 0.0f);
3317 }
3318 state.world.commodity_set_global_market_pool(c, std::max(0.0f, wm_pool - rd));
3319
3320 state.world.nation_set_imports(n, c, std::min(wm_pool, rd));
3321 } else {
3322 state.world.nation_set_imports(n, c, std::min(wm_pool, rd));
3323
3324 state.world.commodity_set_global_market_pool(c, std::max(0.0f, wm_pool - rd));
3325 rd = std::max(rd - wm_pool, 0.0f);
3326
3327 state.world.nation_set_domestic_market_pool(n, c, std::max(0.0f, dom_pool - rd));
3328 rd = std::max(rd - dom_pool, 0.0f);
3329 if(sl) {
3330 state.world.nation_set_domestic_market_pool(sl, c, std::max(0.0f, sl_pool - rd));
3331 rd = std::max(rd - sl_pool, 0.0f);
3332 }
3333 if(state.world.nation_get_drawing_on_stockpiles(n, c)) {
3334 state.world.nation_set_stockpiles(n, c, std::max(0.0f, sp_pool - rd));
3335 }
3336 }
3337 }
3338 }
3339
3340 /*
3341 move remaining domestic supply to global pool, clear domestic market
3342 */
3343 state.world.for_each_commodity([&](dcon::commodity_id c) {
3344 // per good decay would be nice...
3345 float decay = 0.5f;
3346 float world_pool = state.world.commodity_get_global_market_pool(c) * decay;
3347 ve::fp_vector sum;
3348 state.world.execute_serial_over_nation([&](auto nids) {
3349 sum = sum + state.world.nation_get_domestic_market_pool(nids, c);
3350 state.world.nation_set_domestic_market_pool(nids, c, 0.0f);
3351 });
3352 state.world.commodity_set_global_market_pool(c, world_pool + sum.reduce());
3353 });
3354
3355 /*
3356 pay non "employed" pops (also zeros money for "employed" pops)
3357 */
3358
3359 state.world.execute_parallel_over_pop([&](auto ids) {
3360 auto owners = nations::owner_of_pop(state, ids);
3361 auto owner_spending = state.world.nation_get_spending_level(owners);
3362
3363 auto pop_of_type = state.world.pop_get_size(ids);
3364 auto adj_pop_of_type = pop_of_type / state.defines.alice_needs_scaling_factor;
3365
3366 auto const a_spending = owner_spending * ve::to_float(state.world.nation_get_administrative_spending(owners)) * ve::to_float(state.world.nation_get_administrative_spending(owners)) / 100.0f / 100.f;
3367 auto const s_spending = owner_spending * state.world.nation_get_administrative_efficiency(owners) *
3368 ve::to_float(state.world.nation_get_social_spending(owners)) / 100.0f;
3369 auto const e_spending = owner_spending * ve::to_float(state.world.nation_get_education_spending(owners)) * ve::to_float(state.world.nation_get_education_spending(owners)) / 100.0f / 100.f;
3370 auto const m_spending = owner_spending * ve::to_float(state.world.nation_get_military_spending(owners)) * ve::to_float(state.world.nation_get_military_spending(owners)) / 100.0f / 100.0f;
3371 auto const p_level = state.world.nation_get_modifier_values(owners, sys::national_mod_offsets::pension_level);
3372 auto const unemp_level = state.world.nation_get_modifier_values(owners, sys::national_mod_offsets::unemployment_benefit);
3373 auto const di_level = owner_spending * ve::to_float(state.world.nation_get_domestic_investment_spending(owners)) * ve::to_float(state.world.nation_get_domestic_investment_spending(owners)) / 100.0f / 100.f;
3374
3375 auto types = state.world.pop_get_poptype(ids);
3376
3377 auto ln_types = state.world.pop_type_get_life_needs_income_type(types);
3378 auto en_types = state.world.pop_type_get_everyday_needs_income_type(types);
3379 auto lx_types = state.world.pop_type_get_luxury_needs_income_type(types);
3380
3381 auto ln_costs = ve::apply(
3382 [&](dcon::pop_type_id pt, dcon::nation_id n) { return pt ? state.world.nation_get_life_needs_costs(n, pt) : 0.0f; },
3383 types, owners);
3384 auto en_costs = ve::apply(
3385 [&](dcon::pop_type_id pt, dcon::nation_id n) { return pt ? state.world.nation_get_everyday_needs_costs(n, pt) : 0.0f; },
3386 types, owners);
3387 auto lx_costs = ve::apply(
3388 [&](dcon::pop_type_id pt, dcon::nation_id n) { return pt ? state.world.nation_get_luxury_needs_costs(n, pt) : 0.0f; },
3389 types, owners);
3390
3391 auto acc_a =
3392 ve::select(ln_types == int32_t(culture::income_type::administration), a_spending * adj_pop_of_type * ln_costs, 0.0f);
3393 auto acc_e = ve::select(ln_types == int32_t(culture::income_type::education), e_spending * adj_pop_of_type * ln_costs, 0.0f);
3394 auto acc_m = ve::select(ln_types == int32_t(culture::income_type::military), m_spending * adj_pop_of_type * ln_costs, 0.0f);
3395
3396 auto none_of_above = ln_types != int32_t(culture::income_type::military) &&
3397 ln_types != int32_t(culture::income_type::education) &&
3398 ln_types != int32_t(culture::income_type::administration);
3399
3400 auto acc_u = ve::select(none_of_above, s_spending * adj_pop_of_type * p_level * ln_costs, 0.0f);
3401
3402 acc_a = acc_a + ve::select(en_types == int32_t(culture::income_type::administration), a_spending * adj_pop_of_type * en_costs, 0.0f);
3403 acc_e = acc_e + ve::select(en_types == int32_t(culture::income_type::education), e_spending * adj_pop_of_type * en_costs, 0.0f);
3404 acc_m = acc_m + ve::select(en_types == int32_t(culture::income_type::military), m_spending * adj_pop_of_type * en_costs, 0.0f);
3405
3406 acc_u = acc_u + ve::select(types == state.culture_definitions.capitalists, di_level * adj_pop_of_type * state.defines.alice_domestic_investment_multiplier * lx_costs, 0.0f);
3407 acc_u = acc_u + ve::select(types == state.culture_definitions.aristocrat, di_level * adj_pop_of_type * state.defines.alice_domestic_investment_multiplier * lx_costs, 0.0f);
3408
3409 acc_a = acc_a + ve::select(lx_types == int32_t(culture::income_type::administration), a_spending * adj_pop_of_type * lx_costs, 0.0f);
3410 acc_e = acc_e + ve::select(lx_types == int32_t(culture::income_type::education), e_spending * adj_pop_of_type * lx_costs, 0.0f);
3411 acc_m = acc_m + ve::select(lx_types == int32_t(culture::income_type::military), m_spending * adj_pop_of_type * lx_costs, 0.0f);
3412
3413 auto employment = pop_demographics::get_employment(state, ids);
3414
3415 acc_u = acc_u + ve::select(none_of_above && state.world.pop_type_get_has_unemployment(types),
3416 s_spending * (pop_of_type - employment) / state.defines.alice_needs_scaling_factor * unemp_level * ln_costs, 0.0f);
3417
3418 state.world.pop_set_savings(ids, state.inflation * ((acc_e + acc_m) + (acc_u + acc_a)));
3419#ifndef NDEBUG
3420 ve::apply([](float v) { assert(std::isfinite(v) && v >= 0); }, acc_e);
3421 ve::apply([](float v) { assert(std::isfinite(v) && v >= 0); }, acc_m);
3422 ve::apply([](float v) { assert(std::isfinite(v) && v >= 0); }, acc_u);
3423 ve::apply([](float v) { assert(std::isfinite(v) && v >= 0); }, acc_a);
3424#endif
3425 });
3426
3427 /* add up production, collect taxes and tariffs, other updates purely internal to each nation */
3428 concurrency::parallel_for(uint32_t(0), state.world.nation_size(), [&](uint32_t i) {
3429 auto n = dcon::nation_id{ dcon::nation_id::value_base_t(i) };
3430
3431 if(state.world.nation_get_owned_province_count(n) == 0)
3432 return;
3433
3434 /* prepare needs satisfaction caps */
3435 ve::vectorizable_buffer<float, dcon::pop_type_id> ln_max = state.world.pop_type_make_vectorizable_float_buffer();
3436 ve::vectorizable_buffer<float, dcon::pop_type_id> en_max = state.world.pop_type_make_vectorizable_float_buffer();
3437 ve::vectorizable_buffer<float, dcon::pop_type_id> lx_max = state.world.pop_type_make_vectorizable_float_buffer();
3438 uint32_t total_commodities = state.world.commodity_size();
3439 state.world.for_each_pop_type([&](dcon::pop_type_id pt) {
3440 float ln_total = 0.0f;
3441 float en_total = 0.0f;
3442 float lx_total = 0.0f;
3443 for(uint32_t i = 1; i < total_commodities; ++i) {
3444 dcon::commodity_id c{ dcon::commodity_id::value_base_t(i) };
3445 auto kf = state.world.commodity_get_key_factory(c);
3446 if(state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf))) {
3447 auto sat = state.world.nation_get_demand_satisfaction(n, c);
3448
3449 auto ln_val = state.world.pop_type_get_life_needs(pt, c) * state.world.nation_get_life_needs_weights(n, c);
3450 ln_total += ln_val;
3451 ln_max.get(pt) += ln_val * sat;
3452
3453 auto en_val = state.world.pop_type_get_everyday_needs(pt, c) * state.world.nation_get_everyday_needs_weights(n, c);
3454 en_total += en_val;
3455 en_max.get(pt) += en_val * sat;
3456
3457 auto lx_val = state.world.pop_type_get_luxury_needs(pt, c) * state.world.nation_get_luxury_needs_weights(n, c);
3458 lx_total += lx_val;
3459 lx_max.get(pt) += lx_val * sat;
3460 }
3461 }
3462
3463 if(ln_total > 0)
3464 ln_max.get(pt) /= ln_total;
3465 else
3466 ln_max.get(pt) = 1.f;
3467
3468 if(en_total > 0)
3469 en_max.get(pt) /= en_total;
3470 else
3471 en_max.get(pt) = 1.f;
3472
3473 if(lx_total > 0)
3474 lx_max.get(pt) /= lx_total;
3475 else
3476 lx_max.get(pt) = 1.f;
3477 });
3478
3479 /*
3480 determine effective spending levels
3481 */
3482 auto nations_commodity_spending = state.world.nation_get_spending_level(n);
3483 float refund = 0.0f;
3484 {
3485 float max_sp = 0.0f;
3486 float total = 0.0f;
3487 float spending_level = float(state.world.nation_get_naval_spending(n)) / 100.0f;
3488 for(uint32_t k = 1; k < total_commodities; ++k) {
3489 dcon::commodity_id c{ dcon::commodity_id::value_base_t(k) };
3490
3491 auto sat = state.world.nation_get_demand_satisfaction(n, c);
3492 auto val = state.world.nation_get_navy_demand(n, c);
3493 auto delta = val * (1.0f - sat) * nations_commodity_spending * spending_level * state.world.commodity_get_current_price(c);
3494 assert(delta >= 0.f);
3495 refund += delta;
3496 total += val;
3497 max_sp += val * sat;
3498 }
3499 if(total > 0.f)
3500 max_sp /= total;
3501 state.world.nation_set_effective_naval_spending(n, nations_commodity_spending * max_sp * spending_level);
3502 }
3503 {
3504 float max_sp = 0.0f;
3505 float total = 0.0f;
3506 float spending_level = float(state.world.nation_get_land_spending(n)) / 100.0f;
3507 for(uint32_t k = 1; k < total_commodities; ++k) {
3508 dcon::commodity_id c{ dcon::commodity_id::value_base_t(k) };
3509
3510 auto sat = state.world.nation_get_demand_satisfaction(n, c);
3511 auto val = state.world.nation_get_army_demand(n, c);
3512 auto delta = val * (1.0f - sat) * nations_commodity_spending * spending_level * state.world.commodity_get_current_price(c);
3513 assert(delta >= 0.f);
3514 refund += delta;
3515 total += val;
3516 max_sp += val * sat;
3517 }
3518 if(total > 0.f)
3519 max_sp /= total;
3520 state.world.nation_set_effective_land_spending(n, nations_commodity_spending * max_sp * spending_level);
3521 }
3522 {
3523 float max_sp = 0.0f;
3524 float total = 0.0f;
3525 float spending_level = float(state.world.nation_get_construction_spending(n)) / 100.0f;
3526 for(uint32_t k = 1; k < total_commodities; ++k) {
3527 dcon::commodity_id c{ dcon::commodity_id::value_base_t(k) };
3528 // no refund: adjusted for satisfaction in advance_construction
3529 auto sat = state.world.nation_get_demand_satisfaction(n, c);
3530 auto val = state.world.nation_get_construction_demand(n, c);
3531 total += val;
3532 max_sp += val * sat;
3533 }
3534 if(total > 0.f)
3535 max_sp /= total;
3536 state.world.nation_set_effective_construction_spending(n, nations_commodity_spending * max_sp * spending_level);
3537 }
3538 /*
3539 fill stockpiles
3540 */
3541
3542 for(uint32_t k = 1; k < total_commodities; ++k) {
3543 dcon::commodity_id c{ dcon::commodity_id::value_base_t(k) };
3544 auto difference = state.world.nation_get_stockpile_targets(n, c) - state.world.nation_get_stockpiles(n, c);
3545 if(difference > 0.f && state.world.nation_get_drawing_on_stockpiles(n, c) == false) {
3546 auto sat = state.world.nation_get_direct_demand_satisfaction(n, c);
3547 state.world.nation_get_stockpiles(n, c) += difference * nations_commodity_spending * sat;
3548 auto delta =
3549 difference
3550 * (1.0f - sat)
3551 * nations_commodity_spending
3552 * state.world.commodity_get_current_price(c);
3553 assert(delta >= 0.f);
3554 refund += delta;
3555 }
3556 }
3557
3558 /*
3559 calculate overseas penalty
3560 */
3561
3562 {
3563 auto overseas_factor = state.defines.province_overseas_penalty * float(state.world.nation_get_owned_province_count(n) - state.world.nation_get_central_province_count(n));
3564 auto overseas_budget = float(state.world.nation_get_overseas_spending(n)) / 100.f;
3565 auto overseas_budget_satisfaction = 1.f;
3566
3567 if(overseas_factor > 0) {
3568 for(uint32_t k = 1; k < total_commodities; ++k) {
3569 dcon::commodity_id c{ dcon::commodity_id::value_base_t(k) };
3570 auto kf = state.world.commodity_get_key_factory(c);
3571 if(state.world.commodity_get_overseas_penalty(c) &&
3572 (state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf)))) {
3573 auto sat = state.world.nation_get_demand_satisfaction(n, c);
3574 overseas_budget_satisfaction = std::min(sat, overseas_budget_satisfaction);
3575 auto price = state.world.commodity_get_current_price(c);
3576 auto delta = overseas_factor * (1.0f - sat) * nations_commodity_spending * price;
3577 assert(delta >= 0.f);
3578 refund += delta;
3579 }
3580 }
3581
3582 state.world.nation_set_overseas_penalty(n, overseas_budget * overseas_budget_satisfaction);
3583 } else {
3584 state.world.nation_set_overseas_penalty(n, 1.0f);
3585 }
3586 }
3587
3588 assert(std::isfinite(refund) && refund >= 0.0f);
3589 state.world.nation_get_stockpiles(n, money) += refund;
3590
3591 auto const min_wage_factor = pop_min_wage_factor(state, n);
3592
3593 float factory_min_wage = pop_factory_min_wage(state, n, min_wage_factor);
3594 float farmer_min_wage = pop_farmer_min_wage(state, n, min_wage_factor);
3595 float laborer_min_wage = pop_laborer_min_wage(state, n, min_wage_factor);
3596
3598
3599 for(auto p : state.world.nation_get_province_ownership(n)) {
3600 /*
3601 perform production
3602 */
3603
3604 for(auto f : state.world.province_get_factory_location(p.get_province())) {
3605 // factory
3606 update_single_factory_production(state, f.get_factory(), n, factory_min_wage);
3607 }
3608
3609 // artisan
3610 //update_province_artisan_production(state, p.get_province(), n);
3611
3612 // rgo
3613 update_province_rgo_production(state, p.get_province(), n);
3614
3615 /* adjust pop satisfaction based on consumption and subsistence */
3616
3617 float subsistence = adjusted_subsistence_score(state, p.get_province());
3618 float subsistence_life = std::clamp(subsistence, 0.f, subsistence_score_life);
3619 subsistence -= subsistence_life;
3620 float subsistence_everyday = std::clamp(subsistence, 0.f, subsistence_score_everyday);
3621 subsistence -= subsistence_everyday;
3622 float subsistence_luxury = std::clamp(subsistence, 0.f, subsistence_score_luxury);
3623
3624 subsistence_life /= subsistence_score_life;
3625 subsistence_everyday /= subsistence_score_everyday;
3626 subsistence_luxury /= subsistence_score_luxury;
3627
3628 for(auto pl : p.get_province().get_pop_location()) {
3629 auto t = pl.get_pop().get_poptype();
3630
3631 auto ln = pop_demographics::get_life_needs(state, pl.get_pop());
3632 auto en = pop_demographics::get_everyday_needs(state, pl.get_pop());
3633 auto lx = pop_demographics::get_luxury_needs(state, pl.get_pop());
3634
3635
3636 // sat = raw + sub ## first summand is "raw satisfaction"
3637 ln -= subsistence_life;
3638 en -= subsistence_everyday;
3639 lx -= subsistence_luxury;
3640
3641 ln = std::min(ln, ln_max.get(t));
3642 en = std::min(en, en_max.get(t));
3643 lx = std::min(lx, lx_max.get(t));
3644
3645 ln += subsistence_life;
3646 en += subsistence_everyday;
3647 lx += subsistence_luxury;
3648
3649 pop_demographics::set_life_needs(state, pl.get_pop(), ln);
3650 pop_demographics::set_everyday_needs(state, pl.get_pop(), en);
3651 pop_demographics::set_luxury_needs(state, pl.get_pop(), lx);
3652 }
3653 }
3654
3655 /*
3656 pay "employed" pops
3657 */
3658
3659 {
3660 // ARTISAN
3661 auto const artisan_type = state.culture_definitions.artisans;
3662 float artisan_profit = state.world.nation_get_artisan_profit(n);
3663 float num_artisans = state.world.nation_get_demographics(n, demographics::to_key(state, artisan_type));
3664 if(num_artisans > 0) {
3665 auto per_profit = artisan_profit / num_artisans;
3666
3667 for(auto p : state.world.nation_get_province_ownership(n)) {
3668 for(auto pl : p.get_province().get_pop_location()) {
3669 if(artisan_type == pl.get_pop().get_poptype()) {
3670 pl.get_pop().set_savings(pl.get_pop().get_savings() + state.inflation * pl.get_pop().get_size() * per_profit);
3671 assert(std::isfinite(pl.get_pop().get_savings()) && pl.get_pop().get_savings() >= 0);
3672 }
3673 }
3674 }
3675 }
3676 }
3677
3678 /*
3679 pay factory workers / capitalists
3680 */
3681
3682 for(auto si : state.world.nation_get_state_ownership(n)) {
3683 float total_profit = 0.f;
3684 float rgo_owner_profit = 0.f;
3685
3686 float num_capitalist = state.world.state_instance_get_demographics(
3687 si.get_state(),
3688 demographics::to_key(state, state.culture_definitions.capitalists)
3689 );
3690
3691 float num_aristocrat = state.world.state_instance_get_demographics(
3692 si.get_state(),
3693 demographics::to_key(state, state.culture_definitions.aristocrat)
3694 );
3695
3696 float num_rgo_owners = num_capitalist + num_aristocrat;
3697
3698 auto capitalists_ratio = num_capitalist / (num_rgo_owners + 1.f);
3699 auto aristocrats_ratio = num_aristocrat / (num_rgo_owners + 1.f);
3700
3701 province::for_each_province_in_state_instance(state, si.get_state(), [&](dcon::province_id p) {
3702 for(auto f : state.world.province_get_factory_location(p)) {
3703 total_profit += std::max(0.f, f.get_factory().get_full_profit());
3704 }
3705
3706 {
3707 // FARMER / LABORER
3708 bool is_mine = state.world.commodity_get_is_mine(state.world.province_get_rgo(p));
3709 //auto const worker = is_mine ? state.culture_definitions.laborers : state.culture_definitions.farmers;
3710
3711 auto const min_wage = (is_mine ? laborer_min_wage : farmer_min_wage) / state.defines.alice_needs_scaling_factor;
3712
3713 float total_min_to_workers = 0.0f;
3714 float num_workers = 0.0f;
3715 for(auto wt : state.culture_definitions.rgo_workers) {
3716 total_min_to_workers += min_wage * state.world.province_get_demographics(p, demographics::to_employment_key(state, wt));
3717 num_workers += state.world.province_get_demographics(p, demographics::to_key(state, wt));
3718 }
3719 float total_rgo_profit = state.world.province_get_rgo_full_profit(p);
3720 float total_worker_wage = 0.0f;
3721
3722 if(num_rgo_owners > 0) {
3723 // owners ALWAYS get "some" chunk of income
3724 rgo_owner_profit += rgo_owners_cut * total_rgo_profit;
3725 total_rgo_profit = (1.f - rgo_owners_cut) * total_rgo_profit;
3726 }
3727
3728 if(total_min_to_workers <= total_rgo_profit && num_rgo_owners > 0) {
3729 total_worker_wage = total_min_to_workers + (total_rgo_profit - total_min_to_workers) * 0.2f;
3730 rgo_owner_profit += (total_rgo_profit - total_min_to_workers) * 0.8f;
3731 } else {
3732 total_worker_wage = total_rgo_profit;
3733 }
3734
3735 auto per_worker_profit = num_workers > 0 ? total_worker_wage / num_workers : 0.0f;
3736
3737 for(auto pl : state.world.province_get_pop_location(p)) {
3738 if(pl.get_pop().get_poptype().get_is_paid_rgo_worker()) {
3739 pl.get_pop().set_savings(pl.get_pop().get_savings() + state.inflation * pl.get_pop().get_size() * per_worker_profit);
3740 assert(std::isfinite(pl.get_pop().get_savings()) && pl.get_pop().get_savings() >= 0);
3741 }
3742 }
3743 }
3744 });
3745
3746 auto const per_rgo_owner_profit = num_rgo_owners > 0 ? rgo_owner_profit / num_rgo_owners : 0.0f;
3747
3748 auto const min_wage = factory_min_wage / state.defines.alice_needs_scaling_factor;
3749
3750 auto profit = distribute_factory_profit(state, si.get_state(), min_wage, total_profit);
3751
3752 province::for_each_province_in_state_instance(state, si.get_state(), [&](dcon::province_id p) {
3753 for(auto pl : state.world.province_get_pop_location(p)) {
3754 if(state.culture_definitions.primary_factory_worker == pl.get_pop().get_poptype()) {
3755 pl.get_pop().set_savings(pl.get_pop().get_savings() + state.inflation * pl.get_pop().get_size() * profit.per_primary_worker);
3756 assert(std::isfinite(pl.get_pop().get_savings()) && pl.get_pop().get_savings() >= 0);
3757 } else if(state.culture_definitions.secondary_factory_worker == pl.get_pop().get_poptype()) {
3758 pl.get_pop().set_savings(pl.get_pop().get_savings() + state.inflation * pl.get_pop().get_size() * profit.per_secondary_worker);
3759 assert(std::isfinite(pl.get_pop().get_savings()) && pl.get_pop().get_savings() >= 0);
3760 } else if(state.culture_definitions.capitalists == pl.get_pop().get_poptype()) {
3761 pl.get_pop().set_savings(pl.get_pop().get_savings() + state.inflation * pl.get_pop().get_size() * (profit.per_owner + per_rgo_owner_profit));
3762 assert(std::isfinite(pl.get_pop().get_savings()) && pl.get_pop().get_savings() >= 0);
3763 } else if(state.culture_definitions.aristocrat == pl.get_pop().get_poptype()) {
3764 pl.get_pop().set_savings(pl.get_pop().get_savings() + state.inflation * pl.get_pop().get_size() * per_rgo_owner_profit);
3765 assert(std::isfinite(pl.get_pop().get_savings()) && pl.get_pop().get_savings() >= 0);
3766 }
3767 }
3768 });
3769 }
3770
3771 /* advance construction */
3772 advance_construction(state, n);
3773
3774 if(!initiate_buildings) {
3776 }
3777
3778 /* collect and distribute money for private education */
3779 auto edu_money = 0.f;
3780 auto adm_money = 0.f;
3781 auto const edu_adm_spending = 0.05f;
3782 auto const edu_adm_effect = 1.f - edu_adm_spending;
3783 auto const education_ratio = 0.8f;
3784 for(auto p : state.world.nation_get_province_ownership(n)) {
3785 auto province = p.get_province();
3786 if(state.world.province_get_nation_from_province_ownership(province) == state.world.province_get_nation_from_province_control(province)) {
3787 float current = 0.f;
3788 float local_teachers = 0.f;
3789 float local_managers = 0.f;
3790 for(auto pl : province.get_pop_location()) {
3791 auto pop = pl.get_pop();
3792 auto pt = pop.get_poptype();
3793 auto ln_type = culture::income_type(state.world.pop_type_get_life_needs_income_type(pt));
3795 local_managers += pop.get_size();
3796 } else if(ln_type == culture::income_type::education) {
3797 local_teachers += pop.get_size();
3798 }
3799 }
3800 if(local_teachers + local_managers > 0.f) {
3801 for(auto pl : province.get_pop_location()) {
3802 auto const pop_money = pl.get_pop().get_savings();
3803 current += pop_money * edu_adm_spending;
3804 pl.get_pop().set_savings(pop_money * edu_adm_effect);
3805 }
3806 }
3807 float local_education_ratio = education_ratio;
3808 if(local_managers == 0.f) {
3809 local_education_ratio = 1.f;
3810 }
3811 for(auto pl : province.get_pop_location()) {
3812 auto pop = pl.get_pop();
3813 auto pt = pop.get_poptype();
3814 auto ln_type = culture::income_type(state.world.pop_type_get_life_needs_income_type(pt));
3816 float ratio = pop.get_size() / local_managers;
3817 pop.set_savings(pop.get_savings() + current * (1.f - local_education_ratio) * ratio);
3818 adm_money += current * (1.f - local_education_ratio) * ratio;
3819 } else if(ln_type == culture::income_type::education) {
3820 float ratio = pop.get_size() / local_teachers;
3821 pop.set_savings(pop.get_savings() + current * local_education_ratio * ratio);
3822 edu_money += current * local_education_ratio * ratio;
3823 }
3824 }
3825 }
3826 }
3827 state.world.nation_set_private_investment_education(n, edu_money);
3828 state.world.nation_set_private_investment_administration(n, adm_money);
3829
3830 /*
3831 collect taxes
3832 */
3833
3834 auto const tax_eff = nations::tax_efficiency(state, n);
3835
3836 float total_poor_tax_base = 0.0f;
3837 float total_mid_tax_base = 0.0f;
3838 float total_rich_tax_base = 0.0f;
3839
3840 auto const poor_effect = (1.0f - tax_eff * float(state.world.nation_get_poor_tax(n)) / 100.0f);
3841 auto const middle_effect = (1.0f - tax_eff * float(state.world.nation_get_middle_tax(n)) / 100.0f);
3842 auto const rich_effect = (1.0f - tax_eff * float(state.world.nation_get_rich_tax(n)) / 100.0f);
3843
3844 assert(poor_effect >= 0 && middle_effect >= 0 && rich_effect >= 0);
3845
3846 for(auto p : state.world.nation_get_province_ownership(n)) {
3847 auto province = p.get_province();
3848 if(state.world.province_get_nation_from_province_ownership(province) == state.world.province_get_nation_from_province_control(province)) {
3849 for(auto pl : province.get_pop_location()) {
3850 auto& pop_money = pl.get_pop().get_savings();
3851 auto strata = culture::pop_strata(pl.get_pop().get_poptype().get_strata());
3852 if(strata == culture::pop_strata::poor) {
3853 total_poor_tax_base += pop_money;
3854 pop_money *= poor_effect;
3855 } else if(strata == culture::pop_strata::middle) {
3856 total_mid_tax_base += pop_money;
3857 pop_money *= middle_effect;
3858 } else if(strata == culture::pop_strata::rich) {
3859 total_rich_tax_base += pop_money;
3860 pop_money *= rich_effect;
3861 }
3862 }
3863 }
3864 }
3865
3866 state.world.nation_set_total_rich_income(n, total_rich_tax_base);
3867 state.world.nation_set_total_middle_income(n, total_mid_tax_base);
3868 state.world.nation_set_total_poor_income(n, total_poor_tax_base);
3869 auto collected_tax = total_poor_tax_base * tax_eff * float(state.world.nation_get_poor_tax(n)) / 100.0f +
3870 total_mid_tax_base * tax_eff * float(state.world.nation_get_middle_tax(n)) / 100.0f +
3871 total_rich_tax_base * tax_eff * float(state.world.nation_get_rich_tax(n)) / 100.0f;
3872 assert(std::isfinite(collected_tax));
3873 assert(collected_tax >= 0);
3874 state.world.nation_get_stockpiles(n, money) += collected_tax;
3875
3876 {
3877 /*
3878 collect tariffs
3879 */
3880
3881 auto tariff_rate = effective_tariff_rate(state, n);
3882 float t_total = 0.0f;
3883
3884 for(uint32_t k = 1; k < total_commodities; ++k) {
3885 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(k) };
3886 t_total += state.world.commodity_get_current_price(cid) * tariff_rate * state.world.nation_get_imports(n, cid);
3887 }
3888 assert(std::isfinite(t_total));
3889 assert(t_total >= 0);
3890 state.world.nation_get_stockpiles(n, money) += t_total;
3891 }
3892
3893 // shift needs weights
3894 rebalance_needs_weights(state, n);
3895 adjust_artisan_balance(state, n);
3896 });
3897
3898 /*
3899 adjust prices based on global production & consumption
3900 */
3901
3902 state.world.for_each_commodity([&](dcon::commodity_id c) {
3903 if(!state.world.commodity_get_money_rgo(c))
3904 return;
3905
3906 float luxury_costs_laborer = 0.f;
3907 const float base_demand = state.defines.base_goods_demand;
3908
3909 for(uint32_t i = 1; i < total_commodities; ++i) {
3910 dcon::commodity_id _cid{ dcon::commodity_id::value_base_t(i) };
3911
3912 if(state.world.commodity_get_is_available_from_start(_cid)) {
3913 float price = state.world.commodity_get_current_price(_cid);
3914 auto t = state.culture_definitions.laborers;
3915
3916 float base_life = state.world.pop_type_get_life_needs(t, _cid);
3917 float base_everyday = 0.5f * state.world.pop_type_get_everyday_needs(t, _cid);
3918 float base_luxury = 0.1f * state.world.pop_type_get_luxury_needs(t, _cid);
3919
3920 luxury_costs_laborer += base_life * base_demand * state.defines.alice_lf_needs_scale * price;
3921 luxury_costs_laborer += base_everyday * base_demand * state.defines.alice_ev_needs_scale * price;
3922 luxury_costs_laborer += base_luxury * base_demand * state.defines.alice_lx_needs_scale * price;
3923 }
3924 }
3925
3926 state.world.commodity_set_current_price(c, std::clamp(luxury_costs_laborer * 0.3f, 0.001f, 100000.0f));
3927 });
3928
3929 concurrency::parallel_for(uint32_t(0), total_commodities, [&](uint32_t k) {
3930 dcon::commodity_id cid{dcon::commodity_id::value_base_t(k)};
3931
3932 //handling gold cost separetely
3933 if(state.world.commodity_get_money_rgo(cid)) {
3934 return;
3935 }
3936
3937 float total_r_demand = 0.0f;
3938 float total_consumption = 0.0f;
3939 float total_production = 0.0f;
3940
3941 state.world.for_each_nation([&](dcon::nation_id n) {
3942 total_r_demand += state.world.nation_get_real_demand(n, cid);
3943 total_consumption += state.world.nation_get_real_demand(n, cid) * state.world.nation_get_demand_satisfaction(n, cid);
3944 total_production += state.world.nation_get_domestic_market_pool(n, cid);
3945 });
3946
3947 state.world.commodity_set_total_consumption(cid, total_consumption);
3948 state.world.commodity_set_total_real_demand(cid, total_r_demand);
3949
3950 auto prior_production = state.world.commodity_get_total_production(cid);
3951 state.world.commodity_set_total_production(cid, total_production);
3952
3953 float supply = prior_production + state.world.commodity_get_global_market_pool(cid) / 12.f;
3954 float demand = total_r_demand;
3955
3956 auto base_price = state.world.commodity_get_cost(cid);
3957 auto current_price = state.world.commodity_get_current_price(cid);
3958
3959 float market_balance = demand - supply;
3960 float max_slope = math::sqrt(abs(market_balance)) + 20.f;
3961
3962 float oversupply_factor = std::clamp(((supply + 0.001f) / (demand + 0.001f) - 1.f), 0.f, max_slope);
3963 float overdemand_factor = std::clamp(((demand + 0.001f) / (supply + 0.001f) - 1.f), 0.f, max_slope);
3964
3965 float speed_modifer = (overdemand_factor - oversupply_factor);
3966
3967 float price_speed = 0.05f * speed_modifer;
3968
3969 if(current_price < 1.f) {
3970 price_speed *= current_price;
3971 } else {
3972 price_speed *= math::sqrt(current_price);
3973 }
3974
3975 current_price += price_speed;
3976
3977 state.world.commodity_set_current_price(cid, std::clamp(current_price, 0.001f, 100000.0f));
3978 });
3979
3980 if(state.cheat_data.ecodump) {
3981 float accumulator[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
3982 state.world.for_each_commodity([&](dcon::commodity_id c) {
3983 state.cheat_data.prices_dump_buffer += std::to_string(state.world.commodity_get_current_price(c)) + ",";
3984 state.cheat_data.supply_dump_buffer += std::to_string(state.world.commodity_get_total_production(c)) + ",";
3985 state.cheat_data.demand_dump_buffer += std::to_string(state.world.commodity_get_total_real_demand(c)) + ",";
3986 for(int i = 0; i < 8; i++) {
3987 accumulator[i] += state.world.commodity_get_demand_by_category(c, i);
3988 }
3989 });
3990 for(int i = 0; i < 8; i++) {
3991 state.cheat_data.demand_by_category_dump_buffer += std::to_string(accumulator[i]) + ",";
3992 }
3993 state.cheat_data.demand_by_category_dump_buffer += "\n";
3994
3995 state.cheat_data.prices_dump_buffer += "\n";
3996 state.cheat_data.supply_dump_buffer += "\n";
3997 state.cheat_data.demand_dump_buffer += "\n";
3998 }
3999
4000 /*
4001 * Enforce price floors
4002 */
4003
4004 /*
4005 for(auto cid : state.world.in_commodity) {
4006 if(cid.get_artisan_output_amount() > 0.0f) {
4007 float min_price = 0.0f;
4008 auto const& inputs = cid.get_artisan_inputs();
4009 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
4010 if(inputs.commodity_type[i]) {
4011 min_price += state.world.commodity_get_current_price(inputs.commodity_type[i]) * inputs.commodity_amounts[i];
4012 } else {
4013 break;
4014 }
4015 }
4016 min_price /= cid.get_artisan_output_amount();
4017 auto current = cid.get_current_price();
4018 cid.set_current_price(0.9f * current + 0.1f * std::max(min_price * 0.6f, current));
4019 }
4020 }
4021 */
4022
4023 /*
4024 DIPLOMATIC EXPENSES
4025 */
4026
4027 for(auto n : state.world.in_nation) {
4028 for(auto uni : n.get_unilateral_relationship_as_source()) {
4029 if(uni.get_war_subsidies()) {
4030 auto target_m_costs = uni.get_target().get_maximum_military_costs() * state.defines.warsubsidies_percent;
4031 if(target_m_costs <= n.get_stockpiles(money)) {
4032 n.get_stockpiles(money) -= target_m_costs;
4033 uni.get_target().get_stockpiles(money) += target_m_costs;
4034 } else {
4035 uni.set_war_subsidies(false);
4036
4038 [source = n.id, target = uni.get_target().id](sys::state& state, text::layout_base& contents) {
4039 text::add_line(state, contents, "msg_wsub_end_1", text::variable_type::x, source, text::variable_type::y, target);
4040 },
4041 "msg_wsub_end_title",
4042 n.id, uni.get_target().id, dcon::nation_id{},
4044 });
4045 }
4046 }
4047 if(uni.get_reparations() && state.current_date < n.get_reparations_until()) {
4048 auto const tax_eff = nations::tax_efficiency(state, n);
4049 auto total_tax_base = n.get_total_rich_income() + n.get_total_middle_income() + n.get_total_poor_income();
4050
4051 auto payout = total_tax_base * tax_eff * state.defines.reparations_tax_hit;
4052 auto capped_payout = std::min(n.get_stockpiles(money), payout);
4053 assert(capped_payout >= 0.0f);
4054
4055 n.get_stockpiles(money) -= capped_payout;
4056 uni.get_target().get_stockpiles(money) += capped_payout;
4057 }
4058 }
4059 }
4060
4061 /*
4062 BANKRUPTCY
4063 */
4064 for(auto n : state.world.in_nation) {
4065 auto m = n.get_stockpiles(money);
4066 if(m < 0) {
4067 if(m < -max_loan(state, n)) {
4068 go_bankrupt(state, n);
4069 }
4070 }
4071 }
4072
4073 /*
4074 update inflation
4075 */
4076
4077 float primary_commodity_basket = 0.0f;
4078 state.world.for_each_commodity([&](dcon::commodity_id c) {
4079 state.world.for_each_pop_type([&](dcon::pop_type_id pt) {
4080 primary_commodity_basket += 2.0f * state.world.commodity_get_cost(c) * state.world.pop_type_get_life_needs(pt, c);
4081 primary_commodity_basket += 2.0f * state.world.commodity_get_cost(c) * state.world.pop_type_get_everyday_needs(pt, c);
4082 });
4083 });
4084 primary_commodity_basket /= float(state.world.pop_type_size());
4085
4086 float total_pop = 0.0f;
4087 float total_pop_money = 0.0f;
4088
4089 state.world.for_each_nation([&](dcon::nation_id n) {
4090 total_pop += state.world.nation_get_demographics(n, demographics::total);
4091 total_pop_money += state.world.nation_get_total_rich_income(n) + state.world.nation_get_total_middle_income(n) +
4092 state.world.nation_get_total_poor_income(n);
4093 });
4094
4095 float target_money = total_pop * primary_commodity_basket / state.defines.alice_needs_scaling_factor;
4096
4097 // total_pop_money / inflation = real, unadjustead money
4098 // want inflation s.t. inflation * r_money = target_money
4099 // ideal inflation = inflation * target_money / total_pop_money
4100
4101 if(total_pop_money > 0.001f) {
4102 state.inflation = (state.inflation * 0.9f) + (0.1f * target_money / total_pop_money);
4103 }
4104
4105 // make constructions:
4106 resolve_constructions(state);
4107
4108 if(initiate_buildings) {
4109
4110 // make new investments
4111 for(auto n : state.world.in_nation) {
4112 auto nation_rules = n.get_combined_issue_rules();
4113
4114 // check if current projects are already too expensive for capitalists to manage
4115 float total_cost = 0.f;
4116
4117 for(uint32_t i = 1; i < total_commodities; ++i) {
4118 dcon::commodity_id c{ dcon::commodity_id::value_base_t(i) };
4119 total_cost += state.world.nation_get_private_construction_demand(n, c) * state.world.commodity_get_current_price(c);
4120 }
4121
4122 float total_cost_added = 0.f;
4123
4124 if(n.get_private_investment() > total_cost
4125 && n.get_is_civilized()
4127
4128 static std::vector<dcon::factory_type_id> desired_types;
4129 desired_types.clear();
4130
4131 static std::vector<dcon::state_instance_id> states_in_order;
4132 states_in_order.clear();
4133 for(auto si : n.get_state_ownership()) {
4134 if(si.get_state().get_capital().get_is_colonial() == false) {
4135 states_in_order.push_back(si.get_state().id);
4136 }
4137 }
4138 std::sort(states_in_order.begin(), states_in_order.end(), [&](dcon::state_instance_id a, dcon::state_instance_id b) {
4139 auto a_pop = state.world.state_instance_get_demographics(a, demographics::total);
4140 auto b_pop = state.world.state_instance_get_demographics(b, demographics::total);
4141 if(a_pop != b_pop)
4142 return a_pop > b_pop;
4143 return a.index() < b.index(); // force total ordering
4144 });
4145
4146 if(!states_in_order.empty() && (nation_rules & issue_rule::pop_build_factory) != 0) {
4147 ai::get_desired_factory_types(state, n, desired_types);
4148 }
4149
4150 //upgrade all good targets!!!
4151 //upgrading only one per run is too slow and leads to massive unemployment!!!
4152
4153 for(auto s : states_in_order) {
4154 auto pw_num = state.world.state_instance_get_demographics(s,
4155 demographics::to_key(state, state.culture_definitions.primary_factory_worker));
4156 auto pw_employed = state.world.state_instance_get_demographics(s,
4157 demographics::to_employment_key(state, state.culture_definitions.primary_factory_worker));
4158
4159 if(pw_employed >= pw_num && pw_num > 0.0f)
4160 continue; // no spare workers
4161
4162 int32_t num_factories = 0;
4163 float profit = 0.0f;
4164 dcon::factory_id selected_factory;
4165
4166 // is there an upgrade target ?
4167 auto d = state.world.state_instance_get_definition(s);
4168 for(auto p : state.world.state_definition_get_abstract_state_membership(d)) {
4169 if(p.get_province().get_nation_from_province_ownership() == n) {
4170 for(auto f : p.get_province().get_factory_location()) {
4171 ++num_factories;
4172
4173 if(
4174 (nation_rules & issue_rule::pop_expand_factory) != 0
4175 && f.get_factory().get_production_scale() >= 0.9f
4176 && f.get_factory().get_primary_employment() >= 0.9f
4177 && f.get_factory().get_level() < uint8_t(255)) {
4178
4179 auto type = f.get_factory().get_building_type();
4180 auto ug_in_progress = false;
4181 for(auto c : state.world.state_instance_get_state_building_construction(s)) {
4182 if(c.get_type() == type) {
4183 ug_in_progress = true;
4184 break;
4185 }
4186 }
4187
4188 if(ug_in_progress) {
4189 continue;
4190 }
4191
4192 if(auto new_p = f.get_factory().get_full_profit() / f.get_factory().get_level(); new_p > profit) {
4193 profit = new_p;
4194 selected_factory = f.get_factory();
4195 }
4196 }
4197 }
4198 }
4199 }
4200 if(selected_factory && profit > 0.f) {
4201 auto new_up = fatten(state.world, state.world.force_create_state_building_construction(s, n));
4202 new_up.set_is_pop_project(true);
4203 new_up.set_is_upgrade(true);
4204 new_up.set_type(state.world.factory_get_building_type(selected_factory));
4205 }
4206
4207 //try to invest into something new...
4208 //bool found_investment = false;
4209 auto existing_constructions = state.world.state_instance_get_state_building_construction(s);
4210 if(existing_constructions.begin() != existing_constructions.end())
4211 continue; // already building
4212
4213 if(n.get_private_investment() * 0.1f < total_cost + total_cost_added) {
4214 continue;
4215 }
4216
4217 if((num_factories < int32_t(state.defines.factories_per_state)) && (nation_rules & issue_rule::pop_build_factory) != 0) {
4218 // randomly try a valid (check coastal, unlocked, non existing) factory
4219 if(!desired_types.empty()) {
4220 auto selected = desired_types[rng::get_random(state, uint32_t((n.id.index() << 6) ^ s.index())) % desired_types.size()];
4221
4222 if(state.world.factory_type_get_is_coastal(selected) && !province::state_is_coastal(state, s))
4223 continue;
4224
4225 bool already_in_progress = [&]() {
4226 for(auto p : state.world.state_instance_get_state_building_construction(s)) {
4227 if(p.get_type() == selected)
4228 return true;
4229 }
4230 return false;
4231 }();
4232
4233 if(already_in_progress)
4234 continue;
4235
4236
4237 bool present_in_location = false;
4238 province::for_each_province_in_state_instance(state, s, [&](dcon::province_id p) {
4239 for(auto fac : state.world.province_get_factory_location(p)) {
4240 auto type = fac.get_factory().get_building_type();
4241 if(selected == type) {
4242 present_in_location = true;
4243 return;
4244 }
4245 }
4246 });
4247
4248 if(present_in_location)
4249 continue;
4250
4251 auto new_up = fatten(state.world, state.world.force_create_state_building_construction(s, n));
4252 new_up.set_is_pop_project(true);
4253 new_up.set_is_upgrade(false);
4254 new_up.set_type(selected);
4255
4256 auto costs = new_up.get_type().get_construction_costs();
4257
4258 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
4259 if(costs.commodity_type[i]) {
4260 total_cost_added += state.world.nation_get_effective_prices(n, costs.commodity_type[i]) * costs.commodity_amounts[i];
4261 } else {
4262 break;
4263 }
4264 }
4265 //found_investment = true;
4266 }
4267 }
4268 }
4269
4270
4271 if((nation_rules & issue_rule::pop_build_factory) != 0) {
4272 static std::vector<std::pair<dcon::province_id, int32_t>> provinces_in_order;
4273 provinces_in_order.clear();
4274 for(auto si : n.get_state_ownership()) {
4275 if(si.get_state().get_capital().get_is_colonial() == false) {
4276 auto s = si.get_state().id;
4277 auto d = state.world.state_instance_get_definition(s);
4278 int32_t num_factories = 0;
4279 for(auto p : state.world.state_definition_get_abstract_state_membership(d)) {
4280 if(province::generic_can_build_railroads(state, p.get_province(), n) &&
4281 p.get_province().get_nation_from_province_ownership() == n) {
4282 for(auto f : p.get_province().get_factory_location())
4283 num_factories += int32_t(f.get_factory().get_level());
4284 provinces_in_order.emplace_back(p.get_province().id, num_factories);
4285 }
4286 }
4287 // The state's number of factories is intentionally given to all the provinces within the state so the
4288 // railroads aren't just built on a single province within a state
4289 for(auto p : state.world.state_definition_get_abstract_state_membership(d)) {
4290 if(province::generic_can_build_railroads(state, p.get_province(), n) &&
4291 p.get_province().get_nation_from_province_ownership() == n)
4292 provinces_in_order.emplace_back(p.get_province().id, num_factories);
4293 }
4294 }
4295 }
4296 if(!provinces_in_order.empty()) {
4297 std::pair<dcon::province_id, int32_t> best_p = provinces_in_order[0];
4298 for(auto e : provinces_in_order)
4299 if(e.second > best_p.second)
4300 best_p = e;
4301
4302 auto new_rr = fatten(state.world, state.world.force_create_province_building_construction(best_p.first, n));
4303 new_rr.set_is_pop_project(true);
4304 new_rr.set_type(uint8_t(province_building_type::railroad));
4305 //found_investment = true;
4306 }
4307 }
4308 }
4309 n.set_private_investment(0.0f);
4310 }
4311 }
4312
4313 //write gdp to file
4314 if(state.cheat_data.ecodump) {
4315 for(auto n : state.world.in_nation) {
4316 auto life_costs =
4317 state.world.nation_get_life_needs_costs(n, state.culture_definitions.primary_factory_worker)
4318 + state.world.nation_get_everyday_needs_costs(n, state.culture_definitions.primary_factory_worker)
4319 + state.world.nation_get_luxury_needs_costs(n, state.culture_definitions.primary_factory_worker);
4320 auto tag = nations::int_to_tag(state.world.national_identity_get_identifying_int(state.world.nation_get_identity_from_identity_holder(n)));
4321 auto name = text::produce_simple_string(state, text::get_name(state, n));
4322 state.cheat_data.national_economy_dump_buffer +=
4323 tag + ","
4324 + name + ","
4325 + std::to_string(state.world.nation_get_gdp(n)) + ","
4326 + std::to_string(life_costs) + ","
4327 + std::to_string(state.world.nation_get_demographics(n, demographics::total)) + ","
4328 + std::to_string(state.current_date.value) + "\n";
4329 }
4330 }
4331}
4334 state.culture_definitions.rgo_workers.clear();
4335 for(auto pt : state.world.in_pop_type) {
4336 if(pt.get_is_paid_rgo_worker())
4337 state.culture_definitions.rgo_workers.push_back(pt);
4338 }
4339
4340 auto const total_commodities = state.world.commodity_size();
4341 for(uint32_t k = 1; k < total_commodities; ++k) {
4342 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(k) };
4343 for(auto pt : state.world.in_pop_type) {
4344 if(pt != state.culture_definitions.slaves) {
4345 if(pt.get_life_needs(cid) > 0.0f)
4346 state.world.commodity_set_is_life_need(cid, true);
4347 if(pt.get_everyday_needs(cid) > 0.0f)
4348 state.world.commodity_set_is_everyday_need(cid, true);
4349 if(pt.get_luxury_needs(cid) > 0.0f)
4350 state.world.commodity_set_is_luxury_need(cid, true);
4351 }
4352 }
4353 }
4354
4355 state.world.commodity_resize_demand_by_category(8);
4356
4357 state.world.nation_resize_intermediate_demand(state.world.commodity_size());
4358
4359 state.world.nation_resize_life_needs_costs(state.world.pop_type_size());
4360 state.world.nation_resize_everyday_needs_costs(state.world.pop_type_size());
4361 state.world.nation_resize_luxury_needs_costs(state.world.pop_type_size());
4362
4363 state.world.province_resize_rgo_actual_production_per_good(state.world.commodity_size());
4364
4365 state.world.for_each_commodity([&](dcon::commodity_id c) {
4366 auto fc = fatten(state.world, c);
4367 state.world.commodity_set_key_factory(c, dcon::factory_type_id{});
4368 if(fc.get_total_production() > 0.0001f) {
4369 fc.set_producer_payout_fraction(std::min(fc.get_total_consumption() / fc.get_total_production(), 1.0f));
4370 } else {
4371 fc.set_producer_payout_fraction(1.0f);
4372 }
4373 });
4374 state.world.for_each_factory_type([&](dcon::factory_type_id t) {
4375 auto o = state.world.factory_type_get_output(t);
4376 if(o)
4377 state.world.commodity_set_key_factory(o, t);
4378 });
4379}
4381float government_consumption(sys::state& state, dcon::nation_id n, dcon::commodity_id c) {
4382 auto overseas_factor = state.defines.province_overseas_penalty *
4383 float(state.world.nation_get_owned_province_count(n) - state.world.nation_get_central_province_count(n));
4384 auto o_adjust = 0.0f;
4385 if(overseas_factor > 0) {
4386 auto kf = state.world.commodity_get_key_factory(c);
4387 if(state.world.commodity_get_overseas_penalty(c) &&
4388 (state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf)))) {
4389 o_adjust = overseas_factor;
4390 }
4391 }
4392
4393 return (state.world.nation_get_army_demand(n, c) + state.world.nation_get_navy_demand(n, c) +
4394 state.world.nation_get_construction_demand(n, c) + o_adjust);
4395}
4397float factory_type_build_cost(sys::state& state, dcon::nation_id n, dcon::factory_type_id factory_type) {
4398 auto fat = dcon::fatten(state.world, factory_type);
4399 auto& costs = fat.get_construction_costs();
4400
4401 float factory_mod = state.world.nation_get_modifier_values(state.local_player_nation, sys::national_mod_offsets::factory_cost) + 1.0f;
4402 float admin_eff = state.world.nation_get_administrative_efficiency(state.local_player_nation);
4403 float admin_cost_factor = (2.0f - admin_eff) * factory_mod;
4404
4405 auto total = 0.0f;
4406 for(uint32_t i = 0; i < economy::commodity_set::set_size; i++) {
4407 auto cid = costs.commodity_type[i];
4408 if(bool(cid)) {
4409 total += state.world.commodity_get_current_price(cid) * costs.commodity_amounts[i] * admin_cost_factor;
4410 }
4411 }
4412
4413 return total;
4414}
4416float factory_type_output_cost(sys::state& state, dcon::nation_id n, dcon::factory_type_id factory_type) {
4417 auto fac_type = dcon::fatten(state.world, factory_type);
4418 float output_multiplier = nation_factory_output_multiplier(state, factory_type, n);
4419 float total_production = fac_type.get_output_amount() * output_multiplier;
4420
4421 return total_production * state.world.commodity_get_current_price(fac_type.get_output());
4422}
4424float factory_type_input_cost(sys::state& state, dcon::nation_id n, dcon::factory_type_id factory_type) {
4425 auto fac_type = dcon::fatten(state.world, factory_type);
4426 float input_total = factory_input_total_cost(state, n, fac_type);
4427 float e_input_total = factory_e_input_total_cost(state, n, fac_type);
4428
4429 //modifiers
4430 auto const maint_multiplier = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_maintenance) + 1.0f;
4431 float input_multiplier = nation_factory_input_multiplier(state, n);
4432
4433 return input_total * input_multiplier + e_input_total * input_multiplier * maint_multiplier;
4434}
4436float nation_factory_consumption(sys::state& state, dcon::nation_id n, dcon::commodity_id c) {
4437 auto amount = 0.f;
4438 for(auto ownership : state.world.nation_get_province_ownership(n)) {
4439 for(auto location : state.world.province_get_factory_location(ownership.get_province())) {
4440 // factory
4441 auto f = state.world.factory_location_get_factory(location);
4442 auto p = ownership.get_province();
4443 auto s = p.get_state_membership();
4444 auto fac = fatten(state.world, f);
4445 auto fac_type = fac.get_building_type();
4446
4447 // assume that all inputs are available
4448 float min_input_available = 1.f;
4449 float min_e_input_available = 1.f;
4450
4451 //modifiers
4452
4453 float input_multiplier = factory_input_multiplier(state, fac, n, p, s);
4454 float throughput_multiplier = factory_throughput_multiplier(state, fac_type, n, p, s);
4455 float output_multiplier = factory_output_multiplier(state, fac, n, p);
4456
4457 //this value represents total production if 1 lvl of this factory is filled with workers
4458 float total_production = fac_type.get_output_amount()
4459 * (0.75f + 0.25f * min_e_input_available)
4460 * throughput_multiplier
4461 * output_multiplier
4462 * min_input_available;
4463
4464 float effective_production_scale = fac.get_production_scale();
4465
4466 auto& inputs = fac_type.get_inputs();
4467 auto& e_inputs = fac_type.get_efficiency_inputs();
4468
4469 // register real demand : input_multiplier * throughput_multiplier * level * primary_employment
4470 // also multiply by target production scale... otherwise too much excess demand is generated
4471 // also multiply by something related to minimal satisfied input
4472 // to prevent generation of too much demand on rgos already influenced by a shortage
4473
4474 float input_scale =
4475 input_multiplier
4476 * throughput_multiplier
4477 * effective_production_scale
4478 * (0.1f + min_input_available * 0.9f);
4479
4480 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
4481 if(inputs.commodity_type[i]) {
4482 if(inputs.commodity_type[i] == c) {
4483 amount +=
4484 +input_scale * inputs.commodity_amounts[i];
4485 break;
4486 }
4487 } else {
4488 break;
4489 }
4490 }
4491
4492 // and for efficiency inputs
4493 // the consumption of efficiency inputs is (national-factory-maintenance-modifier + 1) x input-multiplier x
4494 // throughput-multiplier x factory level
4495 auto const mfactor = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_maintenance) + 1.0f;
4496 for(uint32_t i = 0; i < small_commodity_set::set_size; ++i) {
4497 if(e_inputs.commodity_type[i]) {
4498 if(e_inputs.commodity_type[i] == c) {
4499 amount +=
4500 mfactor
4501 * input_scale
4502 * e_inputs.commodity_amounts[i]
4503 * (0.1f + min_e_input_available * 0.9f);
4504 break;
4505 }
4506 } else {
4507 break;
4508 }
4509 }
4510 }
4511 }
4512 return amount;
4513}
4515float nation_pop_consumption(sys::state& state, dcon::nation_id n, dcon::commodity_id c) {
4516 auto amount = 0.f;
4517 auto kf = state.world.commodity_get_key_factory(c);
4518 if(state.world.commodity_get_is_available_from_start(c) || (kf && state.world.nation_get_active_building(n, kf))) {
4519 state.world.for_each_pop_type([&](dcon::pop_type_id pt) {
4520 amount += (state.world.pop_type_get_life_needs(pt, c) + state.world.pop_type_get_everyday_needs(pt, c) +
4521 state.world.pop_type_get_luxury_needs(pt, c)) *
4522 state.world.nation_get_demographics(n, demographics::to_key(state, pt)) / state.defines.alice_needs_scaling_factor;
4523 });
4524 }
4525 return amount;
4526}
4528float nation_total_imports(sys::state& state, dcon::nation_id n) {
4529 float t_total = 0.0f;
4530
4531 auto const total_commodities = state.world.commodity_size();
4532 for(uint32_t k = 1; k < total_commodities; ++k) {
4533 dcon::commodity_id cid{ dcon::commodity_id::value_base_t(k) };
4534 t_total += state.world.commodity_get_current_price(cid) * state.world.nation_get_imports(n, cid);
4535 }
4536
4537 return t_total;
4538}
4540float pop_income(sys::state& state, dcon::pop_id p) {
4541 auto saved = state.world.pop_get_savings(p);
4542 if(saved <= 0.0f)
4543 return 0.0f;
4544
4545 auto owner = nations::owner_of_pop(state, p);
4546 auto const tax_eff = nations::tax_efficiency(state, owner);
4547 auto strata = culture::pop_strata(state.world.pop_type_get_strata(state.world.pop_get_poptype(p)));
4548 switch(strata) {
4549 default:
4551 return saved / std::max(0.0001f, (1.0f - tax_eff * float(state.world.nation_get_poor_tax(owner)) / 100.0f));
4553 return saved / std::max(0.0001f, (1.0f - tax_eff * float(state.world.nation_get_middle_tax(owner)) / 100.0f));
4555 return saved / std::max(0.0001f, (1.0f - tax_eff * float(state.world.nation_get_rich_tax(owner)) / 100.0f));
4556 }
4557}
4559float estimate_gold_income(sys::state& state, dcon::nation_id n) {
4560 auto amount = 0.f;
4561 for(auto poid : state.world.nation_get_province_ownership_as_nation(n)) {
4562 auto prov = poid.get_province();
4563
4564 state.world.for_each_commodity([&](dcon::commodity_id c) {
4565 if(state.world.commodity_get_money_rgo(c)) {
4566 amount += province::rgo_production_quantity(state, prov.id, c);
4567 }
4568 });
4569 }
4570 return amount * state.defines.gold_to_cash_rate;
4571}
4573float estimate_tariff_income(sys::state& state, dcon::nation_id n) {
4574 return nations::tariff_efficiency(state, n) * economy::nation_total_imports(state, n);
4575}
4577float estimate_social_spending(sys::state& state, dcon::nation_id n) {
4578 auto total = 0.f;
4579 auto const p_level = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::pension_level);
4580 auto const unemp_level = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::unemployment_benefit);
4581
4582 state.world.for_each_pop_type([&](dcon::pop_type_id pt) {
4583 auto adj_pop_of_type =
4584 state.world.nation_get_demographics(n, demographics::to_key(state, pt)) / state.defines.alice_needs_scaling_factor;
4585
4586 if(adj_pop_of_type <= 0)
4587 return;
4588
4589 auto ln_type = culture::income_type(state.world.pop_type_get_life_needs_income_type(pt));
4591 //nothing
4592 } else { // unemployment, pensions
4593 total += adj_pop_of_type * p_level * state.world.nation_get_life_needs_costs(n, pt);
4594 if(state.world.pop_type_get_has_unemployment(pt)) {
4595 auto emp = state.world.nation_get_demographics(n, demographics::to_employment_key(state, pt)) / state.defines.alice_needs_scaling_factor;
4596 total += (adj_pop_of_type - emp) * unemp_level * state.world.nation_get_life_needs_costs(n, pt);
4597 }
4598 }
4599 });
4600 return total;
4601}
4603float estimate_pop_payouts_by_income_type(sys::state& state, dcon::nation_id n, culture::income_type in) {
4604 auto total = 0.f;
4605 state.world.for_each_pop_type([&](dcon::pop_type_id pt) {
4606 auto adj_pop_of_type =
4607 state.world.nation_get_demographics(n, demographics::to_key(state, pt)) / state.defines.alice_needs_scaling_factor;
4608
4609 if(adj_pop_of_type <= 0)
4610 return;
4611
4612 auto ln_type = culture::income_type(state.world.pop_type_get_life_needs_income_type(pt));
4613 if(ln_type == in) {
4614 total += adj_pop_of_type * state.world.nation_get_life_needs_costs(n, pt);
4615 }
4616
4617 auto en_type = culture::income_type(state.world.pop_type_get_everyday_needs_income_type(pt));
4618 if(en_type == in) {
4619 total += adj_pop_of_type * state.world.nation_get_everyday_needs_costs(n, pt);
4620 }
4621
4622 auto lx_type = culture::income_type(state.world.pop_type_get_luxury_needs_income_type(pt));
4623 if(lx_type == in) {
4624 total += adj_pop_of_type * state.world.nation_get_luxury_needs_costs(n, pt);
4625 }
4626 });
4627 return total;
4628}
4630float estimate_tax_income_by_strata(sys::state& state, dcon::nation_id n, culture::pop_strata ps) {
4631 switch(ps) {
4632 default:
4634 return state.world.nation_get_total_poor_income(n) * nations::tax_efficiency(state, n);
4636 return state.world.nation_get_total_middle_income(n) * nations::tax_efficiency(state, n);
4638 return state.world.nation_get_total_rich_income(n) * nations::tax_efficiency(state, n);
4639 }
4640}
4642float estimate_subsidy_spending(sys::state& state, dcon::nation_id n) {
4643 return state.world.nation_get_subsidies_spending(n);
4644}
4646float estimate_war_subsidies_income(sys::state& state, dcon::nation_id n) {
4647 float total = 0.0f;
4648
4649 for(auto uni : state.world.nation_get_unilateral_relationship_as_target(n)) {
4650 if(uni.get_war_subsidies()) {
4651 total += uni.get_target().get_maximum_military_costs() * state.defines.warsubsidies_percent;
4652 }
4653 }
4654 return total;
4656float estimate_reparations_income(sys::state& state, dcon::nation_id n) {
4657 float total = 0.0f;
4658 for(auto uni : state.world.nation_get_unilateral_relationship_as_target(n)) {
4659 if(uni.get_reparations() && state.current_date < uni.get_source().get_reparations_until()) {
4660 auto source = uni.get_source();
4661 auto const tax_eff = nations::tax_efficiency(state, n);
4662 auto total_tax_base = state.world.nation_get_total_rich_income(source) +
4663 state.world.nation_get_total_middle_income(source) +
4664 state.world.nation_get_total_poor_income(source);
4665 auto payout = total_tax_base * tax_eff * state.defines.reparations_tax_hit;
4666 total += payout;
4667 }
4668 }
4669 return total;
4670}
4672float estimate_war_subsidies_spending(sys::state& state, dcon::nation_id n) {
4673 float total = 0.0f;
4674
4675 for(auto uni : state.world.nation_get_unilateral_relationship_as_source(n)) {
4676 if(uni.get_war_subsidies()) {
4677 total += uni.get_target().get_maximum_military_costs() * state.defines.warsubsidies_percent;
4678 }
4679 }
4680
4681 return total;
4682}
4684float estimate_reparations_spending(sys::state& state, dcon::nation_id n) {
4685 float total = 0.0f;
4686 if(state.current_date < state.world.nation_get_reparations_until(n)) {
4687 for(auto uni : state.world.nation_get_unilateral_relationship_as_source(n)) {
4688 if(uni.get_reparations()) {
4689 auto const tax_eff = nations::tax_efficiency(state, n);
4690 auto total_tax_base = state.world.nation_get_total_rich_income(n) +
4691 state.world.nation_get_total_middle_income(n) +
4692 state.world.nation_get_total_poor_income(n);
4693 auto payout = total_tax_base * tax_eff * state.defines.reparations_tax_hit;
4694 total += payout;
4695 }
4696 }
4697 }
4698 return total;
4699}
4701float estimate_diplomatic_balance(sys::state& state, dcon::nation_id n) {
4702 float w_sub = estimate_war_subsidies_income(state, n) - estimate_war_subsidies_spending(state, n);
4703 float w_reps = estimate_reparations_income(state, n) - estimate_reparations_spending(state, n);
4704 return w_sub + w_reps;
4705}
4707float estimate_domestic_investment(sys::state& state, dcon::nation_id n) {
4708 auto adj_pop_of_type_capis = (state.world.nation_get_demographics(n, demographics::to_key(state, state.culture_definitions.capitalists))) / state.defines.alice_needs_scaling_factor;
4709 auto adj_pop_of_type_arist = (state.world.nation_get_demographics(n, demographics::to_key(state, state.culture_definitions.aristocrat))) / state.defines.alice_needs_scaling_factor;
4710 float arist_costs =
4711 state.world.nation_get_life_needs_costs(n, state.culture_definitions.aristocrat)
4712 + state.world.nation_get_everyday_needs_costs(n, state.culture_definitions.aristocrat)
4713 + state.world.nation_get_luxury_needs_costs(n, state.culture_definitions.aristocrat);
4714 float capis_costs =
4715 state.world.nation_get_life_needs_costs(n, state.culture_definitions.capitalists)
4716 + state.world.nation_get_everyday_needs_costs(n, state.culture_definitions.capitalists)
4717 + state.world.nation_get_luxury_needs_costs(n, state.culture_definitions.capitalists);
4718 return state.defines.alice_domestic_investment_multiplier * (adj_pop_of_type_capis * capis_costs + adj_pop_of_type_arist * arist_costs);
4719}
4721float estimate_land_spending(sys::state& state, dcon::nation_id n) {
4722 float total = 0.0f;
4723 uint32_t total_commodities = state.world.commodity_size();
4724 for(uint32_t i = 1; i < total_commodities; ++i) {
4725 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
4726 total += state.world.nation_get_army_demand(n, cid) * state.world.nation_get_effective_prices(n, cid) * state.world.nation_get_demand_satisfaction(n, cid);
4727 }
4728 return total;
4729}
4731float estimate_naval_spending(sys::state& state, dcon::nation_id n) {
4732 float total = 0.0f;
4733 uint32_t total_commodities = state.world.commodity_size();
4734 for(uint32_t i = 1; i < total_commodities; ++i) {
4735 dcon::commodity_id cid{dcon::commodity_id::value_base_t(i)};
4736 total += state.world.nation_get_navy_demand(n, cid) * state.world.nation_get_effective_prices(n, cid) * state.world.nation_get_demand_satisfaction(n, cid);
4737 }
4738 return total;
4739}
4741float estimate_construction_spending(sys::state& state, dcon::nation_id n) {
4742 float total = 0.0f;
4743 float admin_eff = state.world.nation_get_administrative_efficiency(n);
4744 float admin_cost_factor = 2.0f - admin_eff;
4745
4746 for(auto lc : state.world.nation_get_province_land_construction(n)) {
4747 auto province = state.world.pop_get_province_from_pop_location(state.world.province_land_construction_get_pop(lc));
4748 if(state.world.province_get_nation_from_province_control(province) == n) {
4749
4750 auto& base_cost = state.military_definitions.unit_base_definitions[state.world.province_land_construction_get_type(lc)].build_cost;
4751 auto& current_purchased = state.world.province_land_construction_get_purchased_goods(lc);
4752 float construction_time = global_non_factory_construction_time_modifier(state) * float(state.military_definitions.unit_base_definitions[state.world.province_land_construction_get_type(lc)].build_time);
4753
4754 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
4755 if(base_cost.commodity_type[i]) {
4756 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * admin_cost_factor)
4757 total += state.world.nation_get_effective_prices(n, base_cost.commodity_type[i]) * state.world.nation_get_demand_satisfaction(n, base_cost.commodity_type[i]) * base_cost.commodity_amounts[i] / construction_time;
4758 } else {
4759 break;
4760 }
4761 }
4762 }
4763 }
4764
4765 for(auto po : state.world.nation_get_province_ownership(n)) {
4766 auto p = po.get_province();
4767 if(state.world.province_get_nation_from_province_control(p) != n)
4768 continue;
4769
4770 auto rng = state.world.province_get_province_naval_construction(p);
4771 if(rng.begin() != rng.end()) {
4772 auto c = *(rng.begin());
4773 auto& base_cost = state.military_definitions.unit_base_definitions[c.get_type()].build_cost;
4774 auto& current_purchased = c.get_purchased_goods();
4775 float construction_time = global_non_factory_construction_time_modifier(state) * float(state.military_definitions.unit_base_definitions[c.get_type()].build_time);
4776
4777 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
4778 if(base_cost.commodity_type[i]) {
4779 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * admin_cost_factor)
4780 total += state.world.nation_get_effective_prices(n, base_cost.commodity_type[i]) * state.world.nation_get_demand_satisfaction(n, base_cost.commodity_type[i]) * base_cost.commodity_amounts[i] / construction_time;
4781 } else {
4782 break;
4783 }
4784 }
4785 }
4786 }
4787
4788 for(auto c : state.world.nation_get_province_building_construction(n)) {
4789 if(n == c.get_province().get_nation_from_province_control() && !c.get_is_pop_project()) {
4790 auto t = economy::province_building_type(c.get_type());
4791 auto& base_cost = state.economy_definitions.building_definitions[int32_t(t)].cost;
4792 auto& current_purchased = c.get_purchased_goods();
4793 float construction_time = global_non_factory_construction_time_modifier(state) * float(state.economy_definitions.building_definitions[int32_t(t)].time);
4794
4795 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
4796 if(base_cost.commodity_type[i]) {
4797 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * admin_cost_factor)
4798 total += state.world.nation_get_effective_prices(n, base_cost.commodity_type[i]) * state.world.nation_get_demand_satisfaction(n, base_cost.commodity_type[i]) * base_cost.commodity_amounts[i] / construction_time;
4799 } else {
4800 break;
4801 }
4802 }
4803 }
4804 }
4805
4806 float factory_mod = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_cost) + 1.0f;
4807
4808 for(auto c : state.world.nation_get_state_building_construction(n)) {
4809 if(!c.get_is_pop_project()) {
4810 auto& base_cost = c.get_type().get_construction_costs();
4811 auto& current_purchased = c.get_purchased_goods();
4812 float construction_time = global_factory_construction_time_modifier(state) * float(c.get_type().get_construction_time()) * (c.get_is_upgrade() ? 0.1f : 1.0f);
4813
4814 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
4815 if(base_cost.commodity_type[i]) {
4816 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * factory_mod * admin_cost_factor)
4817 total += state.world.nation_get_effective_prices(n, base_cost.commodity_type[i]) * state.world.nation_get_demand_satisfaction(n, base_cost.commodity_type[i]) * base_cost.commodity_amounts[i] * factory_mod / construction_time;
4818 } else {
4819 break;
4820 }
4821 }
4822 }
4823 }
4824
4825 return total;
4826}
4828float estimate_war_subsidies(sys::state& state, dcon::nation_id n) {
4829 /* total-nation-expenses x defines:WARSUBSIDIES_PERCENT */
4830 return state.world.nation_get_maximum_military_costs(n) * state.defines.warsubsidies_percent;
4831}
4834 for(auto pb_con : state.world.province_get_province_building_construction(p)) {
4835 if(pb_con.get_type() == uint8_t(t)) {
4836 float admin_eff = state.world.nation_get_administrative_efficiency(state.world.province_get_nation_from_province_ownership(p));
4837 float admin_cost_factor = pb_con.get_is_pop_project() ? 1.0f : 2.0f - admin_eff;
4838
4839 float total = 0.0f;
4840 float purchased = 0.0f;
4841 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
4842 total += state.economy_definitions.building_definitions[int32_t(t)].cost.commodity_amounts[i] * admin_cost_factor;
4843 purchased += pb_con.get_purchased_goods().commodity_amounts[i];
4844 }
4845 return construction_status{total > 0.0f ? purchased / total : 0.0f, true};
4846 }
4847 }
4848 return construction_status{0.0f, false};
4849}
4851construction_status factory_upgrade(sys::state& state, dcon::factory_id f) {
4852 auto in_prov = state.world.factory_get_province_from_factory_location(f);
4853 auto in_state = state.world.province_get_state_membership(in_prov);
4854 auto fac_type = state.world.factory_get_building_type(f);
4855
4856 for(auto st_con : state.world.state_instance_get_state_building_construction(in_state)) {
4857 if(st_con.get_type() == fac_type) {
4858 float admin_eff = state.world.nation_get_administrative_efficiency(st_con.get_nation());
4859 float factory_mod = state.world.nation_get_modifier_values(st_con.get_nation(), sys::national_mod_offsets::factory_cost) + 1.0f;
4860 float pop_factory_mod = std::max(0.1f, state.world.nation_get_modifier_values(st_con.get_nation(), sys::national_mod_offsets::factory_owner_cost));
4861 float admin_cost_factor = (st_con.get_is_pop_project() ? pop_factory_mod : (2.0f - admin_eff)) * factory_mod;
4862
4863
4864 float total = 0.0f;
4865 float purchased = 0.0f;
4866 auto& goods = state.world.factory_type_get_construction_costs(fac_type);
4867
4868 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
4869 total += goods.commodity_amounts[i] * admin_cost_factor;
4870 purchased += st_con.get_purchased_goods().commodity_amounts[i];
4871 }
4872
4873 return construction_status{total > 0.0f ? purchased / total : 0.0f, true};
4874 }
4875 }
4876
4877 return construction_status{0.0f, false};
4878}
4880bool state_contains_constructed_factory(sys::state& state, dcon::state_instance_id s, dcon::factory_type_id ft) {
4881 auto d = state.world.state_instance_get_definition(s);
4882 for(auto p : state.world.state_definition_get_abstract_state_membership(d)) {
4883 if(p.get_province().get_state_membership() == s) {
4884 for(auto f : p.get_province().get_factory_location()) {
4885 if(f.get_factory().get_building_type() == ft)
4886 return true;
4887 }
4888 }
4889 }
4890 return false;
4891}
4893bool state_contains_factory(sys::state& state, dcon::state_instance_id s, dcon::factory_type_id ft) {
4894 auto d = state.world.state_instance_get_definition(s);
4895
4896 for(auto p : state.world.state_definition_get_abstract_state_membership(d)) {
4897 if(p.get_province().get_state_membership() == s) {
4898 for(auto f : p.get_province().get_factory_location()) {
4899 if(f.get_factory().get_building_type() == ft)
4900 return true;
4901 }
4902 }
4903 }
4904 for(auto sc : state.world.state_instance_get_state_building_construction(s)) {
4905 if(sc.get_type() == ft)
4906 return true;
4907 }
4908
4909 return false;
4910}
4912int32_t state_factory_count(sys::state& state, dcon::state_instance_id sid, dcon::nation_id n) {
4913 int32_t num_factories = 0;
4914 auto d = state.world.state_instance_get_definition(sid);
4915 for(auto p : state.world.state_definition_get_abstract_state_membership(d))
4916 if(p.get_province().get_nation_from_province_ownership() == n)
4917 num_factories += int32_t(state.world.province_get_factory_location(p.get_province()).end() - state.world.province_get_factory_location(p.get_province()).begin());
4918 for(auto p : state.world.state_instance_get_state_building_construction(sid))
4919 if(p.get_is_upgrade() == false)
4920 ++num_factories;
4921
4922 // For new factories: no more than defines:FACTORIES_PER_STATE existing + under construction new factories must be
4923 assert(num_factories <= int32_t(state.defines.factories_per_state));
4924 return num_factories;
4925}
4927float unit_construction_progress(sys::state& state, dcon::province_land_construction_id c) {
4928
4929 float admin_eff = state.world.nation_get_administrative_efficiency(state.world.province_land_construction_get_nation(c));
4930 float admin_cost_factor = 2.0f - admin_eff;
4931
4932 auto& goods = state.military_definitions.unit_base_definitions[state.world.province_land_construction_get_type(c)].build_cost;
4933 auto& cgoods = state.world.province_land_construction_get_purchased_goods(c);
4934
4935 float total = 0.0f;
4936 float purchased = 0.0f;
4937
4938 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
4939 total += goods.commodity_amounts[i] * admin_cost_factor;
4940 purchased += cgoods.commodity_amounts[i];
4941 }
4942
4943 return total > 0.0f ? purchased / total : 0.0f;
4944}
4946float unit_construction_progress(sys::state& state, dcon::province_naval_construction_id c) {
4947 float admin_eff = state.world.nation_get_administrative_efficiency(state.world.province_naval_construction_get_nation(c));
4948 float admin_cost_factor = 2.0f - admin_eff;
4949
4950 auto& goods = state.military_definitions.unit_base_definitions[state.world.province_naval_construction_get_type(c)].build_cost;
4951 auto& cgoods = state.world.province_naval_construction_get_purchased_goods(c);
4952
4953 float total = 0.0f;
4954 float purchased = 0.0f;
4955
4956 for(uint32_t i = 0; i < commodity_set::set_size; ++i) {
4957 total += goods.commodity_amounts[i] * admin_cost_factor;
4958 purchased += cgoods.commodity_amounts[i];
4959 }
4960
4961 return total > 0.0f ? purchased / total : 0.0f;
4962}
4964void add_factory_level_to_state(sys::state& state, dcon::state_instance_id s, dcon::factory_type_id t, bool is_upgrade) {
4965
4966 if(is_upgrade) {
4967 auto d = state.world.state_instance_get_definition(s);
4968 auto o = state.world.state_instance_get_nation_from_state_ownership(s);
4969 for(auto p : state.world.state_definition_get_abstract_state_membership(d)) {
4970 if(p.get_province().get_nation_from_province_ownership() == o) {
4971 for(auto f : p.get_province().get_factory_location()) {
4972 if(f.get_factory().get_building_type() == t) {
4973 auto factory_level = f.get_factory().get_level();
4974 auto new_factory_level = std::min(float(std::numeric_limits<uint8_t>::max()), float(factory_level) + 1.f + math::sqrt(f.get_factory().get_level()) / 2.f);
4975 f.get_factory().get_level() = uint8_t(new_factory_level);
4976 return;
4977 }
4978 }
4979 }
4980 }
4981 }
4982 auto state_cap = state.world.state_instance_get_capital(s);
4983 auto new_fac = fatten(state.world, state.world.create_factory());
4984 new_fac.set_building_type(t);
4985 new_fac.set_level(uint8_t(1));
4986 new_fac.set_production_scale(1.0f);
4987
4988 state.world.try_create_factory_location(new_fac, state_cap);
4989}
4991void resolve_constructions(sys::state& state) {
4992
4993 for(uint32_t i = state.world.province_land_construction_size(); i-- > 0;) {
4994 auto c = fatten(state.world, dcon::province_land_construction_id{dcon::province_land_construction_id::value_base_t(i)});
4995
4996 float admin_eff = state.world.nation_get_administrative_efficiency(state.world.province_land_construction_get_nation(c));
4997 float admin_cost_factor = 2.0f - admin_eff;
4998
4999 auto& base_cost = state.military_definitions.unit_base_definitions[c.get_type()].build_cost;
5000 auto& current_purchased = c.get_purchased_goods();
5001 float construction_time = float(state.military_definitions.unit_base_definitions[c.get_type()].build_time);
5002
5003 bool all_finished = true;
5004 if(!(c.get_nation().get_is_player_controlled() && state.cheat_data.instant_army)) {
5005 for(uint32_t j = 0; j < commodity_set::set_size && all_finished; ++j) {
5006 if(base_cost.commodity_type[j]) {
5007 if(current_purchased.commodity_amounts[j] < base_cost.commodity_amounts[j] * admin_cost_factor) {
5008 all_finished = false;
5009 }
5010 } else {
5011 break;
5012 }
5013 }
5014 }
5015
5016 if(all_finished) {
5017 auto pop_location = c.get_pop().get_province_from_pop_location();
5018
5019 auto new_reg = military::create_new_regiment(state, c.get_nation(), c.get_type());
5020 auto a = fatten(state.world, state.world.create_army());
5021
5022 a.set_controller_from_army_control(c.get_nation());
5023 state.world.try_create_army_membership(new_reg, a);
5024 state.world.try_create_regiment_source(new_reg, c.get_pop());
5026 military::move_land_to_merge(state, c.get_nation(), a, pop_location, c.get_template_province());
5027
5028 if(c.get_nation() == state.local_player_nation) {
5030 text::add_line(state, contents, "amsg_army_built");
5031 },
5032 "amsg_army_built",
5033 state.local_player_nation, dcon::nation_id{}, dcon::nation_id{},
5035 });
5036 }
5037
5038 state.world.delete_province_land_construction(c);
5039 }
5040 }
5041
5042 province::for_each_land_province(state, [&](dcon::province_id p) {
5043 auto rng = state.world.province_get_province_naval_construction(p);
5044 if(rng.begin() != rng.end()) {
5045 auto c = *(rng.begin());
5046
5047 float admin_eff = state.world.nation_get_administrative_efficiency(state.world.province_naval_construction_get_nation(c));
5048 float admin_cost_factor = 2.0f - admin_eff;
5049
5050 auto& base_cost = state.military_definitions.unit_base_definitions[c.get_type()].build_cost;
5051 auto& current_purchased = c.get_purchased_goods();
5052 float construction_time = float(state.military_definitions.unit_base_definitions[c.get_type()].build_time);
5053
5054 bool all_finished = true;
5055 if(!(c.get_nation().get_is_player_controlled() && state.cheat_data.instant_navy)) {
5056 for(uint32_t i = 0; i < commodity_set::set_size && all_finished; ++i) {
5057 if(base_cost.commodity_type[i]) {
5058 if(current_purchased.commodity_amounts[i] < base_cost.commodity_amounts[i] * admin_cost_factor) {
5059 all_finished = false;
5060 }
5061 } else {
5062 break;
5063 }
5064 }
5065 }
5066
5067 if(all_finished) {
5068 auto new_ship = military::create_new_ship(state, c.get_nation(), c.get_type());
5069 auto a = fatten(state.world, state.world.create_navy());
5070 a.set_controller_from_navy_control(c.get_nation());
5071 a.set_location_from_navy_location(p);
5072 state.world.try_create_navy_membership(new_ship, a);
5073 military::move_navy_to_merge(state, c.get_nation(), a, c.get_province(), c.get_template_province());
5074
5075 if(c.get_nation() == state.local_player_nation) {
5076 notification::post(state, notification::message{ [](sys::state& state, text::layout_base& contents) {
5077 text::add_line(state, contents, "amsg_navy_built");
5078 },
5079 "amsg_navy_built",
5080 state.local_player_nation, dcon::nation_id{}, dcon::nation_id{},
5081 sys::message_base_type::navy_built
5082 });
5083 }
5084
5085 state.world.delete_province_naval_construction(c);
5086 }
5087 }
5088 });
5089
5090 for(uint32_t i = state.world.province_building_construction_size(); i-- > 0;) {
5091 dcon::province_building_construction_id c{dcon::province_building_construction_id::value_base_t(i)};
5092 auto for_province = state.world.province_building_construction_get_province(c);
5093
5094 float admin_eff = state.world.nation_get_administrative_efficiency(state.world.province_building_construction_get_nation(c));
5095 float admin_cost_factor = state.world.province_building_construction_get_is_pop_project(c) ? 1.0f : 2.0f - admin_eff;
5096
5097 auto t = province_building_type(state.world.province_building_construction_get_type(c));
5098 auto& base_cost = state.economy_definitions.building_definitions[int32_t(t)].cost;
5099 auto& current_purchased = state.world.province_building_construction_get_purchased_goods(c);
5100 bool all_finished = true;
5101
5102 for(uint32_t j = 0; j < commodity_set::set_size && all_finished; ++j) {
5103 if(base_cost.commodity_type[j]) {
5104 if(current_purchased.commodity_amounts[j] < base_cost.commodity_amounts[j] * admin_cost_factor) {
5105 all_finished = false;
5106 }
5107 } else {
5108 break;
5109 }
5110 }
5111
5112 if(all_finished) {
5113 if(state.world.province_get_building_level(for_province, uint8_t(t)) < state.world.nation_get_max_building_level(state.world.province_get_nation_from_province_ownership(for_province), uint8_t(t))) {
5114 state.world.province_get_building_level(for_province, uint8_t(t)) += 1;
5115
5116 if(t == province_building_type::railroad) {
5117 /* Notify the railroad mesh builder to update the railroads! */
5118 state.railroad_built.store(true, std::memory_order::release);
5119 }
5120
5121 if(state.world.province_building_construction_get_nation(c) == state.local_player_nation) {
5122 switch(t) {
5123 case province_building_type::naval_base:
5125 text::add_line(state, contents, "amsg_naval_base_complete");
5126 },
5127 "amsg_naval_base_complete",
5128 state.local_player_nation, dcon::nation_id{}, dcon::nation_id{},
5130 });
5131 break;
5132 case province_building_type::fort:
5134 text::add_line(state, contents, "amsg_fort_complete");
5135 },
5136 "amsg_fort_complete",
5137 state.local_player_nation, dcon::nation_id{}, dcon::nation_id{},
5139 });
5140 break;
5141 case province_building_type::railroad:
5143 text::add_line(state, contents, "amsg_rr_complete");
5144 },
5145 "amsg_rr_complete",
5146 state.local_player_nation, dcon::nation_id{}, dcon::nation_id{},
5148 });
5149 break;
5150 default:
5151 break;
5152 }
5153 }
5154 }
5155 state.world.delete_province_building_construction(c);
5156 }
5157 }
5158
5159 for(uint32_t i = state.world.state_building_construction_size(); i-- > 0;) {
5160 dcon::state_building_construction_id c{dcon::state_building_construction_id::value_base_t(i)};
5161 auto n = state.world.state_building_construction_get_nation(c);
5162 auto type = state.world.state_building_construction_get_type(c);
5163 auto& base_cost = state.world.factory_type_get_construction_costs(type);
5164 auto& current_purchased = state.world.state_building_construction_get_purchased_goods(c);
5165
5166 if(!state.world.state_building_construction_get_is_pop_project(c)) {
5167 float admin_eff = state.world.nation_get_administrative_efficiency(n);
5168 float admin_cost_factor = 2.0f - admin_eff;
5169
5170 float factory_mod = state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_cost) + 1.0f;
5171
5172 bool all_finished = true;
5173 if(!(n == state.local_player_nation && state.cheat_data.instant_industry)) {
5174 for(uint32_t j = 0; j < commodity_set::set_size && all_finished; ++j) {
5175 if(base_cost.commodity_type[j]) {
5176 if(current_purchased.commodity_amounts[j] < base_cost.commodity_amounts[j] * factory_mod * admin_cost_factor) {
5177 all_finished = false;
5178 }
5179 } else {
5180 break;
5181 }
5182 }
5183 }
5184 if(all_finished) {
5185 add_factory_level_to_state(state, state.world.state_building_construction_get_state(c), type,
5186 state.world.state_building_construction_get_is_upgrade(c));
5187 state.world.delete_state_building_construction(c);
5188 }
5189 } else {
5190 float factory_mod = (state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_cost) + 1.0f) *
5191 std::max(0.1f, state.world.nation_get_modifier_values(n, sys::national_mod_offsets::factory_owner_cost));
5192
5193 bool all_finished = true;
5194 if(!(n == state.local_player_nation && state.cheat_data.instant_industry)) {
5195 for(uint32_t j = 0; j < commodity_set::set_size && all_finished; ++j) {
5196 if(base_cost.commodity_type[j]) {
5197 if(current_purchased.commodity_amounts[j] < base_cost.commodity_amounts[j] * factory_mod) {
5198 all_finished = false;
5199 }
5200 } else {
5201 break;
5202 }
5203 }
5204 }
5205 if(all_finished) {
5206 add_factory_level_to_state(state, state.world.state_building_construction_get_state(c), type,
5207 state.world.state_building_construction_get_is_upgrade(c));
5208
5209 if(state.world.state_building_construction_get_nation(c) == state.local_player_nation) {
5211 text::add_line(state, contents, "amsg_factory_complete");
5212 },
5213 "amsg_factory_complete",
5214 state.local_player_nation, dcon::nation_id{}, dcon::nation_id{},
5216 });
5217 }
5218
5219 state.world.delete_state_building_construction(c);
5220 }
5221 }
5222 }
5223}
5224
5225/* TODO -
5226 * This should return what we think the income will be next day, and as a result wont account for any unprecedented actions
5227 * return value is passed directly into text::fp_currency{} without adulteration.
5229float estimate_daily_income(sys::state& state, dcon::nation_id n) {
5230 auto const tax_eff = nations::tax_efficiency(state, n);
5231 return (
5232 state.world.nation_get_total_poor_income(n) * state.world.nation_get_poor_tax(n) / 100.f
5233 + state.world.nation_get_total_middle_income(n) * state.world.nation_get_middle_tax(n) / 100.f
5234 + state.world.nation_get_total_rich_income(n) * state.world.nation_get_rich_tax(n) / 100.f
5235 ) * tax_eff;
5236}
5238void try_add_factory_to_state(sys::state& state, dcon::state_instance_id s, dcon::factory_type_id t) {
5239 auto n = state.world.state_instance_get_nation_from_state_ownership(s);
5240
5241 if(state.world.factory_type_get_is_coastal(t)) {
5242 if(!province::state_is_coastal(state, s))
5243 return; // requires coast to build coastal factory
5244 }
5245
5246 auto existing_constructions = state.world.state_instance_get_state_building_construction(s);
5247 int32_t num_factories = 0;
5248 for(auto prj : existing_constructions) {
5249 if(!prj.get_is_upgrade())
5250 ++num_factories;
5251 if(prj.get_type() == t)
5252 return; // can't duplicate type
5253 }
5254
5255 // is there an upgrade target ?
5256 auto d = state.world.state_instance_get_definition(s);
5257 for(auto p : state.world.state_definition_get_abstract_state_membership(d)) {
5258 if(p.get_province().get_nation_from_province_ownership() == n) {
5259 for(auto f : p.get_province().get_factory_location()) {
5260 ++num_factories;
5261 if(f.get_factory().get_building_type() == t)
5262 return; // can't build another of this type
5263 }
5264 }
5265 }
5266
5267 if(num_factories < int32_t(state.defines.factories_per_state)) {
5268 add_factory_level_to_state(state, s, t, false);
5269 }
5270}
5272void bound_budget_settings(sys::state& state, dcon::nation_id n) {
5273 {
5274 auto min_tariff = int32_t(100.0f * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::min_tariff));
5275 auto max_tariff = int32_t(100.0f * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::max_tariff));
5276 max_tariff = std::max(min_tariff, max_tariff);
5277
5278 auto& tariff = state.world.nation_get_tariffs(n);
5279 tariff = int8_t(std::clamp(std::clamp(int32_t(tariff), min_tariff, max_tariff), -100, 100));
5280 }
5281 {
5282 auto min_tax = int32_t(100.0f * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::min_tax));
5283 auto max_tax = int32_t(100.0f * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::max_tax));
5284 if(max_tax <= 0)
5285 max_tax = 100;
5286 max_tax = std::max(min_tax, max_tax);
5287
5288 auto& ptax = state.world.nation_get_poor_tax(n);
5289 ptax = int8_t(std::clamp(std::clamp(int32_t(ptax), min_tax, max_tax), 0, 100));
5290 auto& mtax = state.world.nation_get_middle_tax(n);
5291 mtax = int8_t(std::clamp(std::clamp(int32_t(mtax), min_tax, max_tax), 0, 100));
5292 auto& rtax = state.world.nation_get_rich_tax(n);
5293 rtax = int8_t(std::clamp(std::clamp(int32_t(rtax), min_tax, max_tax), 0, 100));
5294 }
5295 {
5296 auto min_spend =
5297 int32_t(100.0f * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::min_military_spending));
5298 auto max_spend =
5299 int32_t(100.0f * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::max_military_spending));
5300 if(max_spend <= 0)
5301 max_spend = 100;
5302 max_spend = std::max(min_spend, max_spend);
5303
5304 auto& v = state.world.nation_get_military_spending(n);
5305 v = int8_t(std::clamp(std::clamp(int32_t(v), min_spend, max_spend), 0, 100));
5306 }
5307 {
5308 auto min_spend = int32_t(100.0f * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::min_social_spending));
5309 auto max_spend = int32_t(100.0f * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::max_social_spending));
5310 if(max_spend <= 0)
5311 max_spend = 100;
5312 max_spend = std::max(min_spend, max_spend);
5313
5314 auto& v = state.world.nation_get_social_spending(n);
5315 v = int8_t(std::clamp(std::clamp(int32_t(v), min_spend, max_spend), 0, 100));
5316 }
5317 {
5318 auto min_spend =
5319 int32_t(100.0f * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::min_military_spending));
5320 auto max_spend =
5321 int32_t(100.0f * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::max_military_spending));
5322 if(max_spend <= 0)
5323 max_spend = 100;
5324 max_spend = std::max(min_spend, max_spend);
5325
5326 auto& v = state.world.nation_get_military_spending(n);
5327 v = int8_t(std::clamp(std::clamp(int32_t(v), min_spend, max_spend), 0, 100));
5328 }
5329 {
5330 auto min_spend = int32_t(100.0f * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::min_domestic_investment));
5331 auto max_spend = int32_t(100.0f * state.world.nation_get_modifier_values(n, sys::national_mod_offsets::max_domestic_investment));
5332 if(max_spend <= 0)
5333 max_spend = 100;
5334 max_spend = std::max(min_spend, max_spend);
5335
5336 auto& v = state.world.nation_get_domestic_investment_spending(n);
5337 v = int8_t(std::clamp(std::clamp(int32_t(v), min_spend, max_spend), 0, 100));
5338 }
5339}
5341void prune_factories(sys::state& state) {
5342 for(auto si : state.world.in_state_instance) {
5343 auto owner = si.get_nation_from_state_ownership();
5344 auto rules = owner.get_combined_issue_rules();
5345
5346 if(owner.get_is_player_controlled() && (rules & issue_rule::destroy_factory) != 0) // not for players who can manually destroy
5347 continue;
5348
5349 dcon::factory_id deletion_choice;
5350 int32_t factory_count = 0;
5351
5352 province::for_each_province_in_state_instance(state, si, [&](dcon::province_id p) {
5353 for(auto f : state.world.province_get_factory_location(p)) {
5354 ++factory_count;
5355 auto scale = f.get_factory().get_production_scale();
5356 float ten_workers = 10.f / factory_max_employment(state, f.get_factory());
5357 bool unprofitable = f.get_factory().get_unprofitable();
5358 if(((scale < ten_workers) && unprofitable) && (!deletion_choice || state.world.factory_get_level(deletion_choice) > f.get_factory().get_level())) {
5359 deletion_choice = f.get_factory();
5360 }
5361 }
5362 });
5363
5364 // aggressive pruning
5365 // to help building more healthy economy instead of 1 profitable giant factory with 6 small 0 scale factories
5366 if(deletion_choice && (4 + factory_count) >= int32_t(state.defines.factories_per_state)) {
5367 auto production_type = state.world.factory_get_building_type(deletion_choice);
5368 state.world.delete_factory(deletion_choice);
5369
5370 for(auto proj : si.get_state_building_construction()) {
5371 if(proj.get_type() == production_type) {
5372 state.world.delete_state_building_construction(proj);
5373 break;
5374 }
5375 }
5376 }
5377 }
5378}
5380dcon::modifier_id get_province_selector_modifier(sys::state& state) {
5381 return state.economy_definitions.selector_modifier;
5382}
5384dcon::modifier_id get_province_immigrator_modifier(sys::state& state) {
5385 return state.economy_definitions.immigrator_modifier;
5386}
5388void go_bankrupt(sys::state& state, dcon::nation_id n) {
5389 auto& debt = state.world.nation_get_stockpiles(n, economy::money);
5390
5391 /*
5392 If a nation cannot pay and the amount it owes is less than define:SMALL_DEBT_LIMIT, the nation it owes money to gets an on_debtor_default_small event (with the nation defaulting in the from slot). Otherwise, the event is pulled from on_debtor_default. The nation then goes bankrupt. It receives the bad_debter modifier for define:BANKRUPCY_EXTERNAL_LOAN_YEARS years (if it goes bankrupt again within this period, creditors receive an on_debtor_default_second event). It receives the in_bankrupcy modifier for define:BANKRUPCY_DURATION days. Its prestige is reduced by a factor of define:BANKRUPCY_FACTOR, and each of its pops has their militancy increase by 2.
5393 */
5394 auto existing_br = state.world.nation_get_bankrupt_until(n);
5395 if(existing_br && state.current_date < existing_br) {
5396 for(auto gn : state.great_nations) {
5397 if(gn.nation && gn.nation != n) {
5398 event::fire_fixed_event(state, state.national_definitions.on_debtor_default_second, trigger::to_generic(gn.nation), event::slot_type::nation, gn.nation, trigger::to_generic(n), event::slot_type::nation);
5399 }
5400 }
5401 } else if(debt >= -state.defines.small_debt_limit) {
5402 for(auto gn : state.great_nations) {
5403 if(gn.nation && gn.nation != n) {
5404 event::fire_fixed_event(state, state.national_definitions.on_debtor_default_small, trigger::to_generic(gn.nation), event::slot_type::nation, gn.nation, trigger::to_generic(n), event::slot_type::nation);
5405 }
5406 }
5407 } else {
5408 for(auto gn : state.great_nations) {
5409 if(gn.nation && gn.nation != n) {
5410 event::fire_fixed_event(state, state.national_definitions.on_debtor_default, trigger::to_generic(gn.nation), event::slot_type::nation, gn.nation, trigger::to_generic(n), event::slot_type::nation);
5411 }
5412 }
5413 }
5414
5415 sys::add_modifier_to_nation(state, n, state.national_definitions.in_bankrupcy, state.current_date + int32_t(state.defines.bankrupcy_duration * 365));
5416 sys::add_modifier_to_nation(state, n, state.national_definitions.bad_debter, state.current_date + int32_t(state.defines.bankruptcy_external_loan_years * 365));
5417
5418 debt = 0.0f;
5419 state.world.nation_set_is_debt_spending(n, false);
5420 state.world.nation_set_bankrupt_until(n, state.current_date + int32_t(state.defines.bankrupcy_duration * 365));
5421
5423 [n](sys::state& state, text::layout_base& contents) {
5424 text::add_line(state, contents, "msg_bankruptcy_1", text::variable_type::x, n);
5425 },
5426 "msg_bankruptcy_title",
5427 n, dcon::nation_id{}, dcon::nation_id{},
5429 });
5430}
5433 auto commodity = dcon::fatten(state.world, c);
5434 if(commodity.get_rgo_amount() > 0 && (commodity.get_artisan_output_amount() > 0 || commodity.get_key_factory()))
5435 return commodity_production_type::both;
5436 else if(commodity.get_key_factory())
5437 return commodity_production_type::derivative;
5438 else
5439 return commodity_production_type::primary;
5440
5441
5442}
5443
5444} // namespace economy
#define assert(condition)
Definition: debug.h:74
void update_budget(sys::state &state)
Definition: ai.cpp:3098
void get_desired_factory_types(sys::state &state, dcon::nation_id nid, std::vector< dcon::factory_type_id > &desired_types)
Definition: ai.cpp:902
pop_satisfaction_wrapper_fat fatten(data_container const &c, pop_satisfaction_wrapper_id id) noexcept
constexpr dcon::demographics_key total(0)
dcon::demographics_key to_key(sys::state const &state, dcon::pop_type_id v)
dcon::demographics_key to_employment_key(sys::state const &state, dcon::pop_type_id v)
float estimate_reparations_income(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4655
bool state_contains_factory(sys::state &state, dcon::state_instance_id s, dcon::factory_type_id ft)
Definition: economy.cpp:4892
float factory_full_production_quantity(sys::state const &state, dcon::factory_id f, dcon::nation_id n, float mobilization_impact)
Definition: economy.cpp:1274
void initialize(sys::state &state)
Definition: economy.cpp:593
bool valid_artisan_good(sys::state &state, dcon::nation_id n, dcon::commodity_id cid)
Definition: economy.cpp:454
float global_market_commodity_daily_increase(sys::state &state, dcon::commodity_id c)
Definition: economy.cpp:123
dcon::modifier_id get_province_immigrator_modifier(sys::state &state)
Definition: economy.cpp:5383
constexpr float subsistence_score_life
Definition: economy.hpp:93
float total_artisan_exp_score(sys::state &state, dcon::nation_id n, float multiplier, float max_score)
Definition: economy.cpp:516
void register_demand(sys::state &state, dcon::nation_id n, dcon::commodity_id commodity_type, float amount, economy_reason reason)
Definition: economy.cpp:19
float full_private_investment_cost(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:2374
float estimate_subsidy_spending(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4641
constexpr float diff_factory
Definition: economy.cpp:2052
void populate_effective_prices(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:2847
void update_national_consumption(sys::state &state, dcon::nation_id n, float spending_scale, float private_investment_scale)
Definition: economy.cpp:2384
constexpr float slope_factory
Definition: economy.cpp:2054
void for_each_new_factory(sys::state &state, dcon::state_instance_id s, F &&func)
float government_consumption(sys::state &state, dcon::nation_id n, dcon::commodity_id c)
Definition: economy.cpp:4380
float estimate_social_spending(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4576
construction_status province_building_construction(sys::state &state, dcon::province_id p, province_building_type t)
Definition: economy.cpp:4832
float rgo_total_effective_size(sys::state &state, dcon::nation_id n, dcon::province_id p)
Definition: economy.cpp:931
float nation_total_imports(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4527
bool state_contains_constructed_factory(sys::state &state, dcon::state_instance_id s, dcon::factory_type_id ft)
Definition: economy.cpp:4879
float estimate_tariff_income(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4572
float factory_desired_raw_profit(dcon::factory_fat_id fac, float spendings)
Definition: economy.cpp:1533
bool has_building(sys::state const &state, dcon::state_instance_id si, dcon::factory_type_id fac)
Definition: economy.cpp:384
float factory_max_employment(sys::state const &state, dcon::factory_id f)
Definition: economy.cpp:1124
void advance_construction(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:2642
void update_factory_employment(sys::state &state)
Definition: economy.cpp:1143
bool is_bankrupt_debtor_to(sys::state &state, dcon::nation_id debt_holder, dcon::nation_id debtor)
Definition: economy.cpp:398
int32_t state_factory_count(sys::state &state, dcon::state_instance_id sid, dcon::nation_id n)
Definition: economy.cpp:4911
float sphere_leader_share_factor(sys::state &state, dcon::nation_id sphere_leader, dcon::nation_id sphere_member)
Definition: economy.cpp:810
constexpr float diff_non_factory
Definition: economy.cpp:2038
float estimate_diplomatic_balance(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4700
void prune_factories(sys::state &state)
Definition: economy.cpp:5340
constexpr float day_inf_build_time_modifier_non_factory
Definition: economy.cpp:2035
void update_factory_triggered_modifiers(sys::state &state)
Definition: economy.cpp:877
void convert_commodities_into_ingredients(sys::state &state, std::vector< float > &buffer_commodities, std::vector< float > &buffer_ingredients, std::vector< float > &buffer_weights)
Definition: economy.cpp:284
constexpr uint32_t gdp_history_length
Definition: economy.hpp:123
float estimate_pop_payouts_by_income_type(sys::state &state, dcon::nation_id n, culture::income_type in)
Definition: economy.cpp:4602
void populate_construction_consumption(sys::state &state)
Definition: economy.cpp:2065
float estimate_domestic_investment(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4706
int32_t previous_price_record_index(sys::state &state)
Definition: economy.cpp:85
void populate_private_construction_consumption(sys::state &state)
Definition: economy.cpp:2174
constexpr float day_inf_build_time_modifier_factory
Definition: economy.cpp:2049
rgo_workers_breakdown rgo_relevant_population(sys::state &state, dcon::province_id p, dcon::nation_id n)
Definition: economy.cpp:1727
float rgo_desired_worker_norm_profit(sys::state &state, dcon::province_id p, dcon::nation_id n, float min_wage, float total_relevant_population)
Definition: economy.cpp:1743
float factory_min_input_available(sys::state &state, dcon::nation_id n, dcon::factory_type_fat_id fac_type)
Definition: economy.cpp:1356
float estimate_overseas_penalty_spending(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:2354
float nation_factory_consumption(sys::state &state, dcon::nation_id n, dcon::commodity_id c)
Definition: economy.cpp:4435
float nation_factory_input_multiplier(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:1422
constexpr float shift_factory
Definition: economy.cpp:2053
float base_artisan_profit(sys::state &state, dcon::nation_id n, dcon::commodity_id c)
Definition: economy.cpp:422
commodity_production_type get_commodity_production_type(sys::state &state, dcon::commodity_id c)
Definition: economy.cpp:5431
bool has_factory(sys::state const &state, dcon::state_instance_id si)
Definition: economy.cpp:128
float max_loan(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:73
float estimate_construction_spending(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4740
float max_artisan_score(sys::state &state, dcon::nation_id n, float multiplier)
Definition: economy.cpp:496
float effective_tariff_rate(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:860
float estimate_war_subsidies_income(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4645
construction_status factory_upgrade(sys::state &state, dcon::factory_id f)
Definition: economy.cpp:4850
float gdp_adjusted(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:103
void presimulate(sys::state &state)
Definition: economy.cpp:370
void register_domestic_supply(sys::state &state, dcon::nation_id n, dcon::commodity_id commodity_type, float amount, economy_reason reason)
Definition: economy.cpp:40
void update_rgo_employment(sys::state &state)
Definition: economy.cpp:1020
profit_distribution distribute_factory_profit(sys::state const &state, dcon::state_instance_const_fat_id s, float min_wage, float total_profit)
Definition: economy.cpp:2905
float full_spending_cost(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:2224
float estimate_land_spending(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4720
constexpr float day_1_build_time_modifier_factory
Definition: economy.cpp:2048
void update_national_artisan_consumption(sys::state &state, dcon::nation_id n, float expected_min_wage, float mobilization_impact)
Definition: economy.cpp:1878
float rgo_total_employment(sys::state &state, dcon::nation_id n, dcon::province_id p)
Definition: economy.cpp:943
commodity_production_type
Definition: economy.hpp:8
float estimate_daily_income(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:5228
void update_single_factory_production(sys::state &state, dcon::factory_id f, dcon::nation_id n, float expected_min_wage)
Definition: economy.cpp:1666
constexpr uint32_t price_history_length
Definition: economy.hpp:122
float rgo_total_max_employment(sys::state &state, dcon::nation_id n, dcon::province_id p)
Definition: economy.cpp:955
void adjust_artisan_balance(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:556
constexpr float artisan_baseline_score
Definition: economy.cpp:494
void regenerate_unsaved_values(sys::state &state)
Definition: economy.cpp:4332
float artisan_scale_limit(sys::state &state, dcon::nation_id n, dcon::commodity_id c)
Definition: economy.cpp:440
constexpr dcon::commodity_id money(0)
void update_land_ownership(sys::state &state)
Definition: economy.cpp:987
float rgo_efficiency(sys::state &state, dcon::nation_id n, dcon::province_id p, dcon::commodity_id c)
Definition: economy.cpp:1301
bool can_take_loans(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:48
economy_reason
Definition: economy.cpp:15
dcon::modifier_id get_province_selector_modifier(sys::state &state)
Definition: economy.cpp:5379
float unit_construction_progress(sys::state &state, dcon::province_land_construction_id c)
Definition: economy.cpp:4926
constexpr float factory_closed_threshold
Definition: economy.hpp:121
int32_t most_recent_price_record_index(sys::state &state)
Definition: economy.cpp:82
float factory_throughput_multiplier(sys::state &state, dcon::factory_type_fat_id fac_type, dcon::nation_id n, dcon::province_id p, dcon::state_instance_id s)
Definition: economy.cpp:1463
void try_add_factory_to_state(sys::state &state, dcon::state_instance_id s, dcon::factory_type_id t)
Definition: economy.cpp:5237
float pseudo_exp_for_negative(float f)
Definition: economy.cpp:470
bool nation_is_constructing_factories(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:404
float pop_income(sys::state &state, dcon::pop_id p)
Definition: economy.cpp:4539
float rgo_effective_size(sys::state const &state, dcon::nation_id n, dcon::province_id p, dcon::commodity_id c)
Definition: economy.cpp:909
float factory_max_production_scale_non_modified(sys::state &state, dcon::factory_fat_id fac)
Definition: economy.cpp:1482
void update_province_rgo_consumption(sys::state &state, dcon::province_id p, dcon::nation_id n, float mobilization_impact, float expected_min_wage, bool occupied)
Definition: economy.cpp:1812
float subsistence_size(sys::state const &state, dcon::province_id p)
Definition: economy.cpp:904
constexpr float subsistence_score_luxury
Definition: economy.hpp:95
float pop_factory_min_wage(sys::state &state, dcon::nation_id n, float min_wage_factor)
Definition: economy.cpp:2832
float estimate_war_subsidies_spending(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4671
float factory_max_production_scale(sys::state &state, dcon::factory_fat_id fac, float mobilization_impact, bool occupied)
Definition: economy.cpp:1487
float commodity_daily_production_amount(sys::state &state, dcon::commodity_id c)
Definition: economy.cpp:114
float global_non_factory_construction_time_modifier(sys::state &state)
Definition: economy.cpp:2043
float global_market_price_multiplier(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:866
float estimate_war_subsidies(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4827
float rgo_expected_worker_norm_profit(sys::state &state, dcon::province_id p, dcon::nation_id n, dcon::commodity_id c)
Definition: economy.cpp:1793
constexpr float subsistence_factor
Definition: economy.hpp:92
constexpr float production_scale_delta
Definition: economy.hpp:120
bool factory_is_profitable(sys::state const &state, dcon::factory_id f)
Definition: economy.cpp:1011
float convex_function(float x)
Definition: economy.cpp:1808
float estimate_reparations_spending(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4683
int32_t most_recent_gdp_record_index(sys::state &state)
Definition: economy.cpp:89
float nation_factory_output_multiplier(sys::state &state, dcon::factory_type_id fac_type, dcon::nation_id n)
Definition: economy.cpp:1429
float estimate_naval_spending(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4730
float subsistence_max_pseudoemployment(sys::state &state, dcon::nation_id n, dcon::province_id p)
Definition: economy.cpp:939
float get_artisan_distribution_fast(sys::state &state, dcon::nation_id n, dcon::commodity_id c, float max_score, float total_score, float multiplier)
Definition: economy.cpp:534
void for_each_upgraded_factory(sys::state &state, dcon::state_instance_id s, F &&func)
void initialize_needs_weights(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:166
void go_bankrupt(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:5387
void give_sphere_leader_production(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:848
void bound_budget_settings(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:5271
constexpr float slope_non_factory
Definition: economy.cpp:2040
float adjusted_subsistence_score(sys::state &state, dcon::province_id p)
Definition: economy.cpp:981
float get_artisans_multiplier(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:489
float factory_secondary_employment(sys::state const &state, dcon::factory_id f)
Definition: economy.cpp:1132
constexpr float shift_non_factory
Definition: economy.cpp:2039
float rgo_max_employment(sys::state &state, dcon::nation_id n, dcon::province_id p, dcon::commodity_id c)
Definition: economy.cpp:951
float pop_min_wage_factor(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:2813
void resolve_constructions(sys::state &state)
Definition: economy.cpp:4990
void update_province_rgo_production(sys::state &state, dcon::province_id p, dcon::nation_id n)
Definition: economy.cpp:1856
float need_weight(sys::state &state, dcon::nation_id n, dcon::commodity_id c)
Definition: economy.cpp:196
void update_local_subsistence_factor(sys::state &state)
Definition: economy.cpp:963
float estimate_tax_income_by_strata(sys::state &state, dcon::nation_id n, culture::pop_strata ps)
Definition: economy.cpp:4629
float pop_farmer_min_wage(sys::state &state, dcon::nation_id n, float min_wage_factor)
Definition: economy.cpp:2818
float factory_total_employment(sys::state const &state, dcon::factory_id f)
Definition: economy.cpp:1136
float estimate_stockpile_filling_spending(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:2339
void update_pop_consumption(sys::state &state, dcon::nation_id n, float base_demand, float invention_factor)
Definition: economy.cpp:2426
constexpr float rgo_owners_cut
Definition: economy.hpp:124
float stockpile_commodity_daily_increase(sys::state &state, dcon::commodity_id c, dcon::nation_id n)
Definition: economy.cpp:118
float pop_laborer_min_wage(sys::state &state, dcon::nation_id n, float min_wage_factor)
Definition: economy.cpp:2825
void populate_needs_costs(sys::state &state, dcon::nation_id n, float base_demand, float invention_factor)
Definition: economy.cpp:2592
float factory_input_multiplier(sys::state &state, dcon::factory_fat_id fac, dcon::nation_id n, dcon::province_id p, dcon::state_instance_id s)
Definition: economy.cpp:1436
void rebalance_needs_weights(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:200
void populate_army_consumption(sys::state &state)
Definition: economy.cpp:1977
void absorb_sphere_member_production(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:833
void add_factory_level_to_state(sys::state &state, dcon::state_instance_id s, dcon::factory_type_id t, bool is_upgrade)
Definition: economy.cpp:4963
constexpr float ln_2
Definition: economy.cpp:467
void emulate_construction_demand(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:2949
float factory_input_total_cost(sys::state &state, dcon::nation_id n, dcon::factory_type_fat_id fac_type)
Definition: economy.cpp:1377
constexpr float day_1_derivative_factory
Definition: economy.cpp:2050
float rgo_full_production_quantity(sys::state &state, dcon::nation_id n, dcon::province_id p, dcon::commodity_id c)
Definition: economy.cpp:1342
province_building_type
Definition: constants.hpp:578
float global_factory_construction_time_modifier(sys::state &state)
Definition: economy.cpp:2060
void populate_navy_consumption(sys::state &state)
Definition: economy.cpp:2004
float interest_payment(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:62
float factory_e_input_total_cost(sys::state &state, dcon::nation_id n, dcon::factory_type_fat_id fac_type)
Definition: economy.cpp:1408
void initialize_artisan_distribution(sys::state &state)
Definition: economy.cpp:147
void daily_update(sys::state &state, bool initiate_buildings)
Definition: economy.cpp:3070
void set_factory_priority(sys::state &state, dcon::factory_id f, int32_t priority)
Definition: economy.cpp:1007
float factory_primary_employment(sys::state const &state, dcon::factory_id f)
Definition: economy.cpp:1128
void register_construction_demand(sys::state &state, dcon::nation_id n, dcon::commodity_id commodity_type, float amount)
Definition: economy.cpp:36
float update_factory_scale(sys::state &state, dcon::factory_fat_id fac, float max_production_scale, float raw_profit, float desired_raw_profit)
Definition: economy.cpp:1494
bool nation_has_closed_factories(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:408
float ideal_pound_conversion_rate(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:98
float get_artisan_distribution_slow(sys::state &state, dcon::nation_id n, dcon::commodity_id c)
Definition: economy.cpp:546
float factory_output_multiplier(sys::state &state, dcon::factory_fat_id fac, dcon::nation_id n, dcon::province_id p)
Definition: economy.cpp:1470
float nation_pop_consumption(sys::state &state, dcon::nation_id n, dcon::commodity_id c)
Definition: economy.cpp:4514
float factory_min_e_input_available(sys::state &state, dcon::nation_id n, dcon::factory_type_fat_id fac_type)
Definition: economy.cpp:1390
float factory_type_build_cost(sys::state &state, dcon::nation_id n, dcon::factory_type_id factory_type)
Definition: economy.cpp:4396
int32_t previous_gdp_record_index(sys::state &state)
Definition: economy.cpp:93
void register_intermediate_demand(sys::state &state, dcon::nation_id n, dcon::commodity_id commodity_type, float amount, economy_reason reason)
Definition: economy.cpp:25
constexpr float subsistence_score_everyday
Definition: economy.hpp:94
constexpr float day_1_derivative_non_factory
Definition: economy.cpp:2036
float estimate_gold_income(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:4558
void update_single_factory_consumption(sys::state &state, dcon::factory_id f, dcon::nation_id n, dcon::province_id p, dcon::state_instance_id s, float mobilization_impact, float expected_min_wage, bool occupied)
Definition: economy.cpp:1537
void update_national_artisan_production(sys::state &state, dcon::nation_id n)
Definition: economy.cpp:1946
constexpr float day_1_build_time_modifier_non_factory
Definition: economy.cpp:2034
void fire_fixed_event(sys::state &state, std::vector< nations::fixed_event > const &v, int32_t primary_slot, slot_type pt, dcon::nation_id this_slot, int32_t from_slot, slot_type ft)
Definition: events.cpp:709
constexpr uint32_t pop_expand_factory
Definition: culture.hpp:15
constexpr uint32_t destroy_factory
Definition: culture.hpp:11
constexpr uint32_t pop_build_factory
Definition: culture.hpp:14
float sqrt(float x) noexcept
Definition: math_fns.hpp:70
void army_arrives_in_province(sys::state &state, dcon::army_id a, dcon::province_id p, crossing_type crossing, dcon::land_battle_id from)
Definition: military.cpp:3992
float mobilization_impact(sys::state const &state, dcon::nation_id n)
Definition: military.cpp:1160
void move_land_to_merge(sys::state &state, dcon::nation_id by, dcon::army_id a, dcon::province_id start, dcon::province_id dest)
Definition: military.cpp:7377
dcon::regiment_id create_new_regiment(sys::state &state, dcon::nation_id n, dcon::unit_type_id t)
Definition: military.cpp:2047
constexpr uint8_t level_in_sphere
Definition: nations.hpp:169
constexpr uint8_t level_mask
Definition: nations.hpp:163
std::string int_to_tag(uint32_t v)
Definition: nations.hpp:10
float get_foreign_investment(sys::state &state, dcon::nation_id n)
Definition: nations.cpp:314
float tariff_efficiency(sys::state &state, dcon::nation_id n)
Definition: nations.cpp:1055
dcon::nation_id owner_of_pop(sys::state const &state, dcon::pop_id pop_ids)
Definition: nations.cpp:69
float tax_efficiency(sys::state &state, dcon::nation_id n)
Definition: nations.cpp:1061
void post(sys::state &state, message &&m)
float get_employment(sys::state const &state, dcon::pop_id p)
float get_luxury_needs(sys::state const &state, dcon::pop_id p)
void set_raw_employment(sys::state &state, dcon::pop_id p, float v)
void set_luxury_needs(sys::state &state, dcon::pop_id p, float v)
void set_everyday_needs(sys::state &state, dcon::pop_id p, float v)
float get_life_needs(sys::state const &state, dcon::pop_id p)
void set_life_needs(sys::state &state, dcon::pop_id p, float v)
float get_everyday_needs(sys::state const &state, dcon::pop_id p)
void for_each_province_in_state_instance(sys::state &state, dcon::state_instance_id s, F const &func)
bool state_is_coastal(sys::state &state, dcon::state_instance_id s)
Definition: province.cpp:1476
void for_each_land_province(sys::state &state, F const &func)
constexpr uint16_t to_map_id(dcon::province_id id)
Definition: province.hpp:10
bool generic_can_build_railroads(sys::state &state, dcon::province_id id, dcon::nation_id n)
Definition: province.cpp:317
Definition: prng.cpp:6
uint64_t get_random(sys::state const &state, uint32_t value_in)
Definition: prng.cpp:8
MOD_PROV_LIST constexpr uint32_t count
Definition: modifiers.hpp:207
void add_modifier_to_nation(sys::state &state, dcon::nation_id target_nation, dcon::modifier_id mod_id, sys::date expiration)
Definition: modifiers.cpp:63
void add_line(sys::state &state, layout_base &dest, dcon::text_key txt, int32_t indent)
Definition: text.cpp:1899
std::string produce_simple_string(sys::state const &state, dcon::text_key id)
Definition: text.cpp:617
dcon::text_key get_name(sys::state &state, dcon::nation_id id)
Definition: text.cpp:880
int32_t to_generic(dcon::province_id v)
Definition: triggers.hpp:12
bool evaluate(sys::state &state, dcon::trigger_key key, int32_t primary, int32_t this_slot, int32_t from_slot)
Definition: triggers.cpp:5865
T select(bool v, T a, T b)
float to_float(int32_t a)
uint uint32_t
uchar uint8_t
static constexpr uint32_t set_size