Game of Life in R

Before I decided to learn R in a serious way, I thought about learning Flash/Actionscript instead. Most of my work involves evolutionary models that take place over time. I need visual representations of change. It’s certainly possible to represent change and tell an evolving story with a single plot (see for example Tufte’s favorite infographic), but there are a lot more options when you can use animations. Flash is also object oriented, well documented with hundreds of books and websites, and has a powerful (albeit challenging to learn) IDE which helps for large coding projects.

The drawbacks to Flash are that it is way behind R in terms of statistical tools, is a closed, expensive language to work with, and dispute widespread use it might be so weak that a Apple’s iPhone might kill it.

So I picked R, with the idea that when I needed animations, I would find a way to build them. The code below is my first test of using R to generate animations. It’s a variant of Conway’s Game of Life (not to be confused with the Milton Bradley version), where single celled lifeforms live or die based on how many living neighbors they have. In my version, the rules for each cell are determined randomly, in advance of the game. The board size is fixed (see the configuration options at the beginning), whereas Conway’s version was played on a theoretically infinite grid. Green cells are “alive”, black ones are “dead”. I tried for nearly an hour to match the Black=living, White=dead scheme of Conway but couldn’t get that to work, maybe you can figure out how to do it. I re-sized the resulting animated GIF with an external program, that’s another thing I still need to figure out in R.

times = 50
myWidth = 10
myHeight = 10
# Set the 3D array of rules to determine transitions for each cell.
rulesArray = NULL
for(i in 1:9) {
	toBind <- matrix(sample(c(0,1),replace=T,(myWidth*myHeight)),ncol=myWidth)
	rulesArray <- abind(rulesArray, toBind, along=3)
first = T
frames = array(0, c(myWidth, myHeight, times))
for(i in 1:times) {
	if(first) {
		forFrame <- sample(c(0,1),replace=T,(myWidth*myHeight))
		first = F
	} else {
		# Convert last frame data to matrix to make comparing adjacent cells easier
		forFrame <- matrix(forFrame, ncol=myWidth)
		newFrame <- forFrame
		for(m in 1:myHeight) {
			for(n in 1:myWidth) {
				adjLiving = 1 # cuz we start with array index 1
				# Find out how many adjacent are living
				if(m > 1 && n > 1) {
					# Look at top left
					adjLiving = adjLiving + forFrame[(m-1),(n-1)]
				if(m > 1) {
					# Look at top center
					adjLiving = adjLiving + forFrame[(m-1),(n)]
				if(m > 1 && n < myWidth) {
					# Look at top right
					adjLiving = adjLiving + forFrame[(m-1),(n+1)]
				if(n > 1) {
					# Look at left
					adjLiving = adjLiving + forFrame[(m),(n-1)]
				if(n < myWidth) {
					# Look at right
					adjLiving = adjLiving + forFrame[(m),(n+1)]
				if(m < myHeight && n > 1) {
					# Look at bottom left
					adjLiving = adjLiving + forFrame[(m+1),(n-1)]
				if(m < myHeight) {
					# Look at bottom center
					adjLiving = adjLiving + forFrame[(m+1),(n)]
				if(m < myHeight && n < myWidth) {
					# Look at bottom right
					adjLiving = adjLiving + forFrame[(m+1),(n+1)]
				# Find the corresponding rule for this cell
				newStatus = rulesArray[m,n,adjLiving]
				# Update the status of this cell depending on the rule and number of living adjacent
				newFrame[m,n] = newStatus			
		# Pull it out of a matrix
		forFrame = unmatrix(newFrame)	
	frames[,,i] <- forFrame
write.gif(frames, "gameOfLifeRevisited.gif", col=c("#FFFF00", "#000000") , delay=150)

Tags: , ,


  1. Maybe you could take a look at Processing[1]. There are possibilities to integrate R to it [2].


  2. Update:

    I was able to fix the colors. To get black to be alive and white for dead, use these options in write.gif:

    col=gray((255:0)/255) , scale=”always”

  3. For the game, you might wish to check out this demo:

    ## fun: a package existed for long but never published on CRAN
    install.packages(‘fun’, repos=’’)

    and for the animation, I think the R package ‘animation’ might be of help, or specifically, the function saveMovie() there (other possibilities of exporting R animations include: HTML, Flash and PDF). To get started, simply install.packages("animation").

  4. Instead of creating a GIF, I exported the slides as PNG (or any image format) files, then used Quicktime 7 to sequence the images into an MP4 video. That offers you the control of sliding back and forth if you are looking for that. I’m sure there is other software that can sequence images, but QT is free and gets the job done.