Mercurial > public > think_complexity
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) |