Create CLI

....I forgot to commit, didn't I?
This commit is contained in:
Starbeamrainbowlabs 2020-04-29 19:57:18 +01:00
parent c74074402e
commit c3768aca2e
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
7 changed files with 241 additions and 125 deletions

4
.gitignore vendored
View file

@ -1,4 +1,6 @@
*.png
*.scad
*.blend1
# Created by https://www.gitignore.io/api/lua,git # Created by https://www.gitignore.io/api/lua,git
# Edit at https://www.gitignore.io/?templates=lua,git # Edit at https://www.gitignore.io/?templates=lua,git

118
main.lua Normal file
View file

@ -0,0 +1,118 @@
local strings = require("./utils/strings")
local debug = require("./utils/print_r")
local maze2d = require("./maze")
local maze3d = require("./maze3d")
local openscad = require("./openscad")
local settings = {
mode = "help",
extras = {},
width = 11,
height = 11,
depth = 7,
filename = "maze.scad"
}
for i=1,#arg do
if not strings.starts_with(arg[i], "-") then
table.insert(settings.extras, arg[i])
elseif string.match(arg[i], "--width") or string.match(arg[i], "-w") then
i = i + 1
settings.width = tonumber(arg[i])
elseif string.match(arg[i], "--height") or string.match(arg[i], "-h") then
i = i + 1
settings.height = tonumber(arg[i])
elseif string.match(arg[i], "--depth") or string.match(arg[i], "-d") then
i = i + 1
settings.depth = tonumber(arg[i])
elseif string.match(arg[i], "--seed") or string.match(arg[i], "-s") then
i = i + 1
settings.seed = tonumber(arg[i])
elseif string.match(arg[i], "--filename") or string.match(arg[i], "-f") then
i = i + 1
settings.filename = arg[i]
end
end
if #settings.extras > 0 then
settings.mode = table.remove(settings.extras, 1)
end
local function help()
print([[
multimaze: Multidimensional maze generator
By Starbeamrainbowlabs
Usage:
lua main.lua {mode} [{options}]
Modes:
help Displays this message
maze Generates a 2d maze
maze3d Generates a 3d maze
maze3d_openscad Generates a 3d maze as an openscad file
Options:
-w --width Sets the width of the maze
-h --height Sets the height of the maze
-d --depth Sets the depth of the maze (only applicable to 3d mazes)
-s --seed Sets the seed
-f --filename Sets the output filename
]])
end
local function maze_text()
local world, time = maze2d.generate_maze(
os.time(),
settings.width,
settings.height
)
maze2d.printspace(world, settings.width, settings.height)
print("Generation completed in " .. time .. "ms.")
end
local function maze3d_text()
local world, time = maze3d.generate_maze(
os.time(),
settings.width,
settings.height,
settings.depth
)
maze3d.printspace(world, settings.width, settings.height, settings.depth)
print("Generation completed in " .. time .. "ms.")
end
local function maze3d_openscad()
local world, time = maze3d.generate_maze(
os.time(),
settings.width,
settings.height,
settings.depth
)
openscad.write3d(
world,
settings.width, settings.height, settings.depth,
settings.filename
)
print("Maze written to "..settings.filename)
end
local mode_functions = {
["help"] = help,
["maze"] = maze_text,
["maze3d"] = maze3d_text,
["maze3d_openscad"] = maze3d_openscad
}
local selection = mode_functions[settings.mode]
if not selection then
print("Error: Unrecognised mode '"..settings.mode.."'")
selection = mode_functions["help"]
end
selection()

View file

