diff --git a/bundle/main.lua b/bundle/main.lua index f3b939c..24651dc 100644 --- a/bundle/main.lua +++ b/bundle/main.lua @@ -27,7 +27,7 @@ local move_repeat_counter = nil local gamemodes = {normal = 0, won = 1, lost = 2, config = 3} local game_mode = nil -local configuration_steps = {quit = -3, restart = -2, configure = -1} +local configuration_steps = {quit = -4, restart = -3, configure = -2, autoexplore = -1} local configuration_step = nil local direction_keys = {} @@ -40,10 +40,12 @@ direction_keys['.'] = directions.downright direction_keys['l'] = directions.right direction_keys['o'] = directions.upright direction_keys['space'] = directions.inplace -local control_keys = {quit = 'q', restart = 'r', configure = 'c'} +local control_keys = {quit = 'q', restart = 'r', configure = 'c', autoexplore = 'a'} local win_image = nil +local distances = {} --debg + -- ------------------------------------------------------------------ -- Cavern generation -- ------------------------------------------------------------------ @@ -713,6 +715,66 @@ function step(direction) end end +-- ------------------------------------------------------------------ +-- Autoexplore +-- ------------------------------------------------------------------ + +function autoexplore() + -- Use a pathfinding algo where each unknown but accessible space gets labelled 0, and + -- then each known accessible space gets labelled with min(neighbours) + 1. Once we have + -- computed that table, we can then move towards closest unknown accessible space by + -- moving to our neighbouring space with lowest score + --local distances = {} + distances = {} --debg + for x = 1, cavern.width do + local list = {} + for y = 1, cavern.height do + table.insert(list, {value = nil, direction = directions.inplace}) + end + table.insert(distances, list) + end + + local queue = {} + function enqueue(queue, x, y, value, direction) + if 1 < x and x < cavern.width and + 1 < y and y < cavern.height and + cavern[x][y] ~= tiletypes.wall then + table.insert(queue, {x = x, y = y, value = value, direction = direction}) + end + end + function neighbors(q, x, y, v) + -- The directions are reversed, because they tell where to go to get to the + -- unexplored areas + enqueue(q, x, y - 1, v, directions.down) + enqueue(q, x - 1, y, v, directions.right) + enqueue(q, x, y + 1, v, directions.up) + enqueue(q, x + 1, y, v, directions.left) + end + + for x, list in ipairs(visibility_map) do + for y, visible in ipairs(list) do + if not visible and remembered_cavern[x][y] == nil then + distances[x][y] = {value = 0, direction = directions.inplace} + neighbors(queue, x, y, 1) + end + end + end + + repeat + local new_queue = {} + for i, item in ipairs(queue) do + -- Write the lowest distance to each tile + if distances[item.x][item.y].value == nil or distances[item.x][item.y].value > item.value then + distances[item.x][item.y] = {value = item.value, direction = item.direction} + neighbors(new_queue, item.x, item.y, item.value + 1) + end + end + queue = new_queue + until #queue == 0 + + step(distances[player_x][player_y].direction) +end + -- ------------------------------------------------------------------ -- Drawing -- ------------------------------------------------------------------ @@ -790,6 +852,11 @@ function drawCavern() love.graphics.setColor(1, 1, 0) love.graphics.rectangle('fill', x + 0.5 * scale, y + 0.5 * scale, scale/2, scale/2) end + + if distances[tile_x] ~= nil and distances[tile_x][tile_y].value ~= nil then --debg + love.graphics.setColor(0.5, 0.5, 0.5) --debg + love.graphics.print(distances[tile_x][tile_y].value, x, y) --debg + end --debg end end end @@ -925,6 +992,8 @@ function drawConfig() text = "Restart" elseif configuration_step == configuration_steps.configure then text = "Button configuration" + elseif configuration_step == configuration_steps.autoexplore then + text = "Autoexplore" elseif configuration_step == directions.up then text = "Up" elseif configuration_step == directions.upleft then @@ -994,6 +1063,8 @@ function love.keypressed(key) control_keys.restart = key elseif configuration_step == configuration_steps.configure then control_keys.configure = key + elseif configuration_step == configuration_steps.autoexplore then + control_keys.autoexplore = key end configuration_step = configuration_step + 1 @@ -1011,6 +1082,8 @@ function love.keypressed(key) love.event.quit() elseif key == control_keys.restart then newGame() + elseif key == control_keys.autoexplore then + autoexplore() elseif direction_keys[key] ~= nil then step(direction_keys[key]) elseif key == 'pause' then