Search code examples
luamaze

My Lua maze builder that is braiding


I am building a Lua script that generates a maze using a version of the Recursive Backtracker implemented with a stack rather than recursion. Presently the maze is coming out braided and I can't seem to figure out where in my logic this is happening. The function below takes in x and y as a starting point for generating the maze which is a 2d structure (table of tables):

local function buildMazeInternal(x,y,maze)

    local stack = {}
    local directions = {'North','East','South','West'}

    table.insert(stack,{x=x,y=y})

    while #stack > 0 do
        local index = 1
        local nextX = x
        local nextY = y
        local braid = false 

        for i = #directions, 2, -1 do -- backwards
            local r = calc:Roll(1,i) -- select a random number between 1 and i
            directions[i], directions[r] = directions[r], directions[i] -- swap the randomly selected item to position i
        end

        while index <= #directions and nextX == x and nextY == y do
            if directions[index] == 'North' and y > 1 and not maze[y-1][x].Visited then
                maze[y][x].North = true
                maze[y-1][x].South = true
                nextY = y-1
            elseif directions[index] == 'East' and x < width and not maze[y][x+1].Visited then
                maze[y][x].East = true
                maze[y][x+1].West = true
                nextX = x+1
            elseif directions[index] == 'South' and y < height and not maze[y+1][x].Visited then
                maze[y][x].South = true
                maze[y+1][x].North = true
                nextY = y+1
            elseif directions[index] == 'West' and x > 1 and not maze[y][x-1].Visited then
                maze[y][x].West = true
                maze[y][x-1].East = true
                nextX = x-1
            else
                index = index + 1
            end
        end

        if nextX ~= x or nextY ~= y then
            x = nextX
            y = nextY
            maze[y][x].Visited = true
            table.insert(stack,{x=x,y=y})
        else    
            x = stack[#stack].x
            y = stack[#stack].y
            table.remove(stack)
        end
    end
end

I know I'm overlooking something but I can't seem to nail it down. Note that the calc:Roll(1,100) method is a .net method in my app used to simulate rolling dice, in this case 1 * 100 sided die, it could be replaced with a call to math.Random(1,100) for use outside of my application.


Solution

  • I found the answer after posting on Reddit. I wasn't setting the initial cell to visited allowing it to be passed through twice. The correction was to add maze[y][x].Visited = true immediately before table.insert(stack,{x=x,y=y}).