Page 1 of 1

Cellular automata

Posted: Fri Feb 01, 2019 8:46 pm
by Henko
6 years ago i posted a program "automaton", based on an article in the late "Byte" magazine.
I redesigned that program, especially the user interface.
4 files are needed, from which the names of the last three must be followed as given (unless the code is modified). All files must reside in the same directory (unless.....).

EA783DC0-935A-4186-B792-7AA90839C6AC.png
EA783DC0-935A-4186-B792-7AA90839C6AC.png (284.24 KiB) Viewed 10023 times
automaton.sb - the mainprogram
full_dump.sb - draws a full screen picture, started by en returns to the main program
automaton_help - the help text for the help function in the program
auto_rules - rules, selected and saved by the user. Contains 10 rules for a start

automaton.sb

Code: Select all

' Automaton, 1D cellular automata, Byte magazine dec. 1986
' version january 31, 2019
'
option base 1
dim rule$(400),bs(600),r(10),ah$(200)
prog_init() ! goto begin
do
  sel=list_selected("rules")
  if sel>0 then
    selected=sel ! s_play=sel
    aton(rule$(sel),r)
    field "cur_rule" text ntoa$(.r)
    list "rules" select -1
    for i=1 to nb ! bs(i)=rnd(4) ! next i
    start(r,bs)
    end if
 if bp("help") then fhelp()
 if bp("rand") then
    begin: rand_rule(r)
    for i=1 to nb ! bs(i)=rnd(4) ! next i
    start(r,bs)
    end if
  if bp("start") then
    for i=1 to nb ! bs(i)=rnd(4) ! next i
    start(r,bs)
    end if
  if bp("1pix") then
    for i=1 to nb ! bs(i)=0 ! next i
    bs(floor(nb/2))=1+rnd(3)
    start(r,bs)
    end if
  if bp("cont") then start(r,bs)
  if bp("dump") then
    f$="dump_data" ! if file_exists(f$) then file f$ delete
    file f$ print b_size
    for i=1 to 10 ! file f$ print r(i) ! next i
    run "full_dump.sb"
    end if
  if bp("plus") and b_size<5 then
    b_size+=1 ! button "size" text "size="&b_size
    nb=floor(600/b_size) ! start(r,bs)
    end if
  if bp("mins") and b_size>1 then
    b_size-=1 ! button "size" text "size="&b_size
    nbo=nb ! nb=floor(600/b_size)
    for i=nbo+1 to nb ! bs(i)=rnd(4) ! next i
    start(r,bs)
    end if
  if bp("add") and nrec<400 then
    t$=field_text$("cur_rule") ! tcon$=""
    for i=1 to len(t$)
      c$=substr$(t$,i,i) ! if c$<>" " then tcon$&=c$
      next i
    nrec+=1 ! rule$(nrec)=tcon$ ! save_rules()
    c_list("rules","   Rules",rule$,nrec,ex-130,sy,ex,sh-20)
    end if
  if bp("del") and selected>0 then
    if selected<nrec then
      for i=selected to nrec-1 ! rule$(i)=rule$(i+1) ! next i
      end if
    nrec-=1 ! save_rules()
    c_list("rules","   Rules",rule$,nrec,ex-130,sy,ex,sh-20)
    end if
  if bp("pb_ss") then
    button "pb_ss" hide ! button "pb_st" show ! play(s_play,nrec,1,1)
    end if
  if bp("pb_bg") then
    button "pb_st" show ! play(1,nrec,1,1)
    end if
  if bp("pb_en") then
    button "pb_st" show ! play(nrec,1,-1,1)
    end if
  if bp("pb_bk") then
    button "pb_st" show ! play(s_play,1,-1,1)
    end if
  if bp("pb_fb") then
    button "pb_st" show ! play(s_play,1,-1,0)
    end if
  if bp("pb_ff") then
    button "pb_st" show ! play(s_play,nrec,1,0)
    end if
  if field_changed("cur_rule") then
    t$=field_text$("cur_rule")
    aton(t$,r)
    for i=1 to nb ! bs(i)=rnd(4) ! next i
    start(r,bs)
    end if
  if bp("stop") then break
  until forever
