Professor Oops

Runny, sticky and oily

Runny, sticky and oily

Ketchup stands, honey runs and oil floats, with no code for any one liquid

Squeeze ketchup and it keeps its bead. Pour honey and it creeps out flat. Oil floats on water, beaten into egg yolk it turns into mayonnaise, and soap on milk sends the colours flying. Nobody wrote a special effect for any of these. Each spot of the page stores what lies there, and every liquid follows the same few rules with its own numbers.

Painted illustration of the painter shaking a jar, beside a jar of golden oil floating on blue water, a jar of creamy mayonnaise, an egg yolk and mustard

How runny a sauce is and how steep a slope it can hold decide whether it stands or spreads

Everything thick on the page, from paint to mud, is stored as a depth in each tiny square, about half a millimetre across. Many times a second, each square compares its height with its four neighbours and passes some of itself downhill. How much it passes comes from two numbers in the material's row of one shared table: how runny it is, and how steep a slope it can hold before it gives way. That second number is its yield.

Ketchup has a high yield. A step of nearly a whole square's height between neighbours stays put, so ketchup keeps a bead about 42° steep. Mustard holds 45°, mud 39°, tube paint 37°. Honey has no yield at all. It is only slow, and it keeps creeping until it is too thin to flow.

Testing a slope square by square has a catch. Each square looked at its four sides separately, so along a diagonal a slope could be √2 steeper before anything moved, and heaps came to rest as diamonds. next update Pastes now test how steep the whole slope is, whichever way it falls, and heaps come to rest round.

Thin liquids get one more change. next update Milk, ink, juice and drinks keep their way as they run, through four pipes per square that remember what went each way, slowed by the liquid's real viscosity. A hand dragged through milk leaves a track that is half full again in under half a second. In the released game that takes 1.7 s, and milk closes up more like syrup.

Ketchup stands, honey runs and oil floats, with no code for any one liquid

For engineers

Ketchup stands, honey runs and oil floats, with no code for any one liquid

Each cell (about 0.5 mm; 512 × 384 on a full sheet, 288 × 216 on a phone) stacks a water film, a goop layer and a floating layer. Goop moves by explicit height diffusion with a yield dead zone, at 60 Hz, every constant read from one shared material table. Layering follows from a few properties each material has and a density comparison. The code that moves liquids contains no material id at all.

Under the hood
How runny a sauce is and how steep a slope it can hold

Under the hood

How runny a sauce is and how steep a slope it can hold

Each cell keeps a depth, a colour stored as absorbance times height (so goops mix like paint and nothing is made or lost), how much of it has set, and one material. The surface each cell compares includes the paper's own dents and cockle, so the paper's bumps steer every run.

The released rule is a height diffusion with a dead zone: past the material's yield, flow grows with the excess slope, scaled by its runniness, and below a thin film nothing flows. A stability cap keeps the explicit step from overshooting. Mobility falls as a goop sets and its yield rises, so a drying sauce stiffens by the same rule.

next update Pastes test the slope's magnitude instead of each side alone. Straight down one side this is the old rule, and a cheap early exit keeps cells at rest nearly free. A test holds heaps of melted ice cream, egg white and slime round to within a few per cent, where a diamond would be √2 out. Fats on the paper and the floating layer still test per side.

next update Thin liquids run in virtual pipes with water's real g and a viscous hold that follows Poiseuille flow in a thin film. The push is capped for stability, and for a clean liquid the cap wins, so g doesn't set the speed: a real wave on 3 mm of water runs at about 17 cm/s, the game's much slower. Viscosity does slow them. Pipes as a technique are consistent with O'Brien 1995; the yield idea was informed by Liu 1989, a Bingham-like paste in a height field.

Try it: drop heaps of sauce The game's own rule

Ketchup on the left, honey on the right, run by the game's flow rule with their own table numbers. Pick a sauce and tap the paper to drop a heap, or press Drop a heap. What to look for: ketchup stops almost at once, honey never quite does. Then pick melted ice cream, drop it, and switch the yield test: per side it settles toward a diamond, by slope it comes out round. The roundness readout is the test's own measure (1 is round, 1.41 a diamond).

