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