// Cellular automata
// Wolfram, "A New Kind of Science", Chapter 2 and 3.
// Michael Ashley / UNSW / 11-May-2003
#define displayWidth 640
#define maxSteps 480
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
/*
Each cell has a value of 0 or 1.
The value of a cell in the next generation depends on its current
value, and the values of the neighbouring two cells.
The calculation of the new value therefore depends on the values of
3 single-bit quantities, giving 8 possible alternative configurations.
The calculation can therefore be represented using a array giving the
8 possibilities. We call this array "rule".
*/
int rule[8];
typedef struct {
unsigned char cell[displayWidth + 2 * maxSteps];
} state;
void initialise(state * s) {
int i;
for (i = 0; i < (sizeof s->cell) / (sizeof s->cell[0]); i++) {
s->cell[i] = 0;
if (i == maxSteps + displayWidth / 2)
s->cell[i] = 1;
}
}
void createRule(int r[8], unsigned char n) {
int i;
for (i = 0; i < 8; i++) {
r[i] = 0x01 & (n >> i);
}
}
void applyRule(state * prev, state * next, int i) {
/* This function takes an existing state, prev, and applies the
evolution rule to the i'th element, returning the result in next. */
next->cell[i] = rule[prev->cell[i - 1] * 4 +
prev->cell[i] * 2 +
prev->cell[i + 1]];
}
void evolve(state * prev, state * next) {
/* Applies the rule to all elements (apart from the end-points) of
an existing state, prev, and returns the result in next. */
int i;
for (i = 1; i < (sizeof prev->cell) / (sizeof prev->cell[0]) - 1; i++) {
applyRule(prev, next, i);
}
}
void displayState(state * s) {
assert(displayWidth == write(1, &s->cell[maxSteps], displayWidth));
}
void usage(char *prog) {
printf("Usage: %s rule | display -size %dx%d -depth 1 gray:-
where rule is an integer between 0 and 255 inclusive\n",
prog, displayWidth, maxSteps);
exit(1);
}
int main(int argc, char **argv) {
int n, i;
state s0, s1;
assert(maxSteps % 2 == 0); // Ensure we have an even number of steps.
initialise(&s0);
initialise(&s1);
if (argc != 2 ||
1 != sscanf(argv[1], "%d", &n) ||
n < 0 ||
n > 255)
usage(argv[0]);
createRule(rule, n);
for (i = 0; i < maxSteps / 2; i++) {
displayState(&s0);
evolve(&s0, &s1);
displayState(&s1);
evolve(&s1, &s0);
}
return 0;
}
Interesting features of this program include:
And here are some examples of the output from this program:
Rule 2, a class 1 cellular automata
Rule 22, a class 2 cellular automata
Rule 30, a class 3 cellular automata
Rule 110, a class 4 cellular automata