Advertisement
enfiskutensykkel

Conway - Game of Life

May 11th, 2014
461
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.83 KB | None | 0 0
  1. #!/usr/bin/env python
  2. #coding=utf8
  3.  
  4. """An implementation of John Conway's "Game of Life".
  5.  
  6. The universe of the Game of Life is a two-dimensional grid of cells, each
  7. of which is in one of two states: dead or alive. The state of a cell at
  8. a discrete time step (tick) is determined through interaction with adjacent
  9. cells (neighbours).
  10.  
  11. At each tick, the following transitions occur:
  12.     1) If a cell has fewer than two alive neighbours, it dies.
  13.     2) If a cell has two or three alive neighbours, it lives on into the next generation.
  14.     3) If a cell has more than three neighbours, it dies.
  15.     4) If a dead cell has exactly three neighbours, it becomes alive.
  16.  
  17. See Wikipedia for more information:
  18.  
  19.     http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
  20.  
  21. """
  22.  
  23. #__name__ = "pygol"
  24. __version__ = '0.0.1'
  25. __date__ = '2014-05-11'
  26.  
  27.  
  28.  
  29.  
  30. # Not really necessary, but I wanted to try out creating my own decorators.
  31. def _overrides(cls):
  32.     def overrider(method):
  33.         assert(method.__name__ in dir(cls))
  34.         return method
  35.  
  36.     return overrider
  37.  
  38.  
  39.  
  40. class grid(object):
  41.  
  42.     @_overrides(object)
  43.     def __init__(self, width, height):
  44.         self._dim = (width, height)
  45.         self._grid = [ [ False for y in xrange(0, height) ] for x in xrange(0, width) ]
  46.  
  47.  
  48.     @property
  49.     def width(self):
  50.         return self._dim[0]
  51.  
  52.  
  53.     @property
  54.     def height(self):
  55.         return self._dim[1]
  56.  
  57.  
  58.     def __setitem__(self, cell, alive):
  59.         try:
  60.             x, y = int(cell[0]), int(cell[1])
  61.  
  62.         except (TypeError, AttributeError):
  63.             raise TypeError("Invalid coordinate")
  64.  
  65.         try:
  66.             self._grid[x][y] = bool(alive)
  67.  
  68.         except IndexError:
  69.             raise TypeError("Out of bounds")
  70.  
  71.         except (TypeError, ValueError):
  72.             raise TypeError("Value must be boolean")
  73.  
  74.  
  75.     def __getitem__(self, cell):
  76.         try:
  77.             x, y = int(cell[0]), int(cell[1])
  78.         except (TypeError, AttributeError):
  79.             raise TypeError("Invalid coordinate")
  80.  
  81.         try:
  82.             return self._grid[x][y]
  83.         except IndexError:
  84.             raise TypeError("Out of bounds")
  85.  
  86.  
  87.     @_overrides(object)
  88.     def __str__(self):
  89.         return "\n".join( [ "".join( [ "*" if self[(x, y)] else " " for y in xrange(0, self.height) ] ) for x in xrange(0, self.width) ] )
  90.  
  91.  
  92.     def tick(self):
  93.         width, height = self.width, self.height
  94.  
  95.         # Count living neighbours
  96.         def count_living(x, y):
  97.             x_min, y_min = max(0, x-1), max(0, y-1)
  98.             x_max, y_max = min(width-1, x+1), min(height-1, y+1)
  99.  
  100.             alive = 0
  101.             for i in xrange(x_min, x_max+1):
  102.                 for j in xrange(y_min, y_max+1):
  103.                     if not (i == x and j == y):
  104.                         alive += self._grid[i][j]
  105.  
  106.             return alive
  107.  
  108.         # Determine the cells' state for the next generation
  109.         new_grid = [ [ False for y in xrange(0, height) ] for x in xrange(0, width) ]
  110.  
  111.         # 1. any living cell with fewer than two live neighbours dies
  112.         # 2. any living cell with two or three live neighbours lives on to the next generation
  113.         # 3. any living cell with more than three live neighbours dies
  114.         # 4. any dead cell with exactly three live neighbours becomes alive
  115.         for x in xrange(0, width):
  116.             for y in xrange(0, height):
  117.                 alive = self._grid[x][y]
  118.                 count = count_living(x,y)
  119.  
  120.                 if alive and count < 2:
  121.                     new_grid[x][y] = False
  122.                 elif alive and (count == 2 or count == 3):
  123.                     new_grid[x][y] = True
  124.                 elif alive and count > 3:
  125.                     new_grid[x][y] = False
  126.                 elif not alive and count == 3:
  127.                     new_grid[x][y] = True
  128.  
  129.         # Transition into next generation
  130.         changes = 0
  131.         for x in xrange(0, width):
  132.             for y in xrange(0, height):
  133.                 changes += self._grid[x][y] != new_grid[x][y]
  134.  
  135.         self._grid = new_grid
  136.         return changes
  137.  
  138.  
  139.  
  140. def seed(grid, seed):
  141.     import random
  142.  
  143.     random.seed(seed)
  144.     for x in xrange(0, grid.width):
  145.         for y in xrange(0, grid.height):
  146.             grid[(x, y)] = random.randint(0, 1)
  147.  
  148.  
  149. if __name__ == '__main__':
  150.     g = grid(32, 32)
  151.     seed(g, 16)
  152.  
  153.     changes = 1
  154.     while changes > 0:
  155.         raw_input()
  156.         print g
  157.         changes = g.tick()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement