mirror of
https://github.com/kepler155c/opus
synced 2024-12-29 10:00:26 +00:00
169 lines
4.0 KiB
Lua
169 lines
4.0 KiB
Lua
|
-- Various utilities for Jumper top-level modules
|
||
|
|
||
|
if (...) then
|
||
|
|
||
|
-- Dependencies
|
||
|
local _PATH = (...):gsub('%.utils$','')
|
||
|
local Path = require (_PATH .. '.path')
|
||
|
local Node = require (_PATH .. '.node')
|
||
|
|
||
|
-- Local references
|
||
|
local pairs = pairs
|
||
|
local type = type
|
||
|
local t_insert = table.insert
|
||
|
local assert = assert
|
||
|
local coroutine = coroutine
|
||
|
|
||
|
-- Raw array items count
|
||
|
local function arraySize(t)
|
||
|
local count = 0
|
||
|
for k,v in pairs(t) do
|
||
|
count = count+1
|
||
|
end
|
||
|
return count
|
||
|
end
|
||
|
|
||
|
-- Parses a string map and builds an array map
|
||
|
local function stringMapToArray(str)
|
||
|
local map = {}
|
||
|
local w, h
|
||
|
for line in str:gmatch('[^\n\r]+') do
|
||
|
if line then
|
||
|
w = not w and #line or w
|
||
|
assert(#line == w, 'Error parsing map, rows must have the same size!')
|
||
|
h = (h or 0) + 1
|
||
|
map[h] = {}
|
||
|
for char in line:gmatch('.') do
|
||
|
map[h][#map[h]+1] = char
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
return map
|
||
|
end
|
||
|
|
||
|
-- Collects and returns the keys of a given array
|
||
|
local function getKeys(t)
|
||
|
local keys = {}
|
||
|
for k,v in pairs(t) do keys[#keys+1] = k end
|
||
|
return keys
|
||
|
end
|
||
|
|
||
|
-- Calculates the bounds of a 2d array
|
||
|
local function getArrayBounds(map)
|
||
|
local min_x, max_x
|
||
|
local min_y, max_y
|
||
|
for y in pairs(map) do
|
||
|
min_y = not min_y and y or (y<min_y and y or min_y)
|
||
|
max_y = not max_y and y or (y>max_y and y or max_y)
|
||
|
for x in pairs(map[y]) do
|
||
|
min_x = not min_x and x or (x<min_x and x or min_x)
|
||
|
max_x = not max_x and x or (x>max_x and x or max_x)
|
||
|
end
|
||
|
end
|
||
|
return min_x,max_x,min_y,max_y
|
||
|
end
|
||
|
|
||
|
-- Converts an array to a set of nodes
|
||
|
local function arrayToNodes(map)
|
||
|
local min_x, max_x
|
||
|
local min_y, max_y
|
||
|
local min_z, max_z
|
||
|
local nodes = {}
|
||
|
for y in pairs(map) do
|
||
|
min_y = not min_y and y or (y<min_y and y or min_y)
|
||
|
max_y = not max_y and y or (y>max_y and y or max_y)
|
||
|
nodes[y] = {}
|
||
|
for x in pairs(map[y]) do
|
||
|
min_x = not min_x and x or (x<min_x and x or min_x)
|
||
|
max_x = not max_x and x or (x>max_x and x or max_x)
|
||
|
nodes[y][x] = {}
|
||
|
for z in pairs(map[y][x]) do
|
||
|
min_z = not min_z and z or (z<min_z and z or min_z)
|
||
|
max_z = not max_z and z or (z>max_z and z or max_z)
|
||
|
nodes[y][x][z] = Node:new(x,y,z)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
return nodes,
|
||
|
(min_x or 0), (max_x or 0),
|
||
|
(min_y or 0), (max_y or 0),
|
||
|
(min_z or 0), (max_z or 0)
|
||
|
end
|
||
|
|
||
|
-- Iterator, wrapped within a coroutine
|
||
|
-- Iterates around a given position following the outline of a square
|
||
|
local function around()
|
||
|
local iterf = function(x0, y0, z0, s)
|
||
|
local x, y, z = x0-s, y0-s, z0-s
|
||
|
coroutine.yield(x, y, z)
|
||
|
repeat
|
||
|
x = x + 1
|
||
|
coroutine.yield(x,y,z)
|
||
|
until x == x0+s
|
||
|
repeat
|
||
|
y = y + 1
|
||
|
coroutine.yield(x,y,z)
|
||
|
until y == y0 + s
|
||
|
repeat
|
||
|
z = z + 1
|
||
|
coroutine.yield(x,y,z)
|
||
|
until z == z0 + s
|
||
|
repeat
|
||
|
x = x - 1
|
||
|
coroutine.yield(x, y,z)
|
||
|
until x == x0-s
|
||
|
repeat
|
||
|
y = y - 1
|
||
|
coroutine.yield(x,y,z)
|
||
|
until y == y0-s+1
|
||
|
repeat
|
||
|
z = z - 1
|
||
|
coroutine.yield(x,y,z)
|
||
|
until z == z0-s+1
|
||
|
end
|
||
|
return coroutine.create(iterf)
|
||
|
end
|
||
|
|
||
|
-- Extract a path from a given start/end position
|
||
|
local function traceBackPath(finder, node, startNode)
|
||
|
local path = Path:new()
|
||
|
path._grid = finder._grid
|
||
|
while true do
|
||
|
if node._parent then
|
||
|
t_insert(path._nodes,1,node)
|
||
|
node = node._parent
|
||
|
else
|
||
|
t_insert(path._nodes,1,startNode)
|
||
|
return path
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Lookup for value in a table
|
||
|
local indexOf = function(t,v)
|
||
|
for i = 1,#t do
|
||
|
if t[i] == v then return i end
|
||
|
end
|
||
|
return nil
|
||
|
end
|
||
|
|
||
|
-- Is i out of range
|
||
|
local function outOfRange(i,low,up)
|
||
|
return (i< low or i > up)
|
||
|
end
|
||
|
|
||
|
return {
|
||
|
arraySize = arraySize,
|
||
|
getKeys = getKeys,
|
||
|
indexOf = indexOf,
|
||
|
outOfRange = outOfRange,
|
||
|
getArrayBounds = getArrayBounds,
|
||
|
arrayToNodes = arrayToNodes,
|
||
|
strToMap = stringMapToArray,
|
||
|
around = around,
|
||
|
drAround = drAround,
|
||
|
traceBackPath = traceBackPath
|
||
|
}
|
||
|
|
||
|
end
|