# Kirby Urner, 4D Studios, Portland, Oregon  July 30, 2006

# Game of Life on a HexaPent using a globalmatrix from OFF file read in gm2.

# See:  http://www.4dsolutions.net/ocn/life.html


from visual import *
import gm2
from random import randint
import time

globalmatrix, theverts, thefaces, theedges = gm2.getneighbors('globalmatrix.off')

gameboard = {}
for k in globalmatrix:
    gameboard[k] = False
    
edgehandles = {}

scene2 = display(title='Game of Life in a HexaPent', width=1200, height=800)

for e in theedges:
    v1,v2 = [vector(*i) for i in (theverts[e[0]], theverts[e[1]]) ]
    theaxis = v2-v1
    edgehandles[e] = cylinder(pos=v1, axis=theaxis, radius=0.004, color=color.green)


class Cell (object):

    thinradius = 0.004
    fatradius = 0.008
    dead = color.green
    born = color.red
    
    def __init__(self, address):
        self.address = address
	self.edges = self._getedges()

    def _getedges(self):
        pairs = zip(self.address, list(self.address[1:]) + [self.address[0]])
        theedges = [] # local only (there's a global by the same name, tsk)

        for p in pairs:
            theedges.append(tuple(sorted(p)))
        return theedges

    def getborn(self):
        self.setcolor(Cell.born, Cell.fatradius)
        
    def die(self):
        self.setcolor(Cell.dead, Cell.thinradius)
    
    def setcolor(self, thecolor, theradius):
        for e in self.edges:
            edge = edgehandles[e]
            edge.radius = theradius
            edge.color = thecolor

    def __repr__(self):
	return "Cell %s (%s)" % (self.address)
    

def setup():
    for tile in globalmatrix.keys():
        # turn on one pentagon and surrounding hexagons

        if len(tile)==5:
            gameboard[tile] = True
            cell = Cell(tile)
            cell.getborn()
            for n in globalmatrix[tile]:
                gameboard[n] = True
                cell = Cell(n)
                cell.getborn()
            break

def main(howmany):

    setup()        
    cycles = 0
    
    while cycles < howmany:

        time.sleep(0.5)        

        alive = []
        dead = []
        
        for tile in gameboard.keys():

            alive_n = 0
            neighbors = globalmatrix[tile]

            # count living neighbors (if any)

            for n in neighbors:
                if gameboard[n]:
                    alive_n += 1

            # current rules of life (adjust to suit)

            # e.g. you may want a "no change in state" neutral value

            
            if alive_n in [0,1]:
                nextme = False
                
            elif alive_n in [2,3]:
                nextme = True
                                
            elif alive_n in [4,5,6]:
                nextme = False

            if nextme == True:
                alive.append(tile)                
            else:
                dead.append(tile)

        # expire and populate, update gameboard dictionary

        for tile in dead:
            cell = Cell(tile)
            cell.die()
            gameboard[tile] = False
            
        for tile in alive:
            cell = Cell(tile)
            cell.getborn()
            gameboard[tile] = True

        cycles += 1
        
main(50)
# code highlighted using py2html.py version 0.8