Paste: game of life

Author: daniel gabriele
Mode: python
Date: Sat, 6 Jun 2009 15:10:24
Plain Text |
#!/usr/bin/env python
# life.py
'''
Conway's Game of Life '''

import random
import pygame

# Set Up
pygame.init()
colors = pygame.color.THECOLORS
ON, OFF = 1, 0

# The Plan:
# Put the cells in a dict from {relative location : cell}
# That way neighbors can be looked-up easily in a flat list.
#
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
class Cell (object):


	def __init__ (self, **kwargs):
		self.size = (25, 25)		
		self.oncolor = colors['green']
		self.offcolor = colors['black']
		self.state = OFF
		
		# absolute topleft pixel position. 
		# IE: (25,0), (50,0), (75,0), ...
		self.position = None   
		
		# relative position in grid. 
		# IE: (0,0), (1,0), (2,0), ... 
		self.relpos = None        
		
		# unpack kwargs
		for k in kwargs:
			setattr(self, k, kwargs[k])
		
		self._init_default_config()
	
	@property
	def width (self):
		return self.size[0]

	@property
	def height (self):
		return self.size[1]
	
	
	def _init_default_config (self):
		self.image = pygame.Surface(self.size)
		self.image.set_alpha(0)
		self.rect = self.image.get_rect()
	
		if self.state:
			self.image.fill(self.oncolor)
		else:
			self.image.fill(self.offcolor)

		if hasattr(self, 'position'):
			self.rect.topleft = self.position
	
	
	def update (self):
		if self.state:
			self.image.fill(self.oncolor)
			self.image.set_alpha(40)
		else:
			self.image.fill(self.offcolor)
	
	
	def __repr__ (self):
		return "<cell>"


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!	
class Grid (object):


	def __init__ (self, gridsize, cellsize):
		self.w, self.h = gridsize     # grid w, h
		self.cw, self.ch = cellsize   # cell w, h    
		self.n = self.w * self.h      # n cells
		self.cells = {}               # relpos:cell look-up
		
		##### Initial Configuration #####
		
		relx = rely = 0   # relative (x,y) coordinates
		absx = absy = 0   # absolute pixel coordinates
	
		# populate grid, setting positions
		for i in xrange(self.n):
			cell = Cell( size=(self.cw, self.ch),
					     position=(absx, absy), 
					     relpos=(relx, rely),
					     state = random.choice([ON,OFF]) )
			
			# stores previous state
			cell.history = cell.state 
			
			# {relpos:cell}
			self.cells[(relx, rely)] = cell
		
			absx += cell.width 
			rely += 1 
			
			# wraps coordinate counts to new row
			if (i + 1) % self.w == 0 and i != 0:
				absx = 0
				relx += 1
				absy += cell.height
				rely = 0	
				
		
	def update (self):
		for cell in self.cells.itervalues():
			
			cell.history = cell.state    # stores previous state
			cell.update()                # sets cell state color
			x, y = cell.relpos           # relative position in grid
			
			# Cases for cells on grid boundaries. Wrap around nhood.
			if x not in (0, self.w-1) and y not in (0, self.h-1):
				neighbors = [(x-1,y), (x+1,y), (x,y-1), (x,y+1)]
			elif x == 0 and y == 0:
				neighbors = [(self.w-1,y), (x+1,y), (x,self.h-1), (x,y+1)]
			elif x == self.w-1 and y == 0:
				neighbors = [(x-1,y), (0,y), (x,self.h-1), (x,y+1)]
			elif x == 0 and y == self.w-1:
				neighbors = [(x,y-1), (x,0), (self.w-1,y), (x+1, y)]
			elif x == self.w-1 and y == self.h-1:
				neighbors = [(x,y-1), (x,0), (x-1,y), (0, y)]
			elif (x>0 and x<self.w-1) and y == 0:
				neighbors = [(x-1,y), (x+1,y), (x,self.h-1), (x,y+1)]
			elif (x>0 and x<self.w-1) and y == self.h-1:
				neighbors = [(x-1,y), (x+1,y), (x,0), (x,y-1)]
			elif x == 0 and (y>0 and y<self.h-1):
				neighbors = [(x,y-1), (x,y+1), (self.w-1,y), (x+1,y)]
			elif x == self.w-1 and (y>0 and y<self.h-1):
				neighbors = [(x,y-1), (x,y+1), (x-1,y), (0,y)]
			
			# sum neighboring history states + self's history state
			cell.nhood = sum([1 for n in neighbors if self.cells[n].history])
			cell.nhood += cell.history
	
			# set new cell state		
			if cell.nhood < 3 and cell.nhood > 1:
				cell.state = ON
			else:
				cell.state = OFF
			
			# draw to screen
			screen.blit(cell.image, cell.position)
	
	
	def randcolor(self, lower=180, upper=240, alpha=255):
		cvals = range(lower, upper)
		r, g, b = [random.choice(cvals) for i in range(3)]
		return pygame.Color(r, g, b, alpha)




# ////////////////////////
if __name__ == '__main__':
	grid = Grid((50, 50), (14,14))
	screen = pygame.display.set_mode((grid.w*grid.cw, grid.h*grid.ch))
	bg = pygame.Surface(screen.get_size())
	clock = pygame.time.Clock()
	running = True
	
	bg.fill((0,0,0))
	bg.set_alpha(10)
	
	while running:
		clock.tick(30)
		for e in pygame.event.get():
			if not hasattr(e, 'key'): 
				continue
			if e.key == pygame.K_q or e.key == pygame.K_ESCAPE: 
				running = False
		
		#screen.blit(bg, (0,0))
		grid.update()		

		#updaterects = [cell.rect for cell in grid.array if cell.state]
		#pygame.display.update(updaterects)
		pygame.display.flip()

New Annotation

Summary:
Author:
Mode:
Body: