Skip to content

Instantly share code, notes, and snippets.

@anabarasan
Created August 14, 2018 19:10
Show Gist options
  • Save anabarasan/d222d67dfc4737b598c8b44c5decbb05 to your computer and use it in GitHub Desktop.
Save anabarasan/d222d67dfc4737b598c8b44c5decbb05 to your computer and use it in GitHub Desktop.
Conway's Game of Life
#!/usr/bin/env python3
from argparse import ArgumentParser
from enum import Enum
from sys import argv
from time import sleep
BLOCK = [(5,5), (5,6), (6,5), (6,6)]
BLINKER = [(4,4), (4,5), (4,6)]
BEACON = [(4,4), (4,5), (5,4), (5,5), (6,6), (6,7), (7,6), (7,7)]
GLIDER = [(1,2), (2,3), (3,1), (3,2), (3,3)]
CUSTOM = []
def clear_screen():
print(chr(27)+'[2j')
print('\033c')
print('\x1bc')
class Patterns(Enum):
block = "BLOCK"
blinker = "BLINKER"
beacon = "BEACON"
glider = "GLIDER"
custom = "CUSTOM"
def __str__(self):
return self.value
class Extinction(Exception):
pass
class Cell:
"""Co-ordinates start from 1,1 not 0,0"""
def __init__(self, x, y):
self.x = x
self.y = y
self.alive = False
def __repr__(self):
return "(%d,%d)" % (self.x, self.y)
def __eq__(self, cell):
return self.x == cell.x and self.y == cell.y
def neighbours(self):
n = (self.x-1, self.y)
s = (self.x+1, self.y)
e = (self.x, self.y+1)
w = (self.x, self.y-1)
nw = (self.x-1, self.y-1)
ne = (self.x-1, self.y+1)
sw = (self.x+1, self.y-1)
se = (self.x+1, self.y+1)
return [nw, n, ne, w, e, sw, s, se]
class GameOfLife:
def __init__(self, size=10, start_sequence=None):
self.size = size
self.start_sequence = start_sequence if start_sequence is not None else []
self.create_grid()
self._generation = 0
self._display()
def create_grid(self):
grid = []
for row in range(1, self.size+1):
for col in range(1, self.size+1):
cell = Cell(row, col)
if (row, col) in self.start_sequence:
cell.alive = True
grid.append(cell)
self.grid = grid
def _display(self):
clear_screen()
print("Generation : %d" % (self._generation,))
for idx, cell in enumerate(self.grid):
if (idx % self.size) == 0:
print("")
print(1 if cell.alive else ' ', end=' ')
print("")
def _get_cell(self, target):
for cell in self.grid:
if cell == target:
return cell
def _is_cell_alive_in_grid(self, cell):
neighbours = cell.neighbours()
status = []
for row, col in neighbours:
if (0 < row < self.size+1) and (0 < col < self.size+1):
neighbour = self._get_cell(Cell(row, col))
status.append(neighbour.alive)
else:
status.append(False)
alive_neighbours = status.count(True)
if cell.alive: # a live cell
if alive_neighbours < 2 or alive_neighbours > 3:
alive = False # isolation / over population
else:
alive = True # lives on
else: # dead cell
if alive_neighbours == 3: # reproduction
alive = True
else: # baren
alive = False
cell = Cell(cell.x, cell.y)
cell.alive = alive
# if cell == Cell(3,5) or cell == Cell(4,5) or cell == Cell(5,5):
# print("*"*80, "%s:%s => %s ==> %s" % (cell, cell.alive, status, msg), "*"*80, sep="\n")
return cell
def next_generation(self):
grid = []
for row in range(1, self.size+1):
for col in range(1, self.size+1):
cell = self._get_cell(Cell(row, col))
cell = self._is_cell_alive_in_grid(cell)
grid.append(cell)
if grid == self.grid and not any([cell.alive for cell in self.grid]):
raise Extinction
self.grid = grid
self._generation += 1
self._display()
def parse_args(args):
parser = ArgumentParser()
parser.add_argument('-g', '--generations', type=int,
help="Number of generations to display",
default=10)
parser.add_argument('-s', '--size', type=int, help="Grid size", default=20)
parser.add_argument('-p', '--pattern', type=Patterns,
help="Starting pattern", choices=list(Patterns))
args = parser.parse_args(args)
return args.generations, args.size, args.pattern
def get_user_pattern():
while ip:
ip = input("Enter Coordinate x,y. Leave empty to finish")
ip = ip.strip()
coords = ip.split(",")
coords = tuple([int(i) for i in coords])
CUSTOM.append(coords)
def main(args):
generations, size, pattern = parse_args(args)
pattern = globals()[str(pattern)]
if not pattern:
pattern = get_user_pattern()
game = GameOfLife(size=size, start_sequence=pattern)
sleep(2)
for i in range(generations):
try:
game.next_generation()
except Extinction:
clear_screen()
print("Extinction!")
input() # wait for user to press a key
break
sleep(2)
sleep(10)
clear_screen()
if __name__ == '__main__':
main(argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment