Professor Oops

The science of simulating

The science of simulating

Built on the research, cut down to what a child can see

Professor Oops began with a reading list: how computer-animation researchers keep simulated wind from blowing up, why a dried watercolour has a dark rim, how a forensic scientist reads the angle of a falling drop. We kept the effects people recognise and left out what costs a tablet too much. This page lists every source, what we took from it, and what we turned down and why.

Painted illustration of the painter stroking his beard as he studies a light bulb in his hand, with a magnifying glass and a crayon on the table

The game keeps what people recognise, like a dried wash's dark rim, and skips precision no one can see

The game's simulation started in October 2026 with two research notes. They went through the computer graphics and physics literature with one stated rule: believable rather than physically correct, and the cheapest technique that keeps the signatures people recognise.

A dark rim on a dried wash is a signature. So is the way a puddle runs back into the track a finger leaves, or the way a drop that lands at a slant leaves a long stain. The exact speed of a ripple on three millimetres of water is not, at least not to a child holding a tablet.

The research ended up doing three different jobs. A few methods went into the code by name. Much more shaped the idea of a system and then got built in a simpler way. And some of the best-known work was read and deliberately left out. Each source on this page carries one of four labels:

  • Applied directly: the code names the method and follows it

  • Informed the design: it shaped a decision, built or not

  • Found later: the code uses a classic name; the paper behind it, listed for checking

  • Not used yet: strong work we haven't drawn on

The third label is there for honesty. The code uses classic names such as multigrid, over-relaxation, vorticity confinement, the coffee-ring effect, Marangoni flow and Poiseuille's law without citing anyone. We list the papers behind those names so an engineer can check us, and we don't claim we followed them.

Built on the research, cut down to what a child can see

For engineers

Built on the research, cut down to what a child can see

Two methods are applied by name: Stam's stable fluids (1999) for the wind, its pressure solve rebuilt as a mirror-exact screened multigrid, and the forensic rule W/L = sin α for drop stains. Most sources shaped a simpler rule of our own rather than being followed: Curtis et al.'s watercolour, MoXi's fibre noise, the elements × materials split. Some well-known ones were deliberately not built: Kubelka-Munk, Mixbox, lattice Boltzmann, GPU solvers, diffusion-limited aggregation. 56 sources below, each labelled by what we really did with it.

Under the hood: how each source was checked
How each source was checked

Under the hood

How each source was checked

Every entry was checked against an outside record: the Crossref record for its DOI, the publisher's page, or the project page. Four were read in full: Curtis et al. 1997, Stam 2003, Fedkiw et al. 2001 and O'Brien & Hodgins 1995. The rest were checked by record and abstract, which confirms the source exists and says what we say; it doesn't mean the whole paper was checked.

Each relation was then checked against the code. "Applied directly" needs the code to name the method and follow it, which only two sources pass. A recommendation in the project's research notes counts as "informed", even where the code then went another way.

There is no accuracy study of our own. No test compares the air, water, paint, fire or soap with data from any paper here. The tests pin direction, conservation and self-consistency. The one comparison with real arithmetic is the electricity: Ohm's law to three figures, checked by a test.

How each of the 56 sources was used

2 sources were applied directly, 28 informed the design, 13 were found later and 13 are not used yet.

How each of the 56 sources was used051015202530AppliedInformedFound laterNot used yetsourcesHow each of the 56 sources was used0102030AppliedInformedFound laterNot used yetsources
Data table
How each of the 56 sources was used
sources
Applied2
Informed28
Found later13
Not used yet13

Source: Counted from the reference list at the foot of this page. "Informed" includes 16 sources whose method was considered and not built.

The wind is a fluid solver from computer animation, rebuilt for a page seen from above

Hold a hair dryer over flour and the flour is blown off its heap and comes down further out. That wind comes from "stable fluids" Stam 1999, the one fluid method in the game applied directly. It was made for animation rather than engineering accuracy, and its selling point is that it cannot blow up, however big the time step. Each step moves the wind along itself by looking backwards to where each bit of air came from, then takes out the part of the flow that piles up.

We changed it in three places, each for a reason. Seen from above, air isn't trapped in the plane of the paper: a fan blowing down is a source, a fire drawing air up is a sink. So only part of the correction is applied, and the pressure is "screened": its reach fades over a short distance on the paper. There is no viscosity step, only a gentle overall damping. And small swirls are kept alive by vorticity confinement, a technique the code names; it goes back to Steinhoff and Underhill Steinhoff 1994 and came into graphics with Fedkiw, Stam and Jensen Fedkiw 2001.

The pressure solve has its own story. The first air used a fixed run of Gauss-Seidel sweeps, the same kind of relaxation as Stam's short recipe for games Stam 2003. We found it leaned: draughts blew about a fifth harder one way than the other, and the middle of a gust sat half a cell down and to the right of where it was blown. Gauss-Seidel updates cells in reading order, each one using neighbours already updated in the same sweep, so the answer depends on which corner you start from.

That finding was ours, not a paper's. The fix was a classic method used carefully. Multigrid Brandt 1977, Briggs 2000 smooths on the fine grid and solves what's left on coarser ones, where errors that span the page become short-range and cheap to remove. Our sweeps are Jacobi sweeps, every cell from the sweep before, and a cell's neighbours are added in pairs, so the wind mirrored left to right gets a correction mirrored to the bit.

The GPU route in our notes Harris 2004, WebGL fluid was not taken. The air runs on the CPU, in a WebAssembly kernel inside a Web Worker, and that kernel agrees with the plain JavaScript version to the bit. Jacobi was chosen there for symmetry, not for parallel hardware.

Under the hood: the air, against the paper
The air, against the paper

Under the hood

The air, against the paper

The air grid is coarser than the paper grid: 64 × 48 air cells on desktop, 36 × 27 on the phone. Velocity sits at cell centres, and the wind is carried by a semi-Lagrangian backtrace, as in Stam's method.

∇²p − σ p = ∇·u

