diff options
-rw-r--r-- | life.cc | 2 | ||||
-rw-r--r-- | src/util/torus_array.h | 52 | ||||
-rw-r--r-- | src/world.h | 35 |
3 files changed, 69 insertions, 20 deletions
@@ -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_; }; |