It's writing to the same array it's reading from. dvgrn's point is also correct; some instances of fieldB should be field.
One solution is to copy all the contents of field into fieldB and then return fieldB. That makes no sense, though, when you could just alternate between the two arrays, which is obviously faster than redundantly copying the entire field every step.
Here's a modified version of your code that works. You can run it in a command-line and press enter to advance the displayed generation, and type 'quit' to exit:
Code: Select all
function live(field, new_field)
--Simulate one generation of B3/S23 on field, writing the result to new_field.
for i=1, 64 do
for j=1, 64 do
num = 0
if field[i-1][j-1] == 1 then num = num + 1 end
if field[i][j-1] == 1 then num = num + 1 end
if field[i+1][j-1] == 1 then num = num + 1 end
if field[i-1][j] == 1 then num = num + 1 end
if num >= 4 then goto done end
if field[i+1][j] == 1 then num = num + 1 end
if field[i-1][j+1] == 1 then num = num + 1 end
if field[i][j+1] == 1 then num = num + 1 end
if field[i+1][j+1] == 1 then num = num + 1 end
::done::
if (num ~= 3 and field[i][j] == 0) then new_field[i][j] = 0
elseif ((num ~= 2 and num ~= 3) and field[i][j] == 1) then new_field[i][j] = 0
elseif ((num == 2 or num == 3) and field[i][j]) == 1 then new_field[i][j] = 1
elseif (num == 3 and field[i][j] == 0) then new_field[i][j] = 1
else new_field[i][j] = 0
end
end
end
end
fieldA = {}
fieldB = {}
for i=0, 65 do
fieldA[i]={}
fieldB[i]={}
for j=0, 65 do
if i==0 or i==65 or j==0 or j==65 then --ensure cells outside grid are dead
fieldA[i][j]=0
else
fieldA[i][j] = math.random(2)-1
end
fieldB[i][j]=0
end
end
while io.read()~="quit" do
for i=1, 64 do
for j=1, 64 do
io.write(fieldA[i][j]);
end
print("")
end
live(fieldA, fieldB)
swap = fieldA
fieldA = fieldB
fieldB = swap
end
Ian07 wrote: ↑February 2nd, 2020, 3:13 pm
Ah, I might have run into this same issue when trying to make CGoL in JavaScript a while ago. I'm not sure why, but it seems that changing the entire array by saying "currentArray = nextArray;" doesn't actually work: rather you have to change each cell individually using another nested loop. (i.e. "currentArray[ i][j] = nextArray[ i][j];") Again, why this happens is beyond me, but hopefully the solution does work.
I remember having the same experience trying to implement cellular automata in JavaScript. I was similarly baffled and incredulous as to why it didn't copy the contents of the array, and now that I know more about computers, I'm baffled and incredulous at the implication that it should work any other way.
Processors do not deal in large volumes of data, they deal in registers, no larger than 64 bits. The fundamental operations and types of a language will often reflect this. The assignment operator, to me as a more low-level programmer, seems like it should take O(1) under all circumstances, and copying a large space of memory involves many operations, presumably a function call to memcpy(). As such, the intuition of a low-level programmer tells them that copying an entire memory space requires a loop, and since arrays are pointers, setting an array to another array means setting a pointer to another pointer. Thus the low-level programmer finds this behaviour not just reasonable, but obvious.
Does that make sense?
EDIT 2020-12-01: It turns out my swapping code is slightly overcomplicated. You can just do "fieldA, fieldB = fieldB, fieldA" to swap the arrays.