// Copyright (C) 2005 Dave Griffiths // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // A simple lsystem breeder // // Rules: // o : play sound // + : changes current sound // - : changes current sound // . : rest // stops us creating HUGE strings that take hours to process :) int MAX_STRING = 4096; // the interpreter reads the output strings and understands how the symbols map to music commands. class Interpreter { int m_Sound; int m_NumSounds; PSound m_Sounds[]; int m_Pos; Interpreter() { m_Pos=0; m_Sound=0; m_Sounds=new PSound[100]; } void Initialise() { m_Sounds[0]=loadSound("kick.wav"); m_Sounds[1]=loadSound("snare.wav"); m_Sounds[2]=loadSound("snare2.wav"); m_Sounds[3]=loadSound("hihat.wav"); m_Sounds[4]=loadSound("hihat2.wav"); m_NumSounds=5; } void Parse(String t) { boolean finished=false; while(m_Pos=t.length()) { m_Pos=0; m_Sound=0; } } } // the producer is given the rules of the lsystem and is run() to produce // the output string to be given to the interpreter to draw class Producer { String m_String; String m_Axiom; String m_RuleFrom[]; String m_RuleTo[]; int m_NumRules; Producer() { m_NumRules=0; m_RuleFrom = new String[3]; m_RuleTo = new String[3]; } Producer(Producer other) { m_NumRules=other.m_NumRules; m_Axiom=other.m_Axiom; m_String=other.m_String; m_RuleFrom = new String[3]; m_RuleTo = new String[3]; for (int n=0; n<3; n++) { m_RuleFrom[n]=other.m_RuleFrom[n]; m_RuleTo[n]=other.m_RuleTo[n]; } } void AddRule(String from, String to) { m_RuleFrom[m_NumRules]=from; m_RuleTo[m_NumRules]=to; m_NumRules++; } void Run(int gen) { // set the initial string to the axiom m_String=m_Axiom; for (int n=0; nrandom(100)) { int type=(int)random(3); switch (type) { case 0: out+=m_Vocab.charAt((int)random(m_Vocab.length())); break; // change case 1: break; // deletes this char case 2: // add out+=in.charAt(i); out+=m_Vocab.charAt((int)random(m_Vocab.length())); break; } } else { out+=in.charAt(i); } } return out; } void Initialise() { for (int i=0; i<4; i++) { m_Producers[i]=new Producer(); m_Producers[i].m_Axiom=MakeString(m_InitLength); m_Producers[i].AddRule("A",MakeString(m_InitLength)); m_Producers[i].AddRule("B",MakeString(m_InitLength)); m_Producers[i].AddRule("C",MakeString(m_InitLength)); m_Producers[i].Run(m_Generations); } } void Mutate(int n) { m_Producers[n].m_Axiom=MutateString(m_Producers[n].m_Axiom,m_Strength); m_Producers[n].m_RuleTo[0]=MutateString(m_Producers[n].m_RuleTo[0],m_Strength); m_Producers[n].m_RuleTo[1]=MutateString(m_Producers[n].m_RuleTo[1],m_Strength); m_Producers[n].m_RuleTo[2]=MutateString(m_Producers[n].m_RuleTo[2],m_Strength); m_Producers[n].Run(m_Generations); } void Run(int g) { for (int i=0; i<4; i++) { m_Producers[i].Run(g); } } void Pick(int p) { for (int n=0; n<4; n++) { if (n!=p) { m_Producers[n]=new Producer(m_Producers[p]); Mutate(n); } } } } /////////////////////////////////////////////////////////////////////// Interpreter interpreter = new Interpreter(); Mutator mutator = new Mutator(); int picked=0; int swidth=400, sheight=400; int hw=swidth/2, hh=sheight/2; void RenderString(String s, int x, int y) { String RenderStr=""; int linelen=25; int maxlines=14; int count=0; int lines=0; for (int n=0; nlinelen) { RenderStr+="\n"; count=0; lines++; if (lines>maxlines) break; } } text(RenderStr, x, y); } void Render() { // clear the screen fill(204,78,0); noStroke(); rect(0,0,swidth,sheight); fill(255,255,0); if (picked==0) rect(0,0,hw,hh); else if (picked==2) rect(0,hh,hw,sheight); else if (picked==1) rect(hw,0,swidth,hh); else if (picked==3) rect(hw,hh,swidth,sheight); stroke(0); fill(0); RenderString(mutator.m_Producers[0].m_String,5,20); RenderString(mutator.m_Producers[2].m_String,5,220); RenderString(mutator.m_Producers[1].m_String,205,20); RenderString(mutator.m_Producers[3].m_String,205,220); } void Play() { interpreter.Parse(mutator.m_Producers[picked].m_String); } void setup() { size(swidth, sheight); PFont myfont = loadFont("CourierNew36.vlw"); textFont(myfont,12); mutator.Initialise(); interpreter.Initialise(); Render(); framerate(10); } void draw() { if (mousePressed) { if (mouseButton==LEFT) { // do the selection if (mouseXhw && mouseYhw) picked=2; else if (mouseX>hw && mouseY>hw) picked=3; mutator.Pick(picked); Render(); } if (mouseButton==RIGHT) { // do the selection if (mouseXhw && mouseYhw) picked=2; else if (mouseX>hw && mouseY>hw) picked=3; Render(); } } if (keyPressed) { if (key==' ') { mutator.Initialise(); Render(); } } Play(); }