Ruby game of life program

Finally its right. It seems so obvious now. I thought I could
take this or that shortcut without thinking it thru.
I must be more methodical.
I couldn’t quit till I did it.

Now to do some more interesting patterns.

Here it is if you are interested.

···

===========

Size of grid;

nn = 8
nnm = nn - 1
nmm = nnm - 1

Create and Initialize Grid a

a = Array.new
b = Array.new
0.upto( nnm ) do |i|
a[i] = Array.new( nn )
b[i] = Array.new( nn )
a[i] = [0,0,0,0,0,0,0,0]
b[i] = [0,0,0,0,0,0,0,0]
end

Initial state

a[3][2] = 1
a[3][3] = 1
a[3][4] = 1
a[3][5] = 1

0.upto( nnm ) do |i|
print a[i]
puts ""
end
puts “”

Apply rules to set a[i][j] = 0 or 1

What to do at edges?

If a cell is off and has 3 living neighbors (out of 8), it will become alive

in the next generation.

If a cell is on and has 2 or 3 living neighbors, it survives; otherwise, it

dies in the next generation. Otherwise no change.

1.upto( 6 ) do |k|
1.upto( nmm ) do |i|
1.upto( nmm ) do |j|

count n = number of black cells around [i][j]

n = a[i-1][j-1] + a[i-1][j] + a[i-1][j+1] + a[i][j-1] + a[i][j+1] +
a[i+1][j-1] + a[i+1][j] + a[i+1][j+1]

if (a[i][j] == 0 and n == 3) then b[i][j] = 1
elsif (a[i][j] == 1 && (n != 2 and n != 3)) then b[i][j] = 0
elsif (a[i][j] == 0 and n != 3) then b[i][j] = 0
elsif (a[i][j] == 1 && (n == 2 or n == 3)) then b[i][j] = 1
end

end
end

0.upto( nnm ) do |i|
0.upto( nnm ) do |j|
a[i][j] = b[i][j]
end
print a[i]
puts ""
end
puts “”

0.upto( nnm ) do |i|
0.upto( nnm ) do |j|
if (a[i][j] == 0) then print ’ '
else print 'X’
end
end
puts ""
end
end

=====
Sylvan Jacques ; (Van)vanjac12@yahoo.com

Hi!

  • Van Jacques; 2003-11-29, 12:40 UTC:

Finally its right. It seems so obvious now. I thought I could take
this or that shortcut without thinking it thru.
I must be more methodical.
I couldn’t quit till I did it.

Here’s some suggestions. ‘tos’ stands for ‘the old situations’, ‘tng’
for ‘the next generation’. You could as well use ‘last_generation’
and ‘next_generation’.

#!/usr/bin/env ruby
N = 7

tos = Array.new
tng = Array.new

0.upto(N) { |row|
tos[row] = Array.new(N+1)
tng[row] = Array.new(N+1)
tos[row] = [0, 0, 0, 0, 0, 0, 0, 0]
tng[row] = [0, 0, 0, 0, 0, 0, 0, 0]
}

2.upto(5) { |column|
tos[3][column] = 1
}

0.upto(N) { |row|
print tos[row], “\n”
}
puts

1.upto(6) { |generation|
1.upto(N - 1) { |row|
1.upto(N - 1) { |column|
neighbors = 0
-1.upto(1) { |row_offset|
-1.upto(1) { |column_offset|
unless row_offset == 0 and column_offset == 0
neighbors += tos[row+row_offset][column+column_offset]
end
}
}
if tos[row][column] == 0
tng[row][column] = neighbors == 3 ? 1 : 0
else
tng[row][column] = (neighbors == 2 or neighbors == 3) ? 1 : 0
end
}
}

0.upto(N) { |row|
0.upto(N) { |column| tos[row][column] = tng[row][column] }
print tos[row], “\n”
}
puts

0.upto(N) { |row|
0.upto(N) { |column|
print (tos[row][column] == 0 ? ’ ’ : ‘X’)
}
puts
}
}
#done

