''' Created on 6 June 2012 @author: bakera Each cell needs to be considered with neighbours 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 http://en.wikipedia.org/wiki/Conway's_Game_of_Life ''' import numpy as np import time import sys from ctypes import * def check(grid, row,col, countNumberOfAdjoiningCellsActive, verbose=False): try: #if verbose: # print 'before row %d, col %d, value %d, count %d' % (row, col, grid[row, col], len(countNumberOfAdjoiningCellsActive)) if (col >= 0) and (row >=0): # protect if grid[row,col] != 0: countNumberOfAdjoiningCellsActive.append(grid[row,col]) if verbose: print 'after row %d, col %d, value %d, count %d' % (row, col, grid[row, col], len(countNumberOfAdjoiningCellsActive)) except : pass def isalive((r,c), (lr,lc), grid, location, verbose= False): ''' apply rules against the r,c based on the local grid[lr,lc] Parameters ------------ all parameters are keyword parameters (r,c) : interger tuple represents the location of the cell in the global matrix (lr,lc) : integer tuple represents the location in the local grid matrix grid : matrix represents the neighbours to analyse location: string either corner, edge, top or body ''' countNumberOfAdjoiningCellsActive = [] check(grid, lr, lc+1, countNumberOfAdjoiningCellsActive, verbose) check(grid, lr, lc-1, countNumberOfAdjoiningCellsActive, verbose ) check(grid, lr+1, lc, countNumberOfAdjoiningCellsActive, verbose ) check(grid, lr+1, lc+1, countNumberOfAdjoiningCellsActive, verbose ) check(grid, lr+1, lc-1, countNumberOfAdjoiningCellsActive, verbose ) check(grid, lr-1, lc, countNumberOfAdjoiningCellsActive, verbose ) check(grid, lr-1, lc+1, countNumberOfAdjoiningCellsActive, verbose ) check(grid, lr-1, lc-1, countNumberOfAdjoiningCellsActive, verbose ) if verbose: if len(countNumberOfAdjoiningCellsActive) != 0: print 'value %d, countNumberOfAdjoiningCellsActive %d' % (grid[lr,lc], len(countNumberOfAdjoiningCellsActive)) isAlive = False #Any live cell with fewer than two live neighbours dies, as if caused by under-population. #Any live cell with more than three live neighbours dies, as if by overcrowding. if grid[lr,lc] == 1 and (len(countNumberOfAdjoiningCellsActive) < 2 or len(countNumberOfAdjoiningCellsActive) > 3) : # under or over populated then die out isAlive = False #Any live cell with two or three live neighbours lives on to the next generation. elif grid[lr,lc] == 1 and (len(countNumberOfAdjoiningCellsActive) == 2 or len(countNumberOfAdjoiningCellsActive) == 3): isAlive = True #Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. elif grid[lr,lc] == 0 and (len(countNumberOfAdjoiningCellsActive) == 3): isAlive = True return isAlive def iterate_grid(a, (p,q)): ''' generate the next sub matrix from the original matrix yield the sub matrix back to be consumed Parameters ---------- all parameters are keyword parameters a : parent matrix represents the larger parent matrix (p,q): tuple represents the dimensions of each sub matrix to generate Returns ------- yields the next sub matrix ''' row, col = np.shape(a) #print row,col for (r,c) in ((r,c) for r in np.arange(row-p+2) for c in np.arange(col-q+2)): if r ==0 and c == 0: #corner yield (r,r+q, c,c+q), (r,c), (0,0), np.matrix(a[r:r+q, c:c+q]), 'corner' elif r ==0 and c != 0: #top yield (r,r+q, c-1,c+q), (r,c), (0,1), np.matrix(a[r:r+q, c-1:c+q]) , 'top' elif r !=0 and c == 0: # edge, yield (r-1,r+q, c,c+q), (r,c), (1,0), np.matrix(a[r-1:r+q, c:c+q]) , 'edge' else: # normal body yield (r-1,r+p, c-1,c+q), (r,c), (1,1), np.matrix(a[r-1:r+p, c-1:c+q]) , 'body' def prettyprint(state): colours = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'red', 6: 'red'} colour_map = {1: 10, 2: 12, 3: 13, 4: 14, 5: 15, 6: 9, 0:5} # empty cells colour black if (not (sys.platform == 'linux2')):windll.Kernel32.GetStdHandle.restype = c_ulong if (not (sys.platform == 'linux2')):h = windll.Kernel32.GetStdHandle(c_ulong(0xfffffff5)) for i, row in enumerate(state.flat): i = i + 1 color = colour_map[row] if (not (sys.platform == 'linux2')): windll.Kernel32.SetConsoleTextAttribute(h, color) r, c = np.shape(state) if i == 0: sys.stdout.write(" %d" % (row)) elif (i % 10 == 0) : sys.stdout.write(" %d\n" % (row)) # include 2 spaces for the twissler sys.stdout.flush() else: sys.stdout.write(" %d" % (row)) # include 2 spaces for the twissler if (not (sys.platform == 'linux2')):windll.Kernel32.SetConsoleTextAttribute(h, 15) # return to white def test_sharing_array(model, steps=10, verbose=False): start = np.loadtxt(model) next = np.loadtxt('empty.dat') #print start for step in np.arange(steps): time.sleep(1) prettyprint(start) for (r1,r2,c1,c2), (r,c), (lr,lc), grid, location in iterate_grid(start, (2,2)): # data is a 2-D array # r,c - location in the parent matrix # lr, lc - location in the child grid of the cell to evaluate #print (r,c), (lr,lc), grid, grid[lr,lc], location if isalive((r,c), (lr,lc), grid, location, verbose): next[r,c] = 1 else: next[r,c] = 0 start = next.copy() # independent copy of next if __name__ == '__main__': verboseFlag = False test_sharing_array('glider.dat', 5, verboseFlag) glider.dat 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0