163,243-- Create a new turtle "object" with the given parameters.
-- step_size: How far the turtle moves with the F command.
-- angle_inc: The turn amount (in degrees) for +/- commands.
function make_turtle(step_size, angle_inc)
return {d=step_size, a=math.rad(angle_inc), width=2}
end
-- Move the given turtle to point (x,y) facing angle a (degrees).
function place_turtle(turtle, x, y, a)
turtle.x = x
turtle.y = y
turtle.facing = math.rad(a)
end
-- Draw a path from the turtles current position to its next position,
-- taking into account its step size and current direction.
function draw_forward(turtle)
local new_x = turtle.x + turtle.d * math.cos(turtle.facing)
local new_y = turtle.y - turtle.d * math.sin(turtle.facing)
local p = path(turtle.x, turtle.y, new_x, new_y)
p.strokeWidth = turtle.width
turtle.x, turtle.y = new_x, new_y
end
-- Turn the turtle right (CCW) by its angle increment.
function right(turtle)
turtle.facing = turtle.facing - turtle.a
end
-- Turn the turtle left (CW) by its angle increment.
function left(turtle)
turtle.facing = turtle.facing + turtle.a
end
-- Push the current turtle state to the top of a stack.
function push(turtle)
if turtle.stack == nil then
turtle.stack = {}
end
table.insert(turtle.stack,
{x = turtle.x, y = turtle.y, facing = turtle.facing, width = turtle.width})
end
-- Pop the turtle state from the tock of the stack and apply it.
function pop(turtle)
local val = turtle.stack[#turtle.stack]
table.remove(turtle.stack)
turtle.x = val.x
turtle.y = val.y
turtle.facing = val.facing
turtle.width = val.width
end
-- Mapping of command character to turtle action.
local actions = {
["F"] = function(turtle) draw_forward(turtle) end,
["-"] = function(turtle) left(turtle) end,
["+"] = function(turtle) right(turtle) end,
["["] = function(turtle) push(turtle) end,
["]"] = function(turtle) pop(turtle) end
}
-- Drive the turtle according to the given direction string.
function drive_turtle(turtle, directions)
for char in directions:gmatch(".") do
local fnc = actions[char]
if fnc ~= nil then
fnc(turtle)
end
end
if turtle.path ~= nil then
turtle.path.closed = true
end
end
-- Run the L-system productions n times on the given "initial" string (the axiom).
-- Return the resulting command string.
function run_productions(initial, productions, n)
local acc = initial
for i = 1, n do
-- For each char in acc, replace it and append to new acc.
-- then swap acc = newacc
local newacc = ""
for char in acc:gmatch(".") do
local repl = productions[char]
if repl ~= nil then
newacc = newacc .. repl
else
newacc = newacc .. char
end
end
acc = newacc
end
return acc
end
local directions = run_productions("F-", {
["F"] = "FF+F"
}, 3)
local t = make_turtle(30, 90)
place_turtle(t, 100, 100, 90)
drive_turtle(t, directions)
ellipse(100, 100, 1, 1)
Layer 1