home processing download documents tutorial python tutorial gallery source about
 Tutorials (back to the list of tutorials)

Clock Stack Agent Algorithm

     Template Code

import processing.opengl.*;
import igeo.*;

void setup(){
  size(480, 360, IG.GL);
  IConfig.syncDrawAndDynamics=true;
  IG.bg(1.0);
  new ClockStackAgent(new IVec(0,0,0), new IVec(10,0,0), new IVec(0,0,1)).clr(0);
}


class Orientation{
  IVec dir, nml; // as xyz coordinates system, dir corresponds to Y and nml corresponds to Z
  boolean righthand; // right hand coordinates system or not
  Orientation(IVec d, IVec n, boolean righthandsys){ dir=d; nml=n; righthand=righthandsys; }
  Orientation(IVec d, IVec n){ this(d,n,true); }
  Orientation(Orientation o){ dir=o.dir.cp(); nml=o.nml.cp(); righthand=o.righthand; }
  Orientation cp(){ return new Orientation(this); }
  IVec dir(){ return dir.cp(); }
  IVec front(){ return dir(); }
  IVec back(){ return dir().neg(); }
  IVec nml(){ return nml.cp(); }
  IVec up(){ return nml(); }
  IVec down(){ return nml().neg(); }
  IVec side(){ if(righthand){ return dir.cross(nml); }else{ return nml.cross(dir); } }
  IVec right(){ return side(); }
  IVec left(){ if(righthand){ return nml.cross(dir); }else{ return dir.cross(nml); } }
  Orientation rot(double ang){ dir.rot(nml, ang); return this; }
  Orientation rot(IVec ax, double ang){ dir.rot(ax,ang); nml.rot(ax,ang); return this; }
  Orientation pitch(double ang){
    IVec ax = dir.cross(nml); 
    dir.rot(ax, ang); nml.rot(ax, ang);
    return this;
  }
  Orientation yaw(double ang){ dir.rot(nml, ang); return this; }
  Orientation roll(double ang){ nml.rot(dir, ang); return this; }
  Orientation ref(IVec refNml){
    dir.ref(refNml); nml.ref(refNml); righthand = !righthand;
    return this;
  }
  Orientation flip(){ dir.flip(); righthand = !righthand; return this; }// flip front/back
  Orientation flipNml(){ nml.flip(); righthand = !righthand; return this; }// flip up/down
  Orientation flipSide(){ righthand = !righthand; return this; }// flip left/right
  Orientation mul(double v){ dir.mul(v); return this; }
  Orientation div(double v){ dir.div(v); return this; }
}

class ClockStackAgent extends IAgent{
  final double threshold = 1; // collision threshold
  IVec pos, pos2;
  Orientation orient;
  int[] clocks;
  
  boolean isColliding = false, isStopped = false;
  ArrayList< IVec > pts;
  ArrayList< Orientation > nextOrient;
  ArrayList< int[] > nextClocks;
  ArrayList< IAttribute > nextAttr;
  IBounds bounds;
  
  ClockStackAgent(IVec p, Orientation o, int[] clok){
    pos = p;
    orient = o;
    clocks = clok;
  }
  
  ClockStackAgent(IVec p, IVec d, IVec n, int[] clok){
    pos = p;
    if(d.isParallel(n)){
      if(!n.isParallel(IG.zaxis)) n = new IVec(0,0,1);
      else n = new IVec(0,1,0);
    } 
    if(d.dot(n)!=0) n = d.cross(n).icross(d);
    orient = new Orientation(d,n);
    clocks = clok;
  }
  
  ClockStackAgent(IVec p, IVec d, IVec n){
    this(p,d,n,new int[0]);
  }
  
  ClockStackAgent(IVec p, IVec d){
    this(p,d,new IVec(0,0,1),null);
  }
  
  IVec pos2(){
    if(pos2==null) pos2 = pos.cp(orient.dir);
    return pos2;
  }
  
