Skip to content

Commit

Permalink
Fixed Lifeform rules which were causing overpopulation
Browse files Browse the repository at this point in the history
  • Loading branch information
Darius Berghe committed Dec 8, 2016
1 parent b8b0a51 commit a7a5fca
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 49 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
__pycache__
.idea
.gitignore
89 changes: 46 additions & 43 deletions universe.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
from enum import Enum

class LifeformState(Enum):
dead = 0,
alive = 1,
dying = 2,
resurrecting = 3

class Lifeform():
def __init__(self, state=False):
'''
Create a lifeform
:param state: True stands for alive, False stands for dead.
'''
self._age = 0
self._state = state
self._state = LifeformState.alive if state else LifeformState.dead
self._neighbors = []

def alive(self):
'''
Is this cell alive?
'''
return self._state
return True if self._state in [LifeformState.alive, LifeformState.dying] else False

def specifyNeighbor(self, neighbor):
def specifyNeighbors(self, neighbors):
'''
Tell the lifeform whom its neighbor is.
:param neighbor: another lifeform
'''
self._neighbors.append(neighbor)
self._neighbors = neighbors

def aliveNeighbors(self):
'''
Expand All @@ -33,18 +41,21 @@ def play(self):
This is where the Game of Life rules get implemented
'''
nc = self.aliveNeighbors()

if (nc < 2 or nc > 3) and self.alive():
self.kill()
elif nc == 3 and not self.alive():
self.resurrect()
return 0
self._state = LifeformState.dying
if nc == 3 and not self.alive():
self._state = LifeformState.resurrecting

def kill(self):
self._state = False
if self.alive():
self._age += 1

def resurrect(self):
self._state = True
def updateState(self):
if self._state == LifeformState.dying:
self._state = LifeformState.dead

if self._state == LifeformState.resurrecting:
self._state = LifeformState.alive


class Universe():
Expand All @@ -59,49 +70,41 @@ def __init__(self, state):
# create all the Lifeforms and store them into the Universe's state
self._state = [[Lifeform(i) for i in row] for row in state] # 2D list of Lifeforms

# repass over the Universe's state to specify neighbors (there must be a better way!)
def updateNeighbors(self):
# repass over the Universe's state to specify neighbors
for rowi, row in enumerate(self._state):
for lifei, life in enumerate(row):
neighbors = []
for j in range(rowi - 1, rowi + 2):
for i in range(lifei - 1, lifei + 2):
if (i, j) != (lifei, rowi) \
and i >= 0 \
and j >= 0 \
and i < len(row) \
and j < len(self._state):
#print('attempt to access _state[{}][{}]'.format(j,i))
life.specifyNeighbor(self._state[j][i])
'''
try:
print('attempt to access _state[{}][{}]'.format(rowi - 1, lifei - 1))
life.specifyNeighbor(self._state[rowi - 1][lifei - 1])
print('attempt to access _state[{}][{}]'.format(rowi - 1, lifei))
life.specifyNeighbor(self._state[rowi - 1][lifei ])
print('attempt to access _state[{}][{}]'.format(rowi - 1, lifei + 1))
life.specifyNeighbor(self._state[rowi - 1][lifei + 1])
print('attempt to access _state[{}][{}]'.format(rowi, lifei -1))
life.specifyNeighbor(self._state[rowi ][lifei - 1])
print('attempt to access _state[{}][{}]'.format(rowi, lifei + 1))
life.specifyNeighbor(self._state[rowi ][lifei + 1])
print('attempt to access _state[{}][{}]'.format(rowi + 1, lifei - 1))
life.specifyNeighbor(self._state[rowi + 1][lifei - 1])
print('attempt to access _state[{}][{}]'.format(rowi + 1, lifei))
life.specifyNeighbor(self._state[rowi + 1][lifei ])
print('attempt to access _state[{}][{}]'.format(rowi + 1, lifei + 1))
life.specifyNeighbor(self._state[rowi + 1][lifei + 1])
except Exception as e:
pass
'''
if (i, j) != (lifei, rowi):
if i == len(row):
i = 0
if j == len(self._state):
j = 0
# print('attempt to access _state[{}][{}]'.format(j,i))
neighbors.append(self._state[j][i])
life.specifyNeighbors(neighbors)

def evolve(self):
'''
At each time tick, the universe evolves and updates its lifeforms.
'''
self._age += 1
[[life.play() for life in row] for row in self._state]

self.updateNeighbors()

for row in self._state:
for life in row:
life.play()

for row in self._state:
for life in row:
life.updateState()

def state(self):
'''
Get a 2D boolean representation of the Universe's state
:return: 2D list of booleans
'''
return [[life.alive() for life in row] for row in self._state]
return [[life.alive() for life in row] for row in self._state]
28 changes: 22 additions & 6 deletions universeview.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from universe import Universe

class constants():
CellToScreenRatio = 0.002
AtomicTick = 1.0
CellToScreenRatio = 0.001
AtomicTick = 0.2
background = QColor(60, 60, 60)
grid = QColor(20, 20, 20)
cell = QColor(84, 158, 39)
Expand Down Expand Up @@ -46,6 +46,13 @@ def start(self, wscene, hscene):

# create a random initial state for the universe
initial = [[(randint(0, 10) == 9) for i in range(self.cols)] for j in range(self.rows)]
'''initial = [[False for i in range(self.cols)] for j in range(self.rows)]
initial[0][0] = True
initial[0][1] = True
initial[1][2] = True
initial[2][2] = True
initial[3][2] = True
'''

# create the universe
self.universe = Universe(initial)
Expand Down Expand Up @@ -76,9 +83,7 @@ def draw(self, state):
self.drawCell(celli, rowi)

def rePaint(self):
# evolve
self.universe.evolve()
print("Universe age {}".format(self.universe._age))
print("Drawing Universe of age {}".format(self.universe._age))

# delete everything on the canvas
self.scene.clear()
Expand All @@ -96,4 +101,15 @@ def rePaint(self):

# draw the universe
state = self.universe.state()
self.draw(state)
self.draw(state)

# evolve
self.universe.evolve()

def keyPressEvent(self, QKeyEvent):
# delete selected items when pressing the keyboard's delete key
if QKeyEvent.key() == Qt.Key_Space:
if self.timer.isActive():
self.stop()
else:
self.timer.start(constants.AtomicTick * 1000)

0 comments on commit a7a5fca

Please sign in to comment.