248 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			248 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
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
 |