comparison Life.py @ 47:2b0e229e163c

Chapter 7, exercise 2. R-Pentomino game of life.
author Brian Neal <bgneal@gmail.com>
date Thu, 25 Jul 2013 21:53:44 -0500
parents
children 98eb01502cf5
comparison
equal deleted inserted replaced
46:d83a72eec954 47:2b0e229e163c
1 """ Code example from Complexity and Computation, a book about
2 exploring complexity science with Python. Available free from
3
4 http://greenteapress.com/complexity
5
6 Copyright 2011 Allen B. Downey.
7 Distributed under the GNU General Public License at gnu.org/licenses/gpl.html.
8
9 Modified by Brian Neal to add a variable delay to the animation and to provide
10 the cval parameter to convolve.
11
12 """
13
14 import numpy
15 import scipy.ndimage
16
17 import matplotlib
18 matplotlib.use('TkAgg')
19 import matplotlib.pyplot as pyplot
20
21
22 class Life(object):
23 """Implements Conway's Game of Life.
24
25 n: the number of rows and columns
26 """
27
28 def __init__(self, n, mode='wrap', cval=0.0, random=False):
29 """Attributes:
30 n: number of rows and columns
31 mode: how border conditions are handled
32 array: the numpy array that contains the data.
33 weights: the kernel used for convolution
34 """
35 self.n = n
36 self.mode = mode
37 self.cval = cval
38 if random:
39 self.array = numpy.random.random_integers(0, 1, (n, n))
40 else:
41 self.array = numpy.zeros((n, n), numpy.int8)
42
43 self.weights = numpy.array([[1,1,1],
44 [1,10,1],
45 [1,1,1]])
46
47 def add_glider(self, x=0, y=0):
48 coords = [(0,1), (1,2), (2,0), (2,1), (2,2)]
49 for i, j in coords:
50 self.array[x+i, y+j] = 1
51
52 def loop(self, steps=1):
53 """Executes the given number of time steps."""
54 [self.step() for i in xrange(steps)]
55
56 def step(self):
57 """Executes one time step."""
58 con = scipy.ndimage.filters.convolve(self.array,
59 self.weights,
60 mode=self.mode,
61 cval=self.cval)
62
63 boolean = (con==3) | (con==12) | (con==13)
64 self.array = numpy.int8(boolean)
65
66
67 class LifeViewer(object):
68 """Generates an animated view of the grid."""
69 def __init__(self, life, cmap=matplotlib.cm.gray_r, delay=1000):
70 self.life = life
71 self.cmap = cmap
72 self.delay = delay
73
74 self.fig = pyplot.figure()
75 pyplot.axis([0, life.n, 0, life.n])
76 pyplot.xticks([])
77 pyplot.yticks([])
78
79 self.pcolor = None
80 self.update()
81
82 def update(self):
83 """Updates the display with the state of the grid."""
84 if self.pcolor:
85 self.pcolor.remove()
86
87 a = self.life.array
88 self.pcolor = pyplot.pcolor(a, cmap=self.cmap)
89 self.fig.canvas.draw()
90
91 def animate(self, steps=10):
92 """Creates the GUI and then invokes animate_callback.
93
94 Generates an animation with the given number of steps.
95 """
96 self.steps = steps
97 self.fig.canvas.manager.window.after(self.delay, self.animate_callback)
98 pyplot.show()
99
100 def animate_callback(self):
101 """Runs the animation."""
102 for i in range(self.steps):
103 self.life.step()
104 self.update()
105
106
107 def main(script, n=20, *args):
108
109 n = int(n)
110
111 life = Life(n, random=False)
112 life.add_glider()
113 viewer = LifeViewer(life)
114 viewer.animate(steps=100)
115
116
117 if __name__ == '__main__':
118 import sys
119
120 profile = False
121 if profile:
122 import cProfile
123 cProfile.run('main(*sys.argv)')
124 else:
125 main(*sys.argv)