Dungeon 320
Let’s clean up those free-hanging functions just for fun.
I’ve left those utility functions for extending, randomizing, and zipping up Decor arrays. They look like this:
function zip(array1, array2)
assert(#array1==#array2, "arrays don't match "..#array1..","..#array2)
local result = {}
for i = 1,#array1 do
table.insert(result, array1[i]..";"..array2[i]..";avoid(1)")
end
return result
end
function randomize(array)
local copy = {}
table.move(array,1,#array,1,copy)
local result = {}
while #copy > 0 do
local itemNr = math.random(#copy)
table.insert(result,copy[itemNr])
table.remove(copy,itemNr)
end
return result
end
function stringFrom(array)
return ar.reduce(array, "", function(str,item) return str..tostring(item) end)
end
function extendAll(countItemArray)
local entries, residual
local result = {}
residual = countItemArray
while (#residual) > 0 do
entries,residual = extend(residual)
table.move(entries,1,#entries, #result+1, result)
end
return result
end
function extend(countItemArray)
local extended = extendSegment(countItemArray)
local residual = {}
table.move(countItemArray,3,#countItemArray,1,residual)
return extended, residual
end
function extendSegment(countItemArray)
result = {}
for i = 1,countItemArray[1] do
table.insert(result, countItemArray[2])
end
return result
end
In that form, they pollute the global namespace, and are likely to collide with other people’s names at some random future date, or would be in a real effort. So we’ll do well to bring them in from the cold.
Since the program’s name is D2, and D2 is short, we could use that. It’s tempting to use dung
, as that is my pet name for the program. I think we’ll go with D2, as it is more seemly. Most of the Lua prefixes are lower case, like math
and table
, and I used lower case for my FP functions, ar
, kv
, and fp
. Let’s follow that convention and go with … ok … du
for “dungeon utilities”.
In Main, outside all functions, we’ll define it after checking for an existing definition.
assert(du==nil, "Cannot define `du`")
du = {}
OK now:
du.zip = function(array1, array2)
assert(#array1==#array2, "arrays don't match "..#array1..","..#array2)
local result = {}
for i = 1,#array1 do
table.insert(result, array1[i]..";"..array2[i]..";avoid(1)")
end
return result
end
And change all the references:
function DungeonBuilder:placeZippedDecor(decorIn, lootIn, count)
local decor = extendAll(decorIn)
local loot = randomize(extendAll(lootIn))
return count + #self:fromDefs(du.zip(decor,loot))
end
And so on, I’ll spare you all of them. Tests run. Shall we commit or do them all? Do them all. Am I a bad person? Just takes a moment for each.
Test, commit: Put the decor extend and zip into du
namespace.
All functions defined, calls changed. World is just a little better.
There are four other world-level functions in Main:
-- Generally Useful Functions
function clamp(lo,val,hi)
if lo <= hi then
return math.max(math.min(val,hi), lo)
else
return math.max(math.min(val,lo), hi)
end
end
function randomValueAvoiding(vLow,vHigh,vMax)
local numberToSkip = vHigh-vLow + 1
local v = math.random(1, vMax - numberToSkip)
if v >= vLow then
v = v + numberToSkip
end
return v
end
function sign(x)
return (x < 0 and -1) or (x == 0 and 0) or (x > 0 and 1)
end
function splitStringToTable(str)
local lines = {}
for s in str:gmatch("[^\r\n]+") do
table.insert(lines, s)
end
return lines
end
Now that we have a place for them, let’s use it. Another few moments and those are done. Commit: move utility functions from Main to du, and all their uses.
Again, the world is just a slightly better place. I wish everything were this easy.