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