The Advice Paradox
About This Sketch
An animated visualization exploring how we seek wisdom through consuming advice (represented by hollow, appealing but empty circles) when real understanding only comes through direct experience (solid, substantial circles). The seeker initially chases advice nodes in somewhat aimless patterns before the experience nodes gradually reveal themselves as the actual path to wisdom. This accompanies the essay on why actionable advice is often useless and unactionable advice is what we actually needβonce we've done the work to understand it.
Algorithm
This sketch visualizes the paradox that we seek wisdom through advice (hollow circles)
but can only gain it through experience (solid circles).
The animation shows a seeker initially chasing advice nodes scattered around the canvas,
moving in somewhat aimless patterns. After a period of this fruitless seeking, the
experience nodes gradually become visible, revealing the actual path to understanding.
The hollow advice circles represent how advice looks appealing but is ultimately empty
without context. The solid experience circles represent the substantial learning that
comes from doing. The seeker's journey represents how we often waste time consuming
advice before realizing we need to just start doing things.
Pseudocode
SETUP:
Create canvas (400x300)
Initialize advice nodes (hollow circles) at various positions - visible from start
Initialize experience nodes (solid circles) hidden initially
Create target point representing "wisdom"
DRAW (every frame):
Get current theme colors
Clear background
Increment time counter
IF time > 120 frames:
Gradually reveal experience nodes
Fade them in by increasing alpha
IF time > 150 frames:
Draw connections between experience nodes
Show that experience forms the real path to wisdom
FOR each node:
IF advice node:
Draw as hollow circle (stroke only)
IF experience node AND visible:
Draw as solid circle (filled)
Apply pulsing animation to all visible nodes
UPDATE seeker position:
IF time <= 120:
Seeker chases nearest advice node
Moves in somewhat circular/aimless patterns
ELSE:
Seeker follows linear path
Moving toward experience nodes
Draw seeker as small dot
Display contextual labels based on time
Source Code
let sketch = function(p) {
let nodes = [];
let target = null;
let time = 0;
class Node {
constructor(x, y, label, type) {
this.x = x;
this.y = y;
this.label = label;
this.type = type; // 'advice' or 'experience'
this.alpha = type === 'advice' ? 180 : 120;
this.size = type === 'advice' ? 30 : 25;
this.visible = type === 'advice'; // advice nodes start visible
this.pulseOffset = p.random(p.TWO_PI);
}
display(colors) {
if (!this.visible) return;
let pulse = p.sin(time * 0.05 + this.pulseOffset) * 0.2 + 1;
let currentSize = this.size * pulse;
p.noStroke();
if (this.type === 'advice') {
// Hollow circles for advice (looks appealing but empty)
p.noFill();
p.stroke(...colors.accent1, this.alpha);
p.strokeWeight(2);
p.circle(this.x, this.y, currentSize);
} else {
// Solid circles for experience (substantial)
p.fill(...colors.accent2, this.alpha);
p.circle(this.x, this.y, currentSize);
}
}
}
p.setup = function() {
p.createCanvas(400, 300);
p.colorMode(p.RGB);
// Create advice nodes (what you seek - visible)
nodes.push(new Node(80, 70, 'Read more', 'advice'));
nodes.push(new Node(180, 50, 'Network better', 'advice'));
nodes.push(new Node(280, 80, 'Work harder', 'advice'));
nodes.push(new Node(320, 150, 'Find passion', 'advice'));
nodes.push(new Node(250, 220, 'Be authentic', 'advice'));
nodes.push(new Node(150, 240, 'Ship fast', 'advice'));
nodes.push(new Node(60, 180, 'Stay focused', 'advice'));
// Create experience nodes (what you need - initially hidden)
nodes.push(new Node(120, 110, 'failed project', 'experience'));
nodes.push(new Node(200, 140, 'awkward conversation', 'experience'));
nodes.push(new Node(180, 190, 'public mistake', 'experience'));
nodes.push(new Node(260, 170, 'slow progress', 'experience'));
// Target (the wisdom you're seeking)
target = { x: 200, y: 150, reached: false };
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg);
time++;
// Gradually reveal experience nodes
if (time > 120) {
for (let node of nodes) {
if (node.type === 'experience') {
node.visible = true;
node.alpha = p.min(node.alpha + 2, 200);
}
}
}
// Draw connections between experience nodes (the real path)
if (time > 150) {
p.stroke(...colors.accent2, 60);
p.strokeWeight(2);
let experienceNodes = nodes.filter(n => n.type === 'experience' && n.visible);
for (let i = 0; i < experienceNodes.length - 1; i++) {
p.line(experienceNodes[i].x, experienceNodes[i].y,
experienceNodes[i+1].x, experienceNodes[i+1].y);
}
}
// Draw target (wisdom/understanding)
p.noStroke();
p.fill(...colors.accent3, 150);
p.circle(target.x, target.y, 15);
// Display all nodes
for (let node of nodes) {
node.display(colors);
}
// Draw seeker (cursor moving through space)
let seekerX = 50 + (time % 400);
let seekerY = 150 + p.sin(time * 0.03) * 40;
// Before 120 frames: chasing advice nodes (going in circles)
if (time <= 120) {
let closestAdvice = nodes.filter(n => n.type === 'advice')
.reduce((closest, node) => {
let d = p.dist(seekerX, seekerY, node.x, node.y);
return d < closest.d ? {node, d} : closest;
}, {node: null, d: Infinity});
if (closestAdvice.node) {
seekerX += (closestAdvice.node.x - seekerX) * 0.02;
seekerY += (closestAdvice.node.y - seekerY) * 0.02;
}
}
p.noStroke();
p.fill(...colors.accent1, 220);
p.circle(seekerX, seekerY, 8);
// Labels
p.fill(...colors.accent3, 180);
p.textAlign(p.CENTER);
p.textSize(10);
if (time <= 120) {
p.text('seeking advice...', 200, 290);
p.textSize(8);
p.text('(hollow circles)', 200, 20);
} else if (time <= 180) {
p.text('discovering the real path...', 200, 290);
p.textSize(8);
p.text('(solid circles = experience)', 200, 20);
} else {
p.text('wisdom comes from doing, not reading', 200, 290);
}
};
};