  void interact(ArrayList< IDynamics > agents){
    if(threshold > 0 && !isStopped){
      IVec pt2 = pos2();
      for(int i=0; i < agents.size() && !isColliding; i++){
        if(agents.get(i) instanceof ClockStackAgent){
          ClockStackAgent a = (ClockStackAgent)agents.get(i);
          if(a==this){ // check self collision
            for(int j=0; pts!=null && j < pts.size()-2 && !isColliding; j++){ // exclude last segment
              if(IVec.isSegCloserThan(pos, pt2, pts.get(j), pts.get(j+1), threshold)){
                isColliding = true;
              }
            }
          }
          else if(a.time() > 0 || !a.isColliding){ // a!=this
            if(a.bounds!=null && bounds!=null){
              IBounds newbounds = bounds.cp();
              newbounds.compare(pt2);
              if(!newbounds.isCloserThan(a.bounds,threshold)){
                continue;
              }
            }
            IVec apt2 = a.pos2();
            if(IVec.isSegCloserThan(pos, pt2, a.pos, apt2, threshold) && (!pos.eq(a.pos) || pt2.eq(apt2)) ){
              isColliding = true;
            }
            for(int j=0; a.pts!=null && j < a.pts.size() && !isColliding; j++){
              IVec apt3 = a.pos;
              if(j < a.pts.size()-1) apt3 = a.pts.get(j+1);
              if(IVec.isSegCloserThan(pos, pt2, a.pts.get(j), apt3, threshold)
                && (!pos.eq(a.pos) || pt2.eq(apt2) || j < a.pts.size()-1) ){ 
                isColliding = true;
              }
            }
          }
        }
      }
    }
  }
  
  int clock(int i){
    if(i >= clocks.length) return 0;
    return clocks[i];
  }
  
  IAttribute next(int incrementClock){
    return next(orient, incrementClock);
  }
  
  IAttribute next(Orientation o, int incrementClock){
    if(nextOrient==null){
      nextOrient = new ArrayList< Orientation >();
      nextClocks = new ArrayList< int[] >();
      nextAttr = new ArrayList< IAttribute >();
    }
    nextOrient.add(o);
    int[] clocks2 = new int[incrementClock+1 > clocks.length?incrementClock+1:clocks.length];
    for(int i=0; i < clocks2.length; i++){
      if(i < incrementClock) clocks2[i] = 0;
      else if(i < clocks.length) clocks2[i] = clocks[i];
    }
    clocks2[incrementClock]++;
    nextClocks.add(clocks2);
    IAttribute attr = null;
    if(attr()==null) attr = new IAttribute();
    else attr = attr().cp(); // attribute (color) for next agent 
    nextAttr.add(attr);
    return attr;
  }
  
  void generate(){
    if(nextOrient==null || nextOrient.size()==0){
      isStopped=true;
      return;
    }
    for(int i=0; i < nextOrient.size(); i++){
      if(i > 0){
        new ClockStackAgent(pos2(), nextOrient.get(i), nextClocks.get(i)).attr(nextAttr.get(i));
      }
      else{
        if(pts==null){
          pts = new ArrayList< IVec >();
          bounds = new IBounds(pos);
          bounds.compare(pos2);
        }
        if(pts.size() > 1 && pts.get(pts.size()-1).isOnLine(pos, pts.get(pts.size()-2))){
          pts.set(pts.size()-1, pos);
        }
        else{ pts.add(pos); } // past points
        pos = pos2();
        orient = nextOrient.get(i);
        clocks = nextClocks.get(i);
        attr(nextAttr.get(i));
        bounds.compare(pos2); // next point
      }
    }
    pos2 = null; // reset pos2
    nextOrient=null;
    nextClocks=null;
    nextAttr=null;
  }
  
  IVec dir(){ return orient.dir(); }
  IVec front(){ return orient.front(); }
  IVec back(){ return orient.back(); }
  IVec nml(){ return orient.nml(); }
  IVec up(){ return orient.up(); }
  IVec down(){ return orient.down(); }
  IVec right(){ return orient.right(); }
  IVec left(){ return orient.left(); }
  IVec side(){ return orient.side(); }
  
  // transformation methods
  Orientation rot(double angle){ return orient.cp().rot(angle); }
  Orientation rot(IVec axis, double angle){ return orient.cp().rot(axis,angle); }
  Orientation pitch(double angle){ return orient.cp().pitch(angle); }
  Orientation yaw(double angle){ return orient.cp().yaw(angle); }
  Orientation roll(double angle){ return orient.cp().roll(angle); }
  Orientation mul(double factor){ return orient.cp().mul(factor); }
  Orientation div(double factor){ return orient.cp().div(factor); }
  Orientation ref(IVec axis){ return orient.cp().ref(axis); }
  Orientation flip(){ return orient.cp().flip(); }
  Orientation flipNml(){ return orient.cp().flipNml(); }
  Orientation flipSide(){ return orient.cp().flipSide(); }
    
