Where ideas percolate and thoughts brew

Stop Trying to Know Yourself

About This Sketch

Behavior and introspection side by side. Ten particles orbit a center on each half of the canvas — on the left, following clean predictable paths; on the right, the same particles with their trajectories warped by Perlin noise. The underlying pattern is identical. The visibility of it is not.

Accompanies the post on why introspective reports are unreliable guides to self-knowledge, and why behavioral evidence tells you more about yourself than looking inward.

Algorithm

Ten particles orbit a central point on each side of a divided canvas. Left (behavior): particles follow clean, stable orbital paths at fixed radii. Right (introspection): identical particles have their radius and angular position continuously warped by Perlin noise, making their paths drift and scatter. The same underlying motion — the same dots, the same starting conditions — appears legible on the behavioral side and chaotic on the introspective side. This sketch accompanies the post "Stop Trying to Know Yourself," which argues that behavioral patterns are more reliable guides to self-knowledge than introspective reports, which research shows are largely post-hoc narratives.

Pseudocode

SETUP:
  Initialize 10 behavior dots with orbital angles, radii, speeds
  Initialize 10 introspection dots with same parameters + noise seeds
  Canvas 400x300

DRAW (every frame):
  Get theme colors
  Clear background
  Draw dashed dividing line at x=200
  Draw column labels: "behavior" left, "introspection" right
  Draw faint orbit guide rings on left side

  FOR each behavior dot:
    Advance angle by speed
    Compute (x, y) from clean orbital math
    Draw dot at position

  FOR each introspection dot:
    Advance angle by speed
    Sample Perlin noise to warp radius (+/- 27px)
    Sample second noise stream to warp angle (+/- 0.6 rad)
    Compute (x, y) from noisy orbital math
    Constrain to right half of canvas
    Draw dot at drifted position

  Draw caption at bottom

Source Code

let sketch = function(p) {
    let behaviorDots = [];
    let introDots = [];
    let numDots = 10;
    let centerY = 150;
    let leftCX = 105;
    let rightCX = 295;

    p.setup = function() {
        p.createCanvas(400, 300);
        p.frameRate(30);

        for (let i = 0; i < numDots; i++) {
            let angle = (i / numDots) * p.TWO_PI;
            let radius = 35 + (i % 3) * 22;
            behaviorDots.push({
                angle: angle,
                radius: radius,
                speed: 0.012 + (i % 3) * 0.004
            });
            introDots.push({
                angle: angle,
                radius: radius,
                speed: 0.012 + (i % 3) * 0.004,
                seed: p.random(0, 100)
            });
        }
    };

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

        let t = p.frameCount * 0.008;

        p.stroke(...colors.accent3, 50);
        p.strokeWeight(1);
        p.drawingContext.setLineDash([4, 8]);
        p.line(200, 30, 200, 270);
        p.drawingContext.setLineDash([]);

        p.noStroke();
        p.textFont('Georgia');
        p.textSize(10);
        p.textAlign(p.CENTER);
        p.fill(...colors.accent2, 190);
        p.text('behavior', leftCX, 22);
        p.fill(...colors.accent1, 190);
        p.text('introspection', rightCX, 22);

        let radii = [35, 57, 79];
        for (let r of radii) {
            p.noFill();
            p.stroke(...colors.accent2, 22);
            p.strokeWeight(1);
            p.circle(leftCX, centerY, r * 2);
        }

        for (let dot of behaviorDots) {
            dot.angle += dot.speed;
            let x = leftCX + p.cos(dot.angle) * dot.radius;
            let y = centerY + p.sin(dot.angle) * dot.radius;
            p.noStroke();
            p.fill(...colors.accent2, 210);
            p.circle(x, y, 7);
        }

        for (let dot of introDots) {
            dot.angle += dot.speed;
            let radiusNoise = (p.noise(dot.seed, t) - 0.5) * 55;
            let angleNoise = (p.noise(dot.seed + 50, t * 0.7) - 0.5) * 1.2;
            let r = dot.radius + radiusNoise;
            let a = dot.angle + angleNoise;
            let x = rightCX + p.cos(a) * r;
            let y = centerY + p.sin(a) * r;
            x = p.constrain(x, 215, 385);
            y = p.constrain(y, 40, 260);
            p.noStroke();
            p.fill(...colors.accent1, 180);
            p.circle(x, y, 7);
        }

        p.fill(...colors.text, 90);
        p.textSize(9);
        p.textAlign(p.CENTER);
        p.text('the same underlying pattern — seen two ways', 200, 287);
    };
};