I give up on the L-System front. I'm quite happy with what I achieved so far but my motivation has burned out too much to push it further. Here's a screen capture of a demo I've scripted in the last week. All the animations visible in the above video are real time generated, rendered at 60 FPS in my Grove Script interpreter and captured with hypercam. As the script is only 1KB big, the perceived complexity and the way the result is randomized is a nice demonstration of the power of L-Systems and emergence.

http://www.youtube.com/watch?v=twZLhxi_964And this is how the script of the demo looks like:

//set some basic constant parameters to be used in expressions

//feel free to play with the values and see how the animation

//adapts

set speed, 15

set pause, 15

set fadetime, 15

set budstep, 5

set maxage, 80

set leafAge, 5

//let the size of the structure adapt with window size

set step, 0.4*_height/480

//these variables change every frame because they all depend on the current

//value of the time() function.

//Thanks to the modulo operate age wraps around at maxage.

set age, (speed*time()) % maxage

set fade, min(1, (maxage-age-pause) / fadetime)

out fade

set age, 2.5*age^0.55

set frac, max(0.01, frac(age))

//each structure should look unique.

//So we use a different random seed for every new structure

out 'rnd seed, floor(time()*speed/(maxage))

shuffle floor(time()*speed/(maxage))

//init the turtle

dir random(360)

pos 0, step*(5*age-100)

//set the axiom of the 'plant' structre

seed plant, A(0,0,1)

//apply the ruleset 'r1' as often as the plant is old.

repeat age

grow plant, r1

//fun info: how many buds were generated?

out budCnt

//render 'plant' twice - mirrored.

push

rotate -45

run plant

pop

rotate 135

run plant

//Now the Tokens that the L-System operates upon are defined.

//light blue tips of the structure

#A(age, angle)

run shade(leafAge/frac)

size frac^0.5

move step*frac^0.5, angle

//what becomes of A in the next cycle - a simple curve

#B(t, angle)

run shade(leafAge/(t+frac))

size (t+frac)^0.5

move step*(t+frac)^0.5, angle

//B becomes C when it's old enough to spawn leaves - does the same thing, though

#C(t, angle)

run B(t, angle)

//a growing leaf

#L(t, angle)

run leaf(t+frac, angle)

//a finalized leaf

#xL(t, angle)

run leaf(t, angle)

//a growing bud

#Y(t, spread, angle)

run bud(0.3*(t+frac), (spread+frac)*budstep, 0.1*angle)

//a finalized bud

#xY(t, spread, angle)

run bud(0.3*(t+frac), (spread+frac)*budstep, 0.1*angle)

//render a bud

#bud(len, angle, curve)

run budshade(1/len)

//left side

push

size 2*len^0.3

rotate angle

move len^0.3, angle

size len/2

rotate -90

move len, -angle

pop

//right side

push

size 2*len^0.3

rotate -angle

move len^0.3, -angle

size len

rotate 90

move len, angle

pop

//stem

rotate curve

move 0.55*len^0.7

//render a leaf

#leaf(len, ang)

size 1

rotate 10*ang*len^0.6

move 0.5*len^0.3

move len^0.6, ang*(60+len*5)

rotate 180 - ang*0.4*(60+len*10)

move 0.5*len^0.5, -ang*(len*5)

move 0.7*len^0.5, ang*(len*10)

//color buds

#budshade(alpha)

visible alpha * fade

rgb 1.0-0.8*alpha*alpha, 0.6*alpha+0.2, 0.2*alpha*alpha

//color rest

#shade(alpha)

visible alpha * fade

rgb 1.0-0.5*alpha, 0.5*alpha+0.5, 0.3*alpha

#[

push

#]

pop

//The rules are evaluated in the order of appearance.

//rare rules appear first, if all are skipped the general case is usually to just grow the existing tokens

#r1

//BRANCHING

//higher c makes a vine less likely to bend or split but increases chance to spawn buds

A(i, j, c) : rnd(0, c) > 2+budCnt -> B(1, j) Y(0, 1, j)

raise budCnt, 1

//if old enough there's a chance to split into 3

A(i, j, c) : i > c and rnd() < 0.5/c -> B(1, j) [ A(0, rnd(-40,-60), c+2) ] [ A(0, rnd(40,60), c+2) ] A(0, 0, c+1)

//...or into 2

A(i, j, c) : i > c and rnd() < 0.5/c -> B(1, j) [ A(0, rnd(-40,-60), c+1) ] A(0, rnd(40,60), c+1)

//or just change the direction

A(i, j, c) -> B(1, j) A(i+1, j+rnd(-90, 90)/(c+1), c)

//LEAVES

//based on the curvature leaves spawn on different sides

B(i, j) : j < 0 and i = leafAge-1 -> C(i+1, j) [ L(0, 1) ]

B(i, j) : j > 0 and i = leafAge-1 -> C(i+1, j) [ L(0, -1) ]

//GROWTH

//and of course everything needs to grows

Y(i, j, k) -> Y(i+1, j+1, k) xY(i, j, k)

B(i, j) -> B(i+1, j)

C(i, j) -> C(i+1, j)

L(i, j) : i > 1+rnd(7) -> xL(i+1, j)

L(i, j) -> L(i+1, j)