Heaps of ketchup and honey on paper, settling by the game flow rule
Tap to drop
Yield test
×4
yield of the sauce you drop
—
as a slope
—
last heap roundness
—
simulated
—
A ketchup zigzag still standing in a raised bead beside a honey puddle that has spread flat
In the game. The same two rows of the table on a real page: the ketchup zigzag still stands, the honey has spread flat.
How fast each thing spreads in the game (log scale)The whole range is narrow, and honey is only a few times slower than oil. In a kitchen honey is thousands of times thicker than water. On the next update, thin liquids also carry momentum, so this rate is only their ooze.

Drink spreads at 13.8 cells² a second, milk 12, oil 10.8, ketchup 6, mud 4.2, paint 3.6, honey 1.5 and dough 0.72.

How fast each thing spreads in the game (log scale)0.1110100drinkmilkoilketchupmudpainthoneydoughcells² per secondHow fast each thing spreads in the game (log scale)0.1110100drinkoilmudhoneycells² per second
Data table
How fast each thing spreads in the game (log scale)
spreading rate
drink13.8
milk12
oil10.8
ketchup6
mud4.2
paint3.6
honey1.5
dough0.72

Source: Runniness from the game's own material table (paint is tube paint), as a spreading rate.

Oil floats because it's light and shuns water, and the code never names oil

Each square can hold three things stacked: a film of water, a layer of goop, and a floating layer on top. Whenever something lands, one function decides where it goes by asking its row three questions. Does it shun water? Is it lighter than water and runny? Is it soft goop at all, and not grains or a lump?

Two soft things stay apart when one of them floats and only one of them shuns water. Then the lighter one lies on top. Oil on ketchup floats. Honey poured onto oil goes under it, and the oil comes up on top. Oil on melted chocolate stirs in: for its cocoa butter, chocolate's row puts it right on the line where a thing counts as oily. Melted cheese sits just under that line, so by the same rule oil floats on it.

Search the code that moves liquids for the name of any material and you find none. The rows of the table are typed in by hand, though, and a few sit exactly on a line because that gives the right result: chocolate and marbling ink both sit right on the line for shunning water. So the fair claim is that the code never names a material, and the table decides.

Because the layers are real state, everything else can read them. A paper towel dabbed on oily water takes the oil on the first dab and the water on the second. A thin film of oil stops a puddle drying: after 50 s the bare puddle is down to under 10 %, the oiled one still over half.

Under the hood
Oil floats because it's light and shuns water

Under the hood

Oil floats because it's light and shuns water

Three properties are worked out once from each row of the table: is it oily, is it soft, does it float. Two soft things stay apart when at least one floats and they differ on oily. Everything that lands goes through one layering function, and by these rules cooking oil, butter, wax and marbling ink are the things that float. Density is only ever compared: there's no buoyancy force and no ordering among things that mix.

Readers pick a layer by two rules. A touch from above meets the top first once the film is thick enough to cover, and an emulsion covers nothing. Evaporation is scaled by how open the water is to the air, so even a sheen of oil seals it. A test pins that a film of oil keeps a puddle from drying.

The floating layer has its own flow: the same rule, slowed where it is beaten into what lies under it, and quicker and thinner-spreading over a liquid than on paper (a test checks it covers clearly more area there). A page with no oil skips all of it, tile by tile; a test checks that the renderer then gets byte-for-byte what it got before.

One square, from the side

Floating layer

oil · wax · butter

Thick: covers. A sheen: seals. A towel, wind, a flame meet the top.

Goop layer

depth · colour · set

One material.

Water film

Can hold oil. Deep: lifts it.

Paper

Dent, cockle.

Up to three things stack in one square, each with its own fields: on top what shuns water and is light, under it one goop with its colours mixed, and under that the paper's own water. The notes are the rules that decide which layer a towel or the wind meets first, and when oil seals the water from the air. The water and the goop use different units on purpose.

Who floats on whom? The game's own rule

Slide to pick what you pour and what it lands on. The answer comes from the same three properties and density comparison the game uses, from each material's row. Try: oil onto melted chocolate, then oil onto melted cheese.

What you pour lying on top of, going under, or mixing into what it lands on, by the game's layering rule
7
you pour
—
1
onto
—
what you pour
—
rule
—
poured: shuns water
—
→
—
density
—
floats
—
below: shuns water
—
→
—
density
—
floats
—
A puddle of blue water with a golden film of cooking oil spread over it, thickest towards the edge, the blue showing through the gold in the middle, dry paper around
In the game. Cooking oil poured onto a puddle of blue water spreads over it as a golden film of its own. Where the film is thin the blue shows through; the oil lies on top and doesn't mix in.

