From d7fa6069f886158fda39a8522b1a2014ced84a2e Mon Sep 17 00:00:00 2001 From: m Date: Sun, 23 Jul 2023 00:57:19 -0400 Subject: [PATCH 1/2] Drunken walk working but needs some updates as it can go 'off map' and then walk back in, effectively --- documents/algorithms.txt | 3 +- scripts/algorithms/drunk_walk.lua | 34 +++++++++++++++++++ scripts/algorithms/test.lua | 18 ++++++++++ src/engine/scripting/luacontextmanager.cpp | 2 +- src/game/algorithmmanager.cpp | 39 ++++++++++++++++++++-- src/game/algorithmmanager.hpp | 18 +++++----- src/game/tilemap.cpp | 5 +++ src/game/visualizer.cpp | 37 ++++++++++++++++++++ src/game/visualizer.hpp | 4 ++- 9 files changed, 145 insertions(+), 15 deletions(-) create mode 100644 scripts/algorithms/drunk_walk.lua create mode 100644 scripts/algorithms/test.lua diff --git a/documents/algorithms.txt b/documents/algorithms.txt index 0e2e913..9d43ddb 100644 --- a/documents/algorithms.txt +++ b/documents/algorithms.txt @@ -23,5 +23,6 @@ Necessary: init_function(map_w, map_h) Should initialize the function fresh with a given width and height. -update(map) +update() Called updates_per_second times per second. Should calculate new map state and draw on the map as needed. The map will have the previous state retained. +Returns true if finished, else false diff --git a/scripts/algorithms/drunk_walk.lua b/scripts/algorithms/drunk_walk.lua new file mode 100644 index 0000000..3134afe --- /dev/null +++ b/scripts/algorithms/drunk_walk.lua @@ -0,0 +1,34 @@ +require "math" +DrunkenWalk = { + curr_x = 0, + curr_y = 0, + map_w = 0, + map_h = 0, + iterations = 30 +} + +function DrunkenWalk:initialize(w, h) + math.randomseed(os.time()) + self.map_w = w + self.map_h = h + visualizer.map:fill(true) + self.curr_x = math.random(0, w-1) + self.curr_y = math.random(0, h-1); +end + +function DrunkenWalk:update() + self.curr_x = self.curr_x + math.random(-1, 1) + self.curr_y = self.curr_y + math.random(-1, 1) + while self.curr_x >= self.map_w or self.curr_x < 0 or self.curr_y >= self.map_h or self.curr_y < 0 do + self.curr_x = self.curr_x + math.random(-1, 1) + self.curr_y = self.curr_y + math.random(-1, 1) + end + visualizer.map:draw_floor(self.curr_x, self.curr_y) + self.iterations = self.iterations - 1 + if self.iterations == 0 then + return true + end + return false +end + +visualizer.algorithm_manager:register_algorithm("Drunken Walk", function (w, h) DrunkenWalk:initialize(w, h) end, function () return DrunkenWalk:update() end, 5) \ No newline at end of file diff --git a/scripts/algorithms/test.lua b/scripts/algorithms/test.lua new file mode 100644 index 0000000..02ae5e6 --- /dev/null +++ b/scripts/algorithms/test.lua @@ -0,0 +1,18 @@ +Test = {} + +function Test.initialize(w, h) + visualizer.map:fill(false) + for mx = 0, w-1 do + for my = 0, h-1 do + if mx == 0 or mx == w-1 or my == 0 or my == h-1 then + visualizer.map:draw_wall(mx, my) + end + end + end +end + +function Test.update() + +end + +visualizer.algorithm_manager:register_algorithm("Test", Test.initialize, Test.update, 1) \ No newline at end of file diff --git a/src/engine/scripting/luacontextmanager.cpp b/src/engine/scripting/luacontextmanager.cpp index 759a5a8..9545eef 100644 --- a/src/engine/scripting/luacontextmanager.cpp +++ b/src/engine/scripting/luacontextmanager.cpp @@ -11,6 +11,6 @@ std::string LuaContextManager::get_key(std::string args) { // TODO: Switch the arg to a struct and use that to init libraries std::shared_ptr LuaContextManager::load_resource(std::string args) { auto lua = std::make_shared(); - lua->open_libraries(sol::lib::base, sol::lib::package); + lua->open_libraries(sol::lib::base, sol::lib::package, sol::lib::math, sol::lib::os); return lua; } diff --git a/src/game/algorithmmanager.cpp b/src/game/algorithmmanager.cpp index e3cceb1..a204139 100644 --- a/src/game/algorithmmanager.cpp +++ b/src/game/algorithmmanager.cpp @@ -3,8 +3,10 @@ // #include "algorithmmanager.hpp" +#include "../engine/modules/logger.hpp" #include +#include void AlgorithmManager::register_algorithm(std::string name, sol::function initialize, sol::function update, unsigned int updates_per_second) { @@ -19,6 +21,39 @@ void AlgorithmManager::register_algorithm(std::string name, sol::function initia } -ranges::any_view AlgorithmManager::get_algorithms() { - return algorithms; +ranges::any_view AlgorithmManager::get_algorithms() { + auto view = algorithms | ranges::view::transform([](auto& algo) { + return &algo; + }); + return view; +} + +void AlgorithmManager::load_algorithm(DungeonAlgorithm *algorithm, int w, int h) { + algorithm_done = false; + ticks = 0; + loaded_algorithm = algorithm; + auto init_result = loaded_algorithm->initialize(w, h); + if(!init_result.valid()) { + sol::error err = init_result; + Logger::log(LogLevel::ERROR, fmt::format("error while initializing lua: {}", err.what())); + } +} + +void AlgorithmManager::tick_algorithm() { + if(this->loaded_algorithm == nullptr || algorithm_done) { + return; + } + if(ticks >= this->loaded_algorithm->frames_per_update) { + ticks = 0; + auto update_result = this->loaded_algorithm->update(); + if(update_result.valid()) { + algorithm_done = update_result; + } + else { + algorithm_done = true; + sol::error err = update_result; + Logger::log(LogLevel::ERROR, fmt::format("An error occurred while running update: {}", err.what())); + } + } + ticks++; } diff --git a/src/game/algorithmmanager.hpp b/src/game/algorithmmanager.hpp index 044c4c9..1805b95 100644 --- a/src/game/algorithmmanager.hpp +++ b/src/game/algorithmmanager.hpp @@ -8,8 +8,8 @@ #include struct DungeonAlgorithm { unsigned int frames_per_update=1; - sol::function update; - sol::function initialize; + sol::protected_function update; + sol::protected_function initialize; std::string name; }; @@ -17,17 +17,15 @@ class AlgorithmManager { private: std::vector algorithms; unsigned int target_fps=1; + unsigned int ticks=0; + DungeonAlgorithm* loaded_algorithm = nullptr; + bool algorithm_done = false; public: void register_algorithm(std::string name, sol::function initialize, sol::function update, unsigned int updates_per_second); - - void setTargetFps(unsigned int targetFps) { - target_fps = targetFps; - } - - ranges::any_view get_algorithms(); - + ranges::any_view get_algorithms(); + void load_algorithm(DungeonAlgorithm* algorithm, int w, int h); + void tick_algorithm(); explicit AlgorithmManager(unsigned int targetFps) : target_fps(targetFps) {} - AlgorithmManager() = default; }; diff --git a/src/game/tilemap.cpp b/src/game/tilemap.cpp index e3582ee..593b3e2 100644 --- a/src/game/tilemap.cpp +++ b/src/game/tilemap.cpp @@ -4,12 +4,16 @@ #include "tilemap.hpp" #include "../engine/utility/point.hpp" +#include "../engine/modules/logger.hpp" +#include void TileMap::draw_floor(int x, int y) { + Logger::log(LogLevel::DEBUG, fmt::format("Drawing floor at x: {} y: {}", x, y)); grid.insert(x, y, floor_tile); } void TileMap::draw_wall(int x, int y) { + Logger::log(LogLevel::DEBUG, fmt::format("Drawing wall at x: {} y: {}", x, y)); grid.insert(x, y, wall_tile); } @@ -18,6 +22,7 @@ char TileMap::get_tile(int x, int y) { } void TileMap::fill(bool wall) { + Logger::log(LogLevel::DEBUG, fmt::format("Running fill with wall: {}", wall)); for(Point p : grid.get_range()) { if(wall) { draw_wall(p.x, p.y); diff --git a/src/game/visualizer.cpp b/src/game/visualizer.cpp index 7087d65..1744c96 100644 --- a/src/game/visualizer.cpp +++ b/src/game/visualizer.cpp @@ -2,6 +2,7 @@ // Created by m on 12/3/21. // +#include #include "visualizer.hpp" #include "tilemap.hpp" @@ -9,6 +10,7 @@ bool Visualizer::update(InputResult input) { if(input.keycode == KEY_ESCAPE) { return true; } + this->algorithm_manager.tick_algorithm(); switch(input.keycode) { case KEY_RIGHT: x += 1; break; case KEY_LEFT: x -= 1; break; @@ -16,6 +18,12 @@ bool Visualizer::update(InputResult input) { case KEY_DOWN: y += 1; break; default: break; } + if(input.keycode >= InputProcessorKeycode::KEY_1 && input.keycode <= InputProcessorKeycode::KEY_9) { + if(this->keycode_to_algorithm.contains(input.keycode)) { + auto algorithm = this->keycode_to_algorithm[input.keycode]; + this->algorithm_manager.load_algorithm(algorithm, this->map_size_w, this->map_size_h); + } + } this->x = std::clamp(this->x, 0, (int)this->tile_map.get_width()-1); this->y = std::clamp(this->y, 0, (int)this->tile_map.get_height()-1); @@ -63,6 +71,7 @@ void Visualizer::initialize(GameInitArgs args) { this->camera = Camera(Point{x,y}, tilesx, tilesy, tile_map.get_width(), tile_map.get_height()); this->algorithm_manager = AlgorithmManager(args.target_fps); this->initialize_context(); + this->load_algorithms(); Logger::log(LogLevel::DEBUG, "Game initialization finished"); } @@ -86,6 +95,34 @@ void Visualizer::initialize_context() { auto algo_manager_lua = lua->new_usertype("AlgorithmManager", sol::no_constructor); algo_manager_lua["register_algorithm"] = &AlgorithmManager::register_algorithm; + + auto game_state_lua = lua->new_usertype("Visualizer", sol::no_constructor); + game_state_lua.set("algorithm_manager", sol::readonly(&Visualizer::algorithm_manager)); + game_state_lua.set("map", &Visualizer::tile_map); + + lua->set("visualizer", this); +} + +void Visualizer::load_algorithms() { + auto lua = lua_context_manager.get_default_context(); + const std::string algorithms_directory = "scripts/algorithms"; + + for(const auto& file : std::filesystem::directory_iterator(algorithms_directory)) { + lua->script_file(file.path()); + } + Logger::log(LogLevel::DEBUG, "finished loading lua files"); + auto algorithms = this->algorithm_manager.get_algorithms(); + auto algorithm_count = algorithms.size(); + Logger::log(LogLevel::DEBUG, fmt::format("algorithms: {}", algorithm_count)); + + for(int code = InputProcessorKeycode::KEY_1;code < InputProcessorKeycode::KEY_9;code++) { + auto index = code-InputProcessorKeycode::KEY_1; + if(algorithms.size() <= index) { + break; + } + auto algo = algorithms[index]; + this->keycode_to_algorithm[(InputProcessorKeycode)code] = algo; + } } Visualizer::~Visualizer() = default; diff --git a/src/game/visualizer.hpp b/src/game/visualizer.hpp index 7342054..9795154 100644 --- a/src/game/visualizer.hpp +++ b/src/game/visualizer.hpp @@ -38,8 +38,9 @@ private: int window_height = 0; TileMap tile_map = TileMap(0, 0, DEFAULT_WALL_CHAR[0], DEFAULT_FLOOR_CHAR[0]); Camera camera = Camera(); - LuaContextManager lua_context_manager = LuaContextManager(); + LuaContextManager lua_context_manager; AlgorithmManager algorithm_manager; + std::unordered_map keycode_to_algorithm; int x = 0; int y=0; @@ -54,6 +55,7 @@ private: void initialize_map(int width, int height); void initialize_context(); + void load_algorithms(); }; From abf3e3a7192fd9b82f42040fc0de1f68eed63631 Mon Sep 17 00:00:00 2001 From: m Date: Sun, 23 Jul 2023 01:03:10 -0400 Subject: [PATCH 2/2] Cleaned up drunken walk, closes #11 --- scripts/algorithms/drunk_walk.lua | 12 +++++++----- src/game/algorithmmanager.cpp | 3 +++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/algorithms/drunk_walk.lua b/scripts/algorithms/drunk_walk.lua index 3134afe..77f6a05 100644 --- a/scripts/algorithms/drunk_walk.lua +++ b/scripts/algorithms/drunk_walk.lua @@ -17,12 +17,14 @@ function DrunkenWalk:initialize(w, h) end function DrunkenWalk:update() - self.curr_x = self.curr_x + math.random(-1, 1) - self.curr_y = self.curr_y + math.random(-1, 1) - while self.curr_x >= self.map_w or self.curr_x < 0 or self.curr_y >= self.map_h or self.curr_y < 0 do - self.curr_x = self.curr_x + math.random(-1, 1) - self.curr_y = self.curr_y + math.random(-1, 1) + new_x = self.curr_x + math.random(-1, 1) + new_y = self.curr_y + math.random(-1, 1) + while new_x >= self.map_w or new_x < 0 or new_y >= self.map_h or new_y < 0 do + new_x = self.curr_x + math.random(-1, 1) + new_y = self.curr_y + math.random(-1, 1) end + self.curr_x = new_x + self.curr_y = new_y visualizer.map:draw_floor(self.curr_x, self.curr_y) self.iterations = self.iterations - 1 if self.iterations == 0 then diff --git a/src/game/algorithmmanager.cpp b/src/game/algorithmmanager.cpp index a204139..db8ad0f 100644 --- a/src/game/algorithmmanager.cpp +++ b/src/game/algorithmmanager.cpp @@ -48,6 +48,9 @@ void AlgorithmManager::tick_algorithm() { auto update_result = this->loaded_algorithm->update(); if(update_result.valid()) { algorithm_done = update_result; + if(algorithm_done) { + Logger::log(LogLevel::DEBUG, "Finished running algorithm"); + } } else { algorithm_done = true;