programextensions/scene/demos/voxels-water.xtl
Voxels, 11: water that flows. A stepped hill stands by the start with a lake on its top terrace, held in by a rim of grass. Dig into the rim and the lake spills out and runs down the steps like a waterfall; dig beside the sea and the hole fills. Water flows as a cellular automaton on the cells it has just reached (Endless.xtl): each tick a cell falls into the air below it, or, standing on something solid, spreads one level lower into the air at its sides, 7 levels from a source; the lake and the sea are sources that never empty. The cells it reaches are edits like any dug or placed block, so the water stays where it ran. Water is drawn translucent: the lake's floor and the seabed show through. Run: just demo scene voxels-water click (or X) dig, right-click (or E) place, 1 to 7 choose the block (7 is water, which flows), W A S D walk, Space jump, Shift run, F fly (Space up, Shift down), drag or the arrows to look, H back to the rim, q quit
The hill and its lake
hv : Int
A stepped hill on the 17 by 17 columns around (8, 8), built as edits before any column is made: each ring around the center (r, the larger of the distances east-west and north-south) one block lower than the one inside it, down to the ground; the top terrace (r up to 3) at T, five blocks above the highest ground there, dirt under grass; on it a lake (r up to 2) two blocks deep, held in by the rim (r = 3): 50 cells of moving water, each a full block, 25 a layer.
hv ← r̲avel ᵛˣh̲eightsAt 0 0 17
ᵘc̲ells : Int -> Int
ᵘc̲ells ← { m → 2 1 t̲ranspose (3 c̲at '+ r̲/ m) r̲eshape (m r̲eplicate cx) c̲at (m r̲eplicate cy) c̲at m r̲eplicate cz }
s : ((Float, Float, Float, Float, Float, Float), (Int, Int, Box Int, Box Int, Int, Int, Int, Int), (Int, Int, Int, Int), (Int, Int, Float, Int, Int))
the player on the rim, south of the lake, facing it (north)
s ← w ᵉⁿn̲ewAt 8.5 c̲at (f̲loat T + 1) c̲at 11.5
s : ((Float, Float, Float, Float, Float, Float), (Int, Int, Box Int, Box Int, Int, Int, Int, Int), (Int, Int, Int, Int), (Int, Int, Float, Int, Int))
s ← (ᵘc̲ells fill, fill r̲eplicate blk) ᵉⁿs̲etAll s
s : ((Float, Float, Float, Float, Float, Float), (Int, Int, Box Int, Box Int, Int, Int, Int, Int), (Int, Int, Int, Int), (Int, Int, Float, Int, Int))
s ← (lake c̲at₂ ((t̲ally lake) c̲at 3) r̲eshape ᵉⁿfull c̲at 0 0) ᵉⁿp̲our s
Measuring
ᵘm̲easure : (Any a, Any b, Any c, Any d, Any e, Any f, Any g, Any h, Any i, Any j) => (a, (b, c, d, e, f, g, Int, h), i, j) -> (a, (b, c, d, e, f, g, Int, h), i, j)
u:m_easure s: the lake's two layers and all the moving water, in blocks of water, said
ᵘm̲easure ← { s → W ← ᵉⁿw̲ater s x ← 1 s̲elect₂ W y ← 2 s̲elect₂ W z ← 3 s̲elect₂ W inlake ← ((a̲bs x − 8) m̲ax a̲bs z − 8) ≤ 2 a ← 4 s̲elect₂ W t̲oBlocks ← { u → f̲ormat (f̲loat f̲loor 0.5 + 100.0 × (f̲loat u) ÷ f̲loat ᵉⁿfull) ÷ 100.0 } said ← p̲rint! "lake: top layer " c̲at (t̲oBlocks '+ r̲/ a × inlake × y = T) c̲at " of 25 blocks, the layer below " c̲at (t̲oBlocks '+ r̲/ a × inlake × y = T − 1) c̲at " of 25; all the moving water " c̲at t̲oBlocks ᵉⁿw̲aterUnits s s }
ᵘm̲easureIf : (Truthy a, Any b, Any c, Any d, Any e, Any f, Any g, Any h, Any i, Any j, Any k) => a -> ((b, (c, d, e, f, g, h, Int, i), j, k), l) -> (b, (c, d, e, f, g, h, Int, i), j, k)
ᵘm̲easureIf ← { yes sk → (s, k) ← sk yes ? k ᵘm̲easureAt s s }
ᵘm̲easureAt : (Any b, Any c, Any d, Any e, Any f, Any g, Any h, Any i, Any j, Any k) => a -> (b, (c, d, e, f, g, h, Int, i), j, k) -> (b, (c, d, e, f, g, h, Int, i), j, k)
ᵘm̲easureAt ← { k s → said ← p̲rint! "after " c̲at (f̲ormat k) c̲at " frames:" ᵘm̲easure s }
Playing
ᵘf̲rame : (Num a, Num b, Num c, Num d, Truthy d, Num e) => (((Float, Float, Float, Float, Float, Float), (Int, Int, Box Int, Box Int, Int, Int, Int, Int), (a, Int, Int, Int), (Int, Int, Float, b, c)), Int, d, e) -> (((Float, Float, Float, Float, Float, Float), (Int, Int, Box Int, Box Int, Int, Int, Int, Int), (a, Int, Int, Int), (Int, Int, Float, b, c)), Int, d, e)
The state is (the world and its player, the chosen block, whether the water was asleep, the frames so far); each time the water falls asleep after moving, the lake is measured.
ᵘf̲rame ← { (s, sel, was, k) → (s, sel) ← ᵖˡf̲rame (s, sel) now ← ᵉⁿa̲sleep s s ← (now × 1 − was) ᵘm̲easureIf (s, k + 1) (s, sel, now, k + 1) }
s : ((Float, Float, Float, Float, Float, Float), (Int, Int, Box Int, Box Int, Int, Int, Int, Int), (Int, Int, Int, Int), (Int, Int, Float, Int, Int))
s ← (3 × (1 + 2 × ᵉⁿreach) × 1 + 2 × ᵉⁿreach) 'ᵉⁿs̲tream p̲ower s
s : ((Float, Float, Float, Float, Float, Float), (Int, Int, Box Int, Box Int, Int, Int, Int, Int), (Int, Int, Int, Int), (Int, Int, Float, Int, Int))
s ← ᵘm̲easure s
last : (((Float, Float, Float, Float, Float, Float), (Int, Int, Box Int, Box Int, Int, Int, Int, Int), (Int, Int, Int, Int), (Int, Int, Float, Int, Int)), Int, Int, Int)
last ← 100000 'ᵘf̲rame p̲ower (s, 1, 1, 0)
ᵘw̲orldOf : (Any a, Any b, Any c, Any d) => (a, b, c, d) -> a
ᵘw̲orldOf ← { (s, _, _, _) → s }