//L-System Chromosome class class Chromosome{ int chromosomeLength = 10; //Number of genetic traits per tree int binLength = 3; //Binary complexity of a trait float mutationRate = 0.001; //Probability of mutation char [] trait = { //Genetic trait array 'F', '+', '-', '[', ']', 'S' }; StringBuffer dna = new StringBuffer(chromosomeLength * binLength); //Binary genetic code Chromosome(){ while(true){ dna = new StringBuffer(chromosomeLength * binLength); for(int i = 0; i < chromosomeLength; i++){ dna.append(binary((int)random(trait.length), binLength)); } if(healthyTree()){ break; } } } Chromosome(String dna){ this.dna = new StringBuffer(dna); } //Turn binary into an L-System tree String decode(){ StringBuffer decode = new StringBuffer("F[+F]F[-F]F"); StringBuffer insertions = new StringBuffer(""); for(int i = 0; i < dna.length(); i += binLength){ int id = unbinary(dna.substring(i, i + binLength)); if(id < trait.length){ insertions.append(trait[id]); } } for(int i = 0; i < insertions.length(); i++){ decode.insert((i*2) + 1, insertions.charAt(i)); } return decode.toString(); } //Check if the tree is infertile or will grow into the floor boolean healthyTree(){ LSystem lsystem = new LSystem("F", decode()); lsystem.iterate(2); Vector angleStack = new Vector(0); float angle = -HALF_PI; boolean fertile = false; for(int i = 0; i < lsystem.tree.length(); i++){ switch(lsystem.tree.charAt(i)){ case 'S': fertile = true; break; case '+': angle += angleStep; break; case '-': angle -= angleStep; break; case '[': angleStack.add(new Float(angle)); break; case ']': if(angleStack.size() != 0){ Float temp = (Float)angleStack.remove(angleStack.size() - 1); angle = temp.floatValue(); } } if(angle > 0.0 || angle < -PI){ return false; } } if(angle == -HALF_PI || !fertile){ return false; } return true; } //Absorb genetic information from another Chromosome void crossOver(Chromosome mate){ StringBuffer tempDna = dna; while(true){ int position = int(random(dna.length())); for(int i = position; i < dna.length()-1; i++){ char temp = dna.charAt(i); dna.setCharAt(i, mate.dna.charAt(i)); mate.dna.setCharAt(i, temp); } if(healthyTree()){ break; } else{ dna = tempDna; } } } //Mutate dna void mutate(){ StringBuffer tempDna = dna; while(true){ for(int i = 0; i < dna.length(); i++){ if(random(1.0) <= mutationRate){ dna.setCharAt(i, (dna.charAt(i)=='0' ? '1' : '0')); } } if(healthyTree()){ break; } else{ dna = tempDna; } } } }