home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / theory / cellaut / 528 < prev    next >
Encoding:
Text File  |  1992-11-17  |  13.7 KB  |  560 lines

  1. Newsgroups: comp.theory.cell-automata
  2. Path: sparky!uunet!charon.amdahl.com!pacbell.com!decwrl!concert!gatech!news.ans.net!cmcl2!panix!james
  3. From: james@panix.com (James Britt)
  4. Subject: Wolfram CA C source code
  5. Message-ID: <1992Nov17.061208.16131@panix.com>
  6. Date: Tue, 17 Nov 1992 06:12:08 GMT
  7. Organization: PANIX Public Access Unix & Internet, NYC
  8. Lines: 550
  9.  
  10. /************************************************************************
  11.                     November 1992
  12.  
  13. This is a cellular automata that implements a line automata
  14. described in Stephan Wolfram's book, Theory and Aplications of
  15. Cellular Automata.  In this model, any cell in the array may have
  16. one of two states, 1 or 0.  The next state is determined by taking
  17. each cell, along with its immediate neighbors, and using the three
  18. bits to create a binary number:
  19.  
  20. i.e.,            |0|1|1|  -> 3
  21.         |1|1|0|  -> 6
  22.  
  23. So, unlike many automatas, the order of the bits matters.
  24.  
  25. This number is used to index the state transition rule table.  Three
  26. bits can create a number from 0 to 7, so each rule will be a string
  27. of 8 bits.  Thus, you can have 256 different rules.
  28.  
  29. This program gives you three options:
  30.  
  31. You can run the automata in "standard" mode, and see the results
  32. of any given rule table.  Or, you can "mesh" two almost-alike
  33. automata, and see how a small difference in the initial array
  34. propagates differences as time goes by.   This is something
  35. Wolfram does in his book.  He ran two automatas, each with the
  36. same rule, and same starting conditions, except that in the second
  37. one, he flipped a middle bit in the starting array.  Then, for
  38. each generation, he would compare the two arrays, and only display
  39. those cells where the two differed.  Aside from producing some
  40. interesting pictures, this allows you to see how the individual
  41. cells are dependant on each other for information propagation.
  42. This property is interesting to observe, and you may want to think
  43. about what it tells us about a given rule.
  44.  
  45. The third option is to display the standard CA with the
  46. difference pattern overlayed.
  47.  
  48. The code is written in Turbo C++, 3.0.  I've put the graphic routines
  49. in functions to make it easier to convert to whatever C you might
  50. have.  There a few features I would like to add at some point, such
  51. as saving a screen to a GIF file, and automatically executing each rule
  52. from 0 to 127, saving the results.
  53.  
  54. What I would really like to see is a project similar to Fractint, the
  55. large, public domain fractal program.  Fractint consists of a wide range
  56. of fractal routines, contributed by a numerous people.  The code and
  57. executable are re-distributed regularly as the program is updated.
  58.  
  59. Why not have a large, multi-function cellular automata program?  One
  60. that could produce Life; hodge-podge; multi-state line automata; "rug"
  61. generators, etc...
  62.  
  63. Anyway, here it is.
  64.  
  65.  
  66.  
  67.     James Britt
  68.     james@panix.com
  69.     (Compu$erve 73417,2776)
  70.  
  71.  
  72. ***********************************************************************/
  73.  
  74.  
  75. #include <dos.h>
  76. #include <math.h>
  77. #include <conio.h>
  78. #include <stdio.h>
  79. #include <stdlib.h>
  80. #include <graphics.h>
  81.  
  82. #define        ARRAYSIZE    640
  83.  
  84. typedef        struct
  85.         {
  86.             int    rulenumber;
  87.             int    choice;
  88.         } menu_struct;
  89.  
  90.  
  91. void    Menu( menu_struct *);
  92. void    GraphicsOn();
  93. void    GraphicsOff();
  94. void    InitStart();
  95. void    Update();
  96. void    Generate();
  97. void    Display( int *, int, int * );
  98. void    OverDisplay( int *, int, int * );
  99. void    ShowRule( int );
  100. void    SaveRule( int);
  101. void    ReadRule(int );
  102. void    MakeTable( int, int * );
  103. void    ClearScreen();
  104. void    Mesh( int *, int *, int * );
  105.  
  106. main(void)
  107. {
  108. menu_struct    menuchoice;
  109. int    YSIZE = 480;
  110. int    x, y, z;
  111. char    c, mesh, overlay;
  112. int    array1[ARRAYSIZE], array2[ARRAYSIZE];
  113. int    duplicate1[ARRAYSIZE], duplicate2[ARRAYSIZE], dub[ARRAYSIZE];
  114. int    ruletable[8], colors[2], colors2[2];
  115.  
  116.  
  117.  
  118.     clrscr();
  119.     y = 0;
  120.     colors[0] = WHITE;
  121.     colors[1] = CYAN;
  122.     colors2[0] = CYAN;
  123.     colors2[1] = RED;
  124.  
  125.     Menu( &menuchoice );
  126.  
  127.     MakeTable( menuchoice.rulenumber,  ruletable );
  128.     InitStart( array1, duplicate1 );
  129.     GraphicsOn();
  130.     while( 1 )
  131.     {
  132.         Generate( array1,  array2,  ruletable );
  133.  
  134.  
  135.         if( menuchoice.choice < 2 )
  136.             Display( array1,  y, colors );
  137.  
  138.         if( menuchoice.choice == 2 )
  139.         {
  140.             Generate( duplicate1,  duplicate2,  ruletable );
  141.             Mesh( array1,  duplicate1,  dub );
  142.             Display( dub,  y, colors2 );
  143.         }
  144.  
  145.         if( menuchoice.choice > 2 )
  146.         {
  147.             Generate( duplicate1,  duplicate2,  ruletable );
  148.             Mesh( array1,  duplicate1,  dub );
  149.             Display( array1,  y, colors );
  150.             OverDisplay( dub, y, colors2 );
  151.         }
  152.  
  153.  
  154.         y++;
  155.  
  156.         y%=YSIZE;
  157.  
  158.         if( y == 0 )
  159.             ClearScreen();
  160.  
  161.         Update( array1,  array2 );
  162.         Update( duplicate1, duplicate2 );
  163.         if( kbhit() )
  164.         {
  165.             c = getch();
  166.             if( c == 'x')
  167.             {
  168.                 GraphicsOff();
  169.                 return;
  170.             }
  171.             if( c == 's')
  172.                 ShowRule(  menuchoice.rulenumber  );
  173.             if( c == 'n')
  174.             {
  175.                 GraphicsOff();
  176.                 Menu( &menuchoice );
  177.                 MakeTable( menuchoice.rulenumber,  ruletable );
  178.                 InitStart( array1, duplicate1 );
  179.                 GraphicsOn();
  180.                 cleardevice();
  181.                 y = 1;
  182.             }
  183.  
  184.         }
  185.  
  186.  
  187.  
  188.     }
  189. //    GraphicsOff();
  190.  
  191. // return;
  192.  
  193. }    /* end main()  */
  194.  
  195. /**************************************************************************
  196. *
  197. * void    Menu( menu_struct *menuchoice )
  198. *
  199. * Displays the options for this automata, returning the user's choice.
  200. *
  201. ****************************************************************************/
  202.  
  203.  
  204. void    Menu( menu_struct    *menuchoice )
  205. {
  206.  
  207.     clrscr();
  208.     printf("\n                The Wolfram CA Program\n");
  209.     printf("\n            Please send comments to james@panix.com");
  210.     printf("\n\n\n\n");
  211.     printf("This automata has only two states: on and off.\n");
  212.     printf("Each cell has only two neighbors, left and right.\n");
  213.     printf("However, order matters.  |1|0|0| is different than |0|0|1|.\n");
  214.     printf("This allows 2^3 different states, 0 to 7 as writen in binary.\n");
  215.     printf("So, for each possible state, you must decide what the next \n");
  216.     printf("state will be. 2^8 different state tables, 0 to 255 as writen in binary.\n");
  217.     printf("\n\n\n");
  218.     printf("Please enter a number from 0 to 255 for the state table:");
  219.     scanf("%d", &menuchoice->rulenumber );
  220.     printf("\nPlease select a display choice:\n\n");
  221.     printf("1:    Show just the automata.\n");
  222.     printf("2:    Show just the difference pattern.\n");
  223.     printf("3:    Show the difference pattern overlayed on the automata.\n");
  224.     printf("\n? ");
  225.     scanf( "%d", &menuchoice->choice );
  226.     return;
  227. }
  228.  
  229. /**************************************************************************
  230. *
  231. * void    GraphicsOn()
  232. *
  233. * Initializes the graphics, TC++ style.
  234. *
  235. ****************************************************************************/
  236.  
  237. void    GraphicsOn()
  238. {
  239.  
  240.     int    ErrorCode;        /* Reports any graphics errors        */
  241.     int    GraphDriver;        /* The Graphics device driver        */
  242.     int    GraphMode;        /* The Graphics mode value        */
  243.  
  244.     GraphDriver = DETECT;         /* Request auto-detection    */
  245.     initgraph( &GraphDriver, &GraphMode, "" );
  246.     ErrorCode = graphresult();        /* Read result of initialization*/
  247.     if( ErrorCode != grOk ){        /* Error occured during init    */
  248.     printf(" Graphics System Error: %s\n", grapherrormsg( ErrorCode ) );
  249.     exit( 1 );
  250. }
  251.  
  252. return;
  253. }
  254. /**************************************************************************
  255. *
  256. *   void    GraphicsOff()
  257. *
  258. *   Turns off the graphics.
  259. *
  260. ****************************************************************************/
  261.  
  262. void    GraphicsOff()
  263. {
  264.     closegraph();
  265.     return;
  266. }
  267. /**************************************************************************
  268. *
  269. * void    InitStart( int array1[ARRAYSIZE], int    duplicate1[ARRAYSIZE] )
  270. *
  271. * Creates identical random starting arrays for the automatas, then
  272. * flips the middle bit in the duplicate array.
  273. *
  274. ****************************************************************************/
  275.  
  276. void    InitStart( int array1[ARRAYSIZE], int    duplicate1[ARRAYSIZE] )
  277. {
  278.     int    x, y, z;
  279.     for( x = 0; x < ARRAYSIZE; x++ )
  280.     {
  281.         array1[x] = rand()%2;
  282.         duplicate1[x] = array1[x];
  283.     }
  284.  
  285.     if(duplicate1[(int)ARRAYSIZE/2] == 1)
  286.         duplicate1[(int)ARRAYSIZE/2] = 0;
  287.     else
  288.         duplicate1[(int)ARRAYSIZE/2] = 1;
  289.     /*    flip middle bit    */
  290.  
  291.     return;
  292. }
  293.  
  294. /**************************************************************************
  295. *
  296. * void    ShowRule( int rulenumber  )
  297. *
  298. * Displays the current rule, and allows you to save the rule, plus a
  299. * brief description, to a file, by calling SaveRule().
  300. *
  301. ****************************************************************************/
  302.  
  303. void    ShowRule( int rulenumber  )
  304. {
  305.     char    c;
  306.  
  307.     GraphicsOff();
  308.     clrscr();
  309.     printf("\n\n\n\n");
  310.     printf("\The rule is %d", rulenumber );
  311.     printf("\nEnter 's' to save the rule.  Press any other key to continue.");
  312.     flushall();
  313.     c = getch();
  314.     if( c == 's')
  315.         SaveRule(rulenumber);
  316.  
  317.     GraphicsOn();
  318.  
  319.     return;
  320. }
  321. /**************************************************************************
  322. *
  323. * void    MakeTable( int rulenumber, int ruletable[8] )
  324. *
  325. * Creates the state transistion rule table from the rule number given
  326. * by the user.
  327. *
  328. ****************************************************************************/
  329.  
  330. void    MakeTable( int rulenumber, int ruletable[8] )
  331. {
  332.     int    x, MASK = 01;
  333.  
  334.     printf("%d looks like this: ", rulenumber);
  335.  
  336.     for( x = 0; x < 8; x++)
  337.     {
  338.         ruletable[x] = rulenumber&MASK;
  339.         rulenumber = rulenumber>>1;
  340.         printf("%d ", ruletable[x]);
  341.  
  342.     }
  343.     printf("\n");
  344.     delay(1000);
  345.     return;
  346. }
  347. /**************************************************************************
  348. *
  349. *  void      Update(int array1[], int array2[] )
  350. *
  351. *  Copies one array to another.
  352. *
  353. ****************************************************************************/
  354.  
  355. void    Update(int array1[], int array2[] )
  356. {
  357.     int    x;
  358.     for( x = 0; x < ARRAYSIZE; x++ )
  359.         array1[x] = array2[x];
  360.  
  361.     return;
  362. }
  363.  
  364. /**************************************************************************
  365. *
  366. * void    Generate(int array1[ARRAYSIZE], int array2[ARRAYSIZE], int ruletable[8] )
  367. *
  368. *  Creates the next line in the automata.
  369. *
  370. ****************************************************************************/
  371.  
  372. void    Generate(int array1[ARRAYSIZE], int array2[ARRAYSIZE], int ruletable[8] )
  373. {
  374.     int    x, number;
  375.     for( x = 1; x < ARRAYSIZE-1; x++ )
  376.     {
  377.      number = array1[x-1]*4 + array1[x]*2 + array1[x+1];
  378.      array2[x] = ruletable[number];
  379.     }
  380.                                             //    number = array1[ARRAYSIZE-1]*4 + array1[0]*2 + array1[1];      screen wrap
  381.     number =  array1[0]*2 + array1[1];
  382.     array2[0] = ruletable[number];
  383.  
  384.                                         //    number = array1[ARRAYSIZE-2]*4 + array1[ARRAYSIZE-1]*2 + array1[0];    screen wrap
  385.     number = array1[ARRAYSIZE-2]*4 + array1[ARRAYSIZE-1]*2;
  386.     array2[ARRAYSIZE-1] = ruletable[number];
  387.  
  388.     return;
  389. }
  390. /**************************************************************************
  391. *
  392. *  void    SaveRule( int  rulenumber )
  393. *
  394. *  Saves the rule ( by appending) to a file called "wolfca.dat"
  395. *
  396. *  (There should be a GetRule(), but...)
  397. ****************************************************************************/
  398.  
  399.  
  400. void    SaveRule( int  rulenumber )
  401. {
  402.     char    description[40];
  403.     FILE    *fp;
  404.  
  405.     printf("\nPlease enter a short description of the rule:");
  406.     gets( description );
  407.  
  408.     fp = fopen("wolfca.dat", "a" );
  409.     fprintf    (fp,"%d %s\n", rulenumber, description );
  410.     fclose(fp);
  411.  
  412.     return;
  413. }
  414. /**************************************************************************
  415. *
  416. * void    Display( int array1[ARRAYSIZE], int y, int colors[2] )
  417. *
  418. * Diplays the contents of the array to the screen.
  419. *
  420. ****************************************************************************/
  421.  
  422. void    Display( int array1[ARRAYSIZE], int y, int colors[2] )
  423. {
  424.     int    x;
  425.  
  426.     for( x = 0; x < ARRAYSIZE; x++ )
  427.         putpixel( x, y, colors[ array1[x] ]  );
  428.  
  429.  
  430. return;
  431.  
  432. }
  433.  
  434. /**************************************************************************
  435. *
  436. * void    OverDisplay( int array1[ARRAYSIZE], int y, int colors[2] )
  437. *
  438. * Diplays the contents of the mesh array to the screen, only plotting 1's.
  439. *
  440. ****************************************************************************/
  441.  
  442. void    OverDisplay( int array1[ARRAYSIZE], int y, int colors[2] )
  443. {
  444.     int    x;
  445.  
  446.     for( x = 0; x < ARRAYSIZE; x++ )
  447.     if( array1[x] == 1 )
  448.         putpixel( x, y, colors[ array1[x] ]  );
  449.  
  450.  
  451. return;
  452.  
  453. }
  454.  
  455. /**************************************************************************
  456. *
  457. *  void    ClearScreen()
  458. *
  459. *  Makes a beep sound, then waits for a keypress, then clears the
  460. *  graphics didplay.
  461. *
  462. ****************************************************************************/
  463.  
  464. void    ClearScreen()
  465. {
  466.       int    x;
  467.  
  468.       for( x = 0; x < 20000; x++ )
  469.       {
  470.          sound(2100);
  471.          sound(900);
  472.       }
  473.  
  474.       nosound();
  475.       getch();
  476.  
  477.       cleardevice();
  478.  
  479. return;
  480.  
  481. }
  482.  
  483. /**************************************************************************
  484. *
  485. * void    SaveScreen()
  486. *
  487. * Saves the contents of the screen to a file.
  488. * Not fully implemented yet.  Play with it!
  489. *
  490. ****************************************************************************/
  491.  
  492.  
  493.  
  494.  
  495. void    SaveScreen()
  496. {
  497.     #define    XSIZE    640/8
  498.     #define    YSIZE    480
  499.  
  500.     FILE        *fd;
  501.     int        x, y, z;
  502.     unsigned char    screen[XSIZE][YSIZE], bit;
  503.  
  504.  
  505.     for( y = 0; y < 480; y++ )
  506.         for( x = 0; x < 640; x+=8 )
  507.         {
  508.             for( z = 7; z > -1; z-- )
  509.             {
  510.                 bit = getpixel(x+z, y);
  511.                 bit = bit<<z;
  512.                 screen[x][y] = screen[x][y] | bit;
  513.             }
  514.  
  515.          }
  516.  
  517.        fd = fopen( "screen.dat", "wt" );
  518.  
  519.        for( y = 0; y < YSIZE; y++ )
  520.        {
  521.         for( x = 0; x < XSIZE; x++ )
  522.             fprintf( fd, "%c", screen[x][y] );
  523.  
  524.         fprintf( fd, "\n" );
  525.        }
  526.  
  527.        return;
  528. }    /*    end SaveScreen()    */
  529.  
  530. /**************************************************************************
  531. *
  532. *   void    Mesh( int array1[ARRAYSIZE], int duplicate1[ARRAYSIZE],
  533. *                     int dub[ARRAYSIZE] )
  534. *
  535. *   Compares the results of two arrays and puts the result in a third array.
  536. *
  537. ****************************************************************************/
  538.  
  539. void Mesh(int array1[ARRAYSIZE],int duplicate1[ARRAYSIZE],int dub[ARRAYSIZE] )
  540. {
  541.     int    x;
  542.     FILE    *fd;
  543.  
  544.     for( x = 0; x < ARRAYSIZE; x++)
  545.     {
  546.         if( array1[x] == duplicate1[x])
  547.             dub[x] = 0;
  548.         else
  549.             dub[x] = 1;
  550.     }
  551.  
  552.     return;
  553. }
  554.  
  555. -- 
  556. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  557. Just another speed-metal vegetarian anarchist cyberhippie Zen Socratic...
  558. Diblo Rules!                                        Hack The Wetware!
  559. james@panix.com  .............................................................
  560.