Skip to content

Commit 7d00ff5

Browse files
committed
added game of life example
1 parent ab5307d commit 7d00ff5

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed

examples/life.py

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#!/usr/bin/env python
2+
3+
import random
4+
import time
5+
6+
import tdl
7+
8+
WIDTH = 80
9+
HEIGHT = 40
10+
11+
class LifeBoard():
12+
13+
def __init__(self, width, height):
14+
self.width = width
15+
self.height = height
16+
self.live_cells = set()
17+
self.wrap = True
18+
19+
def set(self, x, y, value):
20+
if value:
21+
self.live_cells.add((x, y))
22+
else:
23+
self.live_cells.discard((x, y))
24+
25+
def set_batch(self, x, y, batch):
26+
for y_, line in enumerate(batch):
27+
for x_, char in enumerate(line):
28+
self.set(x + x_, y + y_, char != ' ')
29+
30+
def get(self, x, y):
31+
if(self.wrap is False
32+
and not (0 <= x < self.width and 0 <= y < self.height)):
33+
return False
34+
return (x % self.width, y % self.height) in self.live_cells
35+
36+
def clear(self):
37+
self.live_cells.clear()
38+
39+
def toggle(self, x, y):
40+
self.live_cells.symmetric_difference_update([(x, y)])
41+
42+
43+
def get_neighbours(self, x, y):
44+
count = 0
45+
for neighbour_x in [-1, 0, 1]:
46+
for neighbour_y in [-1, 0, 1]:
47+
if 0 == neighbour_x == neighbour_y:
48+
continue
49+
count += self.get(x + neighbour_x, y + neighbour_y)
50+
return count
51+
52+
def rule(self, is_alive, neighbours):
53+
"""
54+
1. Any live cell with fewer than two live neighbours dies, as if caused
55+
by under-population.
56+
2. Any live cell with two or three live neighbours lives on to the next
57+
generation.
58+
3. Any live cell with more than three live neighbours dies, as if by
59+
overcrowding.
60+
4. Any dead cell with exactly three live neighbours becomes a live
61+
cell, as if by reproduction.
62+
"""
63+
if is_alive:
64+
return 2 <= neighbours <= 3
65+
else:
66+
return neighbours == 3
67+
68+
def step(self):
69+
70+
next_generation = set()
71+
for x in range(self.width):
72+
for y in range(self.height):
73+
if self.rule(self.get(x, y), self.get_neighbours(x, y)):
74+
next_generation.add((x, y))
75+
self.live_cells = next_generation
76+
77+
def main():
78+
console = tdl.init(WIDTH, HEIGHT)
79+
board = LifeBoard(WIDTH, HEIGHT - 1)
80+
# The R-pentomino
81+
#board.set_batch(WIDTH // 2 - 2,HEIGHT // 2 - 2,
82+
# [' **',
83+
# '** ',
84+
# ' * '])
85+
86+
# Diehard
87+
#board.set_batch(WIDTH // 2 - 5,HEIGHT // 2 - 2,
88+
# [' * ',
89+
# '** ',
90+
# ' * ***'])
91+
92+
# Gosper glider gun
93+
board.set_batch(1, 1,
94+
[' ',
95+
' * ',
96+
' * * ',
97+
' ** ** **',
98+
' * * ** **',
99+
'** * * ** ',
100+
'** * * ** * * ',
101+
' * * * ',
102+
' * * ',
103+
' ** '])
104+
105+
play = False
106+
redraw = True
107+
mouse_drawing = None
108+
mouse_x = -1
109+
mouse_y = -1
110+
while True:
111+
for event in tdl.event.get():
112+
if event.type == 'QUIT':
113+
return
114+
elif event.type == 'KEYDOWN':
115+
if event.key == 'SPACE':
116+
play = not play
117+
redraw = True
118+
elif event.char.upper() == 'S':
119+
board.step()
120+
redraw = True
121+
elif event.char.upper() == 'C':
122+
board.clear()
123+
redraw = True
124+
elif event.char.upper() == 'W':
125+
board.wrap = not board.wrap
126+
redraw = True
127+
elif event.type == 'MOUSEDOWN':
128+
x, y, = event.cell
129+
board.toggle(x, y)
130+
mouse_drawing = event.cell
131+
redraw = True
132+
elif event.type == 'MOUSEUP':
133+
mouse_drawing = None
134+
elif event.type == 'MOUSEMOTION':
135+
if(mouse_drawing and mouse_drawing != event.cell):
136+
x, y = mouse_drawing = event.cell
137+
board.toggle(x, y)
138+
mouse_x, mouse_y = event.cell
139+
redraw = True
140+
if play and mouse_drawing is None:
141+
board.step()
142+
redraw = True
143+
if redraw:
144+
redraw = False
145+
console.clear()
146+
for x, y in board.live_cells:
147+
console.draw_char(x, y, '*')
148+
console.draw_rect(0, -1, None, None, None, bg=(64, 64, 80))
149+
console.draw_str(0, -1, "Mouse:Toggle Cells, Space:%5s, [S]tep, [C]lear, [W]rap Turn %s" % (['Play', 'Pause'][play], ['On', 'Off'][board.wrap]), None, None)
150+
if (mouse_x, mouse_y) in console:
151+
console.draw_char(mouse_x, mouse_y,
152+
None, (0, 0, 0), (255, 255, 255))
153+
else:
154+
time.sleep(0.01)
155+
tdl.flush()
156+
157+
158+
if __name__ == '__main__':
159+
main()
160+

0 commit comments

Comments
 (0)