end

def play(rs,re,dr,dt)
for i=rs to re step dr
  list "rules" select i
  button "disp" text "Rule "&i
  aton(.rule$(i),.r)
  field "cur_rule" text ntoa$(.r)
  for j=1 to .nb ! .bs(j)=rnd(4) ! next j
  start(.r,.bs) ! pause dt
  if bp("pb_st") then
    .s_play=i ! button "pb_st" hide ! button "pb_ss" show ! break
    end if
  next i

end def

def prog_init()
graphics ! graphics clear .8,.8,.8 ! draw color 0,0,0
set orientation portrait ! randomize
set toolbar off ! refresh off
get screen size .sw,.sh
.nrec=load_rules()
.sx=84 ! .ex=.sx+599 ! .sy=650 ! .s_play=1
.b_size=3 ! .nb=floor(600/.b_size)
draw rect .sx, 24 to .ex,.ex-.sx+24
c_list("rules","   Rules",.rule$,.nrec,.ex-130,.sy,.ex,.sh-20)
field "cur_rule" text "" at 250,.sy size 280,50
rand_rule(.r)
button "rand"  text "Random rule" at .sx,.sy size 140,30
button "start" text "Restart" at .sx,.sy+50 size 140,30
button "1pix" text "1 pix start" at .sx,.sy+100 size 140,30
button "cont" text "Continue" at .sx,.sy+150 size 140,30
button "dump" text "Full dump" at .sx,.sy+270 size 140,30
button "stop" text "Stop" at .sx,.sh-50 size 100,30
button "mins" text "-" at 250,.sy+70 size 50,30
button "size" text "size=3" at 320,.sy+70 size 140,30
button "plus" text "+" at 480,.sy+70 size 50,30
button "add"  text "Add rule" at 390,.sy+120 size 140,30
button "del"  text "Delete rule" at 390,.sy+170 size 140,30
button "disp" text "playing" at 334,930 size 140,30
button "help" text "Help" at 265,800 size 90,90
play_bar(280,965,30)
win_help("autohelp",.sx,24,600,600,3)
refresh
end def

def load_rules()
f$="auto_rules" 
if not file_exists(f$) then file f$ print  """"&"0230101303"&""""
while data_exist(f$)
  nrec+=1
  file f$ input .rule$(nrec)
  end while
return nrec
end def

def save_rules()
f$="auto_rules"
if file_exists(f$) then file f$ delete
if .nrec then
  for i=1 to .nrec
    rr$="""" & .rule$(i) & """"
    file f$ print rr$
    next i
  end if
end def

def start(r(),s())
for i=1 to .nb
  if i>1 then
    t1=s(.nb)+s(1)+s(2) ! tn=s(1)+s(.nb-1)+s(.nb)
    for j=2 to .nb-1
      t2=s(j-1)+s(j)+s(j+1) ! s(j-1)=t1 ! t1=t2
      next j
    s(.nb)=tn
    for j=1 to .nb ! s(j)=r(s(j)+1) ! next j
    end if
  for j=1 to .nb 
    set_col(s(j))
    x1=.sx+(j-1)*.b_size ! y1=24+(i-1)*.b_size
    x2=x1+.b_size ! y2=y1+.b_size
    fill rect x1,y1 to x2,y2
    next j
  refresh
  next i
end def

def ntoa$(r())
t$="  "
for i=1 to 10 ! t$=t$ & "   " & r(i) ! next i
return t$
end def

def aton(t$,r())
k=0
for i=1 to len(t$)
  c$=substr$(t$,i,i) 
  if c$<>" " then
    k=k+1 ! r(k)=c$
    end if
  next i
