28 #include <tbb/blocked_range.h>
29 #include <tbb/concurrent_vector.h>
30 #include <tbb/parallel_for.h>
31 #include <tbb/combinable.h>
33 #include "eng3d/disc_dist.hpp"
39 static DiscreteDistribution<float> rng_multipliers({ 0.01f, 0.05f, 0.25f, 0.3f, 0.5f, 1.f }, { 1.f, 0.5f, 0.25f, 0.01f, 0.2f, 0.1f });
41 static inline void conlonial_migration(
World& world);
42 static inline void internal_migration(
World& world);
43 static inline void external_migration(
World& world);
46 external_migration(world);
47 internal_migration(world);
48 conlonial_migration(world);
51 static inline void conlonial_migration(
World&) {
55 static inline void internal_migration(
World&) {
60 static inline float nation_attraction(
Nation& nation,
Language& language) {
62 return attraction + rng_multipliers.get_item();
65 static inline float province_attraction(
const Province& province) {
66 auto rand_attractive = province.
base_attractive + rng_multipliers.get_item();
69 return rand_attractive;
72 static inline void external_migration(
World& world) {
73 std::vector<DiscreteDistribution<Province*>> province_distributions;
74 province_distributions.reserve(world.provinces.size());
75 for(
auto& nation : world.nations) {
76 std::vector<float> attractions;
77 std::vector<Province*> viable_provinces;
79 auto& province = world.provinces[province_id];
82 auto attraction = province_attraction(province);
85 attractions.push_back(attraction);
86 viable_provinces.push_back(&province);
88 if(viable_provinces.empty()) {
89 attractions.push_back(1.f);
90 viable_provinces.push_back(
nullptr);
92 province_distributions.emplace_back(viable_provinces, attractions);
94 assert(!province_distributions.empty());
96 std::vector<DiscreteDistribution<Nation*>> nation_distributions;
97 nation_distributions.reserve(world.nations.size());
98 for(
auto& language : world.languages) {
99 std::vector<float> attractions;
100 std::vector<Nation*> viable_nations;
101 for(
auto& nation : world.nations) {
102 auto attraction = nation_attraction(nation, language);
103 if(attraction <= 0.f)
105 attractions.push_back(attraction);
106 viable_nations.push_back(&nation);
108 if(viable_nations.empty()) {
109 attractions.push_back(1.f);
110 viable_nations.push_back(
nullptr);
112 nation_distributions.emplace_back(viable_nations, attractions);
114 assert(!nation_distributions.empty());
116 struct EmigrationData {
123 tbb::parallel_for(
tbb::blocked_range(world.provinces.begin(), world.provinces.end()), [&emigration, &nation_distributions, &province_distributions, &world](
const auto& provinces_range) {
124 for(auto& province : provinces_range) {
125 if(world.terrain_types[province.terrain_type_id].is_water_body)
128 const auto language_id = std::distance(province.languages.begin(), std::max_element(province.languages.begin(), province.languages.end()));
130 for(auto& pop : province.pops) {
138 const auto emigration_desire = glm::max(pop.militancy * -pop.life_needs_met, 1.f);
139 auto emigrants = glm::min(pop.size * emigration_desire * rng_multipliers.get_item(), pop.size);
140 if(emigrants > 0.f) {
141 auto& nation_distribution = nation_distributions[language_id];
142 const auto* random_nation = nation_distribution.get_item();
143 if(random_nation == nullptr)
146 auto& province_distribution = province_distributions[random_nation->get_id()];
147 auto* choosen_province = province_distribution.get_item();
148 if(choosen_province == nullptr || world.terrain_types[choosen_province->terrain_type_id].is_water_body)
151 emigration.local().push_back(EmigrationData{
153 choosen_province->get_id(),
158 pop.size -= emigrants;
159 assert(!(pop.size < 0.f));
167 for(
const auto& e : list) {
168 auto& target = world.provinces[e.target_id];
169 const auto it = std::find(target.pops.begin(), target.pops.end(), e.emigred);
170 assert(it != target.pops.end());
Uses the Aiias method to generate a lookup table of with different probabilties.
std::vector< ProvinceId > controlled_provinces
std::vector< float > language_acceptance
A single province, which is used to simulate economy in a "bulk-tiles" way instead of doing economica...
float average_militancy() const
TerrainTypeId terrain_type_id
void do_emigration(World &world)
void parallel_for(T range, F &&func)
void combine_each(F &&func)