-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgol.py
198 lines (160 loc) · 5.01 KB
/
gol.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
from time import sleep
from random import randint
import json
import os
# The rules:
# Any live cell with fewer than two live neighbours dies, as if caused by underpopulation.
# Any live cell with two or three live neighbours lives on to the next generation.
# Any live cell with more than three live neighbours dies, as if by overpopulation.
# Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
SIZE = 42
SHOW_GENERATIONS = False
THRESHOLD = 15
MAX = (SIZE * 10)
CLOCK = 0.5
if SHOW_GENERATIONS:
DEAD = ' '
LIVE = '###'
else:
DEAD = ' '
LIVE = '@'
def generate_row(size):
"""
Creates an empty row.
"""
return [DEAD for i in range(size)]
def generate_board(size, seed=False):
"""
Creates an empty board, optionally filling
it with live cells.
"""
board = [generate_row(size) for i in range(size)]
# seed a glider
# if seed:
if False:
board[1][3] = LIVE
board[2][4] = LIVE
board[3][2] = LIVE
board[3][3] = LIVE
board[3][4] = LIVE
if seed:
# insert a random selection of LIVE cells
how_many = 0
for y in range(size):
for x in range(size):
if how_many < MAX:
randy = randint(0, 100)
if randy < THRESHOLD:
board[x][y] = LIVE
how_many = how_many + 1
return board
def neighbors(cells, y, x):
"""
Given a board and some coordinates,
returns the neighbor cells.
"""
neighbor_cells = []
if x > 0:
neighbor_cells.append(cells[y][x-1])
if x < SIZE - 1:
neighbor_cells.append(cells[y][x+1])
if y > 0:
neighbor_cells.append(cells[y-1][x])
if y < SIZE - 1:
neighbor_cells.append(cells[y+1][x])
if x > 0 and y > 0:
neighbor_cells.append(cells[y-1][x-1])
if x < SIZE - 1 and y < SIZE - 1:
neighbor_cells.append(cells[y+1][x+1])
if x > 0 and y < SIZE - 1:
neighbor_cells.append(cells[y+1][x-1])
if x < SIZE - 1 and y > 0:
neighbor_cells.append(cells[y-1][x+1])
return neighbor_cells
def is_live(cell):
"""
Whether or not a cell contains a live
entity, True or False.
"""
return cell is LIVE
def live_neighbors(cells, y, x):
"""
Returns the number of live neighbor cells.
"""
return sum(1 for c in neighbors(cells, y, x) if is_live(c))
def has_under_population(live_neighbor_count):
"""
If fewer than 2 live neighbors, True.
Otherwise, False.
"""
return live_neighbor_count < 2
def will_live_on(live_neighbor_count):
"""
Has 2 or 3 live neighbors, True.
Otherwise, False.
"""
return live_neighbor_count == 2 or live_neighbor_count == 3
def has_over_population(live_neighbor_count):
"""
Has more than 3 live neighbors, True.
Otherwise, False.
"""
return live_neighbor_count > 3
def will_reproduce(live_neighbor_count):
"""
Has exactly 3 live neighbors, True.
Otherwise, False.
"""
return live_neighbor_count == 3
def print_board(cells):
"""
Clears the screen, then prints
the board.
"""
os.system('clear')
for row in cells:
print(' '.join(row))
def game_loop(cells):
"""
Repeatedly calculates the next generation
of cells and prints cells to screen.
Keeps count of how many generations.
Ends when there is no more change.
"""
gen_count = 0
# Stringify the board for comparing generations.
prev_gen = json.dumps(cells)
while True:
gen_count = gen_count + 1
# Keep next generation in a new board.
new_cells = generate_board(SIZE)
# Iterate through current board, calculating
# birth/death for next generation.
for y in range(len(cells)):
for x in range(len(cells[y])):
c = cells[y][x]
count = live_neighbors(cells, y, x)
if is_live(c):
if has_under_population(count):
new_cells[y][x] = DEAD
elif will_live_on(count):
new_cells[y][x] = cells[y][x]
elif has_over_population(count):
new_cells[y][x] = DEAD
elif will_reproduce(count):
if SHOW_GENERATIONS:
new_cells[y][x] = str(gen_count)
else:
new_cells[y][x] = LIVE
# If no change from previous (or next previous) generation,
# end the game loop.
if cells == new_cells or prev_gen == json.dumps(new_cells):
break
else:
prev_gen = json.dumps(cells)
cells = new_cells[:]
print_board(cells)
print("Generation: ", gen_count)
sleep(CLOCK)
if __name__ == '__main__':
game_loop(generate_board(SIZE, True))