return k
end def

def rand_rule(r())
for i=1 to 10 !  r(i)=rnd(4) ! next i
tt$=ntoa$(r)
field "cur_rule" text tt$
end def

def set_col(p)
if p=0 then fill color 0,0,0
if p=1 then fill color 1,0,0
if p=2 then fill color 0,1,0
if p=3 then fill color 0,0,1
end def

def play_bar(x,y,bs)
dx=10 ! dy=5 ! yy=y+dy ! set buttons font size bs
button "pb_bar" text "" at x,y size 250,bs+10
button "pb_bg" text chr$(9198)  at x+dx,yy size bs,bs
button "pb_fb" text chr$(9194)  at x+bs+2*dx,yy size bs,bs
button "pb_bk" text chr$(57915) at x+2*bs+3*dx,yy size bs,bs
button "pb_ss" text chr$(57914) at x+3*bs+4*dx,yy size bs,bs
button "pb_st" text chr$(9209)  at x+3*bs+4*dx,yy size bs,bs
button "pb_ff" text chr$(9193)  at x+4*bs+5*dx,yy size bs,bs
button "pb_en" text chr$(9197)  at x+5*bs+6*dx,yy size bs,bs
button "pb_st" hide
end def

def fhelp()
page "autohelp" alpha 0 ! page "autohelp" show
for i=0 to 1 step .05
  page "autohelp" alpha i ! pause .05
  next i
do slowdown ! until bp("help") or bp("hback")
for i=1 to 0 step -.05
  page "autohelp" alpha i ! pause .05
  next i
page "autohelp" hide
end def

def win_help(hn$,xo,yo,w,h,t)
dim ah$(64) ! nr=0
do 
  nr+=1 ! file "automaton_help" readline ah$(nr)
  until file_end("automaton_help")
t2=2*t ! t4=4*t
page hn$ set
page hn$ frame xo,yo, w,h
page hn$ color .8,.8,.8,1
set buttons custom ! set buttons font size 22
draw color 0,0,0 ! fill color .8,.8,.8
button "h1" text "" at -t2,0 size w+t4,3
button "h2" text "" at 0,-t2 size t,h+t4
button "h3" text "" at -t2,h-t size w+t4,t
button "h4" text "" at w-t,-t2 size t,h+t4
button "h5" text "" at -t2,48 size w+t4,t
field "htitle" text "   Automaton help" at 90,10 size 320,33 RO
field "htitle" back color .8,.8,.8
field "htitle" font color 0,0,0
field "htitle" font name "Courier-Bold"
field "htitle" font size 30
button "hback" text "Return" at w-100,10 size 92,33
set lists custom
set lists font size 20 ! draw color 0,0,1
list hn$ text ah$ at 7,52 size w-10,h-56
draw color 0,0,0
page hn$ hide
end def

' id$ = object name
' cont$ = array met elementen
' size = aantal elementen in de list
'
def c_list(id$,title$,cont$(),size,xt,yt,xb,yb)
dim temp$(size)
for i=1 to size ! temp$(i)=cont$(i) ! next i
fill color 1,1,1 ! draw color 0,0,0 ! set lists font size 16
list id$ text temp$ at xt+2,yt+32 size xb-xt-4,yb-yt-34
draw size 3
draw rect xt,yt to xb,yb ! draw line xt,yt+30 to xb,yt+30
draw color 0,0,1 ! draw text title$ at xt+5,yt+5
end def

def bp(a$) = button_pressed(a$)
full_dump.sb

Code: Select all

