home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 245_01 / lca23.c < prev    next >
Text File  |  1987-10-28  |  29KB  |  917 lines

  1.  
  2.  
  3. /* (2,3) Linear Cellular Automaton    */
  4.  
  5. /* Reference:                */
  6. /*                    */
  7. /*    Kenneth E. Perry            */
  8. /*    Abstract Mathematical Art        */
  9. /*    BYTE                */
  10. /*    December, 1986            */
  11. /*    pages 181-192            */
  12.  
  13. /*    Copyright (C) 1987        */
  14. /*    Harold V. McIntosh        */
  15. /*    Gerardo Cisneros S.        */
  16.  
  17. /* G. Cisneros, 4.3.87                        */
  18. /* 10 April 1987 - modified for (4,2) [HVM]            */
  19. /* 26 April 1987 - Multiple menus [HVM]                */
  20. /* 28 April 1987 - back modified to (4,1) [HVM]            */
  21. /* 28 April 1987 - version for XVI Feria de Puebla [HVM]    */
  22. /* 14 May 1987 - modified for (3,1) and general rule [HVM]    */
  23. /* 19 May 1987 - modified for (2,2)                */
  24. /* 20 May 1987 - modified for (2,3)                */
  25.  
  26. # include <bdos.h>
  27.  
  28. # define COLGRAF     4  /* graph resolution            */
  29. # define T80X25      3  /* text resolution            */
  30. # define WHCYMAG     1  /* color quad for normal screen        */
  31. # define AL        320  /* array length (screen width)        */
  32. # define TS         8    /* distinct sums w/totalistic rule    */
  33. # define DS        32  /* (number of distinct neighborhoods)/4    */
  34. # define KK         2  /* number of states per cell        */
  35. # define NX         14    /* number of sample rules        */
  36.  
  37. char xrule[NX][KK][KK][KK][KK][KK];
  38.  
  39. char ixrule[NX][DS]=
  40.  
  41.     "00AC324A8D30329A99A108A46C9FDCB7",    /* cycles on dgl bgrnd    */
  42.     "088686698669337E8669699E699E9EE7",    /* class iv - try vnts    */
  43.     "088E8CC78EAEE5888CC7E67FE7717118",    /* very complex gliders    */
  44.     "088E8EE78EE7E7798EE7E779E7797996",    /* Extrmly good varnts    */
  45.     "088071C431F94830C78A435E015198DC",
  46.  
  47.     "1008088608868669088686698669699E",    /* dominant triangles    */
  48.     "11000100000010110111001011001100",    /* flotsam & jetsam    */
  49.     "28CA858DC0500D0512AAA0BACBBB94B3",
  50.     "381E3AFA19D7CECBCE5867F7206F7B6E",    /* mottled        */
  51.     "4A1ADAD80AAC3E8E8AEE4D138308E0FB",    /* crossed gliders    */
  52.  
  53.     "88EF636569ABE6994C073A1FF3AC5EFE",    /*            */
  54.     "8A0FFA23E1FF8558675AFF0B53AD9FCB",    /* dislocatns & regns    */
  55.     "A3F73FA3A81F3F4AE4280DED0E317F1B",
  56.     "D2BF4202000000005CEDB7C000000000"    /* dislocation        */
  57.  
  58.     ;
  59.  
  60. char  xx[4], rule[DS+1], ascrule[KK][KK][KK][KK][KK][KK][KK];
  61. int   binrule[KK][KK][KK][KK][KK][KK][KK], arule[DS], arr1[AL], arr2[AL];
  62. char  trule[TS]="00000000";
  63.  
  64. main()
  65. {
  66. int  i, j, i0, i1, i2, i3, i4, i5, i6;
  67. int  more = 'r';
  68. char a, b, c;
  69.  
  70. for (i=0; i<NX; i++) {                    /* copy to 5-index array */
  71. i0=0; i1=0; i2=0; i3=0; i4=0;
  72. for (j=0; j<DS; j++) {
  73.   xrule[i][i0][i1][i2][i3][i4]=ixrule[i][j];
  74.   i4++;
  75.   if (i4==KK) {i4=0; i3++;};
  76.   if (i3==KK) {i3=0; i2++;};
  77.   if (i2==KK) {i2=0; i1++;};
  78.   if (i1==KK) {i1=0; i0++;};
  79.   if (i0==KK) {i0=0; };
  80. };};
  81.  
  82.  
  83.     videopalette(WHCYMAG);                /* white/cyan/magenta */
  84.  
  85.     tuto();
  86.     while (!kbdst()) rand();                /* wait for keypress */
  87.     kbdin();                        /* ignore it */
  88.     videomode(T80X25);
  89.     videoscroll(3,0,5,71,0,3);                /* menu on blue background */
  90.     videoscroll(19,0,24,71,0,3);
  91.     xtoasc(rand()%NX);
  92.     rule[DS]=0;
  93.     ranlin();                        /* random initial array */
  94.  
  95.     while (more!='n') {                    /* execute multiple runs */
  96.     rmenu();
  97.     lmenu();
  98.     while (0<1) {                    /* set up one run */
  99.     c=kbdin();
  100.     if (c=='g') break;                    /* go draw graph */
  101.     if (c=='q') more='n';                /* quit for good */
  102.     if (more=='n') break;
  103.     switch (c) {
  104.     case '@':                    /* numbered tot rule */
  105.         nutoto(numin(0));
  106.         totoasc();
  107.         rmenu();
  108.         videocursor(0,4,0);
  109.         break;
  110.     case '$':                    /* dozen totalistics */
  111.         j=numin(0);
  112.         for (i=0; i<12; i++) {
  113.           nutoto(j+i);
  114.           totoasc();
  115.           ranlin();
  116.           evolve(rule);
  117.           };
  118.         videomode(T80X25);
  119.         rmenu();
  120.         lmenu();
  121.         break;
  122.     case 't':                    /* totalistic rule */
  123.         xblnk();
  124.         tmenu();
  125.         edtrule();
  126.         totoasc();
  127.         for (i0=0; i0<KK; i0++) {
  128.         for (i1=0; i1<KK; i1++) {
  129.         for (i2=0; i2<KK; i2++) {
  130.         for (i3=0; i3<KK; i3++) {
  131.         for (i4=0; i4<KK; i4++) {
  132.         for (i5=0; i5<KK; i5++) {
  133.         for (i6=0; i6<KK; i6++) {
  134.         ascrule[i0][i1][i2][i3][i4][i5][i6]=trule[i0+i1+i2+i3+i4+i5+i6];
  135.         };};};};};};};
  136.         videocursor(0,4,0);
  137.         rmenu();
  138.         xmenu(totonu(0));
  139.         break;
  140.         case 'r':                    /* edit rule */    
  141.         xblnk();
  142.         edrule();
  143.         videocursor(0,4,0);
  144.         rmenu();
  145.         break;
  146.         case 'l':                    /* edit cell string */
  147.         xblnk();
  148.         edline();
  149.         videocursor(0,3,0);
  150.         lmenu();
  151.         break;
  152.         case '#':                    /* read stored rule */
  153.         xmenu(NX);
  154.         xtoasc(lim(1,numin(0),NX)-1);
  155.         rmenu();
  156.             break;
  157.     case 'D':                    /* run through samples */
  158.         for (i=0; i<NX; i++) {
  159.           xmenu(i);
  160.           xtoasc(i);
  161.           ranlin();
  162.           evolve(rule);
  163.           };
  164.         videomode(T80X25);
  165.         rmenu();
  166.         break;
  167.         case 'u':                    /* sparse init arry */
  168.         xblnk();
  169.         for (i=0; i<AL; i++) arr1[i]=0;
  170.         arr1[AL/4]=1;
  171.             arr1[AL/2]=1;
  172.             arr1[(3*AL)/4]=1;
  173.             arr1[(3*AL)/4+2]=1;
  174.         lmenu();
  175.             break;
  176.     case 'x':                    /* random rule */
  177.         xblnk();
  178.         for (i0=0; i0<KK; i0++) {
  179.         for (i1=0; i1<KK; i1++) {
  180.         for (i2=0; i2<KK; i2++) {
  181.         for (i3=0; i3<KK; i3++) {
  182.         for (i4=0; i4<KK; i4++) {
  183.         for (i5=0; i5<KK; i5++) {
  184.         for (i6=0; i6<KK; i6++) {
  185.           if (i4 == 0) i=rand();
  186.           ascrule[i0][i1][i2][i3][i4][i5][i6]='0'+i%2;
  187.           i/=2;
  188.         };};};};};};};
  189.         rmenu();
  190.         break;
  191.     case 'y':                    /* random line */
  192.         xblnk();
  193.         ranlin();
  194.             lmenu();
  195.         break;
  196.     case 'Y':                    /* symmetrize rule */
  197.         for (i0=0; i0<KK; i0++) {
  198.         for (i1=0; i1<KK; i1++) {
  199.         for (i2=0; i2<KK; i2++) {
  200.         for (i3=0; i3<KK; i3++) {
  201.         for (i4=0; i4<KK; i4++) {
  202.         for (i5=0; i5<KK; i5++) {
  203.         for (i6=0; i6<KK; i6++) {
  204.         ascrule[i6][i5][i4][i3][i2][i1][i0]=ascrule[i0][i1][i2][i3][i4][i5][i6];      
  205.         };};};};};};};
  206.         break;
  207.     case 'B':                    /* begin barrier */
  208.         a=kbdin();
  209.         b=kbdin();
  210.         ascrule[0][0][0][0][0][a-'0'][b-'0']=a;
  211.         ascrule[0][0][1][0][0][a-'0'][b-'0']=a;
  212.         ascrule[0][0][2][0][0][a-'0'][b-'0']=a;
  213.         rmenu();
  214.         break;
  215.     case 'E':                    /* end barrier */
  216.         a=kbdin();
  217.         b=kbdin();
  218.         ascrule[0][0][0][0][a-'0'][b-'0'][0]=b;
  219.         ascrule[0][0][0][0][a-'0'][b-'0'][1]=b;
  220.         ascrule[0][0][0][0][a-'0'][b-'0'][2]=b;
  221.         rmenu();
  222.         break;
  223.     case 'L':                    /* left glider link */
  224.         a=kbdin();
  225.         b=kbdin();
  226.         c=kbdin();
  227.         ascrule[0][0][0][0][a-'0'][b-'0'][c-'0']=c;
  228.         rmenu();
  229.         break;
  230.     case 'R':                    /* left glider link */
  231.         a=kbdin();
  232.         b=kbdin();
  233.         c=kbdin();
  234.         ascrule[0][0][0][0][a-'0'][b-'0'][c-'0']=a;
  235.         rmenu();
  236.         break;
  237.     case 'S':                    /* still life link */
  238.         a=kbdin();
  239.         b=kbdin();
  240.         c=kbdin();
  241.         ascrule[0][0][0][0][a-'0'][b-'0'][c-'0']=b;
  242.         rmenu();
  243.         break;
  244.     case '=':
  245.         for (i=1; i<8;  i++) {
  246.         for (j=0; j<40; j++) arr1[40*i+j]=arr1[j];};
  247.         lmenu();
  248.         break;
  249.     case '~':
  250.         for (i=1; i<16;  i++) {
  251.         for (j=0; j<20; j++) arr1[20*i+j]=arr1[j];};
  252.         lmenu();
  253.         break;
  254.         default: break;
  255.         };
  256.     };
  257.     if (more=='n') break;
  258.     do {
  259.     evolve(rule);
  260.     videocursor(0,0,0);
  261.     scrstr("?");
  262.     videocursor(0,0,34);
  263.     scrstr("y/n/cr");
  264.     more=kbdin();
  265.     } while (more=='\015');
  266.     videomode(T80X25);                    /* reset the screen */
  267.     if (more=='n') break;
  268.     };
  269.   videomode(T80X25);}    
  270.  
  271. /* edit the rule */
  272. edrule() {
  273. char c;
  274. int  i, i0, i1, i2, i3, i4;
  275.  
  276. i=6; i0=0; i1=0; i2=0; i3=0; i4=0;
  277.     while (0<1) {
  278.         videocursor(0,3,i);
  279.         c = kbdin();
  280.         if (c == '\015') break;                /* carriage return exits */
  281.         switch (c) {
  282.         case '0':                    /* state */
  283.         ascrule[i0][i1][i2][i3][i4][0][0]='0';
  284.         ascrule[i0][i1][i2][i3][i4][0][1]='0';
  285.         ascrule[i0][i1][i2][i3][i4][1][0]='0';
  286.         ascrule[i0][i1][i2][i3][i4][1][1]='0';
  287.             i4++;
  288.         if (i4==KK) {i4=0; i3++;};
  289.         if (i3==KK) {i3=0; i2++;};
  290.         if (i2==KK) {i2=0; i1++;};
  291.         if (i1==KK) {i1=0; i0++;};
  292.         if (i0==KK) {i0=0; };
  293.             videocattr(0,c,3,1);
  294.             if (i<6+DS) i++;
  295.             break;
  296.         case '1':                    /* state */
  297.         ascrule[i0][i1][i2][i3][i4][0][0]='1';
  298.         ascrule[i0][i1][i2][i3][i4][0][1]='0';
  299.         ascrule[i0][i1][i2][i3][i4][1][0]='0';
  300.         ascrule[i0][i1][i2][i3][i4][1][1]='0';
  301.             i4++;
  302.         if (i4==KK) {i4=0; i3++;};
  303.         if (i3==KK) {i3=0; i2++;};
  304.         if (i2==KK) {i2=0; i1++;};
  305.         if (i1==KK) {i1=0; i0++;};
  306.         if (i0==KK) {i0=0; };
  307.             videocattr(0,c,3,1);
  308.             if (i<6+DS) i++;
  309.             break;
  310.         case '2':                    /* state */
  311.         ascrule[i0][i1][i2][i3][i4][0][0]='0';
  312.         ascrule[i0][i1][i2][i3][i4][0][1]='1';
  313.         ascrule[i0][i1][i2][i3][i4][1][0]='0';
  314.         ascrule[i0][i1][i2][i3][i4][1][1]='0';
  315.             i4++;
  316.         if (i4==KK) {i4=0; i3++;};
  317.         if (i3==KK) {i3=0; i2++;};
  318.         if (i2==KK) {i2=0; i1++;};
  319.         if (i1==KK) {i1=0; i0++;};
  320.         if (i0==KK) {i0=0; };
  321.             videocattr(0,c,3,1);
  322.             if (i<6+DS) i++;
  323.             break;
  324.         case '3':                    /* state */
  325.         ascrule[i0][i1][i2][i3][i4][0][0]='1';
  326.         ascrule[i0][i1][i2][i3][i4][0][1]='1';
  327.         ascrule[i0][i1][i2][i3][i4][1][0]='0';
  328.         ascrule[i0][i1][i2][i3][i4][1][1]='0';
  329.             i4++;
  330.         if (i4==KK) {i4=0; i3++;};
  331.         if (i3==KK) {i3=0; i2++;};
  332.         if (i2==KK) {i2=0; i1++;};
  333.         if (i1==KK) {i1=0; i0++;};
  334.         if (i0==KK) {i0=0; };
  335.             videocattr(0,c,3,1);
  336.             if (i<6+DS) i++;
  337.             break;
  338.         case '4':                    /* state */
  339.         ascrule[i0][i1][i2][i3][i4][0][0]='0';
  340.         ascrule[i0][i1][i2][i3][i4][0][1]='0';
  341.         ascrule[i0][i1][i2][i3][i4][1][0]='1';
  342.         ascrule[i0][i1][i2][i3][i4][1][1]='0';
  343.             i4++;
  344.         if (i4==KK) {i4=0; i3++;};
  345.         if (i3==KK) {i3=0; i2++;};
  346.         if (i2==KK) {i2=0; i1++;};
  347.         if (i1==KK) {i1=0; i0++;};
  348.         if (i0==KK) {i0=0; };
  349.             videocattr(0,c,3,1);
  350.             if (i<6+DS) i++;
  351.             break;
  352.         case '5':                    /* state */
  353.         ascrule[i0][i1][i2][i3][i4][0][0]='1';
  354.         ascrule[i0][i1][i2][i3][i4][0][1]='0';
  355.         ascrule[i0][i1][i2][i3][i4][1][0]='1';
  356.         ascrule[i0][i1][i2][i3][i4][1][1]='0';
  357.             i4++;
  358.         if (i4==KK) {i4=0; i3++;};
  359.         if (i3==KK) {i3=0; i2++;};
  360.         if (i2==KK) {i2=0; i1++;};
  361.         if (i1==KK) {i1=0; i0++;};
  362.         if (i0==KK) {i0=0; };
  363.             videocattr(0,c,3,1);
  364.             if (i<6+DS) i++;
  365.             break;
  366.         case '6':                    /* state */
  367.         ascrule[i0][i1][i2][i3][i4][0][0]='0';
  368.         ascrule[i0][i1][i2][i3][i4][0][1]='1';
  369.         ascrule[i0][i1][i2][i3][i4][1][0]='1';
  370.         ascrule[i0][i1][i2][i3][i4][1][1]='0';
  371.             i4++;
  372.         if (i4==KK) {i4=0; i3++;};
  373.         if (i3==KK) {i3=0; i2++;};
  374.         if (i2==KK) {i2=0; i1++;};
  375.         if (i1==KK) {i1=0; i0++;};
  376.         if (i0==KK) {i0=0; };
  377.             videocattr(0,c,3,1);
  378.             if (i<6+DS) i++;
  379.             break;
  380.         case '7':                    /* state */
  381.         ascrule[i0][i1][i2][i3][i4][0][0]='1';
  382.         ascrule[i0][i1][i2][i3][i4][0][1]='1';
  383.         ascrule[i0][i1][i2][i3][i4][1][0]='1';
  384.         ascrule[i0][i1][i2][i3][i4][1][1]='0';
  385.             i4++;
  386.         if (i4==KK) {i4=0; i3++;};
  387.         if (i3==KK) {i3=0; i2++;};
  388.         if (i2==KK) {i2=0; i1++;};
  389.         if (i1==KK) {i1=0; i0++;};
  390.         if (i0==KK) {i0=0; };
  391.             videocattr(0,c,3,1);
  392.             if (i<6+DS) i++;
  393.             break;
  394.         case '8':                    /* state */
  395.         ascrule[i0][i1][i2][i3][i4][0][0]='0';
  396.         ascrule[i0][i1][i2][i3][i4][0][1]='0';
  397.         ascrule[i0][i1][i2][i3][i4][1][0]='0';
  398.         ascrule[i0][i1][i2][i3][i4][1][1]='1';
  399.             i4++;
  400.         if (i4==KK) {i4=0; i3++;};
  401.         if (i3==KK) {i3=0; i2++;};
  402.         if (i2==KK) {i2=0; i1++;};
  403.         if (i1==KK) {i1=0; i0++;};
  404.         if (i0==KK) {i0=0; };
  405.             videocattr(0,c,3,1);
  406.             if (i<6+DS) i++;
  407.             break;
  408.         case '9':                    /* state */
  409.         ascrule[i0][i1][i2][i3][i4][0][0]='1';
  410.         ascrule[i0][i1][i2][i3][i4][0][1]='0';
  411.         ascrule[i0][i1][i2][i3][i4][1][0]='0';
  412.         ascrule[i0][i1][i2][i3][i4][1][1]='1';
  413.             i4++;
  414.         if (i4==KK) {i4=0; i3++;};
  415.         if (i3==KK) {i3=0; i2++;};
  416.         if (i2==KK) {i2=0; i1++;};
  417.         if (i1==KK) {i1=0; i0++;};
  418.         if (i0==KK) {i0=0; };
  419.             videocattr(0,c,3,1);
  420.             if (i<6+DS) i++;
  421.             break;
  422.         case 'A': case 'a':                /* state */
  423.         ascrule[i0][i1][i2][i3][i4][0][0]='0';
  424.         ascrule[i0][i1][i2][i3][i4][0][1]='1';
  425.         ascrule[i0][i1][i2][i3][i4][1][0]='0';
  426.         ascrule[i0][i1][i2][i3][i4][1][1]='1';
  427.             i4++;
  428.         if (i4==KK) {i4=0; i3++;};
  429.         if (i3==KK) {i3=0; i2++;};
  430.         if (i2==KK) {i2=0; i1++;};
  431.         if (i1==KK) {i1=0; i0++;};
  432.         if (i0==KK) {i0=0; };
  433.             videocattr(0,c,3,1);
  434.             if (i<6+DS) i++;
  435.             break;
  436.         case 'B': case 'b':                /* state */
  437.         ascrule[i0][i1][i2][i3][i4][0][0]='1';
  438.         ascrule[i0][i1][i2][i3][i4][0][1]='1';
  439.         ascrule[i0][i1][i2][i3][i4][1][0]='0';
  440.         ascrule[i0][i1][i2][i3][i4][1][1]='1';
  441.             i4++;
  442.         if (i4==KK) {i4=0; i3++;};
  443.         if (i3==KK) {i3=0; i2++;};
  444.         if (i2==KK) {i2=0; i1++;};
  445.         if (i1==KK) {i1=0; i0++;};
  446.         if (i0==KK) {i0=0; };
  447.             videocattr(0,c,3,1);
  448.             if (i<6+DS) i++;
  449.             break;
  450.         case 'C': case 'c':                /* state */
  451.         ascrule[i0][i1][i2][i3][i4][0][0]='0';
  452.         ascrule[i0][i1][i2][i3][i4][0][1]='0';
  453.         ascrule[i0][i1][i2][i3][i4][1][0]='1';
  454.         ascrule[i0][i1][i2][i3][i4][1][1]='1';
  455.             i4++;
  456.         if (i4==KK) {i4=0; i3++;};
  457.         if (i3==KK) {i3=0; i2++;};
  458.         if (i2==KK) {i2=0; i1++;};
  459.         if (i1==KK) {i1=0; i0++;};
  460.         if (i0==KK) {i0=0; };
  461.             videocattr(0,c,3,1);
  462.             if (i<6+DS) i++;
  463.             break;
  464.         case 'D': case 'd':                /* state */
  465.         ascrule[i0][i1][i2][i3][i4][0][0]='1';
  466.         ascrule[i0][i1][i2][i3][i4][0][1]='0';
  467.         ascrule[i0][i1][i2][i3][i4][1][0]='1';
  468.         ascrule[i0][i1][i2][i3][i4][1][1]='1';
  469.             i4++;
  470.         if (i4==KK) {i4=0; i3++;};
  471.         if (i3==KK) {i3=0; i2++;};
  472.         if (i2==KK) {i2=0; i1++;};
  473.         if (i1==KK) {i1=0; i0++;};
  474.         if (i0==KK) {i0=0; };
  475.             videocattr(0,c,3,1);
  476.             if (i<6+DS) i++;
  477.             break;
  478.         case 'E': case 'e':                /* state */
  479.         ascrule[i0][i1][i2][i3][i4][0][0]='0';
  480.         ascrule[i0][i1][i2][i3][i4][0][1]='1';
  481.         ascrule[i0][i1][i2][i3][i4][1][0]='1';
  482.         ascrule[i0][i1][i2][i3][i4][1][1]='1';
  483.             i4++;
  484.         if (i4==KK) {i4=0; i3++;};
  485.         if (i3==KK) {i3=0; i2++;};
  486.         if (i2==KK) {i2=0; i1++;};
  487.         if (i1==KK) {i1=0; i0++;};
  488.         if (i0==KK) {i0=0; };
  489.             videocattr(0,c,3,1);
  490.             if (i<6+DS) i++;
  491.             break;
  492.         case 'F': case 'f':                /* state */
  493.         ascrule[i0][i1][i2][i3][i4][0][0]='1';
  494.         ascrule[i0][i1][i2][i3][i4][0][1]='1';
  495.         ascrule[i0][i1][i2][i3][i4][1][0]='1';
  496.         ascrule[i0][i1][i2][i3][i4][1][1]='1';
  497.             i4++;
  498.         if (i4==KK) {i4=0; i3++;};
  499.         if (i3==KK) {i3=0; i2++;};
  500.         if (i2==KK) {i2=0; i1++;};
  501.         if (i1==KK) {i1=0; i0++;};
  502.         if (i0==KK) {i0=0; };
  503.             videocattr(0,c,3,1);
  504.             if (i<6+DS) i++;
  505.             break;
  506.         case ' ': case '\315':                /* space = advance */
  507.             i4++;
  508.         if (i4==KK) {i4=0; i3++;};
  509.         if (i3==KK) {i3=0; i2++;};
  510.         if (i2==KK) {i2=0; i1++;};
  511.         if (i1==KK) {i1=0; i0++;};
  512.         if (i0==KK) {i0=0; };
  513.             if (i<6+DS) i++;
  514.             break;
  515.         case '\010': case '\313':            /* backspace */
  516.         if (i4!=0) i4--; else {i4=KK-1;
  517.         if (i3!=0) i3--; else {i3=KK-1;
  518.         if (i2!=0) i2--; else {i2=KK-1;
  519.         if (i1!=0) i1--; else {i1=KK-1;
  520.         if (i0!=0) i0--; else {i0=KK-1;
  521.         };};};};};
  522.             if (i>6) i--;
  523.             break;
  524.     default: break;
  525.         };
  526.     };
  527. }
  528.  
  529. /* edit totalistic rule */
  530. edtrule() {char c; int  i;
  531.     i=0;
  532.     while (i<TS) {
  533.     c=trule[i];
  534.     videocursor(0,3,56+i);
  535.         videocattr(0,c,3,1);
  536.         c = kbdin();
  537.         if (c == '\015') break;
  538.         switch (c) {
  539.           case '0': case '1':                /* state */
  540.             trule[i]=c;
  541.             videocattr(0,c,5,1);
  542.         i++; break;
  543.           case ' ': case '\315':            /* space = advance */
  544.         i++; break;
  545.           case '\010': case '\313':            /* backspace */
  546.             if (i!=0) i--;
  547.         break;
  548.       default: break;
  549.           };
  550.     };
  551. }
  552.  
  553. /* edit the line */
  554. edline() {
  555. char c;
  556. int  i, j, k, ii, jj;
  557.  
  558.     videocursor(0,19,0);
  559.     scrstr("insert states using 0, 1");
  560.     videocursor(0,20,0);
  561.     scrstr("move cursor with n(north), s(south), e(east), w(west), or");
  562.     videocursor(0,21,0);
  563.     scrstr("with keyboard arrows. Space, backspace move right and left.");
  564.     videocursor(0,22,0);
  565.     scrstr("( seeks left margin, < absolutely, { up one line, [ down one line");
  566.     videocursor(0,23,0);
  567.     scrstr(") seeks right margin, > absolutely, } up one line, ] down one line");
  568.     videocursor(0,24,0);
  569.     scrstr("carriage return exits");
  570.     jj=4;
  571.     ii=1;
  572.     while (0<1) {
  573.     ii=lim(1,ii,40);
  574.     jj=lim(1,jj,8);
  575.     j=jj-1;
  576.     i=ii-1;
  577.     videocursor(0,j+9,i);
  578.     c=kbdin();
  579.     if (c == '\015') {videoscroll(19,0,24,70,0,3); break;};
  580.     switch (c) {
  581.     case '0':  case '1':        /* enter  state */
  582.        arr1[40*j+i]=c-'0'; ii++; break;
  583.     case 's': case '\012': case '\320':          jj++; break;    /* down - next line */
  584.     case 'n': case '\013': case '\310':          jj--; break;    /* up   - last line */
  585.     case 'e': case '\014': case '\315': case ' ': ii++; break;    /* space = advance  */
  586.     case 'w': case '\010': case '\313':          ii--; break;    /* backspace */
  587.     case '<': ii=1;  jj=1;  break;  /* absolute left */
  588.     case '{': ii=1;  jj--;  break;  /* left one row up */
  589.     case '(': ii=1;         break;  /* left this row */
  590.     case '[': ii=1;  jj++;  break;  /* left next row */
  591.     case '>': ii=40; jj=40; break;  /* absolute right */
  592.     case '}': ii=40; jj--;  break;  /* right one row up */
  593.     case ')': ii=40;        break;  /* right this row */
  594.     case ']': ii=40; jj++;  break;  /* right next row */
  595.     default: break;
  596.         };
  597.     videocursor(0,j+9,0);
  598.     for (k=0; k<40; k++) videoputc('0'+arr1[40*j+k],1);
  599.     };
  600. }
  601.  
  602. /* display a screen of evolution */
  603. evolve(rule) char *rule; {
  604. int i0, i1, i2, i3, i4, i5, i6, i, j;
  605.   videomode(COLGRAF);                    /* erase the screen */
  606.   videocursor(0,0,0);                    /* top text line */
  607.   scrstr(":");
  608.   scrrul();
  609.   for (i=0; i<DS; i++) {arule[i] = rule[i]-'0';};
  610.   for (i0=0; i0<KK; i0++) {
  611.   for (i1=0; i1<KK; i1++) {
  612.   for (i2=0; i2<KK; i2++) {
  613.   for (i3=0; i3<KK; i3++) {
  614.   for (i4=0; i4<KK; i4++) {
  615.   for (i5=0; i5<KK; i5++) {
  616.   for (i6=0; i6<KK; i6++) {
  617.     binrule[i0][i1][i2][i3][i4][i5][i6]=ascrule[i0][i1][i2][i3][i4][i5][i6]-'0';
  618.     };};};};};};};
  619.   for (j=8; j<200; j++) videodot(j,AL-1,2);
  620.   for (j=8; j<200; j++) {                /* evolve for 192 generations */
  621.     arr2[0]=binrule[arr1[AL-3]][arr1[AL-2]][arr1[AL-1]][arr1[0]][arr1[1]][arr1[2]][arr1[3]];
  622.     arr2[1]=binrule[arr1[AL-2]][arr1[AL-1]][arr1[0]][arr1[1]][arr1[2]][arr1[3]][arr1[4]];
  623.     arr2[2]=binrule[arr1[AL-1]][arr1[0]][arr1[1]][arr1[2]][arr1[3]][arr1[4]][arr1[5]];
  624.     for (i=3; i<AL-3; i++) {
  625.       arr2[i]=binrule[arr1[i-3]][arr1[i-2]][arr1[i-1]][arr1[i]][arr1[i+1]][arr1[i+2]][arr1[i+3]]; };
  626.     arr2[AL-3]=binrule[arr1[AL-6]][arr1[AL-5]][arr1[AL-4]][arr1[AL-3]][arr1[AL-2]][arr1[AL-1]][arr1[0]];
  627.     arr2[AL-2]=binrule[arr1[AL-5]][arr1[AL-4]][arr1[AL-3]][arr1[AL-2]][arr1[AL-1]][arr1[0]][arr1[1]];
  628.     arr2[AL-1]=binrule[arr1[AL-4]][arr1[AL-3]][arr1[AL-2]][arr1[AL-1]][arr1[0]][arr1[1]][arr1[2]];
  629.   for (i=0; i<AL; i++) {videodot(j,i,arr1[i]); arr1[i]=arr2[i];};
  630.   if (kbdst()) {kbdin(); break;};
  631.       }
  632. }
  633.  
  634. /* generate a random line of cells in arr1 */
  635. ranlin() {int i, c;
  636. for (i=0; i<AL; i++) {
  637.   if (i%8 == 0) c=rand();
  638.   arr1[i]=c%2; c/=2;};
  639. }
  640.  
  641. /* tutorial and Help screen */
  642. tuto() {
  643.     videomode(T80X25);
  644.     videocursor(0,2,0);
  645.     scrstr("<Copyright (C) 1987 - H.V. McIntosh, G. Cisneros S.>");
  646.     videocursor(0,4,0);
  647.     scrstr("      ******* LIFE in One Dimension *******");
  648.     videocursor(0,6,0);
  649.     scrstr("Two States - Black(0), Cyan(1).");
  650.     videocursor(0,8,0);
  651.     scrstr("Third neighbors - three on each side, seven altogether.");
  652.     videocursor(0,10,0);
  653.     scrstr("Complete transition rule - random, edited, or stored.");
  654.     videocursor(0,12,0);
  655.     scrstr("Initial Cellular Array - random, edited, or patterned.");
  656.     videocursor(0,14,0);
  657.     scrstr("Some rules are fragile and require several tries before");
  658.     videocursor(0,15,0);
  659.     scrstr("manifesting an interesting evolutionary pattern.");
  660.     videocursor(0,17,0);
  661.     scrstr("Use any key to terminate a display in progress.");
  662.     videocursor(0,21,0);
  663.     scrstr("now, press any key to continue ...");
  664. }
  665.  
  666. /* rule menu */
  667. rmenu() {
  668.     videocursor(0,0,0);
  669.     scrstr("      ....1111....1111....1111....1111");
  670.     videocursor(0,1,0);
  671.     scrstr("      ..11..11..11..11..11..11..11..11");
  672.     videocursor(0,2,0);
  673.     scrstr("      01010101010101010101010101010101");
  674.     videocursor(0,3,0);
  675.     scrstr("Rule: ");
  676.     scrrul();
  677.     if (istot()==1) {scrstr("     "); printf("%5d",totonu(0));};
  678.     videocursor(0,5,0);
  679.     scrstr("    r(rule), l(line), #nn(stored rule), g(graph), q(quit),");
  680.     videocursor(0,6,0);
  681.     scrstr("             x(random rule), y(random line), u(unit line),");
  682.     videocursor(0,7,0);
  683.     scrstr("             @nn(tot/rule), $nn(dzn tot/rules), t(ed tot/rule).");
  684.     videocursor(0,5,0);
  685.     }
  686.  
  687. /* totalistic rule menu*/
  688. tmenu() {
  689.     videocursor(0,2,50);
  690.     scrstr("      0......1");
  691.     videocursor(0,3,50);
  692.     scrstr("rule: ");
  693.     tscrrul();
  694.     videocursor(0,3,56);
  695.     }
  696.  
  697. /* line menu */
  698. lmenu() {int i, j;
  699.     for (j=0; 40*j<AL; j++) {
  700.     videocursor(0,9+j,0);
  701.     for (i=0; i<40; i++) videoputc('0'+arr1[40*j+i],1);
  702.     }
  703.     videocursor(0,5,0); }
  704.  
  705. /* display rule number */
  706. xmenu(n) int n;
  707. {int i, nn;  
  708.     nn=sprintf(xx,"%3d",n);
  709.     videocursor(0,1,40);
  710.     for (i=0; i<nn; i++) videoputc(xx[i],1);
  711.     videocursor(0,1,40); }
  712.  
  713. /* clear screen space for rule number */
  714. xblnk() {
  715.     videocursor(0,1,40);
  716.     scrstr("    ");
  717.     videocursor(0,5,0); }
  718.  
  719. /* copy saved rule #n into active rule */
  720. xtoasc(n) int n; { int i0, i1, i2, i3, i4;
  721.     xmenu(n+1);
  722.     for (i0=0; i0<KK; i0++) {
  723.     for (i1=0; i1<KK; i1++) {
  724.     for (i2=0; i2<KK; i2++) {
  725.     for (i3=0; i3<KK; i3++) {
  726.     for (i4=0; i4<KK; i4++) {
  727.     switch (xrule[n][i0][i1][i2][i3][i4]) {
  728.       case '0':
  729.      ascrule[i0][i1][i2][i3][i4][0][0]='0';
  730.      ascrule[i0][i1][i2][i3][i4][0][1]='0';
  731.      ascrule[i0][i1][i2][i3][i4][1][0]='0';
  732.      ascrule[i0][i1][i2][i3][i4][1][1]='0';
  733.      break;
  734.       case '1':
  735.      ascrule[i0][i1][i2][i3][i4][0][0]='1';
  736.      ascrule[i0][i1][i2][i3][i4][0][1]='0';
  737.      ascrule[i0][i1][i2][i3][i4][1][0]='0';
  738.      ascrule[i0][i1][i2][i3][i4][1][1]='0';
  739.      break;
  740.       case '2':
  741.      ascrule[i0][i1][i2][i3][i4][0][0]='0';
  742.      ascrule[i0][i1][i2][i3][i4][0][1]='1';
  743.      ascrule[i0][i1][i2][i3][i4][1][0]='0';
  744.      ascrule[i0][i1][i2][i3][i4][1][1]='0';
  745.      break;
  746.       case '3':
  747.      ascrule[i0][i1][i2][i3][i4][0][0]='1';
  748.      ascrule[i0][i1][i2][i3][i4][0][1]='1';
  749.      ascrule[i0][i1][i2][i3][i4][1][0]='0';
  750.      ascrule[i0][i1][i2][i3][i4][1][1]='0';
  751.      break;
  752.       case '4':
  753.      ascrule[i0][i1][i2][i3][i4][0][0]='0';
  754.      ascrule[i0][i1][i2][i3][i4][0][1]='0';
  755.      ascrule[i0][i1][i2][i3][i4][1][0]='1';
  756.      ascrule[i0][i1][i2][i3][i4][1][1]='0';
  757.      break;
  758.       case '5':
  759.      ascrule[i0][i1][i2][i3][i4][0][0]='1';
  760.      ascrule[i0][i1][i2][i3][i4][0][1]='0';
  761.      ascrule[i0][i1][i2][i3][i4][1][0]='1';
  762.      ascrule[i0][i1][i2][i3][i4][1][1]='0';
  763.      break;
  764.       case '6':
  765.      ascrule[i0][i1][i2][i3][i4][0][0]='0';
  766.      ascrule[i0][i1][i2][i3][i4][0][1]='1';
  767.      ascrule[i0][i1][i2][i3][i4][1][0]='1';
  768.      ascrule[i0][i1][i2][i3][i4][1][1]='0';
  769.      break;
  770.       case '7':
  771.      ascrule[i0][i1][i2][i3][i4][0][0]='1';
  772.      ascrule[i0][i1][i2][i3][i4][0][1]='1';
  773.      ascrule[i0][i1][i2][i3][i4][1][0]='1';
  774.      ascrule[i0][i1][i2][i3][i4][1][1]='0';
  775.      break;
  776.       case '8':
  777.      ascrule[i0][i1][i2][i3][i4][0][0]='0';
  778.      ascrule[i0][i1][i2][i3][i4][0][1]='0';
  779.      ascrule[i0][i1][i2][i3][i4][1][0]='0';
  780.      ascrule[i0][i1][i2][i3][i4][1][1]='1';
  781.      break;
  782.       case '9':
  783.      ascrule[i0][i1][i2][i3][i4][0][0]='1';
  784.      ascrule[i0][i1][i2][i3][i4][0][1]='0';
  785.      ascrule[i0][i1][i2][i3][i4][1][0]='0';
  786.      ascrule[i0][i1][i2][i3][i4][1][1]='1';
  787.      break;
  788.       case 'A':
  789.      ascrule[i0][i1][i2][i3][i4][0][0]='0';
  790.      ascrule[i0][i1][i2][i3][i4][0][1]='1';
  791.      ascrule[i0][i1][i2][i3][i4][1][0]='0';
  792.      ascrule[i0][i1][i2][i3][i4][1][1]='1';
  793.      break;
  794.       case 'B':
  795.      ascrule[i0][i1][i2][i3][i4][0][0]='1';
  796.      ascrule[i0][i1][i2][i3][i4][0][1]='1';
  797.      ascrule[i0][i1][i2][i3][i4][1][0]='0';
  798.      ascrule[i0][i1][i2][i3][i4][1][1]='1';
  799.      break;
  800.       case 'C':
  801.      ascrule[i0][i1][i2][i3][i4][0][0]='0';
  802.      ascrule[i0][i1][i2][i3][i4][0][1]='0';
  803.      ascrule[i0][i1][i2][i3][i4][1][0]='1';
  804.      ascrule[i0][i1][i2][i3][i4][1][1]='1';
  805.      break;
  806.       case 'D':
  807.      ascrule[i0][i1][i2][i3][i4][0][0]='1';
  808.      ascrule[i0][i1][i2][i3][i4][0][1]='0';
  809.      ascrule[i0][i1][i2][i3][i4][1][0]='1';
  810.      ascrule[i0][i1][i2][i3][i4][1][1]='1';
  811.      break;
  812.       case 'E':
  813.      ascrule[i0][i1][i2][i3][i4][0][0]='0';
  814.      ascrule[i0][i1][i2][i3][i4][0][1]='1';
  815.      ascrule[i0][i1][i2][i3][i4][1][0]='1';
  816.      ascrule[i0][i1][i2][i3][i4][1][1]='1';
  817.      break;
  818.       case 'F':
  819.      ascrule[i0][i1][i2][i3][i4][0][0]='1';
  820.      ascrule[i0][i1][i2][i3][i4][0][1]='1';
  821.      ascrule[i0][i1][i2][i3][i4][1][0]='1';
  822.      ascrule[i0][i1][i2][i3][i4][1][1]='1';
  823.      break;
  824.       default:
  825.      break;
  826.      };
  827.     };};};};}; }
  828.  
  829. /* change totalistic rule to general rule */
  830. totoasc() {
  831. int i0, i1, i2, i3, i4, i5, i6;
  832. for (i0=0; i0<3; i0++) {
  833. for (i1=0; i1<3; i1++) {
  834. for (i2=0; i2<3; i2++) {
  835. for (i3=0; i3<3; i3++) {
  836. for (i4=0; i4<3; i4++) {
  837. for (i5=0; i5<3; i5++) {
  838. for (i6=0; i6<3; i6++) {
  839. ascrule[i0][i1][i2][i3][i4][i5][i6]=trule[i0+i1+i2+i3+i4+i5+i6];
  840. };};};};};};};
  841. }
  842.  
  843. /* change decimal totalistic rule to sum values */
  844. nutoto(x) int x; {int i;
  845. for (i=0; i<TS; i++) {trule[i]=x%2+'0'; x/=2;};}
  846.  
  847. /* change sum values to decimal totalistic rule */
  848. int totonu(i) int i; {int r;
  849.   if (i<TS) r=(trule[i]-'0')+2*totonu(i+1); else r=0;
  850.   return r; }
  851.  
  852. /* test whether a rule is totalistic */
  853. int istot() {int i0, i1, i2, i3, i4, i5, i6, l;
  854.     l=1;
  855.     trule[0]=ascrule[0][0][0][0][0][0][0];
  856.     trule[1]=ascrule[1][0][0][0][0][0][0];
  857.     trule[2]=ascrule[1][1][0][0][0][0][0];
  858.     trule[3]=ascrule[1][1][1][0][0][0][0];
  859.     trule[4]=ascrule[1][1][1][1][0][0][0];
  860.     trule[5]=ascrule[1][1][1][1][1][0][0];
  861.     trule[6]=ascrule[1][1][1][1][1][1][0];
  862.     trule[7]=ascrule[1][1][1][1][1][1][1];
  863.     for (i0=0; i0<KK; i0++) {
  864.     for (i1=0; i1<KK; i1++) {
  865.     for (i2=0; i2<KK; i2++) {
  866.     for (i3=0; i3<KK; i3++) {
  867.     for (i4=0; i4<KK; i4++) {
  868.     for (i5=0; i5<KK; i5++) {
  869.     for (i6=0; i6<KK; i6++) {
  870.     if (ascrule[i0][i1][i2][i3][i4][i5][i6]!=trule[i0+i1+i2+i3+i4+i5+i6]) l=0;      
  871.     };};};};};};};
  872.     return l; }
  873.  
  874. /* limit j to interval (i,k) */
  875. int lim(i,j,k) int i, j, k;
  876.     {if (i>=j) return i; if (k<=j) return k; return j;}
  877.  
  878. /* display the rule number on the screen */
  879. scrrul() {char i; int i0, i1, i2, i3, i4;
  880.   for (i0=0; i0<KK; i0++) {
  881.   for (i1=0; i1<KK; i1++) {
  882.   for (i2=0; i2<KK; i2++) {
  883.   for (i3=0; i3<KK; i3++) {
  884.   for (i4=0; i4<KK; i4++) {
  885.   i='0'+(ascrule[i0][i1][i2][i3][i4][0][0]-'0')+
  886.       2*(ascrule[i0][i1][i2][i3][i4][0][1]-'0')+
  887.       4*(ascrule[i0][i1][i2][i3][i4][1][0]-'0')+
  888.       8*(ascrule[i0][i1][i2][i3][i4][1][1]-'0');
  889.   if (i>'9') i=i+('A'-':');
  890.   videoputc(i,1);      
  891.   };};};};}; }
  892.  
  893. /* display totalistic rule number by sum */
  894. tscrrul() {int i;
  895.   for (i=0; i<TS; i++) {videoputc(trule[i]); }; }
  896.  
  897. /* write a string in graphics mode */
  898. scrstr(s) char *s;
  899.   {for (; *s != '\0'; s++) videoputc(*s,1); }
  900.  
  901. /* keyboard status */
  902. int kbdst() {return(bdos(11) & 0xFF);}
  903.  
  904. /* direct keyboard input, no echo */
  905. kbdin() {int c;
  906.   if ((c = bdos(7) & 0xFF) == '\0') c = (bdos(7) & 0xFF) | 0x80;
  907.   return(c);
  908. }
  909.  
  910. /* read number from keyboard */
  911. int numin(n) int n; {char c;
  912.   c=kbdin();
  913.   if (c>='0'&&c<='9') return(numin(10*n+(c-'0'))); else return(n);
  914. }
  915.  
  916. /* end */
  917.