From c09a4f39f742a94b150cad6a3fb0bbbfbb99e495 Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Fri, 24 Mar 2017 22:47:19 +0100 Subject: 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. --- life.cc | 2 +- src/util/torus_array.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/world.h | 35 ++++++++++++++++----------------- 3 files changed, 69 insertions(+), 20 deletions(-) create mode 100644 src/util/torus_array.h 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 +#include + +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, 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 #include #include #include #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, HEIGHT> matrix_; + util::TorusArray matrix_; }; -- cgit v1.2.3