Conway's game of life is not, strictly speaking, geometric art. However, as you progress through the stages of 'life' in this 'game' you'll often see interesting geometric patterns emerge. Let's start by looking at a few examples.
Examples
Sometimes, you'll get patterns that end after a certain number of timepoints:
Other times, you'll get patterns that continuously repeat:
Even if you start from a completely random assortment of white and black pixels, you can get something that looks pretty interesting.
Okay, that looks pretty neat, but what is it?
Conway's Game of Life relies on each pixel in the image having a state: alive (black) or dead (white). For each 'tick' of the clock (i.e. for each video frame) you evaluate for each pixel whether it will remain in its current state or change state.
The rules of life
You determine what happens to each pixel by evaluating its neighbors. In a square grid, every pixel has eight neighbors (except the border pixels, which have less). Then, you evaluate these four rules:
- Any live cell with fewer than two live neighbors dies, as if by under-population.
- Any live cell with two or three live neighbors lives on to the next generation.
- Any live cell with more than three live neighbors dies, as if by over-population.
- Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
(source: wikipedia)
You can play around with Conway's game of life easily here. Or, you can use the code I provide below (which also allows you to make a video).
Code
% To use this code, you can either run one of the pre-programmed examples
% (i.e. set startingMatrix to 1, 2, 3, 4, or 5), or make up your own "life"
% matrix. Set makeVideo to 1 if you want to record a video
makeVideo=0;
startingMatrix=5;
% Pattern that ends
if startingMatrix==1
size1=17;
size2=17;
iterations=15;
life=zeros(size1,size2,iterations+1);
life(8,8:10)=[1 1 1];
life(9,8)=1;
life(9,10)=1;
life(10,9:10)=[1 1];
life(11,8)=1;
end
% Pattern that repeats
if startingMatrix==2
size1=11;
size2=18;
iterations=50;
life=zeros(size1,size2,iterations+1);
life(4,7:12)=[1,1,1,1,1,1];
life(8,7:12)=[1 1 1 1 1 1];
life(5,6)=1;
life(5,13)=1;
life(7,6)=1;
life(7,13)=1;
life(6,5)=1;
life(6,14)=1;
end
% Simple repeating pattern
if startingMatrix==3
size1=5;
size2=5;
iterations=8;
life=zeros(size1,size2,iterations+1);
life(2:4,3)=[1;1;1];
end
% Pattern that repeats
if startingMatrix==4
size1=17;
size2=17;
iterations=4;
life=zeros(size1,size2,iterations+1);
life(3,5:7)=[1 1 1];
life(3,11:13)=[1 1 1];
life(8,5:7)=[1 1 1];
life(8,11:13)=[1 1 1];
life(10,5:7)=[1 1 1];
life(10,11:13)=[1 1 1];
life(15,5:7)= [1 1 1];
life(15,11:13)= [1 1 1];
life(5:7,3)=[1;1;1];
life(11:13,3)=[1;1;1];
life(5:7,8)=[1;1;1];
life(11:13,8)=[1;1;1];
life(5:7,10)=[1;1;1];
life(11:13,10)=[1;1;1];
life(5:7,15)=[1;1;1];
life(11:13,15)=[1;1;1];
end
% Start with a random matrix
if startingMatrix==5
size1=50;
size2=50;
iterations=600;
life=ones(size1,size2,iterations+1);
for i=1:size1
for j=1:size2
life(i,j)=round(rand);
end
end
end
% If making a video, initialize the video
if makeVideo==1
writerObj = VideoWriter('GameOfLifeStopExample1.avi'); % Name it.
writerObj.FrameRate = 1;
writerObj.Quality=100;
open(writerObj)
end
% Initialize the figure and display the starting matrix
figure('Position',[10,10,700,700],'Color',[1 1 1]);
imagesc(life(:,:,1))
hold on
axis off
axis equal
% Plot the grid
for m=0:size1
plot([0,size2]+.5,[m,m]+.5,'Color',[0.6 0.6 0.6],'LineWidth',1.5);
end
for m=0:size2
plot([m,m]+.5,[0,size1]+.5,'Color',[0.6 0.6 0.6],'LineWidth',1.5);
end
colormap('hot')
colormap(flipud(colormap))
% Grab a frame for the video
if makeVideo==1
frame = getframe(1);
writeVideo(writerObj, frame)
end
pause(1)
finish=0;
% Repeat for each iteration
for i=2:iterations+1
% Clear the current axes
cla
% For each row
for j=1:size1
% For each column
for k=1:size2
% Edge case: corner
if j==1 && k==1
a=life(j+1,k,i-1);
b=life(j,k+1,i-1);
c=0;
d=0;
e=life(j+1,k+1,i-1);
f=0;
g=0;
h=0;
% Edge case: corner
elseif j==1 && k==size2
a=life(j+1,k,i-1);
b=life(j,k-1,i-1);
c=0;
d=0;
e=life(j+1,k-1,i-1);
f=0;
g=0;
h=0;
% Edge case: corner
elseif j==size1 && k==size2
a=life(j-1,k,i-1);
b=life(j,k-1,i-1);
c=0;
d=0;
e=life(j-1,k-1,i-1);
f=0;
g=0;
h=0;
% Edge case: corner
elseif j==size1 && k==1
a=life(j-1,k,i-1);
b=life(j,k+1,i-1);
c=0;
d=0;
e=life(j-1,k+1,i-1);
f=0;
g=0;
h=0;
% Edge case: side
elseif j==1
a=life(j+1,k,i-1);
b=life(j,k-1,i-1);
c=life(j,k+1,i-1);
d=0;
e=life(j+1,k-1,i-1);
f=life(j+1,k+1,i-1);
g=0;
h=0;
% Edge case: side
elseif k==1
a=life(j+1,k,i-1);
b=life(j-1,k,i-1);
c=life(j,k+1,i-1);
d=0;
e=life(j+1,k+1,i-1);
f=life(j-1,k+1,i-1);
g=0;
h=0;
% Edge case: side
elseif j==size1
a=life(j-1,k,i-1);
b=life(j,k-1,i-1);
c=life(j,k+1,i-1);
d=0;
e=life(j-1,k-1,i-1);
f=life(j-1,k+1,i-1);
g=0;
h=0;
% Edge case: side
elseif k==size2
a=life(j+1,k,i-1);
b=life(j-1,k,i-1);
c=life(j,k-1,i-1);
d=0;
e=life(j-1,k-1,i-1);
f=life(j+1,k-1,i-1);
g=0;
h=0;
% For any non-border pixel
else
a=life(j,k-1,i-1);
b=life(j,k+1,i-1);
c=life(j-1,k,i-1);
d=life(j+1,k,i-1);
e=life(j-1,k-1,i-1);
f=life(j-1,k+1,i-1);
g=life(j+1,k+1,i-1);
h=life(j+1,k-1,i-1);
end
% If the square is alive
if life(j,k,i-1)==1
if a+b+c+d+e+f+g+h==2 || a+b+c+d+e+f+g+h==3
life(j,k,i)=1;
elseif a+b+c+d+e+f+g+h>3
life(j,k,i)=0;
elseif a+b+c+d+e+f+g+h==0 || a+b+c+d+e+f+g+h==1
life(j,k,i)=0;
end
% If the square is dead
elseif life(j,k,i-1)==0
if a+b+c+d+e+f+g+h==3
life(j,k,i)=1;
else
life(j,k,i)=0;
end
end
end
end
% If you've reached a state where life no longer changes, end the
% simulation
if life(:,:,i)==life(:,:,i-1)
disp(['SAME at round ',num2str(i-2)]);
finish=i-2;
break
else
finish=i-1;
end
% Display the current state
imagesc(life(:,:,i));
hold on
% Draw the grid
for m=0:size1
plot([0,size2]+.5,[m,m]+.5,'Color',[0.6 0.6 0.6],'LineWidth',1.5);
end
for m=0:size2
plot([m,m]+.5,[0,size1]+.5,'Color',[0.6 0.6 0.6],'LineWidth',1.5);
end
axis off
axis equal
pause(1)
% Grab a frame for the video
if makeVideo==1
frame = getframe(1);
writeVideo(writerObj, frame)
end
end
% Terminate the video
if makeVideo==1
close(writerObj)
end