Meine Version nochmal in Javascript. Ausgabe wieder als SVG. Diesesmal habe ich ein Feature eingebaut, mit dem die Schildkröte "langsamer" läuft, damit man sehen kann, welchen weg sie nimmt. Besonders schön bei dem Hilbert-Beispiel oder "Baum 1".

Direkt Live zu sehen gibts das ganze hier: http://olli.keller-delirium.de/turtle



HTML-Code:
<html xmlns="http://www.w3.org/1999/xhtml">  
    <head>
        <style>
            html, body {
                background: #ddd;
            }
            
            #SVGCanvas {
                position: relative;
                margin: auto auto;
                
                display: block;
                background: #fff;
                border: 1px dotted #888;
            }
            
            #Container {
                position: relative;
                margin: auto auto;
                width: 480px;
            }
            
            #Input {
                position: relative;
                display: block;
                width: 100%;
                height: 160px;
            }
            
            input[type='submit'] {
                position: relative;
                float: right;
            }
            
            br {
                clear: both;
                margin-bottom: 32px;
            }
            
            #StopButtons {
                display: none;
            }
            
        </style>
        
        <script><![CDATA[
            
            /**
                Die Turtle
            */
            function Turtle() {
                this.left = 0;
                this.top = 0;
                
                this.angle = 0;
                this.speedStep = 0;
                this.angleStep = 0;
                
                this.sequence = 0;
                this.svg = document.getElementById( "SVGCanvas" );
                
                this.onFinish = function(){};
                
                this._stop = false;
                this.stop = function() {
                    this._stop = true;
                }
                
                this.run = function( mode ) {
                    try {
                        var memory = [];
                        
                        while( this.svg.firstChild )
                            this.svg.removeChild( this.svg.firstChild );
                        
                        this.svg.setAttribute( "width", this.width + "px" );
                        this.svg.setAttribute( "height", this.height + "px" );
                        
                        var i = 0;
                        var self = this;
                        var stepSize = {
                                slow: Math.ceil(this.sequence.length / 1000),
                                normal: 2000,
                                fast: this.sequence.length
                            }[ mode ];
                            
                        var _doSomeWork = function() {
                            try {
                                var end = Math.min( i + stepSize, self.sequence.length );
                                
                                var points = [];
                                points.push( self.left + " " + (self.height - self.top) );
                                
                                for( ; i < end; i++ ) {
                                    switch( self.sequence[i] ) {
                                        case '+':
                                            self.angle += self.angleStep;
                                            break;
                                        
                                        case '-':
                                            self.angle -= self.angleStep;
                                            break;
                                        
                                        case 'F':
                                            self.left += Math.cos( self.angle ) * self.speedStep;
                                            self.top  += Math.sin( self.angle ) * self.speedStep;
                                            points.push( self.left + " " + (self.height - self.top) );
                                            break;
                                        
                                        case '[':
                                            memory.push({
                                                left:  self.left,
                                                top:   self.top,
                                                angle: self.angle
                                            });
                                            break;
                                        
                                        case ']':
                                            self.draw( points );
                                            
                                            var state = memory.pop(-1);
                                            self.left = state.left;
                                            self.top = state.top;
                                            self.angle = state.angle;
                                            
                                            points = [];
                                            points.push( self.left + " " + (self.height - self.top) );
                                            break;
                                    }
                                }
                                
                                self.draw( points );
                                
                                if( i < self.sequence.length && !self._stop ) {
                                    window.setTimeout( function() {
                                        _doSomeWork();
                                    }, 0);
                                } else {
                                    self.onFinish();
                                }
                            } catch( error ) {
                                alert( error );
                                self.onFinish();
                            }
                        }
                        
                        _doSomeWork();
                    } catch( error ) {
                        alert( error );
                        this.onFinish();
                    }
                }
                
                
                this.draw = function( points ) {
                    var line = document.createElementNS( "http://www.w3.org/2000/svg", "polyline" );
                    line.setAttribute( "points", points.join( "," ) );
                    this.svg.appendChild( line );
                }
                
                
                this.parse = function( input ) {
                    var lines = input.split( "\n" );
                    
                    var result = /([0-9]+)\s+([0-9]+)/.exec( lines[0] );
                    this.width  = parseInt( result[1] );
                    this.height = parseInt( result[2] );
                    
                    result = /([0-9.]+)\s+([0-9.]+)/.exec( lines[1] );
                    this.left = parseFloat( result[1] );
                    this.top  = parseFloat( result[2] );
                    
                    this.speedStep = parseFloat( lines[2] );
                    this.angleStep = parseFloat( lines[3] ) * (3.141592653 / 180);
                    
                    this.sequence = lines[4];
                    
                    if( lines.length >= 7 ) {
                        var iterations = parseInt( lines[5] );
                        
                        var rules = {};
                        if( lines[6].indexOf( " " ) == -1 ) {
                            var rule = lines[6];
                            rules[ 'F' ] = rule;
                        } else {
                            for( var i = 6; i < lines.length; i++ ) {
                                if( lines[i].indexOf( " " ) != 1 )
                                    break;
                                
                                var name = lines[i][0];
                                var rule = lines[i].slice( 2 );
                                rules[ name ] = rule;
                            }
                        }
                        
                        for( var i = 0; i < iterations; i++ )
                            this.extend( rules );
                        
                    }
                }
                
                
                this.extend = function( rules ) {
                    var repl = function( ch ) {
                        return ch in rules ? rules[ch] : ch;
                    };
                    
                    this.sequence = this.sequence.replace( /./g, repl );
                }
            }
            
            var turtle = null;
            
            function run( mode ) {
                try {
                
                    turtle = new Turtle();
                    
                    document.getElementById( "StartButtons" ).style.display = "none";
                    document.getElementById( "StopButtons" ).style.display = "block";
                    
                    turtle.onFinish = function() {
                        document.getElementById( "StartButtons" ).style.display = "block";
                        document.getElementById( "StopButtons" ).style.display = "none";
                    }
                    
                    var input = document.getElementById( "Input" ).value;
                    turtle.parse( input );
                    
                    window.setTimeout( function() {
                        turtle.run( mode );
                    }, 0 );
                    
                } catch( error ) {
                    alert( error );
                    document.getElementById( "StartButtons" ).style.display = "block";
                    document.getElementById( "StopButtons" ).style.display = "none";
                }
            }
            
            function cancel() {
                if( turtle ) {
                    turtle.stop();
                    turtle = null;
                }
            }
            
            var examples = {
                dreieck: "130 110\n15 10\n100\n120\nF+F+F",
                schneeflocke: "260 300\n10 80\n1\n60\nF++F++F\n5\nF-F++F-F",
                hilbert: "340 340\n10 10\n5\n90\nX\n6\nX +YF-XFX-FY+\nY -XF+YFY+FX-",
                tutorials1: "460 100\n30 10\n20\n90\n+FF+F--F+FF--FF+F--F+FF+FF+FF--FF+FF+FF--FF+FF+FF+F--F+FF--FF+F--F+FF+FFFF+FF+FF+FF+FFF+FF-F--F+FF+FF+FF--FF+FFF+FF-F++FFF+FF+FFFF+FFFF++FFFF+FFF+F+FF-F-FF",
                tutorials2: "460 100\n30 10\n20\n90\n[+FF[FF][+F][-F]]FF[+FF]FF[+FF]FF[+FF[FF][+F][-F]]FFFF[+FF+FF+FF]F[+FF-F]FF[+FF]FFF[+FF[-F]+FF+FF]FF[+FFFF]FFF+F+FF-F-FF",
                baum1: "400 600\n130 10\n5\n22.5\n++++F\n5\nFF-[-F+F+F]+[+F-F-F]",
                baum2: "290 430\n190 10\n5\n22.5\n++++X\n5\nX F-[[X]+X]+F[+FX]-X\nF FF"
            }
            
            function load( what ) {
                var input = document.getElementById( "Input" );
                input.value = examples[ what ];
            }
            
            
        ]]></script>
    </head>
    
    <body>
        <div id='Container'>
            
            <strong>Beispiele:</strong>
            <a href='javascript:load( "dreieck" );'>Dreieck</a>
            <a href='javascript:load( "schneeflocke" );'>Schneeflocke</a>
            <a href='javascript:load( "hilbert" );'>Hilbert</a>
            <a href='javascript:load( "tutorials1" );'>Tutorials 1</a>
            <a href='javascript:load( "tutorials2" );'>Tutorials 2</a>
            <a href='javascript:load( "baum1" );'>Baum 1</a>
            <a href='javascript:load( "baum2" );'>Baum 2</a>
            <br/>
                
            <textarea id='Input' />
            <div id='StartButtons'>
                
                <input type='submit' value='Schnell zeichnen' onclick='run( "fast" );' />
                <input type='submit' value='Normal zeichnen' onclick='run( "normal" );' />
                <input type='submit' value='Langsam zeichnen' onclick='run( "slow" );' />
            </div>
            
            <div id='StopButtons'>
                <input type='submit' value='Abbrechen' onclick='cancel();' />
            </div>
            
            <br />
        </div>
        
        <svg xmlns="http://www.w3.org/2000/svg" version="1.1"
            width='320px' height='240px'
            stroke='black' fill='none' id='SVGCanvas'>
            
        </svg>
        
        
    </body>
</html>