-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathworld.cpp
More file actions
130 lines (115 loc) · 4.09 KB
/
Copy pathworld.cpp
File metadata and controls
130 lines (115 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "world.hpp"
#include <algorithm>
#include <random>
World::World(int size, double start_black_percentage,
double start_white_percentage, int max_age)
: size_{size}, max_age_{max_age} {
auto const num_daisies_ = size_ * size_;
daisies_.reserve(num_daisies_);
auto const num_black_patches =
static_cast<int>(num_daisies_ * start_black_percentage);
auto const num_white_patches =
static_cast<int>(num_daisies_ * start_white_percentage);
auto const num_empty_patches =
num_daisies_ - num_black_patches - num_white_patches;
std::uniform_int_distribution<int> dist{0, max_age_};
// Generate daisies with random colors and ages using generators
auto out =
std::generate_n(std::back_inserter(daisies_), num_black_patches, [&] {
return Daisy{DaisyColor::Black, dist(gen_)};
});
out = std::generate_n(out, num_white_patches, [&] {
return Daisy{DaisyColor::White, dist(gen_)};
});
std::generate_n(out, num_empty_patches, [] {
return Daisy{DaisyColor::None, 0};
});
// Shuffle the daisies
std::shuffle(daisies_.begin(), daisies_.end(), gen_);
}
void World::compute_temperatures(double solar_luminosity) {
for (auto &daisy : daisies_) {
daisy.absorb_light(solar_luminosity);
}
}
double World::global_temperature() const {
return std::accumulate(daisies_.begin(), daisies_.end(), 0.,
[](double sum, Daisy const &daisy) {
return sum + daisy.temperature();
}) /
daisies_.size();
}
void World::step(double solar_luminosity) {
compute_temperatures(solar_luminosity);
compute_diffusion();
spread();
}
std::vector<double> diffuse(std::vector<double> const &temperatures, int size,
double diffusion_rate) {
std::vector<double> new_temperatures(size * size);
for (int idx{0}; idx < size * size; ++idx) {
double temperature = temperatures[idx];
double const diffused_temperature = temperature * diffusion_rate / 8;
int const row = idx / size;
int const col = idx % size;
for (int neighborRow : {row - 1, row, row + 1}) {
for (int neighborCol : {col - 1, col, col + 1}) {
// Check if the neighbor is within the grid bounds
if (neighborRow >= 0 && neighborRow < size && neighborCol >= 0 &&
neighborCol < size) {
new_temperatures[neighborRow * size + neighborCol] +=
diffused_temperature;
temperature -= diffused_temperature;
}
}
}
// Keep leftover temperature
new_temperatures[idx] += temperature;
}
// Update original patches
return new_temperatures;
}
void World::compute_diffusion() {
std::vector<double> temperatures;
temperatures.reserve(daisies_.size());
for (auto const &p : daisies_) {
temperatures.push_back(p.temperature());
}
auto new_temperatures = diffuse(temperatures, size_, 0.5);
for (int i{0}; i < size_ * size_; ++i) {
daisies_[i].temperature(new_temperatures[i]);
}
}
void World::spread() {
for (auto &daisy : daisies_) {
daisy.age_and_die(max_age_);
}
auto new_daisies = daisies_;
std::uniform_real_distribution<double> flat;
for (int idx{0}; idx < size_ * size_; ++idx) {
auto &daisy = daisies_[idx];
if (daisy.color() == DaisyColor::None ||
flat(gen_) >= daisy.seeding_threshold()) {
continue;
}
std::vector<Daisy *> barren_neighbors;
int const row = idx / size_;
int const col = idx % size_;
for (int neighborRow : {row - 1, row, row + 1}) {
for (int neighborCol : {col - 1, col, col + 1}) {
if (neighborRow >= 0 && neighborRow < size_ && neighborCol >= 0 &&
neighborCol < size_) {
auto &neighbor = new_daisies[neighborRow * size_ + neighborCol];
if (neighbor.color() == DaisyColor::None) {
barren_neighbors.emplace_back(&neighbor);
}
}
}
}
if (barren_neighbors.size() > 0) {
std::uniform_int_distribution<> flat_i(0, barren_neighbors.size() - 1);
barren_neighbors[flat_i(gen_)]->sprout(daisy.color());
}
}
daisies_ = new_daisies;
}