-
Notifications
You must be signed in to change notification settings - Fork 5
/
game_of_life.cpp
135 lines (112 loc) · 3.81 KB
/
game_of_life.cpp
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
131
132
133
134
135
/* Copyright 2019-2024 Michael Sippel, Sergei Bastrakov, Tapish Narwal
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/**
* @file examples/game_of_life.cpp
*/
#include "redGrapes/resource/fieldresource.hpp"
#include <redGrapes/redGrapes.hpp>
#include <array>
#include <cstdlib>
#include <iostream>
#include <random>
struct Vec2
{
int x, y;
};
enum Cell
{
DEAD,
ALIVE
};
static constexpr Vec2 size{32, 32};
static constexpr Vec2 chunk_size{4, 4};
Cell next_state(Cell const neighbours[][size.x + 2])
{
int count = neighbours[-1][-1] + neighbours[-1][0] + neighbours[-1][1] + neighbours[0][-1] + neighbours[0][1]
+ neighbours[1][-1] + neighbours[1][0] + neighbours[1][1];
if(count < 2 || count > 3)
return DEAD;
else if(count == 3)
return ALIVE;
else
return neighbours[0][0];
}
int main(int, char*[])
{
spdlog::set_level(spdlog::level::trace);
spdlog::set_pattern("[thread %t] %^[%l]%$ %v");
auto rg = redGrapes::init(4);
using Buffer = std::array<std::array<Cell, size.x + 2>, size.y + 2>;
std::vector<redGrapes::FieldResource<Buffer>> buffers;
for(size_t i = 0; i < 4; ++i)
buffers.emplace_back();
int current = 0;
// initialization
rg.emplace_task(
[](auto buf)
{
std::default_random_engine generator;
std::bernoulli_distribution distribution{0.35};
for(size_t x = 0; x < size.x + 2; ++x)
for(size_t y = 0; y < size.y + 2; ++y)
buf[{x, y}] = distribution(generator) ? ALIVE : DEAD;
},
buffers[current].write());
for(int generation = 0; generation < 500; ++generation)
{
int next = (current + 1) % buffers.size();
// copy borders
rg.emplace_task(
[](auto buf)
{
for(size_t x = 0; x < size.x + 2; ++x)
{
buf[{x, 0}] = buf[{x, size.y}];
;
buf[{x, size.y + 1}] = buf[{x, 1}];
}
for(size_t y = 0; y < size.y + 2; ++y)
{
buf[{0, y}] = buf[{size.x, y}];
buf[{size.x + 1, y}] = buf[{1, y}];
}
},
buffers[current].write());
// print buffer
rg.emplace_task(
[](auto buf)
{
for(size_t x = 1; x < size.x; ++x)
{
for(size_t y = 1; y < size.y; ++y)
{
std::cout << ((buf[{x, y}] == ALIVE) ? "[47m" : "[100m") << " ";
}
std::cout << "[0m" << std::endl;
}
std::cout << std::endl;
},
buffers[current].read())
.get();
// calculate next step
for(size_t x = 1; x <= size.x; x += chunk_size.x)
for(size_t y = 1; y <= size.y; y += chunk_size.y)
rg.emplace_task(
[x, y](auto dst, auto src)
{
for(int xi = 0; xi < chunk_size.x; ++xi)
for(int yi = 0; yi < chunk_size.y; ++yi)
dst[{x + xi, y + yi}]
= next_state((Cell const(*)[size.x + 2]) & (src[{x + xi, y + yi}]));
},
buffers[next].write().area({x, y}, {x + chunk_size.x, y + chunk_size.y}),
buffers[current].read().area({x - 1, y - 1}, {x + chunk_size.x + 2, y + chunk_size.y + 2}));
current = next;
}
SPDLOG_DEBUG("END!!!!");
return 0;
}