    # --- GEOMETRY --------------------------------------------------------------

    from math import degrees, atan2
    from math import sqrt, pow
    from math import radians, sin, cos

    def angle(x0, y0, x1, y1):
        """ Returns the angle between two points.
        """
        return degrees( atan2(y1-y0, x1-x0) )

    def distance(x0, y0, x1, y1):
        """ Returns the distance between two points.
        """
        return sqrt(pow(x1-x0, 2) + pow(y1-y0, 2))

    def coordinates(x0, y0, distance, angle):
        """ Returns the coordinates of given distance and angle from a point.
        """
        return (x0 + cos(radians(angle)) * distance,
                y0 + sin(radians(angle)) * distance)

    # --- WORLD -----------------------------------------------------------------

    class World:
        def __init__(self):
            self.obstacles = []

    # --- OBSTACLE --------------------------------------------------------------

    class Obstacle:
        def __init__(self, x, y, radius):
            self.x = x
            self.y = y
            self.radius = radius

    # --- CREATURE --------------------------------------------------------------

    class Creature:

        def __init__(self, world, x, y, speed=1.0, size=4):

            self.x = x
            self.y = y
            self.speed = speed
            self.size = size

            self.world = world
            self.feeler_length = 25

            self._vx = 0
            self._vy = 0

        def heading(self):

            """ Returns the creature's heading as angle in degrees.
            """

            return angle(self.x, self.y, self.x+self._vx, self.y+self._vy)

        def avoid_obstacles(self, m=0.4, collision=4):

            # Find out where the creature is going.
            a = self.heading()

            for obstacle in self.world.obstacles:

                # Calculate the distance between the creature and the obstacle.
                d = distance(self.x, self.y, obstacle.x, obstacle.y)

                # Respond faster if the creature is very close to an obstacle.
                if d - obstacle.radius < 4: m *= 10

                # Check if the tip of the feeler falls inside the obstacle.
                # This is never true if the feeler length
                # is smaller than the distance to the obstable.
                if d - obstacle.radius <= self.feeler_length:
                    tip_x, tip_y = coordinates(self.x, self.y, d, a)
                    if distance(obstacle.x, obstacle.y,
                                tip_x, tip_y) < obstacle.radius:

                        # Nudge the creature away from the obstacle.
                        m *= self.speed

                        if tip_x < obstacle.x: self._vx -= random(m)
                        if tip_y < obstacle.y: self._vy -= random(m)
                        if tip_x > obstacle.x: self._vx += random(m)
                        if tip_y > obstacle.y: self._vy += random(m)

                        if d - obstacle.radius < 4: return

        def roam(self):

            """ Creature changes heading aimlessly.
            With its feeler it will scan for obstacles and steer away.
            """

            self.avoid_obstacles()

            v = self.speed
            self._vx += random(-v, v)
            self._vy += random(-v, v)
            self._vx = max(-v, min(self._vx, v))
            self._vy = max(-v, min(self._vy, v))

            self.x += self._vx
            self.y += self._vy

    # ---------------------------------------------------------------------------

    size(550, 200)

    # Create a world with obstacles at random positions.
    world = World()
    for i in range(15):
        obstacle = Obstacle(random(WIDTH), random(HEIGHT), random(10, 30))
        world.obstacles.append(obstacle)

    # Create a number of ants.
    ants = []
    for i in range(4):
        ant = Creature(world, 225, 100, speed=2.0)
        ants.append(ant)

    speed(30)
    def draw():

        background(0.2)

        # Draw all the obstacles in the world.
        fill(0.5, 0.5)
        for obstacle in world.obstacles:
            oval(obstacle.x - obstacle.radius,
                 obstacle.y - obstacle.radius,
                 obstacle.radius * 2,
                 obstacle.radius * 2)

        # Draw each ant and its feeler.
        stroke(1)
        fill(1, 0.5)
        for ant in ants:
            push()
            transform(CORNER)
            translate(ant.x, ant.y)
            rotate(-ant.heading())
            line(0, 0, ant.feeler_length, 0)
            pop()
            oval(ant.x-ant.size*0.5, ant.y-ant.size*0.5, ant.size, ant.size)

        # Move all the ants around.
        for ant in ants:
            ant.roam()