A screened Poisson equation, with a small screening term σ.

  • Projection share: only part of the pressure gradient is taken out of the wind. The wind is not incompressible, and isn't meant to be.

  • Levels: the screening grows on each coarser grid, so coarsening stops once it dominates, after a few levels. Grids with odd sides, such as the phone's, coarsen in their own way.

  • Sweeps: weighted Jacobi smoothing, full multigrid with V-cycles; a cell's neighbours are added in mirrored pairs.

  • Damping: a flat decay per step in place of a diffusion step.

  • Vorticity confinement: a force that spins up existing swirls, switched on only when the wind is fast, with small random eddies in strong gusts.

  • Bit-exact: single precision, rounded after every operation, in a fixed order, so the WebAssembly twin agrees with the JavaScript to the bit. Automated tests check both the twin and the mirror symmetry.

Try it: race Gauss-Seidel against multigrid The game's own rule

Both panes solve the same pressure for one fan on the 64 × 48 desktop air grid, from nothing, and spend the same amount of work. The multigrid pane is the game's solver step by step: coarsest grid first, then one V-cycle per level, then more V-cycles. The Gauss-Seidel pane runs the plain method on the same equation, one sweep at a time. Tap a pane to move the fan, or press Move the fan. What to look for: multigrid shows a coarse answer almost at once and its full answer after about five sweeps' worth of work, already close; Gauss-Seidel creeps outward, and its centre (the cross) sits off the fan's (the ring). Switch the screening off to see how slowly a single sweep's reach spreads across a whole page.

Two pressure fields filling in around a fan: plain Gauss-Seidel in one pane, the game multigrid in the other
  • Gauss-Seidel
  • Multigrid (the game)
  • ring: the fan · cross: the centre of the answer
Screening
Sweep order
7 sweeps/s
work so far
—
Gauss-Seidel
—
Multigrid
—
V-cycles on the finest grid
—
Gauss-Seidel off by
—
multigrid off by
—
Gauss-Seidel centre moved, across
—
down
—
levels
—
How far the game's pressure may be from its exact answer"Exact" means the screened equation, which is a choice, not physics. A slow device without the WebAssembly kernel settles for the cheaper answer.

One V-cycle from nothing may be up to 35 % off; the game's full multigrid is held within 12 %.

How far the game's pressure may be from its exact answer0%10%20%30%40%1 V-cycle from no…Full multigrid (t…% off, at mostHow far the game's pressure may be from its exact answer0%10%20%30%40%1 V-cycle fro…Full multigri…% off, at most
Data table
How far the game's pressure may be from its exact answer
allowed error
1 V-cycle from nothing35%
Full multigrid (the game)12%

Source: Bounds asserted by an automated test, against a long run of V-cycles as the exact answer.

What we'd read next

Three works we haven't drawn on would be the first checks of these choices. McAdams, Sifakis and Teran McAdams 2010 is multigrid for fluids in graphics, the nearest prior art to our solver. Bridson's textbook Bridson 2016 would question our velocities at cell centres rather than on cell faces. Chorin's 1968 paper Chorin 1968 is an ancestor of the projection step itself.

Puddles run in virtual pipes, with real gravity held back to stay stable

next update In the released game, standing water evens itself out at a plain rate, with no momentum. In the next update it keeps going once it's moving. Drag a finger through a puddle and the water runs back into the track at once; a thin sheen hardly moves at all.

The technique is "virtual pipes". Every cell is joined to its four neighbours by a pipe. What a pipe carries this step is what it carried last step, sped up by how much higher the water stands on one side. The idea goes back to O'Brien and Hodgins O'Brien 1995, and reached us through the hydraulic erosion work of Mei, Decaudin and Hu Mei 2007 and the small-scale shallow water of Dagenais et al. Dagenais 2018. That last one also uses half-millimetre cells and treats viscosity implicitly, as our code does, though our viscous term is derived separately, from Poiseuille's law Sutera 1993. Water as a height field at all goes back further, to Kass and Miller Kass 1990.

The rule carries real constants: gravity at its true 9.81 m/s², scaled to half-millimetre cells, and water's real viscosity of 1 mm²/s. That is also where it meets its limit. A wave on 3 mm of real water runs at 17 cm/s, ten cells in one step, faster than a step can carry and stay stable. So the push is capped. The cap always wins in practice, and waves in the game run at about 7 mm/s, some 25 times slower than real ones. The rule has the right form and real constants, and it is deliberately held back.

Under the hood: one pipe, per pass of 1/30 s
One pipe, per pass of 1/30 s

Under the hood

One pipe, per pass of 1/30 s

Each pipe remembers its flow from the last pass. Two things act on it. The difference in water surface between its two cells pushes it on, with real gravity scaled to the cell size. The viscous drag of a thin film holds it back, from Poiseuille's law with water's real viscosity, applied implicitly so that thick liquids can't make it unstable. The push is then held under a stability cap, and tiny differences in level are left to rest.

All of a cell's outflows together are held below the water it has, so no column goes negative, as in O'Brien & Hodgins (who scale outflows the same way, with eight neighbours rather than four and no viscous hold). Flow that meets a level or uphill surface slows down. A very thin film doesn't run at all, and at a puddle's edge the old levelling rule still applies.

At the game's pass of 1/30 s, real gravity would push harder than the cap at every depth where water runs, so every running cell is capped. An automated test measures the result: a palm's track through a puddle is back to half the puddle's depth within a second, where the levelling rule had it 5 % back after five seconds; a fingertip's track closes behind it at once.

Try it: drag a finger through a puddle The game's own rule

next update A 6 cm × 4 cm puddle about 1 mm deep, at the game's half-millimetre cells, stepped at the game's 30 passes a second. Every two and a half seconds a fingertip drags across it; drag your own finger through it too, or press Drag a finger across. What to look for: with pipes, the track fills back in almost at once. Switch to the released rule and the same track fills far more slowly. Thicken the liquid and the pipes lose their momentum. Low ridges stay put: a surface that is nearly level between neighbours is left to rest. Pipes only move water, so the total stays the same.

A shallow puddle seen from above; a fingertip drags a track through it and the water runs back in
Rule
1 mm²/s
last track refilled
—
water on the page
—
fastest pipe
—
running cells at the push cap
—
Real gravity would push puddle water hard; a stability cap holds it backThe two lines part at about 0.08 mm, below the depth at which water starts to run, so every running cell is capped.

From real gravity the push per pass climbs from about 0.003 at 0.03 mm to over 10 at 1.5 mm; the game holds it at 0.2 from about 0.08 mm on.

