/* === LINEAUTO = Vers 2/12/92 */
/* By William T Newton 4/18/89 */
/* This program generates one  */
/* dimensional line automata   */
/* from a rule string of the   */
/* digits 0-3. Link to...      */
/*  AUTO.OBJ     Generation ML */
/*  GR7P6F00.OBJ Simulate GR15 */
/*  ACECIO.CCC   Function Libr */
/*  ENGINE.OBJ   ACE C Runtime */

char rulestr[23],rule[23];
char pattern[160],inpstr[80];
int  radius,midflg,esc,temp,i,rand;
int  rulelen,pattlen,key;
int  c0,c1,c2,c3,randmode;
int  creg,cbyte,intens,hue;
int  curpos,esc1;
char *text;
main() $(
/* set Sparta RUNLOC */
 if(peek(dpeek(10)+28)==128||
    peek(0x0700)==0x53)
  dpoke(dpeek(10)+61,0x3635);
 intro();randmode=1;
 c0=0;c1=8+192;c2=12+64;c3=4+128;
 clear(inpstr,23);clear(pattern,160);
 strcpy(inpstr,"1012132");
 convrule();
 graphics(8);graphics(8+32);
 gr7plus();setcols();
 while(1) $(
  esc=1;while(esc) $(
   clear(inpstr,23);
   strcpy(inpstr,rulestr);
   printf("↰↓Rule:%s\n",rulestr);
   temp=radius*2;
   if(midflg==0)temp++;
   printf("Neighborhood Size:%d\n",temp);
   poke(752,0);printf("↑↑→→→→→");
   inputstr();
   if(i=='C')altcols();
   else if(i=='E')edit();
   else if(i=='R')randmode=1;
   else if(i==155)esc=0;
   else convrule();
  $)
  convrule();
/* random starting pattern */
  if(randmode) $(
   i=0;for(;i<160;i++) $(
    rand=peek(0xd20a)&3;
    poke(pattern+i,rand);
   $)
  $)
/* run the automaton */
  setauto(rule,pattern,radius,midflg);
  graphics(8+48);gr7plus();setcols();
  esc=0;while(esc==0) $(
   clear(dpeek(0x0058),7680);
   runauto();
   key=getkey();if(key=='␛')esc=1;
  $)
  graphics(8+32);gr7plus();setcols();
 $)
$)
/* start automaton code */
setauto()
  asm 0x7000;
/* generate automaton code */
runauto()
  asm 0x7003;
/* gr7plus mach code */
gr7plus()
  asm 0x6F01;
