3 def dead=0, alive= not dead:
6 diameter= (2*radius)+1,
7 neighbours= (diameter*diameter)-1:
9 proc calculate.next.state(chan link[], value in[], state, var next.state)=
12 var state.of.neighbour[neighbours]:
14 par i=[0 for neighbours]
15 link[in[i]] ? state.of.neighbour[i]
17 seq i=[0 for neighbours]
19 state.of.neighbour[i]=alive
21 state.of.neighbour[i]=dead
34 proc broadcast.present.state(chan link[], value out[], state)=
35 par i=[0 for neighbours]
39 def set.state=1, ask.state=2, terminate=3:
41 proc cell(chan link[], value in[], out[], chan control, sense)=
42 var state, instruction:
46 while instruction <> terminate
55 broadcast.present.state(link, out, state)
57 calculate.next.state(link, in, state,
59 sense ! (state<>next.state); next.state
66 def array.width=5, array.height=5:
67 def number.of.cells=array.height*array.width,
68 number.of.links=neighbours*number.of.cells:
70 proc initialize(value x, y, var in[], out[])=
71 seq delta.x=[-radius for diameter]
72 seq delta.y=[-radius for diameter]
75 direction:=delta.x+(diameter*delta.y)
80 process:=x+(array.width*y)
81 index:=(neighbours+direction) \ (neighbours+1)
82 out[index]:=index+(neighbours*process)
84 process:=((x+delta.x+array.width) \ array.width) +
86 ((y+delta.y+array.height) \ array.height))
87 index:=(neighbours-direction) \ (neighbours+1)
88 in[index]:=index+(neighbours*process)
93 def control= not ((not 0)<<5), escape=control/\'[':
95 proc move.cursor(chan screen, value x, y)=
96 screen ! escape; '='; '*s'+y; '*s'+x
99 proc initialize.display(chan screen)=
100 screen ! control /\ 'Z'
103 proc clean.up.display(chan screen)=
104 move.cursor(screen, 0, array.height)
107 proc display.state(chan screen, value x, y, state)=
109 move.cursor(screen, x, y)
117 proc generation(chan screen, control[], sense[], var active)=
119 seq cell=[0 for number.of.cells]
120 control[cell] ! ask.state
122 seq cell=[0 for number.of.cells]
123 var changed, next.state:
125 sense[cell] ? changed; next.state
129 display.state(screen, cell\array.width,
130 cell/array.width, next.state)
136 proc edit(chan keyboard, screen, control[])=
137 def ctrl= not ((not 0)<<5):
138 def left.key= 'h', right.key= 'l', up.key= 'k', down.key= 'j',
139 uproot.key= '*s', plant.key= '**', plant.key2= '8':
140 var x, y, editing, ch:
147 move.cursor(screen, x, y)
150 (ch=left.key) and (x>0)
152 (ch=right.key) and (x<(array.width-1))
154 (ch=up.key) and (y>0)
156 (ch=down.key) and (y<(array.height-1))
158 (ch=uproot.key) or (ch=plant.key) or (ch=plant.key2)
161 state:=(dead /\ (ch=uproot.key)) \/
162 (alive /\ ((ch=plant.key) or (ch=plant.key2)))
163 control[x+(array.width*y)] ! set.state; state
164 display.state(screen, x, y, state)
171 def idle=1, editing=2, single.stepping=3, free.running=4, terminated=5:
173 proc display.activity(chan screen, value activity)=
175 move.cursor(screen, array.width+1, array.height+2)
177 proc write.string(value str[])=
178 seq i=[1 for str[byte 0]]
186 activity=single.stepping
188 activity=free.running
194 proc controller(chan keyboard, screen, control[], sense[])=
198 initialize.display(screen)
199 while activity<>terminated
201 display.activity(screen, activity)
204 (activity <> editing) & keyboard ? ch
213 activity:=free.running
215 activity:=single.stepping
216 (activity=editing) & skip
218 edit(keyboard, screen, control)
220 (activity=free.running) or (activity=single.stepping) & skip
223 generation(screen, control, sense, changing)
225 (activity=single.stepping) or (not changing)
227 (activity=free.running) and changing
229 display.activity(screen, activity)
230 seq cell=[0 for number.of.cells]
231 control[cell] ! terminate
232 clean.up.display(screen)
235 chan link[number.of.links], control[number.of.cells], sense[number.of.cells]:
239 controller(input, output, control, sense)
241 par x=[0 for array.width]
242 par y=[0 for array.height]
243 var in[neighbours], out[neighbours]:
245 initialize(x, y, in, out)
246 cell(link, in, out, control[x+(array.width*y)],
247 sense[x+(array.width*y)])