As the last example, we will simulate life with Conway's Game of Life. The original game of life is based on a few basic rules. We start out with a random configuration on a two-dimensional square grid. Each cell in the grid can be either dead or alive. This state depends on the eight neighbors of the cell. Convolution can be used to evaluate the basic rules of the game. We will need the SciPy package for the convolution bit.
Install SciPy with either of the following two commands:
sudo pip install scipy
easy_install scipy
The following code is an implementation of Game of Life with some modifications:
The most important data structure in the code is a two-dimensional array holding the color values of the pixels on the game screen. This array is initialized with random values and then recalculated in the game loop. More information about the involved functions can be found in the next section. As previously mentioned, the following is the code:
import os, pygame from pygame.locals import * import numpy from scipy import ndimage def get_pixar(arr, weights): states = ndimage.convolve(arr, weights, mode='wrap') bools = (states == 13) | (states == 12 ) | (states == 3) return bools.astype(int) def draw_cross(pixar): (posx, posy) = pygame.mouse.get_pos() pixar[posx, :] = 1 pixar[:, posy] = 1 def random_init(n): return numpy.random.random_integers(0, 1, (n, n)) def draw_pattern(pixar, pattern): print pattern if pattern == 'glider': coords = [(0,1), (1,2), (2,0), (2,1), (2,2)] elif pattern == 'block': coords = [(3,3), (3,2), (2,3), (2,2)] elif pattern == 'exploder': coords = [(0,1), (1,2), (2,0), (2,1), (2,2), (3,3)] elif pattern == 'fpentomino': coords = [(2,3),(3,2),(4,2),(3,3),(3,4)] pos = pygame.mouse.get_pos() xs = numpy.arange(0, pos[0], 10) ys = numpy.arange(0, pos[1], 10) for x in xs: for y in ys: for i, j in coords: pixar[x + i, y + j] = 1 def main(): pygame.init () N = 400 pygame.display.set_mode((N, N)) pygame.display.set_caption("Life Demo") screen = pygame.display.get_surface() pixar = random_init(N) weights = numpy.array([[1,1,1], [1,10,1], [1,1,1]]) cross_on = False while True: pixar = get_pixar(pixar, weights) if cross_on: draw_cross(pixar) pygame.surfarray.blit_array(screen, pixar * 255 ** 3) pygame.display.flip() for event in pygame.event.get(): if event.type == QUIT: return if event.type == MOUSEBUTTONDOWN: cross_on = not cross_on if event.type == KEYDOWN: if event.key == ord('r'): pixar = random_init(N) print "Random init" if event.key == ord('g'): draw_pattern(pixar, 'glider') if event.key == ord('b'): draw_pattern(pixar, 'block') if event.key == ord('e'): draw_pattern(pixar, 'exploder') if event.key == ord('f'): draw_pattern(pixar, 'fpentomino') if __name__ == '__main__': main()
You should be able to view a screencast on YouTube at https://www.youtube.com/watch?v=NNsU-yWTkXM.
A screenshot of the game in action is shown as follows:
We used some NumPy and SciPy functions that need explaining:
Function |
Description |
---|---|
|
This applies the convolve operation on the given array, using weights in wrap mode. The mode has to do with the array borders. See http://en.wikipedia.org/wiki/Convolution for the mathematical details. |
|
This converts the array of Booleans to integers. |
|
This creates an array from |