[code]
randomize ! option base 1
set orientation landscape
set toolbar off
get screen size sw,sh
graphics ! graphics clear .8,.8,.8
f$="dump_data"
if not file_exists(f$) then stop
file f$ input bs ' pixel size
nb=floor(sw/bs) ' # of pixels on one line
nc=floor(sh/bs) ' # of pixels in one column
dim s(nb),r(10)
for i=1 to 10 ! file f$ input r(i) ! next i ' read rule
for i=1 to nb ! s(i)=rnd(4) ! next i ' init base line
' fill the screen
for i=1 to nc
if i>1 then
t1=s(nb)+s(1)+s(2) ! tn=s(1)+s(nb-1)+s(nb)
for j=2 to .nb-1
t2=s(j-1)+s(j)+s(j+1) ! s(j-1)=t1 ! t1=t2
next j
s(nb)=tn
for j=1 to nb ! s(j)=r(s(j)+1) ! next j
end if
for j=1 to nb
set_col(s(j))
x1=(j-1)*bs ! y1=(i-1)*bs ! x2=x1+bs ! y2=y1+bs
fill rect x1,y1 to x2,y2
next j
refresh
next i
' take picture and save it
graphics save 0,0,sw,sh to "automaton_pic.jpg"
pause 3
run "automaton.sb"
end

def set_col(p)
if p=0 then fill color 0,0,0
if p=1 then fill color 1,0,0
if p=2 then fill color 0,1,0
if p=3 then fill color 0,0,1
end def
[/code]

automaton_help

Code: Select all

'Automaton'
The 'automaton' is a very simple digital machine, 
extensively described in the december 1986 edition of
the Byte magazine. It consists of a one-dimensional
array of elements that can each have 1 out of 4 statusses.
By assigning a color to each of the statusses, the array
can be put on the screen as a multicolored line.
For the next step, the status of each element is
recalculated as the sum of his former status and those of
its neighbours (points). This sum can be anything between
0 and 9. That sum is reduced to a value between
0 and 3 by a 'rule'. An example of such rule:        
    sum:  0  1  2  3  4  5  6  7  8  9       
    rule:   0  2  3  0  1  1  0  2  2  1
The new line is drawn, and the proces is repeated a
number of times to produce a pattern.
Dependent on the starting values of the points and the
rule that is applied, interesting patterns may emerge.
In general, all patterns converge to a stable pattern,
some quickly, others only after a considerable number of
steps.
The screen has a display window in which the pattern
enrolls, an edit window containing the current rule,
a scrollable listbox containing all saved rules that
produce an interesting pattern, and some buttons.
Buttons:
Tapping the 'random rule' button places a new rule in the
edit window and starts rendering that rule.
The 'restart' button will use the same rule in the edit
window, but starts rendering with a new random starting
line.
The '1 pix start' button uses one non-zero pixel in the
middle of the rendering square as a new starting line.
The 'continue' button continues the rendering with the
same rule and using the last generated line as starting
line.
The 'full dump' button starts rendering a full screen with
the current rule. The program is ended upon completion of
the rendering.
The 'stop' button will end the program.

The size of the 'pixels' may be adapted using the 
'+' and the '-' button.
Default is the value 3, the maximum size is 5 pixels.
The rendering speed varies strongly with the pixel size.

Rules: In the edit field the rule may be modified.
Spaces are inserted for readability, but they need not be
retained. Just take care, that 10 numbers remain in the
window after editing.
A rule in the edit window can be added to the rules table
with the 'Add rule' button. 

The rules table is displayed in a scrollable listbox.
When selecting a rule, the rule is placed in the edit field
and rendering starts immediatly.
A selected rule may be deleted from the table using the
'delete rule' button.
Using the playing buttons, the rules in the table may be
processed sequentially in both directions, fast or slow.
Starting points are the beginning or the end of the table,
or an arbitrary rule as set by the button 'random rule'.
The rules in the listbox are kept in a file, which is
loaded and updated automatically. 

auto_rules

Code: Select all

"0232133112"
"1032201112"
"0020231331"
"2331113001"
"0230101303"
"1230332320"
"1212202313"
"0111032213"
"0203020332"
"2303112313"
"2331200111"
"2113131220"