@ -3,60 +3,25 @@
------------------------------------- -------------------------------------
-- A test by @Starbeamrainbowlabs -- A test by @Starbeamrainbowlabs
--------------------------------------------- local M = {}
-- Intelligent table printing function
---------------------------------------------
-- From http://coronalabs.com/blog/2014/09/02/tutorial-printing-table-contents/
function print_r ( t ) -- Intelligent table printing function: http://coronalabs.com/blog/2014/09/02/tutorial-printing-table-contents/
local print_r_cache={}
local function sub_print_r(t,indent)
if (print_r_cache[tostring(t)]) then
print(indent.."*"..tostring(t))
else
print_r_cache[tostring(t)]=true
if (type(t)=="table") then
for pos,val in pairs(t) do
if (type(val)=="table") then
print(indent.."["..pos.."] => "..tostring(t).." {")
sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
print(indent..string.rep(" ",string.len(pos)+6).."}")
elseif (type(val)=="string") then
print(indent.."["..pos..'] => "'..val..'"')
else
print(indent.."["..pos.."] => "..tostring(val))
end
end
else
print(indent..tostring(t))
end
end
end
if (type(t)=="table") then
print(tostring(t).." {")
sub_print_r(t," ")
print("}")
else
sub_print_r(t," ")
end
print()
end
if arg[1] ~= nil then -- if arg[1] ~= nil then
width = tonumber(arg[1]) -- width = tonumber(arg[1])
else -- else
width = 35 -- width = 35
end -- end
if arg[2] ~= nil then -- if arg[2] ~= nil then
height = tonumber(arg[2]) -- height = tonumber(arg[2])
else -- else
height = 15 -- height = 15
end -- end
---------------------------------- ----------------------------------
-- function to print out the world -- function to print out the world
---------------------------------- ----------------------------------
function printspace(space, w, h) function M.printspace(space, w, h)
for y = 0, h - 1, 1 do for y = 0, h - 1, 1 do
local line = "" local line = ""
for x = 0, w - 1, 1 do for x = 0, w - 1, 1 do
@ -67,9 +32,9 @@ function printspace(space, w, h)
end end
-- Initialise the world -- Initialise the world
start_time = os.clock()
function generate_maze(seed, width, height) function M.generate_maze(seed, width, height)
start_time = os.clock()
-- minetest.log("action", "width: "..width..", height: "..height) -- minetest.log("action", "width: "..width..", height: "..height)
math.randomseed(seed) -- seed the random number generator with the system clock math.randomseed(seed) -- seed the random number generator with the system clock
@ -151,11 +116,13 @@ function generate_maze(seed, width, height)
--printspace(world, width, height) --printspace(world, width, height)
end end
return world end_time = os.clock()
return world, (end_time - start_time) * 1000
end end
local world = generate_maze(os.time(), width, height) -- local world, time = generate_maze(os.time(), width, height)
-- printspace(world, width, height)
-- print("Generation completed in " .. time .. "s.")
printspace(world, width, height) return M
end_time = os.clock()
print("Generation completed in " .. (end_time - start_time) .. "s.")

View file

