Created
June 21, 2012 03:50
-
-
Save rgrannell1/2963715 to your computer and use it in GitHub Desktop.
An R implementation of Game of Life
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
AutonomaGenerate = function( | |
dims = 25 # the size of the autonomaton | |
) | |
{ | |
# Ryan Grannell, 2012 | |
# A function to generate random autonoma (tend to be square, | |
# or hazy clouds) | |
on = sample(1:dims^2, size = | |
sample(1:dims^2, size = 1) | |
) | |
newCreature = matrix(0, dims, dims) | |
newCreature[on] = 1 | |
kIndex = which(newCreature == 1) | |
ID = c(dims,kIndex) | |
return(ID) | |
} | |
GameOfLife = function( | |
creatureID = c(4,1,2,3), # the starting autonoma, in ID form | |
iterations = 10, # how many times the autonomaton is updated | |
size = 75 # the size of the torus we are playing on | |
) | |
{ | |
# Ryan Grannell, 2012 | |
# A function to generate an array with each slice showing one step of | |
# the Game of Life | |
creature = matrix(0,creatureID[1], creatureID[1]) | |
creature[creatureID[-1]] = longevity = 1 | |
border = rep(0, 4) | |
stepList = list() | |
neighboursI = neighboursJ = rep(0,8) | |
names(border) = c( | |
"left", "right", | |
"top", "bottom" | |
) | |
neighbourNames = c( | |
"topleft", "top", "topright", | |
"left", "right", | |
"bottomleft", "bottom", "bottomleft" | |
) | |
#1. add the creature to the grid | |
grid = array(0, | |
dim = c(size, size, iterations+1) | |
) | |
tempGrid = matrix(0, | |
size, size | |
) | |
grid[ | |
50:(50+(nrow(creature)-1)), | |
50:(50+(ncol(creature)-1)), | |
1 | |
] = creature | |
nonZero = which(grid[,,1] == 1) | |
#2. update the grid based on Conway's rules | |
for(step in 1:iterations){ | |
longevity = longevity + 1 | |
print( | |
paste("STEP",step,";", length(nonZero), "active cells") | |
) | |
for(i in 1:size){ | |
for(j in 1:size){ | |
#3. make two vectors containing the i,j positions of the neighbours | |
neighboursI[c("topleft", "top", "topright")] = i - 1 | |
neighboursI[c("left", "right")] = i | |
neighboursI[c("bottomleft", "bottom", "bottomright")] = i + 1 | |
neighboursJ[c("topleft", "left", "bottomleft")] = j - 1 | |
neighboursJ[c("top", "bottom")] = j | |
neighboursJ[c("topright", "right", "bottomright")] = j + 1 | |
neighboursI[ | |
neighboursI == 0 | |
] = size | |
neighboursI[ | |
neighboursI == size + 1 | |
] = 1 | |
neighboursJ[ | |
neighboursJ == 0 | |
] = size | |
neighboursJ[ | |
neighboursJ == size + 1 | |
] = 1 | |
#4. check the array at these positions (at the appropriate time dimension) | |
noNeighbours = sum( | |
c( | |
grid[neighboursI["topleft"], neighboursJ["topleft"], step], | |
grid[neighboursI["top"], neighboursJ["top"], step], | |
grid[neighboursI["topright"], neighboursJ["topright"], step], | |
grid[neighboursI["left"], neighboursJ["left"], step], | |
grid[neighboursI["right"], neighboursJ["right"], step], | |
grid[neighboursI["bottomleft"], neighboursJ["bottomleft"], step], | |
grid[neighboursI["bottom"], neighboursJ["bottom"], step], | |
grid[neighboursI["bottomright"], neighboursJ["bottomright"], step] | |
) | |
) | |
#5. turn on or off cells accordingly | |
if(noNeighbours < 2) tempGrid[i, j] = 0 | |
if(noNeighbours > 3) tempGrid[i, j] = 0 | |
if(noNeighbours == 3) tempGrid[i, j] = 1 | |
} | |
} | |
grid[,,step + 1] = tempGrid | |
tempGrid = matrix(0, size, size) | |
nonZero = which(grid[,,step+1] == 1) | |
if(length(nonZero) == 0){ | |
break | |
} | |
} | |
stepList$steps = grid | |
stepList$longevity = longevity | |
stepList$dimension = size | |
return(stepList) | |
} | |
ScaleUp = function( | |
gridData, # the object created by GameOfLife() | |
scale = 5 # an integer denoting how many times larger to make the | |
# array | |
){ | |
# Ryan Grannell, 2012 | |
dimension = gridData$dimension | |
scaledArray = array(0, | |
dim = c(scale * dimension, | |
scale * dimension, | |
gridData$longevity | |
) | |
) | |
for(i in 1:dimension){ | |
toFillI = c( | |
(((i - 1) * scale) + 1): | |
(((i - 1) * scale) + scale) | |
) | |
for(j in 1:dimension){ | |
toFillJ = c( | |
(((j - 1) * scale) + 1): | |
(((j - 1) * scale) + scale) | |
) | |
for(k in 1:gridData$longevity){ | |
scaledArray[toFillI, toFillJ, k] = gridData$steps[i,j,k] | |
} | |
} | |
} | |
return(scaledArray) | |
} | |
GameOfLifePlot = function( | |
gridData, # the object created by GameOfLife() | |
filename = "defaultFilename", # a filename fot the GIF, excluding the extension | |
scale = 5 # an integer denoting how many times larger to make the | |
# array | |
) | |
{ | |
# Ryan Grannell, 2012 | |
# A .gif visualisation function | |
require(caTools) | |
#1. scale the image, so that the .gif is a suitable size | |
gridArray = ScaleUp(gridData, scale) | |
write.gif(gridArray, | |
paste(filename, ".gif"), | |
col = c(0,1), delay = 75 | |
) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment