Conway's Game of Life, slow update

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Teptai
Prole
Posts: 3
Joined: Sun Oct 08, 2017 8:12 am

Conway's Game of Life, slow update

Post by Teptai »

Hi, i made a simple version of Conway's Game of Life but the bigger the grid is the slower it updates. How can i make the calculation cycle faster so i can update the grid every second?

Code: Select all

function love.load()

--https://forums.coronalabs.com/topic/27482-copy-not-direct-reference-of-table/
-- Creates a complete/deep copy of the data
function deepCopy(object)
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for index, value in pairs(object) do
            new_table[_copy(index)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end
    return _copy(object)
end

map = {
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0},
	{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0},
	{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}
}

tempmap = deepCopy(map)
gridMax = #map
gridX = 1
gridY = 1
count = 0
deadCount = 0
generation = 1
tick = 0

end
 
function love.update(dt)
	tick = tick + dt
	if (tick > 1) then	
		love.loop()
	end
end

function love.loop()

	--main loop
	do					
		--check north
		if (map[gridX][gridY] == 1 and gridY > 1) then			
			if (map[gridX][gridY - 1] == 1) then
				count = count + 1
			end
		elseif (map[gridX][gridY] == 0 and gridY > 1) then			
			if (map[gridX][gridY - 1] == 1) then
				deadCount = deadCount + 1
			end
		end	
		--check east
		if (map[gridX][gridY] == 1 and gridX < gridMax) then			
			if (map[gridX + 1][gridY] == 1) then
				count = count + 1
			end
		elseif (map[gridX][gridY] == 0 and gridX < gridMax) then			
			if (map[gridX + 1][gridY] == 1) then
				deadCount = deadCount + 1
			end
		end
		--check south
		if (map[gridX][gridY] == 1 and gridY < gridMax) then			
			if (map[gridX][gridY + 1] == 1) then
				count = count + 1
			end
		elseif (map[gridX][gridY] == 0 and gridY < gridMax) then			
			if (map[gridX][gridY + 1] == 1) then
				deadCount = deadCount + 1
			end
		end	
		--check west
		if (map[gridX][gridY] == 1 and gridX > 1) then			
			if (map[gridX - 1][gridY] == 1) then
				count = count + 1
			end
		elseif (map[gridX][gridY] == 0 and gridX > 1) then			
			if (map[gridX - 1][gridY] == 1) then
				deadCount = deadCount + 1
			end
		end		
		--check ne
		if (map[gridX][gridY] == 1 and gridX < gridMax and gridY > 1) then			
			if (map[gridX + 1][gridY - 1] == 1) then
				count = count + 1
			end
		elseif (map[gridX][gridY] == 0 and gridX < gridMax and gridY > 1) then			
			if (map[gridX + 1][gridY - 1] == 1) then
				deadCount = deadCount + 1
			end
		end		
		--check se
		if (map[gridX][gridY] == 1 and gridX < gridMax and gridY < gridMax) then			
			if (map[gridX + 1][gridY + 1] == 1) then
				count = count + 1
			end
		elseif (map[gridX][gridY] == 0 and gridX < gridMax and gridY < gridMax) then			
			if (map[gridX + 1][gridY + 1] == 1) then
				deadCount = deadCount + 1
			end
		end		
		--check sw
		if (map[gridX][gridY] == 1 and gridX > 1 and gridY < gridMax) then			
			if (map[gridX - 1][gridY + 1] == 1) then
				count = count + 1
			end
		elseif (map[gridX][gridY] == 0 and gridX > 1 and gridY < gridMax) then			
			if (map[gridX - 1][gridY + 1] == 1) then
				deadCount = deadCount + 1
			end
		end			
		--check nw
		if (map[gridX][gridY] == 1 and gridX > 1 and gridY > 1) then			
			if (map[gridX - 1][gridY - 1] == 1) then
				count = count + 1
			end
		elseif (map[gridX][gridY] == 0 and gridX > 1 and gridY > 1) then			
			if (map[gridX - 1][gridY - 1] == 1) then
				deadCount = deadCount + 1
			end
		end
		
		--check if cell lives or dies			
		if(map[gridX][gridY] == 1 and count < 2) then
			tempmap[gridX][gridY] = 0
		elseif (map[gridX][gridY] == 1 and count <= 3 and count > 1) then
			tempmap[gridX][gridY] = 1
		elseif (map[gridX][gridY] == 1 and count > 3) then
			tempmap[gridX][gridY] = 0
		--check if dead cell reanimates			
		elseif (map[gridX][gridY] == 0 and deadCount == 3) then
			tempmap[gridX][gridY] = 1
		elseif (map[gridX][gridY] == 0 and deadCount ~= 3) then
			tempmap[gridX][gridY] = 0			
		end
		
		--check if there's grid positions left, if not then start over		
		if (gridX >= gridMax and gridY < gridMax) then
			gridX = 1
			gridY = gridY + 1
			count = 0
			deadCount = 0
		elseif (gridX >= gridMax and gridY >= gridMax) then
			gridX = 1
			gridY = 1
			count = 0
			deadCount = 0
			map = deepCopy(tempmap)
			generation = generation + 1
			tick = 0
		else
			gridX = gridX + 1
			count = 0
			deadCount = 0
		end
	end

