File contents
#!/usr/bin/env python
# 2006 Guyon Moree ( http://gumuz.looz.net/ )
# python implementation of Conway's game of life using pygame ( http://www.pygame.org )
# controls:
# space = start/stop evolution
# +/- = faster/slower evolution
# r = seed the grid random
# c = clear grid
# mouseclick = paint cell
import sys, pygame
import random, time
pygame.init()
size = width, height = 800, 600
black = 0, 0, 0
blocksize = 10
# Initial pattern for glider
glider = ((-1,0),(-1,1),(0,-1),(0,1),(1,1))
# Initial pattern for gliergun
glidergun = ((25,1),
(23,2),(25,2),
(13,3),(14,3),(21,3),(22,3),(35,3),(36,3),
(12,4),(16,4),(21,4),(22,4),(35,4),(36,4),
(1,5),(2,5),(11,5),(17,5),(21,5),(22,5),
(1,6),(2,6),(11,6),(15,6),(17,6),(18,6),(23,6),(25,6),
(11,7),(17,7),(25,7),
(12,8),(16,8),
(13,9),(14,9))
patterns = { ord('g'): glider,
ord('f'): glidergun,
}
def putpattern(pattern):
grid = startgrid()
xc = width/blocksize/4
yc = height/blocksize/4
for x,y in pattern:
grid[y + yc][x + xc] = 1
return grid
screen = pygame.display.set_mode(size)
def startagegrid(grid):
agegrid = []
for r in grid:
row = []
for c in r:
row.append(0)
agegrid.append(row)
return agegrid
def startgrid(rnd=False):
""" generate emtpy or randomly filled grid """
grid = []
for y in range(height/blocksize):
row = []
for x in range(width/blocksize):
if rnd:
row.append(random.choice([0,1]))
else:
row.append(0)
grid.append(row)
return grid
def getneighbours(grid, x,y):
""" find all 8 possible neigbours """
offsets = ((-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1))
count = 0
for a,b in offsets:
ny,nx = (y+a)%len(grid), (x+b)%len(grid[y])
count += grid[ny][nx]
return count
def evolvegrid(grid, agegrid=None):
""" evolve grid to next generation """
dupe = []
for row in grid:
dupe.append(row[:])
for y in range(height/blocksize):
for x in range(width/blocksize):
pop = grid[y][x]
neighbours = getneighbours(grid, x, y)
# next step?
if pop:
if neighbours < 2 or neighbours > 3:
dupe[y][x] = 0
else:
if neighbours == 3:
dupe[y][x] = 1
if agegrid:
if pop and dupe[y][x] and agegrid[y][x] < 250:
agegrid[y][x] += 15
elif not dupe[y][x]:
agegrid[y][x] = 0
return dupe
def paintgrid(surface, grid, agegrid=None):
""" paint grid to screen """
for y in range(height/blocksize):
for x in range(width/blocksize):
if grid[y][x]:
if agegrid:
color = (255-agegrid[y][x],255-agegrid[y][x],255)
else:
color = (255,255,255)
surface.fill(color, pygame.Rect((x*blocksize,y*blocksize), (blocksize, blocksize)))
def paintcell(grid, pos, brush):
""" paint a cell in the gid """
x,y = pos
grid[y/blocksize][x/blocksize] = brush
return grid
# init the grid
grid = startgrid()
agegrid = startagegrid(grid)
# init some vars
evolve = False
mousedown = False
interval = 0
brush = 1
step = False
# main loop
while 1:
for event in pygame.event.get():
""" handle events """
# escape
if event.type == pygame.QUIT: sys.exit()
# space play/pause
if event.type == pygame.KEYDOWN and event.key == 32: #SP
evolve = not evolve
# step 1 generation
if event.type == pygame.KEYDOWN and event.key == 115: # s
step = True
# randomise/reset grid
if event.type == pygame.KEYDOWN and event.key == 114: # r
grid = startgrid(True)
if event.type == pygame.KEYDOWN and event.key == 99: # c
grid = startgrid()
# Hack! patterns
if event.type == pygame.KEYDOWN and event.key in patterns.keys():
grid = putpattern(patterns[event.key])
# speed control
if event.type == pygame.KEYDOWN and event.key == 270:
if interval > 0: interval -= .1
if interval < 0: interval = 0
if event.type == pygame.KEYDOWN and event.key == 269:
interval += .1
# mouse paint
if event.type == pygame.MOUSEBUTTONDOWN:
mousedown = True
x,y = event.pos
brush = not grid[y/blocksize][x/blocksize]
grid = paintcell(grid, event.pos, brush)
if event.type == pygame.MOUSEBUTTONUP:
mousedown = False
if event.type == pygame.MOUSEMOTION and mousedown:
grid = paintcell(grid, event.pos, brush)
# reset screen
screen.fill(black)
# paint the grid
paintgrid(screen, grid, agegrid)
# if not paused or 'step' was pressed and no mousedown, evolve the grid
if (evolve or step) and not mousedown:
grid = evolvegrid(grid, agegrid)
time.sleep(interval)
step = False
# display to screen
pygame.display.flip()