-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathconways_game_of_life.py
138 lines (114 loc) · 4 KB
/
conways_game_of_life.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
from time import sleep_ms
from framebuf import FrameBuffer1
from urandom import getrandbits
class ConwaysGameOfLife:
def __init__(self, lcd):
# High score
self.best = 0
# PCD8544 (Nokia 5110) LCD
self.lcd = lcd
self.width = 84
self.height = 48
self.buffer = bytearray((self.height // 8) * self.width)
self.framebuf = FrameBuffer1(self.buffer, self.width, self.height)
def draw(self):
self.lcd.data(self.buffer)
def intro(self):
self.framebuf.fill(0)
self.framebuf.text("Conway's", 10, 8, 1)
self.framebuf.text("Game", 26, 16, 1)
self.framebuf.text("of", 34, 24, 1)
self.framebuf.text("Life", 26, 32, 1)
self.draw()
def end(self, score, best, size):
# The 8x8 font is too wide to fit "Generations", so I called it "Score"
self.framebuf.fill(0)
self.framebuf.text("Score", 0, 0, 1)
self.framebuf.text(str(score), 0, 8, 1)
self.framebuf.text("Best score", 0, 16, 1)
self.framebuf.text(str(best), 0, 24, 1)
self.framebuf.text("Pixel size", 0, 32, 1)
self.framebuf.text(str(size), 0, 40, 1)
self.draw()
def begin(self, size=4, delay=20):
# Size of lifeforms in pixels
self.size = size
# Delay in ms between generations
self.delay = delay
# Localised to avoid self lookups
# Possible performance optimisation, TBC
draw = self.draw
delay = self.delay
tick = self.tick
# Randomise initial pixels
self.randomise()
# Begin
generations = 0
try:
while tick():
generations = generations + 1
draw()
sleep_ms(delay)
except KeyboardInterrupt:
pass
# New high score?
if generations > self.best:
self.best = generations
# End
self.end(generations, self.best, self.size)
def randomise(self):
size = self.size
width = self.width
height = self.height
cell = self.cell
self.framebuf.fill(0)
for x in range(0, width, size):
for y in range(0, height, size):
# random bit: 0 = pixel off, 1 = pixel on
cell(x, y, getrandbits(1))
self.draw()
def cell(self, x, y, colour):
size = self.size
buf = self.framebuf
for i in range(size):
for j in range(size):
buf.pixel(x + i, y + j, colour)
def get(self, x, y):
if not 0 <= x < self.width or not 0 <= y < self.height:
return 0
return self.framebuf.pixel(x, y) & 1
def tick(self):
size = self.size
width = self.width
height = self.height
get = self.get
cell = self.cell
# If no pixels are born or die, the game ends
something_happened = False
for x in range(0, width, size):
for y in range(0, height, size):
# Is the current cell alive
alive = get(x, y)
# Count number of neighbours
neighbours = (
get(x - size, y - size) +
get(x, y - size) +
get(x + size, y - size) +
get(x - size, y) +
get(x + size, y) +
get(x + size, y + size) +
get(x, y + size) +
get(x - size, y + size)
)
# Apply the game rules
if alive and not 2 <= neighbours <= 3:
# This pixel dies
cell(x, y, 0)
if not something_happened:
something_happened = True
elif not alive and neighbours == 3:
# A new pixel is born
cell(x, y, 1)
if not something_happened:
something_happened = True
return something_happened