# Class file for Genetic Cellular Automaton, see GCAprog.py
# Alice Durand and David Olsen, Physics 198/250 Spring 2007

from random import randint,seed,random
from numpy import array

class GCA1D:
	def __init__(self,size,genemap,inseed):
		self.size = size
		self.Seed = inseed
		if inseed != 0:
			seed(inseed)
		self.genemap = genemap
		self.current = []
		self.next = []
		for i in range(size): #initializes the current state and sets up next state
			r1 = randint(0,len(genemap)-1)
			r2 = randint(0,len(genemap)-1)
			g1 = genemap.keys()[r1]
			g2 = genemap.keys()[r2]
			self.current.append([g1,g2])
			self.next.append([0,0])
			
	def iterate(self): #iteration algorithm, randomly selects 1 gene from each parent and gives to daughter cell
		for i in range(self.size):
			r1 = randint(0,1)
			r2 = randint(0,1)
			if ((i+1)== self.size):
				self.next[i] = [(self.current[i-1][r1]),(self.current[0][r2])]
			else:
				self.next[i] = [(self.current[i-1][r1]),(self.current[i+1][r2])]
		self.current = self.next
		
	def mutate(self, mutcof): #allows for mutations
		for i in range(self.size):
			if random()<mutcof:
				r1,r2 = randint(0,len(self.genemap)-1),randint(0,len(self.genemap)-1)
				g1,g2 = self.genemap.keys()[r1],self.genemap.keys()[r2]
				self.current[i] = [g1,g2]
			
	
	def ConvertToTuples(self): #changes from the gene pair format to a color representation of the blending, in the form of a hex tuple.
		outseq = []
		for i in range(len(self.current)):
			color1 = self.genemap[self.current[i][0]]
			color2 = self.genemap[self.current[i][1]]
			color = (color1 + color2)/2
			for j in range(len(color)):
				if color[j]!=0:
					color[j]-=1
			color = tuple(color)
			outseq.append(color)
		return outseq

class StateMatrix: #a construct to hold the screen color variables to pass into pygame
	def __init__(self, Hsize, Vsize):
		self.state = []
		self.width = Hsize
		for i in range(Vsize):
			self.state.append([])
			for j in range(Hsize):
				self.state[i].append((0,0,0))
		
	def addelement(self,inseq): #function to add rows to the matrix, pops off 1st element and adds new state at the end
		self.state.append([])
		self.state.pop(0)
		for i in range((self.width-len(inseq))/2):
			self.state[-1].append((0,0,0))
		for element in inseq:
				self.state[-1].append(element)
		for i in range(self.width-len(self.state[-1])):
			self.state[-1].append((0,0,0))