Beat oil into egg yolk and it stays mayonnaise, beat it into vinegar and it clears

Pour oil onto egg yolk and leave it, and it stays a layer on top. Only working it mixes them: a finger whisking, a blow, drops splashing in. Then the two cloud together, and what happens next depends on what's in the bowl.

Yolk carries an emulsifier, and a little yolk can hold several times its own amount of oil. Beaten, it goes creamy and stays that way: a test checks it is still creamy two minutes later. Once there is clearly more oil than yolk, fully beaten, the oil is packed so tight that it stands up like mayonnaise. Vinegar has no emulsifier. Beaten, it clouds over, and in about two minutes it has cleared again. Soap counts as an emulsifier too, and soapy water worked over a grease spot lifts the fat out of the paper.

There are no droplets in the simulation. Each square keeps one number: the share of its oil beaten into what lies under it. The oil stays counted as oil and the water as water, so nothing can go missing when it separates again.

Under the hood
Beat oil into egg yolk and it stays mayonnaise

Under the hood

Beat oil into egg yolk and it stays mayonnaise

Per cell, one number holds the share of the floating oil that is beaten into the layer under it. Anything that works the page (a finger, wind, a splash) leaves a record of how hard it was stirred, and the share climbs toward what the water present can take, faster where an emulsifier is on hand. How much emulsifier there is, from the yolk, the oil's own row or soap, sets how much oil it can hold. Where it can't hold it all, the share relaxes back at a steady rate, faster the further short it falls.

Stiffness comes from the share of oil, φ = oil/(oil + water), in the bottom layer's flow: past a certain packing the emulsion runs less and less freely, and fully packed it stands. That is the same jamming that makes real mayonnaise stiff, reduced to one ramp.

Automated tests pin both ends: stirred yolk and oil stay creamy for two minutes with almost no oil lost, vinegar and oil clear, oil left on yolk unbeaten stays a layer, a little oil in milk still slumps and a lot of it stands. Standing is tested on milk with the emulsion set by the test; no test beats a yolk and then measures it standing.

Try it: whisk oil into a bowl The game's own rule

The bowl opens being whisked. Drag across it to whisk more, or press Whisk, then watch. What to look for: with egg yolk the cream stays; with vinegar or milk it goes back to streaks of oil within a couple of minutes (raise the time-lapse). Add oil until the readout says it stands. The emulsion rule is the game's; how it evens out across the bowl is a simple blur here.

A bowl of oil on egg yolk being whisked into an emulsion
In the bowl
2.0
×1
oil beaten in
—
emulsifier holds
—
it
—
since whisking
—
After beating: what stays mixedA test checks yolk is still creamy after two minutes and vinegar clears.

Egg yolk stays fully mixed; with half the emulsifier it needs, 22 % is still mixed after two minutes, and beaten vinegar is down to 5 %.

After beating: what stays mixed0.00.20.40.60.81.0050100150seconds after you stopshare still mixedtested hereAfter beating: what stays mixed0.00.20.40.60.81.0050100150seconds after you stopshare still mixedtested here
  • egg yolk (holds fully)
  • half the emulsifier it needs
  • vinegar (none)
Data table
After beating: what stays mixed
seconds after you stopegg yolk (holds fully)half the emulsifier it needsvinegar (none)
0111
310.96320.9277
610.92770.8607
910.89360.7985
1210.86070.7408
1510.8290.6873
1810.79850.6376
2110.76910.5916
2410.74080.5488
2710.71360.5092
3010.68730.4724
3310.6620.4382
3610.63760.4066
3910.61420.3772
4210.59160.3499
4510.56980.3247
4810.54880.3012
5110.52860.2794
5410.50920.2592
5710.49040.2405
6010.47240.2231
6310.4550.207
6610.43820.192
6910.42210.1782
7210.40660.1653
7510.39160.1534
7810.37720.1423
8110.36330.132
8410.34990.1225
8710.33710.1136
9010.32470.1054
9310.31270.0978
9610.30120.0907
9910.29010.0842
10210.27940.0781
10510.26910.0724
10810.25920.0672
11110.24970.0623
11410.24050.0578
11710.23170.0537
12010.22310.0498
12310.21490.0462
12610.2070.0429
12910.19940.0398
13210.1920.0369
13510.1850.0342
13810.17820.0317
14110.17160.0295
14410.16530.0273
14710.15920.0253
15010.15340.0235
15310.14770.0218
15610.14230.0202
15910.1370.0188
16210.1320.0174
16510.12710.0162
16810.12250.015
17110.11790.0139
17410.11360.0129
17710.10940.012
18010.10540.0111