Real gravity would push puddle water hard; a stability cap holds it back0.0010.010.11101000.00.20.40.60.81.01.21.4water depth (mm)push per pass (log)from here on, water runsReal gravity would push puddle water hard; a stability cap holds it back0.0010.010.11101000.00.51.01.5water depth (mm)push per pass (log)from here on, water runs
  • g·dt²·h·keep, from real g and ν
  • what the game uses, capped
Data table
Real gravity would push puddle water hard; a stability cap holds it back
water depth (mm)g·dt²·h·keep, from real g and νwhat the game uses, capped
0.030.011670.01167
0.03370.016440.01644
0.03780.023160.02316
0.04240.032590.03259
0.04750.045830.04583
0.05330.064370.06437
0.05990.090270.09027
0.06720.12640.1264
0.07540.17650.1765
0.08460.2460.2
0.09490.34150.2
0.10640.47230.2
0.11940.650.2
0.1340.88950.2
0.15041.2090.2
0.16871.630.2
0.18932.1770.2
0.21242.8780.2
0.23833.7630.2
0.26744.860.2
0.36.1960.2
0.33667.7960.2
0.37779.680.2
0.423811.870.2
0.475514.370.2
0.533517.210.2
0.598620.40.2
0.671623.970.2
0.753627.940.2
0.845532.340.2
0.948737.230.2
1.064442.650.2
1.194348.660.2
1.340155.340.2

Source: Computed from real gravity, water's real viscosity and the game's cap, at the game's pass of 1/30 s.

Ketchup holds its shape by a threshold, not by a yield-stress law

A heap of ketchup stays a heap; paint spreads. In real life that's a yield stress: the paste doesn't flow until it's pushed hard enough. Lubrication theory for such thin "Bingham" sheets Liu 1989 gives a flux that depends on depth and slope, and our research note wrote it out. The code does something far simpler. Paste flows to a neighbour only where its surface stands higher by more than a per-material step, and then in proportion to the excess. Depth doesn't enter. The code calls it "Bingham-ish", and that is the honest word.

Two other papers shaped the goop the same way, as ideas. Carlson et al.'s melting and flowing Carlson 2002 was on the reading list, and we used none of its method. Our goop simply runs less the more of it has set. Sumner, O'Brien and Hodgins Sumner 1999 pushed sand, mud and snow aside as height columns and let steep columns slump; our bulldozing and slumping does the same with nothing lost, though none of their parameters are used. Heaped grains avalanche past a fixed rise per cell, the same family of threshold rule as the sandpile model of self-organised criticality Bak 1987.

Under the hood: how far the goop is from Bingham
How far the goop is from Bingham

Under the hood

How far the goop is from Bingham

The note's lubrication flux, not built:

q ∝ (h − h0)² (2h + h0),   h0 = τy / (ρ g |∇s|)

What the game does instead: each material has its own yield step and its own mobility. Paste flows to a neighbour only where the surface step is larger than the yield, in proportion to the excess, and a material that has partly set moves less. Ketchup has a high yield and a low mobility; paint the other way round. An automated test pins that runny paint spreads further than ketchup.

Grains have an angle of repose of their own, with volume conserved. Another test checks that sand settles to its angle and salt stands steeper.

Watercolour dries with a dark edge, an idea from a classic research paper done a cheaper way

Brush a wash onto the paper, let it dry, and its edge comes out darker than its middle. Drop clean water into a drying wash and it pushes the colour out into a bloom. Those signatures come from one paper more than any other: "Computer-Generated Watercolor" by Curtis, Anderson, Seims, Fleischer and Salesin Curtis 1997. It gave us the mental model: water on the sheet, water in the fibres, pigment carried to the edges.

It did not give us its method. Curtis et al. run a small fluid simulation on the paper, with a velocity field, a mask of the wet area, an outward flow computed from a blurred mask, and glazes composited by the Kubelka-Munk optics of paint. The game has no velocity in the paper water at all. Each cell exchanges water and dye with its neighbours by their difference in wetness, gated by a fibre pattern, and every spot dries at the same rate unless it's heated. The rim appears anyway, because the thin edge empties first and water evens out toward it, bringing colour along. A test checks that the rim comes out 1.3 to 2.5 times as strong as the wash inside it.

The fibre pattern is the one thing we kept from MoXi Chu 2005, a beautiful real-time ink model built on lattice Boltzmann flow on the GPU. We parked that method as a possible special brush. What survived is its idea that noise in the fibres breaks up the wet front. The same fibre field now also sets how fast paper burns and conducts heat. The saturation-dependent spreading in our notes, which would give sharper wet fronts, was not built. Van Laerhoven and Van Reeth's real-time watery paint Van Laerhoven 2005 was in the notes too; it is GPU dynamics as well, and we took nothing specific from it.

A dried coffee drop has a dark ring for a reason explained by Deegan et al. Deegan 1997: liquid lost at a pinned edge is replaced from inside, and that flow carries the solids out. The game's grains also ride the water toward a drying edge. That's consistent in mechanism only. There's no pinned contact line, no extra evaporation at the rim, and nobody has tested the paper's power law.

Under the hood: the watercolour rule
The watercolour rule

Under the hood

The watercolour rule

  • Water moves between neighbouring spots in proportion to their difference in wetness, gated by the fibre noise of both. The exchange is linear in wetness, where MoXi and Richards would have it grow with wetness.

  • Bleed: wet pigment spreads only between spots that are both wet.

  • Grains ride a share of the water's flow, a larger share where the paper is wetter.

  • The edge: where wetness drops away, colour is pulled toward the drier side, which builds the rim.

  • Tide mark: a faint tint where wet meets dry. It adds colour rather than moving it, so that one term doesn't conserve dye.

  • Drying is the same everywhere, faster where the paper is hot.

Automated tests pin the rim at 1.3 to 2.5 times the wash, soft and a few cells wide; a bloom that keeps the wash's colour; wet pigment that bleeds while dry pigment stays; and the colour bands of a wet marker line.

In the game, a dried blue watercolour wash whose edge is clearly darker than its middle
A dried wash keeps a darker rim, in the game. Water carries colour toward the drying edge and leaves it there. Curtis et al. drew the same signature with a full flow model; ours comes from a simple rule between neighbouring spots.

We turned down the famous paint-mixing models

Real paint scatters light as well as absorbing it. That is why light paint can cover dark. The classic model of it is Kubelka and Munk's Kubelka 1931, and our research note recommended storing its two numbers per pigment. A modern method built on it, Mixbox Sochorová 2021, mixes digital paint beautifully, but its licence is non-commercial, and that ruled it out. The open spectral.js library spectral.js was considered and not adopted.