/* set plotting colors */
setcols() $(
 poke(708,c1);poke(709,c2);
 poke(710,c3);poke(712,c0);
$)
/* Alter Colors */
altcols() $(
 creg=0; esc=0;
 while(esc==0) $(
  poke(752,1);
  if(creg==0)i=712;else i=707+creg;
  cbyte=peek(i)&254;
  hue=cbyte/16; intens=hue*16;
  intens=(cbyte-intens)&14;
  printf("\f  CHANGE COLOR REGISTERS\n");
  printf("\n   R  Reg:%-2d  H  Hue:%-2d  L  Lum:%d",creg,hue,intens);
  key=toupper(getkey());
  if(key=='R') $(
   creg++;
   if(creg>3) creg=0;
  $)
  else if(key=='H') $(
   hue++;
   if(hue>15) hue=0;
  $)
  else if(key=='L') $(
   intens+=2;
   if(intens>14) intens=0;
  $)
  else esc=1;
  if(key=='H' || key=='L') $(
   cbyte=hue*16; cbyte+=intens;
   if(creg==0)i=712;else i=707+creg;
   poke(i,cbyte);
  $)
 $)
 c0=peek(712);c1=peek(708);
 c2=peek(709);c3=peek(710);
$)
/* edit starting pattern */
edit() $(
 text=peek(106)*256;text-=160;
 esc=0;while(esc!=1) $(
  randmode=0;curpos=0;
  poke(82,0);poke(752,1);printf("↰");
  i=0;for(;i<158;i++)
   poke(text+i,peek(pattern+i)+16);
  poke(752,0);printf("\r\l");
  esc=0;while(esc==0) $(
   key=getkey();
   if(key>='0'&&key<='3') $(
    i=key-48;poke(pattern+curpos,i);
    printf("\r");
    poke(text+curpos,i+16);curpos++;
    if(curpos==40||curpos==80|| curpos==120)printf("↓");
    if(curpos>157) $(
     curpos=157;printf("\l");
    $)
   $)
   if(key=='+'&&curpos>0) $(
    curpos--;printf("\l");
    if(curpos==39||curpos==79|| curpos==119)printf("↑"); $)
   if(key=='*'&&curpos<158) $(
    curpos++;printf("\r");
    if(curpos==40||curpos==80|| curpos==120)printf("↓"); $)
   if(key=='-'&&curpos>39) $(
    printf("↑");curpos-=40; $)
   if(key=='='&&curpos<118) $(
    printf("↓");curpos+=40; $)
   if(key=='␛')esc=1;
   if(key=='↰')esc=2;
  $)
  if(esc==2) for(i=0;i<160;i++) poke(pattern+i,0);
 $)
 poke(82,2);
$)
/* convert input into rule */
convrule() $(
 rulelen=strlen(inpstr);
 if(rulelen>22)rulelen=22;
 clear(rule,23);clear(rulestr,23);
 i=0;for(;i<rulelen;i++) $(
  temp=0;key=peek(inpstr+i);
  if(key=='1')temp=1;
  if(key=='2')temp=2;
  if(key=='3')temp=3;
  poke(rule+i,temp);
  if(temp==0)key='0';
  if(temp==1)key='1';
  if(temp==2)key='2';
  if(temp==3)key='3';
  poke(rulestr+i,key);
 $)
 rulelen=strlen(rulestr);
/* normalize rule length */
 while(rulelen%3!=1||rulelen<7) $(
  poke(rulestr+rulelen,'0');
  rulelen++;
 $)
/* infer radius and middle count */
 radius=1;midflg=1;
 if(rulelen==10)midflg=0;
 else if(rulelen==13)radius=2;
 else if(rulelen==19)radius=3;
 else if(rulelen==16) $(
  radius=2;midflg=0; $)
 else if(rulelen==22) $(
  radius=3;midflg=0; $)
$)
inputstr() $(
 curpos=0;esc1=1;while(esc1) $(
  i=toupper(getkey());
  if(i=='↰'||i=='<') $(
   poke(inpstr+curpos,0);esc1=0;
  $)
  if(i>='0'&&i<='3') $(
   printf("%c",i);
   poke(inpstr+curpos,i);
   curpos++;
   if(curpos>21) $(
    printf("\l");curpos--;
   $)
  $)
  if(i=='+'&&curpos>0) $(
   printf("\l");curpos--;
  $)
  if(i=='*'&&curpos<22) $(
   printf("\r");curpos++;
  $)
  if(i==155||i==' '||i=='C'||
     i=='E'||i=='R')esc1=0;
 $)
$)
/* introducing... */
intro() $(
 graphics(0);poke(752,1);
 poke(709,12);poke(710,0);poke(712,0);
 printf("*** LINEAUTO *** By Terry Newton\n");
 printf("This program generates four state\n");
 printf("one dimensional automata from a rule\n");
 printf("string of the digits 0 to 3 defining\n");
 printf("the next state for all state totals.\n\n");
 printf("At rule prompt...\n");
 printf(" [0][1][2][3] Change rule state\n");
 printf(" [+][*]       Move cursor\n");
 printf(" [Clear]      Zero rule from cursor\n");
 printf(" [Space]      Normalize rule length\n");
 printf(" [Return]     Generate automaton\n");
 printf(" [C]          Change plotting colors\n");
 printf(" [E]          Edit starting pattern\n");
 printf(" [R]          Random start mode\n\n");
 printf("While editing start...\n");
 printf(" [0][1][2][3] Change cell states\n");
 printf(" [+][*][-][=] Move cursor\n");
 printf(" [Clear]      Zero all cells\n");
 printf(" [ESC]        Go to rule prompt\n\n");
 printf("During automaton press [ESC] to exit\n");
 printf("or any key for next screen.");
 getkey();
$)