//One dimensional automata based on: //http://processing.org/learning/examples/wolframca.html //detailed in A New Kind of Science (Wolfram Stephen, 2002) int base = 4; int digits = 3; // for now - don't change Automata auto; Buttons [] button; AutoButtonTemplate [] template; PFont font; int [] rules; int [][] conditions; color [] colTable; void setup(){ size(500,720); font = loadFont("Kartika-48.vlw"); textFont(font, 28); conditions = combinations(digits, base); colTable = new color[base]; for(int i = 0; i < colTable.length; i++) colTable[i] = color((255.0/(base-1)) * i); rules = new int[conditions.length]; for(int i = 0; i < rules.length; i++) rules[i] = int(random(base)); auto = new Automata(400,700); button = new Buttons[conditions.length+2]; template = new AutoButtonTemplate[conditions.length]; for (int i = 0; i < conditions.length; i++){ int x = width - 60; int y = i * 20; if (y >= height - 60){ y -= height - 60; x += 40; } button[i] = new Buttons(x, 10 + y, 9, 9, colTable[rules[i]], null); template[i] = new AutoButtonTemplate(x - 10, y, conditions[i]); } button[button.length-1] = new Buttons(width - 90, height - 30, 90, 30, color(240), "Propagate"); button[button.length-2] = new Buttons(width - 90, height - 60, 90, 30, color(240), "Randomise"); background(255); } void draw(){ //draw gui fill(200); stroke(0); rect(width - 92, 0, 92, height); for(int i = 0; i < template.length; i++) template[i].draw(); for(int i = 0; i < button.length; i++) button[i].draw(); fill(0); text("hit propagate to generate pattern", 20, height - 10); } void mousePressed(){ int choice = -1; for(int i = 0; i < button.length; i++) if(button[i].over()) choice = i; if (choice == button.length - 1){ auto.propagate(rules); auto.draw(0,0); } if (choice == button.length - 2){ for(int i = 0; i < rules.length; i++){ rules[i] = int(random(base)); button[i].col = colTable[rules[i]]; } } if(choice > -1 && choice < button.length - 2){ rules[choice] = (rules[choice]+1)%base; button[choice].col = colTable[rules[choice]]; } } class Automata{ int [] cell; int w,h; Automata(int w, int h){ this.w = w; this.h = h; cell = new int[w * h]; for(int i = 0; i < cell.length; i++) cell[i]= 0; cell[w / 2] = 1; } void propagate (int [] rules){ //clear cells for(int i = 0; i < cell.length; i++) cell[i] = 0; cell[w / 2] = 1; //propagate rules for(int i = 0; i < h - 1; i++) for(int j = 1; j < w - 1; j++) for(int k = 0; k < conditions.length; k++){ if(cell[(j - 1) + i * w] == conditions[k][0] && cell[j + i * w] == conditions[k][1] && cell[(j + 1) + i * w] == conditions[k][2]) cell[j + (i + 1) * w] = rules[k]; } } void draw(int x, int y){ for(int i = 0; i < cell.length; i++){ stroke(colTable[cell[i]]); point(x + (i % w), y + (i / w)); } } } class AutoButtonTemplate{ int [] cell; int x,y; AutoButtonTemplate(int x, int y, int [] cell){ this.x = x; this.y = y; this.cell = cell; } void draw(){ for(int i = 0; i < cell.length; i++){ stroke(0); fill(colTable[cell[i]]); rect(x + i * 10, y, 9, 9); } } } int [][] combinations(int digits, int base){ //returns all possible combinations //format: [combination index][digit] int [] digit = new int[digits]; for(int i = 0; i < digit.length; i++) digit[i] = 0; int [][] combo = new int[int(pow(base, digits))][digits]; for(int i = 0; i < combo.length; i++){ for(int j = 0; j < combo[i].length; j++){ combo[i][j] = digit[j]; } digit[digit.length-1]++; for(int k = digit.length-1; k > 0; k--) if(digit[k] >= base){ digit[k] = 0; digit[k-1]++; } } return combo; }