# Object-oriented Game of Life in Python

09 Aug 2018### Intro

I have been planning to build a superior GUI alternative to *NetLogo* for a long time. When I finally started working on a project, I decided to test the basic implementations in Python. Sure enough, the first app was *Conway’s Game of Life* - a great special case of *cellular automata*.

Can you imagine my surprise that I haven’t found an object-oriented implementation of the game in Python — all codes were either written in Java or in *imperative* Python.

So, I decided to build the model. I used two classes — *Person*, which corresponded to each cell, and *Game*, which controlled the system dynamics. A great article by *Giorgio Sironi* also adviced to create a third class *Generation*, but I didn’t find it necessary.

### Model

So, first, I imported three libraries that I used:

```
from math import ceil, floor, sqrt
import random
from matplotlib import pyplot as plt
```

Then I defined a *Person* class with *(x,y)*-coordinates and empty vector of *alive-dead* statuses for every time period. Every *Person* object contains *neighbours* method which returns adjacent cells and *kill-resurrect* methods to change the life status:

```
class Person:
people = []
def __init__(self,x,y,alive):
self.x = x
self.y = y
self.alive = alive
Person.people.append(self)
return
def kill(self,t):
self.alive[t] = False
return
def resurrect(self,t):
self.alive[t] = True
return
def neighbours(self):
a = []
people = Person.people
a += [z for z in people if z.x == self.x and z.y == self.y+1]
a += [z for z in people if z.x == self.x and z.y == self.y-1]
a += [z for z in people if z.x == self.x-1 and z.y == self.y]
a += [z for z in people if z.x == self.x-1 and z.y == self.y+1]
a += [z for z in people if z.x == self.x-1 and z.y == self.y-1]
a += [z for z in people if z.x == self.x+1 and z.y == self.y-1]
a += [z for z in people if z.x == self.x+1 and z.y == self.y+1]
a += [z for z in people if z.x == self.x+1 and z.y == self.y]
return a
def alive_neighbours(self,t):
a = [z for z in self.neighbours() if z.alive[t]]
return a
```

Then I defined a Game class with *setup* method which randomly draws initial stage, and *stage* method which executes system dynamics:

```
class Game:
def __init__(self, n, m, t):
self.n = n
self.m = m
self.t = t
return
def setup(self):
for i in range(self.n):
for j in range(self.m):
a = [False]*self.t
a[0] = random.choice([True, False])
Person(i,j,a)
return
def stage(self, t):
for person in Person.people:
if person.alive[t-1]:
if len(person.alive_neighbours(t-1))<2:
person.kill(t)
if len(person.alive_neighbours(t-1)) in [2,3]:
person.resurrect(t)
if len(person.alive_neighbours(t-1))>3:
person.kill(t)
else:
if len(person.alive_neighbours(t-1))==3:
person.resurrect(t)
return
def play(self):
self.setup()
for i in range(1,self.t):
self.stage(i)
return
def results(self):
people = Person.people
a = [[z.x, z.y, z.alive] for z in people]
print(a)
return a
```

So, this was it. Now, you just have to input number of rows and columns *(x,y)* and number of time periods *t* and play the game. The resulting plots will be exported to your working directory:

```
# game:
a = Game(x,y,t)
a.play()
a.results()
# plot:
for j in range(t):
b = []
for i in range(x):
b.append([z[2][j] for z in a.results() if z[0]==i])
plt.spy(b)
plt.savefig(f"time{j}.png")
```

For presentation purposes I animated the resulting graphs:

### Conclusion

Here we go, I have built and shared the very basic object-oriented implementation of the very basic game in the most popular language, and somehow I ended up being the first one to do it. So, I will just leave it here as a starting point for future learners.

Be sure to check my other posts in *ravshansk.com/blog* and to *subscribe to my Twitter @ravshansk*.