// Using base L-System implementation from reinder
// Global code will be evaluated once.
Canvas.setpenopacity(1);
const turtle = new Turtle(0,110);

let distance = 98;
let angle = 37.5;
let curving = 0.56;

// l-system
function createLSystem(numIters, axiom) {
    let s = axiom;
    for (let i=0; i<numIters; i++) {
        s = processString(s);
    }
    return s;
}

function processString(oldStr) {
    let newstr = "";
    for (let i=0; i<oldStr.length; i++) {
        newstr += applyRules(oldStr[i]);
    }
    return newstr;
}

function applyRules(ch) {
    switch (ch) {
        case "F": return "F[-F][+F]";
        default: return ch;
    }
}

let data = [];
const saveP = (x, y, a) => data.push({x, y, a});
const loadP = () => data.pop();

turtle.setheading(270);
const inst = createLSystem(13, "F"); // number of iterations and axiom

// The walk function will be called until it returns false.
function walk(i) {
    const cmd = inst[i];

    switch (cmd) {
        case "F":   turtle.forward(distance);
                    break;
        case "-":   turtle.right(angle);
                    break;
        case "+":   turtle.left(angle);
                    break;
        case "[":   data.push(turtle.x())
                    data.push(turtle.y())
                    data.push(turtle.heading());
                    distance *= curving;
                    break;
        case "]":   turtle.setheading(data.pop());
                    turtle.penup();
                    turtle.sety(data.pop());
                    turtle.setx(data.pop());
                    turtle.pendown();
                    distance /= curving;
                    break;
        default:
    }
      
    return i < inst.length - 1;
}