aboutsummaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2022-07-01 16:01:04 +0200
committerHampusM <hampus@hampusmat.com>2022-07-01 16:01:04 +0200
commit7307815e99a79dac42f2a9c06b0fe6171ea11ba0 (patch)
treead41ee819dc87fc2653caf720fa7d1df30c0caeb /src/game
parent2bff8c999edde11270ecaf6fbd2d24f54d0e360b (diff)
refactor: use ranges
Diffstat (limited to 'src/game')
-rw-r--r--src/game/RLE_reader.cpp44
-rw-r--r--src/game/cell_helper.hpp9
-rw-r--r--src/game/cell_helper_impl.hpp121
-rw-r--r--src/game/components/statusline.cpp23
-rw-r--r--src/game/game.cpp86
-rw-r--r--src/game/game.hpp5
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;
};