main.lua:147: stack overflow
Traceback
[love "callbacks.lua"]:228: in function 'handler'
main.lua:94: in function 'matches'
main.lua:80: in function 'checkforNil'
main.lua:89: in function 'removeMatches'
main.lua:148: in function 'matches'
main.lua:80: in function 'checkforNil'
main.lua:89: in function 'removeMatches'
main.lua:148: in function 'matches'
main.lua:80: in function 'checkforNil'
main.lua:89: in function 'removeMatches'
...
main.lua:89: in function 'removeMatches'
main.lua:148: in function 'matches'
main.lua:80: in function 'checkforNil'
main.lua:89: in function 'removeMatches'
main.lua:148: in function 'matches'
main.lua:161: in function 'swap'
main.lua:183: in function <main.lua:175>
[love "callbacks.lua"]:154: in function <[love "callbacks.lua"]:144>
[C]: in function 'xpcall'
I'm was working a tile matching game using Love2D. The game involves a grid of colored tiles that players can swap to form matches of three or more. When matches are formed, the tiles are removed, and new tiles drop down to fill the empty spaces. However, I'm encountering a "stack overflow" error, and I'm not sure how to resolve it. Here is my code: How can I resolve this stack overflow error? It seems to occur in the matches and removeMatches functions, causing an infinite loop or recursion issue.
updated to provide error and minimal case of working.
local game = {}
-- Table to store the grid elements
gridTable = {}
local selectedTile = nil
-- Function to initialize the gridTable with colors
function game:initializeGrid()
for i = 1, 64 do
gridTable[i] = {
x = ((i - 1) % 8) * 65,
y = (math.floor((i - 1) / 8) * 65),
color = love.math.random(7)
}
end
end
-- Function to draw the grid elements
function game:drawGrid()
for i, cell in ipairs(gridTable) do
if cell.color then
love.graphics.setColor(self:getColor(cell.color))
love.graphics.rectangle("fill", cell.x, cell.y, 50, 50)
end
end
if selectedTile then
love.graphics.setColor(1, 1, 1)
love.graphics.rectangle("line", gridTable[selectedTile].x, gridTable[selectedTile].y, 50, 50)
end
end
-- Helper function to get color by index
function game:getColor(index)
local colors = {
{1, 0, 0},
{0, 1, 0},
{0, 0, 1},
{1, 1, 0},
{0, 1, 1},
{1, 0, 1},
{0.5, 0.5, 0.5}
}
return colors[index]
end
function game:checkforNil() -- looks for nil values in the table
for i = 64, 56, -1 do --grid is 8x8 so 64 items
local counter = 8 -- looks through each row
for j = i, 1, -8 do
local tempY, tempColor = 0, 0
if gridTable[j].y == nil then -- if value at j is nil we swap the nil value with what's about it and repeats until all values are filled
for test = j, 1, -8 do
if gridTable[test].y ~= nil then
tempY = gridTable[test].y
tempColor = gridTable[test].color
gridTable[j].y = ((counter) * 50) + (((counter) - 1) * 15)
gridTable[j].color = tempColor
gridTable[test].y = nil
gridTable[test].color = nil
break
end
end
end
for k = 1, 8 do -- loops through the top and assigns random colours
if gridTable[k].y == nil then
gridTable[k].y = 50
gridTable[k].color = love.math.random(7)
end
end
counter = counter - 1
end
end
self:matches(gridTable)
end
function game:removeMatches(grid)
for _, v in ipairs(listofMatches) do --lists of matches contain where in the table there are 3 or more colours of the same
grid[v].y = nil --and removes them
grid[v].color = nil
end
listofMatches = {} --resets the list
self:checkforNil() -- calls the function that pushes bricks down
end
function game:matches(grid) --searches everytime we swap for a match
matchTest = false --if we find at least one match we'll set this to true
listofMatches = {}
local matches = 0
for i = 1, 63 do --loops through the table of which there are 64 items
for _, y in ipairs(listofMatches) do
if i == y then
goto continue --if i and i+1 are a match we skip to i+2 to see if that matches too
end
end
::continue::
for j = i + 1, 64 do --in this loop we are looking for horizontal matches
local currentColor = grid[i].color --sets the current colour we are searching for
if currentColor ~= grid[j].color then --we break out of searching for the same colour and if the
if matches > 1 then --matches are 3+ we set match test to tru and insert into list of matches
matchTest = true
for k = i, j - 1 do
table.insert(listofMatches, k)
end
end
matches = 0
break
else
matches = matches + 1
end
end
end
for num = 1, 8 do --looking for vertical
for vertical = num, 48, 8 do
for _, y in ipairs(listofMatches) do
if vertical == y then
goto continue
end
end
::continue::
for down = vertical + 8, 64, 8 do
local currentColor = grid[vertical].color
if currentColor ~= grid[down].color then
if matches > 1 then
matchTest = true
for k = vertical, down - 8, 8 do
table.insert(listofMatches, k)
end
end
matches = 0
break
else
matches = matches + 1
end
end
end
end
if matchTest then --if there is a match test we want to remove matches so call the function and add points
self:removeMatches(grid)
game.points = (game.points or 0) + 500
matchTest = false
end
end
function game:swap(swap1, swap2) --swapping blocks and then checking if there's a match
local temp1 = gridTable[swap1].color
local temp2 = gridTable[swap2].color
gridTable[swap1].color = temp2
gridTable[swap2].color = temp1
self:matches(gridTable)
end
-- Love2D callback functions
function love.load()
game:initializeGrid()
end
function love.draw()
game:drawGrid()
love.graphics.setColor(1, 1, 1)
love.graphics.print("Points: " .. (game.points or 0), 10, 10)
end
function love.mousepressed(x, y, button)
if button == 1 then
local tileIndex = game:getTileIndex(x, y)
if tileIndex then
if not selectedTile then
selectedTile = tileIndex
else
if selectedTile ~= tileIndex then
game:swap(selectedTile, tileIndex)
selectedTile = nil
else
selectedTile = nil
end
end
end
end
end
function game:getTileIndex(x, y)
for i, cell in ipairs(gridTable) do
if x > cell.x and x < cell.x + 50 and y > cell.y and y < cell.y + 50 then
return i
end
end
return nil
end