Source: The game's separation rule: an emulsion short of emulsifier relaxes back at a steady rate, faster the further short it falls.

More oil, stiffer emulsionMarks: oil to milk 1 : 5 and 4 : 1, the two cases a test checks (a fifth as much oil as milk runs; four times as much stands).

Up to a share of oil of 0.35 it runs freely; from 0.35 to 0.6 it stiffens, and past 0.6 it stands.

More oil, stiffer emulsion0.00.20.40.60.81.00.00.20.40.60.81.0share of oil, φhow freely it runs1 : 54 : 1More oil, stiffer emulsion0.00.20.40.60.81.00.00.20.40.60.81.0share of oil, φhow freely it runs1 : 54 : 1
Data table
More oil, stiffer emulsion
share of oil, φhow freely it runs
01
0.011
0.021
0.031
0.041
0.051
0.061
0.071
0.081
0.091
0.11
0.111
0.121
0.131
0.141
0.151
0.161
0.171
0.181
0.191
0.21
0.211
0.221
0.231
0.241
0.251
0.261
0.271
0.281
0.291
0.31
0.311
0.321
0.331
0.341
0.351
0.360.96
0.370.92
0.380.88
0.390.84
0.40.8
0.410.76
0.420.72
0.430.68
0.440.64
0.450.6
0.460.56
0.470.52
0.480.48
0.490.44
0.50.4
0.510.36
0.520.32
0.530.28
0.540.24
0.550.2
0.560.16
0.570.12
0.580.08
0.590.04
0.60
0.610
0.620
0.630
0.640
0.650
0.660
0.670
0.680
0.690
0.70
0.710
0.720
0.730
0.740
0.750
0.760
0.770
0.780
0.790
0.80
0.810
0.820
0.830
0.840
0.850
0.860
0.870
0.880
0.890
0.90
0.910
0.920
0.930
0.940
0.950
0.960
0.970
0.980
0.990
10

Source: The game's stiffness ramp: past a certain packing of oil the emulsion jams.

Soap on milk pulls the surface away, and the show ends when the soap is used up

Drop food colouring on milk, touch it with soap, and the colours burst away from the soap. That's the Marangoni effect Scriven 1960. Soap lowers the surface's tension, and the clean surface around it, pulling harder, draws the surface toward itself, carrying the colours along.

In the game soap lies on the surface as an amount per square. The surface moves as a sheet of blocks four squares across, each pulled toward where the tension is higher. Milk's fat matters twice. It makes the surface answer harder, so milk pulls far harder than water. And it binds the soap and is spent doing so. The motion eases by itself as the soap is used up and evened out, with no timer anywhere.

The same moving surface carries whatever rides on it. Soap on a puddle sprinkled with pepper sends the pepper fleeing at once. Soap on wet watercolour pushes the paint into a ring round a pale hole.

In the released game the colours burst outward and curl a little at the edges. next update They really swirl. Cream isn't spread evenly through milk, so along the soap's front the pull is stronger in one stretch than the next, and the two shear past each other. That difference spins the surface, and the spin goes on for seconds after the push has eased.

Under the hood
Soap on milk pulls the surface away

Under the hood

Soap on milk pulls the surface away

The surface sheet runs at a lower rate than the liquids, only while something moves, and only over a box round the soap. It is coarser than the page: each block covers a small patch of squares.

Soap lowers the tension along a saturating curve, so a little soap does most of the work and more soap on a soapy spot adds little. The surface pull follows the tension's slope, grows with the milk's fat, and ignores slopes too faint to matter. The sheet's velocity relaxes toward that pull, carried along by itself semi-Lagrangian, as in the air Stam 1999, and kept curling by vorticity confinement, consistent with Fedkiw 2001, under a speed limit. There's no pressure projection: the sheet may bunch and thin. Soap slowly sinks out of the surface and is bound by free fat, which spends the fat; that is what ends the show.

