diff options
Diffstat (limited to 'src/game')
-rw-r--r-- | src/game/RLE_reader.cpp | 44 | ||||
-rw-r--r-- | src/game/cell_helper.hpp | 9 | ||||
-rw-r--r-- | src/game/cell_helper_impl.hpp | 121 | ||||
-rw-r--r-- | src/game/components/statusline.cpp | 23 | ||||
-rw-r--r-- | src/game/game.cpp | 86 | ||||
-rw-r--r-- | src/game/game.hpp | 5 |
6 files changed, 156 insertions, 132 deletions
diff --git a/src/game/RLE_reader.cpp b/src/game/RLE_reader.cpp index df2823c..79890f1 100644 --- a/src/game/RLE_reader.cpp +++ b/src/game/RLE_reader.cpp @@ -1,14 +1,19 @@ #include "RLE_reader.hpp" -#include <ctre.hpp> #include <cctype> +#include <ctre.hpp> +#include <range/v3/algorithm/find_if.hpp> +#include <range/v3/algorithm/fold_left.hpp> +#include <range/v3/range/conversion.hpp> +#include <range/v3/view/drop.hpp> +#include <range/v3/view/iota.hpp> +#include <range/v3/view/join.hpp> #include <string> #include <vector> #include "engine/data/bounds.hpp" #include "engine/data/vector2.hpp" #include "errors/RLE_reader.hpp" -#include "util/algorithm_impl.hpp" #include "util/io_impl.hpp" #include "util/string_impl.hpp" @@ -32,15 +37,14 @@ auto RLEReader::read_RLE_file(const std::filesystem::path &path) const content_lines.pop_back(); } - const auto header_line_iter = container_find( + const auto header_line_iter = ranges::find_if( content_lines, [](const std::string &line) { return ctre::starts_with<"x = \\d+, y = \\d+">(line); - // return ctre::match<"x = \\d+, y = \\d+(, rule = [a-zA-Z0-9/]+)?">(line); }); - if (header_line_iter == content_lines.end()) + if (header_line_iter == ranges::end(content_lines)) { throw InvalidRLEFileError(path, "No header line"); } @@ -64,26 +68,28 @@ auto RLEReader::read_RLE_file(const std::filesystem::path &path) const auto pattern_pos = Vector2({.x = 0, .y = 0}); - const auto first_pattern_line_iter = header_line_iter + 1; + const auto header_line_index = + static_cast<int32_t>(header_line_iter - content_lines.begin()); - for (auto pattern_line_iter = first_pattern_line_iter; - pattern_line_iter != content_lines.end(); - ++pattern_line_iter) + const auto pattern_lines = content_lines | + ranges::views::drop(header_line_index + 1) | + ranges::to<std::vector>(); + + for (const auto &pattern_line : pattern_lines) { - if (!ctre::match<"[bo$0-9!]+">(*pattern_line_iter)) + if (!ctre::match<"[bo$0-9!]+">(pattern_line)) { throw InvalidRLEFileError(path, "Invalid pattern line"); } } - auto pattern = std::string(); - - for (auto pattern_line_iter = first_pattern_line_iter; - pattern_line_iter != content_lines.end(); - ++pattern_line_iter) - { - pattern.append(*pattern_line_iter); - } + auto pattern = ranges::fold_left( + pattern_lines, + std::string(), + [](const std::string &acc, const std::string &line) + { + return acc + line; + }); auto run_count_str = std::string(); @@ -111,7 +117,7 @@ auto RLEReader::read_RLE_file(const std::filesystem::path &path) const continue; } - for (auto run_index = 0; run_index < run_count; run_index++) + for (const auto &run_index : ranges::views::iota(0, run_count)) { if (pattern_size.validate_coords(pattern_pos) != CoordsValidation::VALID) { diff --git a/src/game/cell_helper.hpp b/src/game/cell_helper.hpp index cf84a75..c54b12e 100644 --- a/src/game/cell_helper.hpp +++ b/src/game/cell_helper.hpp @@ -5,7 +5,6 @@ #include "engine/data/vector2.hpp" -#include <list> #include <memory> #include <vector> @@ -19,17 +18,17 @@ public: -> bool override; [[nodiscard]] auto - get_birth_cell_positions(const std::list<Vector2> &cell_positions) const noexcept - -> std::list<Vector2> override; + get_birth_cell_positions(const std::vector<Vector2> &cell_positions) const noexcept + -> std::vector<Vector2> override; [[nodiscard]] auto find_neighbours(const Vector2 &cell_pos) const noexcept -> std::vector<Vector2> override; private: - std::shared_ptr<IMatrix<MatrixElement>> _matrix; + const std::shared_ptr<IMatrix<MatrixElement>> _matrix; static auto _get_position_neighbours(const Vector2 &position) noexcept - -> std::list<Vector2>; + -> std::vector<Vector2>; }; #include "cell_helper_impl.hpp" diff --git a/src/game/cell_helper_impl.hpp b/src/game/cell_helper_impl.hpp index bd40794..c03b80c 100644 --- a/src/game/cell_helper_impl.hpp +++ b/src/game/cell_helper_impl.hpp @@ -2,18 +2,15 @@ #include "cell_helper.hpp" -#include "util/algorithm.hpp" - -template <typename MatrixElement> -constexpr auto has_matrix_value( - const std::shared_ptr<IMatrix<MatrixElement>> &matrix, - const MatrixElement &value) noexcept -{ - return [&matrix, &value](const Vector2 &pos) - { - return matrix->get(pos) == value; - }; -} +#include <memory> +#include <range/v3/action/insert.hpp> +#include <range/v3/action/sort.hpp> +#include <range/v3/action/unique.hpp> +#include <range/v3/algorithm/count_if.hpp> +#include <range/v3/algorithm/fold_left.hpp> +#include <range/v3/range/conversion.hpp> +#include <range/v3/view/filter.hpp> +#include <utility> template <typename MatrixElement> CellHelper<MatrixElement>::CellHelper( @@ -26,74 +23,82 @@ template <typename MatrixElement> auto CellHelper<MatrixElement>::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(); + 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 <typename MatrixElement> auto CellHelper<MatrixElement>::get_birth_cell_positions( - const std::list<Vector2> &cell_positions) const noexcept -> std::list<Vector2> + const std::vector<Vector2> &cell_positions) const noexcept -> std::vector<Vector2> { - auto all_empty_neighbour_positions = std::list<Vector2>(); - - for (const auto &cell_pos : cell_positions) - { - const std::vector<Vector2> 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; + std::vector<Vector2> empty_neighbour_positions = + ranges::fold_left( + cell_positions, + std::vector<Vector2>(), + [this](std::vector<Vector2> acc, const Vector2 &pos) + { + std::vector<Vector2> 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<std::vector>(); } template <typename MatrixElement> auto CellHelper<MatrixElement>::find_neighbours(const Vector2 &cell_pos) const noexcept -> std::vector<Vector2> { - std::vector<Vector2> 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; + return neighbours | + ranges::views::filter( + [&matrix_size](const Vector2 &neighbour_pos) + { + return matrix_size.validate_coords(neighbour_pos) == + CoordsValidation::VALID; + }) | + ranges::to<std::vector>(); } template <typename MatrixElement> auto CellHelper<MatrixElement>::_get_position_neighbours(const Vector2 &position) noexcept - -> std::list<Vector2> + -> std::vector<Vector2> { return { position + Vector2::up(), diff --git a/src/game/components/statusline.cpp b/src/game/components/statusline.cpp index aac1c27..8344c22 100644 --- a/src/game/components/statusline.cpp +++ b/src/game/components/statusline.cpp @@ -1,12 +1,11 @@ #include "statusline.hpp" #include <fmt/color.h> +#include <range/v3/view/iota.hpp> #include <utility> #include "engine/data/vector2.hpp" #include "interfaces/matrix.hpp" -#include "util/ranges.hpp" -#include "util/ranges_impl.hpp" StatusLine::StatusLine(std::shared_ptr<ComponentMatrix> component_matrix) noexcept : _component_matrix(std::move(component_matrix)), _need_render(false) @@ -55,7 +54,8 @@ void StatusLine::set_section_status( auto pos = Vector2({.x = section_start + start, .y = 0}); - const auto column_cnt = static_cast<std::int32_t>(_component_matrix->get_column_cnt()); + const auto column_cnt = + static_cast<std::int32_t>(_component_matrix->get_column_cnt()); const auto section_length = _section_lengths[section]; @@ -73,7 +73,7 @@ void StatusLine::set_section_status( _component_matrix->set(pos, {.value = ' ', .style = section_style}); padding_remaining--; - for (auto index : IotaView(0U, padding_remaining)) + for (auto index : ranges::views::iota(0U, padding_remaining)) { pos += Vector2::right(); @@ -103,11 +103,13 @@ void StatusLine::set_section_status( _matrix_write_string( pos, - status.substr(status_offset_start, static_cast<std::uint32_t>(final_status_length))); + status.substr( + status_offset_start, + static_cast<std::uint32_t>(final_status_length))); pos = pos.to_direction(Vector2::right(), final_status_length); - for (auto index : IotaView(0U, section_style.padding_right)) + for (auto index : ranges::views::iota(0U, section_style.padding_right)) { _component_matrix->set(pos, {.value = ' '}); @@ -119,7 +121,9 @@ void StatusLine::set_section_status( set_need_render(true); } -void StatusLine::set_section_length(StatusLineSection section, std::int32_t length) noexcept +void StatusLine::set_section_length( + StatusLineSection section, + std::int32_t length) noexcept { _section_lengths[section] = length; } @@ -143,7 +147,8 @@ void StatusLine::_matrix_write_string( } } -auto StatusLine::_get_section_start_x(StatusLineSection section) const noexcept -> std::int32_t +auto StatusLine::_get_section_start_x(StatusLineSection section) const noexcept + -> std::int32_t { std::int32_t section_start = 0; @@ -169,7 +174,7 @@ void StatusLine::_clear_section(StatusLineSection section, std::int32_t start) n auto section_length = _section_lengths[section]; - for (auto index : IotaView(0, section_length - start)) + for (auto index : ranges::views::iota(0, section_length - start)) { _component_matrix->set(pos, ComponentElement({.value = ' '})); diff --git a/src/game/game.cpp b/src/game/game.cpp index a121089..86b6eac 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -1,20 +1,23 @@ #include "game.hpp" +#include <cstdlib> +#include <filesystem> #include <fmt/color.h> #include <fmt/core.h> #include <fmt/format.h> -#include <yacppdic/factory.hpp> -#include <cstdlib> -#include <filesystem> #include <iostream> #include <iterator> +#include <range/v3/action/remove.hpp> +#include <range/v3/algorithm/contains.hpp> +#include <range/v3/range/conversion.hpp> +#include <range/v3/view/filter.hpp> #include <stdexcept> #include <utility> +#include <yacppdic/factory.hpp> #include "engine/data/bounds.hpp" #include "engine/escape.hpp" #include "engine/graphics/matrix_iterator.hpp" -#include "engine/graphics/matrix_iterator_impl.hpp" #include "engine/keycodes.hpp" #include "errors/RLE_reader.hpp" #include "errors/io.hpp" @@ -24,9 +27,8 @@ #include "interfaces/input.hpp" #include "interfaces/matrix.hpp" #include "interfaces/status_manager.hpp" -#include "util/algorithm_impl.hpp" #include "util/fs.hpp" -#include "util/string_impl.hpp" +#include "util/string.hpp" Game::Game( IStatusLineFactory statusline_factory, @@ -190,7 +192,7 @@ void Game::on_start() scene_matrix->set(col_pos, col); - if (!container_has(_living_cell_positions, col_pos)) + if (!ranges::contains(_living_cell_positions, col_pos)) { _living_cell_positions.push_back(col_pos); } @@ -311,7 +313,7 @@ void Game::_on_normal_mode_update() noexcept } _set_space(matrix, position, ' '); - _living_cell_positions.remove(position); + std::erase(_living_cell_positions, position); break; } @@ -390,38 +392,7 @@ void Game::_on_normal_mode_update() noexcept _last_gen_update_time = time_now; - auto matrix = _scene->get_matrix(); - - const auto dying_cell_positions = container_filter( - _living_cell_positions, - [this](const Vector2 &cell_pos) - { - return _cell_helper->is_cell_dying(cell_pos); - }); - - auto birth_cell_positions = - _cell_helper->get_birth_cell_positions(_living_cell_positions); - - for (const auto &dying_cell_pos : dying_cell_positions) - { - _set_space(matrix, dying_cell_pos, ' '); - - const auto cell_found = container_find(_living_cell_positions, dying_cell_pos); - - if (cell_found != _living_cell_positions.end()) - { - _living_cell_positions.erase(cell_found); - } - } - - for (const auto &birth_cell_pos : birth_cell_positions) - { - if (birth_cell_pos.get_y() >= _minimum_cursor_pos_y) - { - _set_space(matrix, birth_cell_pos, 'x'); - _living_cell_positions.push_back(birth_cell_pos); - } - } + _process_next_generation(); } void Game::_on_command_mode_update() noexcept @@ -640,3 +611,38 @@ void Game::_erase_line_from_cursor() noexcept std::cout.flush(); } +void Game::_process_next_generation() noexcept +{ + const auto dying_cell_positions = + _living_cell_positions | + ranges::views::filter( + [this](const Vector2 &cell_pos) + { + return _cell_helper->is_cell_dying(cell_pos); + }) | + ranges::to<std::vector>(); + + auto birth_cell_positions = + _cell_helper->get_birth_cell_positions(_living_cell_positions); + + auto matrix = _scene->get_matrix(); + + for (const auto &dying_cell_pos : dying_cell_positions) + { + _set_space(matrix, dying_cell_pos, ' '); + + if (ranges::contains(_living_cell_positions, dying_cell_pos)) + { + ranges::actions::remove(_living_cell_positions, dying_cell_pos); + } + } + + for (const auto &birth_cell_pos : birth_cell_positions) + { + if (birth_cell_pos.get_y() >= _minimum_cursor_pos_y) + { + _set_space(matrix, birth_cell_pos, 'x'); + _living_cell_positions.push_back(birth_cell_pos); + } + } +} diff --git a/src/game/game.hpp b/src/game/game.hpp index 13e229e..9fc5237 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -29,6 +29,7 @@ class IGenerationTracker; class IRLEReader; class IStatusManager; class IUserInputObserver; + template <typename ElementType> class IMatrix; @@ -107,7 +108,7 @@ private: std::int64_t _generations_per_second = DEFAULT_GENERATIONS_PER_SECOND; - std::list<Vector2> _living_cell_positions; + std::vector<Vector2> _living_cell_positions; void _on_normal_mode_update() noexcept; @@ -129,4 +130,6 @@ private: static void _erase_entire_line() noexcept; static void _erase_line_from_cursor() noexcept; + + void _process_next_generation() noexcept; }; |