The game does something cheaper. A colour is how much light it takes away, per red, green and blue channel. Layers add their absorbance and the light left falls exponentially with it, which is what the Beer-Lambert law describes Swinehart 1962; the code calls it optical density. Two thin washes darken together the way real ones do. What's lost is scattering: light paint can't cover dark. How colours mix has the whole model.

The comparison we most want to make

Water climbs into paper with its front moving as the square root of time. Lucas Lucas 1918 and Washburn Washburn 1921 worked that law out, and Richards Richards 1931 wrote the porous-flow equation in which wetter paper carries water better, the cause of a sharp wet front. Nobody has measured the game's wet front against √t yet. If it holds, it would be a real comparison with physics rather than a resemblance. Before Curtis et al., Small Small 1991 simulated watercolour on a Connection Machine; Curtis et al. call it groundbreaking, and we haven't read it.

Every drop stain follows a rule from forensic science

Splash paint across the page and each drop leaves a stain. A drop that comes straight down leaves a round dot; one that skims in at a low angle leaves a long oval pointing the way it was going. Crime-scene investigators use this to work out where blood came from. The rule is simple: the stain's width divided by its length is the sine of the angle the drop came in at. It's credited to Balthazard and colleagues in 1939, and we applied it directly from a fluid dynamics write-up by Neitzel and Smith Neitzel & Smith.

The game works out each drop's impact angle from its own speed across the page and its speed coming down, so a drop thrown fast and low leaves a long stain and one that falls straight down a round one. The stretch is capped, so very shallow drops don't turn into thin streaks.

The rest of the splash research in our notes we didn't build: how many fingers form round a drop hitting a plate Mehdizadeh 2004, how a crown splash's rim grows and breaks up Agbaglah 2014, and crown fingers from non-spherical drops Anirudh 2026. Splash physics of this kind weighs a drop's inertia against its surface tension, the Weber number. No Weber number exists anywhere in the code. Tails and satellite droplets come from simple rules.

Under the hood: the landing
The landing

Under the hood

The landing

At the moment a drop lands, its speed across the page and its speed coming down give the sine of its impact angle. The stain is stretched by 1 / sin α, up to a cap, and its long axis follows the drop's direction across the page. The source page credits sin α = W/L to Balthazard, Piedelievre, Desoille and DeRobert (1939); we know that paper only through it, and nothing on the page shows peer review.

Try it: throw drops at an angle The game's own rule

Drops fly in from the left and land at the angle you set. Tap the paper to throw one at a spot, or press Throw a drop. What to look for: at 90° the stains are round; below 30° they stretch to twice their width and more; below about 14.5° they stop growing at 4 : 1, where the real rule would keep going. Turn on the outline to see the real rule's shape around the newest stain.

Red drops landing on paper at a chosen angle, leaving round or long oval stains
25°
real W/L = sin α
—
game W/L
—
real length ÷ width
—
game length ÷ width
—
capped
—
A stain stretches as a drop comes in flatter, up to 4 : 1

The forensic rule gives 11.5 : 1 at 5° and 2 : 1 at 30°; the game follows it down to 14.5° and stays at 4 : 1 below that.

A stain stretches as a drop comes in flatter, up to 4 : 1024681012102030405060708090impact angle (degrees)length ÷ widthcap reached at 14.5°A stain stretches as a drop comes in flatter, up to 4 : 1051020406080impact angle (degrees)length ÷ widthcap reached at 14.5°
  • the forensic rule, 1 / sin α
  • the game, capped at 4
Data table
A stain stretches as a drop comes in flatter, up to 4 : 1
impact angle (degrees)the forensic rule, 1 / sin αthe game, capped at 4
511.4744
69.5674
78.2064
87.1854
96.3924
105.7594
115.2414
124.814
134.4454
144.1344
153.8643.864
163.6283.628
173.423.42
183.2363.236
193.0723.072
202.9242.924
212.792.79
222.6692.669
232.5592.559
242.4592.459
252.3662.366
262.2812.281
272.2032.203
282.132.13
292.0632.063
3022
311.9421.942
321.8871.887
331.8361.836
341.7881.788
351.7431.743
361.7011.701
371.6621.662
381.6241.624
391.5891.589
401.5561.556
411.5241.524
421.4941.494
431.4661.466
441.441.44
451.4141.414
461.391.39
471.3671.367
481.3461.346
491.3251.325
501.3051.305
511.2871.287
521.2691.269
531.2521.252
541.2361.236
551.2211.221
561.2061.206
571.1921.192
581.1791.179
591.1671.167
601.1551.155
611.1431.143
621.1331.133
631.1221.122
641.1131.113
651.1031.103
661.0951.095
671.0861.086
681.0791.079
691.0711.071
701.0641.064
711.0581.058
721.0511.051
731.0461.046
741.041.04
751.0351.035
761.0311.031
771.0261.026
781.0221.022
791.0191.019
801.0151.015
811.0121.012
821.011.01
831.0081.008
841.0061.006
851.0041.004
861.0021.002
871.0011.001
881.0011.001
8911
9011

Source: The rule as given by Neitzel & Smith, and the game's capped version of it.

In the game, a blob of ketchup hit with the hammer, and round it the drops it threw: some round, some ovals pointing away from the blow
Slanted drops leave longer stains, in the game. A hammer blow on a blob of ketchup throws drops out at many angles. Each stain is stretched by the forensic rule, width over length equals the sine of the impact angle, so drops that came down steeply left round spots and low ones left ovals pointing the way they flew, away from the blow.

Mould grows by a formula, so "come back in three days" costs nothing

Leave food out on the page, skip ahead three days, and fuzzy mould colonies have spread over it. Real mould grows as branching threads. The textbook way to grow branching shapes in a computer is diffusion-limited aggregation Witten 1981: particles wander at random until they touch the cluster and stick. It makes lovely, lifelike fronds.

We turned it down for two reasons. Literal random walkers are slow, and a time skip would mean simulating every hour of the three days. Instead each colony's radius is a formula of its age. "Come back three days later" is one sum per colony, not three days of work, which is exactly what our research note asked for.

