#pragma once #include "cell_helper.hpp" #include #include #include #include #include #include #include #include #include template CellHelper::CellHelper( std::shared_ptr> matrix) noexcept : _matrix(std::move(matrix)) { } template auto CellHelper::is_cell_dying(const Vector2 &cell_pos) const noexcept -> bool { int64_t neighbour_cell_cnt = ranges::count_if( find_neighbours(cell_pos), [this](const Vector2 &pos) { return _matrix->get(pos) == 'x'; }); return neighbour_cell_cnt < 2 || neighbour_cell_cnt >= 4; } template auto CellHelper::get_birth_cell_positions( const std::vector &cell_positions) const noexcept -> std::vector { std::vector empty_neighbour_positions = ranges::fold_left( cell_positions, std::vector(), [this](std::vector acc, const Vector2 &pos) { std::vector neighbours = find_neighbours(pos); auto empty_neighbours = neighbours | ranges::views::filter( [this](const Vector2 &neighbour_pos) { return _matrix->get(neighbour_pos) == ' '; }); ranges::actions::insert(acc, acc.end(), empty_neighbours); return acc; }) | ranges::actions::sort | ranges::actions::unique; auto birth_cell_positions = empty_neighbour_positions | ranges::views::filter( [this](const Vector2 &cell_pos) { auto neighbours = find_neighbours(cell_pos); int64_t neighbour_cell_cnt = ranges::count_if( neighbours, [this](const Vector2 &neighbour_pos) { return _matrix->get(neighbour_pos) == 'x'; }); return neighbour_cell_cnt == 3; }); return birth_cell_positions | ranges::to(); } template auto CellHelper::find_neighbours(const Vector2 &cell_pos) const noexcept -> std::vector { const auto matrix_size = Bounds({.width = _matrix->get_column_cnt(), .height = _matrix->get_row_cnt()}); const auto neighbours = _get_position_neighbours(cell_pos); return neighbours | ranges::views::filter( [&matrix_size](const Vector2 &neighbour_pos) { return matrix_size.validate_coords(neighbour_pos) == CoordsValidation::VALID; }) | ranges::to(); } template auto CellHelper::_get_position_neighbours(const Vector2 &position) noexcept -> std::vector { return { position + Vector2::up(), position + Vector2::down(), position + Vector2::left(), position + Vector2::right(), position + Vector2::up() + Vector2::left(), position + Vector2::up() + Vector2::right(), position + Vector2::down() + Vector2::left(), position + Vector2::down() + Vector2::right()}; }