Shiffman teaches at NYU ITP/IMA, co-founded the Processing Foundation, and runs The Coding Train, which is how a lot of people, including myself, first discover the joy of creative coding! The Nature of Code (No Starch / Penguin, 2024) is the JavaScript and p5.js reboot of the 2012 Processing edition.

Online edition and examples: natureofcode.com. Below, several chapters include a short runnable exercise (p5.js in the page): try the prompt yourself, then reveal a solution sketch.

Each chapter summary in this post also embeds a live expansion sketch from my Emergence Atlas playground (write-ups in Growing Wild Gardens), plus a Make it real strategy for pointing that chapter’s ideas at real data from a keyless public API.

Chapter by chapter

Introduction

Shiffman sets the book up as a single story told in three acts:

  1. Inanimate motion under named forces
  2. Life-like systems (agents, automata, fractals)
  3. The phenomena of seeming intelligence (evolution, neural nets, neuroevolution)

The recurring homework in the book is an “Ecosystem Project”, a simulated world you can keep extending as each chapter adds a new mechanism. I love this beautiful structure!

Basic programming comfort helps with the Javascript version of Processing used in this book. A physics degree is absolutely not required. The Coding Train videos on Daniel’s YouTube channel are great to watch alongside the exercises in each of the chapters.

Chapter 0: Randomness

The book starts with coding out a random walk. At each step a walker picks a displacement \(\Delta \vec{x}\) from some distribution and adds it: \(\vec{x}_{t+1} = \vec{x}_t + \Delta \vec{x}\). Change the distribution and the picture changes. Draw \(\Delta x\) and \(\Delta y\) from a uniform interval.

If you draw them from a Gaussian, the walker stays local most of the time, the same way pollen on water jitters under Brownian motion without suddenly teleporting across the dish:

\[ P(\Delta x) = \frac{1}{\sigma\sqrt{2\pi}}\, e^{-\Delta x^{2}/(2\sigma^{2})}. \]

Rare large jumps need a heavy-tailed family instead: a Lévy-style step where \(P(|\ell|) \propto |\ell|^{-(1+\alpha)}\) for \(\alpha \in (0,2)\). Most steps are tiny; every so often one is enormous. That is how some foraging animals actually search, and how earthquake magnitudes pile up under Gutenberg-Richter. The canvas suddenly shows dense clusters linked by faint long leaps.

Then Shiffman introduces Perlin noise: a smooth, coherent field \(n(x,y,t)\) instead of independent draws. Uniform randomness is static. Perlin noise is what we see in weather, wood grain, the slow drift of clouds.

Building a Walker class and swapping only the sampling rule allows you to visualize these patterns. You can see the difference between unstructured noise and structured stochasticity, which is the intuition this chapter helps you develop.

My own expanded sketch: Dust Gardens (write-up in Growing Wild Gardens).

Make it real: Random walks get more interesting when the step sizes come from the real world. Fetch the USGS feed of the past month’s earthquakes (https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson, keyless and CORS friendly, so loadJSON works straight from the browser). Magnitudes follow the Gutenberg-Richter power law, the same heavy-tailed family as a Levy flight. Drive your walker’s step length with successive real magnitudes (something like step = pow(10, mag - 4)) and compare the trail against the Gaussian version. The difference between static and rare catastrophic jumps is the whole lesson of heavy tails, drawn by real seismicity.

Chapter 1: Vectors

A vector \(\vec{v} = (v_x, v_y)\) is an arrow: direction plus magnitude \(\lvert\vec{v}\rvert = \sqrt{v_x^{2} + v_y^{2}}\). Position, velocity, and acceleration are all the same kind of object, related by

\[ \vec{v} = \frac{d\vec{x}}{dt}, \qquad \vec{a} = \frac{d\vec{v}}{dt}. \]

In code that becomes Euler’s method on a canvas. Each frame is \(\vec{v} \leftarrow \vec{v} + \vec{a}\,\Delta t\) and \(\vec{x} \leftarrow \vec{x} + \vec{v}\,\Delta t\). Daniel teaches p5.Vector as the vocabulary for those operations: add, subtract, scale, normalize (\(\hat{v} = \vec{v}/\lvert\vec{v}\rvert\)), set magnitude. The mouse-seeking demo is just building a desired direction \(\vec{x}_{\text{mouse}} - \vec{x}\) and turning it into an acceleration.

