This repository has been archived by the owner on Apr 17, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathautomata.py
221 lines (171 loc) · 5.72 KB
/
automata.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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
from copy import deepcopy
import random
import datetime
from browser import document, timer
canvas = document["my-canvas"]
ctx = canvas.getContext("2d")
#self.ctx.translate(.5, .5)
fillRect = ctx.fillRect
is_active = False
in_tick = False
grid = []
initial_state = []
tick_count = 0
dead = 0
alive = 0
line_width = 1
alive_cell_color = "#00FF00"
dead_cell_color = "#e5e5e5"
blank_cell_color = "#FFFFFF"
grid_color = "#808080"
document["btn_start_stop"].disabled = "disabled"
document["btn_tick"].disabled = "disabled"
document["btn_clear"].disabled = "disabled"
cols, rows, size, seed_ratio, rule, dead, alive, tick_delay = 0, 0, 0, 0, 0, 0, 0, 0
def init_grid(ev=None):
global cols, rows, size, seed_ratio, rule, canvas, tick_count, grid
print(">> init_grid", datetime.datetime.utcnow())
cols = int(document["edt_cols"].value)
rows = int(document["edt_rows"].value)
size = int(document["edt_size"].value)
seed_ratio = int(document["edt_seed"].value)
#Rule is defined as S/B notation.
#Some well-known rules :
#23/3 : Conway's game of life
#1234/3 : Mazetric
#12345/3 : Maze
#For more info : http://www.conwaylife.com/wiki/Cellular_automaton
rule = document["edt_rule"].value
tick_count = 0
canvas.width = cols * size
canvas.height = rows * size
document["btn_start_stop"].disabled = "disabled"
document["btn_tick"].disabled = "disabled"
document["btn_clear"].disabled = "disabled"
grid = [[0 for x in range(cols)] for y in range(rows)]
print("<< init_grid", datetime.datetime.utcnow())
def update_canvas():
global dead, alive
dead = 0
alive = 0
print(">> update_canvas", datetime.datetime.utcnow())
rw = 0
for rw in range(rows):
for cl in range(cols):
if grid[rw][cl]:
color = alive_cell_color
alive += 1
else:
color = dead_cell_color
dead += 1
x1 = cl * size
y1 = rw * size
ctx.fillStyle = color
fillRect(x1, y1, size, size)
update_labels()
print("<< update_canvas", datetime.datetime.utcnow())
def seed(ev):
global initial_state, alive, dead
print(">> seed", datetime.datetime.utcnow())
init_grid()
alive = 0
for rw in range(rows):
for cl in range(cols):
seed_chance = random.randint(1, 100)
if seed_chance <= seed_ratio:
grid[rw][cl] = 1
alive += 1
color = alive_cell_color
else:
grid[rw][cl] = 0 #empty cell
color = dead_cell_color
x1 = cl * size
y1 = rw * size
ctx.fillStyle = color
fillRect(x1, y1, size, size)
dead = (rows * cols) - alive
update_labels()
document["btn_start_stop"].disabled = ""
document["btn_tick"].disabled = ""
document["btn_clear"].disabled = ""
initial_state = deepcopy(grid)
print("<< seed", datetime.datetime.utcnow())
def start_stop(ev):
global is_active, tick_delay
if is_active:
is_active = False
document["btn_start_stop"].text = "Start"
document["btn_start_stop"].disabled = ""
document["btn_tick"].disabled = ""
document["btn_clear"].disabled = ""
else:
tick_delay = int(document["edt_delay"].value)
is_active = True
document["btn_start_stop"].text = "Stop"
document["btn_start_stop"].disabled = ""
document["btn_tick"].disabled = "disabled"
document["btn_clear"].disabled = "disabled"
tick()
timer.set_timeout(tick, tick_delay)
def update_labels():
document["lbl_tickno"].text = "Round: %d" %(tick_count)
document["lbl_alive"].text = "Alive: %d" %(alive)
document["lbl_dead"].text = "Dead: %d" %(dead)
def tick(ev=None):
global in_tick, alive, dead, tick_count
if in_tick:
return
in_tick = True
alive = 0
dead = 0
#because slicing does not copy if a list is contained in a list !
old_grid = deepcopy(grid)
_sr, _br = rule.split('/')
_sr = [int(x) for x in _sr]
_br = [int(x) for x in _br]
for rw in range(rows):
for cl in range(cols):
n_alive = 0
for x in range(-1, 2):
nx = cl + x
if nx < 0:
nx = cols - 1
elif nx >= cols:
continue
for y in range(-1, 2):
ny = rw + y
if ny < 0:
ny = rows - 1
if (ny < rows) and ((x != 0) or (y != 0)):
if old_grid[ny][nx] == 1:
n_alive += 1
if grid[rw][cl] == 1:
#if cell is alive !
if not(n_alive in _sr):
grid[rw][cl] = 0
dead += 1
x1 = cl * size
y1 = rw * size
ctx.fillStyle = dead_cell_color
fillRect(x1, y1, size, size)
else:
if n_alive in _br:
grid[rw][cl] = 1
x1 = cl * size
y1 = rw * size
ctx.fillStyle = alive_cell_color
fillRect(x1, y1, size, size)
else:
dead += 1
alive = (rows * cols) - dead
in_tick = False
tick_count += 1
update_labels()
if is_active:
timer.set_timeout(tick, tick_delay)
init_grid()
update_canvas()
document['btn_seed'].bind('click', seed)
document['btn_start_stop'].bind('click', start_stop)
document['btn_tick'].bind('click', tick)
document['btn_clear'].bind('click', init_grid)