Why Advice Fails
About This Sketch
A visual exploration of survivorship bias in advice. Multiple paths try to reach the same goal, but most wander aimlessly. We only remember the ones that succeeded—creating the illusion that their specific paths represent universal truth. This sketch accompanies the blog post "Why Advice Fails" exploring why guidance from successful people is often misleading.
Algorithm
This sketch visualizes the survivorship bias and context collapse problems in advice-giving.
Multiple paths emanate from a source (advice) trying to reach a target (your goal). Most paths (representing bad or context-inappropriate advice) wander randomly with high variance, often failing to reach the destination. A small percentage of paths (good advice or lucky fits) take more direct routes.
The key insight: we only see the paths that succeeded (survivorship bias), and we assume those successful paths represent good advice when they might just be lucky. The wandering paths that fail fade away, invisible to observers, while successful paths remain visible—creating the illusion that all advice from successful people must be good.
The visualization cycles continuously, showing how each generation of advice-seekers sees different successful paths, reinforcing the pattern.
Pseudocode
SETUP:
Initialize canvas (400x300)
Create 8 advice paths from source to various targets
80% are "bad advice" (high random wander)
20% are "good advice" (low random wander)
DRAW (every frame):
Get current theme colors
Draw semi-transparent background (creates trail effect)
For each path:
If not complete:
Calculate direction to target
Add random deviation (more for bad advice)
Add new point along wandering path
Fade out over time if not reaching target
If complete:
Keep path visible (survivor bias visibility)
Draw source and target points
Draw labels
If 70% of paths complete or exhausted:
Reset and create new generation of paths
Source Code
let sketch = function(p) {
let paths = [];
let numPaths = 8;
class AdvicePath {
constructor(startX, startY, targetX, targetY, isGood) {
this.points = [{x: startX, y: startY}];
this.targetX = targetX;
this.targetY = targetY;
this.isGood = isGood;
this.wanderAmount = isGood ? 0.5 : 3.0; // Good advice has less random wander
this.complete = false;
this.age = 0;
}
update() {
if (this.complete) {
this.age++;
return;
}
let last = this.points[this.points.length - 1];
// Direction toward target
let dx = this.targetX - last.x;
let dy = this.targetY - last.y;
let dist = p.sqrt(dx * dx + dy * dy);
if (dist < 5) {
this.complete = true;
return;
}
// Normalize direction
dx /= dist;
dy /= dist;
// Add random wander (more for bad advice)
let angle = p.atan2(dy, dx);
angle += p.random(-this.wanderAmount, this.wanderAmount);
// Step forward
let stepSize = 2;
let newX = last.x + p.cos(angle) * stepSize;
let newY = last.y + p.sin(angle) * stepSize;
this.points.push({x: newX, y: newY});
// Keep only recent points
if (this.points.length > 150) {
this.points.shift();
}
}
display(colors) {
if (this.points.length < 2) return;
p.noFill();
// Bad advice (most paths) fade out if they haven't reached target
if (!this.isGood && !this.complete) {
let alpha = p.map(this.points.length, 0, 150, 180, 20);
p.stroke(...colors.accent3, alpha);
} else if (!this.isGood && this.complete) {
// Bad advice that reached target (survivor bias)
let alpha = p.map(this.age, 0, 100, 200, 80);
p.stroke(...colors.accent2, alpha);
} else {
// Good advice - clear path
p.stroke(...colors.accent1, 200);
}
p.strokeWeight(this.isGood ? 2 : 1);
p.beginShape();
for (let pt of this.points) {
p.vertex(pt.x, pt.y);
}
p.endShape();
}
}
p.setup = function() {
p.createCanvas(400, 300);
// Create multiple advice paths from left to right
// Most are bad advice (wander a lot)
// Only 1-2 are good advice (direct path)
for (let i = 0; i < numPaths; i++) {
let startY = p.random(50, 250);
let targetY = p.random(50, 250);
let isGood = p.random() < 0.2; // 20% chance of being "good advice"
paths.push(new AdvicePath(20, startY, 380, targetY, isGood));
}
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg, 25); // Trail effect
// Update and display all paths
for (let path of paths) {
path.update();
path.display(colors);
}
// Draw source (advice giver) and target (your goal)
p.fill(...colors.accent2);
p.noStroke();
p.ellipse(20, 150, 12, 12);
p.ellipse(380, 150, 12, 12);
// Label
p.fill(...colors.accent3);
p.textSize(10);
p.textAlign(p.CENTER);
p.text('Advice', 20, 30);
p.text('Your Goal', 380, 30);
// Reset when most paths are complete or too long
let completedOrTired = paths.filter(p => p.complete || p.points.length > 140).length;
if (completedOrTired > numPaths * 0.7) {
paths = [];
for (let i = 0; i < numPaths; i++) {
let startY = p.random(50, 250);
let targetY = p.random(50, 250);
let isGood = p.random() < 0.2;
paths.push(new AdvicePath(20, startY, 380, targetY, isGood));
}
}
};
};