#pragma once #include "cell_helper.hpp" #include "util/algorithm.hpp" template constexpr auto has_matrix_value( const std::shared_ptr> &matrix, const MatrixElement &value) noexcept { return [&matrix, &value](const Vector2 &pos) { return matrix->get(pos) == value; }; } 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 { const auto neighbour_cell_positions = container_filter(find_neighbours(cell_pos), has_matrix_value(_matrix, 'x')); const auto neighbour_cell_cnt = neighbour_cell_positions.size(); return neighbour_cell_cnt < 2 || neighbour_cell_cnt >= 4; } template auto CellHelper::get_birth_cell_positions( const std::list &cell_positions) const noexcept -> std::list { auto all_empty_neighbour_positions = std::list(); for (const auto &cell_pos : cell_positions) { const std::vector empty_neighbour_positions = container_filter(find_neighbours(cell_pos), has_matrix_value(_matrix, ' ')); all_empty_neighbour_positions.insert( all_empty_neighbour_positions.end(), empty_neighbour_positions.begin(), empty_neighbour_positions.end()); } // Remove duplicates all_empty_neighbour_positions.sort(); all_empty_neighbour_positions.unique(); auto birth_cell_positions = container_filter( all_empty_neighbour_positions, [this](const Vector2 &cell_pos) { const auto neighbour_cell_positions = container_filter( find_neighbours(cell_pos), has_matrix_value(_matrix, 'x')); return neighbour_cell_positions.size() == 3; }); return birth_cell_positions; } template auto CellHelper::find_neighbours(const Vector2 &cell_pos) const noexcept -> std::vector { std::vector cell_positions = {}; const auto matrix_size = Bounds({.width = _matrix->get_column_cnt(), .height = _matrix->get_row_cnt()}); const auto neighbours = _get_position_neighbours(cell_pos); for (const auto &neighbour_pos : neighbours) { if (matrix_size.validate_coords(neighbour_pos) == CoordsValidation::VALID) { cell_positions.push_back(neighbour_pos); } } return cell_positions; } template auto CellHelper::_get_position_neighbours(const Vector2 &position) noexcept -> std::list { 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()}; }