end

function love.draw()

	--draw map
	for y=1, #map do
		for x=1, #map[y] do
			if map[y][x] == 1 then
				love.graphics.setColor(20, 248, 242)
				love.graphics.rectangle("fill", x * 32, y * 32, 32, 32)
			else
				love.graphics.rectangle("line", x * 32, y * 32, 32, 32)
			end
		end
	end
	
	--draw infotext
	love.graphics.setColor(20, 248, 242)
	love.graphics.print("gridX " .. gridX, 700, 30)
	love.graphics.print("gridY " .. gridY, 700, 45)
	love.graphics.print("gridMax " .. gridMax, 700, 60)	
	love.graphics.print("generation " .. generation, 700, 75)	
	love.graphics.print("tick " .. tick, 700, 90)
end
 
function love.keypressed(key)
	if key == "escape" then
		love.event.quit()
	end
end
 
Attachments
gameoflife.love
(2.33 KiB) Downloaded 78 times
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: Conway's Game of Life, slow update

Post by grump »

You're updating only one grid cell per update call: love.update gets called only once per frame. You probably want to update the whole thing instead by making two loops that iterate over the grid.

Code: Select all

for gridY = 1, gridMax do
    for gridX = 1, gridMax do 
       .....
    end
end
Your code is kind of strange. You're not supposed to put everything in love.load. And while not exactly wrong, it makes little sense to put random functions in the love table, like you did with love.loop.
Teptai
Prole
Posts: 3
Joined: Sun Oct 08, 2017 8:12 am

Re: Conway's Game of Life, slow update

Post by Teptai »

Hi, thanks for your reply, i got it to work as intended with your for loop. Thank you. Here's the updated code and .love file if anyone's intrested. Any other suggestions to make the code better?

Code: Select all

function love.load()

--https://forums.coronalabs.com/topic/27482-copy-not-direct-reference-of-table/
-- Creates a complete/deep copy of the data
function deepCopy(object)
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for index, value in pairs(object) do
            new_table[_copy(index)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end
    return _copy(object)
end

map = {
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0},
	{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0},
	{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}
}

tempmap = deepCopy(map)
gridMax = #map
gridX = 1
gridY = 1
count = 0
deadCount = 0
generation = 1
tick = 0
mouseX = 0
mouseY = 0
lifeTime = 0.5

end
 
function love.update(dt)
	tick = tick + dt
	if (tick > lifeTime) then	
		mainLoop()
	end
	
	function love.mousepressed(x, y)
			mouseX = x
			mouseY = y
	end
end

