| Draws fractals using L-Systems. 
 
'#
'# L-System Fractal Viewer
'# By Rich Dodson a.k.a. Sushimasta
'# 2006
'#
SuperStrict
SeedRnd MilliSecs()
Type TRule
	Global _rules:TList = CreateList()
	
	Field _before:String
	Field _after:String
	
	Method Construct:TRule(before:String, after:String)
		_rules.AddLast(Self)
		_before = before
		_after = after
		Return Self
	EndMethod
	
	Method Destruct()
		_rules.Remove(Self)
	EndMethod
	
	Function GetRules:TList()
		Return _rules
	EndFunction
	
	Method GetBefore:String()
		Return _before
	EndMethod
	
	Method GetAfter:String()
		Return _after
	EndMethod
EndType
Function Rule(before:String, after:String)
	New TRule.Construct(before, after)
EndFunction
'#
'# -------------------------
'# L-System Fractal Design
'#	Move the fractal around the screen using the mouse
'#	Click the left mouse button to draw the next level of the fractal
'#	Don't increase the level too high as the time it takes to compute increases exponentially
'#
'# Length of each line
Const radius:Float = 10.0	
'# Angle of each turn
Const angle:Float = 60.0
'# Initial axiom for fractal
Local line:String = "F"
'# Rules for expanding a fractal
Rule("F", "F+F--F+F")
'#
'# Rules are in the form of before -> after where each occurance of before is replaced with after
'# In the above example, each occurance of F is is replaced by F+F--F+F
'# Strings are executed as commands to a Turtle drawer
'#
'# Characters:
'#	F	- Draw a line with length radius
'#	+	- Turn left by angle
'#	-	- Turn right by angle
'#	[	- Push current state on to stack
'#	]	- Pop current state off of stack
'#	
'#
'# For example:
'#	F
'#	F+F--F+F
'#	F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F
'# etc, etc.
'# -------------------------
'#
Graphics(800, 600, 32, 60)
HideMouse()
Local timer:TTimer = CreateTimer(60)
Local advance:Int = 0
Repeat
	Select WaitEvent()
	Case EVENT_KEYDOWN
		Select EventData()
		Case KEY_ESCAPE
			Exit
		EndSelect
	Case EVENT_MOUSEDOWN
		Select EventData()
		Case MOUSE_LEFT
			advance :+ 1
		EndSelect
	Case EVENT_TIMERTICK
		If EventSource() = timer
			Cls
			RunTurtle(line, MouseX(), MouseY(), 0.0)
			If KeyDown(KEY_TAB)
				DrawText(line, 0, 0)
				DrawText(line.length, 0, 20)
			EndIf
			Flip
			
			If advance
				Local nline:String = ""
				
				Local p:Int = 0
				While p < line.length
					Local c:String = line[p..p + 1]
					Local matched:Int = False
					For Local rule:TRule = EachIn TRule.GetRules()
						Local l:Int = rule.GetBefore().length
						If line[p..p + l] = rule.GetBefore()
							nline :+ rule.GetAfter()
							matched = True
							p :+ l
							Exit
						EndIf
					Next
					If Not matched
						nline :+ c
						p :+ 1
					EndIf
				Wend
				
				line = nline
				
				advance :- 1
			EndIf
		EndIf
	EndSelect
Forever
For Local rule:TRule = EachIn TRule.GetRules()
	rule.Destruct()
Next
Function RunTurtle(line:String, x:Float, y:Float, a:Float)
	Global stack:Float[] = New Float[256]
	Global index:Float = 0
	
	For Local p:Int = 0 Until line.length
		Local c:String = line[p..p + 1]
		If "A" <= c And c <= "Z"
			Local nx:Float = x + radius * Cos(a)
			Local ny:Float = y + radius * Sin(a)
			DrawLine(x, y, nx, ny)
			x = nx
			y = ny
		Else
			Select c
			Case "+"
				a :- angle
			Case "-"
				a :+ angle
			Case "["
				stack[index] = x
				stack[index + 1] = y
				stack[index + 2] = a
				index :+ 3
			Case "]"
				index :- 3
				x = stack[index]
				y = stack[index + 1]
				a = stack[index + 2]
			EndSelect
		EndIf
	Next
EndFunction
 
 |