This program is best run in Processing on a computer. The above video is compressed, thus losing much of the complexity of the program. Code for running locally can be found below.

The program creates an interesting amount of complexity and quickly reaches a dynamic (cells are always changing and unpredictable), but stable (some patterns emerge, but it never become a solid color) state. It is easy to tweak the rules and variable to create new configurations.

RULES:

CODE (TO RUN IN PROCESSING):
int vwidth = 720;
int vheight = 480;

void setup(){
    size(vwidth,vheight);
    colorMode(HSB,360,100,250);
    setPixels();
    frameRate(30);
}

void draw(){
  changePixels();
}  

void changePixels() {
  loadPixels();
  for (int i = 1; i < vwidth*vheight-1; i++){
    color c = pixels[i];
    color cprev = pixels[i-1];
    color cnext = pixels[i+1];
    c = int(brightness(c));
    cprev = int(brightness(cprev));
    cnext = int(brightness(cnext));
    if (cprev + cnext > 250) {
      pixels[i] = color(220,100,c-5);
    } else if (cprev + cnext < 250) {  
      pixels[i] = color(220,100,c+5);
    }
  
    if (cprev + cnext > 460){
      pixels[i] = color(220,100,c+50);  
    } 
    if (cprev + cnext < 40){
      pixels[i] = color(220,100,c-50);  
    } 
  } 
 updatePixels(); 
}

void setPixels() {
  loadPixels();
  for (int i = 0; i < vwidth*vheight; i++){
    color setColor = color(220,100,random(0,250));
    pixels[i] = setColor; 
  }
  updatePixels();  
}    


CODE (FOR CREATING A .MOV FILE):
import processing.video.*;

MovieMaker mm;

PImage img;
int vwidth = 720;
int vheight = 480;

void setup(){
    size(vwidth,vheight);
    colorMode(HSB,360,100,250);
    setPixels();
    frameRate(30);
    
    mm = new MovieMaker(this,vwidth,vheight,"ca.mov", 30, MovieMaker.ANIMATION, MovieMaker.BEST);
    for (int i = 0; i < 480; i++){
      changePixels();
      if (i % 10 == 0) {
        println(i);
      }  
    mm.addFrame();
    }
    mm.finish();
}

void draw(){
}  

void changePixels() {
  loadPixels();
  for (int i = 1; i < vwidth*vheight-1; i++){
    color c = pixels[i];
    color cprev = pixels[i-1];
    color cnext = pixels[i+1];
    c = int(brightness(c));
    cprev = int(brightness(cprev));
    cnext = int(brightness(cnext));
    if (cprev + cnext > 250) {
      pixels[i] = color(220,100,c-5);
    } else if (cprev + cnext < 250) {  
      pixels[i] = color(220,100,c+5);
    }
  
    if (cprev + cnext > 460){
      pixels[i] = color(220,100,c+50);  
    } 
    if (cprev + cnext < 40){
      pixels[i] = color(220,100,c-50);  
    } 
  } 
 updatePixels(); 
}

void setPixels() {
  loadPixels();
  for (int i = 0; i < vwidth*vheight; i++){
    color setColor = color(220,100,random(0,250));
    pixels[i] = setColor; 
  }
  updatePixels();  
}