The Game of Life, created by John Conway in 1970, is probably the most well known cellular automata. Implemented on a grid it has a few very simple rules that are imposed at each cycle:
1. Any cell with fewer than two live neighbors dies
2. Any living cell with two or three living neighbors lives
3. Any living cell with more than three living neighbors dies
4. Any dead cell with exactly three living neighbors becomes a living cell
While there are many different types of cellular automata I’ve decided to use this one for a few reasons: it’s very well known, easy to code, and most importantly it is Turing complete so anything that can be computed can be done within the Game of Life (GOL).
The algorithm for the game of life is shown in the following pseudo-code:
#Declarations rows = 40 #num rows of matrix columns = 80 #num columns of matrix fps = 20 #number of frames per second to display cycles = 500 #number of simulation iterations use_seed = 1 #0=no, 1=yes #define locations of 8 neighbor cells neighbors = [[-1,-1],[0,-1],[1,-1],[-1,0],[1,0],[-1,1],[0,1],[1,1]] seed = [[0,0,1], #glider [1,0,1], [0,1,1]] #seed = [[0,1,0], #blinker # [0,1,0], # [0,1,0]]
#Initialize currentState = populate(rows, columns, use_seed, 3, 3, seed)
def populate(numR, numC, use_seed, insertR, insertC, seed): #populate either with a seed or with random 1s and 0s if use_seed == 0: #Populate with random field of 1s and 0s currentState = [[random.randint(0,1) for i in range(numC)] for j in range(numR)] else: #Populate with seed currentState = [[0 for i in range(numC)] for j in range(numR)] nextState = [[0 for i in range(numC)] for j in range(numR)] Cseed = len(seed[0]) Rseed = len(seed) for i in range(Rseed): for j in range(Cseed): currentState[insertR+i][insertC+j] = seed[i][j] return currentState
#Main print "Running" for i in range(cycles): currentState = update_state(currentState, neighbors) #print "Cycle ", i display(currentState,fps) print "Done"
def update_state(currentState, neighbors): ''' this function is where the actual game of life calculations happen for each cell count = 0 for each neighbor if currentState == alive count = ++ if count == 3 nextState = alive else if count != 2 or 3 nextState = dead ''' nextState = copy.deepcopy(currentState) Rindex = 0 for row in currentState: Cindex = 0 for cell in row: count = 0 for neighbor in neighbors: # % does modulo indexing to create toroidal universe neighborR = (Rindex + neighbor[1]) % len(currentState) neighborC = (Cindex + neighbor[0]) % len(currentState[0]) if currentState[neighborR][neighborC] == 1: count += 1 if count == 3: nextState[Rindex][Cindex] = 1 elif count != (2 or 3): nextState[Rindex][Cindex] = 0 Cindex += 1 Rindex += 1 return nextState
def display(universe, fps): #very simple routine to display animated cell state in terminal #calculate time to sleep sleepTime = 1.0/fps #clear screen and reposition cursor sys.stderr.write("\x1b[2J\x1b[H") for row in universe: for column in row: if column == 0: #leave empty for 0 sys.stdout.write(' ') else: #fill in for 1 sys.stdout.write('#') print "\r" sys.stdout.flush() time.sleep(sleepTime)
sys.stderr.write("\x1b[2J\x1b[H") #clear screen and reposition cursor
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 ''' Chad Bonner Nov.23.2013 Game of Life ''' #Module import import copy import sys import time import random # Function Definitions def update_state(currentState, neighbors): ''' this function is where the actual game of life calculations happen for each cell count = 0 for each neighbor if currentState == alive count = ++ if count == 3 nextState = alive else if count != 2 or 3 nextState = dead ''' nextState = copy.deepcopy(currentState) Rindex = 0 for row in currentState: Cindex = 0 for cell in row: count = 0 for neighbor in neighbors: # % does modulo indexing to create toroidal universe neighborR = (Rindex + neighbor[1]) % len(currentState) neighborC = (Cindex + neighbor[0]) % len(currentState[0]) if currentState[neighborR][neighborC] == 1: count += 1 if count == 3: nextState[Rindex][Cindex] = 1 elif count != (2 or 3): nextState[Rindex][Cindex] = 0 Cindex += 1 Rindex += 1 return nextState def display(universe, fps): #very simple routine to display animated cell state in terminal #calculate time to sleep sleepTime = 1.0/fps #clear screen and reposition cursor sys.stderr.write("\x1b[2J\x1b[H") for row in universe: for column in row: if column == 0: #leave empty for 0 sys.stdout.write(' ') else: #fill in for 1 sys.stdout.write('#') print "\r" sys.stdout.flush() time.sleep(sleepTime) def populate(numR, numC, use_seed, insertR, insertC, seed): #populate either with a seed or with random 1s and 0s if use_seed == 0: #Populate with random field of 1s and 0s currentState = [[random.randint(0,1) for i in range(numC)] for j in range(numR)] else: #Populate with seed currentState = [[0 for i in range(numC)] for j in range(numR)] nextState = [[0 for i in range(numC)] for j in range(numR)] Cseed = len(seed[0]) Rseed = len(seed) for i in range(Rseed): for j in range(Cseed): currentState[insertR+i][insertC+j] = seed[i][j] return currentState #Declarations rows = 40 #num rows of matrix columns = 80 #num columns of matrix fps = 1 #number of frames per second to display cycles = 500 #number of simulation iterations use_seed = 0 #0=no, 1=yes #define locations of 8 neighbor cells neighbors = [[-1,-1],[0,-1],[1,-1],[-1,0],[1,0],[-1,1],[0,1],[1,1]] seed = [[0,0,1], #glider [1,0,1], [0,1,1]] #seed = [[0,1,0], #blinker # [0,1,0], # [0,1,0]] #Initialize currentState = populate(rows, columns, use_seed, 3, 3, seed) #Main print "Running" for i in range(cycles): currentState = update_state(currentState, neighbors) #print "Cycle ", i display(currentState,fps) print "Done"
Comments:2
Leave a Reply