Cellular Automata 1D — CA with Random Ruleset

On Monday, Mar. 28, we did this illustration of the first half of Chapter 7. It is Exercise 7.1: CA with random ruleset.

Implementation

// This sketch implements Exercise 7.7 (wraparound) and
// Exercise 7.10 (probabilistic).
// It is not object-oriented. Instead, it builds on the version
// that Shiffman described in Section 7.7.

static final float overpopulation_probability_of_dying = 1.0; // Shiffman suggests trying 0.8
static final float loneliness_probability_of_dying = 1.0; // Shiffman suggests trying 0.6

static final int w = 5;

int rows;
int columns;
int[][] board;
int[][] next;

void setup() {
  size(600, 400);
  frameRate(5);
  rows = height / w;
  columns = width / w;
  board = new int[rows][columns];
  next = new int[rows][columns];

  for (int i = 0; i < rows; i++) {
    for (int j = 0; j < columns; j++) {
      board[i][j] = int(random(2));
    }
  }
}

void draw() {
  for (int i = 0; i < rows; i++) {
    for (int j = 0; j < columns; j++) {
      int neighbors = 0;
      for (int ii = -1; ii <= 1; ii++) {
        for (int jj = -1; jj <= 1; jj++) {
          // don't count self
          if (ii == 0 && jj == 0) continue;
          // implement wraparound
          int neighbor_i = (i + ii + rows) % rows;
          int neighbor_j = (j + jj + columns) % columns;
          neighbors += board[neighbor_i][neighbor_j];
        }
      }
      if (board[i][j] == 1 && neighbors < 2 && random(1) < loneliness_probability_of_dying) {
        next[i][j] = 0;
      } else if (board[i][j] == 1 && neighbors > 3 && random(1) < overpopulation_probability_of_dying) {
        next[i][j] = 0;
      } else if (board[i][j] == 0 && neighbors == 3) {
        next[i][j] = 1;
      } else {
        next[i][j] = board[i][j];
      }
    }
  }

  for (int i = 0; i < rows; i++) {
    for (int j = 0; j < columns; j++) {
      int before = board[i][j];
      int after = next[i][j];
      if (before == 0 && after == 0) {
        // println("dead");
        fill(0); // death is black
      } else if (before == 0 && after == 1) {
        // println("birth");
        fill(0, 0, 255); // birth is blue
      } else if (before == 1 && after == 0) {
        // println("dying");
        fill(255, 0, 0); // dying is red
      } else {
        // println("alive");
        fill(255); // alive is white
      }
      stroke(0);
      rect(j * w, i * w, w, w);
      board[i][j] = next[i][j];
    }
  }
}