Other pattern makers were noted and not built either: Gray-Scott reaction-diffusion as Karl Sims's tutorial presents it Sims, and the slime-mould transport networks of Jones Jones 2010. Turing's 1952 paper on patterns from reaction and diffusion Turing 1952 is the classic behind the first. (A comment in the fire code says "reaction-diffusion", but it means heat and fuel; the fire is a travelling front, not a Turing pattern.)

Under the hood: a colony's radius
A colony's radius

Under the hood

A colony's radius

r(age) grows as √age, up to a largest size

Nothing shows for the first hours. Each colony draws its own growth rate, and growth slows as it gets bigger. Colonies are seeded on food residue, more where it's damp, and spread only over cells with something to eat. While the app is open the mould clock runs at a steady pace of its own, much faster than real time but held back during play; a time skip is not held back.

The cost is O(colonies) per evaluation, whatever the time skip. A walker cluster needs one random walk for every particle in it, each walk running until it hits.

Try it: random walkers against the game's formula Illustration

The game's own rule Two colonies on the same clock, four sim-hours a second. The random walkers grow by diffusion-limited aggregation: walkers wander until they touch the colony and stick. The other pane is the game's formula for a typical colony. Each frame the walkers get a fixed budget of steps, as a device would. What to look for: press "Come back in 3 days". The formula jumps there at once; the walkers have to catch up step by step, and the step counter shows the bill. Lower the budget to play a slower tablet.

Two mould colonies growing on the same clock: random walkers in one pane, the game formula in the other
  • Random walkers
  • The game: radius from age
40k steps/frame
sim time
—
and
—
formula radius
—
walkers reached
—
walker steps so far
—
In the game, three blobs of ketchup grown over with mould after a three-day skip: green colonies, patches of white fuzz and one small orange colony
Three days later, in the game. Each colony's size is a formula of its age, so the skip costs one sum per colony. Colonies that started earlier or grow faster are bigger: here green and white ones have spread over whole blobs of ketchup, while a small orange one, later or slower, is still a spot.
No line sets the fire's speed, yet it comes out the same order as real paper

One published measurement for paper gives 0.8 mm/s; the game's front, measured, runs at 1.1 mm/s.

No line sets the fire's speed, yet it comes out the same order as real paper0.00.20.40.60.81.01.2One published mea…The game, measuredfront speed, mm/sNo line sets the fire's speed, yet it comes out the same order as real paper0.00.20.40.60.81.01.2One published…The game, mea…front speed, mm/s
Data table
No line sets the fire's speed, yet it comes out the same order as real paper
front speed
One published measurement, paper0.8
The game, measured1.1

Source: Measured in the game: the same order of magnitude, not calibrated. The published source is thin; see Heat and fire.

For fire, electricity and soap we kept the classic laws and turned down the clever papers

Fire

Hold a match to paper and a ragged front eats outward, with a blackened edge. We read up on burning paper in graphics: three papers by Melek and Keyser, one of them on bending burning matches and crumpling burning paper Melek 2005, Melek 2006, Melek 2007, and Larboulette, Quesada and Dumas, who burn paper fibre by fibre Larboulette 2013. Our research note turned down that paper's curling sheet of masses and springs as overkill, in writing. A clean example of a source consulted and declined.

The game's fire is heat spreading through the paper, with fuel that burns away. Paper catches at a fixed threshold, about 230 °C; the randomness sits instead in the fuel and in burn rates tied to the fibre field. There's no oxygen field: carbon dioxide and anything lying on top stand in for "no air". Water holds a cell at boiling until it has dried. No line sets the speed of the front, yet it comes out at about 1.1 mm a second, the same order as one published measurement for paper. It wasn't calibrated to it.

Strong fire work we haven't drawn on: Rothermel's classic spread model for wildland fires Rothermel 1972, at the wrong scale for paper but useful as a concept; flames in graphics Nguyen 2002; and two physics papers on slowly burning paper fronts Maunuksela 1997, Zik 1998.

Electricity

Draw a copper wire from a battery to a bulb and the bulb lights. The game solves for the voltage in every cell of the sheet, with each cell's real conductance, until the current balances. Engineers know the method as successive over-relaxation Young 1954. The very problem of current spreading through a flat plate was the subject of a paper Kirchhoff wrote as a student in 1845 Kirchhoff 1845. We didn't follow either paper; these are the classic names for what the code does. The answer matches Ohm's law to three figures: 0.273 A through copper and a bulb.

Soap on milk

Drop washing-up liquid onto milk with colour on it and the colours burst away from it, then stop. That's Marangoni flow Scriven 1960: soap lowers the surface tension and the surface pulls away toward where it's higher. In the game the milk's fat takes up the soap, so the burst stops by itself. A real soluble surfactant drives a flow of finite size Roché 2014; ours also clears a finite patch and eases out, consistent in kind. Nobody has compared it with that paper's scaling laws, which makes it a good candidate for a real test.

Under the hood: three solvers, three classic names
Three solvers, three classic names

Under the hood

Three solvers, three classic names

  • Fire: heat diffuses through the paper, faster where the fibres are denser; a cell lights at about 230 °C; the fuel in each cell varies with a noise field, and its burn rate follows the fibre. Pinned by automated tests.

  • Electricity: ∇·(σ∇V) = 0, Kirchhoff's current law on the paper's cells, solved by over-relaxation, forward then back, until the power in the sheet stops changing. The same sum gives the current per volt. Every material has its own conductance per square, copper far above pencil graphite. Checked against Ohm's law by a test.

  • Soap: surface tension falls with soap along a saturating curve, chosen by eye rather than fitted to a measured isotherm. The surface velocity lives on a coarser grid, is drawn toward the pull of surface tension with a short delay and a speed limit, and is carried semi-Lagrangian as in the air. The long curling swirl, from a few over-relaxation sweeps of its own, comes in the next update.

Falling-sand games showed how many materials can meet without a rule for every pair

Some of the most useful sources weren't papers at all. Falling-sand games have spent years on the question of how many materials can meet without anyone writing every pair.

Sandspiel Bittker 2019 packs each cell into 32 bits: a species, two registers and a clock. The Powder Toy Powder Toy keeps each element as a flat record of properties; its water next to salt has a 1 in 50 chance of becoming salt water. We went another way: Professor Oops isn't a cellular automaton of discrete species. Each cell carries many continuous layers, such as water, heat, dye and dissolved substances, because a wash of colour or a slowly drying puddle needs amounts, not types.