@ -2,45 +2,7 @@
-- 3D Maze generation script -- 3D Maze generation script
------------------------------------- -------------------------------------
-- A test by @Starbeamrainbowlabs -- A test by @Starbeamrainbowlabs
local M = {}
---------------------------------------------
-- Intelligent table printing function
---------------------------------------------
-- From http://coronalabs.com/blog/2014/09/02/tutorial-printing-table-contents/
function print_r ( t )
local print_r_cache = {}
local function sub_print_r(t, indent)
if (print_r_cache[tostring(t)]) then
print(indent.."*"..tostring(t))
else
print_r_cache[tostring(t)] = true
if (type(t) == "table") then
for pos, val in pairs(t) do
if (type(val) == "table") then
print(indent.."["..pos.."] => "..tostring(t).." {")
sub_print_r(val, indent..string.rep(" ", string.len(pos) + 8))
print(indent..string.rep(" ", string.len(pos) + 6).."}")
elseif (type(val) == "string") then
print(indent.."["..pos..'] => "'..val..'"')
else
print(indent.."["..pos.."] => "..tostring(val))
end
end
else
print(indent..tostring(t))
end
end
end
if (type(t) == "table") then
print(tostring(t).." {")
sub_print_r(t, " ")
print("}")
else
sub_print_r(t, " ")
end
print()
end
if arg[1] ~= nil then if arg[1] ~= nil then
width = tonumber(arg[1]) width = tonumber(arg[1])
@ -66,7 +28,7 @@ end
---------------------------------- ----------------------------------
-- function to print out the world -- function to print out the world
---------------------------------- ----------------------------------
function printspace(space, w, h, d) function M.printspace(space, w, h, d)
for z = 0, d - 1, 1 do for z = 0, d - 1, 1 do
for y = 0, h - 1, 1 do for y = 0, h - 1, 1 do
local line = "" local line = ""
@ -80,9 +42,10 @@ function printspace(space, w, h, d)
end end
-- Initialise the world -- Initialise the world
start_time = os.clock()
function generate_maze3d(seed, width, height, depth) function M.generate_maze(seed, width, height, depth)
start_time = os.clock()
print("Generating maze "..width.."x"..height.."x"..depth) print("Generating maze "..width.."x"..height.."x"..depth)
math.randomseed(seed) -- seed the random number generator with the system clock math.randomseed(seed) -- seed the random number generator with the system clock
@ -113,7 +76,6 @@ function generate_maze3d(seed, width, height, depth)
local directions = "" -- the different directions we can move in local directions = "" -- the different directions we can move in
if cz - 2 > 0 and world[cz - 2][cy][cx] == "#" then if cz - 2 > 0 and world[cz - 2][cy][cx] == "#" then
directions = directions .. "-" directions = directions .. "-"
-- print("cz: "..cz..", cz - 2: "..(cz-2)..", here: '"..world[cz][cy][cx].."', there: '"..world[cz - 2][cy][cx].."'")
end end
if cz + 2 < depth and world[cz + 2][cy][cx] == "#" then if cz + 2 < depth and world[cz + 2][cy][cx] == "#" then
directions = directions .. "+" directions = directions .. "+"
@ -131,17 +93,12 @@ function generate_maze3d(seed, width, height, depth)
directions = directions .. "r" directions = directions .. "r"
end end
print("Currently at ("..cx..", "..cy..", "..cz..") - directions: "..directions)
--print("radar output: '" .. directions .. "' (length: " .. #directions .. "), curnode: " .. curnode) --print("radar output: '" .. directions .. "' (length: " .. #directions .. "), curnode: " .. curnode)
if #directions > 0 then if #directions > 0 then
-- we still have somewhere that we can go -- we still have somewhere that we can go
--print("This node is not a dead end yet.")
local curdirnum = math.random(1, #directions) local curdirnum = math.random(1, #directions)
local curdir = string.sub(directions, curdirnum, curdirnum) local curdir = string.sub(directions, curdirnum, curdirnum)
print("Picked direction '"..curdir.."' (index "..curdirnum..")")
if curdir == "+" then if curdir == "+" then
world[cz + 1][cy][cx] = " " world[cz + 1][cy][cx] = " "
world[cz + 2][cy][cx] = " " world[cz + 2][cy][cx] = " "
@ -168,37 +125,28 @@ function generate_maze3d(seed, width, height, depth)
cx = cx + 2 cx = cx + 2
end end
print("Now at ("..cx..", "..cy..", "..cz..") ")
table.insert(nodes, { x = cx, y = cy, z = cz }) table.insert(nodes, { x = cx, y = cy, z = cz })
else else
-- print("The node at " .. curnode .. " is a dead end.")
table.remove(nodes, curnode) table.remove(nodes, curnode)
if #nodes > 0 then if #nodes > 0 then
--print("performing teleport.");
curnode = math.random(1, #nodes) curnode = math.random(1, #nodes)
--print("New node: " .. curnode)
-- print("Nodes table: ")
-- print_r(nodes)
cx = nodes[curnode]["x"] cx = nodes[curnode]["x"]
cy = nodes[curnode]["y"] cy = nodes[curnode]["y"]
cz = nodes[curnode]["z"] cz = nodes[curnode]["z"]
else
--print("Maze generation complete, no teleportation necessary.")
end end
end end
-- io.read("*l")
-- print("\n\n\n\n\n\n\n\n\n")
-- printspace(world, width + 1, height + 1, depth + 1)
end end
return world end_time = os.clock()
return world, (end_time - start_time) * 1000
end end
local world = generate_maze3d(seed, width, height, depth) return M
printspace(world, width, height, depth) -- local world = M.generate_maze3d(seed, width, height, depth)
end_time = os.clock() --
print("Generation completed in " .. (end_time - start_time) .. "s.") -- M.printspace(world, width, height, depth)
-- end_time = os.clock()
-- print("Generation completed in " .. (end_time - start_time) .. "s.")

28
openscad.lua Normal file
View file

@ -0,0 +1,28 @@
local M = {}
function M.write3d(maze, width, height, depth, filename)
local scale = 5
local inverted = true
local out = io.open(filename, "w")
out:write("// Generated by multimaze (lua)\n")
out:write("// Hit the Render button (F6) to make the preview look better")
out:write("// Uncomment to make the preview look transclucent")
out:write("// color(\"red\", 0.25)\n");
if inverted then out:write("difference() {\n\tcube(size=["..scale*width..", "..scale*height..", "..scale*depth.."])")
else out:write("union() {") end
out:write("\n")
for z = 0, depth - 1, 1 do
for y = 0, height - 1, 1 do
for x = 0, width - 1, 1 do
if maze[z][y][x] == "#" then
out:write("\ttranslate(["..x*scale..", "..y*scale..", "..z*scale.."]) cube(size = "..scale..");\n")
end
end
end
end
out:write("}\n")
out:close()
end
return M

42
utils/print_r.lua Normal file
View file

@ -0,0 +1,42 @@
local M = {}
---------------------------------------------
-- Intelligent table printing function
---------------------------------------------
-- From http://coronalabs.com/blog/2014/09/02/tutorial-printing-table-contents/
function M.print_r ( t )
local print_r_cache = {}
local function sub_print_r(t, indent)
if (print_r_cache[tostring(t)]) then
print(indent.."*"..tostring(t))
else
print_r_cache[tostring(t)] = true
if (type(t) == "table") then
for pos, val in pairs(t) do
if (type(val) == "table") then
print(indent.."["..pos.."] => "..tostring(t).." {")
sub_print_r(val, indent..string.rep(" ", string.len(pos) + 8))
print(indent..string.rep(" ", string.len(pos) + 6).."}")
elseif (type(val) == "string") then
print(indent.."["..pos..'] => "'..val..'"')
else
print(indent.."["..pos.."] => "..tostring(val))
end
end
else
print(indent..tostring(t))
end
end
end
if (type(t) == "table") then
print(tostring(t).." {")
sub_print_r(t, " ")
print("}")
else
sub_print_r(t, " ")
end
print()
end
return M;

11
utils/strings.lua Normal file
View file

@ -0,0 +1,11 @@
local M = {}
function M.starts_with(str, start)
return str:sub(1, #start) == start
end
function M.ends_with(str, ending)
return ending == "" or str:sub(-#ending) == ending
end
return M