require("string") function load_level(file) local f = file_read { file = file } local result = { classes = {}, glossary = {}, grid = {}, map = {}, } -- iterate over lines local section, subsection = "none", "none" local from = 1 local start, limit = string.find(f, "\n", from) while start do local line = string.sub(f, from, start - 1) -- skip over if #line == 0 or line:find("^%-%-%s*") then goto skip -- start new section elseif line:find("^@%a+") then section = line:sub(2); subsection = "none" -- decode map one line at a time elseif section == "map" then local l = #result.map + 1 result.map[l] = {} for i = 1, #line do result.map[l][i] = line:sub(i,i) end assert(#result.map[1] == #result.map[l]) -- templates to expand elseif section == "classes" then -- properties if line:find("^ %a+") then local _, _, property, value = line:find("^ (%a+)%s?:%s?(.*)") result.classes[subsection][property] = value goto skip end local symbol, classname = line:sub(1,1), line:sub(3) result.classes[classname] = { symbol = symbol, } result.glossary[symbol] = classname subsection = classname elseif section ~= "none" then local _, _, property, value = line:find("^(%a+)%s?:%s?(.*)") if result[section] == nil then result[section] = {} end result[section][property] = value end ::skip:: from = limit + 1 start, limit = string.find(f, "\n", from) end -- post process for y = 1, #result.map do result.grid[y] = {} for x = 1, #result.map[y] do local class = result.classes[result.glossary[result.map[y][x]]] if class["unique"] ~= nil then class.position = { x = x, y = y } end result.grid[y][x] = class end end print(result.meta.description) return result end function game_tick() if ctx.udata == nil then ctx.udata = { level = load_level("levels/00.lvl") } log_vec2 { value = ctx.udata.level.classes.player_spawn.position } end end