Noita Purho 2019 showed how a big sand world stays fast: only redraw and recompute the rectangles that changed. We built the same idea our own way, with small square tiles where calm ones are worked only every few passes. Nothing in the code says it came from Noita, so we don't claim it did.

The biggest idea came from a talk on The Legend of Zelda: Breath of the Wild Dohta 2017, as our notes summarised it: send interactions through shared elements, so the number of rules grows as elements times materials instead of materials times materials. The game's dissolved elements and its data-driven reaction table are built that way. That is how vinegar fizzes on baking soda and lemon turns red cabbage pink: acid, baking soda's base and the cabbage's colour are shared elements, so any material that carries them joins in. Built for surprises tells that story.

Under the hood: the tile clock
The tile clock

Under the hood

The tile clock

The page is cut into small square tiles. Each system keeps its own clock per tile and tracks how much moved there; quiet tiles are worked every few passes, still ones not at all until something wakes them. The research note proposed larger chunks after reading about Noita's dirty rectangles; the built tiles are smaller, and nothing in the code or its history names Noita.

The shared elements and the reaction table are data, not code per pair. Unlike the falling-sand games, these fields are continuous amounts. Nobody here has watched the Breath of the Wild talk; the idea came through secondary notes, so we say "informed", never "goes further than".

Only the tiles where something happens are worked every pass Illustration

Dark blue: busy, every pass. Pale blue: settling, every few passes. Paper: still, asleep until woken. Illustration of the game's tile clock: a puddle spreading in one corner and a candle burning in another, on a page cut into tiles.

A page cut into 16 by 9 tiles; tiles round a spreading puddle and a burning candle are busy, a ring round them settling, the rest still
  • puddle
  • candle

Every technique here feeds a system you can play with

Each source on this page ends up in a chapter of its own. These are the threads, with the test that holds each one.

Shared: wetness + dye per cell

Paint a wash and let it dry

The edge dries darker, 1.3 to 2.5 times the middle, pinned by a test.

Water in paper

Shared: the wind field u, v

Hold a hair dryer over flour

The flour is blown off its heap and comes down further out, and a test holds the pressure solve mirror-exact to the bit.

Air that really moves

Shared: water depth + pipe flows

Drag a finger through a puddle

next update The water runs back into the track, measured by a test.

Runny, sticky and oily

Shared: conductance per cell

Draw a copper wire from battery to bulb

The current settles by over-relaxation and matches Ohm's law to three figures, checked by a test.

Electricity

Shared: water + heat + fibre

Wet the paper, then light it

Soaked paper won't light: its water holds it at boiling until it has dried, pinned by a test.

Heat and fire

Shared: surface tension field

Drop washing-up liquid on milk

Colours burst away and stop as the fat binds the soap, pinned by a test.

Runny, sticky and oily

56 sources read, two methods followed by name, and the rest cut down to fit a tablet

56
Sources on this page: 43 the project used or considered, 13 we haven't drawn on yet.
2
Applied directly by name: stable fluids for the wind, and the forensic stain rule.
4
Sources read in full; the rest checked by their record and abstract against an outside record.
64 × 48
Air cells on desktop, with the pressure solved by multigrid on every pass, mirror-exact to the bit.
25×
Slower than real waves, so the pipe water stays stable at 30 passes a second (next update).
1.1 mm/s
The speed of the fire front on paper. No line sets it; it comes out of heat and fuel, the same order as one published measurement.

Where we simplify, and why

Every technique here was cut down on purpose. This is what reality does, what the game does, and why that's the right trade for a child on a tablet.

In real life. Air over a table moves in three dimensions, has viscosity, and barely compresses

In the game. A 2D grid of 64 × 48 air cells; part of a screened pressure correction; a flat damping and no viscosity step

Why that's enough. Seen from above, a fan is a source and a fire a sink. A fully incompressible wind pushed back on gusts from across the page and blew a fifth to a third weaker. No real speed or pressure is claimed.

In real life. The pressure is solved exactly

In the game. Full multigrid, within 12 % of its own exact screened answer, held there by a test

Why that's enough. A gust a tenth too weak looks the same. One that leans to the right gets noticed, so the effort went into symmetry, not digits.

In real life. A wave on 3 mm of water runs at 17 cm/s

In the game. About 7 mm/s: the pipes' push is held under a stability cap next update

Why that's enough. Stable at 30 passes a second. A child sees water slosh back into a finger's track; the speed of a ripple is not something they judge.

In real life. Ketchup has a yield stress, and its flux depends on depth and slope

In the game. Flow in proportion to how far the surface step exceeds a per-material yield; depth doesn't enter

Why that's enough. Ketchup heaps and paint runs, in the right order, pinned by a test. Lost: a thick blob outrunning a thin one on the same slope.

In real life. Watercolour flows as a thin fluid layer, with faster evaporation at the edge

In the game. One linear exchange gated by fibre noise, uniform drying, grains riding at a share of the water's flow

Why that's enough. The rim, the bloom and the bleed are all there and tested. Lost: currents inside a wet wash.

In real life. Paint absorbs and scatters light

In the game. Absorbance per red, green and blue channel; the light left falls exponentially with it

Why that's enough. Layers darken together like real washes. Lost: light paint covering dark.

In real life. A splash forms a crown, fingers and satellites that depend on the Weber number

In the game. Stain width ÷ length = sin of the impact angle, up to a capped stretch; tails by simple rules

Why that's enough. The stain shows where a drop came from and how steeply, as a forensic reading does.

In real life. Mould grows as branching threads, fed by food and damp

In the game. A colony's radius is a formula of its age, growing as its square root after a delay

Why that's enough. "Come back in three days" is one sum per colony, on any device.

All 56 sources, and what we did with each

Grouped by system. Each says how it was used. Most were checked by record and abstract; the four read in full are marked. A source listed here that we haven't used is listed as a gap, never as an influence.

