--- title: "Cellular Automata" type: "article" slug: "cellular-automata" url: "http://localhost/article/cellular-automata/" markdown_url: "http://localhost/article/cellular-automata.md" published_at: "2025-11-20T07:24:36+00:00" modified_at: "2026-06-21T23:20:20+00:00" featured_image: url: "http://localhost/wp-content/uploads/2022/04/20230809-041332.jpg" excerpt: "Back in college, I was short 1/2 a unit from graduating. To make up the unit, I enrolled in a 1 unit Independent Study course. With hours left before the enrollment deadline, I picked what I thought was a weak but interesting subject, Cellular Automata (CA). Well, the more I researched the topic, the more…" category: - name: "QL Hacker's Journal" slug: "ql-hackers-journal" taxonomy: "category" url: "http://localhost/category/periodicals/ql-hackers-journal/" post_tag: - name: "C (programming language)" slug: "c-programming-language" taxonomy: "post_tag" url: "http://localhost/tag/c-programming-language/" - name: "Full Text" slug: "fulltext" taxonomy: "post_tag" url: "http://localhost/tag/fulltext/" - name: "Pascal (programming language)" slug: "pascal" taxonomy: "post_tag" url: "http://localhost/tag/pascal/" - name: "QL" slug: "ql" taxonomy: "post_tag" url: "http://localhost/tag/ql/" - name: "Superbasic (programming language)" slug: "superbasic-programming-language" taxonomy: "post_tag" url: "http://localhost/tag/superbasic-programming-language/" - name: "Type-in program" slug: "type-in-program" taxonomy: "post_tag" url: "http://localhost/tag/type-in-program/" model: - name: "Sinclair QL" slug: "sinclair-ql" taxonomy: "model" url: "http://localhost/model/sinclair-ql/" indiv: - name: "Tim Swenson" slug: "tim-swenson" taxonomy: "indiv" url: "http://localhost/indiv/tim-swenson/" publication_r: id: 33686 title: "QL Hacker’s Journal" type: "periodical" url: "http://localhost/periodical/ql-hackers-journal/" authors_r: - name: "Tim Swenson" slug: "tim-swenson" taxonomy: "indiv" url: "http://localhost/indiv/tim-swenson/" issue: "4" issues_articles: - id: 61540 title: "QL Hacker’s Journal 4" type: "issue" url: "http://localhost/issue/ql-hackers-journal-4/" pubdate: "July 1991" archive_link: true --- # Cellular Automata Back in college, I was short 1/2 a unit from graduating. To make up the unit, I enrolled in a 1 unit Independent Study course. With hours left before the enrollment deadline, I picked what I thought was a weak but interesting subject, Cellular Automata (CA). Well, the more I researched the topic, the more interesting the class became, and the more involved I became. The end result of the class was a paper on CA and a demonstration program. I originally wrote the program in Pascal, because Pascal was the language the college used in most of the undergrad courses. Later I translated the program to SuperBasic so I could utilize the full power of the QL. Since it ran so slow in SuperBasic, I decided to write it in C for speed. Before I go into the program, let me first explain what Cellular Automata is. CA is comprised of four items; an array (Cellular Space), a number of values for each cell in the array (States), a Neighborhood relation that defines how cells relate to each other, and a Transition Rule that defines how cells change from one state to another over time. One popular version of CA, is the Game of Life by John Conway. Here you have a 2 dimensional CA with 2 states and an 8 cell neighborhood. The Quanta library has a good version of this game (although it’s not considered a game by many). I focused on 1 dimensional CA (1DCA). This is where the array is only 1 dimensional and the array is displayed over time by plotting each new array below the previous one. This makes for some rather interesting displays. I could to on for pages about CA, but I hope you have the general idea. If you would like to know more, let me know and I’ll send you a copy of my college paper and copies of my references. The SuperBasic version of the program is the most complete. The C version is short and sweet, due to my lack of knowing how to do many things in C. The Pascal version is a little more advanced over the C version. I’m not too sure if the Pascal version is working 100%. My Pascal compiler is on long-term loan to a friend so I have not had the chance to compile it and try it out. It is written for the Metacomco Pascal compiler. ### SuperBASIC ``` 100 LET xmax = 512 110 alldone = 0 120 DIM world(xmax) 130 DIM rule(64,9,2) 140 WINDOW #1,512,256,0,0 150 PAPER #1,0 : INK #1,4 160 LET rule1 = 1 : LET cycle = 15 170 LET bloksiz = 2 180 IF alldone = 1 THEN STOP 190 CLS #1 200 CSIZE 2,1 210 PRINT " ONE DIMENSIONAL" 220 PRINT " CELLULAR AUTOMATA"\\ 230 CSIZE 0,0 240 PRINT \\ 250 LET tab = 20 260 PRINT TO tab;" M E N U " 270 PRINT TO tab;" --------------"\\ 280 PRINT TO tab;" 1] Load Rule File" 290 PRINT TO tab;" 2] Choose Rule To Use" 300 PRINT TO tab;" 3] Display Rule" 310 PRINT TO tab;" 4] Set Number of Cycles" 320 PRINT TO tab;" 5] Set Block Size" 330 PRINT TO tab;" 6] Run Automata" 340 PRINT TO tab;" 7] Instructions"\\ 350 INPUT TO tab;" Enter Choice : ";menu 360 SELect ON menu 370 ON menu = 1 380 loadrule 390 ON menu = 2 400 chooserule 410 ON menu = 3 420 displayrule 430 ON menu = 4 440 setcycles 450 ON menu = 5 460 setblock 470 ON menu = 6 480 startautomata 490 ON menu = 7 500 instruct 510 END SELect 520 GO TO 180 530 REMark ************************ 540 DEFine PROCedure loadrule 550 LOCal a$,b$,xx,yy 560 CLS #1 570 PRINT\\\\\\\\\\ 580 PRINT "Enter File Name to Load. Include Device Name (i.e MDV1_)"\\ 590 INPUT a$ 600 OPEN_IN #4,a$ 610 INPUT #4,b$ 620 INPUT #4,neighbor 630 INPUT #4,number 640 FOR xx = 1 TO number 650 INPUT #4,b$ 660 INPUT #4,b$ 670 FOR yy = 1 TO neighbor+1 680 rule(xx,yy,1) = b$(yy) 690 NEXT yy 700 INPUT #4,b$ 710 FOR yy = 1 TO neighbor+1 720 rule(xx,yy,2) = b$(yy) 730 NEXT yy 740 NEXT xx 750 CLOSE #4 760 END DEFine 770 REMark ********************** 780 DEFine PROCedure chooserule 790 CLS #1 800 PRINT\\\\\\\\\\ 810 PRINT "Enter Rule to Use. Enter the Nth Rule in the File." 820 INPUT rule1 830 PAUSE 20 840 END DEFine 850 REMark ********************* 860 DEFine PROCedure displayrule 870 LOCal xx 880 CLS #1 890 PRINT \\\\\\\ : PRINT TO 28;"R U L E ";rule1 900 PRINT TO 27;"-------------" 910 PRINT\ : PRINT TO 28; 920 FOR xx = 1 TO neighbor+1 930 PRINT rule(rule1,xx,1);" "; 940 NEXT xx 950 PRINT : PRINT TO 28; 960 FOR xx = 1 TO neighbor+1 970 PRINT rule(rule1,xx,2);" "; 980 NEXT xx 990 PRINT \\\\\ 1000 PRINT TO 20;"Enter Any Key to Continue" 1010 PAUSE 1020 END DEFine 1030 REMark ************************* 1040 DEFine PROCedure setcycles 1050 CLS #1 1060 PRINT\\\\\\\\\\ 1070 PRINT TO 15;"Enter Number of Cycles to Run Through" 1080 PRINT TO 15;" the Program Pauses"\\ 1090 INPUT cycle 1100 PAUSE 10 1110 END DEFine 1120 REMark ********************* 1130 DEFine PROCedure setblock 1140 CLS #1 1150 PRINT\\\\\\\\\\ 1160 PRINT TO 15;"Enter the Size of the Blocks to Use." 1170 PRINT TO 15;" ( 1 to 8 )"\\ 1180 INPUT bloksiz 1190 PAUSE 20 1200 END DEFine 1210 REMark ************************* 1220 DEFine PROCedure instruct 1230 CLS #1 : PRINT \\\\\ 1240 PRINT TO 10;" This program will run a cellular system through a specified rule." 1250 PRINT TO 10;"The program lets you choose the size of the blocks to display." 1260 PRINT TO 10;"This allows you to see in greater detail what is going on. Once" 1270 PRINT TO 10;"the program pauses, you may hit F1 to start to program over, or" 1280 PRINT TO 10;"you may hit F2 to stop the program. The program does not clear" 1290 PRINT TO 10;"the screen so that you may use a screen dump program to print " 1300 PRINT TO 10;"out the results. This will give you a hard copy for later ref-" 1310 PRINT TO 10;"erence." 1320 PRINT \\\\ : PRINT TO 30;"Hit Any Key To Continue" 1330 PAUSE 1340 END DEFine 1350 REMark ************************* 1360 DEFine PROCedure startautomata 1370 setinit 1380 count = 15 1390 CLS #1 1400 PRINT TO 15;"Neighborhood ";neighbor;" Rule ";rule1 1410 display 1420 up = -bloksiz 1430 REPeat done 1440 FOR loop = 1 TO cycle 1450 count = count + bloksiz 1460 IF count > 250 THEN 1470 count = 250 1480 SCROLL up,0 1490 END IF 1500 nextcycle 1510 display 1520 NEXT loop 1530 BEEP 150,4 1540 PAUSE 1550 LET key = KEYROW(0) 1560 IF key = 2 THEN EXIT done 1570 IF key = 8 THEN 1580 LET alldone = 1 1590 EXIT done 1600 END IF 1610 END REPeat done 1620 END DEFine 1630 REMark ************************ 1640 DEFine PROCedure getdata 1650 PRINT\\\\\\\\\\ 1660 PRINT TO 15;"Enter File Name of Set-up File to Load." 1670 PRINT TO 15;"Include Drive Name (i.e MDV1_ )"\\ 1680 INPUT a$ 1690 OPEN_IN #4,a$ 1700 INPUT #4,b$ 1710 LET world(b$)=1 1720 IF EOF(#4) THEN 1730 CLOSE #4 1740 RETurn 1750 ELSE 1760 GO TO 1700 1770 END IF 1780 END DEFine 1790 REMark ********************* 1800 DEFine PROCedure initialise1 1810 LOCal z, rand 1820 world(1) = 0 : world(xmax) = 0 1830 FOR z = 2 TO INT(xmax/bloksiz)-1 1840 LET rand = RND(1 TO 10) 1850 IF rand <4 THEN 1860 world(z) = 1 1870 ELSE 1880 world(z) = 0 1890 END IF 1900 NEXT z 1910 END DEFine 1920 REMark ************************ 1930 DEFine PROCedure initialise2 1940 LOCal xx 1950 FOR xx = 1 TO xmax 1960 world(xx) = 0 1970 NEXT xx 1980 END DEFine 1990 REMark *********************** 2000 DEFine PROCedure nextcycle 2010 LOCal start, finish, x, number 2020 start = neighbor/2 : finish=INT(xmax/bloksiz)-start 2030 FOR x = start TO finish 2040 number = ruleeval 2050 IF (number=1) AND (world(x)=0) THEN world(x)=2 2060 IF (number=0) AND (world(x)=1) THEN world(x)=3 2070 NEXT x 2080 END DEFine 2090 REMark ***************************** 2100 DEFine PROCedure display 2110 LOCal xx, xxx 2120 FOR xx = 1 TO INT(xmax/bloksiz)-1 2130 xxx = xx * bloksiz 2140 IF (world(xx)=1) OR (world(xx)=2) THEN BLOCK bloksiz,bloksiz,xxx,count,4 2150 IF world(xx) = 2 THEN world(xx) = 1 2160 IF world(xx) = 3 THEN world(xx) = 0 2170 NEXT xx 2180 END DEFine 2190 REMark ************************** 2200 DEFine FuNction neighborhood2 2210 LOCal count 2220 LET count = 0 2230 IF (world(x-1)=1) OR (world(x-1)=3) THEN count=count+1 2240 IF (world(x+1)=1) OR (world(x+1)=3) THEN count=count+1 2250 RETurn count 2260 END DEFine 2270 REMark ************************* 2280 DEFine FuNction neighborhood4 2290 LOCal count 2300 LET count = 0 2310 IF (world(x-2)=1) OR (world(x-2)=3) THEN count=count+1 2320 IF (world(x-1)=1) OR (world(x-1)=3) THEN count=count+1 2330 IF (world(x+1)=1) OR (world(x+1)=3) THEN count=count+1 2340 IF (world(x+2)=1) OR (world(x+2)=3) THEN count=count+1 2350 RETurn count 2360 END DEFine 2370 REMark ************************* 2380 DEFine FuNction neighborhood6 2390 LOCal count 2400 LET count = 0 2410 IF (world(x-3)=1) OR (world(x-3)=3) THEN count=count+1 2420 IF (world(x-2)=1) OR (world(x-2)=3) THEN count=count+1 2430 IF (world(x-1)=1) OR (world(x-1)=3) THEN count=count+1 2440 IF (world(x+1)=1) OR (world(x+1)=3) THEN count=count+1 2450 IF (world(x+2)=1) OR (world(x+2)=3) THEN count=count+1 2460 IF (world(x+3)=1) OR (world(x+3)=3) THEN count=count+1 2470 RETurn count 2480 END DEFine 2490 REMark ************************* 2500 DEFine FuNction ruleeval 2510 LOCal number, tempx 2520 SELect ON neighbor 2530 ON neighbor = 2 2540 number = neighborhood2 2550 ON neighbor = 4 2560 number = neighborhood4 2570 ON neighbor = 6 2580 number = neighborhood6 2590 END SELect 2600 tempx = world(x) 2610 RETurn rule(rule1, number+1, tempx+1) 2620 END DEFine 2630 REMark ************************* 2640 DEFine PROCedure setinit 2650 CLS #1 2660 PRINT\\\\\\ 2670 PRINT TO 20;"Method of Initialisation" 2680 PRINT TO 20;"------------------------"\\ 2690 PRINT TO 20;" 1] Load From a File" 2700 PRINT TO 20;" 2] Random "\\ 2710 PRINT TO 20;"Enter Way to Initialise"\\ 2720 INPUT init 2730 IF init = 1 THEN 2740 CLS #1 2750 initialise2 2760 getdata 2770 END IF 2780 IF init = 2 THEN initialise1 2790 END DEFine ``` Example Rule file for Neighborhood of 2. ``` Totalalistic Rules 2 7 Rule 1 100 100 Rule 2 010 010 Rule 3 110 110 Rule 4 001 001 Rule 5 101 101 Rule 6 011 011 Rule 7 111 111 ``` ### C ``` /* cell_c One Dimensional Cellular Automata (1DCA) This program is used to study 1DCA. It will only evaluate one rule at a time. It can be setup to start processing on a particular array or you may choose a random array. This program requires a rule file and optional an array file. The formats are below: Rule File: two lines of 1's or 0's, length equal to MAX_NEIGHBORHOOD. Sample: 011010 - Alive 001100 - Dead */ #include #include "flp2_rand_c" #define MAX_WORLD 516 #define MAX_NEIGHBORHOOD 5 #define MAX_Y 256 #define EOL LF int world_array[MAX_WORLD], alive_array[MAX_NEIGHBORHOOD], dead_array[MAX_NEIGHBORHOOD], y, fd; main() { int i; y = 0; printf("One Dimensional Cellular Automata\n"); printf(" Analysis Program\n"); printf("\n"); printf(" by Timothy Swenson\n"); printf("\n"); initrand(); load_rule(); init_array(); fd = fopen("scr_512x256a0x0","w"); if (fd == NULL) { printf("Error Opening Screen\n"); abort(1); } cls(fd); display(); ++y; for (i = 0; i < MAX_Y; ++i) { next_cycle(); display(); ++y; } } /*******************************************/ /* This procedure loads the rule from a */ /* file into two arrays; alive_array and */ /* dead_array. */ /*******************************************/ load_rule() { int rule_fd, count, c; char string[30]; puts("Enter Rule File to Load\n"); gets(string); rule_fd = fopen(string,"r"); if (rule_fd == NULL) { printf("Error Loading File"); abort(1); } count = 0; while ( (c = fgetc(rule_fd)) != EOL) { alive_array[count] = c-'0'; count++; } count = 0; while ( (c = fgetc(rule_fd)) != EOL) { dead_array[count] = c-'0'; count++; } fclose(rule_fd); } /************************************/ /* This procedures initalises the */ /* array randomly */ /************************************/ init_array() { int i,temp1[3], temp2[3]; char c; *temp2 = atof("0.45"); printf("Creating Random Array\n"); for (i=2; i 0) world_array[i] = 1; else world_array[i] = 0; } } /********************************/ /* This procedures diplays the */ /* current array below the */ /* previous array. */ /********************************/ display() { int i; for (i=2; i < MAX_WORLD-2; ++i) { if (world_array[i] == 1 || world_array[i] == 2) { world_array[i] = 1; block(fd,1,1,i-2,y,4); } else world_array[i] = 0; } } /***********************************/ /* This procedures evalutates the */ /* next cycle. */ /***********************************/ next_cycle() { int i, temp, result; for (i=2; i 250 THEN BEGIN COUNT := 250; ERR := SCREEN2(SCREENSCROLL,UP); END; NEXTCYCLE(RULENUM, NEIGHBOR, BLOKSIZ); DISPLAY(COUNT, BLOKSIZ); END; END; {@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@} {@@@@@@ M A I N P R O G R A M @@@@@@} {@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@} BEGIN MAXX := XMAX+1; MAXY :=256; ZERO := 0; CYCLE := 10; RULENUM := 1; BLOKSIZ := 1; ERR := WINDOW7(WINDOWDEFINE,MAXX,MAXY,ZERO,ZERO,ZERO,ZERO); ALLDONE := FALSE; WHILE NOT ALLDONE DO BEGIN ERR := SCREEN1(SCREENCLEAR); WRITELN(' C E L L U L A R A U T O M A T A'); WRITELN(' - O N E D I M E N S I O N A L - '); WRITELN; WRITELN(' By Timothy Swenson '); WRITELN; WRITELN(' When the program pauses between a number of cycles '); WRITELN(' you may hit any key to go on. Hit F1 to restart '); WRITELN(' the program. Hit F2 to end the program.'); WRITELN; WRITELN; WRITELN(' M E N U'); WRITELN; WRITELN(' 1] Load Rule File'); WRITELN(' 2] Choose Rule to use'); WRITELN(' 3] Set number of Cycles'); WRITELN(' 4] Set Block Size'); WRITELN(' 5] Run Automata '); WRITELN; WRITE(' Enter Choice : '); READLN( MENU ); CASE MENU OF 1 : GETRULES( NEIGHBOR ); 2 : BEGIN WRITELN; WRITELN; WRITELN(' Enter a rule to use: by number only '); WRITELN(' The Nth rule in the Rule file is the Nth Rule '); WRITELN(' and will be entered as such. '); READLN ( RULENUM ); END; 3 : BEGIN WRITELN; WRITELN('How many cycles to run through before a pause.'); READLN( CYCLE ); END; 4 : BEGIN WRITELN; WRITELN(' What size of blocks do you want for the display? '); WRITELN(' 1 is the smallest and 8 is the largest suggested '); READLN(BLOKSIZ); END; 5 : BEGIN SETINIT; ERR := SCREEN1(SCREENCLEAR); DONE := FALSE; COUNT := 15; WRITELN(' R U L E ',RULENUM); DISPLAY(COUNT, BLOKSIZ); UP := -BLOKSIZ; WHILE NOT DONE DO BEGIN MAINLOOP; KEY := READKEY; { once the program has cyclesd through the main loop for the desired number of loops, the program waits for a user input for what it should do next } IF KEY = 1256 THEN DONE := TRUE; { start the program again } IF KEY = 1260 THEN BEGIN { end the progam } ALLDONE := TRUE; DONE := TRUE; END; { If } END; { While done } END; { Case of 5} END; { Case total } END; { while alldone } { The program does not clear the screen. This leaves the results on the screen and ready to be dumped to the printer. This way I have a hard copy of the results. } END. ```