Where ideas percolate and thoughts brew

The Curiosity Trap

About This Sketch

A visual comparison of scattered curiosity versus focused execution. Watch as unbounded curiosity spawns endless new interests while rarely completing anything, while focused execution steadily produces tangible results by maintaining attention on one goal at a time.

Algorithm

This sketch visualizes the contrast between unbounded curiosity and focused execution through two animated personas. The left side shows "Unbounded Curiosity"—a person whose attention constantly splinters into new interests. New interest points spawn regularly, creating a cloud of scattered exploration. Each interest pulses and glows when new, then fades as attention shifts to the next shiny thing. Despite all this exploration, actual output (completed work) is rare because energy is constantly diverted to new explorations. The right side shows "Focused Execution"—a person with a single target and steady progress toward completion. A focused beam of attention connects the person to their goal. A progress indicator shows steady advancement. When work completes, tangible output is created and floats upward, then new focused work begins. This person produces regular results because attention isn't fragmented. The sketch accompanies the blog post "The Curiosity Trap" and visualizes its central argument: unlimited curiosity without execution constraints becomes sophisticated procrastination.

Pseudocode

SETUP:
  Initialize canvas (400x300)
  Create CuriousPerson (left side)
    - Start with 3 random interests
    - Track total interest count
  Create FocusedPerson (right side)
    - Single target above person
    - Progress starts at 0

DRAW (every frame):
  Get current theme colors
  Clear background

  CURIOUS PERSON:
    Every 60 frames:
      - Spawn new interest at random angle/distance
      - Increment total interest count
    For each interest:
      - Age the interest
      - After 180 frames, start fading (abandoned)
      - Draw connection line
      - Draw pulsing interest point
      - Add glow to new interests
    Rarely (0.5% chance) produce output
    Draw person at center
    Draw radiating attention waves (unfocused)

  FOCUSED PERSON:
    Increment progress by 0.5 each frame
    When progress reaches 100:
      - Create completed output object
      - Reset progress to 0 (start new work)
    For each completed output:
      - Age and fade gradually
      - Float upward slightly
    Draw connection beam to target
    Draw target with progress arc
    Draw person at center

  Display labels and statistics
  Show contrast in shipped work count

Source Code

