`turtle`module in Python's standard library, plus several other implementations.

But all the implementations I know of keep the poor little turtle stuck inside a dull little window. Last night I realized that, with Sikuli, I can set the turtle free! It can roam freely beyond one little window and have adventures in the big, wide world. Here it is marching right past the edge of TuxPaint and onto GNU Paint.

Note that this is an invisible turtle. But you can see its effects.

For the new free-range turtle, "penDown" and "penUp" are actually "mouse button down" and "mouse button up". If it's walking across a drawing program with a paintbrush turned on, it will paint a line like a traditional Logo turtle. Otherwise, it will click and drag its way across your desktop and your other applications. This turtle can be mischievous!

What really pleased me was just how easy it was to implement with Sikuli. Here's the code in an .skl bundle - it's a zipfile that Sikuli can use directly.

import math

class Turtle(object):

def __init__(self):

self.heading = 0

self.penDown()

self.loc = Env.getMouseLocation()

def forward(self, distance):

sin = math.sin(math.radians(self.heading))

cos = math.cos(math.radians(self.heading))

endpoint = (int(self.loc.x + cos * distance),

int(self.loc.y + sin * distance))

if self.down:

dragDrop(self.loc, endpoint)

else:

mouseMove(endpoint)

self.loc = Location(*endpoint)

def backward(self, distance):

self.forward(distance * -1)

def right(self, degrees):

self.heading = (self.heading + degrees) % 360

def left(self, degrees):

self.right(-1 * degrees)

def penUp(self):

self.down = False

def penDown(self):

self.down = True

def circle(self, radius, extent=360., steps=20):

circ = 2 * math.pi * radius

fraction = extent / 360.

step_length = (circ * fraction) / steps

for i in range(steps):

self.forward(step_length)

self.left(360. * fraction / steps)

def zigzag(startHeading, size, angle, steps):

t = Turtle()

t.heading = startHeading

t.left(angle * 0.5)

for i in range(steps):

t.forward(size)

t.right(angle)

t.forward(size)

t.left(angle)