Skip to content

Instantly share code, notes, and snippets.

@lonnen
Created December 13, 2010 03:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lonnen/738622 to your computer and use it in GitHub Desktop.
Save lonnen/738622 to your computer and use it in GitHub Desktop.
Processing.py demo of 1D Cellular Automata
'''ca.py
Wolfram Cellular Automata by Chris Lonnen
Demonstration of Processing.py features (in both the traditional and Microsoft
sense) in the form of a Wolfram 1-dimensional cellular automata.
Compare to Shiffman's pure Processing implementation:
http://processing.org/learning/topics/wolfram.html
'''
# like a Python script, this executes first
# Python print statements are used instead of Processing println
print __doc__
# init global state
ca = None
def setup():
size(640, 360, P2D)
frameRate(30)
background(0)
ruleset = [0,1,0,1,1,0,1,0]
# Processing relies on muddying the global namespace between
# setup() and draw(), so the global keyword is needed
global ca
ca = CA(ruleset)
def draw():
global ca
ca.render()
ca.generate()
if ca.finished():
background(0)
ca.randomize()
ca.restart()
def mousePressed():
# It handles mouse events!
background(0)
ca.randomize()
ca.restart()
class CA(object):
'''A Cellular Automata Python class with Processing keywords and methods.
This is a Python class, so the self keyword appears a lot here.
Like the parent.method() annoyances of Processing-Java alchemy, this
is an implementation quirk you'll need to be aware of if you write
your own classes.'''
def __init__(self, ruleset=None, scale=1):
if ruleset:
self.set_rules(ruleset)
else:
self.randomize()
self.scale = scale
self.cells = [0] * (width / self.scale)
self.restart()
def set_rules(self, ruleset):
'''Set the rules of the CA, and print them to screen'''
# Python builtins!
rules = [(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0),
(1, 0, 1), (1, 1, 0), (1, 1, 1)]
self.rules = dict(zip(rules,ruleset))
print self.rules
def randomize(self):
'''Make a random ruleset'''
# mixing processing functions and list comprehensions
r = [int(random(2)) for x in range(8)]
self.set_rules(r)
def restart(self):
'''Reset to generation 0'''
# map() and lambda! oh my!
self.cells = map(lambda k: 0, self.cells)
self.generation = 0
self.cells[len(self.cells)/2] = 1
def generate(self):
'''The process of creating the new generation'''
# directish reimplementation!
# be aware of the difference between range and a java-like for loop!
# also, that this is recreating i = 1; i < cells.length-1
nextgen = [0] * len(self.cells)
for i in range(len(self.cells)-2):
left = self.cells[i]
me = self.cells[i+1]
right = self.cells[i+2]
nextgen[i] = self.rules[(left,me,right)]
self.cells = list(nextgen) # copy
self.generation += 1
def render(self):
'''Render the one line CA'''
# list comprehensions with Python builtins!
[self.render_cell(x) for x in zip(range(len(self.cells)), self.cells)]
def render_cell(self, packedCell):
'''Paint a tuple(position, cell value)'''
# contrived tuple unpacking example!
xpos, value = packedCell
if value:
fill(255)
else:
fill(0)
noStroke()
rect(xpos*self.scale, self.generation*self.scale, self.scale, self.scale)
def finished(self):
'''The CA is done if it reaches the bottom of the screen'''
return (self.generation > (height / self.scale))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment