local svg = require("../utils/svg_writer") ------------------------------------- -- Maze generation script ------------------------------------- -- A test by @Starbeamrainbowlabs local M = {} -- Intelligent table printing function: http://coronalabs.com/blog/2014/09/02/tutorial-printing-table-contents/ -- if arg[1] ~= nil then -- width = tonumber(arg[1]) -- else -- width = 35 -- end -- if arg[2] ~= nil then -- height = tonumber(arg[2]) -- else -- height = 15 -- end ---------------------------------- -- function to print out the world ---------------------------------- function M.printspace(space, w, h) for y = 0, h - 1, 1 do local line = "" for x = 0, w - 1, 1 do line = line .. space[y][x] end print(line) end end function M.make_svg(space, width, height, settings) -- Settings: scale, colour, inverted local result = { svg.start(width * settings.scale, height * settings.scale) } for y = 0, height - 1, 1 do for x = 0, width - 1, 1 do local do_square = false if settings.inverted then if space[y][x] == "#" then do_square = true end else if space[y][x] == " " then do_square = true end end if do_square then table.insert(result, svg.rect( x * settings.scale, y * settings.scale, settings.scale, settings.scale, settings.colour )) end end end table.insert(result, svg.finish()) return table.concat(result, "") end -- Initialise the world function M.generate_maze(seed, width, height, path_length, path_width, branching_factor) local start_time = os.clock() if not path_length then path_length = 2 end if not path_width then path_width = 1 end if not branching_factor then branching_factor = 6 end math.randomseed(seed) -- seed the random number generator with the system clock -- width = width - 1 -- height = height - 1 local world = {} for y = 0, height, 1 do world[y] = {} for x = 0, width, 1 do world[y][x] = "#" end end -- do a random walk to create pathways local nodes = {} -- the nodes left that we haven't investigated local curnode = 1 -- the node we are currently operating on local cx, cy = 1, 1 -- our current position table.insert(nodes, { x = cx, y = cy }) world[cy][cx] = " " while #nodes > 0 do -- io.write("Nodes left: " .. curnode .. "\r") --print("Nodes left: " .. #nodes) -- print("Currently at (" .. cx .. ", " .. cy .. "), up: "..(cy-path_length)..", down: "..cy+path_length..", left: "..cx-path_length..", right: "..cx+path_length..", width: "..width..", height: "..height) local directions = "" -- the different directions we can move if cy - path_length > 0 and world[cy - path_length][cx] == "#" then directions = directions .. "u" -- print("up | cy: "..cy..", target: "..cy-path_length..", value: '"..world[cy - path_length][cx].."', path_length: "..path_length) end if cy + path_length < height-path_width+1 and world[cy + path_length][cx] == "#" then directions = directions .. "d" -- print("down | cy: "..cy..", target: "..cy+path_length..", value: '"..world[cy + path_length][cx].."', path_length: "..path_length) end if cx - path_length > 0 and world[cy][cx - path_length] == "#" then directions = directions .. "l" -- print("left | cx: "..cx..", target: "..cx-path_length..", value: '"..world[cy][cx - path_length].."', path_length: "..path_length) end if cx + path_length < width-path_width+1 and world[cy][cx + path_length] == "#" then directions = directions .. "r" -- print("right | cx: "..cx..", target: "..cx+path_length..", value: '"..world[cy][cx + path_length].."', path_length: "..path_length) end -- print("radar output: '" .. directions .. "' (length: " .. #directions .. "), curnode: " .. curnode) local shift_attention = math.random(0, branching_factor) if #directions > 0 then -- we still have somewhere that we can go --print("This node is not a dead end yet.") local curdirnum = math.random(1, #directions) local curdir = string.sub(directions, curdirnum, curdirnum) if curdir == "u" then for ix = cx,cx+(path_width-1) do for iy = cy-path_length,cy do world[iy][ix] = " " end end -- world[cy - 1][cx] = " " -- world[cy - 2][cx] = " " cy = cy - path_length elseif curdir == "d" then for ix = cx,cx+path_width-1 do for iy = cy,cy+path_length+(path_width-1) do world[iy][ix] = " " end end -- world[cy + 1][cx] = " " -- world[cy + 2][cx] = " " cy = cy + path_length elseif curdir == "l" then for iy = cy,cy+path_width-1 do for ix = cx-path_length,cx do world[iy][ix] = " " end end -- world[cy][cx - 1] = " " -- world[cy][cx - 2] = " " cx = cx - path_length elseif curdir == "r" then for iy = cy,cy+(path_width-1) do for ix = cx,cx+path_length+(path_width-1) do world[iy][ix] = " " end end -- world[cy][cx + 1] = " " -- world[cy][cx + 2] = " " cx = cx + path_length end -- print("Now at ("..cx..", "..cy..")") -- If the number of directions we could travel in was 1, then we've just travelled in the last remaining direction possible -- THIS ISN'T TRUE, because we're analysing the old position and then inserting the new one - so we have to insert regardless table.insert(nodes, { x = cx, y = cy }) else --print("The node at " .. curnode .. " is a dead end.") table.remove(nodes, curnode) end if #directions == 0 or shift_attention <= 1 then if #nodes > 0 then --print("performing teleport."); curnode = math.random(1, #nodes) cx = nodes[curnode]["x"] cy = nodes[curnode]["y"] end end -- M.printspace(world, width, height) -- io.read("*l") end end_time = os.clock() return world, (end_time - start_time) * 1000 end -- local world, time = generate_maze(os.time(), width, height) -- printspace(world, width, height) -- print("Generation completed in " .. time .. "s.") return M