Project Alice
Loading...
Searching...
No Matches
demographics.cpp
Go to the documentation of this file.
1#include "demographics.hpp"
2#include "dcon_generated.hpp"
3#include "system_state.hpp"
4#include "prng.hpp"
6#include "nations.hpp"
8#include "triggers.hpp"
10#include "container_types.hpp"
11
12// #define CHECK_LLVM_RESULTS
13
15
16dcon::pop_demographics_key to_key(sys::state const& state, dcon::ideology_id v) {
17 return dcon::pop_demographics_key(dcon::pop_demographics_key::value_base_t(v.index() + count_special_keys));
18}
19dcon::pop_demographics_key to_key(sys::state const& state, dcon::issue_option_id v) {
20 return dcon::pop_demographics_key(
21 dcon::pop_demographics_key::value_base_t(state.world.ideology_size() + v.index() + count_special_keys));
22}
23uint32_t size(sys::state const& state) {
24 return state.world.ideology_size() + state.world.issue_option_size() + count_special_keys;
25}
26
28 state.world.for_each_pop([&](dcon::pop_id p) {
29 state.world.pop_set_is_primary_or_accepted_culture(p, false);
30 auto n = nations::owner_of_pop(state, p);
31 if(state.world.nation_get_primary_culture(n) == state.world.pop_get_culture(p)) {
32 state.world.pop_set_is_primary_or_accepted_culture(p, true);
33 return;
34 }
35 if(state.world.nation_get_accepted_cultures(n, state.world.pop_get_culture(p)) == true) {
36 state.world.pop_set_is_primary_or_accepted_culture(p, true);
37 return;
38 }
39 });
40}
41
42float get_demo(sys::state const& state, dcon::pop_id p, dcon::pop_demographics_key k) {
43 auto ival = state.world.pop_get_udemographics(p, k);
44 return from_pu8(ival);
45}
46void set_demo(sys::state& state, dcon::pop_id p, dcon::pop_demographics_key k, float v) {
47 state.world.pop_set_udemographics(p, k, to_pu8(v));
48}
49template<typename T>
50void set_demo(sys::state& state, T p, dcon::pop_demographics_key k, ve::fp_vector v) {
51 state.world.pop_set_udemographics(p, k, to_pu8(v));
52}
53float get_militancy(sys::state const& state, dcon::pop_id p) {
54 auto ival = state.world.pop_get_umilitancy(p);
55 return from_pmc(ival);
56}
57void set_militancy(sys::state& state, dcon::pop_id p, float v) {
58 state.world.pop_set_umilitancy(p, to_pmc(v));
59}
60template<typename T>
61void set_militancy(sys::state& state, T p, ve::fp_vector v) {
62 state.world.pop_set_umilitancy(p, to_pmc(v));
63}
64float get_consciousness(sys::state const& state, dcon::pop_id p) {
65 auto ival = state.world.pop_get_uconsciousness(p);
66 return from_pmc(ival);
67}
68void set_consciousness(sys::state& state, dcon::pop_id p, float v) {
69 state.world.pop_set_uconsciousness(p, to_pmc(v));
70}
71template<typename T>
72void set_consciousness(sys::state& state, T p, ve::fp_vector v) {
73 state.world.pop_set_uconsciousness(p, to_pmc(v));
74}
75float get_literacy(sys::state const& state, dcon::pop_id p) {
76 auto ival = state.world.pop_get_uliteracy(p);
77 return from_pu16(ival);
78}
79template<typename T>
80void set_literacy(sys::state& state, T p, ve::fp_vector v) {
81 state.world.pop_set_uliteracy(p, to_pu16(v));
82}
83void set_literacy(sys::state& state, dcon::pop_id p, float v) {
84 state.world.pop_set_uliteracy(p, to_pu16(v));
85}
86float get_employment(sys::state const& state, dcon::pop_id p) {
87 auto ival = state.world.pop_get_uemployment(p);
88 return from_pu8(ival) * state.world.pop_get_size(p);
89}
90float get_raw_employment(sys::state const& state, dcon::pop_id p) {
91 auto ival = state.world.pop_get_uemployment(p);
92 return from_pu8(ival);
93}
94void set_employment(sys::state& state, dcon::pop_id p, float v) {
95 state.world.pop_set_uemployment(p, to_pu8(v / state.world.pop_get_size(p)));
96}
97void set_raw_employment(sys::state& state, dcon::pop_id p, float v) {
98 state.world.pop_set_uemployment(p, to_pu8(v));
99}
100float get_life_needs(sys::state const& state, dcon::pop_id p) {
101 auto ival = state.world.pop_get_ulife_needs_satisfaction(p);
102 return from_pu8(ival);
103}
104template<typename P, typename V>
105void set_life_needs(sys::state& state, P p, V v) {
106 state.world.pop_set_ulife_needs_satisfaction(p, to_pu8(v));
107}
108template void set_life_needs<dcon::pop_id, float>(sys::state&, dcon::pop_id, float);
109template void set_life_needs<dcon::pop_fat_id, float>(sys::state&, dcon::pop_fat_id, float);
110template void set_life_needs<ve::contiguous_tags<dcon::pop_id>, ve::fp_vector>(sys::state&, ve::contiguous_tags<dcon::pop_id>, ve::fp_vector);
111template void set_life_needs<ve::partial_contiguous_tags<dcon::pop_id>, ve::fp_vector>(sys::state&, ve::partial_contiguous_tags<dcon::pop_id>, ve::fp_vector);
112
113float get_everyday_needs(sys::state const& state, dcon::pop_id p) {
114 auto ival = state.world.pop_get_ueveryday_needs_satisfaction(p);
115 return from_pu8(ival);
116}
117template<typename P, typename V>
118void set_everyday_needs(sys::state& state, P p, V v) {
119 state.world.pop_set_ueveryday_needs_satisfaction(p, to_pu8(v));
120}
121template void set_everyday_needs<dcon::pop_id, float>(sys::state&, dcon::pop_id, float);
122template void set_everyday_needs<dcon::pop_fat_id, float>(sys::state&, dcon::pop_fat_id, float);
123template void set_everyday_needs<ve::contiguous_tags<dcon::pop_id>, ve::fp_vector>(sys::state&, ve::contiguous_tags<dcon::pop_id>, ve::fp_vector);
124template void set_everyday_needs<ve::partial_contiguous_tags<dcon::pop_id>, ve::fp_vector>(sys::state&, ve::partial_contiguous_tags<dcon::pop_id>, ve::fp_vector);
125
126float get_luxury_needs(sys::state const& state, dcon::pop_id p) {
127 auto ival = state.world.pop_get_uluxury_needs_satisfaction(p);
128 return from_pu8(ival);
129}
130template<typename P, typename V>
131void set_luxury_needs(sys::state& state, P p, V v) {
132 state.world.pop_set_uluxury_needs_satisfaction(p, to_pu8(v));
133}
134template void set_luxury_needs<dcon::pop_id, float>(sys::state&, dcon::pop_id, float);
135template void set_luxury_needs<dcon::pop_fat_id, float>(sys::state&, dcon::pop_fat_id, float);
136template void set_luxury_needs<ve::contiguous_tags<dcon::pop_id>, ve::fp_vector>(sys::state&, ve::contiguous_tags<dcon::pop_id>, ve::fp_vector);
137template void set_luxury_needs<ve::partial_contiguous_tags<dcon::pop_id>, ve::fp_vector>(sys::state&, ve::partial_contiguous_tags<dcon::pop_id>, ve::fp_vector);
138
139float get_social_reform_desire(sys::state const& state, dcon::pop_id p) {
140 auto ival = state.world.pop_get_usocial_reform_desire(p);
141 return from_pu8(ival);
142}
143void set_social_reform_desire(sys::state& state, dcon::pop_id p, float v) {
144 state.world.pop_set_usocial_reform_desire(p, to_pu8(v));
145}
146float get_political_reform_desire(sys::state const& state, dcon::pop_id p) {
147 auto ival = state.world.pop_get_upolitical_reform_desire(p);
148 return from_pu8(ival);
149}
150void set_political_reform_desire(sys::state& state, dcon::pop_id p, float v) {
151 state.world.pop_set_upolitical_reform_desire(p, to_pu8(v));
152}
153
154} // namespace pop_demographics
155namespace demographics {
156
157inline constexpr float small_pop_size = 100.0f;
158
159dcon::demographics_key to_key(sys::state const& state, dcon::pop_type_id v) {
160 return dcon::demographics_key(dcon::pop_demographics_key::value_base_t(
161 count_special_keys + v.index()));
162}
163dcon::demographics_key to_employment_key(sys::state const& state, dcon::pop_type_id v) {
164 return dcon::demographics_key(dcon::pop_demographics_key::value_base_t(
165 count_special_keys + state.world.pop_type_size() + v.index()));
166}
167dcon::demographics_key to_key(sys::state const& state, dcon::culture_id v) {
168 return dcon::demographics_key(
169 dcon::pop_demographics_key::value_base_t(count_special_keys + state.world.pop_type_size() * 2 + v.index()));
170}
171dcon::demographics_key to_key(sys::state const& state, dcon::ideology_id v) {
172 return dcon::demographics_key(dcon::pop_demographics_key::value_base_t(count_special_keys + state.world.pop_type_size() * 2 + state.world.culture_size() + v.index()));
173}
174dcon::demographics_key to_key(sys::state const& state, dcon::issue_option_id v) {
175 return dcon::demographics_key(dcon::pop_demographics_key::value_base_t(count_special_keys + state.world.pop_type_size() * 2 + state.world.culture_size() + state.world.ideology_size() + v.index()));
176}
177dcon::demographics_key to_key(sys::state const& state, dcon::religion_id v) {
178 return dcon::demographics_key(dcon::pop_demographics_key::value_base_t(count_special_keys + state.world.pop_type_size() * 2 + state.world.culture_size() + state.world.ideology_size() + state.world.issue_option_size() + v.index()));
179}
180
181uint32_t size(sys::state const& state) {
182 return count_special_keys + state.world.ideology_size() + state.world.issue_option_size() + uint32_t(2) * state.world.pop_type_size() + state.world.culture_size() + state.world.religion_size();
183}
185 return count_special_keys + uint32_t(2) * state.world.pop_type_size();
186}
187
188template<typename F>
189void sum_over_demographics(sys::state& state, dcon::demographics_key key, F const& source) {
190 // clear province
191 province::ve_for_each_land_province(state, [&](auto pi) { state.world.province_set_demographics(pi, key, ve::fp_vector()); });
192 // sum in province
193 state.world.for_each_pop([&](dcon::pop_id p) {
194 auto location = state.world.pop_get_province_from_pop_location(p);
195 state.world.province_get_demographics(location, key) += source(state, p);
196 });
197 // clear state
198 state.world.execute_serial_over_state_instance(
199 [&](auto si) { state.world.state_instance_set_demographics(si, key, ve::fp_vector()); });
200 // sum in state
201 province::for_each_land_province(state, [&](dcon::province_id p) {
202 auto location = state.world.province_get_state_membership(p);
203 state.world.state_instance_get_demographics(location, key) += state.world.province_get_demographics(p, key);
204 });
205 // clear nation
206 state.world.execute_serial_over_nation([&](auto ni) { state.world.nation_set_demographics(ni, key, ve::fp_vector()); });
207 // sum in nation
208 state.world.for_each_state_instance([&](dcon::state_instance_id s) {
209 auto location = state.world.state_instance_get_nation_from_state_ownership(s);
210 state.world.nation_get_demographics(location, key) += state.world.state_instance_get_demographics(s, key);
211 });
212}
213
214template<typename F>
215void alt_sum_over_demographics(sys::state& state, dcon::demographics_key key, F const& source) {
216 // clear province
217 province::ve_for_each_land_province(state, [&](auto pi) { state.world.province_set_demographics_alt(pi, key, ve::fp_vector()); });
218 // sum in province
219 state.world.for_each_pop([&](dcon::pop_id p) {
220 auto location = state.world.pop_get_province_from_pop_location(p);
221 state.world.province_get_demographics_alt(location, key) += source(state, p);
222 });
223 // clear state
224 state.world.execute_serial_over_state_instance(
225 [&](auto si) { state.world.state_instance_set_demographics_alt(si, key, ve::fp_vector()); });
226 // sum in state
227 province::for_each_land_province(state, [&](dcon::province_id p) {
228 auto location = state.world.province_get_state_membership(p);
229 state.world.state_instance_get_demographics_alt(location, key) += state.world.province_get_demographics_alt(p, key);
230 });
231 // clear nation
232 state.world.execute_serial_over_nation([&](auto ni) { state.world.nation_set_demographics_alt(ni, key, ve::fp_vector()); });
233 // sum in nation
234 state.world.for_each_state_instance([&](dcon::state_instance_id s) {
235 auto location = state.world.state_instance_get_nation_from_state_ownership(s);
236 state.world.nation_get_demographics_alt(location, key) += state.world.state_instance_get_demographics_alt(s, key);
237 });
238}
239
240void alt_copy_demographics(sys::state& state, dcon::demographics_key key) {
241 province::ve_for_each_land_province(state, [&](auto pi) {
242 state.world.province_set_demographics_alt(pi, key, state.world.province_get_demographics(pi, key));
243 });
244 state.world.execute_serial_over_state_instance([&](auto si) {
245 state.world.state_instance_set_demographics_alt(si, key, state.world.state_instance_get_demographics(si, key));
246 });
247 state.world.execute_serial_over_nation([&](auto ni) {
248 state.world.nation_set_demographics_alt(ni, key, state.world.nation_get_demographics(ni, key));
249 });
250}
251
252inline constexpr uint32_t extra_demo_grouping = 8;
253
254template<typename F>
255void sum_over_single_nation_demographics(sys::state& state, dcon::demographics_key key, dcon::nation_id n, F const& source) {
256 // clear province
257 for(auto pc : state.world.nation_get_province_control_as_nation(n)) {
258 auto location = pc.get_province();
259 state.world.province_set_demographics(location, key, 0.f);
260 for(auto pl : pc.get_province().get_pop_location_as_province()) {
261 state.world.province_get_demographics(location, key) += source(state, pl.get_pop());
262 }
263 }
264 for(auto sc : state.world.nation_get_state_ownership_as_nation(n)) {
265 auto location = sc.get_state();
266 state.world.state_instance_set_demographics(location, key, 0.f);
267 for(auto sm : sc.get_state().get_definition().get_abstract_state_membership()) {
268 state.world.state_instance_get_demographics(location, key) += state.world.province_get_demographics(sm.get_province(), key);
269 }
270
271 }
272 state.world.nation_set_demographics(n, key, 0.f);
273 for(auto sc : state.world.nation_get_state_ownership_as_nation(n)) {
274 state.world.nation_get_demographics(n, key) += state.world.state_instance_get_demographics(sc.get_state(), key);
275 }
276}
277
278void regenerate_jingoism_support(sys::state& state, dcon::nation_id n) {
279 dcon::demographics_key key = to_key(state, state.culture_definitions.jingoism);
280 auto pdemo_key = pop_demographics::to_key(state, state.culture_definitions.jingoism);
281 for(const auto pc : state.world.nation_get_province_control_as_nation(n)) {
282 sum_over_single_nation_demographics(state, key, n, [pdemo_key](sys::state const& state, dcon::pop_id p) {
283 return pop_demographics::get_demo(state, p, pdemo_key) * state.world.pop_get_size(p);
284 });
285 }
286}
287
288template<bool full>
290 auto const sz = size(state);
291 auto const csz = common_size(state);
292 auto const extra_size = sz - csz;
293 auto const extra_group_size = (extra_size + extra_demo_grouping - 1) / extra_demo_grouping;
294
295 concurrency::parallel_for(uint32_t(0), full ? sz : csz + extra_group_size, [&](uint32_t base_index) {
296 auto index = base_index;
297 if constexpr(!full) {
298 if(index >= csz) {
299 index += extra_group_size * (state.current_date.value % extra_demo_grouping);
300 if(index >= sz)
301 return;
302 }
303 }
304 dcon::demographics_key key{dcon::demographics_key::value_base_t(index)};
305 if(index < count_special_keys) {
306 switch(index) {
307 case 0: // constexpr inline dcon::demographics_key total(0);
308 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) { return state.world.pop_get_size(p); });
309 break;
310 case 1: // constexpr inline dcon::demographics_key employable(1);
311 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
312 return state.world.pop_type_get_has_unemployment(state.world.pop_get_poptype(p)) ? state.world.pop_get_size(p) : 0.0f;
313 });
314 break;
315 case 2: // constexpr inline dcon::demographics_key employed(2);
316 sum_over_demographics(state, key,
317 [](sys::state const& state, dcon::pop_id p) { return pop_demographics::get_employment(state, p); });
318 break;
319 case 3: // constexpr inline dcon::demographics_key consciousness(3);
320 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
321 return pop_demographics::get_consciousness(state, p) * state.world.pop_get_size(p);
322 });
323 break;
324 case 4: // constexpr inline dcon::demographics_key militancy(4);
325 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
326 return pop_demographics::get_militancy(state, p) * state.world.pop_get_size(p);
327 });
328 break;
329 case 5: // constexpr inline dcon::demographics_key literacy(5);
330 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
331 return pop_demographics::get_literacy(state, p) * state.world.pop_get_size(p);
332 });
333 break;
334 case 6: // constexpr inline dcon::demographics_key political_reform_desire(6);
335 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
336 if(state.world.province_get_is_colonial(state.world.pop_get_province_from_pop_location(p)) == false) {
337 auto movement = state.world.pop_get_movement_from_pop_movement_membership(p);
338 if(movement) {
339 auto opt = state.world.movement_get_associated_issue_option(movement);
340 auto optpar = state.world.issue_option_get_parent_issue(opt);
341 if(opt && state.world.issue_get_issue_type(optpar) == uint8_t(culture::issue_type::political))
342 return state.world.pop_get_size(p);
343 }
344 return 0.0f;
345 } else
346 return 0.0f;
347 });
348 break;
349 case 7: // constexpr inline dcon::demographics_key social_reform_desire(7);
350 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
351 if(state.world.province_get_is_colonial(state.world.pop_get_province_from_pop_location(p)) == false) {
352 auto movement = state.world.pop_get_movement_from_pop_movement_membership(p);
353 if(movement) {
354 auto opt = state.world.movement_get_associated_issue_option(movement);
355 auto optpar = state.world.issue_option_get_parent_issue(opt);
356 if(opt && state.world.issue_get_issue_type(optpar) == uint8_t(culture::issue_type::social))
357 return state.world.pop_get_size(p);
358 }
359 return 0.0f;
360 } else
361 return 0.0f;
362 });
363 break;
364 case 8: // constexpr inline dcon::demographics_key poor_militancy(8);
365 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
366 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
367 ? pop_demographics::get_militancy(state, p) * state.world.pop_get_size(p)
368 : 0.0f;
369 });
370 break;
371 case 9: // constexpr inline dcon::demographics_key middle_militancy(9);
372 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
373 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
374 ? pop_demographics::get_militancy(state, p) * state.world.pop_get_size(p)
375 : 0.0f;
376 });
377 break;
378 case 10: // constexpr inline dcon::demographics_key rich_militancy(10);
379 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
380 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
381 ? pop_demographics::get_militancy(state, p) * state.world.pop_get_size(p)
382 : 0.0f;
383 });
384 break;
385 case 11: // constexpr inline dcon::demographics_key poor_life_needs(11);
386 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
387 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
388 ? pop_demographics::get_life_needs(state, p) * state.world.pop_get_size(p)
389 : 0.0f;
390 });
391 break;
392 case 12: // constexpr inline dcon::demographics_key middle_life_needs(12);
393 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
394 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
395 ? pop_demographics::get_life_needs(state, p) * state.world.pop_get_size(p)
396 : 0.0f;
397 });
398 break;
399 case 13: // constexpr inline dcon::demographics_key rich_life_needs(13);
400 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
401 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
402 ? pop_demographics::get_life_needs(state, p) * state.world.pop_get_size(p)
403 : 0.0f;
404 });
405 break;
406 case 14: // constexpr inline dcon::demographics_key poor_everyday_needs(14);
407 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
408 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
409 ? pop_demographics::get_everyday_needs(state, p) * state.world.pop_get_size(p)
410 : 0.0f;
411 });
412 break;
413 case 15: // constexpr inline dcon::demographics_key middle_everyday_needs(15);
414 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
415 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
416 ? pop_demographics::get_everyday_needs(state, p) * state.world.pop_get_size(p)
417 : 0.0f;
418 });
419 break;
420 case 16: // constexpr inline dcon::demographics_key rich_everyday_needs(16);
421 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
422 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
423 ? pop_demographics::get_everyday_needs(state, p) * state.world.pop_get_size(p)
424 : 0.0f;
425 });
426 break;
427 case 17: // constexpr inline dcon::demographics_key poor_luxury_needs(17);
428 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
429 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
430 ? pop_demographics::get_luxury_needs(state, p) * state.world.pop_get_size(p)
431 : 0.0f;
432 });
433 break;
434 case 18: // constexpr inline dcon::demographics_key middle_luxury_needs(18);
435 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
436 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
437 ? pop_demographics::get_luxury_needs(state, p) * state.world.pop_get_size(p)
438 : 0.0f;
439 });
440 break;
441 case 19: // constexpr inline dcon::demographics_key rich_luxury_needs(19);
442 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
443 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
444 ? pop_demographics::get_luxury_needs(state, p) * state.world.pop_get_size(p)
445 : 0.0f;
446 });
447 break;
448 case 20: // constexpr inline dcon::demographics_key poor_total(20);
449 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
450 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
451 ? state.world.pop_get_size(p)
452 : 0.0f;
453 });
454 break;
455 case 21: // constexpr inline dcon::demographics_key middle_total(21);
456 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
457 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
458 ? state.world.pop_get_size(p)
459 : 0.0f;
460 });
461 break;
462 case 22: // constexpr inline dcon::demographics_key rich_total(22);
463 sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
464 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
465 ? state.world.pop_get_size(p)
466 : 0.0f;
467 });
468 break;
469 }
470 // common - pop type - employment - culture - ideology - issue option - religion
471 } else if(key.index() < to_employment_key(state, dcon::pop_type_id(0)).index()) { // pop type
472 dcon::pop_type_id pkey{ dcon::pop_type_id::value_base_t(index - (count_special_keys)) };
473 sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
474 return state.world.pop_get_poptype(p) == pkey ? state.world.pop_get_size(p) : 0.0f;
475 });
476 } else if(key.index() < to_key(state, dcon::culture_id(0)).index()) { // employment
477 dcon::pop_type_id pkey{ dcon::pop_type_id::value_base_t(index - (count_special_keys + state.world.pop_type_size())) };
478 if(state.world.pop_type_get_has_unemployment(pkey)) {
479 sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
480 return state.world.pop_get_poptype(p) == pkey ? pop_demographics::get_employment(state, p) : 0.0f;
481 });
482 } else {
483 sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
484 return state.world.pop_get_poptype(p) == pkey ? state.world.pop_get_size(p) : 0.0f;
485 });
486 }
487 } else if(key.index() < to_key(state, dcon::ideology_id(0)).index()) { // culture
488 dcon::culture_id pkey{
489 dcon::culture_id::value_base_t(index - (count_special_keys + state.world.pop_type_size() * 2)) };
490 sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
491 return state.world.pop_get_culture(p) == pkey ? state.world.pop_get_size(p) : 0.0f;
492 });
493 } else if(key.index() < to_key(state, dcon::issue_option_id(0)).index()) { // ideology
494 dcon::ideology_id pkey{dcon::ideology_id::value_base_t(index - (count_special_keys + state.world.pop_type_size() * 2 + state.world.culture_size()))};
495 auto pdemo_key = pop_demographics::to_key(state, pkey);
496 sum_over_demographics(state, key, [pdemo_key](sys::state const& state, dcon::pop_id p) {
497 return pop_demographics::get_demo(state, p, pdemo_key) * state.world.pop_get_size(p);
498 });
499 } else if(key.index() < to_key(state, dcon::religion_id(0)).index()) { // issue option
500 dcon::issue_option_id pkey{dcon::issue_option_id::value_base_t(index - (count_special_keys + state.world.pop_type_size() * 2 + state.world.culture_size() + state.world.ideology_size()))};
501 auto pdemo_key = pop_demographics::to_key(state, pkey);
502 sum_over_demographics(state, key, [pdemo_key](sys::state const& state, dcon::pop_id p) {
503 return pop_demographics::get_demo(state, p, pdemo_key) * state.world.pop_get_size(p);
504 });
505 } else { // religion
506 dcon::religion_id pkey{dcon::religion_id::value_base_t(
507 index - (count_special_keys + state.world.pop_type_size() * 2 + state.world.culture_size() + state.world.ideology_size() + state.world.issue_option_size()))};
508 sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
509 return state.world.pop_get_religion(p) == pkey ? state.world.pop_get_size(p) : 0.0f;
510 });
511 }
512 });
513
514 //
515 // calculate values derived from demographics
516 //
517 concurrency::parallel_for(uint32_t(0), uint32_t(17), [&](uint32_t index) {
518 switch(index) {
519 case 0: {
520 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
521
522 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
523 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
524 state.world.for_each_culture([&](dcon::culture_id c) {
525 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, k = to_key(state, c)](auto p) {
526 auto v = state.world.province_get_demographics(p, k);
527 auto old_max = max_buffer.get(p);
528 auto mask = v > old_max;
529 state.world.province_set_dominant_culture(p,
530 ve::select(mask, ve::tagged_vector<dcon::culture_id>(c), state.world.province_get_dominant_culture(p)));
531 max_buffer.set(p, ve::select(mask, v, old_max));
532 });
533 });
534 break;
535 }
536 case 1: {
537 static ve::vectorizable_buffer<float, dcon::state_instance_id> max_buffer(uint32_t(1));
538 static uint32_t old_count = 1;
539
540 auto new_count = state.world.state_instance_size();
541 if(new_count > old_count) {
542 max_buffer = state.world.state_instance_make_vectorizable_float_buffer();
543 old_count = new_count;
544 }
545 state.world.execute_serial_over_state_instance([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
546 state.world.for_each_culture([&](dcon::culture_id c) {
547 state.world.execute_serial_over_state_instance([&, k = to_key(state, c)](auto p) {
548 auto v = state.world.state_instance_get_demographics(p, k);
549 auto old_max = max_buffer.get(p);
550 auto mask = v > old_max;
551 state.world.state_instance_set_dominant_culture(p,
552 ve::select(mask, ve::tagged_vector<dcon::culture_id>(c), state.world.state_instance_get_dominant_culture(p)));
553 max_buffer.set(p, ve::select(mask, v, old_max));
554 });
555 });
556 break;
557 }
558 case 2: {
559 static ve::vectorizable_buffer<float, dcon::nation_id> max_buffer(uint32_t(1));
560 static uint32_t old_count = 1;
561
562 auto new_count = state.world.nation_size();
563 if(new_count > old_count) {
564 max_buffer = state.world.nation_make_vectorizable_float_buffer();
565 old_count = new_count;
566 }
567 state.world.execute_serial_over_nation([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
568 state.world.for_each_culture([&](dcon::culture_id c) {
569 state.world.execute_serial_over_nation([&, k = to_key(state, c)](auto p) {
570 auto v = state.world.nation_get_demographics(p, k);
571 auto old_max = max_buffer.get(p);
572 auto mask = v > old_max;
573 state.world.nation_set_dominant_culture(p,
574 ve::select(mask, ve::tagged_vector<dcon::culture_id>(c), state.world.nation_get_dominant_culture(p)));
575 max_buffer.set(p, ve::select(mask, v, old_max));
576 });
577 });
578 break;
579 }
580 case 3: {
581 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
582
583 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
584 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
585 state.world.for_each_religion([&](dcon::religion_id c) {
586 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, k = to_key(state, c)](auto p) {
587 auto v = state.world.province_get_demographics(p, k);
588 auto old_max = max_buffer.get(p);
589 auto mask = v > old_max;
590 state.world.province_set_dominant_religion(p,
591 ve::select(mask, ve::tagged_vector<dcon::religion_id>(c), state.world.province_get_dominant_religion(p)));
592 max_buffer.set(p, ve::select(mask, v, old_max));
593 });
594 });
595 break;
596 }
597 case 4: {
598 static ve::vectorizable_buffer<float, dcon::state_instance_id> max_buffer(uint32_t(1));
599 static uint32_t old_count = 1;
600
601 auto new_count = state.world.state_instance_size();
602 if(new_count > old_count) {
603 max_buffer = state.world.state_instance_make_vectorizable_float_buffer();
604 old_count = new_count;
605 }
606 state.world.execute_serial_over_state_instance([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
607 state.world.for_each_religion([&](dcon::religion_id c) {
608 state.world.execute_serial_over_state_instance([&, k = to_key(state, c)](auto p) {
609 auto v = state.world.state_instance_get_demographics(p, k);
610 auto old_max = max_buffer.get(p);
611 auto mask = v > old_max;
612 state.world.state_instance_set_dominant_religion(p,
613 ve::select(mask, ve::tagged_vector<dcon::religion_id>(c), state.world.state_instance_get_dominant_religion(p)));
614 max_buffer.set(p, ve::select(mask, v, old_max));
615 });
616 });
617 break;
618 }
619 case 5: {
620 static ve::vectorizable_buffer<float, dcon::nation_id> max_buffer(uint32_t(1));
621 static uint32_t old_count = 1;
622
623 auto new_count = state.world.nation_size();
624 if(new_count > old_count) {
625 max_buffer = state.world.nation_make_vectorizable_float_buffer();
626 old_count = new_count;
627 }
628 state.world.execute_serial_over_nation([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
629 state.world.for_each_religion([&](dcon::religion_id c) {
630 state.world.execute_serial_over_nation([&, k = to_key(state, c)](auto p) {
631 auto v = state.world.nation_get_demographics(p, k);
632 auto old_max = max_buffer.get(p);
633 auto mask = v > old_max;
634 state.world.nation_set_dominant_religion(p,
635 ve::select(mask, ve::tagged_vector<dcon::religion_id>(c), state.world.nation_get_dominant_religion(p)));
636 max_buffer.set(p, ve::select(mask, v, old_max));
637 });
638 });
639 break;
640 }
641 case 6: {
642 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
643
644 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
645 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
646 state.world.for_each_ideology([&](dcon::ideology_id c) {
647 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, k = to_key(state, c)](auto p) {
648 auto v = state.world.province_get_demographics(p, k);
649 auto old_max = max_buffer.get(p);
650 auto mask = v > old_max;
651 state.world.province_set_dominant_ideology(p,
652 ve::select(mask, ve::tagged_vector<dcon::ideology_id>(c), state.world.province_get_dominant_ideology(p)));
653 max_buffer.set(p, ve::select(mask, v, old_max));
654 });
655 });
656 break;
657 }
658 case 7: {
659 static ve::vectorizable_buffer<float, dcon::state_instance_id> max_buffer(uint32_t(1));
660 static uint32_t old_count = 1;
661
662 auto new_count = state.world.state_instance_size();
663 if(new_count > old_count) {
664 max_buffer = state.world.state_instance_make_vectorizable_float_buffer();
665 old_count = new_count;
666 }
667 state.world.execute_serial_over_state_instance([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
668 state.world.for_each_ideology([&](dcon::ideology_id c) {
669 state.world.execute_serial_over_state_instance([&, k = to_key(state, c)](auto p) {
670 auto v = state.world.state_instance_get_demographics(p, k);
671 auto old_max = max_buffer.get(p);
672 auto mask = v > old_max;
673 state.world.state_instance_set_dominant_ideology(p,
674 ve::select(mask, ve::tagged_vector<dcon::ideology_id>(c), state.world.state_instance_get_dominant_ideology(p)));
675 max_buffer.set(p, ve::select(mask, v, old_max));
676 });
677 });
678 break;
679 }
680 case 8: {
681 static ve::vectorizable_buffer<float, dcon::nation_id> max_buffer(uint32_t(1));
682 static uint32_t old_count = 1;
683
684 auto new_count = state.world.nation_size();
685 if(new_count > old_count) {
686 max_buffer = state.world.nation_make_vectorizable_float_buffer();
687 old_count = new_count;
688 }
689 state.world.execute_serial_over_nation([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
690 state.world.for_each_ideology([&](dcon::ideology_id c) {
691 state.world.execute_serial_over_nation([&, k = to_key(state, c)](auto p) {
692 auto v = state.world.nation_get_demographics(p, k);
693 auto old_max = max_buffer.get(p);
694 auto mask = v > old_max;
695 state.world.nation_set_dominant_ideology(p,
696 ve::select(mask, ve::tagged_vector<dcon::ideology_id>(c), state.world.nation_get_dominant_ideology(p)));
697 max_buffer.set(p, ve::select(mask, v, old_max));
698 });
699 });
700 break;
701 }
702 case 9: {
703 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
704
705 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
706 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
707 state.world.for_each_issue_option([&](dcon::issue_option_id c) {
708 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, k = to_key(state, c)](auto p) {
709 auto v = state.world.province_get_demographics(p, k);
710 auto old_max = max_buffer.get(p);
711 auto mask = v > old_max;
712 state.world.province_set_dominant_issue_option(p,
713 ve::select(mask, ve::tagged_vector<dcon::issue_option_id>(c), state.world.province_get_dominant_issue_option(p)));
714 max_buffer.set(p, ve::select(mask, v, old_max));
715 });
716 });
717 break;
718 }
719 case 10: {
720 static ve::vectorizable_buffer<float, dcon::state_instance_id> max_buffer(uint32_t(1));
721 static uint32_t old_count = 1;
722
723 auto new_count = state.world.state_instance_size();
724 if(new_count > old_count) {
725 max_buffer = state.world.state_instance_make_vectorizable_float_buffer();
726 old_count = new_count;
727 }
728 state.world.execute_serial_over_state_instance([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
729 state.world.for_each_issue_option([&](dcon::issue_option_id c) {
730 state.world.execute_serial_over_state_instance([&, k = to_key(state, c)](auto p) {
731 auto v = state.world.state_instance_get_demographics(p, k);
732 auto old_max = max_buffer.get(p);
733 auto mask = v > old_max;
734 state.world.state_instance_set_dominant_issue_option(p, ve::select(mask, ve::tagged_vector<dcon::issue_option_id>(c), state.world.state_instance_get_dominant_issue_option(p)));
735 max_buffer.set(p, ve::select(mask, v, old_max));
736 });
737 });
738 break;
739 }
740 case 11: {
741 static ve::vectorizable_buffer<float, dcon::nation_id> max_buffer(uint32_t(1));
742 static uint32_t old_count = 1;
743
744 auto new_count = state.world.nation_size();
745 if(new_count > old_count) {
746 max_buffer = state.world.nation_make_vectorizable_float_buffer();
747 old_count = new_count;
748 }
749 state.world.execute_serial_over_nation([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
750 state.world.for_each_issue_option([&](dcon::issue_option_id c) {
751 state.world.execute_serial_over_nation([&, k = to_key(state, c)](auto p) {
752 auto v = state.world.nation_get_demographics(p, k);
753 auto old_max = max_buffer.get(p);
754 auto mask = v > old_max;
755 state.world.nation_set_dominant_issue_option(p,
756 ve::select(mask, ve::tagged_vector<dcon::issue_option_id>(c), state.world.nation_get_dominant_issue_option(p)));
757 max_buffer.set(p, ve::select(mask, v, old_max));
758 });
759 });
760 break;
761 }
762 case 12: {
763 static ve::vectorizable_buffer<float, dcon::pop_id> max_buffer(uint32_t(1));
764 static uint32_t old_count = 1;
765
766 auto new_count = state.world.pop_size();
767 if(new_count > old_count) {
768 max_buffer = state.world.pop_make_vectorizable_float_buffer();
769 old_count = new_count;
770 }
771 state.world.execute_serial_over_pop([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
772 state.world.for_each_issue_option([&](dcon::issue_option_id c) {
773 state.world.execute_serial_over_pop([&, k = pop_demographics::to_key(state, c)](auto p) {
774 auto v = pop_demographics::get_demo(state, p, k);
775 auto old_max = max_buffer.get(p);
776 auto mask = v > old_max;
777 state.world.pop_set_dominant_issue_option(p,
778 ve::select(mask, ve::tagged_vector<dcon::issue_option_id>(c), state.world.pop_get_dominant_issue_option(p)));
779 max_buffer.set(p, ve::select(mask, v, old_max));
780 });
781 });
782 break;
783 }
784 case 13: {
785 static ve::vectorizable_buffer<float, dcon::pop_id> max_buffer(uint32_t(1));
786 static uint32_t old_count = 1;
787
788 auto new_count = state.world.pop_size();
789 if(new_count > old_count) {
790 max_buffer = state.world.pop_make_vectorizable_float_buffer();
791 old_count = new_count;
792 }
793 state.world.execute_serial_over_pop([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
794 state.world.for_each_ideology([&](dcon::ideology_id c) {
795 state.world.execute_serial_over_pop([&, k = pop_demographics::to_key(state, c)](auto p) {
796 auto v = pop_demographics::get_demo(state, p, k);
797 auto old_max = max_buffer.get(p);
798 auto mask = v > old_max;
799 state.world.pop_set_dominant_ideology(p,
800 ve::select(mask, ve::tagged_vector<dcon::ideology_id>(c), state.world.pop_get_dominant_ideology(p)));
801 max_buffer.set(p, ve::select(mask, v, old_max));
802 });
803 });
804 break;
805 }
806 case 14: {
807 // clear nation
808 state.world.execute_serial_over_nation(
809 [&](auto ni) { state.world.nation_set_non_colonial_population(ni, ve::fp_vector()); });
810 // sum in nation
811 state.world.for_each_state_instance([&](dcon::state_instance_id s) {
812 if(!state.world.province_get_is_colonial(state.world.state_instance_get_capital(s))) {
813 auto location = state.world.state_instance_get_nation_from_state_ownership(s);
814 state.world.nation_get_non_colonial_population(location) +=
815 state.world.state_instance_get_demographics(s, demographics::total);
816 }
817 });
818 break;
819 }
820 case 15: {
821 // clear nation
822 state.world.execute_serial_over_nation(
823 [&](auto ni) { state.world.nation_set_non_colonial_bureaucrats(ni, ve::fp_vector()); });
824 // sum in nation
825 state.world.for_each_state_instance(
826 [&, k = demographics::to_key(state, state.culture_definitions.bureaucrat)](dcon::state_instance_id s) {
827 if(!state.world.province_get_is_colonial(state.world.state_instance_get_capital(s))) {
828 auto location = state.world.state_instance_get_nation_from_state_ownership(s);
829 state.world.nation_get_non_colonial_bureaucrats(location) += state.world.state_instance_get_demographics(s, k);
830 }
831 });
832 break;
833 }
834 case 16:
835 {
836 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
837 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
838 [&](auto p) { state.world.province_set_dominant_accepted_culture(p, dcon::culture_id{}); });
839 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
840 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
841
842 state.world.for_each_culture([&](dcon::culture_id c) {
843 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, key = to_key(state, c)](auto p) {
844 auto v = state.world.province_get_demographics(p, key);
845 auto old_max = max_buffer.get(p);
846 auto mask = v > old_max && nations::nation_accepts_culture(state, state.world.province_get_nation_from_province_ownership(p), c);
847 state.world.province_set_dominant_accepted_culture(p,
848 ve::select(mask, ve::tagged_vector<dcon::culture_id>(c), state.world.province_get_dominant_accepted_culture(p)));
849 max_buffer.set(p, ve::select(mask, v, old_max));
850 });
851 });
852 break;
853 }
854 default:
855 break;
856 }
857 });
858}
859
861 regenerate_from_pop_data<true>(state);
862}
864 regenerate_from_pop_data<false>(state);
865}
866
867template<bool full>
869 auto const sz = size(state);
870 auto const csz = common_size(state);
871 auto const extra_size = sz - csz;
872 auto const extra_group_size = (extra_size + extra_demo_grouping - 1) / extra_demo_grouping;
873
874 concurrency::parallel_for(uint32_t(0), full ? sz : csz + extra_group_size, [&](uint32_t base_index) {
875 auto index = base_index;
876 if constexpr(!full) {
877 if(index >= csz) {
878 index += extra_group_size * (state.current_date.value % extra_demo_grouping);
879 if(index >= sz)
880 return;
881 }
882 }
883 dcon::demographics_key key{ dcon::demographics_key::value_base_t(index) };
884 if(index < count_special_keys) {
885 switch(index) {
886 case 0: // constexpr inline dcon::demographics_key total(0);
887 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) { return state.world.pop_get_size(p); });
888 break;
889 case 1: // constexpr inline dcon::demographics_key employable(1);
890 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
891 return state.world.pop_type_get_has_unemployment(state.world.pop_get_poptype(p)) ? state.world.pop_get_size(p) : 0.0f;
892 });
893 break;
894 case 2: // constexpr inline dcon::demographics_key employed(2);
895 alt_sum_over_demographics(state, key,
896 [](sys::state const& state, dcon::pop_id p) { return pop_demographics::get_employment(state, p); });
897 break;
898 case 3: // constexpr inline dcon::demographics_key consciousness(3);
899 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
900 return pop_demographics::get_consciousness(state, p) * state.world.pop_get_size(p);
901 });
902 break;
903 case 4: // constexpr inline dcon::demographics_key militancy(4);
904 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
905 return pop_demographics::get_militancy(state, p) * state.world.pop_get_size(p);
906 });
907 break;
908 case 5: // constexpr inline dcon::demographics_key literacy(5);
909 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
910 return pop_demographics::get_literacy(state, p) * state.world.pop_get_size(p);
911 });
912 break;
913 case 6: // constexpr inline dcon::demographics_key political_reform_desire(6);
914 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
915 if(state.world.province_get_is_colonial(state.world.pop_get_province_from_pop_location(p)) == false) {
916 auto movement = state.world.pop_get_movement_from_pop_movement_membership(p);
917 if(movement) {
918 auto opt = state.world.movement_get_associated_issue_option(movement);
919 auto optpar = state.world.issue_option_get_parent_issue(opt);
920 if(opt && state.world.issue_get_issue_type(optpar) == uint8_t(culture::issue_type::political))
921 return state.world.pop_get_size(p);
922 }
923 return 0.0f;
924 } else
925 return 0.0f;
926 });
927 break;
928 case 7: // constexpr inline dcon::demographics_key social_reform_desire(7);
929 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
930 if(state.world.province_get_is_colonial(state.world.pop_get_province_from_pop_location(p)) == false) {
931 auto movement = state.world.pop_get_movement_from_pop_movement_membership(p);
932 if(movement) {
933 auto opt = state.world.movement_get_associated_issue_option(movement);
934 auto optpar = state.world.issue_option_get_parent_issue(opt);
935 if(opt && state.world.issue_get_issue_type(optpar) == uint8_t(culture::issue_type::social))
936 return state.world.pop_get_size(p);
937 }
938 return 0.0f;
939 } else
940 return 0.0f;
941 });
942 break;
943 case 8: // constexpr inline dcon::demographics_key poor_militancy(8);
944 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
945 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
946 ? pop_demographics::get_militancy(state, p) * state.world.pop_get_size(p)
947 : 0.0f;
948 });
949 break;
950 case 9: // constexpr inline dcon::demographics_key middle_militancy(9);
951 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
952 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
953 ? pop_demographics::get_militancy(state, p) * state.world.pop_get_size(p)
954 : 0.0f;
955 });
956 break;
957 case 10: // constexpr inline dcon::demographics_key rich_militancy(10);
958 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
959 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
960 ? pop_demographics::get_militancy(state, p) * state.world.pop_get_size(p)
961 : 0.0f;
962 });
963 break;
964 case 11: // constexpr inline dcon::demographics_key poor_life_needs(11);
965 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
966 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
967 ? pop_demographics::get_life_needs(state, p) * state.world.pop_get_size(p)
968 : 0.0f;
969 });
970 break;
971 case 12: // constexpr inline dcon::demographics_key middle_life_needs(12);
972 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
973 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
974 ? pop_demographics::get_life_needs(state, p) * state.world.pop_get_size(p)
975 : 0.0f;
976 });
977 break;
978 case 13: // constexpr inline dcon::demographics_key rich_life_needs(13);
979 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
980 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
981 ? pop_demographics::get_life_needs(state, p) * state.world.pop_get_size(p)
982 : 0.0f;
983 });
984 break;
985 case 14: // constexpr inline dcon::demographics_key poor_everyday_needs(14);
986 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
987 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
988 ? pop_demographics::get_everyday_needs(state, p) * state.world.pop_get_size(p)
989 : 0.0f;
990 });
991 break;
992 case 15: // constexpr inline dcon::demographics_key middle_everyday_needs(15);
993 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
994 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
995 ? pop_demographics::get_everyday_needs(state, p) * state.world.pop_get_size(p)
996 : 0.0f;
997 });
998 break;
999 case 16: // constexpr inline dcon::demographics_key rich_everyday_needs(16);
1000 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1001 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
1002 ? pop_demographics::get_everyday_needs(state, p) * state.world.pop_get_size(p)
1003 : 0.0f;
1004 });
1005 break;
1006 case 17: // constexpr inline dcon::demographics_key poor_luxury_needs(17);
1007 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1008 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
1009 ? pop_demographics::get_luxury_needs(state, p) * state.world.pop_get_size(p)
1010 : 0.0f;
1011 });
1012 break;
1013 case 18: // constexpr inline dcon::demographics_key middle_luxury_needs(18);
1014 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1015 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
1016 ? pop_demographics::get_luxury_needs(state, p) * state.world.pop_get_size(p)
1017 : 0.0f;
1018 });
1019 break;
1020 case 19: // constexpr inline dcon::demographics_key rich_luxury_needs(19);
1021 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1022 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
1023 ? pop_demographics::get_luxury_needs(state, p) * state.world.pop_get_size(p)
1024 : 0.0f;
1025 });
1026 break;
1027 case 20: // constexpr inline dcon::demographics_key poor_total(20);
1028 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1029 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
1030 ? state.world.pop_get_size(p)
1031 : 0.0f;
1032 });
1033 break;
1034 case 21: // constexpr inline dcon::demographics_key middle_total(21);
1035 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1036 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
1037 ? state.world.pop_get_size(p)
1038 : 0.0f;
1039 });
1040 break;
1041 case 22: // constexpr inline dcon::demographics_key rich_total(22);
1042 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1043 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
1044 ? state.world.pop_get_size(p)
1045 : 0.0f;
1046 });
1047 break;
1048 }
1049 // common - pop type - employment - culture - ideology - issue option - religion
1050 } else if(key.index() < to_employment_key(state, dcon::pop_type_id(0)).index()) { // pop type
1051 dcon::pop_type_id pkey{ dcon::pop_type_id::value_base_t(index - (count_special_keys)) };
1052 alt_sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
1053 return state.world.pop_get_poptype(p) == pkey ? state.world.pop_get_size(p) : 0.0f;
1054 });
1055 } else if(key.index() < to_key(state, dcon::culture_id(0)).index()) { // employment
1056 dcon::pop_type_id pkey{ dcon::pop_type_id::value_base_t(index - (count_special_keys + state.world.pop_type_size())) };
1057 if(state.world.pop_type_get_has_unemployment(pkey)) {
1058 alt_sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
1059 return state.world.pop_get_poptype(p) == pkey ? pop_demographics::get_employment(state, p) : 0.0f;
1060 });
1061 } else {
1062 alt_sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
1063 return state.world.pop_get_poptype(p) == pkey ? state.world.pop_get_size(p) : 0.0f;
1064 });
1065 }
1066 } else if(key.index() < to_key(state, dcon::ideology_id(0)).index()) { // culture
1067 dcon::culture_id pkey{
1068 dcon::culture_id::value_base_t(index - (count_special_keys + state.world.pop_type_size() * 2)) };
1069 alt_sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
1070 return state.world.pop_get_culture(p) == pkey ? state.world.pop_get_size(p) : 0.0f;
1071 });
1072 } else if(key.index() < to_key(state, dcon::issue_option_id(0)).index()) { // ideology
1073 dcon::ideology_id pkey{ dcon::ideology_id::value_base_t(index - (count_special_keys + state.world.pop_type_size() * 2 + state.world.culture_size())) };
1074 auto pdemo_key = pop_demographics::to_key(state, pkey);
1075 alt_sum_over_demographics(state, key, [pdemo_key](sys::state const& state, dcon::pop_id p) {
1076 return pop_demographics::get_demo(state, p, pdemo_key) * state.world.pop_get_size(p);
1077 });
1078 } else if(key.index() < to_key(state, dcon::religion_id(0)).index()) { // issue option
1079 dcon::issue_option_id pkey{ dcon::issue_option_id::value_base_t(index - (count_special_keys + state.world.pop_type_size() * 2 + state.world.culture_size() + state.world.ideology_size())) };
1080 auto pdemo_key = pop_demographics::to_key(state, pkey);
1081 alt_sum_over_demographics(state, key, [pdemo_key](sys::state const& state, dcon::pop_id p) {
1082 return pop_demographics::get_demo(state, p, pdemo_key) * state.world.pop_get_size(p);
1083 });
1084 } else { // religion
1085 dcon::religion_id pkey{ dcon::religion_id::value_base_t(
1086 index - (count_special_keys + state.world.pop_type_size() * 2 + state.world.culture_size() + state.world.ideology_size() + state.world.issue_option_size())) };
1087 alt_sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
1088 return state.world.pop_get_religion(p) == pkey ? state.world.pop_get_size(p) : 0.0f;
1089 });
1090 }
1091 });
1092
1093 //
1094 // calculate values derived from demographics
1095 //
1096
1097 concurrency::parallel_for(uint32_t(0), uint32_t(12), [&](uint32_t index) {
1098 switch(index) {
1099 case 0:
1100 {
1101 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
1102
1103 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
1104 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1105 state.world.for_each_culture([&](dcon::culture_id c) {
1106 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, k = to_key(state, c)](auto p) {
1107 auto v = state.world.province_get_demographics_alt(p, k);
1108 auto old_max = max_buffer.get(p);
1109 auto mask = v > old_max;
1110 state.world.province_set_dominant_culture(p,
1111 ve::select(mask, ve::tagged_vector<dcon::culture_id>(c), state.world.province_get_dominant_culture(p)));
1112 max_buffer.set(p, ve::select(mask, v, old_max));
1113 });
1114 });
1115 break;
1116 }
1117 case 1:
1118 {
1119 static ve::vectorizable_buffer<float, dcon::state_instance_id> max_buffer(uint32_t(1));
1120 static uint32_t old_count = 1;
1121
1122 auto new_count = state.world.state_instance_size();
1123 if(new_count > old_count) {
1124 max_buffer = state.world.state_instance_make_vectorizable_float_buffer();
1125 old_count = new_count;
1126 }
1127 state.world.execute_serial_over_state_instance([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1128 state.world.for_each_culture([&](dcon::culture_id c) {
1129 state.world.execute_serial_over_state_instance([&, k = to_key(state, c)](auto p) {
1130 auto v = state.world.state_instance_get_demographics_alt(p, k);
1131 auto old_max = max_buffer.get(p);
1132 auto mask = v > old_max;
1133 state.world.state_instance_set_dominant_culture(p,
1134 ve::select(mask, ve::tagged_vector<dcon::culture_id>(c), state.world.state_instance_get_dominant_culture(p)));
1135 max_buffer.set(p, ve::select(mask, v, old_max));
1136 });
1137 });
1138 break;
1139 }
1140 case 2:
1141 {
1142 static ve::vectorizable_buffer<float, dcon::nation_id> max_buffer(uint32_t(1));
1143 static uint32_t old_count = 1;
1144
1145 auto new_count = state.world.nation_size();
1146 if(new_count > old_count) {
1147 max_buffer = state.world.nation_make_vectorizable_float_buffer();
1148 old_count = new_count;
1149 }
1150 state.world.execute_serial_over_nation([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1151 state.world.for_each_culture([&](dcon::culture_id c) {
1152 state.world.execute_serial_over_nation([&, k = to_key(state, c)](auto p) {
1153 auto v = state.world.nation_get_demographics_alt(p, k);
1154 auto old_max = max_buffer.get(p);
1155 auto mask = v > old_max;
1156 state.world.nation_set_dominant_culture(p,
1157 ve::select(mask, ve::tagged_vector<dcon::culture_id>(c), state.world.nation_get_dominant_culture(p)));
1158 max_buffer.set(p, ve::select(mask, v, old_max));
1159 });
1160 });
1161 break;
1162 }
1163 case 3:
1164 {
1165 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
1166
1167 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
1168 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1169 state.world.for_each_religion([&](dcon::religion_id c) {
1170 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, k = to_key(state, c)](auto p) {
1171 auto v = state.world.province_get_demographics_alt(p, k);
1172 auto old_max = max_buffer.get(p);
1173 auto mask = v > old_max;
1174 state.world.province_set_dominant_religion(p,
1175 ve::select(mask, ve::tagged_vector<dcon::religion_id>(c), state.world.province_get_dominant_religion(p)));
1176 max_buffer.set(p, ve::select(mask, v, old_max));
1177 });
1178 });
1179 break;
1180 }
1181 case 4:
1182 {
1183 static ve::vectorizable_buffer<float, dcon::state_instance_id> max_buffer(uint32_t(1));
1184 static uint32_t old_count = 1;
1185
1186 auto new_count = state.world.state_instance_size();
1187 if(new_count > old_count) {
1188 max_buffer = state.world.state_instance_make_vectorizable_float_buffer();
1189 old_count = new_count;
1190 }
1191 state.world.execute_serial_over_state_instance([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1192 state.world.for_each_religion([&](dcon::religion_id c) {
1193 state.world.execute_serial_over_state_instance([&, k = to_key(state, c)](auto p) {
1194 auto v = state.world.state_instance_get_demographics_alt(p, k);
1195 auto old_max = max_buffer.get(p);
1196 auto mask = v > old_max;
1197 state.world.state_instance_set_dominant_religion(p,
1198 ve::select(mask, ve::tagged_vector<dcon::religion_id>(c), state.world.state_instance_get_dominant_religion(p)));
1199 max_buffer.set(p, ve::select(mask, v, old_max));
1200 });
1201 });
1202 break;
1203 }
1204 case 5:
1205 {
1206 static ve::vectorizable_buffer<float, dcon::nation_id> max_buffer(uint32_t(1));
1207 static uint32_t old_count = 1;
1208
1209 auto new_count = state.world.nation_size();
1210 if(new_count > old_count) {
1211 max_buffer = state.world.nation_make_vectorizable_float_buffer();
1212 old_count = new_count;
1213 }
1214 state.world.execute_serial_over_nation([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1215 state.world.for_each_religion([&](dcon::religion_id c) {
1216 state.world.execute_serial_over_nation([&, k = to_key(state, c)](auto p) {
1217 auto v = state.world.nation_get_demographics_alt(p, k);
1218 auto old_max = max_buffer.get(p);
1219 auto mask = v > old_max;
1220 state.world.nation_set_dominant_religion(p,
1221 ve::select(mask, ve::tagged_vector<dcon::religion_id>(c), state.world.nation_get_dominant_religion(p)));
1222 max_buffer.set(p, ve::select(mask, v, old_max));
1223 });
1224 });
1225 break;
1226 }
1227 case 6:
1228 {
1229 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
1230
1231 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
1232 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1233 state.world.for_each_ideology([&](dcon::ideology_id c) {
1234 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, k = to_key(state, c)](auto p) {
1235 auto v = state.world.province_get_demographics_alt(p, k);
1236 auto old_max = max_buffer.get(p);
1237 auto mask = v > old_max;
1238 state.world.province_set_dominant_ideology(p,
1239 ve::select(mask, ve::tagged_vector<dcon::ideology_id>(c), state.world.province_get_dominant_ideology(p)));
1240 max_buffer.set(p, ve::select(mask, v, old_max));
1241 });
1242 });
1243 break;
1244 }
1245 case 7:
1246 {
1247 static ve::vectorizable_buffer<float, dcon::state_instance_id> max_buffer(uint32_t(1));
1248 static uint32_t old_count = 1;
1249
1250 auto new_count = state.world.state_instance_size();
1251 if(new_count > old_count) {
1252 max_buffer = state.world.state_instance_make_vectorizable_float_buffer();
1253 old_count = new_count;
1254 }
1255 state.world.execute_serial_over_state_instance([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1256 state.world.for_each_ideology([&](dcon::ideology_id c) {
1257 state.world.execute_serial_over_state_instance([&, k = to_key(state, c)](auto p) {
1258 auto v = state.world.state_instance_get_demographics_alt(p, k);
1259 auto old_max = max_buffer.get(p);
1260 auto mask = v > old_max;
1261 state.world.state_instance_set_dominant_ideology(p,
1262 ve::select(mask, ve::tagged_vector<dcon::ideology_id>(c), state.world.state_instance_get_dominant_ideology(p)));
1263 max_buffer.set(p, ve::select(mask, v, old_max));
1264 });
1265 });
1266 break;
1267 }
1268 case 8:
1269 {
1270 static ve::vectorizable_buffer<float, dcon::nation_id> max_buffer(uint32_t(1));
1271 static uint32_t old_count = 1;
1272
1273 auto new_count = state.world.nation_size();
1274 if(new_count > old_count) {
1275 max_buffer = state.world.nation_make_vectorizable_float_buffer();
1276 old_count = new_count;
1277 }
1278 state.world.execute_serial_over_nation([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1279 state.world.for_each_ideology([&](dcon::ideology_id c) {
1280 state.world.execute_serial_over_nation([&, k = to_key(state, c)](auto p) {
1281 auto v = state.world.nation_get_demographics_alt(p, k);
1282 auto old_max = max_buffer.get(p);
1283 auto mask = v > old_max;
1284 state.world.nation_set_dominant_ideology(p,
1285 ve::select(mask, ve::tagged_vector<dcon::ideology_id>(c), state.world.nation_get_dominant_ideology(p)));
1286 max_buffer.set(p, ve::select(mask, v, old_max));
1287 });
1288 });
1289 break;
1290 }
1291 case 9:
1292 {
1293 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
1294
1295 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
1296 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1297 state.world.for_each_issue_option([&](dcon::issue_option_id c) {
1298 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, k = to_key(state, c)](auto p) {
1299 auto v = state.world.province_get_demographics_alt(p, k);
1300 auto old_max = max_buffer.get(p);
1301 auto mask = v > old_max;
1302 state.world.province_set_dominant_issue_option(p,
1303 ve::select(mask, ve::tagged_vector<dcon::issue_option_id>(c), state.world.province_get_dominant_issue_option(p)));
1304 max_buffer.set(p, ve::select(mask, v, old_max));
1305 });
1306 });
1307 break;
1308 }
1309 case 10:
1310 {
1311 static ve::vectorizable_buffer<float, dcon::state_instance_id> max_buffer(uint32_t(1));
1312 static uint32_t old_count = 1;
1313
1314 auto new_count = state.world.state_instance_size();
1315 if(new_count > old_count) {
1316 max_buffer = state.world.state_instance_make_vectorizable_float_buffer();
1317 old_count = new_count;
1318 }
1319 state.world.execute_serial_over_state_instance([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1320 state.world.for_each_issue_option([&](dcon::issue_option_id c) {
1321 state.world.execute_serial_over_state_instance([&, k = to_key(state, c)](auto p) {
1322 auto v = state.world.state_instance_get_demographics_alt(p, k);
1323 auto old_max = max_buffer.get(p);
1324 auto mask = v > old_max;
1325 state.world.state_instance_set_dominant_issue_option(p, ve::select(mask, ve::tagged_vector<dcon::issue_option_id>(c), state.world.state_instance_get_dominant_issue_option(p)));
1326 max_buffer.set(p, ve::select(mask, v, old_max));
1327 });
1328 });
1329 break;
1330 }
1331 case 11:
1332 {
1333 static ve::vectorizable_buffer<float, dcon::nation_id> max_buffer(uint32_t(1));
1334 static uint32_t old_count = 1;
1335
1336 auto new_count = state.world.nation_size();
1337 if(new_count > old_count) {
1338 max_buffer = state.world.nation_make_vectorizable_float_buffer();
1339 old_count = new_count;
1340 }
1341 state.world.execute_serial_over_nation([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1342 state.world.for_each_issue_option([&](dcon::issue_option_id c) {
1343 state.world.execute_serial_over_nation([&, k = to_key(state, c)](auto p) {
1344 auto v = state.world.nation_get_demographics_alt(p, k);
1345 auto old_max = max_buffer.get(p);
1346 auto mask = v > old_max;
1347 state.world.nation_set_dominant_issue_option(p,
1348 ve::select(mask, ve::tagged_vector<dcon::issue_option_id>(c), state.world.nation_get_dominant_issue_option(p)));
1349 max_buffer.set(p, ve::select(mask, v, old_max));
1350 });
1351 });
1352 break;
1353 }
1354 default:
1355 break;
1356 }
1357 });
1358}
1359
1360template<bool full>
1362 auto const sz = size(state);
1363 auto const csz = common_size(state);
1364 auto const extra_size = sz - csz;
1365 auto const extra_group_size = (extra_size + extra_demo_grouping - 1) / extra_demo_grouping;
1366
1367 for(uint32_t base_index = 0; base_index < (full ? sz : csz + extra_group_size); ++ base_index) {
1368 auto index = base_index;
1369 if constexpr(!full) {
1370 if(index >= csz) {
1371 index += extra_group_size * (state.current_date.value % extra_demo_grouping);
1372 if(index >= sz)
1373 break;
1374 }
1375 }
1376 dcon::demographics_key key{ dcon::demographics_key::value_base_t(index) };
1377 if(index < count_special_keys) {
1378 switch(index) {
1379 case 0: // constexpr inline dcon::demographics_key total(0);
1380 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) { return state.world.pop_get_size(p); });
1381 break;
1382 case 1: // constexpr inline dcon::demographics_key employable(1);
1383 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1384 return state.world.pop_type_get_has_unemployment(state.world.pop_get_poptype(p)) ? state.world.pop_get_size(p) : 0.0f;
1385 });
1386 break;
1387 case 2: // constexpr inline dcon::demographics_key employed(2);
1388 alt_sum_over_demographics(state, key,
1389 [](sys::state const& state, dcon::pop_id p) { return pop_demographics::get_employment(state, p); });
1390 break;
1391 case 3: // constexpr inline dcon::demographics_key consciousness(3);
1392 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1393 return pop_demographics::get_consciousness(state, p) * state.world.pop_get_size(p);
1394 });
1395 break;
1396 case 4: // constexpr inline dcon::demographics_key militancy(4);
1397 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1398 return pop_demographics::get_militancy(state, p) * state.world.pop_get_size(p);
1399 });
1400 break;
1401 case 5: // constexpr inline dcon::demographics_key literacy(5);
1402 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1403 return pop_demographics::get_literacy(state, p) * state.world.pop_get_size(p);
1404 });
1405 break;
1406 case 6: // constexpr inline dcon::demographics_key political_reform_desire(6);
1407 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1408 if(state.world.province_get_is_colonial(state.world.pop_get_province_from_pop_location(p)) == false) {
1409 auto movement = state.world.pop_get_movement_from_pop_movement_membership(p);
1410 if(movement) {
1411 auto opt = state.world.movement_get_associated_issue_option(movement);
1412 auto optpar = state.world.issue_option_get_parent_issue(opt);
1413 if(opt && state.world.issue_get_issue_type(optpar) == uint8_t(culture::issue_type::political))
1414 return state.world.pop_get_size(p);
1415 }
1416 return 0.0f;
1417 } else
1418 return 0.0f;
1419 });
1420 break;
1421 case 7: // constexpr inline dcon::demographics_key social_reform_desire(7);
1422 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1423 if(state.world.province_get_is_colonial(state.world.pop_get_province_from_pop_location(p)) == false) {
1424 auto movement = state.world.pop_get_movement_from_pop_movement_membership(p);
1425 if(movement) {
1426 auto opt = state.world.movement_get_associated_issue_option(movement);
1427 auto optpar = state.world.issue_option_get_parent_issue(opt);
1428 if(opt && state.world.issue_get_issue_type(optpar) == uint8_t(culture::issue_type::social))
1429 return state.world.pop_get_size(p);
1430 }
1431 return 0.0f;
1432 } else
1433 return 0.0f;
1434 });
1435 break;
1436 case 8: // constexpr inline dcon::demographics_key poor_militancy(8);
1437 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1438 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
1439 ? pop_demographics::get_militancy(state, p) * state.world.pop_get_size(p)
1440 : 0.0f;
1441 });
1442 break;
1443 case 9: // constexpr inline dcon::demographics_key middle_militancy(9);
1444 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1445 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
1446 ? pop_demographics::get_militancy(state, p) * state.world.pop_get_size(p)
1447 : 0.0f;
1448 });
1449 break;
1450 case 10: // constexpr inline dcon::demographics_key rich_militancy(10);
1451 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1452 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
1453 ? pop_demographics::get_militancy(state, p) * state.world.pop_get_size(p)
1454 : 0.0f;
1455 });
1456 break;
1457 case 11: // constexpr inline dcon::demographics_key poor_life_needs(11);
1458 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1459 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
1460 ? pop_demographics::get_life_needs(state, p) * state.world.pop_get_size(p)
1461 : 0.0f;
1462 });
1463 break;
1464 case 12: // constexpr inline dcon::demographics_key middle_life_needs(12);
1465 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1466 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
1467 ? pop_demographics::get_life_needs(state, p) * state.world.pop_get_size(p)
1468 : 0.0f;
1469 });
1470 break;
1471 case 13: // constexpr inline dcon::demographics_key rich_life_needs(13);
1472 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1473 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
1474 ? pop_demographics::get_life_needs(state, p) * state.world.pop_get_size(p)
1475 : 0.0f;
1476 });
1477 break;
1478 case 14: // constexpr inline dcon::demographics_key poor_everyday_needs(14);
1479 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1480 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
1481 ? pop_demographics::get_everyday_needs(state, p) * state.world.pop_get_size(p)
1482 : 0.0f;
1483 });
1484 break;
1485 case 15: // constexpr inline dcon::demographics_key middle_everyday_needs(15);
1486 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1487 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
1488 ? pop_demographics::get_everyday_needs(state, p) * state.world.pop_get_size(p)
1489 : 0.0f;
1490 });
1491 break;
1492 case 16: // constexpr inline dcon::demographics_key rich_everyday_needs(16);
1493 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1494 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
1495 ? pop_demographics::get_everyday_needs(state, p) * state.world.pop_get_size(p)
1496 : 0.0f;
1497 });
1498 break;
1499 case 17: // constexpr inline dcon::demographics_key poor_luxury_needs(17);
1500 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1501 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
1502 ? pop_demographics::get_luxury_needs(state, p) * state.world.pop_get_size(p)
1503 : 0.0f;
1504 });
1505 break;
1506 case 18: // constexpr inline dcon::demographics_key middle_luxury_needs(18);
1507 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1508 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
1509 ? pop_demographics::get_luxury_needs(state, p) * state.world.pop_get_size(p)
1510 : 0.0f;
1511 });
1512 break;
1513 case 19: // constexpr inline dcon::demographics_key rich_luxury_needs(19);
1514 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1515 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
1516 ? pop_demographics::get_luxury_needs(state, p) * state.world.pop_get_size(p)
1517 : 0.0f;
1518 });
1519 break;
1520 case 20: // constexpr inline dcon::demographics_key poor_total(20);
1521 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1522 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::poor)
1523 ? state.world.pop_get_size(p)
1524 : 0.0f;
1525 });
1526 break;
1527 case 21: // constexpr inline dcon::demographics_key middle_total(21);
1528 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1529 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::middle)
1530 ? state.world.pop_get_size(p)
1531 : 0.0f;
1532 });
1533 break;
1534 case 22: // constexpr inline dcon::demographics_key rich_total(22);
1535 alt_sum_over_demographics(state, key, [](sys::state const& state, dcon::pop_id p) {
1536 return state.world.pop_type_get_strata(state.world.pop_get_poptype(p)) == uint8_t(culture::pop_strata::rich)
1537 ? state.world.pop_get_size(p)
1538 : 0.0f;
1539 });
1540 break;
1541 }
1542 // common - pop type - employment - culture - ideology - issue option - religion
1543 } else if(key.index() < to_employment_key(state, dcon::pop_type_id(0)).index()) { // pop type
1544 dcon::pop_type_id pkey{ dcon::pop_type_id::value_base_t(index - (count_special_keys)) };
1545 alt_sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
1546 return state.world.pop_get_poptype(p) == pkey ? state.world.pop_get_size(p) : 0.0f;
1547 });
1548 } else if(key.index() < to_key(state, dcon::culture_id(0)).index()) { // employment
1549 dcon::pop_type_id pkey{ dcon::pop_type_id::value_base_t(index - (count_special_keys + state.world.pop_type_size())) };
1550 if(state.world.pop_type_get_has_unemployment(pkey)) {
1551 alt_sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
1552 return state.world.pop_get_poptype(p) == pkey ? pop_demographics::get_employment(state, p) : 0.0f;
1553 });
1554 } else {
1555 alt_sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
1556 return state.world.pop_get_poptype(p) == pkey ? state.world.pop_get_size(p) : 0.0f;
1557 });
1558 }
1559 } else if(key.index() < to_key(state, dcon::ideology_id(0)).index()) { // culture
1560 dcon::culture_id pkey{
1561 dcon::culture_id::value_base_t(index - (count_special_keys + state.world.pop_type_size() * 2)) };
1562 alt_sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
1563 return state.world.pop_get_culture(p) == pkey ? state.world.pop_get_size(p) : 0.0f;
1564 });
1565 } else if(key.index() < to_key(state, dcon::issue_option_id(0)).index()) { // ideology
1566 dcon::ideology_id pkey{ dcon::ideology_id::value_base_t(index - (count_special_keys + state.world.pop_type_size() * 2 + state.world.culture_size())) };
1567 auto pdemo_key = pop_demographics::to_key(state, pkey);
1568 alt_sum_over_demographics(state, key, [pdemo_key](sys::state const& state, dcon::pop_id p) {
1569 return pop_demographics::get_demo(state, p, pdemo_key) * state.world.pop_get_size(p);
1570 });
1571 } else if(key.index() < to_key(state, dcon::religion_id(0)).index()) { // issue option
1572 dcon::issue_option_id pkey{ dcon::issue_option_id::value_base_t(index - (count_special_keys + state.world.pop_type_size() * 2 + state.world.culture_size() + state.world.ideology_size())) };
1573 auto pdemo_key = pop_demographics::to_key(state, pkey);
1574 alt_sum_over_demographics(state, key, [pdemo_key](sys::state const& state, dcon::pop_id p) {
1575 return pop_demographics::get_demo(state, p, pdemo_key) * state.world.pop_get_size(p);
1576 });
1577 } else { // religion
1578 dcon::religion_id pkey{ dcon::religion_id::value_base_t(
1579 index - (count_special_keys + state.world.pop_type_size() * 2 + state.world.culture_size() + state.world.ideology_size() + state.world.issue_option_size())) };
1580 alt_sum_over_demographics(state, key, [pkey](sys::state const& state, dcon::pop_id p) {
1581 return state.world.pop_get_religion(p) == pkey ? state.world.pop_get_size(p) : 0.0f;
1582 });
1583 }
1584 }
1585
1586 if constexpr(full == false) { // copies
1587 for(uint32_t base_index = csz; base_index < (full ? sz : csz + extra_group_size); ++base_index) {
1588 auto index = base_index;
1589 index += extra_group_size * ((state.current_date.value + extra_demo_grouping - 1) % extra_demo_grouping);
1590 if(index >= sz)
1591 break;
1592
1593 dcon::demographics_key key{ dcon::demographics_key::value_base_t(index) };
1594 alt_copy_demographics(state, key);
1595 }
1596 }
1597
1598 //
1599 // calculate values derived from demographics
1600 //
1601 uint32_t l2_start = 0;
1602 uint32_t l2_end = 6;
1603 if((state.current_date.value % 1) != 0) {
1604 l2_start = 6;
1605 l2_end = 12;
1606 }
1607 for(uint32_t index = l2_start; index < l2_end; ++index) {
1608 switch(index) {
1609 case 0:
1610 {
1611 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
1612
1613 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
1614 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1615 state.world.for_each_culture([&](dcon::culture_id c) {
1616 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, k = to_key(state, c)](auto p) {
1617 auto v = state.world.province_get_demographics_alt(p, k);
1618 auto old_max = max_buffer.get(p);
1619 auto mask = v > old_max;
1620 state.world.province_set_dominant_culture(p,
1621 ve::select(mask, ve::tagged_vector<dcon::culture_id>(c), state.world.province_get_dominant_culture(p)));
1622 max_buffer.set(p, ve::select(mask, v, old_max));
1623 });
1624 });
1625 break;
1626 }
1627 case 1:
1628 {
1629 static ve::vectorizable_buffer<float, dcon::state_instance_id> max_buffer(uint32_t(1));
1630 static uint32_t old_count = 1;
1631
1632 auto new_count = state.world.state_instance_size();
1633 if(new_count > old_count) {
1634 max_buffer = state.world.state_instance_make_vectorizable_float_buffer();
1635 old_count = new_count;
1636 }
1637 state.world.execute_serial_over_state_instance([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1638 state.world.for_each_culture([&](dcon::culture_id c) {
1639 state.world.execute_serial_over_state_instance([&, k = to_key(state, c)](auto p) {
1640 auto v = state.world.state_instance_get_demographics_alt(p, k);
1641 auto old_max = max_buffer.get(p);
1642 auto mask = v > old_max;
1643 state.world.state_instance_set_dominant_culture(p,
1644 ve::select(mask, ve::tagged_vector<dcon::culture_id>(c), state.world.state_instance_get_dominant_culture(p)));
1645 max_buffer.set(p, ve::select(mask, v, old_max));
1646 });
1647 });
1648 break;
1649 }
1650 case 2:
1651 {
1652 static ve::vectorizable_buffer<float, dcon::nation_id> max_buffer(uint32_t(1));
1653 static uint32_t old_count = 1;
1654
1655 auto new_count = state.world.nation_size();
1656 if(new_count > old_count) {
1657 max_buffer = state.world.nation_make_vectorizable_float_buffer();
1658 old_count = new_count;
1659 }
1660 state.world.execute_serial_over_nation([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1661 state.world.for_each_culture([&](dcon::culture_id c) {
1662 state.world.execute_serial_over_nation([&, k = to_key(state, c)](auto p) {
1663 auto v = state.world.nation_get_demographics_alt(p, k);
1664 auto old_max = max_buffer.get(p);
1665 auto mask = v > old_max;
1666 state.world.nation_set_dominant_culture(p,
1667 ve::select(mask, ve::tagged_vector<dcon::culture_id>(c), state.world.nation_get_dominant_culture(p)));
1668 max_buffer.set(p, ve::select(mask, v, old_max));
1669 });
1670 });
1671 break;
1672 }
1673 case 3:
1674 {
1675 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
1676
1677 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
1678 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1679 state.world.for_each_religion([&](dcon::religion_id c) {
1680 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, k = to_key(state, c)](auto p) {
1681 auto v = state.world.province_get_demographics_alt(p, k);
1682 auto old_max = max_buffer.get(p);
1683 auto mask = v > old_max;
1684 state.world.province_set_dominant_religion(p,
1685 ve::select(mask, ve::tagged_vector<dcon::religion_id>(c), state.world.province_get_dominant_religion(p)));
1686 max_buffer.set(p, ve::select(mask, v, old_max));
1687 });
1688 });
1689 break;
1690 }
1691 case 4:
1692 {
1693 static ve::vectorizable_buffer<float, dcon::state_instance_id> max_buffer(uint32_t(1));
1694 static uint32_t old_count = 1;
1695
1696 auto new_count = state.world.state_instance_size();
1697 if(new_count > old_count) {
1698 max_buffer = state.world.state_instance_make_vectorizable_float_buffer();
1699 old_count = new_count;
1700 }
1701 state.world.execute_serial_over_state_instance([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1702 state.world.for_each_religion([&](dcon::religion_id c) {
1703 state.world.execute_serial_over_state_instance([&, k = to_key(state, c)](auto p) {
1704 auto v = state.world.state_instance_get_demographics_alt(p, k);
1705 auto old_max = max_buffer.get(p);
1706 auto mask = v > old_max;
1707 state.world.state_instance_set_dominant_religion(p,
1708 ve::select(mask, ve::tagged_vector<dcon::religion_id>(c), state.world.state_instance_get_dominant_religion(p)));
1709 max_buffer.set(p, ve::select(mask, v, old_max));
1710 });
1711 });
1712 break;
1713 }
1714 case 5:
1715 {
1716 static ve::vectorizable_buffer<float, dcon::nation_id> max_buffer(uint32_t(1));
1717 static uint32_t old_count = 1;
1718
1719 auto new_count = state.world.nation_size();
1720 if(new_count > old_count) {
1721 max_buffer = state.world.nation_make_vectorizable_float_buffer();
1722 old_count = new_count;
1723 }
1724 state.world.execute_serial_over_nation([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1725 state.world.for_each_religion([&](dcon::religion_id c) {
1726 state.world.execute_serial_over_nation([&, k = to_key(state, c)](auto p) {
1727 auto v = state.world.nation_get_demographics_alt(p, k);
1728 auto old_max = max_buffer.get(p);
1729 auto mask = v > old_max;
1730 state.world.nation_set_dominant_religion(p,
1731 ve::select(mask, ve::tagged_vector<dcon::religion_id>(c), state.world.nation_get_dominant_religion(p)));
1732 max_buffer.set(p, ve::select(mask, v, old_max));
1733 });
1734 });
1735 break;
1736 }
1737 case 6:
1738 {
1739 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
1740
1741 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
1742 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1743 state.world.for_each_ideology([&](dcon::ideology_id c) {
1744 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, k = to_key(state, c)](auto p) {
1745 auto v = state.world.province_get_demographics_alt(p, k);
1746 auto old_max = max_buffer.get(p);
1747 auto mask = v > old_max;
1748 state.world.province_set_dominant_ideology(p,
1749 ve::select(mask, ve::tagged_vector<dcon::ideology_id>(c), state.world.province_get_dominant_ideology(p)));
1750 max_buffer.set(p, ve::select(mask, v, old_max));
1751 });
1752 });
1753 break;
1754 }
1755 case 7:
1756 {
1757 static ve::vectorizable_buffer<float, dcon::state_instance_id> max_buffer(uint32_t(1));
1758 static uint32_t old_count = 1;
1759
1760 auto new_count = state.world.state_instance_size();
1761 if(new_count > old_count) {
1762 max_buffer = state.world.state_instance_make_vectorizable_float_buffer();
1763 old_count = new_count;
1764 }
1765 state.world.execute_serial_over_state_instance([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1766 state.world.for_each_ideology([&](dcon::ideology_id c) {
1767 state.world.execute_serial_over_state_instance([&, k = to_key(state, c)](auto p) {
1768 auto v = state.world.state_instance_get_demographics_alt(p, k);
1769 auto old_max = max_buffer.get(p);
1770 auto mask = v > old_max;
1771 state.world.state_instance_set_dominant_ideology(p,
1772 ve::select(mask, ve::tagged_vector<dcon::ideology_id>(c), state.world.state_instance_get_dominant_ideology(p)));
1773 max_buffer.set(p, ve::select(mask, v, old_max));
1774 });
1775 });
1776 break;
1777 }
1778 case 8:
1779 {
1780 static ve::vectorizable_buffer<float, dcon::nation_id> max_buffer(uint32_t(1));
1781 static uint32_t old_count = 1;
1782
1783 auto new_count = state.world.nation_size();
1784 if(new_count > old_count) {
1785 max_buffer = state.world.nation_make_vectorizable_float_buffer();
1786 old_count = new_count;
1787 }
1788 state.world.execute_serial_over_nation([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1789 state.world.for_each_ideology([&](dcon::ideology_id c) {
1790 state.world.execute_serial_over_nation([&, k = to_key(state, c)](auto p) {
1791 auto v = state.world.nation_get_demographics_alt(p, k);
1792 auto old_max = max_buffer.get(p);
1793 auto mask = v > old_max;
1794 state.world.nation_set_dominant_ideology(p,
1795 ve::select(mask, ve::tagged_vector<dcon::ideology_id>(c), state.world.nation_get_dominant_ideology(p)));
1796 max_buffer.set(p, ve::select(mask, v, old_max));
1797 });
1798 });
1799 break;
1800 }
1801 case 9:
1802 {
1803 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
1804
1805 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
1806 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1807 state.world.for_each_issue_option([&](dcon::issue_option_id c) {
1808 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, k = to_key(state, c)](auto p) {
1809 auto v = state.world.province_get_demographics_alt(p, k);
1810 auto old_max = max_buffer.get(p);
1811 auto mask = v > old_max;
1812 state.world.province_set_dominant_issue_option(p,
1813 ve::select(mask, ve::tagged_vector<dcon::issue_option_id>(c), state.world.province_get_dominant_issue_option(p)));
1814 max_buffer.set(p, ve::select(mask, v, old_max));
1815 });
1816 });
1817 break;
1818 }
1819 case 10:
1820 {
1821 static ve::vectorizable_buffer<float, dcon::state_instance_id> max_buffer(uint32_t(1));
1822 static uint32_t old_count = 1;
1823
1824 auto new_count = state.world.state_instance_size();
1825 if(new_count > old_count) {
1826 max_buffer = state.world.state_instance_make_vectorizable_float_buffer();
1827 old_count = new_count;
1828 }
1829 state.world.execute_serial_over_state_instance([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1830 state.world.for_each_issue_option([&](dcon::issue_option_id c) {
1831 state.world.execute_serial_over_state_instance([&, k = to_key(state, c)](auto p) {
1832 auto v = state.world.state_instance_get_demographics_alt(p, k);
1833 auto old_max = max_buffer.get(p);
1834 auto mask = v > old_max;
1835 state.world.state_instance_set_dominant_issue_option(p, ve::select(mask, ve::tagged_vector<dcon::issue_option_id>(c), state.world.state_instance_get_dominant_issue_option(p)));
1836 max_buffer.set(p, ve::select(mask, v, old_max));
1837 });
1838 });
1839 break;
1840 }
1841 case 11:
1842 {
1843 static ve::vectorizable_buffer<float, dcon::nation_id> max_buffer(uint32_t(1));
1844 static uint32_t old_count = 1;
1845
1846 auto new_count = state.world.nation_size();
1847 if(new_count > old_count) {
1848 max_buffer = state.world.nation_make_vectorizable_float_buffer();
1849 old_count = new_count;
1850 }
1851 state.world.execute_serial_over_nation([&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1852 state.world.for_each_issue_option([&](dcon::issue_option_id c) {
1853 state.world.execute_serial_over_nation([&, k = to_key(state, c)](auto p) {
1854 auto v = state.world.nation_get_demographics_alt(p, k);
1855 auto old_max = max_buffer.get(p);
1856 auto mask = v > old_max;
1857 state.world.nation_set_dominant_issue_option(p,
1858 ve::select(mask, ve::tagged_vector<dcon::issue_option_id>(c), state.world.nation_get_dominant_issue_option(p)));
1859 max_buffer.set(p, ve::select(mask, v, old_max));
1860 });
1861 });
1862 break;
1863 }
1864 default:
1865 break;
1866 }
1867 }
1868}
1869
1871 alt_st_regenerate_from_pop_data<false>(state);
1872}
1874 alt_mt_regenerate_from_pop_data<true>(state);
1875}
1876
1877
1879 concurrency::parallel_for(uint32_t(0), uint32_t(3), [&](uint32_t index) {
1880 switch(index) {
1881 case 0:
1882 {
1883 // clear nation
1884 state.world.execute_serial_over_nation(
1885 [&](auto ni) { state.world.nation_set_non_colonial_population(ni, ve::fp_vector()); });
1886 // sum in nation
1887 state.world.for_each_state_instance([&](dcon::state_instance_id s) {
1888 if(!state.world.province_get_is_colonial(state.world.state_instance_get_capital(s))) {
1889 auto location = state.world.state_instance_get_nation_from_state_ownership(s);
1890 state.world.nation_get_non_colonial_population(location) +=
1891 state.world.state_instance_get_demographics(s, demographics::total);
1892 }
1893 });
1894 break;
1895 }
1896 case 1:
1897 {
1898 // clear nation
1899 state.world.execute_serial_over_nation(
1900 [&](auto ni) { state.world.nation_set_non_colonial_bureaucrats(ni, ve::fp_vector()); });
1901 // sum in nation
1902 state.world.for_each_state_instance(
1903 [&, k = demographics::to_key(state, state.culture_definitions.bureaucrat)](dcon::state_instance_id s) {
1904 if(!state.world.province_get_is_colonial(state.world.state_instance_get_capital(s))) {
1905 auto location = state.world.state_instance_get_nation_from_state_ownership(s);
1906 state.world.nation_get_non_colonial_bureaucrats(location) += state.world.state_instance_get_demographics(s, k);
1907 }
1908 });
1909 break;
1910 }
1911 case 2:
1912 {
1913 static ve::vectorizable_buffer<float, dcon::province_id> max_buffer = state.world.province_make_vectorizable_float_buffer();
1914 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
1915 [&](auto p) { state.world.province_set_dominant_accepted_culture(p, dcon::culture_id{}); });
1916 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()),
1917 [&](auto p) { max_buffer.set(p, ve::fp_vector()); });
1918
1919 state.world.for_each_culture([&](dcon::culture_id c) {
1920 ve::execute_serial<dcon::province_id>(uint32_t(state.province_definitions.first_sea_province.index()), [&, key = to_key(state, c)](auto p) {
1921 auto v = state.world.province_get_demographics_alt(p, key);
1922 auto old_max = max_buffer.get(p);
1923 auto mask = v > old_max && nations::nation_accepts_culture(state, state.world.province_get_nation_from_province_ownership(p), c);
1924 state.world.province_set_dominant_accepted_culture(p,
1925 ve::select(mask, ve::tagged_vector<dcon::culture_id>(c), state.world.province_get_dominant_accepted_culture(p)));
1926 max_buffer.set(p, ve::select(mask, v, old_max));
1927 });
1928 });
1929 break;
1930 }
1931 }
1932 });
1933}
1934
1935inline constexpr uint32_t executions_per_block = 16 / ve::vector_size;
1936
1937template<typename F>
1938void execute_staggered_blocks(uint32_t offset, uint32_t divisions, uint32_t max, F&& functor) {
1939 auto block_index = 16 * offset;
1940 auto const block_advance = 16 * divisions;
1941
1942 assert(divisions > 10);
1943
1944 while(block_index < max) {
1945 for(uint32_t i = 0; i < executions_per_block; ++i) {
1946 functor(ve::contiguous_tags<dcon::pop_id>(block_index + i * ve::vector_size));
1947 }
1948 block_index += block_advance;
1949 }
1950}
1951
1952template<typename F>
1953void pexecute_staggered_blocks(uint32_t offset, uint32_t divisions, uint32_t max, F&& functor) {
1954 concurrency::parallel_for(16 * offset, max, 16 * divisions, [&](uint32_t index) {
1955 for(uint32_t i = 0; i < executions_per_block; ++i) {
1956 functor(ve::contiguous_tags<dcon::pop_id>(index + i * ve::vector_size));
1957 }
1958 });
1959}
1960
1961void update_militancy(sys::state& state, uint32_t offset, uint32_t divisions) {
1962 /*
1963 Let us define the local pop militancy modifier as the province's militancy modifier + the nation's militancy modifier + the
1964 nation's core pop militancy modifier (for non-colonial states, not just core provinces).
1965
1966 Each pop has its militancy adjusted by the
1967 local-militancy-modifier
1968 + (technology-separatism-modifier + 1) x define:MIL_NON_ACCEPTED (if the pop is not of a primary or accepted culture)
1969 - (pop-life-needs-satisfaction - 0.5) x define:MIL_NO_LIFE_NEED
1970 - (pop-everyday-needs-satisfaction - 0.5)^0 x define:MIL_LACK_EVERYDAY_NEED
1971 + (pop-everyday-needs-satisfaction - 0.5)v0 x define:MIL_HAS_EVERYDAY_NEED
1972 + (pop-luxury-needs-satisfaction - 0.5)v0 x define:MIL_HAS_LUXURY_NEED
1973 + pops-support-for-conservatism x define:MIL_IDEOLOGY / 100
1974 + pops-support-for-the-ruling-party-ideology x define:MIL_RULING_PARTY / 100
1975 - (if the pop has an attached regiment, applied at most once) leader-reliability-trait / 1000 + define:MIL_WAR_EXHAUSTION x
1976 national-war-exhaustion x (sum of support-for-each-issue x issues-war-exhaustion-effect) / 100.0
1977 + (for pops not in colonies) pops-social-issue-support x define:MIL_REQUIRE_REFORM
1978 + (for pops not in colonies) pops-political-issue-support x define:MIL_REQUIRE_REFORM
1979 + (for pops overseas) define:alice_overseas_mil x effective-overseas-spending-level - 0.5
1980 + (Nation's war exhaustion x 0.005)
1981 */
1982
1983 auto const conservatism_key = pop_demographics::to_key(state, state.culture_definitions.conservative);
1984
1985 execute_staggered_blocks(offset, divisions, state.world.pop_size(), [&](auto ids) {
1986 auto loc = state.world.pop_get_province_from_pop_location(ids);
1987 auto owner = state.world.province_get_nation_from_province_ownership(loc);
1988 auto ruling_party = state.world.nation_get_ruling_party(owner);
1989 auto ruling_ideology = state.world.political_party_get_ideology(ruling_party);
1990
1991 auto lx_mod = ve::max(pop_demographics::get_luxury_needs(state, ids) - 0.5f, 0.0f) * state.defines.mil_has_luxury_need;
1992 auto con_sup = (pop_demographics::get_demo(state, ids, conservatism_key) * state.defines.mil_ideology);
1993 auto ruling_sup = ve::apply(
1994 [&](dcon::pop_id p, dcon::ideology_id i) {
1995 return i ? pop_demographics::get_demo(state, p, pop_demographics::to_key(state, i)) * state.defines.mil_ruling_party
1996 : 0.0f;
1997 },
1998 ids, ruling_ideology);
1999 auto ref_mod = ve::select(state.world.province_get_is_colonial(loc), 0.0f,
2001 (state.defines.mil_require_reform * 0.25f));
2002
2003 auto o_spending = state.world.nation_get_overseas_penalty(owner);
2004 auto spending_level = state.world.nation_get_spending_level(owner);
2005 auto overseas_mil = ve::select(
2006 province::is_overseas(state, loc),
2007 (state.defines.alice_overseas_mil * 2.f)
2008 * (0.5f - (o_spending * spending_level)),
2009 0.f
2010 );
2011
2012 auto sub_t = (lx_mod + ruling_sup) + (con_sup + ref_mod);
2013
2014 auto pmod = state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::pop_militancy_modifier);
2015 auto omod = state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::global_pop_militancy_modifier);
2016 auto cmod = ve::select(state.world.province_get_is_colonial(loc), 0.0f,
2017 state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::core_pop_militancy_modifier));
2018
2019 auto local_mod = (pmod + omod) + cmod;
2020
2021 auto sep_mod = ve::select(state.world.pop_get_is_primary_or_accepted_culture(ids), 0.0f,
2022 (state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::non_accepted_pop_militancy_modifier) + 1.0f) *
2023 state.defines.mil_non_accepted);
2024 auto ln_mod = ve::min((pop_demographics::get_life_needs(state, ids) - 0.5f), 0.0f) * state.defines.mil_no_life_need;
2025 auto en_mod_a =
2026 ve::min(0.0f, (pop_demographics::get_everyday_needs(state, ids) - 0.5f)) * state.defines.mil_lack_everyday_need;
2027 auto en_mod_b =
2028 ve::max(0.0f, (pop_demographics::get_everyday_needs(state, ids) - 0.5f)) * state.defines.mil_has_everyday_need;
2029 //Ranges from +0.00 - +0.50 militancy monthly, 0 - 100 war exhaustion
2030 auto war_exhaustion = state.world.nation_get_war_exhaustion(owner) * state.defines.mil_war_exhaustion;
2031 auto old_mil = pop_demographics::get_militancy(state, ids);
2032
2034 ids,
2035 ve::min(
2036 ve::max(
2037 0.0f,
2038 ve::select(
2039 owner != dcon::nation_id{},
2040 (
2041 sub_t
2042 + (
2043 local_mod
2044 + old_mil * (1.f - state.defines.alice_militancy_decay)
2045 )
2046 + (
2047 (sep_mod - ln_mod)
2048 + (en_mod_b - en_mod_a)
2049 + (war_exhaustion + overseas_mil)
2050 )
2051 ),
2052 0.0f
2053 )
2054 ),
2055 10.0f
2056 )
2057 );
2058 });
2059}
2060
2061float get_estimated_mil_change(sys::state& state, dcon::pop_id ids) {
2062 auto const conservatism_key = pop_demographics::to_key(state, state.culture_definitions.conservative);
2063
2064 auto loc = state.world.pop_get_province_from_pop_location(ids);
2065 auto owner = state.world.province_get_nation_from_province_ownership(loc);
2066 auto ruling_party = state.world.nation_get_ruling_party(owner);
2067 auto ruling_ideology = state.world.political_party_get_ideology(ruling_party);
2068
2069 float lx_mod = std::max(pop_demographics::get_luxury_needs(state, ids) - 0.5f, 0.0f) * state.defines.mil_has_luxury_need;
2070 float con_sup = (pop_demographics::get_demo(state, ids, conservatism_key) * state.defines.mil_ideology);
2071 float ruling_sup = ruling_ideology
2072 ? pop_demographics::get_demo(state, ids, pop_demographics::to_key(state, ruling_ideology)) * state.defines.mil_ruling_party
2073 : 0.0f;
2074 float ref_mod = state.world.province_get_is_colonial(loc) ? 0.0f :
2076 (state.defines.mil_require_reform * 0.25f);
2077
2078 auto o_spending = state.world.nation_get_overseas_penalty(owner);
2079 auto spending_level = state.world.nation_get_spending_level(owner);
2080 auto overseas_mil = ve::select(
2081 province::is_overseas(state, loc),
2082 (state.defines.alice_overseas_mil * 2.f)
2083 * (0.5f - (o_spending * spending_level)),
2084 0.f
2085 );
2086
2087 float sub_t = (lx_mod + ruling_sup) + (con_sup + ref_mod);
2088
2089 float pmod = state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::pop_militancy_modifier);
2090 float omod = state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::global_pop_militancy_modifier);
2091 float cmod = ve::select(state.world.province_get_is_colonial(loc), 0.0f,
2092 state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::core_pop_militancy_modifier));
2093
2094 float local_mod = (pmod + omod) + cmod;
2095
2096 float sep_mod = ve::select(state.world.pop_get_is_primary_or_accepted_culture(ids), 0.0f,
2097 (state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::non_accepted_pop_militancy_modifier) + 1.0f) *
2098 state.defines.mil_non_accepted);
2099 float ln_mod = std::min((pop_demographics::get_life_needs(state, ids) - 0.5f), 0.0f) * state.defines.mil_no_life_need;
2100 float en_mod_a =
2101 std::min(0.0f, (pop_demographics::get_everyday_needs(state, ids) - 0.5f)) * state.defines.mil_lack_everyday_need;
2102 float en_mod_b =
2103 std::max(0.0f, (pop_demographics::get_everyday_needs(state, ids) - 0.5f)) * state.defines.mil_has_everyday_need;
2104 float war_exhaustion =
2105 state.world.nation_get_war_exhaustion(owner) * 0.005f;
2106 auto old_mil = pop_demographics::get_militancy(state, ids);
2107
2108 return (sub_t + local_mod) + ((sep_mod - ln_mod) + (en_mod_b - en_mod_a) + (war_exhaustion + overseas_mil)) - old_mil * state.defines.alice_militancy_decay;
2109}
2110
2111float get_estimated_mil_change(sys::state& state, dcon::nation_id n) {
2112 float sum = 0.0f;
2113 for(auto prov : dcon::fatten(state.world, n).get_province_ownership()) {
2114 for(auto pop : prov.get_province().get_pop_location()) {
2115 sum += pop.get_pop().get_size() * get_estimated_mil_change(state, pop.get_pop());
2116 }
2117 }
2118 auto t = state.world.nation_get_demographics(n, demographics::total);
2119 return t != 0.f ? sum / t : 0.f;
2120}
2121
2122void update_consciousness(sys::state& state, uint32_t offset, uint32_t divisions) {
2123 // local consciousness modifier = province-pop-consciousness-modifier + national-pop-consciousness-modifier +
2124 // national-core-pop-consciousness-modifier (in non-colonial states)
2125 /*
2126 the daily change in consciousness is:
2127 (pop-luxury-needs-satisfaction x define:CON_LUXURY_GOODS
2128 + define:CON_POOR_CLERGY or define:CON_MIDRICH_CLERGY x clergy-fraction-in-province
2129 + national-plurality x 0v((national-literacy-consciousness-impact-modifier + 1) x define:CON_LITERACY x pop-literacy)) x
2130 define:CON_COLONIAL_FACTOR if colonial
2131 + national-non-accepted-pop-consciousness-modifier (if not a primary or accepted culture)
2132 + local consciousnesses modifier
2133 */
2134
2135 auto const clergy_key = demographics::to_key(state, state.culture_definitions.clergy);
2136
2137 execute_staggered_blocks(offset, divisions, state.world.pop_size(), [&](auto ids) {
2138 auto loc = state.world.pop_get_province_from_pop_location(ids);
2139 auto owner = state.world.province_get_nation_from_province_ownership(loc);
2140 auto cfrac =
2141 state.world.province_get_demographics(loc, clergy_key) / state.world.province_get_demographics(loc, demographics::total);
2142 auto types = state.world.pop_get_poptype(ids);
2143
2144 auto lx_mod = pop_demographics::get_luxury_needs(state, ids) * state.defines.con_luxury_goods;
2145 auto cl_mod = cfrac * ve::select(state.world.pop_type_get_strata(types) == int32_t(culture::pop_strata::poor),
2146 ve::fp_vector{state.defines.con_poor_clergy}, ve::fp_vector{state.defines.con_midrich_clergy});
2147 auto lit_mod = ((state.world.nation_get_plurality(owner) / 10.0f) * (state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::literacy_con_impact) + 1.0f) *
2148 state.defines.con_literacy * pop_demographics::get_literacy(state, ids) * ve::select(state.world.province_get_is_colonial(loc), ve::fp_vector{state.defines.con_colonial_factor}, 1.0f)) / 10.f;
2149
2150 auto pmod = state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::pop_consciousness_modifier);
2151 auto omod = state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::global_pop_consciousness_modifier);
2152 auto cmod = ve::select(state.world.province_get_is_colonial(loc), 0.0f,
2153 state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::core_pop_consciousness_modifier));
2154
2155 auto local_mod = (pmod + omod) + cmod;
2156
2157 auto sep_mod = ve::select(state.world.pop_get_is_primary_or_accepted_culture(ids), 0.0f,
2158 state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::non_accepted_pop_consciousness_modifier));
2159
2160 auto old_con = pop_demographics::get_consciousness(state, ids);
2161
2163 ve::min(ve::max(ve::select(owner != dcon::nation_id{}, ((old_con * 0.99f + lx_mod) + (cl_mod + lit_mod)) + (local_mod + sep_mod), 0.0f), 0.0f), 10.f));
2164 });
2165}
2166
2167float get_estimated_con_change(sys::state& state, dcon::pop_id ids) {
2168 auto const clergy_key = demographics::to_key(state, state.culture_definitions.clergy);
2169
2170 auto loc = state.world.pop_get_province_from_pop_location(ids);
2171 auto owner = state.world.province_get_nation_from_province_ownership(loc);
2172 float cfrac =
2173 state.world.province_get_demographics(loc, clergy_key) / state.world.province_get_demographics(loc, demographics::total);
2174 auto types = state.world.pop_get_poptype(ids);
2175
2176 float lx_mod = pop_demographics::get_luxury_needs(state, ids) * state.defines.con_luxury_goods;
2177 float cl_mod = cfrac * ve::select(state.world.pop_type_get_strata(types) == int32_t(culture::pop_strata::poor),
2178 state.defines.con_poor_clergy, state.defines.con_midrich_clergy);
2179 float lit_mod = ((state.world.nation_get_plurality(owner) / 10.0f) *
2180 (state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::literacy_con_impact) + 1.0f) *
2181 state.defines.con_literacy * pop_demographics::get_literacy(state, ids) *
2182 ve::select(state.world.province_get_is_colonial(loc), state.defines.con_colonial_factor, 1.0f)) / 10.f;
2183
2184 float pmod = state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::pop_consciousness_modifier);
2185 float omod = state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::global_pop_consciousness_modifier);
2186 float cmod = ve::select(state.world.province_get_is_colonial(loc), 0.0f,
2187 state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::core_pop_consciousness_modifier));
2188
2189 float local_mod = (pmod + omod) + cmod;
2190
2191 float sep_mod = ve::select(state.world.pop_get_is_primary_or_accepted_culture(ids), 0.0f,
2192 state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::non_accepted_pop_consciousness_modifier));
2193 auto old_con = pop_demographics::get_consciousness(state, ids);
2194
2195 return (lx_mod + (cl_mod + lit_mod)) + (local_mod + sep_mod) - old_con * 0.01f;
2196}
2197
2198float get_estimated_con_change(sys::state& state, dcon::nation_id n) {
2199 float sum = 0.0f;
2200 for(auto prov : dcon::fatten(state.world, n).get_province_ownership()) {
2201 for(auto pop : prov.get_province().get_pop_location()) {
2202 sum += pop.get_pop().get_size() * get_estimated_con_change(state, pop.get_pop());
2203 }
2204 }
2205 auto t = state.world.nation_get_demographics(n, demographics::total);
2206 return t != 0.f ? sum / t : 0.f;
2207}
2208
2209
2210void update_literacy(sys::state& state, uint32_t offset, uint32_t divisions) {
2211 /*
2212 the literacy of each pop changes by:
2213 0.01
2214 x define:LITERACY_CHANGE_SPEED
2215 x (0.5 + 0.5 * education-spending)
2216 x ((total-province-clergy-population / total-province-population - define:BASE_CLERGY_FOR_LITERACY) /
2217 (define:MAX_CLERGY_FOR_LITERACY
2218 - define:BASE_CLERGY_FOR_LITERACY))^1 x (national-modifier-to-education-efficiency + 1.0) x (tech-education-efficiency + 1.0).
2219
2220 (by peter) additional multiplier to make getting/losing high literacy harder:
2221 change = change * (1 - current-literacy)
2222
2223 Literacy cannot drop below 0.01.
2224 */
2225
2226 auto const clergy_key = demographics::to_key(state, state.culture_definitions.clergy);
2227
2228 execute_staggered_blocks(offset, divisions, state.world.pop_size(), [&](auto ids) {
2229 auto loc = state.world.pop_get_province_from_pop_location(ids);
2230 auto owner = state.world.province_get_nation_from_province_ownership(loc);
2231 auto cfrac =
2232 state.world.province_get_demographics(loc, clergy_key) / state.world.province_get_demographics(loc, demographics::total);
2233
2234 auto tmod = state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::education_efficiency) + 1.0f;
2235 auto nmod = state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::education_efficiency_modifier) + 1.0f;
2236 auto espending = 0.5f +
2237 (ve::to_float(state.world.nation_get_education_spending(owner)) / 100.0f) * state.world.nation_get_spending_level(owner) * 0.5f;
2238 auto cmod = ve::max(
2239 0.0f,
2240 ve::min(
2241 1.0f,
2242 (cfrac - state.defines.base_clergy_for_literacy)
2243 / (state.defines.max_clergy_for_literacy - state.defines.base_clergy_for_literacy)
2244 )
2245 );
2246
2247 auto old_lit = pop_demographics::get_literacy(state, ids);
2248 auto new_lit = ve::min(
2249 ve::max(
2250 old_lit
2251 + (0.01f * state.defines.literacy_change_speed)
2252 * (
2253 (
2254 (espending * cmod)
2255 * (tmod * nmod)
2256 ) *
2257 (
2258 1.f - old_lit
2259 )
2260 ), 0.01f
2261 ), 1.0f);
2262
2263 pop_demographics::set_literacy(state, ids, ve::select(owner != dcon::nation_id{}, new_lit, old_lit));
2264 });
2265}
2266
2267float get_estimated_literacy_change(sys::state& state, dcon::pop_id ids) {
2268 auto const clergy_key = demographics::to_key(state, state.culture_definitions.clergy);
2269
2270 auto loc = state.world.pop_get_province_from_pop_location(ids);
2271 auto owner = state.world.province_get_nation_from_province_ownership(loc);
2272 auto cfrac =
2273 state.world.province_get_demographics(loc, clergy_key) / state.world.province_get_demographics(loc, demographics::total);
2274
2275 auto tmod = state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::education_efficiency) + 1.0f;
2276 auto nmod = state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::education_efficiency_modifier) + 1.0f;
2277 auto espending =
2278 (float(state.world.nation_get_education_spending(owner)) / 100.0f) * state.world.nation_get_spending_level(owner);
2279 auto cmod = std::max(0.0f, std::min(1.0f, (cfrac - state.defines.base_clergy_for_literacy) /
2280 (state.defines.max_clergy_for_literacy - state.defines.base_clergy_for_literacy)));
2281
2282 auto old_lit = pop_demographics::get_literacy(state, ids);
2283 auto new_lit = std::min(std::max(old_lit + (0.01f * state.defines.literacy_change_speed) * ((espending * cmod) * (tmod * nmod)), 0.01f), 1.0f);
2284
2285 return new_lit - old_lit;
2286}
2287
2288float get_estimated_literacy_change(sys::state& state, dcon::nation_id n) {
2289 float sum = 0.0f;
2290 for(auto prov : dcon::fatten(state.world, n).get_province_ownership()) {
2291 for(auto pop : prov.get_province().get_pop_location()) {
2292 sum += pop.get_pop().get_size() * get_estimated_literacy_change(state, pop.get_pop());
2293 }
2294 }
2295 auto t = state.world.nation_get_demographics(n, demographics::total);
2296 return t != 0.f ? sum / t : 0.f;
2297}
2298
2299void update_ideologies(sys::state& state, uint32_t offset, uint32_t divisions, ideology_buffer& ibuf) {
2300 /*
2301 For ideologies after their enable date (actual discovery / activation is irrelevant), and not restricted to civs only for pops
2302 in an unciv, the attraction modifier is computed *multiplicatively*. Then, these values are collectively normalized.
2303 */
2304
2305 auto new_pop_count = state.world.pop_size();
2306 ibuf.update(state, new_pop_count);
2307
2308 assert(state.world.ideology_size() <= 64);
2309
2310 // update
2311
2312 pexecute_staggered_blocks(offset, divisions, new_pop_count, [&](auto ids) {
2313 ve::fp_vector iopt_weights[64];
2314 ve::fp_vector ttotal = 0.0f;
2315
2316 state.world.for_each_ideology([&](dcon::ideology_id i) {
2317 if(!state.world.ideology_get_enabled(i)) {
2318 iopt_weights[i.index()] = 0.0f;
2319 } else {
2320 auto const i_key = pop_demographics::to_key(state, i);
2321 auto owner = nations::owner_of_pop(state, ids);
2322
2323 if(state.world.ideology_get_is_civilized_only(i)) {
2324 auto amount = ve::max(ve::fp_vector{}, ve::apply(
2325 [&](dcon::pop_id pid, dcon::pop_type_id ptid, dcon::nation_id o) {
2326 if(state.world.nation_get_is_civilized(o)) {
2327 if(auto mfn = state.world.pop_type_get_ideology_fns(ptid, i); mfn != 0) {
2328 using ftype = float(*)(int32_t);
2329 ftype fn = (ftype)mfn;
2330 float llvm_result = fn(pid.index());
2331#ifdef CHECK_LLVM_RESULTS
2332 float interp_result = 0.0f;
2333 if(auto mtrigger = state.world.pop_type_get_ideology(ptid, i); mtrigger) {
2334 interp_result = trigger::evaluate_multiplicative_modifier(state, mtrigger, trigger::to_generic(pid), trigger::to_generic(pid), 0);
2335 }
2336 assert(llvm_result == interp_result);
2337#endif
2338 return llvm_result;
2339 } else {
2340 auto ptrigger = state.world.pop_type_get_ideology(ptid, i);
2341 return ptrigger ? trigger::evaluate_multiplicative_modifier(state, ptrigger, trigger::to_generic(pid), trigger::to_generic(pid), 0) : 0.0f;
2342 }
2343 } else {
2344 return 0.0f;
2345 }
2346 }, ids, state.world.pop_get_poptype(ids), owner));
2347
2348 iopt_weights[i.index()] = amount;
2349 ttotal = ttotal + amount;
2350 } else {
2351 auto amount = ve::max(ve::fp_vector{}, ve::apply(
2352 [&](dcon::pop_id pid, dcon::pop_type_id ptid, dcon::nation_id o) {
2353 if(auto mfn = state.world.pop_type_get_ideology_fns(ptid, i); mfn != 0) {
2354 using ftype = float(*)(int32_t);
2355 ftype fn = (ftype)mfn;
2356 float llvm_result = fn(pid.index());
2357#ifdef CHECK_LLVM_RESULTS
2358 float interp_result = 0.0f;
2359 if(auto mtrigger = state.world.pop_type_get_ideology(ptid, i); mtrigger) {
2360 interp_result = trigger::evaluate_multiplicative_modifier(state, mtrigger, trigger::to_generic(pid), trigger::to_generic(pid), 0);
2361 }
2362 assert(llvm_result == interp_result);
2363#endif
2364 return llvm_result;
2365 } else {
2366 auto ptrigger = state.world.pop_type_get_ideology(ptid, i);
2367 return ptrigger ? trigger::evaluate_multiplicative_modifier(state, ptrigger, trigger::to_generic(pid), trigger::to_generic(pid), 0) : 0.0f;
2368 }
2369 }, ids, state.world.pop_get_poptype(ids), owner));
2370
2371 iopt_weights[i.index()] = amount;
2372 ttotal = ttotal + amount;
2373 }
2374 }
2375 });
2376
2377 if(state.network_mode == sys::network_mode_type::single_player) {
2378 ve::fp_vector max_weight{ 0.0f };
2379 ve::tagged_vector<dcon::ideology_id> preferred{};
2380
2381 state.world.for_each_ideology([&](dcon::ideology_id iid) {
2382 auto avalue = iopt_weights[iid.index()] / ttotal;
2383
2384 auto const i_key = pop_demographics::to_key(state, iid);
2385 auto current = pop_demographics::get_demo(state, ids, i_key);
2386
2387 auto new_weight = ve::select(ttotal > 0.0f, state.defines.alice_ideology_base_change_rate * avalue + (1.0f - state.defines.alice_ideology_base_change_rate) * current, current);
2388 auto new_max = new_weight > max_weight;
2389 preferred = ve::select(new_max, ve::tagged_vector<dcon::ideology_id>{iid}, preferred);
2390 max_weight = ve::select(new_max, new_weight, max_weight);
2391
2392 state.world.pop_set_udemographics(ids, i_key, pop_demographics::to_pu8(new_weight));
2393 });
2394
2395 state.world.pop_set_dominant_ideology(ids, preferred);
2396 } else {
2397 state.world.for_each_ideology([&](dcon::ideology_id iid) {
2398 auto avalue = iopt_weights[iid.index()] / ttotal;
2399
2400 auto const i_key = pop_demographics::to_key(state, iid);
2401 auto current = pop_demographics::get_demo(state, ids, i_key);
2402
2403 //pop_demographics::set_demo(state, ids, i_key,
2404 // ve::select(ttotal > 0.0f, state.defines.alice_ideology_base_change_rate * avalue + (1.0f - state.defines.alice_ideology_base_change_rate) * current, current));
2405
2406 ibuf.temp_buffers[iid].set(ids, pop_demographics::to_pu8(ve::select(ttotal > 0.0f,
2407 state.defines.alice_ideology_base_change_rate * avalue + (1.0f - state.defines.alice_ideology_base_change_rate) * current, current)));
2408
2409 });
2410 }
2411 });
2412}
2413
2414void apply_ideologies(sys::state& state, uint32_t offset, uint32_t divisions, ideology_buffer& pbuf) {
2415
2416 /*
2417 If the normalized value is greater than twice the pop's current support for the ideology: add 0.25 to the pop's current
2418 support for the ideology If the normalized value is greater than the pop's current support for the ideology: add 0.05 to the
2419 pop's current support for the ideology If the normalized value is greater than half the pop's current support for the
2420 ideology: do nothing Otherwise: subtract 0.25 from the pop's current support for the ideology (to a minimum of zero)
2421 */
2422
2423 if(state.network_mode == sys::network_mode_type::single_player)
2424 return;
2425
2426 state.world.for_each_ideology([&](dcon::ideology_id i) {
2427 if(state.world.ideology_get_enabled(i)) {
2428 auto const i_key = pop_demographics::to_key(state, i);
2429
2430 execute_staggered_blocks(offset, divisions, std::min(state.world.pop_size(), pbuf.size), [&](auto ids) {
2431 auto avalue = pbuf.temp_buffers[i].get(ids);// / ttotal;
2432 state.world.pop_set_udemographics(ids, i_key, avalue);
2433 });
2434 }
2435 });
2436}
2437
2438inline constexpr float issues_change_rate = 0.20f;
2439
2440void update_issues(sys::state& state, uint32_t offset, uint32_t divisions, issues_buffer& ibuf) {
2441 /*
2442 As with ideologies, the attraction modifier for each issue is computed *multiplicatively* and then are collectively
2443 normalized. Then we zero the attraction for any issue that is not currently possible (i.e. its trigger condition is not met or
2444 it is not the next/previous step for a next-step type issue, and for uncivs only the party issues are valid here)
2445 */
2446
2447 auto new_pop_count = state.world.pop_size();
2448 ibuf.update(state, new_pop_count);
2449
2450 // update
2451 assert(state.world.issue_option_size() <= 720);
2452
2453 pexecute_staggered_blocks(offset, divisions, new_pop_count, [&](auto ids) {
2454 ve::fp_vector iopt_weights[720];
2455 ve::fp_vector ttotal = 0.0f;
2456 auto owner = nations::owner_of_pop(state, ids);
2457
2458 state.world.for_each_issue_option([&](dcon::issue_option_id iid) {
2459 auto opt = fatten(state.world, iid);
2460 auto allow = opt.get_allow();
2461 auto parent_issue = opt.get_parent_issue();
2462 auto const i_key = pop_demographics::to_key(state, iid);
2463 auto is_party_issue = state.world.issue_get_issue_type(parent_issue) == uint8_t(culture::issue_type::party);
2464 auto is_social_issue = state.world.issue_get_issue_type(parent_issue) == uint8_t(culture::issue_type::social);
2465 auto is_political_issue = state.world.issue_get_issue_type(parent_issue) == uint8_t(culture::issue_type::political);
2466 auto has_modifier = is_social_issue || is_political_issue;
2467 auto modifier_key =
2468 is_social_issue ? sys::national_mod_offsets::social_reform_desire : sys::national_mod_offsets::political_reform_desire;
2469
2470 auto current_issue_setting = state.world.nation_get_issues(owner, parent_issue);
2471 auto allowed_by_owner =
2472 (state.world.nation_get_is_civilized(owner) || ve::mask_vector(is_party_issue))
2473 && (ve::mask_vector(!state.world.issue_get_is_next_step_only(parent_issue)) ||
2474 (ve::tagged_vector<int32_t>(current_issue_setting) == iid.index()) ||
2475 (ve::tagged_vector<int32_t>(current_issue_setting) == iid.index() - 1) ||
2476 (ve::tagged_vector<int32_t>(current_issue_setting) == iid.index() + 1));
2477 auto owner_modifier =
2478 has_modifier ? (state.world.nation_get_modifier_values(owner, modifier_key) + 1.0f) : ve::fp_vector(1.0f);
2479
2480 auto amount = ve::max(ve::fp_vector{}, owner_modifier * ve::select(allowed_by_owner,
2481 ve::apply([&](dcon::pop_id pid, dcon::pop_type_id ptid, dcon::nation_id o) {
2482 if(auto mfn = state.world.pop_type_get_issues_fns(ptid, iid); mfn != 0) {
2483 using ftype = float(*)(int32_t);
2484 ftype fn = (ftype)mfn;
2485 float llvm_result = fn(pid.index());
2486#ifdef CHECK_LLVM_RESULTS
2487 float interp_result = 0.0f;
2488 if(auto mtrigger = state.world.pop_type_get_issues(ptid, iid); mtrigger) {
2489 interp_result = trigger::evaluate_multiplicative_modifier(state, mtrigger, trigger::to_generic(pid), trigger::to_generic(pid), 0);
2490 }
2491 assert(llvm_result == interp_result);
2492#endif
2493 return llvm_result;
2494 } else {
2495 if(auto mtrigger = state.world.pop_type_get_issues(ptid, iid); mtrigger) {
2496 return trigger::evaluate_multiplicative_modifier(state, mtrigger, trigger::to_generic(pid), trigger::to_generic(pid), 0);
2497 } else {
2498 return 0.0f;
2499 }
2500 }
2501 }, ids, state.world.pop_get_poptype(ids), owner),
2502 0.0f));
2503
2504 iopt_weights[iid.index()] = amount;
2505 ttotal = ttotal + amount;
2506 });
2507
2508 if(state.network_mode == sys::network_mode_type::single_player) {
2509 ve::fp_vector max_weight{ 0.0f };
2510 ve::tagged_vector<dcon::issue_option_id> preferred{};
2511
2512 state.world.for_each_issue_option([&](dcon::issue_option_id iid) {
2513 auto avalue = iopt_weights[iid.index()] / ttotal;
2514
2515 auto const i_key = pop_demographics::to_key(state, iid);
2516 auto current = pop_demographics::get_demo(state, ids, i_key);
2517 auto owner_rate_modifier = ve::min(ve::max(state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::issue_change_speed) + 1.0f, 0.0f), 5.0f);
2518
2519 auto new_weight = ve::select(ttotal > 0.0f, issues_change_rate * owner_rate_modifier * avalue + (1.0f - issues_change_rate * owner_rate_modifier) * current, current);
2520 auto new_max = new_weight > max_weight;
2521 preferred = ve::select(new_max, ve::tagged_vector<dcon::issue_option_id>{iid}, preferred);
2522 max_weight = ve::select(new_max, new_weight, max_weight);
2523
2524 state.world.pop_set_udemographics(ids, i_key, pop_demographics::to_pu8(new_weight));
2525 });
2526
2527 state.world.pop_set_dominant_issue_option(ids, preferred);
2528 } else {
2529 state.world.for_each_issue_option([&](dcon::issue_option_id iid) {
2530 auto avalue = iopt_weights[iid.index()] / ttotal;
2531
2532 auto const i_key = pop_demographics::to_key(state, iid);
2533 auto current = pop_demographics::get_demo(state, ids, i_key);
2534 auto owner_rate_modifier = ve::min(ve::max(state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::issue_change_speed) + 1.0f, 0.0f), 5.0f);
2535
2536 ibuf.temp_buffers[iid].set(ids, pop_demographics::to_pu8(ve::select(ttotal > 0.0f,
2537 issues_change_rate * owner_rate_modifier * avalue + (1.0f - issues_change_rate * owner_rate_modifier) * current, current)));
2538 });
2539 }
2540 });
2541}
2542
2543void apply_issues(sys::state& state, uint32_t offset, uint32_t divisions, issues_buffer& pbuf) {
2544 /*
2545 Then, like with ideologies, we check how much the normalized attraction is above and below the current support, with a couple
2546 of differences. First, for political or social issues, we multiply the magnitude of the adjustment by
2547 (national-political-reform-desire-modifier + 1) or (national-social-reform-desire-modifier + 1) as appropriate. Secondly, the
2548 base magnitude of the change is either (national-issue-change-speed-modifier + 1.0) x 0.25 or
2549 (national-issue-change-speed-modifier + 1.0) x 0.05 (instead of a fixed 0.05 or 0.25). Finally, there is an additional "bin"
2550 at 5x more or less where the adjustment is a flat 1.0.
2551 */
2552
2553 if(state.network_mode == sys::network_mode_type::single_player)
2554 return;
2555
2556 state.world.for_each_issue_option([&](dcon::issue_option_id i) {
2557 auto const i_key = pop_demographics::to_key(state, i);
2558
2559 execute_staggered_blocks(offset, divisions, std::min(state.world.pop_size(), pbuf.size), [&](auto ids) {
2560 auto avalue = pbuf.temp_buffers[i].get(ids);// / ttotal;
2561 state.world.pop_set_udemographics(ids, i_key, avalue);
2562 });
2563 });
2564
2565}
2566
2567void update_growth(sys::state& state, uint32_t offset, uint32_t divisions) {
2568 /*
2569 Province pop-growth factor: Only owned provinces grow. To calculate the pop growth in a province: First, calculate the
2570 modified life rating of the province. This is done by taking the intrinsic life rating and then multiplying by (1 + the
2571 provincial modifier for life rating). The modified life rating is capped at 40. Take that value, if it is greater than
2572 define:MIN_LIFE_RATING_FOR_GROWTH, subtract define:MIN_LIFE_RATING_FOR_GROWTH from it, and then multiply by
2573 define:LIFE_RATING_GROWTH_BONUS. If it is less than define:MIN_LIFE_RATING_FOR_GROWTH, treat it as zero. Now, take that value
2574 and add it to define:BASE_POPGROWTH. This gives us the growth factor for the province.
2575
2576 The amount a pop grows is determine by first computing the growth modifier sum: (pop-life-needs -
2577 define:LIFE_NEED_STARVATION_LIMIT) x province-pop-growth-factor x 4 + province-growth-modifier + tech-pop-growth-modifier +
2578 national-growth-modifier x 0.1. Then divide that by define:SLAVE_GROWTH_DIVISOR if the pop is a slave, and multiply the pop's
2579 size to determine how much the pop grows by (growth is computed and applied during the pop's monthly tick).
2580 */
2581
2582 execute_staggered_blocks(offset, divisions, state.world.pop_size(), [&](auto ids) {
2583 auto loc = state.world.pop_get_province_from_pop_location(ids);
2584 auto owner = state.world.province_get_nation_from_province_ownership(loc);
2585
2586 auto base_life_rating = ve::to_float(state.world.province_get_life_rating(loc));
2587 auto mod_life_rating = ve::min(
2588 base_life_rating * (state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::life_rating) + 1.0f),
2589 40.0f);
2590 auto lr_factor =
2591 ve::max((mod_life_rating - state.defines.min_life_rating_for_growth) * state.defines.life_rating_growth_bonus, 0.0f);
2592 auto province_factor = lr_factor + state.defines.base_popgrowth;
2593
2594 auto ln_factor = pop_demographics::get_life_needs(state, ids) - state.defines.life_need_starvation_limit;
2595 auto mod_sum = state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::population_growth) + state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::pop_growth);
2596
2597 auto total_factor = ln_factor * province_factor * 4.0f + mod_sum * 0.1f;
2598 auto old_size = state.world.pop_get_size(ids);
2599 auto new_size = old_size * total_factor + old_size;
2600
2601 auto type = state.world.pop_get_poptype(ids);
2602
2603 state.world.pop_set_size(ids,
2604 ve::select((owner != dcon::nation_id{}) && (type != state.culture_definitions.slaves), new_size, old_size));
2605 });
2606}
2607
2608float get_monthly_pop_increase(sys::state& state, dcon::pop_id ids) {
2609 auto type = state.world.pop_get_poptype(ids);
2610 if(type == state.culture_definitions.slaves)
2611 return 0.0f;
2612
2613 auto loc = state.world.pop_get_province_from_pop_location(ids);
2614 auto owner = state.world.province_get_nation_from_province_ownership(loc);
2615
2616 auto base_life_rating = float(state.world.province_get_life_rating(loc));
2617 auto mod_life_rating = std::min(
2618 base_life_rating * (state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::life_rating) + 1.0f), 40.0f);
2619 auto lr_factor =
2620 std::max((mod_life_rating - state.defines.min_life_rating_for_growth) * state.defines.life_rating_growth_bonus, 0.0f);
2621 auto province_factor = lr_factor + state.defines.base_popgrowth;
2622
2623 auto ln_factor = pop_demographics::get_life_needs(state, ids) - state.defines.life_need_starvation_limit;
2624 auto mod_sum = state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::population_growth) + state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::pop_growth);
2625
2626 auto total_factor = ln_factor * province_factor * 4.0f + mod_sum * 0.1f;
2627 auto old_size = state.world.pop_get_size(ids);
2628
2629 return old_size * total_factor;
2630}
2631int64_t get_monthly_pop_increase(sys::state& state, dcon::nation_id n) {
2632 float t = 0.0f;
2633 for(auto prov : state.world.nation_get_province_ownership(n)) {
2634 for(auto pop : prov.get_province().get_pop_location()) {
2635 t += get_monthly_pop_increase(state, pop.get_pop());
2636 }
2637 }
2638 return int64_t(t);
2639}
2640
2641int64_t get_monthly_pop_increase(sys::state& state, dcon::state_instance_id n) {
2642 float t = 0.0f;
2643 province::for_each_province_in_state_instance(state, n, [&](dcon::province_id prov) {
2644 for(auto pop : state.world.province_get_pop_location(prov)) {
2645 t += get_monthly_pop_increase(state, pop.get_pop());
2646 }
2647 });
2648 return int64_t(t);
2649}
2650
2651int64_t get_monthly_pop_increase(sys::state& state, dcon::province_id n) {
2652 float t = 0.0f;
2653 for(auto pop : state.world.province_get_pop_location(n)) {
2654 t += get_monthly_pop_increase(state, pop.get_pop());
2655 }
2656 return int64_t(t);
2657}
2658
2659void update_type_changes(sys::state& state, uint32_t offset, uint32_t divisions, promotion_buffer& pbuf) {
2660 pbuf.update(state.world.pop_size());
2661
2662 /*
2663 Pops appear to "promote" into other pops of the same or greater strata. Likewise they "demote" into pops of the same or lesser
2664 strata. (Thus both promotion and demotion can move pops within the same strata?).
2665 */
2666
2667 pexecute_staggered_blocks(offset, divisions, state.world.pop_size(), [&](auto ids) {
2668 pbuf.amounts.set(ids, 0.0f);
2669 auto owners = nations::owner_of_pop(state, ids);
2670#ifdef CHECK_LLVM_RESULTS
2671 auto promotion_chances = trigger::evaluate_additive_modifier(state, state.culture_definitions.promotion_chance, trigger::to_generic(ids), trigger::to_generic(ids), 0);
2672 auto demotion_chances = trigger::evaluate_additive_modifier(state, state.culture_definitions.demotion_chance, trigger::to_generic(ids), trigger::to_generic(ids), 0);
2673#else
2674 ve::fp_vector promotion_chances;
2675 if(state.culture_definitions.promotion_chance_fn == 0)
2676 promotion_chances = trigger::evaluate_additive_modifier(state, state.culture_definitions.promotion_chance, trigger::to_generic(ids), trigger::to_generic(ids), 0);
2677 ve::fp_vector demotion_chances;
2678 if(state.culture_definitions.demotion_chance_fn == 0)
2679 demotion_chances = trigger::evaluate_additive_modifier(state, state.culture_definitions.demotion_chance, trigger::to_generic(ids), trigger::to_generic(ids), 0);
2680#endif
2681 ve::apply(
2682 [&](dcon::pop_id p, dcon::nation_id owner, float promotion_chance, float demotion_chance) {
2683 /*
2684 Promotion amount:
2685 Compute the promotion modifier *additively*. If it it non-positive, there is no promotion for the day. Otherwise,
2686 if there is a national focus to to a pop type present in the state and the pop in question could possibly promote
2687 into that type, add the national focus effect to the promotion modifier. Conversely, pops of the focused type, are
2688 not allowed to promote out. Then multiply this value by national-administrative-efficiency x
2689 define:PROMOTION_SCALE x pop-size to find out how many promote (although at least one person will promote per day
2690 if the result is positive).
2691
2692 Demotion amount:
2693 Compute the demotion modifier *additively*. If it it non-positive, there is no demotion for the day. Otherwise, if
2694 there is a national focus to to a pop type present in the state and the pop in question could possibly demote into
2695 that type, add the national focus effect to the demotion modifier. Then multiply this value by
2696 define:PROMOTION_SCALE x pop-size to find out how many demote (although at least one person will demote per day if
2697 the result is positive).
2698 */
2699
2700 if(!owner)
2701 return;
2702
2703 auto loc = state.world.pop_get_province_from_pop_location(p);
2704 auto si = state.world.province_get_state_membership(loc);
2705 auto nf = state.world.state_instance_get_owner_focus(si);
2706 auto promoted_type = state.world.national_focus_get_promotion_type(nf);
2707 auto promotion_bonus = state.world.national_focus_get_promotion_amount(nf);
2708 auto ptype = state.world.pop_get_poptype(p);
2709 auto strata = state.world.pop_type_get_strata(ptype);
2710
2711
2712 using ftypeb = float(*)(int32_t);
2713 if(state.culture_definitions.promotion_chance_fn) {
2714 ftypeb fn = (ftypeb)(state.culture_definitions.promotion_chance_fn);
2715 float llvm_result = fn(p.index());
2716#ifdef CHECK_LLVM_RESULTS
2717 assert(llvm_result == promotion_chance);
2718#endif
2719 promotion_chance = llvm_result;
2720 }
2721 if(state.culture_definitions.demotion_chance_fn) {
2722 ftypeb fn = (ftypeb)(state.culture_definitions.demotion_chance_fn);
2723 float llvm_result = fn(p.index());
2724#ifdef CHECK_LLVM_RESULTS
2725 assert(llvm_result == demotion_chance);
2726#endif
2727 demotion_chance = llvm_result;
2728 }
2729
2730 if(promoted_type) {
2731 if(promoted_type == ptype) {
2732 promotion_chance = 0.0f;
2733 } else if(state.world.pop_type_get_strata(promoted_type) >= strata) {
2734 promotion_chance += promotion_bonus;
2735 } else if(state.world.pop_type_get_strata(promoted_type) <= strata) {
2736 demotion_chance += promotion_bonus;
2737 }
2738 }
2739
2740 if(promotion_chance <= 0.0f && demotion_chance <= 0.0f)
2741 return; // skip this pop
2742
2743 float current_size = state.world.pop_get_size(p);
2744
2745 bool promoting = promotion_chance >= demotion_chance;
2746 float base_amount = promoting
2747 ? (std::ceil(promotion_chance * state.world.nation_get_administrative_efficiency(owner) * state.defines.promotion_scale * current_size))
2748 : (std::ceil(demotion_chance * state.defines.promotion_scale * current_size));
2749
2750 if(!promoting) {
2751 if(ptype == state.culture_definitions.artisans) {
2752 base_amount *= 10.f;
2753 }
2754 }
2755
2756 /*if(current_size < small_pop_size && base_amount > 0.0f) {
2757 pbuf.amounts.set(p, current_size);
2758 } else*/ if(base_amount >= 0.001f) {
2759 auto transfer_amount = std::min(current_size, base_amount);
2760 pbuf.amounts.set(p, transfer_amount);
2761 }
2762
2763 tagged_vector<float, dcon::pop_type_id> weights(state.world.pop_type_size());
2764
2765 /*
2766 The promotion and demotion factors seem to be computed additively (by taking the sum of all true conditions). If
2767 there is a national focus set towards a pop type in the state, that is also added into the chances to promote into
2768 that type. If the net weight for the boosted pop type is > 0, that pop type always seems to be selected as the
2769 promotion type. Otherwise, the type is chosen at random, proportionally to the weights. If promotion to farmer is
2770 selected for a mine province, or vice versa, it is treated as selecting laborer instead (or vice versa). This
2771 obviously has the effect of making those pop types even more likely than they otherwise would be.
2772
2773 As for demotion, there appear to an extra wrinkle. Pops do not appear to demote into pop types if there is more
2774 unemployment in that demotion target than in their current pop type. Otherwise, the national focus appears to have
2775 the same effect with respect to demotion.
2776 */
2777
2778 bool is_state_capital = state.world.state_instance_get_capital(state.world.province_get_state_membership(loc)) == loc;
2779
2780 if((promoting && promoted_type && state.world.pop_type_get_strata(promoted_type) >= strata && (is_state_capital || state.world.pop_type_get_state_capital_only(promoted_type) == false))
2781 || (!promoting && promoted_type && state.world.pop_type_get_strata(promoted_type) <= strata && (is_state_capital || state.world.pop_type_get_state_capital_only(promoted_type) == false))) {
2782
2783 float chance = 0.0f;
2784 if(auto mfn = state.world.pop_type_get_promotion_fns(ptype, promoted_type); mfn != 0) {
2785 using ftype = float(*)(int32_t);
2786 ftype fn = (ftype)mfn;
2787 float llvm_result = fn(p.index());
2788#ifdef CHECK_LLVM_RESULTS
2789 float interp_result = 0.0f;
2790 if(auto mtrigger = state.world.pop_type_get_promotion(ptype, promoted_type); mtrigger) {
2791 interp_result = trigger::evaluate_additive_modifier(state, mtrigger, trigger::to_generic(p), trigger::to_generic(p), 0);
2792 }
2793 assert(llvm_result == interp_result);
2794#endif
2795 chance = llvm_result + promotion_bonus;
2796 } else {
2797 if(auto mtrigger = state.world.pop_type_get_promotion(ptype, promoted_type); mtrigger) {
2798 chance = trigger::evaluate_additive_modifier(state, mtrigger, trigger::to_generic(p), trigger::to_generic(p), 0) + promotion_bonus;
2799 }
2800 }
2801
2802 if(chance > 0) {
2803 pbuf.types.set(p, promoted_type);
2804 return; // early exit
2805 }
2806 }
2807
2808 float chances_total = 0.0f;
2809 state.world.for_each_pop_type([&](dcon::pop_type_id target_type) {
2810 if(target_type == ptype) {
2811 weights[target_type] = 0.0f; //don't promote to the same type
2812 } else if(!is_state_capital && state.world.pop_type_get_state_capital_only(target_type)) {
2813 weights[target_type] = 0.0f; //don't promote if the pop is not in the state capital
2814 } else if((promoting && state.world.pop_type_get_strata(promoted_type) >= strata) //if the selected type is higher strata
2815 || (!promoting && state.world.pop_type_get_strata(promoted_type) <= strata) ) { //if the selected type is lower strata
2816
2817 weights[target_type] = 0.0f;
2818
2819 if(auto mfn = state.world.pop_type_get_promotion_fns(ptype, target_type); mfn != 0) {
2820 using ftype = float(*)(int32_t);
2821 ftype fn = (ftype)mfn;
2822 float llvm_result = fn(p.index());
2823#ifdef CHECK_LLVM_RESULTS
2824 float interp_result = 0.0f;
2825 if(auto mtrigger = state.world.pop_type_get_promotion(ptype, target_type); mtrigger) {
2826 interp_result = trigger::evaluate_additive_modifier(state, mtrigger, trigger::to_generic(p), trigger::to_generic(p), 0);
2827 }
2828 assert(llvm_result == interp_result);
2829#endif
2830 auto chance = llvm_result + (target_type == promoted_type ? promotion_bonus : 0.0f);
2831 chances_total += chance;
2832 weights[target_type] = chance;
2833 } else {
2834 if(auto mtrigger = state.world.pop_type_get_promotion(ptype, target_type); mtrigger) {
2835 auto chance = trigger::evaluate_additive_modifier(state, mtrigger, trigger::to_generic(p), trigger::to_generic(p), 0) + (target_type == promoted_type ? promotion_bonus : 0.0f);
2836 chances_total += chance;
2837 weights[target_type] = chance;
2838 }
2839 }
2840
2841 } else {
2842 weights[target_type] = 0.0f;
2843 }
2844 });
2845
2846 if(chances_total > 0.0f) {
2847 auto rvalue = float(rng::get_random(state, uint32_t(p.index())) & 0xFFFF) / float(0xFFFF + 1);
2848 for(uint32_t i = state.world.pop_type_size(); i-- > 0;) {
2849 dcon::pop_type_id pr{dcon::pop_type_id::value_base_t(i)};
2850 rvalue -= weights[pr] / chances_total;
2851 if(rvalue < 0.0f) {
2852 pbuf.types.set(p, pr);
2853 return;
2854 }
2855 }
2856 pbuf.amounts.set(p, 0.0f);
2857 pbuf.types.set(p, dcon::pop_type_id{});
2858 } else {
2859 pbuf.amounts.set(p, 0.0f);
2860 pbuf.types.set(p, dcon::pop_type_id{});
2861 }
2862 },
2863 ids, owners, promotion_chances, demotion_chances);
2864 });
2865}
2866
2867float get_effective_estimation_type_change(sys::state& state, dcon::nation_id nation, dcon::pop_type_id target_type) {
2868 float total_effective_change = .0f;
2869
2870 for(auto prov : state.world.nation_get_province_ownership(nation)) {
2871 for(auto pop : prov.get_province().get_pop_location()) {
2872
2873 auto promotion_chance = trigger::evaluate_additive_modifier(state, state.culture_definitions.promotion_chance,
2874 trigger::to_generic(pop.get_pop()), trigger::to_generic(pop.get_pop()), 0);
2875 auto demotion_chance = trigger::evaluate_additive_modifier(state, state.culture_definitions.demotion_chance,
2876 trigger::to_generic(pop.get_pop()), trigger::to_generic(pop.get_pop()), 0);
2877 auto owner = nation;
2878
2879 auto p = pop.get_pop();
2880
2881 auto loc = state.world.pop_get_province_from_pop_location(pop.get_pop());
2882 auto si = state.world.province_get_state_membership(loc);
2883 auto nf = state.world.state_instance_get_owner_focus(si);
2884 auto promoted_type = state.world.national_focus_get_promotion_type(nf);
2885 auto promotion_bonus = state.world.national_focus_get_promotion_amount(nf);
2886 auto ptype = state.world.pop_get_poptype(pop.get_pop());
2887 auto strata = state.world.pop_type_get_strata(ptype);
2888
2889 if(promoted_type) {
2890 if(promoted_type == ptype) {
2891 promotion_chance = 0.0f;
2892 } else if(state.world.pop_type_get_strata(promoted_type) >= strata) {
2893 promotion_chance += promotion_bonus;
2894 } else if(state.world.pop_type_get_strata(promoted_type) <= strata) {
2895 demotion_chance += promotion_bonus;
2896 }
2897 }
2898
2899 if(promotion_chance <= 0.0f && demotion_chance <= 0.0f)
2900 continue; // skip this pop
2901
2902 float current_size = state.world.pop_get_size(p);
2903
2904 bool promoting = promotion_chance >= demotion_chance;
2905 float base_amount = promoting
2906 ? (std::ceil(promotion_chance * state.world.nation_get_administrative_efficiency(nation) * state.defines.promotion_scale * current_size))
2907 : (std::ceil(demotion_chance * state.defines.promotion_scale * current_size));
2908
2909 auto transfer_amount = base_amount >= 0.001f ? std::min(current_size, base_amount) : 0.0f;
2910
2911 tagged_vector<float, dcon::pop_type_id> weights(state.world.pop_type_size());
2912
2913 bool is_state_capital = state.world.state_instance_get_capital(state.world.province_get_state_membership(loc)) == loc;
2914
2915 if(promoted_type == target_type) {
2916 if(promoting && promoted_type && state.world.pop_type_get_strata(promoted_type) >= strata &&
2917 (is_state_capital || state.world.pop_type_get_state_capital_only(promoted_type) == false)) {
2918 auto promote_mod = state.world.pop_type_get_promotion(ptype, promoted_type);
2919 if(promote_mod) {
2920 auto chance =
2922 promotion_bonus;
2923 if(chance > 0) {
2924 total_effective_change += transfer_amount;
2925 continue; // early exit
2926 }
2927 }
2928 } else if(!promoting && promoted_type && state.world.pop_type_get_strata(promoted_type) <= strata &&
2929 (is_state_capital || state.world.pop_type_get_state_capital_only(promoted_type) == false)) {
2930 auto promote_mod = state.world.pop_type_get_promotion(ptype, promoted_type);
2931 if(promote_mod) {
2932 auto chance =
2934 promotion_bonus;
2935 if(chance > 0) {
2936 total_effective_change += transfer_amount;
2937 continue; // early exit
2938 }
2939 }
2940 }
2941 }
2942
2943 float chances_total = 0.0f;
2944
2945 state.world.for_each_pop_type([&](dcon::pop_type_id t_type) {
2946 if(t_type == ptype) {
2947 weights[t_type] = 0.0f; //don't promote to the same type
2948 } else if(!is_state_capital && state.world.pop_type_get_state_capital_only(t_type)) {
2949 weights[t_type] = 0.0f; //don't promote if the pop is not in the state capital
2950 } else if(promoting && state.world.pop_type_get_strata(promoted_type) >= strata) { //if the selected type is higher strata
2951 auto promote_mod = state.world.pop_type_get_promotion(ptype, t_type);
2952 if(promote_mod) {
2953 auto chance = std::max(trigger::evaluate_additive_modifier(state, promote_mod, trigger::to_generic(p),
2954 trigger::to_generic(p), 0) +
2955 (t_type == promoted_type ? promotion_bonus : 0.0f),
2956 0.0f);
2957 chances_total += chance;
2958 weights[t_type] = chance;
2959 } else {
2960 weights[t_type] = 0.0f;
2961 }
2962 } else if(!promoting && state.world.pop_type_get_strata(promoted_type) <= strata) { //if the selected type is lower strata
2963 auto promote_mod = state.world.pop_type_get_promotion(ptype, t_type);
2964 if(promote_mod) {
2965 auto chance = std::max(trigger::evaluate_additive_modifier(state, promote_mod, trigger::to_generic(p),
2966 trigger::to_generic(p), 0) +
2967 (t_type == promoted_type ? promotion_bonus : 0.0f),
2968 0.0f);
2969 chances_total += chance;
2970 weights[t_type] = chance;
2971 } else {
2972 weights[t_type] = 0.0f;
2973 }
2974 } else {
2975 weights[t_type] = 0.0f;
2976 }
2977 });
2978
2979 if(chances_total > 0.0f) {
2980 total_effective_change += transfer_amount * weights[target_type]/chances_total;
2981 }
2982 }
2983 }
2984
2985 //subtract the amount of target_pops that will get promoted / demoted / emmigrated and take in account the growth
2986 for(auto prov : state.world.nation_get_province_ownership(nation)) {
2987 for(auto pop : prov.get_province().get_pop_location()) {
2988 if(pop.get_pop().get_poptype() == target_type) {
2989 total_effective_change -= get_estimated_type_change(state, pop.get_pop());
2990 total_effective_change += get_monthly_pop_increase(state, pop.get_pop());
2991 total_effective_change -= get_estimated_emigration(state, pop.get_pop());
2992 }
2993 }
2994 }
2995 return total_effective_change;
2996}
2997
2998float get_estimated_type_change(sys::state& state, dcon::pop_id ids) {
2999 auto owner = nations::owner_of_pop(state, ids);
3000 auto promotion_chance = trigger::evaluate_additive_modifier(state, state.culture_definitions.promotion_chance,
3002 auto demotion_chance = trigger::evaluate_additive_modifier(state, state.culture_definitions.demotion_chance,
3004
3005 auto loc = state.world.pop_get_province_from_pop_location(ids);
3006 auto si = state.world.province_get_state_membership(loc);
3007 auto nf = state.world.state_instance_get_owner_focus(si);
3008 auto promoted_type = state.world.national_focus_get_promotion_type(nf);
3009 auto promotion_bonus = state.world.national_focus_get_promotion_amount(nf);
3010 auto ptype = state.world.pop_get_poptype(ids);
3011 auto strata = state.world.pop_type_get_strata(ptype);
3012
3013 if(promoted_type) {
3014 if(promoted_type == ptype) {
3015 promotion_chance = 0.0f;
3016 } else if(state.world.pop_type_get_strata(promoted_type) >= strata) {
3017 promotion_chance += promotion_bonus;
3018 } else if(state.world.pop_type_get_strata(promoted_type) <= strata) {
3019 demotion_chance += promotion_bonus;
3020 }
3021 }
3022
3023 if(promotion_chance <= 0.0f && demotion_chance <= 0.0f)
3024 return 0.0f; // skip this pop
3025
3026 float current_size = state.world.pop_get_size(ids);
3027
3028 bool promoting = promotion_chance >= demotion_chance;
3029 return std::min(current_size, promoting
3030 ? (std::ceil(promotion_chance * state.world.nation_get_administrative_efficiency(owner) *
3031 state.defines.promotion_scale * current_size))
3032 : (std::ceil(demotion_chance * state.defines.promotion_scale * current_size)));
3033}
3034
3035float get_estimated_promotion(sys::state& state, dcon::pop_id ids) {
3036 auto owner = nations::owner_of_pop(state, ids);
3037 auto promotion_chance = trigger::evaluate_additive_modifier(state, state.culture_definitions.promotion_chance,
3039 auto demotion_chance = trigger::evaluate_additive_modifier(state, state.culture_definitions.demotion_chance,
3041
3042 auto loc = state.world.pop_get_province_from_pop_location(ids);
3043 auto si = state.world.province_get_state_membership(loc);
3044 auto nf = state.world.state_instance_get_owner_focus(si);
3045 auto promoted_type = state.world.national_focus_get_promotion_type(nf);
3046 auto promotion_bonus = state.world.national_focus_get_promotion_amount(nf);
3047 auto ptype = state.world.pop_get_poptype(ids);
3048 auto strata = state.world.pop_type_get_strata(ptype);
3049
3050 if(promoted_type) {
3051 if(promoted_type == ptype) {
3052 promotion_chance = 0.0f;
3053 } else if(state.world.pop_type_get_strata(promoted_type) >= strata) {
3054 promotion_chance += promotion_bonus;
3055 } else if(state.world.pop_type_get_strata(promoted_type) <= strata) {
3056 demotion_chance += promotion_bonus;
3057 }
3058 }
3059
3060 if(promotion_chance <= 0.0f && demotion_chance <= 0.0f)
3061 return 0.0f; // skip this pop
3062
3063 float current_size = state.world.pop_get_size(ids);
3064
3065 bool promoting = promotion_chance >= demotion_chance;
3066 return std::min(current_size, promoting
3067 ? (std::ceil(promotion_chance * state.world.nation_get_administrative_efficiency(owner) *
3068 state.defines.promotion_scale * current_size))
3069 : 0.0f);
3070}
3071float get_estimated_demotion(sys::state& state, dcon::pop_id ids) {
3072 auto owner = nations::owner_of_pop(state, ids);
3073 auto promotion_chance = trigger::evaluate_additive_modifier(state, state.culture_definitions.promotion_chance,
3075 auto demotion_chance = trigger::evaluate_additive_modifier(state, state.culture_definitions.demotion_chance,
3077
3078 auto loc = state.world.pop_get_province_from_pop_location(ids);
3079 auto si = state.world.province_get_state_membership(loc);
3080 auto nf = state.world.state_instance_get_owner_focus(si);
3081 auto promoted_type = state.world.national_focus_get_promotion_type(nf);
3082 auto promotion_bonus = state.world.national_focus_get_promotion_amount(nf);
3083 auto ptype = state.world.pop_get_poptype(ids);
3084 auto strata = state.world.pop_type_get_strata(ptype);
3085
3086 if(promoted_type) {
3087 if(promoted_type == ptype) {
3088 promotion_chance = 0.0f;
3089 } else if(state.world.pop_type_get_strata(promoted_type) >= strata) {
3090 promotion_chance += promotion_bonus;
3091 } else if(state.world.pop_type_get_strata(promoted_type) <= strata) {
3092 demotion_chance += promotion_bonus;
3093 }
3094 }
3095
3096 if(promotion_chance <= 0.0f && demotion_chance <= 0.0f)
3097 return 0.0f; // skip this pop
3098
3099 float current_size = state.world.pop_get_size(ids);
3100
3101 bool promoting = promotion_chance >= demotion_chance;
3102 return std::min(current_size, promoting
3103 ? 0.0f
3104 : (std::ceil(demotion_chance * state.defines.promotion_scale * current_size)));
3105}
3106
3108 pbuf.update(state.world.pop_size());
3109
3110 /*
3111 - cultural assimilation -- For a pop to assimilate, there must be a pop of the same strata of either a primary culture
3112 (preferred) or accepted culture in the province to assimilate into. (schombert notes: not sure if it is worthwhile preserving
3113 this limitation)
3114 */
3115
3116 pexecute_staggered_blocks(offset, divisions, state.world.pop_size(), [&](auto ids) {
3117 pbuf.amounts.set(ids, 0.0f);
3118 auto loc = state.world.pop_get_province_from_pop_location(ids);
3119 auto owners = state.world.province_get_nation_from_province_ownership(loc);
3120 auto assimilation_chances = ve::max(trigger::evaluate_additive_modifier(state, state.culture_definitions.assimilation_chance, trigger::to_generic(ids), trigger::to_generic(ids), 0), 0.0f);
3121
3122 ve::apply(
3123 [&](dcon::pop_id p, dcon::province_id location, dcon::nation_id owner, float assimilation_chance) {
3124 // no assimilation in unowned provinces
3125 if(!owner)
3126 return; // early exit
3127
3128 // slaves do not assimilate
3129 if(state.world.pop_get_poptype(p) == state.culture_definitions.slaves)
3130 return; // early exit
3131
3132 // pops of an accepted culture do not assimilate
3133 if(state.world.pop_get_is_primary_or_accepted_culture(p))
3134 return; // early exit
3135
3136 // pops in an overseas and colonial province do not assimilate
3137 if(state.world.province_get_is_colonial(location) && province::is_overseas(state, location))
3138 return; // early exit
3139
3140 if(state.world.province_get_dominant_culture(location) == state.world.pop_get_culture(p))
3141 return;
3142
3143 /*
3144 Amount: define:ASSIMILATION_SCALE x (provincial-assimilation-rate-modifier + 1) x
3145 (national-assimilation-rate-modifier + 1) x pop-size x assimilation chance factor (computed additively, and always
3146 at least 0.01).
3147 */
3148
3149 float current_size = state.world.pop_get_size(p);
3150 float base_amount =
3151 state.defines.assimilation_scale *
3152 std::max(0.0f, (state.world.province_get_modifier_values(location, sys::provincial_mod_offsets::assimilation_rate) + 1.0f)) *
3153 std::max(0.0f, (state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::global_assimilation_rate) + 1.0f)) *
3154 assimilation_chance * current_size;
3155
3156 /*
3157 In a colonial province, assimilation numbers for pops with an *non* "overseas"-type culture group are reduced by a
3158 factor of 100. In a non-colonial province, assimilation numbers for pops with an *non* "overseas"-type culture
3159 group are reduced by a factor of 10.
3160 */
3161
3162 auto pc = state.world.pop_get_culture(p);
3163
3164 if(!state.world.culture_group_get_is_overseas(state.world.culture_get_group_from_culture_group_membership(pc))) {
3165 base_amount /= 10.0f;
3166 }
3167
3168 /*
3169 All pops have their assimilation numbers reduced by a factor of 100 per core in the province sharing their primary
3170 culture.
3171 */
3172
3173 for(auto core : state.world.province_get_core(location)) {
3174 if(core.get_identity().get_primary_culture() == pc) {
3175 base_amount /= 100.0f;
3176 }
3177 }
3178
3179 /*
3180 If the pop size is less than 100 or thereabouts, they seem to get all assimilated if there is any assimilation.
3181 */
3182
3183 /*if(current_size < small_pop_size && base_amount >= 0.001f) {
3184 pbuf.amounts.set(p, current_size);
3185 } else*/ if(base_amount >= 0.001f) {
3186 auto transfer_amount = std::min(current_size, std::ceil(base_amount));
3187 pbuf.amounts.set(p, transfer_amount);
3188 }
3189 },
3190 ids, loc, owners, assimilation_chances);
3191 });
3192}
3193
3194float get_estimated_assimilation(sys::state& state, dcon::pop_id ids) {
3195 auto location = state.world.pop_get_province_from_pop_location(ids);
3196 auto owner = state.world.province_get_nation_from_province_ownership(location);
3197 auto assimilation_chances = std::max(trigger::evaluate_additive_modifier(state, state.culture_definitions.assimilation_chance, trigger::to_generic(ids), trigger::to_generic(ids), 0), 0.0f);
3198
3199 // slaves do not assimilate
3200 if(state.world.pop_get_poptype(ids) == state.culture_definitions.slaves)
3201 return 0.0f; // early exit
3202
3203 // pops of an accepted culture do not assimilate
3204 if(state.world.pop_get_is_primary_or_accepted_culture(ids))
3205 return 0.0f; // early exit
3206
3207 // pops in an overseas and colonial province do not assimilate
3208 if(state.world.province_get_is_colonial(location) && province::is_overseas(state, location))
3209 return 0.0f; // early exit
3210
3211 float current_size = state.world.pop_get_size(ids);
3212 float base_amount =
3213 state.defines.assimilation_scale *
3214 std::max(0.0f, (state.world.province_get_modifier_values(location, sys::provincial_mod_offsets::assimilation_rate) + 1.0f)) *
3215 std::max(0.0f, (state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::global_assimilation_rate) + 1.0f)) *
3216 assimilation_chances * current_size;
3217
3218 /*
3219 In a colonial province, assimilation numbers for pops with an *non* "overseas"-type culture group are reduced by a
3220 factor of 100. In a non-colonial province, assimilation numbers for pops with an *non* "overseas"-type culture
3221 group are reduced by a factor of 10.
3222 */
3223
3224 auto pc = state.world.pop_get_culture(ids);
3225 if(!state.world.culture_group_get_is_overseas(state.world.culture_get_group_from_culture_group_membership(pc))) {
3226 base_amount /= 10.0f;
3227 }
3228
3229
3230 /*
3231 All pops have their assimilation numbers reduced by a factor of 100 per core in the province sharing their primary
3232 culture.
3233 */
3234
3235 for(auto core : state.world.province_get_core(location)) {
3236 if(core.get_identity().get_primary_culture() == pc) {
3237 base_amount /= 100.0f;
3238 }
3239 }
3240
3241 /*
3242 If the pop size is less than 100 or thereabouts, they seem to get all assimilated if there is any assimilation.
3243 */
3244
3245 /*if(current_size < 100.0f && base_amount >= 0.001f) {
3246 return current_size;
3247 } else*/ if(base_amount >= 0.001f) {
3248 return std::min(current_size, std::ceil(base_amount));
3249 } else {
3250 return 0.0f;
3251 }
3252}
3253
3254namespace impl {
3255dcon::province_id get_province_target_in_nation(sys::state& state, dcon::nation_id n, dcon::pop_id p) {
3256 /*
3257 Destination for internal migration: colonial provinces are not valid targets, nor are non state capital provinces for pop
3258 types restricted to capitals. Valid provinces are weighted according to the product of the factors, times the value of the
3259 immigration focus
3260 + 1.0 if it is present, times the provinces immigration attractiveness modifier + 1.0. The pop is then distributed more or
3261 less evenly over those provinces with positive attractiveness in proportion to their attractiveness, or dumped somewhere at
3262 random if no provinces are attractive.
3263 */
3264 auto weights_buffer = state.world.province_make_vectorizable_float_buffer();
3265 float total_weight = 0.0f;
3266
3267 auto pt = state.world.pop_get_poptype(p);
3268 auto modifier = state.world.pop_type_get_migration_target(pt);
3269 auto modifier_fn = state.world.pop_type_get_migration_target_fn(pt);
3270 if(!modifier)
3271 return dcon::province_id{};
3272
3273 bool limit_to_capitals = state.world.pop_type_get_state_capital_only(pt);
3274 for(auto loc : state.world.nation_get_province_ownership(n)) {
3275 if(loc.get_province().get_is_colonial() == false) {
3276 if(!limit_to_capitals || loc.get_province().get_state_membership().get_capital().id == loc.get_province().id) {
3277 float weight = 0.0f;
3278 if(modifier_fn) {
3279 using ftype = float(*)(int32_t, int32_t);
3280 ftype fn = (ftype)modifier_fn;
3281 float llvm_result = fn(loc.get_province().id.index(), p.index());
3282#ifdef CHECK_LLVM_RESULTS
3283 float interp_result = trigger::evaluate_multiplicative_modifier(state, modifier, trigger::to_generic(loc.get_province().id), trigger::to_generic(p), 0);
3284 assert(llvm_result == interp_result);
3285#endif
3286 weight = std::max(0.0f, llvm_result * (loc.get_province().get_modifier_values(sys::provincial_mod_offsets::immigrant_attract) + 1.0f));
3287 } else {
3288 float interp_result = trigger::evaluate_multiplicative_modifier(state, modifier, trigger::to_generic(loc.get_province().id), trigger::to_generic(p), 0);
3289 weight = std::max(0.0f, interp_result * (loc.get_province().get_modifier_values(sys::provincial_mod_offsets::immigrant_attract) + 1.0f));
3290 }
3291
3292 if(weight > 0.0f) {
3293 weights_buffer.set(loc.get_province(), weight);
3294 total_weight += weight;
3295 }
3296 }
3297 }
3298 }
3299
3300 if(total_weight <= 0.0f)
3301 return dcon::province_id{};
3302
3303 auto rvalue = float(rng::get_random(state, (uint32_t(p.index()) << 2) | uint32_t(1)) & 0xFFFF) / float(0xFFFF + 1);
3304 for(auto loc : state.world.nation_get_province_ownership(n)) {
3305 rvalue -= weights_buffer.get(loc.get_province()) / total_weight;
3306 if(rvalue < 0.0f) {
3307 return loc.get_province();
3308 }
3309 }
3310
3311 return dcon::province_id{};
3312}
3313dcon::province_id get_colonial_province_target_in_nation(sys::state& state, dcon::nation_id n, dcon::pop_id p) {
3314 /*
3315 *only* colonial provinces are valid targets, and pops belonging to cultures with "overseas" = false set will not colonially
3316 *migrate outside the same continent. The same trigger seems to be used as internal migration for weighting the colonial
3317 *provinces.
3318 */
3319 auto weights_buffer = state.world.province_make_vectorizable_float_buffer();
3320 float total_weight = 0.0f;
3321
3322 auto modifier = state.world.pop_type_get_migration_target(state.world.pop_get_poptype(p));
3323 auto modifier_fn = state.world.pop_type_get_migration_target_fn(state.world.pop_get_poptype(p));
3324 if(!modifier)
3325 return dcon::province_id{};
3326
3327 auto overseas_culture = state.world.culture_get_group_from_culture_group_membership(state.world.pop_get_culture(p));
3328 auto home_continent = state.world.province_get_continent(state.world.pop_get_province_from_pop_location(p));
3329
3330 bool limit_to_capitals = state.world.pop_type_get_state_capital_only(state.world.pop_get_poptype(p));
3331 for(auto loc : state.world.nation_get_province_ownership(n)) {
3332 if(loc.get_province().get_is_colonial() == true) {
3333 if((overseas_culture || loc.get_province().get_continent() == home_continent) &&
3334 (!limit_to_capitals || loc.get_province().get_state_membership().get_capital().id == loc.get_province().id)) {
3335
3336 float weight = 0.0f;
3337 if(modifier_fn) {
3338 using ftype = float(*)(int32_t, int32_t);
3339 ftype fn = (ftype)modifier_fn;
3340 float llvm_result = fn(loc.get_province().id.index(), p.index());
3341#ifdef CHECK_LLVM_RESULTS
3342 float interp_result = trigger::evaluate_multiplicative_modifier(state, modifier, trigger::to_generic(loc.get_province().id), trigger::to_generic(p), 0);
3343 assert(llvm_result == interp_result);
3344#endif
3345 weight = std::max(0.0f, llvm_result * (loc.get_province().get_modifier_values(sys::provincial_mod_offsets::immigrant_attract) + 1.0f));
3346 } else {
3347 float interp_result = trigger::evaluate_multiplicative_modifier(state, modifier, trigger::to_generic(loc.get_province().id), trigger::to_generic(p), 0);
3348 weight = std::max(0.0f, interp_result * (loc.get_province().get_modifier_values(sys::provincial_mod_offsets::immigrant_attract) + 1.0f));
3349 }
3350
3351 if(weight > 0.0f) {
3352 if(!limit_to_capitals || loc.get_province().get_state_membership().get_capital().id == loc.get_province().id) {
3353 weights_buffer.set(loc.get_province(), weight);
3354 total_weight += weight;
3355 }
3356 }
3357 }
3358 }
3359 }
3360
3361 if(total_weight <= 0.0f)
3362 return dcon::province_id{};
3363
3364 auto rvalue = float(rng::get_random(state, (uint32_t(p.index()) << 2) | uint32_t(2)) & 0xFFFF) / float(0xFFFF + 1);
3365 for(auto loc : state.world.nation_get_province_ownership(n)) {
3366 rvalue -= weights_buffer.get(loc.get_province()) / total_weight;
3367 if(rvalue < 0.0f) {
3368 return loc.get_province();
3369 }
3370 }
3371
3372 return dcon::province_id{};
3373}
3374
3375dcon::nation_id get_immigration_target(sys::state& state, dcon::nation_id owner, dcon::pop_id p, sys::date day) {
3376 /*
3377 Country targets for external migration: must be a country with its capital on a different continent from the source country
3378 *or* an adjacent country (same continent, but non adjacent, countries are not targets). Each country target is then weighted:
3379 First, the product of the country migration target modifiers (including the base value) is computed, and any results less than
3380 0.01 are increased to that value. That value is then multiplied by (1.0 + the nations immigrant attractiveness modifier).
3381 Assuming that there are valid targets for immigration, the nations with the top three values are selected as the possible
3382 targets. The pop (or, rather, the part of the pop that is migrating) then goes to one of those three targets, selected at
3383 random according to their relative attractiveness weight. The final provincial destination for the pop is then selected as if
3384 doing normal internal migration.
3385 */
3386
3387 auto pt = state.world.pop_get_poptype(p);
3388 auto modifier = state.world.pop_type_get_country_migration_target(pt);
3389 auto modifier_fn = state.world.pop_type_get_country_migration_target_fn(pt);
3390 if(!modifier)
3391 return dcon::nation_id{};
3392
3393 dcon::nation_id top_nations[3] = {dcon::nation_id{}, dcon::nation_id{}, dcon::nation_id{}};
3394 float top_weights[3] = {0.0f, 0.0f, 0.0f};
3395
3396 auto home_continent = state.world.province_get_continent(state.world.pop_get_province_from_pop_location(p));
3397
3398 state.world.for_each_nation([&](dcon::nation_id inner) {
3399 if(state.world.nation_get_owned_province_count(inner) == 0)
3400 return; // ignore dead nations
3401 if(state.world.nation_get_is_civilized(inner) == false)
3402 return; // ignore unciv nations
3403 if(inner == owner)
3404 return; // ignore self
3405 if(state.world.province_get_continent(state.world.nation_get_capital(inner)) == home_continent &&
3406 !state.world.get_nation_adjacency_by_nation_adjacency_pair(owner, inner)) {
3407 return; // ignore same continent, non-adjacent nations
3408 }
3409
3410 float weight = 0.0f;
3411 if(modifier_fn) {
3412 using ftype = float(*)(int32_t, int32_t);
3413 ftype fn = (ftype)modifier_fn;
3414 float llvm_result = fn(inner.index(), p.index());
3415#ifdef CHECK_LLVM_RESULTS
3416 float interp_result = trigger::evaluate_multiplicative_modifier(state, modifier, trigger::to_generic(inner), trigger::to_generic(p), 0);
3417 assert( llvm_result == interp_result);
3418#endif
3419 weight = std::max(0.0f, llvm_result * std::max(0.f, (state.world.nation_get_modifier_values(inner, sys::national_mod_offsets::global_immigrant_attract) + 1.0f)));
3420 } else {
3421 float interp_result = trigger::evaluate_multiplicative_modifier(state, modifier, trigger::to_generic(inner), trigger::to_generic(p), 0);
3422 weight = std::max(0.0f, interp_result * std::max(0.f, (state.world.nation_get_modifier_values(inner, sys::national_mod_offsets::global_immigrant_attract) + 1.0f)));
3423 }
3424
3425 if(weight > top_weights[2]) {
3426 top_weights[2] = weight;
3427 top_nations[2] = inner;
3428 if(top_weights[2] > top_weights[1]) {
3429 std::swap(top_weights[1], top_weights[2]);
3430 std::swap(top_nations[1], top_nations[2]);
3431 }
3432 if(top_weights[1] > top_weights[0]) {
3433 std::swap(top_weights[1], top_weights[0]);
3434 std::swap(top_nations[1], top_nations[0]);
3435 }
3436 }
3437 });
3438
3439 float total_weight = top_weights[0] + top_weights[1] + top_weights[2];
3440 if(total_weight <= 0.0f)
3441 return dcon::nation_id{};
3442
3443 auto rvalue = float(rng::get_random(state, uint32_t(day.value), (uint32_t(p.index()) << 2) | uint32_t(3)) & 0xFFFF) / float(0xFFFF + 1);
3444 for(uint32_t i = 0; i < 3; ++i) {
3445 rvalue -= top_weights[i] / total_weight;
3446 if(rvalue < 0.0f) {
3447 return top_nations[i];
3448 }
3449 }
3450
3451 return dcon::nation_id{};
3452}
3453
3454} // namespace impl
3455
3457 pbuf.update(state.world.pop_size());
3458
3459 pexecute_staggered_blocks(offset, divisions, state.world.pop_size(), [&](auto ids) {
3460 pbuf.amounts.set(ids, 0.0f);
3461 /*
3462 For non-slave, non-colonial pops in provinces with a total population > 100, some pops may migrate within the nation. This
3463 is done by calculating the migration chance factor *additively*. If it is non negative, pops may migrate, and we multiply
3464 it by (province-immigrant-push-modifier + 1) x define:IMMIGRATION_SCALE x pop-size to find out how many migrate.
3465 */
3466
3467 auto loc = state.world.pop_get_province_from_pop_location(ids);
3468 auto owners = state.world.province_get_nation_from_province_ownership(loc);
3469 auto pop_sizes = state.world.pop_get_size(ids);
3470 auto amounts = ve::max(trigger::evaluate_additive_modifier(state, state.culture_definitions.migration_chance, trigger::to_generic(ids), trigger::to_generic(ids), 0), 0.0f) * pop_sizes * ve::max((state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::immigrant_push) + 1.0f), 0.0f) * state.defines.immigration_scale;
3471
3472 ve::apply(
3473 [&](dcon::pop_id p, dcon::province_id location, dcon::nation_id owner, float amount, float pop_size) {
3474 if(amount <= 0.0f)
3475 return; // early exit
3476 if(!owner)
3477 return; // early exit
3478 if(state.world.province_get_is_colonial(location))
3479 return; // early exit
3480 if(state.world.pop_get_poptype(p) == state.culture_definitions.slaves)
3481 return; // early exit
3482
3483 auto dest = impl::get_province_target_in_nation(state, owner, p);
3484
3485 //if(pop_size < small_pop_size) {
3486 // pbuf.amounts.set(p, pop_size);
3487 // else {
3488 pbuf.amounts.set(p, std::min(pop_size, std::ceil(amount)));
3489 //}
3490 pbuf.destinations.set(p, dest);
3491 },
3492 ids, loc, owners, amounts, pop_sizes);
3493 });
3494}
3495
3496float get_estimated_internal_migration(sys::state& state, dcon::pop_id ids) {
3497
3498 auto loc = state.world.pop_get_province_from_pop_location(ids);
3499
3500 if(state.world.province_get_is_colonial(loc))
3501 return 0.0f; // early exit
3502 if(state.world.pop_get_poptype(ids) == state.culture_definitions.slaves)
3503 return 0.0f; // early exit
3504
3505 auto owners = state.world.province_get_nation_from_province_ownership(loc);
3506 auto pop_sizes = state.world.pop_get_size(ids);
3507 auto amount = std::max(trigger::evaluate_additive_modifier(state, state.culture_definitions.migration_chance,
3508 trigger::to_generic(ids), trigger::to_generic(ids), 0), 0.0f) * pop_sizes * std::max(0.0f, (state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::immigrant_push) + 1.0f)) * state.defines.immigration_scale;
3509
3510
3511 if(amount <= 0.0f)
3512 return 0.0f; // early exit
3513
3514 auto pop_size = state.world.pop_get_size(ids);
3515 return std::min(pop_size, std::ceil(amount));
3516}
3517
3519 pbuf.update(state.world.pop_size());
3520
3521 pexecute_staggered_blocks(offset, divisions, state.world.pop_size(), [&](auto ids) {
3522 pbuf.amounts.set(ids, 0.0f);
3523
3524 /*
3525 If a nation has colonies, non-factory worker, non-rich pops in provinces with a total population > 100 may move to the
3526 colonies. This is done by calculating the colonial migration chance factor *additively*. If it is non negative, pops may
3527 migrate, and we multiply it by (province-immigrant-push-modifier + 1) x (colonial-migration-from-tech + 1) x
3528 define:IMMIGRATION_SCALE x pop-size to find out how many migrate.
3529 */
3530
3531 auto loc = state.world.pop_get_province_from_pop_location(ids);
3532 auto owners = state.world.province_get_nation_from_province_ownership(loc);
3533 auto pop_sizes = state.world.pop_get_size(ids);
3534 auto amounts = ve::max(trigger::evaluate_additive_modifier(state, state.culture_definitions.colonialmigration_chance, trigger::to_generic(ids), trigger::to_generic(ids), 0), 0.0f) *
3535 pop_sizes *
3536 ve::max((state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::immigrant_push) + 1.0f), 0.0f) *
3537 ve::max((state.world.nation_get_modifier_values(owners, sys::national_mod_offsets::colonial_migration) + 1.0f), 0.0f) *
3538 state.defines.immigration_scale;
3539
3540 ve::apply(
3541 [&](dcon::pop_id p, dcon::province_id location, dcon::nation_id owner, float amount, float pop_size) {
3542 if(amount <= 0.0f)
3543 return; // early exit
3544 if(!owner)
3545 return; // early exit
3546 if(state.world.nation_get_is_colonial_nation(owner) == false)
3547 return; // early exit
3548 auto pt = state.world.pop_get_poptype(p);
3549 if(state.world.pop_type_get_strata(pt) == uint8_t(culture::pop_strata::rich))
3550 return; // early exit
3551 if(state.world.province_get_is_colonial(location))
3552 return; // early exit
3553 if(pt == state.culture_definitions.slaves || pt == state.culture_definitions.primary_factory_worker ||
3554 pt == state.culture_definitions.secondary_factory_worker)
3555 return; // early exit
3556
3557 //if(pop_size < small_pop_size) {
3558 // pbuf.amounts.set(p, pop_size);
3559 //} else {
3560 pbuf.amounts.set(p, std::min(pop_size, std::ceil(amount)));
3561 //}
3562
3563 auto dest = impl::get_colonial_province_target_in_nation(state, owner, p);
3564 pbuf.destinations.set(p, dest);
3565 },
3566 ids, loc, owners, amounts, pop_sizes);
3567 });
3568}
3569
3570float get_estimated_colonial_migration(sys::state& state, dcon::pop_id ids) {
3571 auto loc = state.world.pop_get_province_from_pop_location(ids);
3572 auto owner = state.world.province_get_nation_from_province_ownership(loc);
3573
3574 if(state.world.nation_get_is_colonial_nation(owner) == false)
3575 return 0.0f; // early exit
3576 auto pt = state.world.pop_get_poptype(ids);
3577 if(state.world.pop_type_get_strata(pt) == uint8_t(culture::pop_strata::rich))
3578 return 0.0f; // early exit
3579 if(state.world.province_get_is_colonial(loc))
3580 return 0.0f; // early exit
3581 if(pt == state.culture_definitions.slaves || pt == state.culture_definitions.primary_factory_worker ||
3582 pt == state.culture_definitions.secondary_factory_worker)
3583 return 0.0f; // early exit
3584
3585
3586 auto pop_sizes = state.world.pop_get_size(ids);
3587 auto amounts = std::max(trigger::evaluate_additive_modifier(state, state.culture_definitions.colonialmigration_chance,
3588 trigger::to_generic(ids), trigger::to_generic(ids), 0), 0.0f)
3589 * pop_sizes
3590 * std::max((state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::immigrant_push) + 1.0f), 0.0f)
3591 * std::max((state.world.nation_get_modifier_values(owner, sys::national_mod_offsets::colonial_migration) + 1.0f), 0.0f)
3592 * state.defines.immigration_scale;
3593
3594 if(amounts <= 0.0f)
3595 return 0.0f; // early exit
3596
3597 auto pop_size = state.world.pop_get_size(ids);
3598 return std::min(pop_size, std::ceil(amounts));
3599}
3600
3601void update_immigration(sys::state& state, uint32_t offset, uint32_t divisions, migration_buffer& pbuf) {
3602 pbuf.update(state.world.pop_size());
3603
3604 pexecute_staggered_blocks(offset, divisions, state.world.pop_size(), [&](auto ids) {
3605 pbuf.amounts.set(ids, 0.0f);
3606
3607 /*
3608 pops in a civ nation that are not in a colony any which do not belong to an `overseas` culture group in provinces with a
3609 total population > 100 may emigrate. This is done by calculating the emigration migration chance factor *additively*. If
3610 it is non negative, pops may migrate, and we multiply it by (province-immigrant-push-modifier + 1) x
3611 1v(province-immigrant-push-modifier + 1) x define:IMMIGRATION_SCALE x pop-size to find out how many migrate.
3612 */
3613
3614 auto loc = state.world.pop_get_province_from_pop_location(ids);
3615 auto owners = state.world.province_get_nation_from_province_ownership(loc);
3616 auto pop_sizes = state.world.pop_get_size(ids);
3617 auto impush = (state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::immigrant_push) + 1.0f);
3618 auto trigger_amount = ve::max(trigger::evaluate_additive_modifier(state, state.culture_definitions.emigration_chance, trigger::to_generic(ids), trigger::to_generic(ids), 0), 0.0f);
3619 auto amounts = trigger_amount
3620 * pop_sizes
3621 * ve::max(impush, 0.0f)
3622 * ve::max(impush, 1.0f)
3623 * state.defines.immigration_scale;
3624
3625 ve::apply(
3626 [&](dcon::pop_id p, dcon::province_id location, dcon::nation_id owner, float amount, float pop_size) {
3627
3628 if(amount <= 0.0f)
3629 return; // early exit
3630 if(!owner)
3631 return; // early exit
3632 if(state.world.nation_get_is_civilized(owner) == false)
3633 return; // early exit
3634 if(state.world.province_get_is_colonial(location))
3635 return; // early exit
3636 if(state.world.pop_get_poptype(p) == state.culture_definitions.slaves)
3637 return; // early exit
3638 if(state.world.culture_group_get_is_overseas(
3639 state.world.culture_get_group_from_culture_group_membership(state.world.pop_get_culture(p))) == false) {
3640 return; // early exit
3641 }
3642
3643 //if(pop_size < small_pop_size) {
3644 // pbuf.amounts.set(p, pop_size);
3645 //} else {
3646 pbuf.amounts.set(p, std::min(pop_size, std::ceil(amount)));
3647 //}
3648
3649 auto ndest = impl::get_immigration_target(state, owner, p, state.current_date);
3650 auto dest = impl::get_province_target_in_nation(state, ndest, p);
3651
3652 pbuf.destinations.set(p, dest);
3653 },
3654 ids, loc, owners, amounts, pop_sizes);
3655 });
3656}
3657
3658void estimate_directed_immigration(sys::state& state, dcon::nation_id n, std::vector<float>& national_amounts) {
3659 auto sz = state.world.nation_size();
3660 national_amounts.resize(sz);
3661 for(auto& v : national_amounts) {
3662 v = 0.0f;
3663 }
3664
3665 auto ymd_date = state.current_date.to_ymd(state.start_date);
3666 auto month_start = sys::year_month_day{ ymd_date.year, ymd_date.month, uint16_t(1) };
3667 auto next_month_start = ymd_date.month != 12 ? sys::year_month_day{ ymd_date.year, uint16_t(ymd_date.month + 1), uint16_t(1) } : sys::year_month_day{ ymd_date.year + 1, uint16_t(1), uint16_t(1) };
3668 auto const days_in_month = uint32_t(sys::days_difference(month_start, next_month_start));
3669
3670 for(auto ids : state.world.in_pop) {
3671 auto loc = state.world.pop_get_province_from_pop_location(ids);
3672 auto owners = state.world.province_get_nation_from_province_ownership(loc);
3673
3674 auto section = uint64_t(ids.id.index()) / 16;
3675 auto tranche = int32_t(section / days_in_month);
3676 auto day_of_month = tranche - 10;
3677 if(day_of_month <= 0)
3678 day_of_month += days_in_month;
3679 int32_t day_adjustment = day_of_month - int32_t(ymd_date.day);
3680 auto est_amount = get_estimated_emigration(state, ids);
3681 if(est_amount > 0.0f) {
3682 auto target = impl::get_immigration_target(state, owners, ids, state.current_date + day_adjustment);
3683 if(owners == n) {
3684 if(target && uint32_t(target.index()) < sz) {
3685 national_amounts[uint32_t(target.index())] -= est_amount;
3686 }
3687 } else if(target == n) {
3688 if(uint32_t(owners.index()) < sz) {
3689 national_amounts[uint32_t(owners.index())] += est_amount;
3690 }
3691 }
3692 }
3693 }
3694}
3695
3696float get_estimated_emigration(sys::state& state, dcon::pop_id ids) {
3697
3698 auto loc = state.world.pop_get_province_from_pop_location(ids);
3699 auto owners = state.world.province_get_nation_from_province_ownership(loc);
3700
3701 if(state.world.nation_get_is_civilized(owners) == false)
3702 return 0.0f; // early exit
3703 if(state.world.province_get_is_colonial(loc))
3704 return 0.0f; // early exit
3705 if(state.world.pop_get_poptype(ids) == state.culture_definitions.slaves)
3706 return 0.0f; // early exit
3707 if(state.world.culture_group_get_is_overseas(
3708 state.world.culture_get_group_from_culture_group_membership(state.world.pop_get_culture(ids))) == false) {
3709 return 0.0f; // early exit
3710 }
3711
3712 auto pop_sizes = state.world.pop_get_size(ids);
3713 auto impush = (state.world.province_get_modifier_values(loc, sys::provincial_mod_offsets::immigrant_push) + 1.0f);
3714 auto trigger_result = std::max(trigger::evaluate_additive_modifier(state, state.culture_definitions.emigration_chance, trigger::to_generic(ids), trigger::to_generic(ids), 0), 0.0f);
3715 auto amounts = trigger_result * pop_sizes * std::max(impush, 0.0f) * std::max(impush, 1.0f) * state.defines.immigration_scale;
3716
3717 if(amounts <= 0.0f)
3718 return 0.0f; // early exit
3719
3720 return std::min(pop_sizes, std::ceil(amounts));
3721}
3722
3723namespace impl {
3724dcon::pop_id find_or_make_pop(sys::state& state, dcon::province_id loc, dcon::culture_id cid, dcon::religion_id rid,
3725 dcon::pop_type_id ptid, float l) {
3726 bool is_mine = state.world.commodity_get_is_mine(state.world.province_get_rgo(loc));
3727 if(is_mine && ptid == state.culture_definitions.farmers) {
3728 ptid = state.culture_definitions.laborers;
3729 } else if(!is_mine && ptid == state.culture_definitions.laborers) {
3730 ptid = state.culture_definitions.farmers;
3731 }
3732 // TODO: fix state capital only type pops ?
3733 for(auto pl : state.world.province_get_pop_location(loc)) {
3734 if(pl.get_pop().get_culture() == cid && pl.get_pop().get_religion() == rid && pl.get_pop().get_poptype() == ptid) {
3735 return pl.get_pop();
3736 }
3737 }
3738 auto np = fatten(state.world, state.world.create_pop());
3739 state.world.force_create_pop_location(np, loc);
3740 np.set_culture(cid);
3741 np.set_religion(rid);
3742 np.set_poptype(ptid);
3743 pop_demographics::set_literacy(state, np.id, l);
3744 {
3745 auto n = state.world.province_get_nation_from_province_ownership(loc);
3746 if(state.world.nation_get_primary_culture(n) == cid) {
3747 np.set_is_primary_or_accepted_culture(true);
3748 } else {
3749 if(state.world.nation_get_accepted_cultures(n, cid) == true) {
3750 np.set_is_primary_or_accepted_culture(true);
3751 }
3752 }
3753 }
3754
3755 { // initial ideology
3756 float totals = 0.0f;
3757 static auto buf = state.world.ideology_make_vectorizable_float_buffer();
3758
3759 state.world.for_each_ideology([&](dcon::ideology_id i) {
3760 buf.set(i, 0.0f);
3761 if(state.world.ideology_get_enabled(i)) {
3762 auto ptrigger = state.world.pop_type_get_ideology(ptid, i);
3763 auto const i_key = pop_demographics::to_key(state, i);
3764 auto owner = nations::owner_of_pop(state, np);
3765 if(state.world.ideology_get_is_civilized_only(i)) {
3766 if(state.world.nation_get_is_civilized(owner)) {
3767 auto amount = ptrigger ? std::max(0.0f, trigger::evaluate_multiplicative_modifier(state, ptrigger, trigger::to_generic(np.id),
3768 trigger::to_generic(owner), 0)) : 0.0f;
3769 buf.set(i, amount);
3770 totals += amount;
3771 }
3772 } else {
3773 auto amount = ptrigger ? std::max(0.0f, trigger::evaluate_multiplicative_modifier(state, ptrigger, trigger::to_generic(np.id),
3774 trigger::to_generic(owner), 0)) : 0.0f;
3775 buf.set(i, amount);
3776 totals += amount;
3777 }
3778 }
3779 });
3780 if(totals > 0) {
3781 state.world.for_each_ideology([&](dcon::ideology_id i) {
3782 auto const i_key = pop_demographics::to_key(state, i);
3783 pop_demographics::set_demo(state, np.id, i_key, buf.get(i) / totals);
3784 });
3785 }
3786 }
3787 { // initial issues
3788 float totals = 0.0f;
3789 static auto buf = state.world.issue_option_make_vectorizable_float_buffer();
3790
3791 state.world.for_each_issue_option([&](dcon::issue_option_id iid) {
3792 auto opt = fatten(state.world, iid);
3793 auto allow = opt.get_allow();
3794 auto parent_issue = opt.get_parent_issue();
3795 auto const i_key = pop_demographics::to_key(state, iid);
3796 auto is_party_issue = state.world.issue_get_issue_type(parent_issue) == uint8_t(culture::issue_type::party);
3797 auto is_social_issue = state.world.issue_get_issue_type(parent_issue) == uint8_t(culture::issue_type::social);
3798 auto is_political_issue = state.world.issue_get_issue_type(parent_issue) == uint8_t(culture::issue_type::political);
3799 auto has_modifier = is_social_issue || is_political_issue;
3800 auto modifier_key =
3801 is_social_issue ? sys::national_mod_offsets::social_reform_desire : sys::national_mod_offsets::political_reform_desire;
3802
3803 auto owner = nations::owner_of_pop(state, np);
3804 auto current_issue_setting = state.world.nation_get_issues(owner, parent_issue);
3805 auto allowed_by_owner =
3806 (state.world.nation_get_is_civilized(owner) || is_party_issue) &&
3807 (!state.world.issue_get_is_next_step_only(parent_issue) || (current_issue_setting.id.index() == iid.index()) || (current_issue_setting.id.index() == iid.index() - 1) || (current_issue_setting.id.index() == iid.index() + 1));
3808 auto owner_modifier = has_modifier ? (state.world.nation_get_modifier_values(owner, modifier_key) + 1.0f) : 1.0f;
3809 buf.set(iid, 0.0f);
3810 if(allowed_by_owner) {
3811 if(auto mtrigger = state.world.pop_type_get_issues(ptid, iid); mtrigger) {
3812 auto amount = std::max(0.0f, owner_modifier * trigger::evaluate_multiplicative_modifier(state, mtrigger, trigger::to_generic(np.id), trigger::to_generic(owner), 0));
3813 buf.set(iid, amount);
3814 totals += amount;
3815 }
3816 }
3817 });
3818 if(totals > 0) {
3819 state.world.for_each_issue_option([&](dcon::issue_option_id i) {
3820 auto const i_key = pop_demographics::to_key(state, i);
3821 pop_demographics::set_demo(state, np.id, i_key, buf.get(i) / totals);
3822 });
3823 }
3824 }
3825 return np;
3826}
3827} // namespace impl
3828
3829void apply_type_changes(sys::state& state, uint32_t offset, uint32_t divisions, promotion_buffer& pbuf) {
3830 execute_staggered_blocks(offset, divisions, std::min(state.world.pop_size(), pbuf.size), [&](auto ids) {
3831 ve::apply(
3832 [&](dcon::pop_id p) {
3833 if(pbuf.amounts.get(p) > 0.0f && pbuf.types.get(p)) {
3834 auto target_pop = impl::find_or_make_pop(state, state.world.pop_get_province_from_pop_location(p),
3835 state.world.pop_get_culture(p), state.world.pop_get_religion(p), pbuf.types.get(p), pop_demographics::get_literacy(state, p));
3836 state.world.pop_get_size(p) -= pbuf.amounts.get(p);
3837 state.world.pop_get_size(target_pop) += pbuf.amounts.get(p);
3838 }
3839 },
3840 ids);
3841 });
3842}
3843
3845 auto exec_fn = [&](auto ids) {
3846 auto locs = state.world.pop_get_province_from_pop_location(ids);
3847 ve::apply([&](dcon::pop_id p, dcon::province_id l, dcon::culture_id dac) {
3848 if(pbuf.amounts.get(p) > 0.0f) {
3849 //auto o = nations::owner_of_pop(state, p);
3850 auto cul = dac ? dac : state.world.province_get_dominant_culture(l);
3851 auto rel = dac
3852 ? state.world.nation_get_religion(nations::owner_of_pop(state, p))
3853 : state.world.province_get_dominant_religion(l);
3854 assert(state.world.pop_get_poptype(p));
3855 auto target_pop = impl::find_or_make_pop(state, l, cul, rel, state.world.pop_get_poptype(p), pop_demographics::get_literacy(state, p));
3856 state.world.pop_get_size(p) -= pbuf.amounts.get(p);
3857 state.world.pop_get_size(target_pop) += pbuf.amounts.get(p);
3858 }
3859 },
3860 ids, locs, state.world.province_get_dominant_accepted_culture(locs));
3861 };
3862 execute_staggered_blocks(offset, divisions, std::min(state.world.pop_size(), pbuf.size), exec_fn);
3863}
3864
3866 execute_staggered_blocks(offset, divisions, std::min(state.world.pop_size(), pbuf.size), [&](auto ids) {
3867 ve::apply(
3868 [&](dcon::pop_id p) {
3869 if(pbuf.amounts.get(p) > 0.0f && pbuf.destinations.get(p)) {
3870 assert(state.world.pop_get_poptype(p));
3871 auto target_pop = impl::find_or_make_pop(state, pbuf.destinations.get(p), state.world.pop_get_culture(p),
3872 state.world.pop_get_religion(p), state.world.pop_get_poptype(p), pop_demographics::get_literacy(state, p));
3873 state.world.pop_get_size(p) -= pbuf.amounts.get(p);
3874 state.world.pop_get_size(target_pop) += pbuf.amounts.get(p);
3875 state.world.province_get_daily_net_migration(state.world.pop_get_province_from_pop_location(p)) -=
3876 pbuf.amounts.get(p);
3877 state.world.province_get_daily_net_migration(pbuf.destinations.get(p)) += pbuf.amounts.get(p);
3878 }
3879 },
3880 ids);
3881 });
3882}
3883
3885 execute_staggered_blocks(offset, divisions, std::min(state.world.pop_size(), pbuf.size), [&](auto ids) {
3886 ve::apply(
3887 [&](dcon::pop_id p) {
3888 if(pbuf.amounts.get(p) > 0.0f && pbuf.destinations.get(p)) {
3889 assert(state.world.pop_get_poptype(p));
3890 auto target_pop = impl::find_or_make_pop(state, pbuf.destinations.get(p), state.world.pop_get_culture(p),
3891 state.world.pop_get_religion(p), state.world.pop_get_poptype(p), pop_demographics::get_literacy(state, p));
3892 state.world.pop_get_size(p) -= pbuf.amounts.get(p);
3893 state.world.pop_get_size(target_pop) += pbuf.amounts.get(p);
3894 state.world.province_get_daily_net_migration(state.world.pop_get_province_from_pop_location(p)) -=
3895 pbuf.amounts.get(p);
3896 state.world.province_get_daily_net_migration(pbuf.destinations.get(p)) += pbuf.amounts.get(p);
3897 }
3898 },
3899 ids);
3900 });
3901}
3902
3903void apply_immigration(sys::state& state, uint32_t offset, uint32_t divisions, migration_buffer& pbuf) {
3904 execute_staggered_blocks(offset, divisions, std::min(state.world.pop_size(), pbuf.size), [&](auto ids) {
3905 ve::apply(
3906 [&](dcon::pop_id p) {
3907 auto amount = pbuf.amounts.get(p);
3908 if(amount > 0.0f && pbuf.destinations.get(p)) {
3909 assert(state.world.pop_get_poptype(p));
3910 auto target_pop = impl::find_or_make_pop(state, pbuf.destinations.get(p), state.world.pop_get_culture(p),
3911 state.world.pop_get_religion(p), state.world.pop_get_poptype(p), pop_demographics::get_literacy(state, p));
3912
3913 state.world.pop_get_size(p) -= amount;
3914 state.world.pop_get_size(target_pop) += amount;
3915 state.world.province_get_daily_net_immigration(state.world.pop_get_province_from_pop_location(p)) -= amount;
3916 state.world.province_get_daily_net_immigration(pbuf.destinations.get(p)) += amount;
3917 state.world.province_set_last_immigration(pbuf.destinations.get(p), state.current_date);
3918 }
3919 },
3920 ids);
3921 });
3922}
3923
3925 // IMPORTANT: we count down here so that we can delete as we go, compacting from the end
3926 for(auto last = state.world.pop_size(); last-- > 0;) {
3927 dcon::pop_id m{dcon::pop_id::value_base_t(last)};
3928 if(state.world.pop_get_size(m) < 1.0f) {
3929 state.world.delete_pop(m);
3930 }
3931 }
3932}
3933
3935 // IMPORTANT: we count down here so that we can delete as we go, compacting from the end
3936 for(auto last = state.world.pop_size(); last-- > 0;) {
3937 dcon::pop_id m{ dcon::pop_id::value_base_t(last) };
3938 if(state.world.pop_get_size(m) < 20.0f) {
3939 state.world.delete_pop(m);
3940 }
3941 }
3942}
3943
3944float calculate_nation_sol(sys::state& state, dcon::nation_id nation_id) {
3945 auto pln = state.world.nation_get_demographics(nation_id, demographics::poor_life_needs);
3946 auto mln = state.world.nation_get_demographics(nation_id, demographics::middle_life_needs);
3947 auto rln = state.world.nation_get_demographics(nation_id, demographics::rich_life_needs);
3948
3949 auto pen = state.world.nation_get_demographics(nation_id, demographics::poor_everyday_needs);
3950 auto men = state.world.nation_get_demographics(nation_id, demographics::middle_everyday_needs);
3951 auto ren = state.world.nation_get_demographics(nation_id, demographics::rich_everyday_needs);
3952
3953 auto plun = state.world.nation_get_demographics(nation_id, demographics::poor_luxury_needs);
3954 auto mlun = state.world.nation_get_demographics(nation_id, demographics::middle_luxury_needs);
3955 auto rlun = state.world.nation_get_demographics(nation_id, demographics::rich_luxury_needs);
3956
3957 float p = state.world.nation_get_demographics(nation_id, demographics::total);
3958 float pp = state.world.nation_get_demographics(nation_id, demographics::poor_total);
3959 float mp = state.world.nation_get_demographics(nation_id, demographics::middle_total);
3960 float rp = state.world.nation_get_demographics(nation_id, demographics::rich_total);
3961
3962 auto poor_score = (pln + pen + plun) / pp;
3963 auto middle_score = (mln + men + mlun) / mp;
3964 auto rich_score = (rln + ren + rlun) / rp;
3965
3966 auto finalscore = (poor_score * pp + middle_score * mp + rich_score * rp) * 33 / p;
3967
3968 return finalscore;
3969}
3970
3971void reduce_pop_size_safe(sys::state& state, dcon::pop_id pop_id, int32_t amount) {
3972 if(state.world.pop_get_size(pop_id) >= amount) {
3973 state.world.pop_get_size(pop_id) -= amount;
3974 } else {
3975 state.world.pop_get_size(pop_id) = 0;
3976 }
3977}
3978
3979void modify_militancy(sys::state& state, dcon::nation_id n, float v) {
3980 for(auto pr : state.world.nation_get_province_ownership(n)) {
3981 for(auto pop : pr.get_province().get_pop_location()) {
3982 auto base_mil = pop_demographics::get_militancy(state, pop.get_pop());
3983 auto adj_mil = base_mil + v;
3984 pop_demographics::set_militancy(state, pop.get_pop().id, std::clamp(adj_mil, 0.0f, 10.0f));
3985 }
3986 }
3987}
3988
3989} // namespace demographics
#define assert(condition)
Definition: debug.h:74
pop_satisfaction_wrapper_fat fatten(data_container const &c, pop_satisfaction_wrapper_id id) noexcept
dcon::province_id get_province_target_in_nation(sys::state &state, dcon::nation_id n, dcon::pop_id p)
dcon::nation_id get_immigration_target(sys::state &state, dcon::nation_id owner, dcon::pop_id p, sys::date day)
dcon::pop_id find_or_make_pop(sys::state &state, dcon::province_id loc, dcon::culture_id cid, dcon::religion_id rid, dcon::pop_type_id ptid, float l)
dcon::province_id get_colonial_province_target_in_nation(sys::state &state, dcon::nation_id n, dcon::pop_id p)
void alt_copy_demographics(sys::state &state, dcon::demographics_key key)
void modify_militancy(sys::state &state, dcon::nation_id n, float v)
float get_effective_estimation_type_change(sys::state &state, dcon::nation_id nation, dcon::pop_type_id target_type)
constexpr dcon::demographics_key rich_life_needs(13)
constexpr dcon::demographics_key poor_luxury_needs(17)
constexpr dcon::demographics_key middle_life_needs(12)
float get_estimated_colonial_migration(sys::state &state, dcon::pop_id ids)
void estimate_directed_immigration(sys::state &state, dcon::nation_id n, std::vector< float > &national_amounts)
void alt_st_regenerate_from_pop_data(sys::state &state)
void alt_demographics_update_extras(sys::state &state)
float get_estimated_literacy_change(sys::state &state, dcon::pop_id ids)
void sum_over_demographics(sys::state &state, dcon::demographics_key key, F const &source)
constexpr dcon::demographics_key middle_total(21)
constexpr dcon::demographics_key middle_luxury_needs(18)
float get_estimated_type_change(sys::state &state, dcon::pop_id ids)
float calculate_nation_sol(sys::state &state, dcon::nation_id nation_id)
void remove_small_pops(sys::state &state)
void regenerate_jingoism_support(sys::state &state, dcon::nation_id n)
void update_immigration(sys::state &state, uint32_t offset, uint32_t divisions, migration_buffer &pbuf)
constexpr dcon::demographics_key total(0)
void regenerate_from_pop_data(sys::state &state)
constexpr dcon::demographics_key rich_everyday_needs(16)
constexpr float issues_change_rate
constexpr dcon::demographics_key rich_luxury_needs(19)
void pexecute_staggered_blocks(uint32_t offset, uint32_t divisions, uint32_t max, F &&functor)
void apply_assimilation(sys::state &state, uint32_t offset, uint32_t divisions, assimilation_buffer &pbuf)
constexpr dcon::demographics_key poor_everyday_needs(14)
void update_internal_migration(sys::state &state, uint32_t offset, uint32_t divisions, migration_buffer &pbuf)
void apply_type_changes(sys::state &state, uint32_t offset, uint32_t divisions, promotion_buffer &pbuf)
dcon::demographics_key to_key(sys::state const &state, dcon::pop_type_id v)
constexpr float small_pop_size
float get_estimated_mil_change(sys::state &state, dcon::pop_id ids)
constexpr uint32_t count_special_keys
void update_growth(sys::state &state, uint32_t offset, uint32_t divisions)
void alt_sum_over_demographics(sys::state &state, dcon::demographics_key key, F const &source)
void alt_regenerate_from_pop_data_daily(sys::state &state)
void update_issues(sys::state &state, uint32_t offset, uint32_t divisions, issues_buffer &ibuf)
void apply_internal_migration(sys::state &state, uint32_t offset, uint32_t divisions, migration_buffer &pbuf)
constexpr dcon::demographics_key rich_total(22)
constexpr dcon::demographics_key poor_total(20)
void update_type_changes(sys::state &state, uint32_t offset, uint32_t divisions, promotion_buffer &pbuf)
void regenerate_from_pop_data_full(sys::state &state)
void reduce_pop_size_safe(sys::state &state, dcon::pop_id pop_id, int32_t amount)
float get_estimated_internal_migration(sys::state &state, dcon::pop_id ids)
float get_estimated_demotion(sys::state &state, dcon::pop_id ids)
constexpr dcon::demographics_key poor_life_needs(11)
void execute_staggered_blocks(uint32_t offset, uint32_t divisions, uint32_t max, F &&functor)
uint32_t size(sys::state const &state)
void sum_over_single_nation_demographics(sys::state &state, dcon::demographics_key key, dcon::nation_id n, F const &source)
float get_monthly_pop_increase(sys::state &state, dcon::pop_id ids)
float get_estimated_con_change(sys::state &state, dcon::pop_id ids)
dcon::demographics_key to_employment_key(sys::state const &state, dcon::pop_type_id v)
void update_assimilation(sys::state &state, uint32_t offset, uint32_t divisions, assimilation_buffer &pbuf)
void alt_regenerate_from_pop_data_full(sys::state &state)
void alt_mt_regenerate_from_pop_data(sys::state &state)
void remove_size_zero_pops(sys::state &state)
void update_colonial_migration(sys::state &state, uint32_t offset, uint32_t divisions, migration_buffer &pbuf)
constexpr uint32_t extra_demo_grouping
void apply_ideologies(sys::state &state, uint32_t offset, uint32_t divisions, ideology_buffer &pbuf)
void update_ideologies(sys::state &state, uint32_t offset, uint32_t divisions, ideology_buffer &ibuf)
constexpr uint32_t executions_per_block
void update_consciousness(sys::state &state, uint32_t offset, uint32_t divisions)
constexpr dcon::demographics_key middle_everyday_needs(15)
float get_estimated_assimilation(sys::state &state, dcon::pop_id ids)
void update_literacy(sys::state &state, uint32_t offset, uint32_t divisions)
void update_militancy(sys::state &state, uint32_t offset, uint32_t divisions)
uint32_t common_size(sys::state const &state)
void apply_colonial_migration(sys::state &state, uint32_t offset, uint32_t divisions, migration_buffer &pbuf)
float get_estimated_emigration(sys::state &state, dcon::pop_id ids)
void regenerate_from_pop_data_daily(sys::state &state)
void apply_immigration(sys::state &state, uint32_t offset, uint32_t divisions, migration_buffer &pbuf)
float get_estimated_promotion(sys::state &state, dcon::pop_id ids)
void apply_issues(sys::state &state, uint32_t offset, uint32_t divisions, issues_buffer &pbuf)
@ key
the parser read a key of a value in an object
dcon::nation_id owner_of_pop(sys::state const &state, dcon::pop_id pop_ids)
Definition: nations.cpp:87
auto nation_accepts_culture(sys::state const &state, T ids, U cul_ids)
void set_luxury_needs(sys::state &state, P p, V v)
void set_political_reform_desire(sys::state &state, dcon::pop_id p, float v)
void set_militancy(sys::state &state, dcon::pop_id p, float v)
float from_pmc(uint16_t v)
void set_everyday_needs(sys::state &state, P p, V v)
void set_social_reform_desire(sys::state &state, dcon::pop_id p, float v)
uint16_t to_pmc(float v)
template void set_everyday_needs< dcon::pop_id, float >(sys::state &, dcon::pop_id, float)
uint32_t size(sys::state const &state)
float get_employment(sys::state const &state, dcon::pop_id p)
template void set_life_needs< dcon::pop_fat_id, float >(sys::state &, dcon::pop_fat_id, float)
void set_employment(sys::state &state, dcon::pop_id p, float v)
float get_social_reform_desire(sys::state const &state, dcon::pop_id p)
float get_luxury_needs(sys::state const &state, dcon::pop_id p)
void set_raw_employment(sys::state &state, dcon::pop_id p, float v)
void regenerate_is_primary_or_accepted(sys::state &state)
void set_demo(sys::state &state, dcon::pop_id p, dcon::pop_demographics_key k, float v)
template void set_luxury_needs< dcon::pop_fat_id, float >(sys::state &, dcon::pop_fat_id, float)
uint16_t to_pu16(float v)
float from_pu8(uint8_t v)
void set_consciousness(sys::state &state, dcon::pop_id p, float v)
dcon::pop_demographics_key to_key(sys::state const &state, dcon::ideology_id v)
float get_literacy(sys::state const &state, dcon::pop_id p)
float get_consciousness(sys::state const &state, dcon::pop_id p)
float get_militancy(sys::state const &state, dcon::pop_id p)
float get_raw_employment(sys::state const &state, dcon::pop_id p)
template void set_luxury_needs< dcon::pop_id, float >(sys::state &, dcon::pop_id, float)
float get_life_needs(sys::state const &state, dcon::pop_id p)
float get_political_reform_desire(sys::state const &state, dcon::pop_id p)
void set_literacy(sys::state &state, T p, ve::fp_vector v)
void set_life_needs(sys::state &state, P p, V v)
template void set_everyday_needs< dcon::pop_fat_id, float >(sys::state &, dcon::pop_fat_id, float)
float get_everyday_needs(sys::state const &state, dcon::pop_id p)
float from_pu16(uint16_t v)
constexpr uint32_t count_special_keys
Definition: demographics.hpp:7
float get_demo(sys::state const &state, dcon::pop_id p, dcon::pop_demographics_key k)
template void set_life_needs< dcon::pop_id, float >(sys::state &, dcon::pop_id, float)
uint8_t to_pu8(float v)
bool is_overseas(sys::state const &state, dcon::province_id ids)
Definition: province.cpp:19
void ve_for_each_land_province(sys::state &state, F const &func)
void for_each_province_in_state_instance(sys::state &state, dcon::state_instance_id s, F const &func)
void for_each_land_province(sys::state &state, F const &func)
uint64_t get_random(sys::state const &state, uint32_t value_in)
Definition: prng.cpp:8
int32_t days_difference(year_month_day start, year_month_day end)
int32_t to_generic(dcon::province_id v)
Definition: triggers.hpp:12
float evaluate_additive_modifier(sys::state &state, dcon::value_modifier_key modifier, int32_t primary, int32_t this_slot, int32_t from_slot)
Definition: triggers.cpp:5826
float evaluate_multiplicative_modifier(sys::state &state, dcon::value_modifier_key modifier, int32_t primary, int32_t this_slot, int32_t from_slot)
Definition: triggers.cpp:5812
T select(bool v, T a, T b)
uint uint32_t
ulong uint64_t
uchar uint8_t
ve::vectorizable_buffer< float, dcon::pop_id > amounts
void update(sys::state &state, uint32_t s)
void update(sys::state &state, uint32_t s)
tagged_vector< ve::vectorizable_buffer< uint8_t, dcon::pop_id >, dcon::issue_option_id > temp_buffers
Holds important data about the game world, state, and other data regarding windowing,...