next update The swirl: the fat varies over the milk in a smooth noise seeded by the paper, much more than in the released game. The curl of the pull spins up vorticity, which decays over seconds; a stream function is solved from it each step by a few warm-started over-relaxation sweeps, and the surface moves round its contours. A test checks that uneven fat turns the surface and even fat barely does.

An automated test pins the burst: it opens fast in the first second, is still moving more than ten seconds later, never leaps, and at last rests. The WebAssembly twin keeps every colour and the milk to within rounding. The finite, easing clearing is consistent in kind with Roché 2014; nothing was fitted to it.

Try it: soap on milk The game's own rule

A soap drop lands in the middle soon after it opens. Tap to add more soap, or switch to colour and tap to add drops; the buttons add them too. What to look for: the burst, then the slow easing as fat binds the soap. A second soap drop on a soapy spot does little; on clean milk, a lot. Switch to the next update's milk for the swirl. The surface sheet follows the game's rule; here soap and colours ride it by a simpler method than the game's, and both keep every drop.

Food colouring on milk bursting away from a drop of soap
Tap adds
Milk
fastest
—
soap on the surface
—
most fat spent in a square
—
time
—
Milk with red, blue, yellow and green food colouring bursting away from a touch of soap
In the game. Four drops of food colouring on milk, a moment after a drop of dish soap in the middle.
A little soap does almost everythingThe soap axis is logarithmic: −5 is 0.00001, 0 is 1. A test checks that a drop on a spot already soapy does little; on clean milk, a lot.

Tension is half gone at 0.005 of soap; by 0.05, where a spot counts as already soapy, it is down to 0.09.

A little soap does almost everything0.00.20.40.60.81.0−5−4−3−2−10soap on the surface, as a power of tensurface tension σalready soapyhalf-wayA little soap does almost everything0.00.20.40.60.81.0−5−4−3−2−10soap on the surface, as a power of tensurface tension σalready…half-way
Data table
A little soap does almost everything
soap on the surface, as a power of tensurface tension σ
−50.998
−4.93750.9977
−4.8750.9973
−4.81250.9969
−4.750.9965
−4.68750.9959
−4.6250.9953
−4.56250.9946
−4.50.9937
−4.43750.9927
−4.3750.9916
−4.31250.9904
−4.250.9889
−4.18750.9872
−4.1250.9852
−4.06250.983
−40.9804
−3.93750.9774
−3.8750.974
−3.81250.9701
−3.750.9657
−3.68750.9605
−3.6250.9547
−3.56250.9481
−3.50.9405
−3.43750.9319
−3.3750.9222
−3.31250.9113
−3.250.8989
−3.18750.8851
−3.1250.8696
−3.06250.8524
−30.8333
−2.93750.8124
−2.8750.7895
−2.81250.7645
−2.750.7377
−2.68750.7089
−2.6250.6783
−2.56250.6461
−2.50.6126
−2.43750.5779
−2.3750.5425
−2.31250.5066
−2.250.4707
−2.18750.435
−2.1250.4
−2.06250.366
−20.3333
−1.93750.3022
−1.8750.2727
−1.81250.2451
−1.750.2195
−1.68750.1958
−1.6250.1741
−1.56250.1544
−1.50.1365
−1.43750.1204
−1.3750.106
−1.31250.0931
−1.250.0817
−1.18750.0715
−1.1250.0625
−1.06250.0546
−10.0476
−0.93750.0415
−0.8750.0361
−0.81250.0314
−0.750.0273
−0.68750.0238
−0.6250.0206
−0.56250.0179
−0.50.0156
−0.43750.0135
−0.3750.0117
−0.31250.0102
−0.250.0088
−0.18750.0076
−0.1250.0066
−0.06250.0057
00.005

Source: The game's tension curve: a chosen saturating shape, not a fitted isotherm.

Fat makes the surface pull harderThe game has one milk: skimmed exists only in a test that changes the table, where it bursts clearly less far.

Water pulls at 180, skimmed milk (in a test) at 250 and whole milk at 547 cells a second per unit of σ slope.

