aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdrian Kummerlaender2017-03-24 22:47:19 +0100
committerAdrian Kummerlaender2017-03-24 23:12:22 +0100
commitc09a4f39f742a94b150cad6a3fb0bbbfbb99e495 (patch)
treef1ecea6ba17f75af4c71b8a30beeafac09454673 /src
parent23a3e7a41a05ce3e4c8dcc2bc75ce366d8fd8fbb (diff)
downloadtermlife-c09a4f39f742a94b150cad6a3fb0bbbfbb99e495.tar
termlife-c09a4f39f742a94b150cad6a3fb0bbbfbb99e495.tar.gz
termlife-c09a4f39f742a94b150cad6a3fb0bbbfbb99e495.tar.bz2
termlife-c09a4f39f742a94b150cad6a3fb0bbbfbb99e495.tar.lz
termlife-c09a4f39f742a94b150cad6a3fb0bbbfbb99e495.tar.xz
termlife-c09a4f39f742a94b150cad6a3fb0bbbfbb99e495.tar.zst
termlife-c09a4f39f742a94b150cad6a3fb0bbbfbb99e495.zip
Switch to toroidial world matrix
i.e. glue together top and bottom respectively right hand side and left hand side borders. This makes for nicer life behaviour in constrained worlds.
Diffstat (limited to 'src')
-rw-r--r--src/util/torus_array.h52
-rw-r--r--src/world.h35
2 files changed, 68 insertions, 19 deletions
diff --git a/src/util/torus_array.h b/src/util/torus_array.h
new file mode 100644
index 0000000..bef0c9f
--- /dev/null
+++ b/src/util/torus_array.h
@@ -0,0 +1,52 @@
+#ifndef LIFE_SRC_UTIL_TORUS_ARRAY_
+#define LIFE_SRC_UTIL_TORUS_ARRAY_
+
+#include <array>
+#include <cstdint>
+
+namespace life {
+namespace util {
+
+template<
+ typename TYPE,
+ std::size_t WIDTH,
+ std::size_t HEIGHT
+>
+class TorusArray {
+ static std::size_t toMatrixColumn(const std::ptrdiff_t x) {
+ if ( x >= 0 ) {
+ return x % WIDTH;
+ } else {
+ return WIDTH - ( std::abs(x) % WIDTH );
+ }
+ }
+
+ static std::size_t toMatrixRow(const std::ptrdiff_t y) {
+ if ( y >= 0 ) {
+ return y % HEIGHT;
+ } else {
+ return HEIGHT - ( std::abs(y) % HEIGHT );
+ }
+ }
+
+ public:
+ static const std::size_t width = WIDTH;
+ static const std::size_t height = HEIGHT;
+
+ TYPE get(const std::ptrdiff_t x, const std::ptrdiff_t y) const {
+ return this->matrix_[toMatrixRow(y)][toMatrixColumn(x)];
+ }
+
+ void set(const std::ptrdiff_t x, const std::ptrdiff_t y, TYPE&& value) {
+ this->matrix_[toMatrixRow(y)][toMatrixColumn(x)] = value;
+ }
+
+ private:
+ std::array<std::array<TYPE, WIDTH>, HEIGHT> matrix_;
+
+};
+
+}
+}
+
+#endif // LIFE_SRC_UTIL_TORUS_ARRAY_
diff --git a/src/world.h b/src/world.h
index e70e20e..a09eb5a 100644
--- a/src/world.h
+++ b/src/world.h
@@ -1,12 +1,12 @@
#ifndef LIFE_SRC_WORLD_H_
#define LIFE_SRC_WORLD_H_
-#include <array>
#include <stack>
#include <tuple>
#include <cstdint>
#include "util/box_traverser.h"
+#include "util/torus_array.h"
namespace life {
@@ -22,19 +22,16 @@ class World {
World():
area_(width, height) {
this->area_.for_each([&](std::size_t i, std::size_t j) {
- this->matrix_[j][i] = false;
+ this->matrix_.set(i, j, false);
});
}
- bool isLifeAt(std::ptrdiff_t x, std::ptrdiff_t y) const {
- if ( this->area_(x, y) ) {
- return this->matrix_[y][x];
- } else {
- return false; // end of world is dead
- }
+ bool isLifeAt(const std::ptrdiff_t x, const std::ptrdiff_t y) const {
+ return this->matrix_.get(x, y);
}
- std::uint8_t lifeDensityAt(std::size_t x, std::size_t y) const {
+ std::uint8_t lifeDensityAt(
+ const std::ptrdiff_t x, const std::ptrdiff_t y) const {
std::uint8_t counter{};
counter += this->isLifeAt(x - 1, y);
@@ -57,20 +54,20 @@ class World {
return this->population_;
}
- void summonLifeAt(std::size_t x, std::size_t y) {
+ void summonLifeAt(const std::ptrdiff_t x, const std::ptrdiff_t y) {
if ( this->area_(x, y) ) {
- if ( !this->matrix_[y][x] ) {
- this->matrix_[y][x] = true;
- this->population_ += 1;
+ if ( !this->matrix_.get(x, y) ) {
+ this->matrix_.set(x, y, true);
+ this->population_ += 1;
}
}
}
- void extinguishLifeAt(std::size_t x, std::size_t y) {
+ void extinguishLifeAt(const std::ptrdiff_t x, const std::ptrdiff_t y) {
if ( this->area_(x, y) ) {
- if ( this->matrix_[y][x] ) {
- this->matrix_[y][x] = false;
- this->population_ -= 1;
+ if ( this->matrix_.get(x, y) ) {
+ this->matrix_.set(x, y, false);
+ this->population_ -= 1;
}
}
}
@@ -83,7 +80,7 @@ class World {
this->area_.for_each([&](std::size_t i, std::size_t j) {
const std::uint8_t d{this->lifeDensityAt(i, j)};
- if ( this->matrix_[j][i] ) {
+ if ( this->matrix_.get(i, j) ) {
if ( d < 2 ) {
updates.emplace(i, j, false);
} else if ( d == 2 || d == 3 ) {
@@ -122,7 +119,7 @@ class World {
std::size_t age_{};
std::size_t population_{};
- std::array<std::array<bool, WIDTH>, HEIGHT> matrix_;
+ util::TorusArray<bool, WIDTH, HEIGHT> matrix_;
};