Centuries of a meandering river, with oxbow lakes and scroll bars, on a survey map.
The river is a chain of nodes whose banks migrate every simulated year at a rate set by the channel's curvature: a local term plus a stronger, exponentially fading memory of the curvature upstream, from the bend theory of Ikeda, Parker and Sawai. Bends grow, skew downstream and eventually touch; the neck is then cut off and the loop is abandoned as an oxbow lake that slowly fills into a marsh. Every floodplain cell remembers when the channel last crossed it, so the map is shaded by age from fresh point-bar sand to old forest, and a periodic ripple in that age draws the curved scroll bars that migrating bends leave behind. Valley walls and planted bedrock resist erosion.
Try it. Click to plant a resistant bedrock outcrop. Drag up or down (or press the up and down arrows) to steepen or flatten the valley. Choose Decades, Centuries or Millennia to change the pace (keys 1 to 3), and press R to survey a new valley.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a meandering river simulation with JavaScript and the HTML canvas element. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
Start simple:
- Make a canvas that fills the window and stays sharp on high-DPI screens, with a green floodplain background.
- Represent the river's centerline as an array of points from the left edge to the right edge, spaced about 5 pixels apart, with small random wiggles.
- Each step, compute the curvature at every point from its neighbours. Set a migration rate R0 = k * curvature, then a rate R1 that adds the curvature upstream: R1[i] = -R0[i] + 2.5 * (weighted average of R0 over the previous 15 points, with weights falling off exponentially with distance). This upstream memory is what makes bends grow and drift downstream.
- Move each point sideways (perpendicular to the channel) by R1 times a small time step, keep the two end points fixed, then resample the line to even spacing.
- Cutoffs: if two points that are far apart along the river come closer than about 1.3 channel widths, remove the loop between them and keep it as an oxbow lake.
- Draw the river as a thick blue stroke and the oxbows as thinner blue arcs.
Once that works, make it beautiful:
- Keep an image of the floodplain where each pixel stores the year the channel last passed over it, and colour it by age: pale sand for fresh point bars, then grass, then dark forest. A gentle sine wave in that age draws curved scroll bars.
- Let oxbow lakes shrink and turn into green marsh scars over a few hundred years.
- Style it like a printed survey map: a frame, a title with the year, a scale bar and a north arrow.
Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as valley walls that resist erosion, a speed control for centuries per second, or naming each new oxbow lake.