shiffman_pearson_textbook · boidsClassic
Reynolds Boids (Separation / Alignment / Cohesion)
Reynolds' classic boids flocking model. Each of N agents has position and velocity. On every tick three steering rules are computed for each boid relative to its local neighbours: (1) separation — steer away from neighbours inside sep_radius with magnitude inversely proportional to distance; (2) alignment — steer toward the average velocity of neighbours inside ali_radius; (3) cohesion — steer toward the centroid of neighbours inside coh_radius. Each rule produces a desired velocity; the steering force is desired minus current velocity, capped at max_force. Position updates wrap toroidally on the square canvas. Boids leave a fading trail plus a bright head dot.
Original: https://natureofcode.com/autonomous-agents/
▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.
Math essence
Toroidal pairwise distances via diff - dim*round(diff/dim). Per boid: sep_desired = mean(diff/(d^2 + eps)) over sep-neighbours; ali_desired = mean(velocity) over ali-neighbours; coh_desired = centroid(positions) - position over coh-neighbours. steer = limit(desired - vel, max_force). vel += weighted_sum(steers); vel = limit(vel, max_speed); pos = (pos + vel) mod dim. Canvas blending: canvas[p] = (1 - alpha) * canvas[p] + alpha * ink.
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 480 | 200–1200 | Square canvas side length (toroidal). |
num_boids | int | 150 | 20–600 | Population size; Reynolds' canonical demo used ~150. |
perception_r | float | 50 | 5–200 | Default perception radius used when ali/coh radii are None. |
sep_radius | float | 24 | 2–200 | Separation perception radius. |
ali_radius | float | 50 | 5–300 | Alignment perception radius. |
coh_radius | float | 50 | 5–300 | Cohesion perception radius. |
sep_weight | float | 1.5 | 0–5 | Separation weight in acceleration sum. |
ali_weight | float | 1 | 0–5 | Alignment weight in acceleration sum. |
coh_weight | float | 1 | 0–5 | Cohesion weight in acceleration sum. |
max_speed | float | 3.5 | 0.5–12 | Velocity clamp (pixels per tick). |
max_force | float | 0.18 | 0.01–1 | Steering force clamp per rule. |
trail_alpha | float | 0.35 | 0.01–1 | Trail blend opacity per segment. |
bg_color | tuple | 20,24,36 | — | |
ink_color | tuple | 200,220,255 | — | |
head_color | tuple | 255,220,130 | — | |
seed | int | null | 0–999999 |
Reference
First 60 lines of reference.py. Full source:
library_external/shiffman_pearson_textbook/boidsClassic/reference.py
from __future__ import annotations
from typing import ClassVar
import numpy as np
class BoidsClassic:
"""Reynolds boids flocking (separation, alignment, cohesion).
Implements the three classic Reynolds 1987 steering rules on a population
of N point-boids with position and velocity:
- **separation**: steer away from neighbours within ``sep_radius``
(weighted inversely with distance).
- **alignment**: steer toward the average heading of neighbours within
``ali_radius``.
- **cohesion**: steer toward the centroid of neighbours within
``coh_radius``.
Each rule produces a *desired* velocity; the steering force is the
difference between desired and current velocity, capped at ``max_force``.
Acceleration is integrated with explicit Euler, velocities are clamped to
``max_speed``, and the canvas wraps toroidally. Boids draw a short fading
trail of their previous positions. This is the canonical Nature of Code /
Coding Train / Generative Art formulation.
Parameters
----------
dim : int
Square canvas side length (torus topology).
num_boids : int
Population size. Default 150 per Reynolds' original.
perception_r : float
Default radius for cohesion and alignment; separation uses its own.
sep_radius, ali_radius, coh_radius : float | None
Per-rule radii (default to ``perception_r`` if None).
sep_weight, ali_weight, coh_weight : float
Mixing weights for the three steering rules.
max_speed, max_force : float
Velocity and steering clamps.
trail_alpha : float
Per-segment trail fade.
"""
family: ClassVar[str] = "shiffman_pearson_textbook"
sketch: ClassVar[str] = "boidsClassic"
def __init__(
self,
dim: int = 480,
num_boids: int = 150,
perception_r: float = 50.0,
sep_radius: float | None = 24.0,
ali_radius: float | None = 50.0,
coh_radius: float | None = 50.0,
sep_weight: float = 1.5,
ali_weight: float = 1.0,
coh_weight: float = 1.0,
max_speed: float = 3.5, Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/shiffman_pearson_textbook/boidsClassic/reference.py Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.
More from shiffman · pearson
Genetic Algorithm (Evolve Toward Target String)
shiffman_pearson_textbook · geneticAlgorithmString
A textbook genetic algorithm that evolves a population of binary strings toward a target ASCII string (default 'HELLO WORLD!').
Lindenmayer L-System (Textbook Formulation)
shiffman_pearson_textbook · lindenmayerTextbook
Lindenmayer L-system string rewriting with a 2-D turtle interpreter, the canonical textbook formulation used in both Shiffman's Nature of Code Ch.
Mandelbrot Set (Escape-Time Fractal)
shiffman_pearson_textbook · mandelbrotSet
The Mandelbrot set rendered by escape-time iteration of z = z^2 + c on a window of the complex plane.
Perlin Noise Flow Field
shiffman_pearson_textbook · perlinFlowField
A 2-D scalar field of Perlin gradient noise is sampled on a coarse grid; each cell is assigned a heading theta = 2*pi * n.
Random Walk / Drunkard's Walk
shiffman_pearson_textbook · randomWalkDrunkard
Many random walkers each start at the canvas center and take a stochastic 2-D step every tick.
Stochastic Recursive Fractal Tree
shiffman_pearson_textbook · recursiveTree
Stack-based stochastic fractal tree from Shiffman's Nature of Code Ch.