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);
};
};