249 lines
5.6 KiB
Plaintext
249 lines
5.6 KiB
Plaintext
def otherwise=true:
|
|
|
|
def dead=0, alive= not dead:
|
|
|
|
def radius=1,
|
|
diameter= (2*radius)+1,
|
|
neighbours= (diameter*diameter)-1:
|
|
|
|
proc calculate.next.state(chan link[], value in[], state, var next.state)=
|
|
var count:
|
|
seq
|
|
var state.of.neighbour[neighbours]:
|
|
seq
|
|
par i=[0 for neighbours]
|
|
link[in[i]] ? state.of.neighbour[i]
|
|
count:=0
|
|
seq i=[0 for neighbours]
|
|
if
|
|
state.of.neighbour[i]=alive
|
|
count:=count+1
|
|
state.of.neighbour[i]=dead
|
|
skip
|
|
if
|
|
count<2
|
|
next.state:=dead
|
|
count=2
|
|
next.state:=state
|
|
count=3
|
|
next.state:=alive
|
|
count>3
|
|
next.state:=dead
|
|
:
|
|
|
|
proc broadcast.present.state(chan link[], value out[], state)=
|
|
par i=[0 for neighbours]
|
|
link[out[i]] ! state
|
|
:
|
|
|
|
def set.state=1, ask.state=2, terminate=3:
|
|
|
|
proc cell(chan link[], value in[], out[], chan control, sense)=
|
|
var state, instruction:
|
|
seq
|
|
state:=dead
|
|
control ? instruction
|
|
while instruction <> terminate
|
|
seq
|
|
if
|
|
instruction=set.state
|
|
control ? state
|
|
instruction=ask.state
|
|
var next.state:
|
|
seq
|
|
par
|
|
broadcast.present.state(link, out, state)
|
|
seq
|
|
calculate.next.state(link, in, state,
|
|
next.state)
|
|
sense ! (state<>next.state); next.state
|
|
|
|
state:=next.state
|
|
|
|
control ? instruction
|
|
:
|
|
|
|
def array.width=5, array.height=5:
|
|
def number.of.cells=array.height*array.width,
|
|
number.of.links=neighbours*number.of.cells:
|
|
|
|
proc initialize(value x, y, var in[], out[])=
|
|
seq delta.x=[-radius for diameter]
|
|
seq delta.y=[-radius for diameter]
|
|
var direction:
|
|
seq
|
|
direction:=delta.x+(diameter*delta.y)
|
|
if
|
|
direction<>0
|
|
var index, process:
|
|
seq
|
|
process:=x+(array.width*y)
|
|
index:=(neighbours+direction) \ (neighbours+1)
|
|
out[index]:=index+(neighbours*process)
|
|
|
|
process:=((x+delta.x+array.width) \ array.width) +
|
|
(array.width*
|
|
((y+delta.y+array.height) \ array.height))
|
|
index:=(neighbours-direction) \ (neighbours+1)
|
|
in[index]:=index+(neighbours*process)
|
|
direction=0
|
|
skip
|
|
:
|
|
|
|
def control= not ((not 0)<<5), escape=control/\'[':
|
|
|
|
proc move.cursor(chan screen, value x, y)=
|
|
screen ! escape; '='; '*s'+y; '*s'+x
|
|
:
|
|
|
|
proc initialize.display(chan screen)=
|
|
screen ! control /\ 'Z'
|
|
:
|
|
|
|
proc clean.up.display(chan screen)=
|
|
move.cursor(screen, 0, array.height)
|
|
:
|
|
|
|
proc display.state(chan screen, value x, y, state)=
|
|
seq
|
|
move.cursor(screen, x, y)
|
|
if
|
|
state=alive
|
|
screen ! '**'
|
|
state=dead
|
|
screen ! '*s'
|
|
:
|
|
|
|
proc generation(chan screen, control[], sense[], var active)=
|
|
seq
|
|
seq cell=[0 for number.of.cells]
|
|
control[cell] ! ask.state
|
|
active:=false
|
|
seq cell=[0 for number.of.cells]
|
|
var changed, next.state:
|
|
seq
|
|
sense[cell] ? changed; next.state
|
|
if
|
|
changed
|
|
seq
|
|
display.state(screen, cell\array.width,
|
|
cell/array.width, next.state)
|
|
active:=true
|
|
not changed
|
|
skip
|
|
:
|
|
|
|
proc edit(chan keyboard, screen, control[])=
|
|
def ctrl= not ((not 0)<<5):
|
|
def left.key= 'h', right.key= 'l', up.key= 'k', down.key= 'j',
|
|
uproot.key= '*s', plant.key= '**', plant.key2= '8':
|
|
var x, y, editing, ch:
|
|
seq
|
|
x:=array.width/2
|
|
y:=array.height/2
|
|
editing:=true
|
|
while editing
|
|
seq
|
|
move.cursor(screen, x, y)
|
|
keyboard ? ch
|
|
if
|
|
(ch=left.key) and (x>0)
|
|
x:=x-1
|
|
(ch=right.key) and (x<(array.width-1))
|
|
x:=x+1
|
|
(ch=up.key) and (y>0)
|
|
y:=y-1
|
|
(ch=down.key) and (y<(array.height-1))
|
|
y:=y+1
|
|
(ch=uproot.key) or (ch=plant.key) or (ch=plant.key2)
|
|
var state:
|
|
seq
|
|
state:=(dead /\ (ch=uproot.key)) \/
|
|
(alive /\ ((ch=plant.key) or (ch=plant.key2)))
|
|
control[x+(array.width*y)] ! set.state; state
|
|
display.state(screen, x, y, state)
|
|
(ch='q') or (ch='Q')
|
|
editing:=false
|
|
otherwise
|
|
skip
|
|
:
|
|
|
|
def idle=1, editing=2, single.stepping=3, free.running=4, terminated=5:
|
|
|
|
proc display.activity(chan screen, value activity)=
|
|
seq
|
|
move.cursor(screen, array.width+1, array.height+2)
|
|
|
|
proc write.string(value str[])=
|
|
seq i=[1 for str[byte 0]]
|
|
screen ! str[byte i]
|
|
:
|
|
if
|
|
activity=idle
|
|
write.string("Idle")
|
|
activity=editing
|
|
write.string("Edit")
|
|
activity=single.stepping
|
|
write.string("Step")
|
|
activity=free.running
|
|
write.string("Busy")
|
|
activity=terminated
|
|
write.string("Done")
|
|
:
|
|
|
|
proc controller(chan keyboard, screen, control[], sense[])=
|
|
var activity:
|
|
seq
|
|
activity:=idle
|
|
initialize.display(screen)
|
|
while activity<>terminated
|
|
seq
|
|
display.activity(screen, activity)
|
|
var ch:
|
|
pri alt
|
|
(activity <> editing) & keyboard ? ch
|
|
if
|
|
(ch='q') or (ch='Q')
|
|
activity:=terminated
|
|
(ch='i') or (ch='I')
|
|
activity:=idle
|
|
(ch='e') or (ch='E')
|
|
activity:=editing
|
|
(ch='r') or (ch='R')
|
|
activity:=free.running
|
|
(ch='s') or (ch='S')
|
|
activity:=single.stepping
|
|
(activity=editing) & skip
|
|
seq
|
|
edit(keyboard, screen, control)
|
|
activity:=idle
|
|
(activity=free.running) or (activity=single.stepping) & skip
|
|
var changing:
|
|
seq
|
|
generation(screen, control, sense, changing)
|
|
if
|
|
(activity=single.stepping) or (not changing)
|
|
activity:=idle
|
|
(activity=free.running) and changing
|
|
skip
|
|
display.activity(screen, activity)
|
|
seq cell=[0 for number.of.cells]
|
|
control[cell] ! terminate
|
|
clean.up.display(screen)
|
|
:
|
|
|
|
chan link[number.of.links], control[number.of.cells], sense[number.of.cells]:
|
|
seq
|
|
output ! RAW
|
|
par
|
|
controller(input, output, control, sense)
|
|
|
|
par x=[0 for array.width]
|
|
par y=[0 for array.height]
|
|
var in[neighbours], out[neighbours]:
|
|
seq
|
|
initialize(x, y, in, out)
|
|
cell(link, in, out, control[x+(array.width*y)],
|
|
sense[x+(array.width*y)])
|
|
output ! TEXT
|