Air and wind

  • Jos Stam, 1999. "Stable Fluids." SIGGRAPH '99, pp. 121–128.

    Applied directly. What we did: the wind's semi-Lagrangian advection and pressure projection, named in the code. Departures: no viscous diffusion, only part of a screened correction.

  • Jos Stam, 2003. "Real-Time Fluid Dynamics for Games." Game Developers Conference.

    Informed the design · read in full. What we did: recommended in the notes for smoke. The first air's Gauss-Seidel sweeps resembled its recipe; they have since been replaced.

  • Mark J. Harris, 2004. "Fast Fluid Dynamics Simulation on the GPU." GPU Gems, chapter 38, NVIDIA.

    What we did: GPU route not taken; the air runs on the CPU and in WebAssembly. Our Jacobi sweeps are there for mirror symmetry.

  • PavelDoGreat. WebGL-Fluid-Simulation. GitHub, MIT licence.

    What we did: a reference implementation in the notes; not used.

  • Ronald Fedkiw, Jos Stam, Henrik Wann Jensen, 2001. "Visual Simulation of Smoke." SIGGRAPH 2001, pp. 15–22.

    Found later · read in full. What we did: the code names vorticity confinement and uses a force of the same shape, gated on speed. The repo never cites this paper.

  • J. Steinhoff, D. Underhill, 1994. "Modification of the Euler equations for 'vorticity confinement'." Physics of Fluids 6(8), 2738–2744.

    What we did: the origin of the technique above.

  • Achi Brandt, 1977. "Multi-Level Adaptive Solutions to Boundary-Value Problems." Mathematics of Computation 31(138), 333–390.

    What we did: a foundational multigrid paper; our solver names multigrid and cites nothing.

  • William L. Briggs, Van Emden Henson, Steve F. McCormick, 2000. A Multigrid Tutorial, 2nd ed. SIAM.

    What we did: the standard introduction to V-cycles and full multigrid; good reading for anyone checking our solver.

  • A. McAdams, E. Sifakis, J. Teran, 2010. "A Parallel Multigrid Poisson Solver for Fluids Simulation on Large Grids." SCA 2010.

    Not used yet. Multigrid for fluids in graphics: the nearest prior art to our solver.

  • Robert Bridson, 2016. Fluid Simulation for Computer Graphics, 2nd ed. A K Peters/CRC.

    Not used yet. The standard text; it would be the first check of the air's choices, including velocity at cell centres rather than on faces.

  • Alexandre J. Chorin, 1968. "Numerical solution of the Navier-Stokes equations." Mathematics of Computation 22, 745–762.

    Not used yet. An ancestor of the projection step.

Water, goop and grains

  • James F. O'Brien, Jessica K. Hodgins, 1995. "Dynamic Simulation of Splashing Fluids." Computer Animation '95, pp. 198–205.

    Found later · read in full. What we did: the origin of virtual pipes, per later sources. Our rule has its form, with four neighbours instead of eight and a viscous hold next update.

  • Xing Mei, Philippe Decaudin, Bao-Gang Hu, 2007. "Fast Hydraulic Erosion Simulation and Visualization on GPU." Pacific Graphics 2007, pp. 47–56.

    What we did: the notes' pointer to virtual pipes, for thick layers. The pipes went in by name next update; nothing shows this paper's formulas were used.

  • François Dagenais et al., 2018. "Extended virtual pipes for the stable and real-time simulation of small-scale shallow water." Computers & Graphics 76, 84–95.

    What we did: same 0.5 mm cell and implicit viscosity next update, though our term is derived from Poiseuille. Its extended pipes and multi-layer heightmaps were not built.

  • Michael Kass, Gavin Miller, 1990. "Rapid, Stable Fluid Dynamics for Computer Graphics." SIGGRAPH '90, pp. 49–57.

    What we did: the ancestor of water as a height field.

  • Salvatore P. Sutera, Richard Skalak, 1993. "The History of Poiseuille's Law." Annual Review of Fluid Mechanics 25, 1–20.

    What we did: the code names Poiseuille's 3ν/h² and computes it from water's real ν next update; this review is a citable history of the law.

  • Ko Fei Liu, Chiang C. Mei, 1989. "Slow spreading of a sheet of Bingham fluid on an inclined plane." Journal of Fluid Mechanics 207, 505–529.

    What we did: the idea of a threshold, yes; the flux formula, no.

  • Mark Carlson, Peter J. Mucha, R. Brooks Van Horn III, Greg Turk, 2002. "Melting and Flowing." SCA 2002, pp. 167–174.

    What we did: not its method. Our goop simply moves less as it sets.

  • Robert W. Sumner, James F. O'Brien, Jessica K. Hodgins, 1999. "Animating Sand, Mud, and Snow." Computer Graphics Forum 18(1), 17–26.

    What we did: pushing material aside as height columns and slumping steep ones, with nothing lost. None of its parameters are used.

  • Per Bak, Chao Tang, Kurt Wiesenfeld, 1987. "Self-organized criticality: An explanation of the 1/f noise." Physical Review Letters 59, 381–384.

    Not used yet. The sandpile model: the same family of threshold rule as our grain slump.

Watercolour and paper

  • Cassidy Curtis, Sean Anderson, Josh Seims, Kurt Fleischer, David Salesin, 1997. "Computer-Generated Watercolor." SIGGRAPH '97, pp. 421–430.

    Informed the design · read in full. What we did: the most important single influence on the paper model, for its behaviours. None of its method: no velocity layer, mask, blur or glazing.

  • Tom Van Laerhoven, Frank Van Reeth, 2005. "Real-time simulation of watery paint." Computer Animation and Virtual Worlds 16(3–4), 429–439.

    What we did: in the notes; no GPU dynamics and no Kubelka-Munk built.

  • Nelson S.-H. Chu, Chiew-Lan Tai, 2005. "MoXi: Real-Time Ink Dispersion in Absorbent Paper." ACM TOG 24(3), 504–511.

    What we did: kept the fibre noise that gates the flow; lattice Boltzmann parked as a possible special brush.

  • Robert D. Deegan, Olgica Bakajin, Todd F. Dupont, Greg Huber, Sidney R. Nagel, Thomas A. Witten, 1997. "Capillary flow as the cause of ring stains from dried liquid drops." Nature 389, 827–829.

    What we did: the code says "coffee-ring effect". Consistent in mechanism only: no pinned line, no edge evaporation peak, no power-law test.

  • David Small, 1991. "Simulating watercolor by modeling diffusion, pigment, and paper fibers." SPIE vol. 1460, pp. 140–146.

    Not used yet. Watercolour on a Connection Machine, which Curtis et al. call groundbreaking.

  • R. Lucas, 1918. "Ueber das Zeitgesetz des kapillaren Aufstiegs von Flüssigkeiten." Kolloid-Zeitschrift 23, 15–22.

    Not used yet. The √t law of capillary rise.

  • Edward W. Washburn, 1921. "The Dynamics of Capillary Flow." Physical Review 17, 273–283.

    Not used yet. Front distance as √t. The most useful gap: nobody has measured the game's front against it.

  • L. A. Richards, 1931. "Capillary conduction of liquids through porous mediums." Physics 1, 318–333.

    Not used yet. Diffusivity that depends on saturation: the formal version of the D ∝ water² we didn't build, and the cause of sharp wet fronts.

