1D cellular automata - image output

1D cellular automata - image output

// 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