You are the bird: selection turns moths invisible on lichen, then on sooty bark.
Moths rest on a procedurally generated trunk: Worley noise plates split by wandering fissures, a lit height field, and a lichen crust with tiny tiles and black fruiting bodies. Each moth's wings are painted pixel by pixel from a genome of lightness, tint, mottling, grain, speckles and cross lines, plus a carbonaria locus whose dark allele is dominant. When half the moths are eaten, the survivors recombine and mutate, and their offspring settle wherever the bark best matches their wings. Toggle soot to blacken the trunk and kill the lichen, and the dark allele sweeps through the population, plotted generation by generation. The autopilot bird ranks moths by visual saliency, a z-score of their pixels against the surrounding bark.
Try it. Click moths to eat them. Toggle Soot (or press S) to darken the bark, hold H or toggle Reveal to outline every moth colored by how conspicuous it is, F to fast-forward and R to restart. When you stop, the autopilot bird takes over, hunts faster after the first season and replays the soot arriving and clearing every five generations.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a natural selection game about peppered moths with JavaScript and the HTML canvas element. Moths rest on tree bark and I play the bird: the moths I can't find survive and breed, so the population evolves camouflage. 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. Generate a bark texture once into an offscreen canvas: write a small 2D value or Perlin noise function yourself, stretch it vertically for furrows, and mix in pale grey-green patches of "lichen" where a second, larger noise is above a threshold.
- Give each moth a genome of a few numbers between 0 and 1: lightness, tint and speckle density. Paint each moth once into its own small canvas: a triangular wing shape, filled pixel by pixel from its genome, with the pattern mirrored so it is symmetric.
- Place 24 moths at random. When I click one, it is eaten. When half are gone, each new moth gets genes from two random survivors (pick each gene from either parent) plus a small random mutation, and the new generation appears.
- Show the generation number and a small chart of average wing lightness over generations.
Once that works, make it beautiful:
- Add a "soot" toggle that cross-fades to a darkened version of the bark with the lichen removed, and watch dark moths take over.
- Add a dominant "dark" allele: two copies of a gene, and if either one is dark the moth is nearly black, like the real carbonaria form. Plot its frequency.
- Animate moths flying in, and let each new moth land on the best matching of a few random spots.
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 an automatic predator that hunts the most conspicuous moths, lighting the bark from a height map, or a reveal mode that outlines every moth.