Fat makes the surface pull harder0100200300400500600waterskimmed (test)whole milkpull, cells/s per σ slopeFat makes the surface pull harder0200400600waterskimmed (test)whole milkpull, cells/s per σ slope
Data table
Fat makes the surface pull harder
pull
water180
skimmed (test)250
whole milk547

Source: The game's pull with even fat, from milk's row in the material table.

A hand, a toothpick and a drop of ink move liquid without making or losing any

Drag a palm through paint and the paste heaps up in front of it while runny stuff closes in behind. A soft palm doesn't wipe the paper clean. It rides on part of the paste and leaves a thinner layer behind, faintly streaked along the stroke. The same code serves a palm, a paw, a wheel, a ball and a squeegee. They differ in footprint, hardness, how flat their face is and how much they slip.

Strike oobleck with a hammer and it doesn't splash; press it slowly and you sink in. The faster a push is for its size, the more the cornflour jams.

A toothpick works differently. It drags what is near it along, and what is further out flows back the other way, the way a stick swirls colour on shaving foam. The flow is built so that whatever goes into a square comes out of it. The colour is drawn into veins and none is lost.

Marbling ink shows this most clearly. A new drop on water spreads at once into a thin film and pushes every earlier ring outward by exactly as much as makes room for itself. Drop after drop in one spot makes rings inside rings, each colour kept. Comb them and you get feathers. The result barely depends on how you move: combing in one long swipe or in tiny moves comes out within 15 % on shape.

Under the hood
A hand, a toothpick and a drop of ink move liquid

Under the hood

A hand, a toothpick and a drop of ink move liquid

Any drag becomes a row of small pushes along the stroke. Each push takes a share of what lies under the footprint, more near its middle and more from soft stuff, and sets it down a little ahead, spread smoothly over neighbouring cells so a slanted stroke doesn't staircase. A flat face ploughs only what holds its shape. A soft face rides on part of the film, depending on how hard it is and how well the stuff clings, and leaves faint streaks along the stroke. Afterwards a paste slumps back to a slope its yield can hold. Oobleck jams by how fast the push is for its size, so a hammer meets a solid and a slow press sinks in. A test checks that the film left behind depends on the material, that its streaks run along the stroke, and that none is made or lost. Height-field pushing like this was informed by Sumner 1999.

A point moves the liquid with a stream function along its path: it drags what is near and sends a gentle return flow further out. Each face's flow is a difference of the stream function at its corners, so it is divergence-free by construction, and nothing can pile up or vanish. A marbling drop uses the point source of mathematical marbling: every spot of the film at radius r moves out to √(r² + a), where a is the drop's own area over π, so the old rings make exactly the room the new drop needs. A test checks the rings stay concentric with their colours kept, and that combing keeps each spot's main colour with very little mud.

Try it: drop and comb marbling ink The game's own rule

Drops land in the middle, then a toothpick combs across. Tap to drop ink, or switch to the toothpick and drag; Drop ink and Comb across do the same from the keyboard. What to look for: each new drop pushes the old rings out without mixing them, and combing makes feathers. The readout compares the film's area with what the drops put in: combing never changes it. The rings here are outlines moved by the game's own formulas; the game moves the film cell by cell.

Marbling ink drops pushed into rings and combed with a toothpick
Tap or drag
10 cells
drops
—
film area
—
drops put in
—
A band of blue tube paint after one palm stroke from left to right: a raised ridge of paint where the hand stopped, a flatter, faintly streaked layer in the track behind
In the game. One palm stroke through tube paint, left to right: the paste piles up in a ridge where the hand stopped, and the track behind keeps a thinner layer, faintly streaked along the stroke.
Rings of blue, red and yellow marbling ink on water, combed by a toothpick into pointed feathers
In the game. Marbling inks dropped in one spot, blue, red and yellow twice over, then combed with a toothpick three times across.

Butter leaves a see-through spot, soapy water froths and mud cracks as it dries

Grease. Melt butter on paper and it leaves a see-through spot that widens slowly to an edge and stops. Water and a sponge won't shift it. Add dish soap to the water and it washes out without scrubbing. Wet paper won't take fat in, and greasy paper keeps most water out, so whichever came first wins. Fat washed out always comes up as cooking oil, whatever went in: the paper keeps one number for fat, not a recipe.

