aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Kummerlaender2017-03-24 22:47:19 +0100
committerAdrian Kummerlaender2017-03-24 23:12:22 +0100
commitc09a4f39f742a94b150cad6a3fb0bbbfbb99e495 (patch)
treef1ecea6ba17f75af4c71b8a30beeafac09454673
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.
-rw-r--r--life.cc2
-rw-r--r--src/util/torus_array.h52
-rw-r--r--src/world.h35
3 files changed, 69 insertions, 20 deletions
diff --git a/life.cc b/life.cc
index 3af4e69..a60667e 100644
--- a/life.cc
+++ b/life.cc
@@ -41,7 +41,7 @@ void draw(
int main(int, char*[]) {
util::TermGuard guard;
- life::World<60,40> world;
+ life::World<80,40> world;
std::size_t worldOffsetX = tb_width() / 2 - world.width / 2;
std::size_t worldOffsetY = tb_height() / 2 - world.height / 2;
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_;
};