ack/lang/occam/test/lifegame.ocm
1987-02-25 17:14:10 +00:00

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