### L-System

I adapted my small L-System Parser to turtletoy.

Half of the time, it is shows a tree. The other half, it shows a snowflake.

#lsystem #fractal

```var turtle = new Turtle();

var PI = Math.PI;
var width = 1024;
var height = 1024;

var ANGLE;
var START;
var RULES = {};
var ITERATIONS;
var turtle_length;
var turtle_scale;
var turtle_scale_factor = 1.5;

if(Math.random() < 0.5){
// Half of the time, render snowflake
ANGLE = 36/360*PI*2;
START = 'F++F++F++F++F';
RULES = {
'F': 'F++F++F|F-F++F',
};
ITERATIONS = 5;
turtle_length = 0.2;
turtle_scale = 2.3;
turtle.up();
turtle.goto(-30,30);
turtle.down();
} else {
ANGLE = 40/360*PI*2;
START = 'FX';
RULES = {
'X': '>[-FX]+FX',
};
ITERATIONS = 8;
turtle_length = 40;
turtle_scale = 0.9;
turtle.left(PI/2);
turtle.up();
turtle.goto(0,40);
turtle.down();
}

var stack = [];

var alphabet = {
'+': function(){
// turn left
turtle.left(ANGLE);
},
'-': function(){
// turn right
turtle.right(ANGLE);
},
'F': function(){
// go forward
turtle.forward(turtle_scale * turtle_length);    },
'0': function(){
},
'1': function(){
// go forward
turtle.forward(turtle_scale * turtle_length);
},
'X': function(){
// do nothing
},
'Y': function(){
// do nothing
},
'[': function(){
stack.push({
x: turtle.x(),
y: turtle.y(),
turtle_scale: turtle_scale,
});
},
']': function(){
state = stack.pop();
turtle.up();
turtle.goto(state.x, state.y);
turtle.down();
turtle_scale = state.turtle_scale;
},
'A': function() {},
'B': function() {},
'M': function() {turtle.forward(turtle_scale * turtle_length);},
'N': function() {turtle.forward(turtle_scale * turtle_length);},
'O': function() {turtle.forward(turtle_scale * turtle_length);},
'P': function() {turtle.forward(turtle_scale * turtle_length);},
'<': function() {turtle_scale *= turtle_scale_factor;},
'>': function() {turtle_scale /= turtle_scale_factor;},
'|': function() {turtle.right(PI)},
};

// Thanks to wikipedia for teaching me about l-systems:
// https://en.wikipedia.org/wiki/L-system

// Note: I learned from the L-system Wikipedia article that:
//       F means go forward
//       + means turn left by angle (which is 90 for Dragon curve)
//       - means turn left by same angle
//       X and Y mean \"do nothing\"
//           Their purpose is only to control the creation of the string

// Produce the string
// This means \"read the string\" and:
//    Replace X by something
//    Replace Y by something else
//    [...]
function produce(initial){
let string = initial;

for(let j = 0; j < string.length; j++){
let before = string.substr(0,j);
let after = string.substr(j+1,string.length);

for(let key in RULES){
if(string[j] == key){
string = before + RULES[key] + after;
j += RULES[key].length-1;
}
}
}

return string;
}

function setup() {
string = START;
execute_step = 0;
// Generate the string only one time
for(let i = 0; i < ITERATIONS; i++){
string = produce(string);
}
}

// These are the actions we will take when executing the string

// Used to keep track of current position in string
var execute_step = 0;

// Run some characters of the string
function execute(string, steps_per_frame){
for(let i = 0; i < steps_per_frame && execute_step < string.length; i++){
// Reset turtle angle, background, etc at frame 0
try {
// Execute the function at given letter
alphabet[string[execute_step]]();
} catch (e) {
throw new Error("Error executing rule for: " + string[execute_step] + "\n" + e);
}
execute_step++;

}
}

Canvas.setpenopacity(1);

setup();

// The walk function will be called until it returns false.
function walk(i) {
let steps_per_frame = 1;

execute(string, steps_per_frame);

return i < 400000;
}
```