Colour

  • P. Kubelka, F. Munk, 1931. "Ein Beitrag zur Optik der Farbanstriche." Zeitschrift für Technische Physik 12, 593–601.
    Informed

    Informed the design, not built. What we did: the notes recommended K and S per pigment; the code has neither, and no scattering term.

  • Šárka Sochorová, Ondřej Jamriška, 2021. "Practical Pigment Mixing for Digital Painting." ACM TOG 40(6), article 234.

    Informed the design, not built. What we did: Mixbox; ruled out by its non-commercial licence.

  • Ronald van Wijnen. spectral.js. GitHub, MIT licence.

    Informed the design, not built. What we did: considered; not in the app. (Its README describes seven primary curves sampled at 38 points from 380 to 750 nm, with single-constant Kubelka-Munk.)

  • D. F. Swinehart, 1962. "The Beer-Lambert Law." Journal of Chemical Education 39(7), 333.

    What we did: the game's colour is what the law describes: absorbance adds, light is exp(−absorbance), per channel. The code calls it optical density.

Soap on milk

  • L. E. Scriven, C. V. Sternling, 1960. "The Marangoni Effects." Nature 187, 186–188.

    What we did: the code names the flow and cites nothing.

  • Matthieu Roché et al., 2014. "Marangoni Flow of Soluble Amphiphiles." Physical Review Letters 112, 208302.

    What we did: our clearing is also finite and eases out, consistent in kind. Not compared with its scaling laws: a good candidate for a real test.

Drop stains and splashes

  • G. Paul Neitzel, Marc Smith. "The Fluid Dynamics of Droplet Impact on Inclined Surfaces with Application to Forensic Blood Spatter Analysis." Posted on crime-scene-investigator.net, 2018; no original date or venue given.

    Applied directly. What we did: sin α = W/L for every drop stain, with a cap on the stretch.

  • Navid Z. Mehdizadeh, Sanjeev Chandra, Javad Mostaghimi, 2004. "Formation of fingers around the edges of a drop hitting a metal plate with high velocity." Journal of Fluid Mechanics 510, 353–373.

    What we did: in the notes; no Weber number in the code.

  • G. Agbaglah, R. D. Deegan, 2014. "Growth and instability of the liquid rim in the crown splash regime." Journal of Fluid Mechanics 752, 485–496.

    What we did: in the notes; not built as a rule.

  • Nagula Venkata Anirudh, Sachidananda Behera, Kirti Chandra Sahu, 2026. "Unveiling crown-finger instability of a non-spherical drop impacting a liquid surface." arXiv 2601.19621, accepted in the Journal of Fluid Mechanics.

    What we did: in the notes; not built as a rule.

Growth and pattern

  • Thomas A. Witten, Leonard Sander, 1981. "Diffusion-Limited Aggregation, a Kinetic Critical Phenomenon." Physical Review Letters 47, 1400–1403.

    Informed the design, rejected. What we did: walkers judged too slow; mould's radius is a formula of age instead.

  • Karl Sims. "Reaction-Diffusion Tutorial."

    Informed the design, not built. What we did: Gray-Scott noted as an idea; not in the sim.

  • Jeff Jones, 2010. "Characteristics of pattern formation and evolution in approximations of Physarum transport networks." Artificial Life 16(2), 127–153.

    Informed the design, not built. What we did: a bonus idea in the notes; not built.

  • Alan M. Turing, 1952. "The Chemical Basis of Morphogenesis." Philosophical Transactions of the Royal Society B 237, 37–72.

    Not used yet. The classic paper on patterns from reaction and diffusion.

Fire

  • Zeki Melek, John Keyser, 2005. "Multi-representation interaction for physically based modeling." ACM Symposium on Solid and Physical Modeling, pp. 187–196.

    What we did: consulted for burning paper; no deformation from burning built.

  • Zeki Melek, John Keyser, 2006. "Bending burning matches and crumpling burning paper." SIGGRAPH 2006 Posters.

    What we did: as above.

  • Zeki Melek, John Keyser, 2007. "Driving object deformations from internal physical processes." Symposium on Solid and Physical Modeling, pp. 51–59.

    What we did: as above.

  • Caroline Larboulette, Pablo Quesada, Olivier Dumas, 2013. "Burning Paper: Simulation at the Fiber's Level." Motion in Games 2013, pp. 47–52.

    Informed the design, rejected. What we did: its mass-spring curling turned down in writing as overkill.

  • Richard C. Rothermel, 1972. A mathematical model for predicting fire spread. USDA Forest Service research paper INT-115.

    Not used yet. The classic wildland spread model: moisture, wind, slope. The wrong fuel scale for paper; useful as a concept.

  • Duc Quang Nguyen, Ronald Fedkiw, Henrik Wann Jensen, 2002. "Physically Based Modeling and Animation of Fire." ACM TOG 21(3), 721–728.

    Not used yet. Fire in graphics: flames rather than fronts on paper.

  • J. Maunuksela et al., 1997. "Kinetic Roughening in Slow Combustion of Paper." Physical Review Letters 79, 1515–1518.

    Not used yet. A lead on burning fronts in paper; not read.

  • O. Zik, Z. Olami, E. Moses, 1998. "Fingering Instability in Combustion." Physical Review Letters 81, 3868–3871.

    Not used yet. A lead on burning fronts; not read.

Electricity

  • Gustav Kirchhoff, 1845. "Ueber den Durchgang eines elektrischen Stromes durch eine Ebene, insbesondere durch eine kreisförmige." Annalen der Physik 140(4), 497–514.

    What we did: a historical aside. It is about what the game does, current spreading across a flat sheet; the repo names only Kirchhoff's laws.

  • David M. Young, 1954. "Iterative methods for solving partial difference equations of elliptic type." Transactions of the AMS 76, 92–111.

    What we did: the circuit uses over-relaxation, forward then back; no citation in the repo.

Sandbox games and talks