Skip to content

Instantly share code, notes, and snippets.

@Lanny
Created June 2, 2013 01:07
Show Gist options
  • Save Lanny/5692241 to your computer and use it in GitHub Desktop.
Save Lanny/5692241 to your computer and use it in GitHub Desktop.
A poorly optimized implementation of Conway's Game of Life in Python with PyGame.
#! /usr/bin/env python
# Conway's game of life
# Copyright(c) 2012 Ryan Jenkins
import pygame, time
from pygame.locals import *
class lifeGrid() :
def __init__(self, width, height) :
self.grid = []
# Populate our grid
for col in range(width) :
self.grid.append([])
for cell in range(height) :
self.grid[-1].append(0)
def set(self, value, x, y) :
'''Sets cell x, y to value'''
self.grid[x][y] = value
def toggle(self, x, y) :
if self.grid[x][y] :
self.grid[x][y] = 0
else :
self.grid[x][y] = 1
def get(self, x, y) :
'''Return cell state at x,y'''
return self.grid[x][y]
def birth(self, x, y) :
'''Force cell x,y to life'''
self.grid[x][y] = 1
def kill(self, x, y) :
'''Force cell x,y to death'''
self.grid[x][y] = 0
def get_neighbors(self, x, y) :
'''Return list of neighbors, live or dead'''
possibleNeighbors = [[x+1, y],
[x+1, y+1],
[x+1, y-1],
[x-1, y],
[x-1, y+1],
[x-1, y-1],
[x, y+1],
[x, y-1]]
trueNeighbors= []
for z in possibleNeighbors :
if z[0] == -1 :
z[0] = self.get_dims()[0] - 1
elif z[0] == self.get_dims()[0] :
z[0] = 0
if z[1] == -1 :
z[1] = self.get_dims()[1] - 1
elif z[1] == self.get_dims()[1] :
z[1] = 0
trueNeighbors.append(self.grid[z[0]][z[1]])
return trueNeighbors
def get_live_neighbors(self, x, y) :
'''Return number of living cells adjacent to cell x,y'''
live_count = 0
for neighbor in self.get_neighbors(x, y) :
if neighbor : live_count += 1
return live_count
def get_dims(self) :
return (len(self.grid[0]), len(self.grid))
def conways_life(start_grid) :
x, y = start_grid.get_dims()
new_grid = lifeGrid(x, y)
updateRects = []
for mapy in range(y) :
for mapx in range(x) :
if start_grid.get_live_neighbors(mapx, mapy) < 2 or start_grid.get_live_neighbors(mapx, mapy) > 3 :
if start_grid.get(mapx, mapy) :
# If we're actually changing the value of the cell, add it
# to the list of cells to be re-drawn
updateRects.append(coord_to_px(start_grid, mapx, mapy))
new_grid.kill(mapx, mapy)
elif start_grid.get_live_neighbors(mapx, mapy) == 3 :
if not start_grid.get(mapx, mapy) :
updateRects.append(coord_to_px(start_grid, mapx, mapy))
new_grid.birth(mapx, mapy)
else :
new_grid.set(start_grid.get(mapx, mapy), mapx, mapy)
return (new_grid, updateRects)
def px_to_coord(grid, x, y) :
gridx = x / 10
gridy = -((y / 10)-grid.get_dims()[1]+1)
print gridx, gridy
return (gridx, gridy)
def coord_to_px(grid, x, y) :
mapy = (grid.get_dims()[1] - 1 - y) * 10
mapx = (x) * 10
#print mapx, mapy
return pygame.Rect(mapx, mapy, 9, 9)
def renderGrid(screen, grid) :
# Blit the background
screen.blit(background, (0,0))
# Draw our cells
for gridy in range(grid.get_dims()[1]) :
mapy = (grid.get_dims()[1] - 1 - gridy) * 10
for gridx in range(grid.get_dims()[0]) :
mapx = gridx * 10
if grid.get(gridx, gridy) :
pygame.draw.rect(screen, LIVE_COLOR, (mapx, mapy, 9, 9))
elif not grid.get(gridx, gridy) :
pygame.draw.rect(screen, DEAD_COLOR, (mapx, mapy, 9, 9))
if __name__ == '__main__' :
WINDOW_SIZE = (600,600)
BACKGROUND_COLOR = (0, 0, 0)
DEAD_COLOR = (50, 50, 50)
LIVE_COLOR = (255, 255, 0)
# Pygame ceremony.
pygame.init()
screen = pygame.display.set_mode(WINDOW_SIZE)
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill(BACKGROUND_COLOR)
grid = lifeGrid(60, 60)
'''
grid.birth(56,57);
grid.birth(57,56);
grid.birth(55,55);grid.birth(56,55);grid.birth(57,55);
'''
running = True
accept_input = True
updateRects = []
generation = 0
# Primary event loop. The important stuff goes on here.
while running:
# Get our event. Prosessing one at a time because of the nature of our game,
# we don't need to consider the possibility of simultanious input.
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
if accept_input :
# Go through and figure out what to do with the input
if event.type == KEYDOWN :
if event.key == 13 :
accept_input = False
elif event.type == MOUSEBUTTONDOWN :
x,y = event.pos
gx,gy = px_to_coord(grid,x,y)
grid.toggle(gx,gy)
renderGrid(screen, grid)
pygame.display.update()
else :
oldRects = updateRects
grid, updateRects = conways_life(grid)
renderGrid(screen, grid)
if generation == 0 :
# On first gen, update the whole damn thing
pygame.display.update()
# And finally update everything added to updateRects that needs to be
# drawn to the screen
updateRects.extend(oldRects)
pygame.display.update()#updateRects)
generation += 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment