"""Generates the L-System for the Dragon Fractal, using the turtle module.""" import re, turtle from math import sin, pi """The default L-System rules for the dragon fractal are: Angle 45 degrees Starting Axiom FX F = Y = +FX--FY+ X = -FX++FY- I've optimised them a little bit the following ways: Take out all occurances of F. Replace Y with +FN--FY+ Replace X with -FX++FY- Replace N with X Take out all occurances of -+ Take out all occurances of +- """ def rules(instring): """I originally had this as a series of nested re.sub expressions. Once the rule list got long though, I split it up to make it more "pythonic". """ newstring, subs = re.subn("F", "", instring) # Use N as a placeholder for X newstring, subs = re.subn("Y", "+FN--FY+", newstring) # So that we don't get double substitution. newstring, subs = re.subn("X", "-FX++FY-", newstring) # Now we replace the placeholder with X newstring, subs = re.subn("N", "X", newstring) # And optimise the string in regard to left/right turns. subs = 1 while subs: newstring, first = re.subn("-\+", "", newstring) newstring, second = re.subn("\+-", "", newstring) subs = first + second return newstring def colorator(value): # Makes the colour of the cursor cycle. range, fract = divmod(value*6, 1) if range == 0: red = 1.0 green = fract blue = 0.0 elif range == 1: red = 1.0 - fract green = 1.0 blue = 0.0 elif range == 2: red = 0.0 green = 1.0 blue = fract elif range == 3: red = 0.0 green = 1.0 - fract blue = 1.0 elif range == 4: red = fract green = 0.0 blue = 1.0 elif range >= 5: red = 1.0 green = 0.0 blue = 1.0 - fract return red, green, blue # The default is that the turtle will only move one pixel def parser(parsestring, distance=1, angle=45): # First we clean up the parsestring newstring = re.sub("X", "", parsestring) newstring = re.sub("Y", "", newstring) # Clear the screen turtle.clear() strlen = len(newstring) colorinc = 1.0 / float(strlen) turtle.color(colorator(0)) for i in range(strlen): value = newstring[i] turtle.color(colorator(float(i) * colorinc)) if value == "+": turtle.right(angle) elif value == "-": turtle.left(angle) elif value == "F": turtle.forward(distance) # Hide the cursor turtle.color(1.0,1.0,1.0) def run(count=15, distance=1, angle=45, width=1): string = "FX" while count > 0: string = rules(string) count -= 1 # "Hide" the cursor while we are moving it. ## print string turtle.width(width) turtle.color(1.0,1.0,1.0) # Move the cursor so the turtle won't go off the screen. # You might want to resize the turtle screen while the program is doing this turtle.setx(100) turtle.sety(-200) parser(string, distance=distance, angle=angle) if __name__ == "__main__": run(15)