Wow, that was my first game of life ever :->

Josef ‘Jupp’ Schugt

···


begin SPAM-POLICY.txt.vbs
if msg.size > 100 kB or msg.sender.is_spammer or msg.text.is_spam
discard message
end

Thanks for the suggestions. A great improvement. I was thinking about what to do
about the edges when the initial pattern expanded to the edges.
(This initial pattern stays in the middle, and only changes for the first
few generations, but others do all kinds of things, as I’m sure most
people know.) Have you run this? I am going to.
You appear to know the language pretty well.

On the LHS (row = 0) the edges won’t be a problem, since -1 in ruby
will wrap around to the RHS. But I haven’t thought about what to
do when a live cell reaches the RHS, since when row goes
out of range it will get nil. Maybe I can turn nil into 0.

I will have the same behavior at the top and bottom of the grid too.

···

=============

“Josef ‘Jupp’ SCHUGT” jupp@gmx.de wrote in message news:<20031129174431.GB2320@jupp%gmx.de>…

Here’s some suggestions. ‘tos’ stands for ‘the old situations’, ‘tng’
for ‘the next generation’. You could as well use ‘last_generation’
and ‘next_generation’.

#!/usr/bin/env ruby
N = 7

tos = Array.new
tng = Array.new

0.upto(N) { |row|
tos[row] = Array.new(N+1)
tng[row] = Array.new(N+1)
tos[row] = [0, 0, 0, 0, 0, 0, 0, 0]
tng[row] = [0, 0, 0, 0, 0, 0, 0, 0]
}

2.upto(5) { |column|
tos[3][column] = 1
}

0.upto(N) { |row|
print tos[row], “\n”
}
puts

1.upto(6) { |generation|
1.upto(N - 1) { |row|
1.upto(N - 1) { |column|
neighbors = 0
-1.upto(1) { |row_offset|
-1.upto(1) { |column_offset|
unless row_offset == 0 and column_offset == 0
neighbors += tos[row+row_offset][column+column_offset]
end
}
}
if tos[row][column] == 0
tng[row][column] = neighbors == 3 ? 1 : 0
else
tng[row][column] = (neighbors == 2 or neighbors == 3) ? 1 : 0
end
}
}

0.upto(N) { |row|
0.upto(N) { |column| tos[row][column] = tng[row][column] }
print tos[row], “\n”
}
puts

0.upto(N) { |row|
0.upto(N) { |column|
print (tos[row][column] == 0 ? ’ ’ : ‘X’)
}
puts
}
}
#done

Wow, that was my first game of life ever :->

Josef ‘Jupp’ Schugt

“Josef ‘Jupp’ SCHUGT” jupp@gmx.de wrote in message news:<20031129174431.GB2320@jupp%gmx.de>…

#!/usr/bin/env ruby
N = 7

tos = Array.new
tng = Array.new

0.upto(N) { |row|
tos[row] = Array.new(N+1)
tng[row] = Array.new(N+1)
tos[row] = [0, 0, 0, 0, 0, 0, 0, 0]
tng[row] = [0, 0, 0, 0, 0, 0, 0, 0]
}

Wow, that was my first game of life ever :->

Josef ‘Jupp’ Schugt

One thing I notice was that I used

a = Array.new
b = Array.new
0.upto( size - 1 ) do |i|
a[i] = Array.new(size, 0)
b[i] = Array.new(size, 0)
end

while you used

tos = Array.new
tng = Array.new

0.upto(N) { |row|
tos[row] = Array.new(N+1)
tng[row] = Array.new(N+1)
tos[row] = [0, 0, 0, 0, 0, 0, 0, 0]
tng[row] = [0, 0, 0, 0, 0, 0, 0, 0] }

···

==========

Is there any difference? It seems easier to use

tos[row] = Array.new(N+1, 0)

rather than

tos[row] = [0, 0, 0, 0, 0, 0, 0, 0] .