function mainLoop()

	for gridY = 1, gridMax do
	
		for gridX = 1, gridMax do 
			
			--check north
			if (map[gridX][gridY] == 1 and gridY > 1) then			
				if (map[gridX][gridY - 1] == 1) then
					count = count + 1
				end
			elseif (map[gridX][gridY] == 0 and gridY > 1) then			
				if (map[gridX][gridY - 1] == 1) then
					deadCount = deadCount + 1
				end
			end	
			--check east
			if (map[gridX][gridY] == 1 and gridX < gridMax) then			
				if (map[gridX + 1][gridY] == 1) then
					count = count + 1
				end
			elseif (map[gridX][gridY] == 0 and gridX < gridMax) then			
				if (map[gridX + 1][gridY] == 1) then
					deadCount = deadCount + 1
				end
			end
			--check south
			if (map[gridX][gridY] == 1 and gridY < gridMax) then			
				if (map[gridX][gridY + 1] == 1) then
					count = count + 1
				end
			elseif (map[gridX][gridY] == 0 and gridY < gridMax) then			
				if (map[gridX][gridY + 1] == 1) then
					deadCount = deadCount + 1
				end
			end	
			--check west
			if (map[gridX][gridY] == 1 and gridX > 1) then			
				if (map[gridX - 1][gridY] == 1) then
					count = count + 1
				end
			elseif (map[gridX][gridY] == 0 and gridX > 1) then			
				if (map[gridX - 1][gridY] == 1) then
					deadCount = deadCount + 1
				end
			end		
			--check ne
			if (map[gridX][gridY] == 1 and gridX < gridMax and gridY > 1) then			
				if (map[gridX + 1][gridY - 1] == 1) then
					count = count + 1
				end
			elseif (map[gridX][gridY] == 0 and gridX < gridMax and gridY > 1) then			
				if (map[gridX + 1][gridY - 1] == 1) then
					deadCount = deadCount + 1
				end
			end		
			--check se
			if (map[gridX][gridY] == 1 and gridX < gridMax and gridY < gridMax) then			
				if (map[gridX + 1][gridY + 1] == 1) then
					count = count + 1
				end
			elseif (map[gridX][gridY] == 0 and gridX < gridMax and gridY < gridMax) then			
				if (map[gridX + 1][gridY + 1] == 1) then
					deadCount = deadCount + 1
				end
			end		
			--check sw
			if (map[gridX][gridY] == 1 and gridX > 1 and gridY < gridMax) then			
				if (map[gridX - 1][gridY + 1] == 1) then
					count = count + 1
				end
			elseif (map[gridX][gridY] == 0 and gridX > 1 and gridY < gridMax) then			
				if (map[gridX - 1][gridY + 1] == 1) then
					deadCount = deadCount + 1
				end
			end			
			--check nw
			if (map[gridX][gridY] == 1 and gridX > 1 and gridY > 1) then			
				if (map[gridX - 1][gridY - 1] == 1) then
					count = count + 1
				end
			elseif (map[gridX][gridY] == 0 and gridX > 1 and gridY > 1) then			
				if (map[gridX - 1][gridY - 1] == 1) then
					deadCount = deadCount + 1
				end
			end
			
			--check if cell lives or dies			
			if(map[gridX][gridY] == 1 and count < 2) then
				tempmap[gridX][gridY] = 0
			elseif (map[gridX][gridY] == 1 and count <= 3 and count > 1) then
				tempmap[gridX][gridY] = 1
			elseif (map[gridX][gridY] == 1 and count > 3) then
				tempmap[gridX][gridY] = 0
			--check if dead cell reanimates			
			elseif (map[gridX][gridY] == 0 and deadCount == 3) then
				tempmap[gridX][gridY] = 1
			elseif (map[gridX][gridY] == 0 and deadCount ~= 3) then
				tempmap[gridX][gridY] = 0			
			end
			
			if (gridX >= gridMax and gridY < gridMax) then
				gridX = 1
				gridY = gridY + 1
				count = 0
				deadCount = 0
			elseif (gridX >= gridMax and gridY >= gridMax) then
				gridX = 1
				gridY = 1
				count = 0
				deadCount = 0
				map = deepCopy(tempmap)
				generation = generation + 1
				tick = 0
			else
				gridX = gridX + 1
				count = 0
				deadCount = 0
			end
		end			
	end
end


function love.draw()

	--draw map
	for y=1, #map do
		for x=1, #map[y] do
			if map[y][x] == 1 then
				love.graphics.setColor(20, 248, 242)
				love.graphics.rectangle("fill", x * 32, y * 32, 32, 32)
			else
				love.graphics.rectangle("line", x * 32, y * 32, 32, 32)
			end
		end
	end
	
	--draw infotext
	love.graphics.setColor(20, 248, 242)
	love.graphics.print("gridX " .. gridX, 700, 30)
	love.graphics.print("gridY " .. gridY, 700, 45)
	love.graphics.print("gridMax " .. gridMax, 700, 60)	
	love.graphics.print("generation " .. generation, 700, 75)	
	love.graphics.print("tick " .. tick, 700, 90)
	love.graphics.print("mouseX " .. mouseX, 700, 105)
	love.graphics.print("mouseY " .. mouseY, 700, 120)
	
end
 
function love.keypressed(key)
	if key == "escape" then
		love.event.quit()
	end	
end
 
Attachments
gameoflife.love
(2.38 KiB) Downloaded 68 times
hamberge
Prole
Posts: 25
Joined: Wed Aug 16, 2017 2:55 pm

Re: Conway's Game of Life, slow update

Post by hamberge »

Well you could take deepcopy and map outside of love.load. You don't really need to put function definitions or table definitions in there. Maybe take mousepressed out of update -- this is a callback that will be called whenever the mouse is clicked. Other than that it looks ok. I also don't think you need deepcopy -- I think you can just use nested for loops for your own copy. And you don't need the first deepcopy call in load because you will generate your first tempmap in the first iteration of update.
Post Reply

Who is online

Users browsing this forum: No registered users and 42 guests