  void update(){
    if(isStopped) return;
    if(isColliding){
      if(time()==0) del();
      else isStopped=true;
      return;
    }
    pos2 = pos2();
    // make geometry
    ICurve line = new ICurve(pos, pos2).attr(attr());
    rules();
    generate();
  }
   
  // update rules
  void rules(){
    // describe update rules here
    // - clock( x ) :
    //   checks the current clock number at the level x
    // - next( x ) :
    //   creates next instance with incrementing the clock at level x
    // - next( transformation method, x ) :
    //   creates next instance after the transfomration with incrementing the clock at level x
    if(clock(0) == 7) next(rot(-PI/2), 1);
    next(rot(PI/12), 0);
  }
}


     Rule 1

To run the code, replace the rule method in the template code with the following.

  void rules(){
    if(clock(0)==9){
      if(clock(1)==0){
        next(2);
      }
      next(rot(PI/2), 1);
    }
    else{
      next(0);
    }
  }


     Rule 2

  void rules(){
    if(clock(0)==9){
      if(clock(1)==0){
        if(clock(2)==3){
          next(rot(-PI/2), 3);
        }
        else{ next(2); }
      }
      next(rot(PI/2), 1);
    }
    else{ next(0); }
  }


     Rule 3

  void rules(){
    if(clock(0)==9){
      if(clock(1)==0){
        if(clock(2)==3){
          next(rot(-PI/2), 3);
        }
        else{ next(2); }
      }
      if(clock(1)==2 && clock(2)==0 && clock(3)==1){
        next(rot(-PI/2), 4);
      }
      next(rot(PI/2), 1);
    }
    else{ next(0); }
  }


     Rule 4

  void rules(){
    if(clock(0)==3){
      if(clock(1)==0){
        if(clock(2)==3){
          next(rot(-PI/2), 3);
        }
        else{ next(2); }
      }
      if(clock(4)==3){
        if(clock(1)==2 && clock(2)==0 && clock(3)==0){
          next(rot(-PI/2), 5).clr(0);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==1){
          next(rot(-PI/2), 5).clr(0);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==2){
          next(rot(-PI/2), 5).clr(0);
        }
      }
      else if(clock(1)==2 && clock(2)==0 && clock(3)==1){
        next(rot(-PI/2), 4);
      }
      next(rot(PI/2), 1);
    }
    else{ next(0); }
  }


     Rule 5

  void rules(){
    if(clock(0)==3){
      if(clock(1)==0){
        if(clock(2)==3){
          next(rot(-PI/2), 3);
        }
        else{ next(2); }
      }
      if(clock(4)==3){
        if(clock(1)==2 && clock(2)==0 && clock(3)==0){
          next(rot(-PI/3), 5).clr(0);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==1){
          next(rot(-PI/2), 5).clr(0);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==2){
          next(rot(-PI/3), 5).clr(0);
        }
      }
      else if(clock(1)==2 && clock(2)==0 && clock(3)==1){
        next(rot(-PI/2), 4); //.clr(0, 0, (clock(4)+1)*0.3);
      }
      next(rot(PI/2), 1);
    }
    else{ next(0); }
  }


     Rule 6

  void rules(){
    if(clock(0)==3){
      if(clock(1)==0){
        if(clock(2)==3){
          next(rot(-PI/2), 3);
        }
        else{ next(2); }
      }
      if(clock(4)==3){
        if(clock(1)==2 && clock(2)==0 && clock(3)==0){
          next(rot(-PI/2), 5).clr(0);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==1){
          next(rot(-PI/2), 5).clr(0);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==2){
          next(rot(-PI/2), 5).clr(0);
        }
      }
      else if(clock(1)==2 && clock(2)==0 && clock(3)==1){
        next(rot(-PI/2), 4); //.clr(0, 0, (clock(4)+1)*0.3);
      }
      next(rot(PI/2), 1);
    }
    else{ next(rot(PI/180*1), 0); }
  }


     Rule 7

  void rules(){
    if(clock(0)==3){
      if(clock(1)==0){
        if(clock(2)==3){
          next(rot(-PI/2), 3);
        }
        else{ next(2); }
      }
      if(clock(4)==3){
        if(clock(1)==2 && clock(2)==0 && clock(3)==0){
          next(rot(-PI/2), 5).clr(0);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==1){
          next(rot(-PI/2), 5).clr(0);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==2){
          next(rot(-PI/2), 5).clr(0);
        }
      }
      else if(clock(1)==2 && clock(2)==0 && clock(3)==1){
        next(rot(-PI/2), 4); //.clr(0, 0, (clock(4)+1)*0.3);
      }
      next(rot(PI/2), 1);
    }
    else{ next(rot(PI/180*0.1), 0); }
  }


     Rule 8

  void rules(){
    if(clock(0)==3){
      if(clock(1)==0){
        if(clock(2)==3){
          next(rot(-PI/2), 3);
        }
        else{ next(2); }
      }
      if(clock(4) >= IRand.getInt(2, 7)){
        if(clock(1)==2 && clock(2)==0 && clock(3)==0){
          next(rot(-PI/2), 5); //.clr(IRand.clr());
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==1){
          next(rot(-PI/2), 5); //.clr(IRand.clr());
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==2){
          next(rot(-PI/2), 5); //.clr(IRand.clr());
        }
      }
      else if(clock(1)==2 && clock(2)==0 && clock(3)==1){
        next(rot(-PI/2), 4);
      }
      next(rot(PI/2), 1);
    }
    else{ next(0); }
  }


     Rule 9

  void rules(){
    if(clock(0)==3){
      if(clock(1)==0){
        if(clock(2) >= IRand.getInt(3,10)){
          next(rot(-PI/2), 3);
        }
        else{ next(2); }
      }
      if(clock(4) == 3){
        if(clock(1)==2 && clock(2)==0 && clock(3)==0){
          next(rot(-PI/2), 5);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==1){
          next(rot(-PI/2), 5);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==2){
          next(rot(-PI/2), 5);
        }
      }
      else if(clock(1)==2 && clock(2)==0 && clock(3)==1){
        next(rot(-PI/2), 4);
      }
      next(rot(PI/2), 1);
    }
    else{ next(0); }
  }


     Rule 10

  void rules(){
    if(clock(0)==3){
      if(clock(1)==0){
        if(clock(2) >= IRand.getInt(3,10)){
          next(rot(-PI/2), 3);
        }
        else{ next(2); }
      }
      if(clock(4) == 3){
        if(clock(1)==2 && clock(2)==0 && clock(3)==0){
          next(rot(-PI/2+IRand.get(-PI/12,PI/12)), 5);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==1){
          next(rot(-PI/2), 5);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==2){
          next(rot(-PI/2+IRand.get(-PI/12,PI/12)), 5);
        }
      }
      else if(clock(1)==2 && clock(2)==0 && clock(3)==1){
        next(rot(-PI/2), 4);
      }
      next(rot(PI/2), 1);
    }
    else{ next(0); }
  }


     Rule 11

  void rules(){
    if(clock(0)>=IRand.getInt(3,10)){
      if(clock(1)==0){
        if(clock(2) >= IRand.getInt(1,5)){
          next(rot(-PI/2), 3);
        }
        else{ next(rot(IRand.get(-0.15, 0.15)), 2); }
      }
      if(clock(4) == 3){
        if(clock(1)==2 && clock(2)==0 && clock(3)==0){
          next(rot(-PI/2), 5);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==1){
          next(rot(-PI/2), 5);
        }
        if(clock(1)==2 && clock(2)==0 && clock(3)==2){
          next(rot(-PI/2), 5);
        }
      }
      else if(clock(1)==2 && clock(2)==0 && clock(3)==1){
        next(rot(-PI/2), 4);
      }
      next(rot(PI/2), 1);
    }
    else{ next(0); }
  }


     Rule 12

  void rules(){
    if(clock(0)==1){
      next(rot(-PI/6), 2);
      next(rot(PI/3*2), 1);
    }
    else{ next(0); }
  }


     Rule 13

  void rules(){
    if(clock(0)==1){
      next(rot(PI/3).flipNml(), 2);
      next(rot(PI/3*2), 1);
    }
    else{ next(0); }
  }


     Rule 14

  void rules(){
    if(clock(1)==0){
      if(clock(0)==5){
        next(rot(PI/2), 1);
      }
      else{ next(mul(0.99),0); }
    }
    else{
      if(clock(0)==15){
        next(rot(PI/2), 3);
      }
      else if(clock(0)==2){
        next(rot(-PI/2).flipNml(), 2);
        next(0);
      }
      else{ next(mul(0.99), 0); }
    }
  }


     Rule 15

  void rules(){
    if(clock(1)==0){
      if(clock(0)==15){
        next(rot(PI/3), 1);
        next(rot(-PI/3), 2);
      }
      else{ next(mul(0.99), 0); }
    }
    else if(clock(1)==1){
      if(clock(0)==5){
        next(rot(PI/3), 1);
      }
      else{ next(mul(0.99), 0); }
    }
    else{
      if(clock(0)==5){
        next(rot(PI/3), 3);
      }
      else{ next(mul(0.99), 0); }
    }
  }


     Rule 16

  void rules(){
    if(clock(1)==0){
      if(clock(0)==15){
        next(rot(PI/3), 1);
        next(rot(-PI/3), 2);
      }
      else{ next(0); }
    }
    else if(clock(1)==1){
      if(clock(0)==5){
        next(rot(PI/3), 1);
      }
      else{ next(0); }
    }
    else{
      if(clock(0)==5){
        next(rot(PI/3), 3);
      }
      else{ next(mul(0.99), 0); }
    }
  }


     Rule 17

  void rules(){
    if(clock(1)==0){
      next(rot(-PI/4), 1);
      next(rot(PI/2).flipNml(), 2);
    }
    else{
      if(clock(0)==5){
        if(IRand.pct(20)){
          next(rot(-PI/4).flipNml(), 2);
        }
      }
      else{ next(0); }
    }
  }


     Rule 18

  void rules(){
    if(clock(1)==0){
      if(clock(0)==5){
        next(rot(PI/2), 1);
        if(clock(2)==3){
          if(IRand.pct(70)) next(rot(PI/3),3);
          if(IRand.pct(50)) next(3);
          if(IRand.pct(30)) next(rot(-PI/2), 3);
        }
        else{ next(2); }
      }
      else{ next(0); }
    }
    else{
      if(clock(0)==5){
        next(rot(PI/2), 1);
      }
      else{
        next(mul(0.98), 0).clr(clock(0)*0.2, 0, clock(1)*0.1);
      }
    }
  }


     Rule 19

  void rules(){
    if(clock(1)==0){
      if(clock(0)==5){
        next(rot(PI/2), 1).clr(0,0.5,1.0);
        if(clock(2)==0){
          if(clock(3)==0){
            next(rot(-PI/2), 3).clr(0,0,1.0);
          }
          else{ next(rot(-PI/4), 4).clr(0); }
        }
      }
      else{ next(rot(PI/20),0); }
    }
    else{
      if(clock(0)==10){
        next(rot(PI/2),1).clr(0.5,0,1);
        if(clock(2)==0){
          next(3).clr(1.0,0.5,0);
        }
      }
      else{ next(rot(PI/20),0); }
    }
  }


     Rule 20

  void rules(){
    if(clock(1)==0){
      if(clock(0)==5){
        next(rot(PI/2), 1).clr(0,0.5,1.0);
        if(clock(2)==0){
          if(clock(3)==0){
            if(IRand.pct(90)) next(rot(-PI/4), 3).clr(0,0,1.0);
          }
          else{
            if(IRand.pct(40)) next(rot(-PI/2), 4).clr(0);
          }
        }
      }
      else{
        if(clock(2)==1){
          next(mul(0.99), 0);
        }
        else{ next(0); }
      }
    }
    else if(clock(1)==1){
      if(clock(0)==10){
        next(rot(PI/2),1).clr(0.5,0,1);
        if(clock(2)==0){
          next(3).clr(1.0,0.5,0);
        }
      }
      else{
        if(clock(2)==1){
          next(mul(0.99), 0);
        }
        else{ next(0); }
      }
    }
    else if(clock(1)==2){
      if(clock(0)==5){
        next(rot(PI/2), 1);
      }
      else{
        if(clock(2)==1){
          next(mul(0.99), 0);
        }
        else{ next(0); }
      }
    }
    else{
      if(clock(0)==10){
        if(clock(2)==0){
          next(rot(PI/2),2);
        }
      }
      else{ next(mul(0.99), 0); }
    }
  }


     Rule 21

  void rules(){
    if(clock(4)==0){
      if(clock(0)==3){
        next(rot(PI/2),1);
        if(clock(1)==0){
          if(clock(2)==2) next(rot(-PI/2),3);
          else next(2);
        }
      }
      else{
        if(clock(1)==2 && clock(0)==0) next(rot(-PI/2),4).clr(1.0,0,1.0);
        next(0);
      }
    }
    else{
      if(clock(0)==15) next(rot(PI/2),5).clr(0);
      else next(0);
    }
  }


     Rule 22

  void rules(){
    if(clock(0)==1){
      if(clock(1)==1){
        if(clock(2)==10){
          next(rot(-PI/6), 3);
        }
        else{ next(rot(-PI*5/6), 2); }
      }
      else{
        next(rot(PI*5/6), 1);
        if(clock(2)==5){
          next(rot(-PI/2),4);
        }
      }
    }
    else{ next(0); }
  }


     Rule 23

  void rules(){
    if(clock(0)==2){
      if(clock(1)==0 && clock(2)==3){
        next(rot(-PI/3), 3);
      }
      if(clock(1)==2){
        if(clock(2)==5){
          next(rot(-PI/3), 4);
        }
        else{ next(rot(-PI/3).flipNml(), 2); }
      }
      next(rot(PI/3), 1);
    }
    else{ next(0); }
  }


     Rule 24

  void rules(){
    if(clock(0)==2){
      if(clock(1)==0 && clock(2) >= IRand.get(3,6)){
        next(rot(-PI/3), 3);
      }
      if(clock(1)==2){
        if(clock(2) == IRand.getInt(2,5)){
          next(rot(-PI/3), 4);
        }
        else{ next(rot(-PI/3).flipNml(), 2); }
      }
      next(rot(PI/3), 1);
    }
    else{ next(0); }
  }


     Rule 25

  void rules(){
    if(clock(6)==0){
      if(clock(0)==3){
        if(clock(1)==0){
          if(clock(2) >= IRand.getInt(2,10)){
            next(rot(-PI/2), 3);
          }
          else{ next(2); }
        }
        if(clock(4) == 2){
          if(clock(1)==2 && clock(2)==0 && clock(3)==0){ // left
            if(IRand.pct(70)) next(rot(-PI/2), 5);
          }
          if(clock(1)==2 && clock(2)==0 && clock(3)==1){ // straight
            next(rot(-PI/2), 5);
          }
          if(clock(1)==2 && clock(2)==0 && clock(3)==2){ // right
            if(IRand.pct(70)) next(rot(-PI/2), 5);
          }
        }
        else if(clock(1)==2 && clock(2)==0 && clock(3)==1){
          next(rot(-PI/2), 4);
        }
        next(rot(PI/2), 1);
      }
      else{
        if(clock(0)==2 && clock(1)==0 && clock(3)==2){
          next(rot(-PI/2).mul(1), 6).clr(0.5,0,1);
        }
        next(0);
      }
    }
    else{ // branch mode
      if(clock(1)==60){
        if(IRand.pct(10)){
          next(mul(1), 7).clr(0,0,0.5);
        }
      }
      else{
        if(IRand.pct(20)){
          next(rot(-PI/4), 1);
        }
        if(IRand.pct(20)){
          next(rot(PI/4), 1);
        }
        if(IRand.pct(90)){
          next(1);
        }
      }
    }
  }


     Rule 26

  void rules(){
    if(clock(3)==1){
      if(clock(0)>=2 && IRand.pct(10)){
        next(4);
      }
      else{ next(0); }
    }
    else if(clock(0)==2){
      if(clock(1)==0){
        next(rot(-PI/3), 3);
      }
      if(clock(1)==0){
        next(rot(PI/3), 2);
      }
      else{ next(rot(PI/3), 1); }
    }
    else{ next(0); }
  }


     Rule 27

  void rules(){
    if(clock(3)==1){
      if(clock(0)>=2){
        next(4);
      }
      else{ next(rot(0.05), 0); }
    }
    else if(clock(0)==2){
      if(clock(1)==0){
        next(rot(-PI/3), 3);
      }
      if(clock(1)==0){
        next(rot(PI/3), 2);
      }
      else{ next(rot(PI/3), 1); }
    }
    else{ next(0); }
  }


     Rule 28

  void rules(){
    // corrugate
    if(clock(6)==0){ 
      if(clock(3)==1){
        if(clock(1)==1){
          if(clock(0)==5){
            if(clock(4)==12){ next(6); }
            else{ next(rot(PI/2), 4); }
          }
          else{ next(0); }
        }
        else{ next(rot(-PI/2), 1); }
      }
      else{
        if(clock(1)==1){
          if(clock(0)==5){
            next(rot(-PI/2), 3);
            if(clock(4)==10){ next(5); }
          }
          else{ next(0); }
        }
        else{ next(rot(PI/2), 1); }
      }
    }
    // triangles
    else if(clock(6)==1){
      if(clock(0)==3){
        if(clock(1)==0){
          if(clock(2)==20){ next(rot(-PI/4), 6); }
          else{ next(rot(-PI/3*2).flipNml(), 2); }
        }
        next(rot(PI/3*2), 1);
      }
      else{ next(0); }
    }
    // squares
    else{
      if(clock(0)==3){
        if(clock(1)==1){
          if(clock(2)==0){
            if(clock(3)==4){ next(rot(-PI/2), 7); }
            else{ next(rot(-PI/2),3); }
          }
          next(2);
        }
        next(rot(PI/2), 1);
      }
      else{ next(0); }
    }
  }


     Rule 29

  void rules(){
    if(clock(0)==10){
      
      if(clock(1)==0){
        if(clock(2)==0){
          next(pitch(PI/2).roll(-PI/2), 2);
        }
        else{
          next(pitch(-PI/2).roll(PI/2), 3);
        }
      }
      
      if(clock(1)==20); // stop
      else{
        if(clock(1)==0 || clock(1)==1){
          if(clock(1)==1 && clock(3)==1){
            next(4);
          }
          next(yaw(PI/2), 1).hsb(clock(1)*0.02,1,1);
        }
        else{
          next(yaw(PI/2).mul(0.9), 1).hsb(clock(1)*0.02,1,1);
        }
      }
    }
    else{ next(0); }
  }


     Rule 30

  void rules(){
    if(clock(0)==10){
      if(clock(1)==0){
        if(clock(2)==0){
          if(clock(3)==2){
            next(pitch(PI/2).roll(PI/2).mul(0.9), 2);
            next(yaw(-PI/2), 4); // new cube
          }
          else{
            next(pitch(PI/2).roll(PI/2), 2);
            if(clock(4)==4 && clock(3)==1){
              next(yaw(-PI/2), 5); // new cube
            }
          }
        }
        else{
          next(pitch(-PI/2).roll(-PI/2), 3);
        }
      }
      
      if(clock(1)==20); // stop
      else{
        next(yaw(PI/2).mul(0.9), 1).hsb(clock(1)*0.02,1,1);
      }
    }
    else{ next(0); }
  }


     Rule 31

  void rules(){
    if(clock(0)==3){
      if(clock(1)==0){
        if(clock(2)==0){
          if(clock(3)>=IRand.get(5,10)){
            next(yaw(-PI/2), 4).hsb(sin(IG.time()*.02)*.1+.7,1,1);
            if(IRand.pct(70)) next(4).hsb(sin(IG.time()*.02)*.1+.7,1,1);
          }
          else if(IRand.pct(97)) next(3).hsb(sin(IG.time()*.02)*.1+.7,1,1);
          next(pitch(PI/2).roll(PI/2), 2).hsb(sin(IG.time()*.02)*.1+.7,1,1);
        }
        else if(clock(2)==1){
          if(clock(3)>=IRand.get(5,10)){
            if(IRand.pct(70)) next(roll(-PI/2), 4).hsb(sin(IG.time()*.02)*.1+.7,1,1);
          }
          next(pitch(-PI/2).roll(PI/2), 2).hsb(sin(IG.time()*.02)*.1+.7,1,1);
        }
        else if(clock(2)==2){
          next(pitch(PI/2).roll(PI/2), 2).hsb(sin(IG.time()*.02)*.1+.7,1,1);
        }
        else if(clock(2)==3){
          next(pitch(-PI/2).roll(PI/2), 2).hsb(sin(IG.time()*.02)*.1+.7,1,1);
        }
      }
      next(yaw(PI/2),1).hsb(sin(IG.time()*.02)*.1+.7,1,1);
    }
    else{ next(0).hsb(sin(IG.time()*.02)*.1+.7,1,1); }
  }


     Rule 32

  void rules(){
    if(clock(0)==3){
      if(clock(1)==0){
        if(clock(2)==0){
          if(clock(3)>=IRand.get(5,10)){
            next(rot(-PI/2), 4).hsb(sin(IG.time()*.02)*.1,1,1);
            if(IRand.pct(50)) next(4).hsb(sin(IG.time()*.02)*.1,1,1);
          }
          else next(3).hsb(sin(IG.time()*.02)*.1,1,1);
          next(roll(PI/2).yaw(PI/2), 2).hsb(sin(IG.time()*.02)*.1,1,1);
        }
        else if(clock(2)==1){
          if(clock(3)>=IRand.get(5,10)){
            if(IRand.pct(10)) next(roll(-PI/2), 4).hsb(sin(IG.time()*.02)*.1,1,1);
          }
          next(roll(-PI/2).yaw(PI/2), 2).hsb(sin(IG.time()*.02)*.1,1,1);
        }
        else if(clock(2)==2){
          next(roll(PI/2).yaw(PI/2), 2).hsb(sin(IG.time()*.02)*.1,1,1);
        }
        else if(clock(2)==3){
          next(roll(-PI/2).yaw(PI/2), 2).hsb(sin(IG.time()*.02)*.1,1,1);
        }
      }
      next(rot(PI/2),1).hsb(sin(IG.time()*.02)*.1,1,1);
    }
    else{ next(pitch(-0.03).yaw(0.03), 0).hsb(sin(IG.time()*.02)*.1,1,1); }
  }


     Rule 33

  void rules(){
    if(clock(0)==99){
      next(pitch(PI/2).roll(PI/2), 1).clr(0,0,.5-cos(IG.time()*.05)*.5);
    }
    if(clock(0)==100){
      next(pitch(PI/3).roll(PI/2), 1).clr(0,0,.5-cos(IG.time()*.05)*.5);
    }
    next(yaw(PI/3*2).pitch(0.1), 0).clr(0,0,.5-cos(IG.time()*.05)*.5);
  }


     Rule 34

  void rules(){
    if(clock(0)==99){
      next(pitch(PI/2).roll(PI/2), 1); 
    }
    if(clock(0)==100){
      next(pitch(PI/3).roll(PI/2), 1); 
    }
    if(clock(0)%3==0){
      next(roll(0.1).yaw(PI/3*2).pitch(0.1), 0).clr(clock(0)*0.01,0,clock(1)*0.1);
    }
    else{
      next(yaw(PI/3*2).pitch(0.1), 0).clr(clock(0)*0.01,0,clock(1)*0.1);
    }
  }


     Rule 35

  void rules(){
    if(clock(5)==1){
      if(clock(0)==6){
        next(rot(PI/3).flipNml(),6);
      }
      else{ next(rot(PI/3).flipNml(),0); }
    }
    else{
      if(clock(0)==0){
        if(clock(4)==43 && clock(1)==1 && clock(2)==0){
          next(rot(PI/3),5);
        }
        else{
          if(clock(1)==2){
            if(clock(2)==1){
              if(clock(3)==11){
                next(yaw(PI/3-PI/15).pitch(PI/6).roll(PI/6), 4);
              }
              else{ next(yaw(PI/3).pitch(PI/6).roll(PI/6), 3); }
            }
            else{ next(yaw(PI/3).pitch(PI/6), 2); }
          }
          else{ next(yaw(PI/3),1); }
        }
      }
      else{ next(0); }
    }
  }


     Rule 36

  void rules(){
    if(clock(7)==2){ // stop
      return;
    }
    if(clock(2)==0){ // segment
      next(rot(PI/2), 2);
    }
    else{ // square
      if(clock(0)==3){
        if(clock(1)==2){
          if(clock(3)==3 && clock(5)==0){
            next(4);
          }
          else if(clock(3)==9 && clock(5)==1){
            next(6).clr(0);
          }
          else{ next(rot(PI/2), 3); }
        }
        next(rot(-PI/2),1);
      }
      else{
        if(clock(0)==1 && clock(1)==1 && clock(3)==1 && clock(5)==0){
          if(clock(6)==1){
            next(yaw(PI/2).pitch(PI/2), 7);
          }
          else{ next(rot(PI/2), 5).clr(0.5,0,0.5); }
        }
        next(0);
      }
    }
  }


(back to the list of tutorials)

HOME
FOR PROCESSING
DOWNLOAD
DOCUMENTS
TUTORIALS (Java / Python)
GALLERY
SOURCE CODE(GitHub)
ABOUT