Hi there!
I would like to ask for some help. There is a logic flaw which I cannot figure out…
I’m creating a couple of objects with a factory and I want all of them to be at random but different places.
I’m using a Set to store the vector3 positions and before creating a new object I would like to check if the Set already contains it. I’m using this implementation which should work fine. However the check always returns false. Also debugged it, expected 50 objects were created but at less then 50 positions.
I think the issue is somewhere around the storing local position variable.
Here is the code snippet:
local wallPositionSet = Set.new()
function initMaze()
local counter = NULL
repeat
local position = vmath.vector3(NULL, NULL, ONE)
position.x = math.random(FIRST_INNER_COL, LAST_INNER_COL)
position.y = math.random(FIRST_INNER_ROW, LAST_INNER_ROW)
if not wallPositionSet.contains(wallPositionSet, position) then
factory.create("#maze", position)
wallPositionSet.insert(wallPositionSet, position)
counter = counter + ONE
end
until(counter == FIFTY)
end
I think you are overcomplicating things. First, there is no NULL in Lua. Then tables can act as a set.
And don’t use global variables, your initMaze() function is global.
I’d write something like this.
local walls = {}
local function initMaze()
for i = 1, 50 do
local is_placed = false
repeat
local x, y = math.random(FIRST_INNER_COL, LAST_INNER_COL), math.random(FIRST_INNER_ROW, LAST_INNER_ROW)
if not walls[x + y * width] then
walls[x + y * width] = true
is_placed = true
factory.create("#maze", vmath.vector3(x, y, 1))
end
until is_placed
end
end
The reason why it’s not working with that Set module is because vectors are passed around by reference, not by value. Each vector you create is a different object, even if they have exactly the same values. That means if you use vectors as table keys (like your Set module), if you use two vectors with exactly the same values, they will still be recognized as different keys. You can check this with a table:
local v1 = vmath.vector3(1, 2, 3)
local v2 = vmath.vector3(1, 2, 3)
local t = {}
t[v1] = true
print(t[v1]) -- Will be true.
print(t[v2]) -- Will be nil.
t[v2] = true
pprint(t) -- Will give this:
-- { --[[0000000002160340]]
-- vmath.vector3(1, 2, 3) = true,
-- vmath.vector3(1, 2, 3) = true
-- }
Defold does specifically allow you to compare vectors with ‘==’, but that’s a special case.
(I’m also confused why you are using variables for literal numbers and “NULL”…but to each their own I guess.)
Thank you for confirming, that was my guess as well.
(regarding variables for literals: I’m a Java backend dev and on my project we have strict code-style rules, ex. not to use ‘magic numbers’ in code and to declare them as constants )
The Lua table is an interesting data structure. You can use it as all three of the above:
local set = {}
set["foo"] = true
set["bar"] = true
print("Set has foo: ", set["foo"]) -- true
for v,_ in pairs(set) do
print(v)
end
local array = { "foo", "bar" }
print(array[1]) -- "foo"
for i=1,#array do
print(i, array[i])
end
for i,v in ipairs(array) do
print(i, v)
end
local map = {}
map["foo"] = 42
map["bar"] = 10101
print("Map value for key foo is:", map["foo"]) -- 42
for k,v in pairs(map) do
print(k, v)
end
A bit off-topic here, but doesn’t using FIFTY instead of 50 still count as using a ‘magic number’? Rather than MAZE_WALL_COUNTor something? Just curious. I’m not a professional programmer myself.