let sketch = function(p) {
    let curiousPerson;
    let focusedPerson;
    let time = 0;

    class CuriousPerson {
        constructor() {
            this.x = 100;
            this.y = 150;
            this.interests = [];
            this.interestCount = 0;
            this.output = 0;

            // Start with a few interests
            for (let i = 0; i < 3; i++) {
                this.addInterest();
            }
        }

        addInterest() {
            let angle = p.random(p.TWO_PI);
            let distance = p.random(30, 70);
            this.interests.push({
                x: this.x + p.cos(angle) * distance,
                y: this.y + p.sin(angle) * distance,
                age: 0,
                explored: false,
                alpha: 255
            });
            this.interestCount++;
        }

        update() {
            // Add new interests frequently (curiosity spawning more curiosity)
            if (p.frameCount % 60 === 0 && this.interests.length < 15) {
                this.addInterest();
            }

            // Age interests
            for (let i = this.interests.length - 1; i >= 0; i--) {
                let interest = this.interests[i];
                interest.age++;

                // Fade out old interests (abandoned for new ones)
                if (interest.age > 180) {
                    interest.alpha = p.max(0, interest.alpha - 3);
                    if (interest.alpha <= 0) {
                        this.interests.splice(i, 1);
                    }
                }
            }

            // Very rarely produce output (too busy exploring)
            if (p.random() < 0.005) {
                this.output++;
            }
        }

        display(colors) {
            // Draw all interests as scattered points
            for (let interest of this.interests) {
                // Connection line
                p.stroke(...colors.accent3, interest.alpha * 0.3);
                p.strokeWeight(1);
                p.line(this.x, this.y, interest.x, interest.y);

                // Interest point (pulsing to show active exploration)
                let pulse = p.sin(interest.age * 0.1) * 0.3 + 0.7;
                p.noStroke();
                p.fill(...colors.accent3, interest.alpha);
                p.circle(interest.x, interest.y, 8 * pulse);

                // Glow around new interests
                if (interest.age < 60) {
                    p.fill(...colors.accent3, (60 - interest.age) * 2);
                    p.circle(interest.x, interest.y, 12);
                }
            }

            // Draw the person (scattered attention)
            p.noStroke();
            p.fill(...colors.accent3, 180);
            p.circle(this.x, this.y, 14);

            // Attention radiating outward (unfocused)
            for (let i = 0; i < 3; i++) {
                let radius = (time * 2 + i * 20) % 60;
                let alpha = p.map(radius, 0, 60, 100, 0);
                p.stroke(...colors.accent3, alpha);
                p.strokeWeight(1);
                p.noFill();
                p.circle(this.x, this.y, radius);
            }
        }
    }

    class FocusedPerson {
        constructor() {
            this.x = 300;
            this.y = 150;
            this.target = {
                x: this.x,
                y: this.y - 60,
                progress: 0
            };
            this.output = 0;
            this.completedOutputs = [];
        }

        update() {
            // Steady progress on one thing
            if (this.target.progress < 100) {
                this.target.progress += 0.5;
            } else {
                // Complete the work, create output
                this.completedOutputs.push({
                    x: this.target.x + p.random(-15, 15),
                    y: this.target.y - 30,
                    age: 0,
                    alpha: 255
                });
                this.output++;

                // Start new focused work
                this.target.progress = 0;
            }

            // Age and fade completed outputs
            for (let i = this.completedOutputs.length - 1; i >= 0; i--) {
                let output = this.completedOutputs[i];
                output.age++;

                // Move up slightly
                output.y -= 0.3;

                if (output.age > 200) {
                    output.alpha = p.max(0, output.alpha - 2);
                    if (output.alpha <= 0) {
                        this.completedOutputs.splice(i, 1);
                    }
                }
            }
        }

        display(colors) {
            // Draw completed outputs
            for (let output of this.completedOutputs) {
                p.noStroke();
                p.fill(...colors.accent2, output.alpha);
                p.circle(output.x, output.y, 18);

                // Glow
                p.fill(...colors.accent2, output.alpha * 0.4);
                p.circle(output.x, output.y, 28);
            }

            // Draw connection to current target
            p.stroke(...colors.accent2, 200);
            p.strokeWeight(2);
            p.line(this.x, this.y, this.target.x, this.target.y);

            // Draw target (single point of focus)
            p.noStroke();
            p.fill(...colors.accent2, 220);
            p.circle(this.target.x, this.target.y, 16);

            // Progress indicator around target
            let progressAngle = p.map(this.target.progress, 0, 100, 0, p.TWO_PI);
            p.noFill();
            p.stroke(...colors.accent2, 200);
            p.strokeWeight(3);
            p.arc(this.target.x, this.target.y, 28, 28, -p.HALF_PI, -p.HALF_PI + progressAngle);

            // Draw the person (focused)
            p.noStroke();
            p.fill(...colors.accent2, 200);
            p.circle(this.x, this.y, 14);

            // Focused beam toward target
            p.stroke(...colors.accent2, 60);
            p.strokeWeight(20);
            p.line(this.x, this.y, this.target.x, this.target.y);
        }
    }

    p.setup = function() {
        p.createCanvas(400, 300);
        p.colorMode(p.RGB);

        curiousPerson = new CuriousPerson();
        focusedPerson = new FocusedPerson();
    };

    p.draw = function() {
        const colors = getThemeColors();
        p.background(...colors.bg);

        time++;

        // Labels
        p.noStroke();
        p.fill(...colors.accent1, 180);
        p.textAlign(p.CENTER);
        p.textSize(11);
        p.text('Unbounded Curiosity', 100, 30);
        p.text('Focused Execution', 300, 30);

        // Divider
        p.stroke(...colors.accent1, 50);
        p.strokeWeight(1);
        p.line(200, 40, 200, 260);

        // Update and display
        curiousPerson.update();
        focusedPerson.update();

        curiousPerson.display(colors);
        focusedPerson.display(colors);

        // Stats
        p.noStroke();
        p.textSize(9);
        p.textAlign(p.LEFT);
        p.fill(...colors.accent3, 150);
        p.text(`Topics explored: ${curiousPerson.interestCount}`, 20, 270);
        p.text(`Shipped: ${curiousPerson.output}`, 20, 283);

        p.textAlign(p.RIGHT);
        p.fill(...colors.accent2, 150);
        p.text(`Projects: ${focusedPerson.output}`, 380, 270);
        p.text(`Shipped: ${focusedPerson.output}`, 380, 283);

        // Bottom message
        p.textAlign(p.CENTER);
        p.fill(...colors.accent1, 140);
        p.textSize(9);
        p.text('Curiosity without execution is just procrastination', 200, 295);
    };
};