#pragma once #include "interfaces/RLE_reader.hpp" #include "interfaces/cell_helper.hpp" #include "interfaces/cursor.hpp" #include "interfaces/game.hpp" #include "interfaces/generation_tracker.hpp" #include "interfaces/input.hpp" #include "interfaces/matrix.hpp" #include "interfaces/scene.hpp" #include "interfaces/status_manager.hpp" #include "interfaces/statusline.hpp" #include "engine/data/vector2.hpp" #include #include #include #include #include #include #include #include #include constexpr auto DEFAULT_GENERATIONS_PER_SECOND = 5L; constexpr auto MAXIMUM_GENERATIONS_PER_SECOND = 512L; constexpr auto MILLIS_IN_SECOND = 1000; constexpr auto CURSOR_FALLBACK_POS_X = 10; constexpr auto CURSOR_FALLBACK_POS_Y = 10; constexpr std::string_view ERASE_ENTIRE_LINE = "{esc}[2K"; constexpr std::string_view ERASE_LINE_FROM_CURSOR = "{esc}[0K"; enum Mode { NORMAL, COMMAND }; class CommandInfo { public: using Options = const std::vector &; using CommandFunction = std::function; std::size_t option_cnt; CommandFunction function; }; class Game : public IGame { public: Game( IStatusLineFactory statusline_factory, std::shared_ptr scene, std::shared_ptr cursor_controller, std::shared_ptr generation_tracker, std::shared_ptr status_manager, std::shared_ptr user_input_observer, std::shared_ptr cell_helper, std::shared_ptr rle_reader) noexcept; void on_start() noexcept override; void on_update() noexcept override; void on_exit() const noexcept override; private: IStatusLineFactory _statusline_factory; std::shared_ptr _scene; std::shared_ptr _cursor_controller; std::shared_ptr _generation_tracker; std::shared_ptr _status_manager; std::shared_ptr _user_input_observer; std::shared_ptr _cell_helper; std::shared_ptr _rle_reader; Mode _current_mode; CursorStyle _normal_mode_cursor_style; CursorStyle _command_mode_cursor_style; int32_t _minimum_cursor_pos_y; std::optional _last_pos_before_command_mode; std::string _command_mode_input; std::unordered_map _commands; std::chrono::system_clock::time_point _last_gen_update_time; int64_t _generations_per_second = DEFAULT_GENERATIONS_PER_SECOND; std::list _living_cell_positions; void _on_normal_mode_update() noexcept; void _on_command_mode_update() noexcept; void _return_to_normal_mode() noexcept; void _run_command(const std::string &command) noexcept; void _show_command_error(const std::string_view &error_message) noexcept; auto _move_cursor(const Vector2 &direction) noexcept -> bool; void _set_space( const std::shared_ptr> &matrix, const Vector2 &position, char character) noexcept; static void _erase_entire_line() noexcept; static void _erase_line_from_cursor() noexcept; };