This is the math of wind and current. A weather map is a vector field \(\vec{v}(x,y)\): an arrow at every point telling air which way to go. A salmon holding station in a river is continuously correcting against a flow vector.

My own expanded sketch: Compass Meadow (write-up in Growing Wild Gardens).

Make it real: A vector field is more compelling when it is today’s actual weather. Open-Meteo is keyless and CORS friendly: request wind_speed_10m and wind_direction_10m for a grid of lat/lon points around your city (https://api.open-meteo.com/v1/forecast?latitude=40.7&longitude=-74&hourly=wind_speed_10m,wind_direction_10m). Convert each speed and direction pair into a vector, interpolate between grid points, and drop walkers into the field. You get streamlines of the real forecast, and if you animate the hourly index you can watch tomorrow’s front comb the field.

Chapter 2: Forces

Newton’s second law is illustrated throughout this chapter:

\[ \vec{F}_{\text{net}} = m\vec{a} \quad\Rightarrow\quad \vec{a} = \frac{1}{m}\sum_i \vec{F}_i. \]

In each frame I accumulate forces (wind, gravity, friction, drag, attraction), divide by mass, to integrate into motion. Gravity near Earth is \(\vec{F}_g = m\vec{g}\). Between two bodies it is the prettier inverse-square law, which is why planets do not fall in straight lines and why a sketch.

A few attractors mapped out mathematically in motion can quickly simulate a tiny solar system:

\[ \vec{F}_{12} = G\,\frac{m_1 m_2}{r^{2}}\,\hat{r}_{12}. \]

Friction and fluid drag oppose velocity (\(F_d \propto -\lvert\vec{v}\rvert^{2}\) in the quadratic regime), which is why a feather and a hammer disagree in air and agree in vacuum.

What I love about this chapter is the way in which it teaches composition of multiple diverse objects. A leaf in a gust of wind is acted upon by gravity as well as drag by a noisy wind vector. An orbit is animated by continuous free-fall that keeps missing the ground.

My own expanded sketch: Orbital Calligraphy (write-up in Growing Wild Gardens).

Make it real: Make a little solar system by seeding movers with real planetary masses and mean orbital velocities of the inner planets (constants from any ephemeris table). Scale to canvas units, and see whether your integrator can actually keep Mercury in orbit for more than a few minutes. (I can’t seem to do this!) Naive Euler will not actually keep planets in orbit, and this is a lesson in the book between abstract and real forces in the real world.

For live data, you can poll https://api.wheretheiss.at/v1/satellites/25544 (keyless, CORS friendly) every few seconds to draw the real ISS ground position beside your simulated Earth-satellite pair.

Chapter 3: Oscillation

Anything that repeats in time can be shown in simple harmonic motion:

\[ x(t) = A\sin(\omega t + \phi), \qquad \omega = 2\pi f, \]

with amplitude \(A\), angular frequency \(\omega\), and phase \(\phi\). A spring obeying Hooke’s law \(F = -kx\) produces exactly this (for small motion), with \(\omega = \sqrt{k/m}\). A pendulum under the small-angle approximation does the same, with \(\omega = \sqrt{g/L}\). Polar coordinates \((r,\theta)\) and the conversions \(x = r\cos\theta\), \(y = r\sin\theta\) show up constantly: heading, orbits, the way a creature should rotate to face its velocity.

The tides of the ocean are also sums of a few sinusoids (lunar semidiurnal near \(12.42\,\mathrm{h}\), solar near \(12.00\,\mathrm{h}\)). A heartbeat, a dripping faucet, a jellyfish bell, the sway of a skyscraper in wind: these can all be portrayed as oscillators, sometimes coupled or detuned.

My own expanded sketch: Harmonograph Choir (write-up in Growing Wild Gardens).

Make it real: Tides are the natural world’s Fourier series. NOAA’s CO-OPS API serves observed water levels for any US station without a key (https://api.tidesandcurrents.noaa.gov/api/prod/datagetter?date=latest&station=9414290&product=water_level&datum=MLLW&units=metric&time_zone=gmt&format=json). Plot 48 hours of real water level, then try to reproduce it with two or three of simple harmonic oscillators. The lunar semidiurnal constituent at 12.42 hours and the solar at 12.00 hours can get you surprisingly far, and sliders for amplitude and phase can turn the exercise into a harmonic model of the ocean.

Chapter 4: Particle Systems

A particle is a tiny Newton object with a lifespan. Birth starts with an emitter, with vector forces while alive, and decaying to death when life hits zero:

\[ \vec{x}_{t+\Delta t} = \vec{x}_t + \vec{v}\,\Delta t, \qquad \vec{v}_{t+\Delta t} = \vec{v}_t + \vec{a}\,\Delta t, \qquad \ell_{t+\Delta t} = \ell_t - \delta. \]

One particle is boring. A thousand particles with staggered \(\ell\), small random \(\vec{v}\), and a shared force field is how we have smoke, spray, sparks, and snow. The math in chapter 2 is amplified when you put these into an ensemble: manage birth and death rates, apply \(\vec{F}\) to the whole array, cull the dead without leaking memory. Inheritance lets sparks and embers share an update loop while drawing different patterns.

Nature runs particle systems like these constantly. Rain is an emitter in a cloud. A volcanic plume is hot particles under buoyancy and wind. Spore release, blood cells in a vessel, the glitter of a breaking wave: these are all populations of short-lived bodies under shared forces.

My own expanded sketch: Ember Fountain (write-up in Growing Wild Gardens).

Make it real: Give each emitter a city and let live pollution set its behavior. Open-Meteo’s air quality endpoint is keyless (https://air-quality-api.open-meteo.com/v1/air-quality?latitude=52.5&longitude=13.4&hourly=pm2_5). Map PM2.5 to spawn rate and particle opacity, reuse the previous chapter’s real wind vectors as the force pushing the plume, and you have a live smoke map built from your own particle system. Three cities side by side make air quality differences visceral in a way a bar chart never is.

Chapter 5: Autonomous Agents

Craig Reynolds’ steering model is almost embarrassingly small. Desired velocity points at a target; steering is the correction:

\[ \vec{v}_{\text{desired}} = \frac{\vec{x}_{\text{target}} - \vec{x}}{\lvert\vec{x}_{\text{target}} - \vec{x}\rvert}\, v_{\max}, \qquad \vec{F}_{\text{steer}} = \operatorname{clamp}\!\left(\vec{v}_{\text{desired}} - \vec{v},\, F_{\max}\right). \]

Seek, flee, arrive, wander, and path following are variations on that template. Flocking adds three local averages over neighbors inside a radius: separation (don’t crowd), alignment (match \(\langle\vec{v}\rangle\)), cohesion (move toward \(\langle\vec{x}\rangle\)).

Real flocks, schools, and herds run on the same kind of local rules. Each body only knows a neighborhood, and the wave of turns propagates through the body like a flock of birds, which seem to magically know how to navigate emergent change in a collective in flight.

My own expanded sketch: Murmuration (write-up in Growing Wild Gardens).

Make it real: OpenSky’s states endpoint returns every ADS-B aircraft in a bounding box, anonymously and with CORS (https://opensky-network.org/api/states/all?lamin=45&lomin=5&lamax=48&lomax=11). Draw the real planes as triangles oriented by their true heading, then release your boids into the same sky with an added separation rule against the real traffic, refreshing every ten seconds. The flock threading itself through actual holding patterns is emergence negotiating with reality, and it exposes how conservative your separation radii need to be.

Chapter 6: Physics Libraries

Chapters 1 through 5 integrate \(\vec{F} = m\vec{a}\) by hand. Soft bodies, cloth, and stacking boxes want constraints: keep two points a fixed rest length \(\ell_0\) apart, or keep a joint at a fixed angle. Verlet integration stores position and previous position instead of an explicit velocity, then repeatedly projects each constraint back toward \(\lvert\vec{x}_j - \vec{x}_i\rvert = \ell_0\):

\[ \vec{x}_{t+\Delta t} = \vec{x}_t + (\vec{x}_t - \vec{x}_{t-\Delta t}) + \vec{a}\,(\Delta t)^{2}. \]

A grid of points plus distance constraints becomes like a cloth. Matter.js and Toxiclibs.js are used to show these points in motion.

Nature is full of constrained soft matter. A spider’s web is a tensegrity of threads under load. Skin, fascia, a jellyfish bell, a leaf in wind: these are networks of roughly fixed-length fibers that redistribute force when one region stretches.

My own expanded sketch: Soft Loom (write-up in Growing Wild Gardens).

Make it real: Turn the spring lattice into a seismograph. Take the same USGS earthquake feed from chapter 0, map each quake’s longitude to a horizontal position on a hanging verlet cloth, and apply an impulse scaled by magnitude (normalize pow(10, mag) against the largest event) at the moment its time-compressed timestamp arrives. A day of global seismicity replays as ripples through fabric, and strain coloring shows how the largest event dwarfs everything else.

Chapter 7: Cellular Automata

A cellular automaton is a grid where each cell’s next state depends only on a local neighborhood. For Conway’s Game of Life on a cell \(c\) with live-neighbor count \(n\),

\[ c_{t+1} = \begin{cases} 1 & \text{if } n = 3 \quad\text{(birth)}\\ c_t & \text{if } n \in \{2,3\} \quad\text{(survival)}\\ 0 & \text{otherwise (death by loneliness or overcrowding)}. \end{cases} \]

From this formula emerges still lifes, oscillators, gliders, and a simulation that never quite repeats! Life is both incredibly unique in its chaos, and also quite formulaic.

Elementary 1D automata (Wolfram’s rule space) are even smaller: three bits of neighborhood in, one bit out, \(2^8 = 256\) possible rules, some of which make nested triangles and some of which look like noise with structure hiding inside.

In nature, excitable heart tissue, Belousov-Zhabotinsky chemical waves, the advancing front of a forest fire or an invasive species, are all examples of this algorithm. Each patch only knows its neighbors. Yet, nevertheless, a coherent pattern travels across the field. (This is also a useful reminder that interesting computation does not have to be gradient descent.)

My own expanded sketch: Bloom Automata (write-up in Growing Wild Gardens).

Make it real: GBIF’s occurrence API is keyless and CORS friendly. Query an invasive species year by year (https://api.gbif.org/v1/occurrence/search?scientificName=Vespa%20velutina&year=2015&limit=300 for the Asian hornet in Europe). Rasterize each year’s coordinates onto your CA grid as live cells, then tune a probabilistic spread rule until the automaton’s year-over-year growth resembles the real invasion front. You are doing informal model calibration, which is what a lot of spatial ecology actually is.

Chapter 8: Fractals

A fractal here is a shape built by recursion, with self-similarity that obeys the same rule at every scale. For example, the Cantor set removes middle thirds forever. The Koch curve replaces each segment with four segments of length \(1/3\), and the limiting length diverges while the curve stays bounded. A binary tree is every engineer’s most familiar Leetcode algorithm visualized on a canvas:

\[ \text{branch}(L) \;=\; \text{line of length } L \;\text{ then }\; \text{branch}(r L) \text{ left and right}, \]

with \(r < 1\) until \(L\) is too small to draw. L-systems push the same idea into a rewriting grammar: a string of symbols expands by production rules, then a turtle interprets the string as drawing commands. Branching angle and contraction ratio become the genotype of a plant.

Tree limbs, bronchial airways, river networks, and lightning forks all approximate space-filling branching where a similar motif repeats at smaller scales. The coastline paradox (measured length grows as the ruler shrinks) is the same self-similarity biting surveyors.

My own expanded sketch: Wind Grove (write-up in Growing Wild Gardens).

Make it real: River basins are nature’s recursion. USGS Water Services returns live discharge for any gauge without a key (https://waterservices.usgs.gov/nwis/iv/?format=json&sites=09380000&parameterCd=00060). Pick a main-stem gauge plus gauges on its tributaries, build your recursive tree so each branch’s thickness scales with its gauge’s real-time discharge, and let the noise sway stand in for turbulence. The tree becomes a living hydrograph: after a storm upstream, one limb visibly fattens.

Chapter 9: Evolutionary Computing

A genetic algorithm treats candidate solutions as genomes in a population. In each generation:

  1. evaluate fitness \(f(g)\) for every genome \(g\),
  2. select parents with probability biased by fitness (roulette, tournament, rank),
  3. recombine (crossover) and mutate to form children,
  4. replace the population and repeat.

Mutation is usually a small random edit; for a real-valued gene, something like \(g_i \leftarrow g_i + \mathcal{N}(0,\sigma^{2})\). Crossover splices two parents so children inherit chunks of each. The “design” is whatever maximizes \(f\).

Darwin’s loop is illustrated here in nature’s algorithm. Beak depth is Darwin’s finches, antibiotic resistance, the way a virus explores sequence space. It’s selection on variation, iterated over and over again.

One thing that this chapter illustrates is how violently a bad fitness function can steer the population. Evolve toward the wrong target and the population gets brilliantly good at the wrong thing. That lesson transfers straight into reward design for learning systems.

My own expanded sketch: Selective Gardens (write-up in Growing Wild Gardens).

Make it real: Give the genetic algorithm a real optimization target. Fetch world capitals with coordinates from REST Countries (https://restcountries.com/v3.1/all?fields=capital,capitalInfo), pick fifteen, and evolve a tour: the genome is the visiting order, fitness is total haversine distance, crossover is ordered crossover, and mutation swaps two stops. Draw the best tour of each generation over a equirectangular projection. Watch the route untangle itself over real geography. This is the classic traveling salesman demo on a map!

Chapter 10: Neural Networks

The perceptron is a linear classifier with a threshold. For inputs \(\vec{x}\) and weights \(\vec{w}\) (plus bias \(b\)),

\[ \hat{y} = f\!\left(\vec{w}\cdot\vec{x} + b\right), \]

where \(f\) might be a step function or a smooth sigmoid \(\sigma(z) = 1/(1+e^{-z})\). Training nudges weights when the prediction is wrong. The classic perceptron update is

\[ \vec{w} \leftarrow \vec{w} + \eta\,(y - \hat{y})\,\vec{x}, \]

with learning rate \(\eta\). Stack layers are the same idea in a multilayer net. Each layer is an affine transform plus nonlinearity. An error at the output propagates backward through the chain rule (backpropagation). Shiffman builds this concept in simple arrays.

This is the mechanism at the center of a neural network for deep learning. However, do not confuse a three-weight perceptron with a neural cortex. This small demo shows how organisms tune response strengths to stimuli. Habituation, sensitization, the way a retina’s receptive field: these are all essentially weighted neighborhood of photoreceptors.

My own expanded sketch: Neural Lace (write-up in Growing Wild Gardens).

Make it real: Swap the synthetic points under the perceptron for real measurements. loadTable can pull the classic Iris dataset from a raw GitHub URL, or fetch a year of daily humidity and pressure from Open-Meteo’s archive endpoint (https://archive-api.open-meteo.com/v1/archive) and label each day by whether it rained. Train the same 3-weight perceptron on two features, draw the decision boundary over the real scatter, and notice which feature pairs are linearly separable and which need the multilayer step.

Chapter 11: Neuroevolution

Neuroevolution is actually chapters 9 and 10 braided together. The genome is the weight vector \(\vec{w}\) of a controller network (sometimes the topology too). Fitness is how well the agent behaves in a simulated environment: distance traveled, food eaten, time survived. Selection, crossover, and mutation search weight space without taking an analytic gradient.

\[ \vec{w}^{\star} \approx \arg\max_{\vec{w}}\; f\!\left(\text{agent}_{\vec{w}}\text{ in environment}\right). \]

That is actually machine learning as population dynamics! Gradients need a differentiable path from reward to weights. Evolution is roughly scored in the same way. In nature, nervous systems are shaped by selection on behavior \(\partial L/\partial w\): bird flight controllers, insect visuomotor loops, the tuning of a fish’s escape response. Brains and behaviors backpropagating through time and evolution.

Pedagogically I think this chapter is absolutely amazing! Even though current ML industry treats neuroevolution as a niche. PyTorch, JAX, CUDA kernels, mixed precision, distributed data-parallel training: all of these mechanisms are built around \(\partial L/\partial w\). However, neuroevolution algorithms require a massive parallel eval to determine fitness score and a lot of independent forward runs, which is not the most cost-efficient technique. It is still useful when fitness is non-differentiable or difficult to differentiate, such as in real robots with sparse rewards, or in AutoML architecture.

Make it real: Combine everything: build the real wind field from the chapter 1 idea, then evolve tiny neural steering brains (inputs: local wind vector and bearing to target; outputs: thrust and turn) for agents that must cross the map on a fuel budget. Selection pressure discovers tacking strategies appropriate to each day’s actual forecast. The next day’s weather silently changes which brains win.

Appendix: Creature Design Tutorial

The last chapter asks me to take many of these mechanisms together to make a little creature! I gave this a try for fun in this sketch of a jellyfish bell.

(Read my write-up for this exercise in Growing Wild Gardens.)