Foam. Soapy water rubbed or splashed froths up into foam; still water on soap stays still. The foam itself is a stiff goop that never flows, and the bubbles on it are drawn objects with timers, up to a fixed number. They swell, pop and leave the paper a little damp. No gas is tracked.

Mud. Mud is just another row in the table, like ketchup: fairly stiff, holding a slope nearly as well as ketchup, and it forms a crust as it dries. A splat of it comes with pebbles and twigs. Leave it six hours or bake it, and it cracks into plates a few millimetres across. The cracks are a pattern laid down at the end of the wait. No stress is worked out, and nothing cracks while you play.

next update Stones lie on mud as a layer of their own and sink as the mud under them slumps, and froth bursts within seconds unless soap holds it up.

Under the hood
Butter leaves a see-through spot, soapy water froths and mud cracks

Under the hood

Butter leaves a see-through spot, soapy water froths and mud cracks

Grease: paper holds a limited amount of fat in its fibres. Fat goes in only as far as there's room and the paper isn't wet, and greasy paper soaks water more slowly in turn. Every so often the fat spreads by neighbour diffusion of what is above a held amount, so a spot widens to an edge and stops; once it is still, the code stops looking at it. It's drawn see-through in proportion to how full the paper is. Soapy water worked over it lifts some out each time. The oven reruns the same rule many times over. An automated test pins how it washes out.

Lather is made a few times a second, only where soap is worked and water is there; strong wind counts as working it. Bubbles have a random size, and their chance of popping grows with age and is higher for small ones, so the small ones go first.

Mud: a Voronoi pattern is applied once after a wait of six hours or more, or the oven; thin gaps crack, edges curl and the plates go paler. Crusting loses water only, so the colour per unit stays and deepens; a skin holds a light touch, and a palm breaks it where a fingertip doesn't.

Try it: a grease spot, a heap of suds, a mud pie The game's own rule

