Welcome, guest | Sign In | My Account | Store | Cart
'''
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

History