After playing with binary cellular automata I thought I’d expand the script a little to accommodate more than two states of a pixel. Three loops are nested and each is iterated once for each state. If the index of each loop equals the three values above the current point the function returns the current state of a counter which is incremented in the innermost loop. In a binary system this is a little more complex than just testing each of the eight possible combinations, but is almost necessary when dealing with more states. I’ll post my code at the bottom of this post. But first, some pretty pictures.

processing cellular automata 4

processing cellular automata 3

processing cellular automata 2

processing cellular automata 5

processing cellular automata 1

My code. Straight up. I used Dan Shiffman’s example as a model and then went from there to add a few more features. Sorry the code isn’t annotated much but feel free to ask if you have any questions, and let me know if you make something cool with it.

processing code
code formatter
Cellular Automata

// Cellular Automata Script
// www.anthonymattox.com
// based on Dan Shiffman's example at
//      http://www.shiffman.net/teaching/nature/week7/
// added unlimited states of cells, colors, and keyboard control

cellsystem CS;

void setup() {
  size(1920,1200);
  background(0);
  CS=new cellsystem();
  noFill();
  noStroke();
  rectMode(CENTER);
  frameRate(100);
  smooth();
}

void draw() {
  CS.run();
}

//---------- Cellular Automata Class

class cellsystem{
  int States;
  int[] cells;
  int[] newGen;
  int[] rules;
  int gen;
  float Size;
  float RSize;

  cellsystem() {
    States=4;
    Size=10;
    RSize=8;
    cells=new int[int((width+Size)/Size)];
    newGen=new int[int((width+Size)/Size)];
    rules=new int[States*States*States];
    restart();
  }

  void restart() {
    gen=0;
    noiseSeed(int(random(500)));
    background(255);
    for (int i=0; i<rules.length; i++) {
      rules[i]=int(random(States));
    }
    for (int i=0; i<cells.length; i++) {
      cells[i]=constrain(int(noise(i/20)*States),0,States-1);
    }
  }

  void Continue() {
    gen=0;
    background(255);
  }

  void run() {
    if (finished()==false) {
      gen++;
      update();
      render();
    }

  }

  void render() {
    for (int i=0; i<cells.length; i++) {

      if (cells[i]==0) {
        fill(255);
        //stroke(255);
      } else if (cells[i]==1) {
        fill(255,10,0,180);
        //stroke(255,10,0,180);
      } else if (cells[i]==2) {
        fill(0,200,215,180);
        //stroke(0,200,215,180);
      } else{
        fill(0,220,160,180);
        //stroke(0,220,160,180);
      }

      ellipse(i*Size,gen*Size,RSize,RSize);
      //rect(i*Size,gen*Size,RSize,RSize);
    }
  }

  void update() {
    for (int i=1; i<newGen.length-1; i++) {
      int l=cells[i-1];
      int m=cells[i];
      int r=cells[i+1];
      newGen[i]=next(l,m,r);
    }
    cells=(int[]) newGen.clone();
  }

  int next(int l, int m, int r) {
    int n=0;
    for (int iL=0; iL<States; iL++) {
      for (int iM=0; iM<States; iM++) {
        for (int iR=0; iR<States; iR++) {
          if (l==iL && m==iM && r==iR) {
            return rules[n];
          } else {
            n++;
          }
        }
      }
    }
    return 0;
  }

  boolean finished() {
    if (gen > ((height-Size*2)/Size)) {
      return true;
    } else {
      return false;
    }
  }
}

//---------- Input Scripts

void keyPressed() {
  if (key=='s') {     // save image
    saveFrame("cellular_automata-####.png");
  } else
  if (key==' ') {
    CS.restart();     // restart from top, new rules+initial values
  } else
  if (key=='r') {     // start back at top with current values
    CS.Continue();
  }
}

void mousePressed() {
  if (mouseButton==LEFT) {
    CS.cells[int(mouseX/CS.Size)]=int(random(CS.States));
  }
}

8 comments

  • johnnp
    04.10.09

    hello there~
    I love this!!
    but I got ERRO when I copy this code to my Processing1.0
    he said” A web color “such as #ffcc0 0″ must be six digits.
    Bad erro line: -2


  • tony
    04.10.09

    thanks,
    Sorry about that. The way I have my code set up I wasn’t able to use ampersands and forgot the make a note. I’ve updated the code and there’s a comment about one thing you need to fix to get it working. I’ll address this issue properly soon.


  • johnnp
    04.13.09

    it’s works,
    Deeeeeeply appreciate your helps.


  • johnnp
    04.20.09

    hello again~
    the code run just fine!
    but We got the another problem~
    the image that created is 72dpi
    when we print it out,but the quality didn’t enough(either “tif”, “tga”, “jpg”, “png”)
    is there any solution?


  • tony
    04.20.09

    I’m glad it’s working.

    To get a print-sized image you can either export a vector image (for this that might not be the best idea) or increase the size of the render-window and all of the objects. I explain both methods in my post on Rendering Processing for Print.


  • noman
    05.05.09

    Are we supposed to get stills like above?
    All I get are light red and blue circles and my window is positioned on the top left, making me miss half of the window.


  • tony
    05.05.09

    The images above come from the same script but just have different rendering parameters.

    If you look within the cellsystem class you will find a few variables are defined, States, Size (size of each cell), and RSize (size of the point drawn). If Size is greater than RSize there will be space between the points and if RSize is greater the shapes will overlap. In the images above the bot Size and RSize were 1 or less, making the individual points blend into an intricate pattern. I’m sorry these might not be the most logical terms or put in the easiest place. I was just having fun with this and for whatever reason it made sense to me at the time.

    The images I posted are, of course, some of the more interesting patterns. Depending on the initial points and the ruleset (both of which are randomized) it will sometimes just look like noise. The rendering size I have is very large to fit my screen, but you can scale it down to something more reasonable by changing the parameters of the size() function in the setup.


  • noman
    05.06.09

    Thanks, problem was with quite a few processing problems, that I had to save, then restart processing after resizing, for the resizing to work.