Pick one and tap the paper, or press Add one. What to look for: the butter spot widens fast, then slower, and stops at an edge (the readout says when it's at rest). The small bubbles go first and the heap thins out over a minute. The mud dries for six hours in a few seconds, then cracks into plates all at once. Each runs on the game's numbers: the grease spot on its own spreading rule, the bubbles on their own pop chance, the cracks on mud's plate size and gap. The drawing is simpler than the game's.

A butter spot spreading in paper, a heap of suds popping, or mud drying and cracking, by the game rules
Tap adds
spot across
—
fat
—
bubbles
—
popped
—
in play
—
drying
—
plates
—

Most of the page sits still, so the tablet only works where something moves

A full page is about 200,000 squares, and most of them aren't moving at any moment. The page is cut into small tiles that sleep when nothing in them changes, wake when something lands, and make up the time they slept when they get their turn. On a page with no oil the floating layer's work is skipped. The soap-on-milk surface only runs while something moves, and only round the soap.

The busiest loops also run as WebAssembly, written by hand and checked against the plain code square by square, most of them to the last bit. The engineering chapter tells that story.

Under the hood
Most of the page sits still, so the tablet only works where something moves

Under the hood

Most of the page sits still, so the tablet only works where something moves

Tiles are awake, creeping or settled. Creeping tiles are worked less often, settled ones only looked at now and then, and empty ones hardly ever, within a per-frame tile budget that shrinks with the detail level. Slow local work (soaking, staining, drying) catches up in closed form when a tile gets its turn; a test holds ketchup's stain at the lightest detail close to what full detail gives.

WebAssembly twins of the goop, floating-layer, Marangoni and pushing loops, written by hand in AssemblyScript and working in the simulation's own memory. Goop, pushing and Marangoni are bit-exact with their JavaScript, each pinned by its own test; the floating layer agrees to within rounding. Measured when each landed: pushing 2.6–2.9× faster than JS with oil on the page; the floating layer 2.2–2.4× less time, 30–35 % less a tick in all; Marangoni on milk with 12 drops and 2 of soap, 2.8–3.0 ms a tick down to 1.5–1.7 ms at 432 × 324. Of these four, in the released game only the floating layer uses SIMD. Time skips run the same flow passes in slices, on the same tile budget on every device, so a slow tablet gets the same page.

3
things can stack in one square: a water film, a goop layer and a floating layer.
0
material names in the five files that move liquids. The table decides.
512 × 384
squares on a full page, each about half a millimetre, most of them asleep until something moves near them.
2 min
for beaten vinegar and oil to clear again. Beaten egg yolk stays creamy.
4
liquid loops with a hand-written WebAssembly twin; three of them bit-exact with the plain code.
2.6–2.9×
faster pushing through oily goop with the WebAssembly twin than in plain JavaScript.

Fire, wind and the dog meet the same oil and milk, because they all read the same layers

The fire, the wind and the dog read and write the same fields as the liquids, and the effects below come out of that. Each is pinned by a test.

Shared: floating layer over water · air contact

Pour a little oil on one of two puddles and wait

The bare puddle dries; the oiled one is still there.

Water in paper

Shared: water under the floating layer · heat

Drip water on burning oil

It flashes to steam and throws the burning oil up. On hot oil it only spits; on cold oil it slides under.

Heat and fire

Shared: wind · the top layer

Blow a hair dryer over oil lying on a sauce

The oil film blows along; the sauce under it barely moves, held by its yield.

Air that really moves

Shared: the top layer · what paws carry

Let the dog walk through oily water

It leaves oily paw prints wherever it goes next.

Animals with their own minds

Shared: acid element in goop

Brush lemon juice into milk

With enough of it, the milk curdles into curd and whey.

Chemistry and pH

Shared: surfactant · wet paper's film

Touch wet watercolour with soap

The surface pulls away and pushes the paint into a ring round a pale hole.

How colours mix

Ketchup stands and honey runs on a tablet because the game gives up splashing and sloshing

A child on a tablet needs ketchup that stands and honey that runs, sixty times a second, on 200,000 squares. Each shortcut below keeps a behaviour a child can see, and gives up something nobody at that scale would notice.

In real life. Liquids are three-dimensional and carry momentum.

In the game. A height field: one depth, one colour, one material per layer per square. Pastes have no velocity at all.

Why that's enough. It runs on a phone. Lost: overhangs, folding and sloshing; ketchup never splashes back.

In real life. A yield-stress paste holds where its weight on the slope is below its yield, so a thicker layer holds a gentler slope.

In the game. A slope threshold per material, with no depth in it. Only the separate slide rule on a tilted page looks at depth.

Why that's enough. One number gives the bead. Heaps rest as straight-sided cones, not domes, and the threshold isn't a stress: it has no units.

In real life. Viscosities span thousands to one between water and honey.

In the game. Runniness spans a narrow range. Honey is only a few times slower than oil.

Why that's enough. An explicit step is only stable below a limit, and anything much slower looks stuck. Speed is a feel here, not a measurement.

In real life. Thin films flow as depth cubed.

In the game. Paste flow grows with the slope past the yield, independent of depth; below a thin film nothing flows.

Why that's enough. Stable and cheap. A thick pool and a thin film creep at the same rate until the film is thin enough to stop.

In real life. Liquids sort into towers by density.

In the game. Two layers and a water film. Density is compared only for things that don't mix.

Why that's enough. A few extra numbers a square, and no work for them on a page with no oil. No density tower: honey in milk just mixes.

In real life. Two liquids in one spot blend their properties.

In the game. Colours average by amount; the material is winner-takes-all, the biggest stream coming in.

Why that's enough. One material a square. A honey and ketchup mix behaves as one or the other, square by square.

In real life. An emulsion is droplets of many sizes.

In the game. One share per square, a stiffness ramp as the oil gets packed, and a steady rate of separating.

Why that's enough. Oil is conserved by construction. Droplet size is gone; the rate and the ramp are tuned to read right.

In real life. Soap lowers tension along a measured curve, and the surface drags the liquid under it.

In the game. σ falls along one saturating curve, the same for water and milk; a coarse sheet relaxes toward the pull, with no projection.

Why that's enough. Only the slope of σ drives the flow, and the shape is right in kind. The strength of the pull is tuned, and the milk's depth plays no part.

In real life. Foam coarsens as gas moves between bubbles; mud cracks by stress as it shrinks.

In the game. Bubbles are circles with timers; cracks are a Voronoi pattern laid down at the end of a long wait.

Why that's enough. Both look right for the cost of almost nothing. Neither changes during play the way the real thing would.