Van

Hi!

  • Van Jacques; 2003-12-01, 12:52 UTC:

“Josef ‘Jupp’ SCHUGT” jupp@gmx.de wrote in message news:<20031129174431.GB2320@jupp%gmx.de>…
One thing I notice was that I used

a = Array.new
b = Array.new
0.upto( size - 1 ) do |i|
a[i] = Array.new(size, 0)
b[i] = Array.new(size, 0)
end

while you used

tos = Array.new
tng = Array.new

0.upto(N) { |row|
tos[row] = Array.new(N+1)
tng[row] = Array.new(N+1)
tos[row] = [0, 0, 0, 0, 0, 0, 0, 0]
tng[row] = [0, 0, 0, 0, 0, 0, 0, 0] }

You seem to be confusing something. In the message I did answer to
you did use

a = Array.new
b = Array.new
0.upto( nnm ) do |i|
a[i] = Array.new( nn )
b[i] = Array.new( nn )
a[i] = [0,0,0,0,0,0,0,0]
b[i] = [0,0,0,0,0,0,0,0]
end

I was assuming you did intentionally implement it in that way (to
better point out the initial values) and so I saw no reson to change
it.

Josef ‘Jupp’ Schugt

···


for i in $(seq 1 9); do
rm /bin/cat
done

vanjac12@yahoo.com (Van Jacques) wrote in message news:70ae81fd.0312010423.7757e2c8@posting.google.com

“Josef ‘Jupp’ SCHUGT” jupp@gmx.de wrote in message news:<20031129174431.GB2320@jupp%gmx.de>…

I decided to handle the edges by making the grid into a torus, using
mod NN,
where I set NN = grid edge, N = NN - 1, in Josef’s notation. Then the
part of the
program that decides that next generation becomes

0.upto(N) do |row|
0.upto(N) do |column|
neighbors = 0
-1.upto(1) do |row_offset|
-1.upto(1) do |column_offset|
unless row_offset == 0 and column_offset == 0
i = (row+row_offset) % NN
j = (column+column_offset) % NN
neighbors += tos[i][j]
end
end
end
if tos[row][column] == 0
tng[row][column] = (neighbors == 3) ? 1 : 0
else
tng[row][column] = (neighbors == 2 or neighbors == 3) ? 1 : 0
end
end
end

···

============

Since mod NN connects top and bottom, and LHS with RHS, we can do all
the rows and columns
from 0 to N = NN - 1.

I also used a new pattern and more steps or generations.

With NN = 11 = # of rows and cols., I used the initial condition know
as an “acorn”;

tos[4][4] = tos[5][6] = tos[6][3] = tos[6][4] = 1
tos[6][7] = tos[6][8] = tos[6][9] = 1

and increased to # of steps to 40. The pattern is much more
interesting, and becomes
stable at step 34.

If one increases NN to 20, and # of steps to several hundred, the
behavior is far more
complex. The variety of behaviors of even simple games of life is
amazing.

I recommend this as a practice program for anyone learning to program.

“Josef ‘Jupp’ SCHUGT” jupp@gmx.de wrote in message news:<20031201153328.GF605@jupp%gmx.de>…

Hi!

  • Van Jacques; 2003-12-01, 12:52 UTC:

“Josef ‘Jupp’ SCHUGT” jupp@gmx.de wrote in message news:<20031129174431.GB2320@jupp%gmx.de>…
One thing I notice was that I used

You seem to be confusing something. In the message I did answer to
you did use

a = Array.new
b = Array.new
0.upto( nnm ) do |i|
a[i] = Array.new( nn )
b[i] = Array.new( nn )
a[i] = [0,0,0,0,0,0,0,0]
b[i] = [0,0,0,0,0,0,0,0]
end

I was assuming you did intentionally implement it in that way (to
better point out the initial values) and so I saw no reson to change
it.

Josef ‘Jupp’ Schugt

I see. I must have changed it after I made the first post.