Merge pull request 'feature/rla-11_AlgorithmsP1' (#12) from feature/rla-11_AlgorithmsP1 into master

Reviewed-on: #12
This commit was merged in pull request #12.
This commit is contained in:
2023-07-23 05:04:15 +00:00
9 changed files with 150 additions and 15 deletions

View File

@@ -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

View File

@@ -0,0 +1,36 @@
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()
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
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)

View File

@@ -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)

View File

@@ -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<sol::state> LuaContextManager::load_resource(std::string args) {
auto lua = std::make_shared<sol::state>();
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;
}

View File

@@ -3,8 +3,10 @@
//
#include "algorithmmanager.hpp"
#include "../engine/modules/logger.hpp"
#include <utility>
#include <fmt/format.h>
void AlgorithmManager::register_algorithm(std::string name, sol::function initialize, sol::function update,
unsigned int updates_per_second) {
@@ -19,6 +21,42 @@ void AlgorithmManager::register_algorithm(std::string name, sol::function initia
}
ranges::any_view<DungeonAlgorithm> AlgorithmManager::get_algorithms() {
return algorithms;
ranges::any_view<DungeonAlgorithm*, ranges::category::random_access | ranges::category::sized> 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;
if(algorithm_done) {
Logger::log(LogLevel::DEBUG, "Finished running algorithm");
}
}
else {
algorithm_done = true;
sol::error err = update_result;
Logger::log(LogLevel::ERROR, fmt::format("An error occurred while running update: {}", err.what()));
}
}
ticks++;
}

View File

@@ -8,8 +8,8 @@
#include <range/v3/view.hpp>
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<DungeonAlgorithm> 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<DungeonAlgorithm> get_algorithms();
ranges::any_view<DungeonAlgorithm*, ranges::category::random_access | ranges::category::sized> get_algorithms();
void load_algorithm(DungeonAlgorithm* algorithm, int w, int h);
void tick_algorithm();
explicit AlgorithmManager(unsigned int targetFps) : target_fps(targetFps) {}
AlgorithmManager() = default;
};

View File

@@ -4,12 +4,16 @@
#include "tilemap.hpp"
#include "../engine/utility/point.hpp"
#include "../engine/modules/logger.hpp"
#include <fmt/format.h>
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);

View File

@@ -2,6 +2,7 @@
// Created by m on 12/3/21.
//
#include <filesystem>
#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>("AlgorithmManager", sol::no_constructor);
algo_manager_lua["register_algorithm"] = &AlgorithmManager::register_algorithm;
auto game_state_lua = lua->new_usertype<Visualizer>("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;

View File

@@ -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<InputProcessorKeycode, DungeonAlgorithm*> 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();
};