Skip to content

The level audit ​

The geometric rules a level passes without anybody looking at a picture of it, and the repair a generation makes before it gives up. Every generated level is audited (apps/worker/src/audit.ts, before its preview and its cache), every bundled level is held to it with no repair (packages/catalogue/src/levels-audit.test.ts), and random specs are built and audited on every pull request and every night (apps/worker/src/fuzz.ts).

The rules ​

auditLevel(level, { factsOf, keep, rules }) runs them all (or those rules names) and answers one finding per fault: its rule, its severity, the placements it is about, where, a sentence naming the pieces, the point and its district, and what a repair would drop to clear it.

RuleWhat it findsAllowed
props-in-each-otherTwo props whose cores share a quarter of the smaller one's footprint and 15 cm of heightTwo barriers (fences, guardrails, bollards); two of nature (trees, bushes, rocks); a flat pad
prop-in-buildingA prop whose core shares a quarter of its footprint with a building's, the building's own faces over it and under itAt the building's anchors; in a building people walk into; on its roof
buildings-in-each-otherTwo buildings' cores sharing more than half a square metre
not-restingA piece floating (everything under its foot more than 12 cm below) or sunk (everything more than 25 cm above, a metre for nature); a boat off the waterWhat rests on the water is measured at its waterline
in-the-roadA piece more than 30 cm inside a carriageway, on the road's levelWhat is made for the road (a traffic cone)
z-fightingFaces of one piece, or of two, in one plane, facing the same way, in two coloursUndersides lying on the ground
paint-over-paintTwo patches of the level's paint over each other, whatever their colours
roads-joinedA road the players' spawn's road cannot reach (a warning)

A piece's core (cores.ts) is the box round its lowest metre, turned with it: boxes round whole pieces meet everywhere in a city (a tree's crown over a bench, a lamp's arm over a bin: 2,214 false pairs on main-riverbend), cores only where the pieces stand in each other.

Only the pieces of the shared kits are judged as pieces: factsOf (@foi/catalogue's pieceFacts, from the kit library) tells their tags, what they rest on (a kit sidecar's rests: water for the boats and buoys, road for the traffic cone), their anchors and whether people walk into them. A level's own meshes (its ground, its paint, its roads' carriers) and the unit blocks are no pieces to judge; without factsOf only the faces, the paint and the roads are.

The roads' lines are no rule: they give way to the level's paint as they are laid (../road-paint.ts), so no step of a line ever lies over a crossing, a stop line or a grate.

The repair ​

repairLevel(level, options) audits, drops what may be dropped, and audits again, three rounds at most (a dropped container leaves the one stacked on it floating). It never moves anything:

  • Dropped: a faulty prop of a shared kit (of two props in each other, the smaller), and the triangles of the level's own paint that lie under other paint.
  • Never dropped: buildings, structures, the ground, blocks, and what keep says (a generation keeps what stands on one of the level's named places). A fault there is the generator's: the build reports it, naming the piece and the point, and says that another seed usually clears it.

The z-fighting search (coplanar.ts) searches each distinct mesh once, in its own frame, and across pieces only the planes two pieces' faces share: 2.3 s and half a gigabyte on main-riverbend's 943,000 triangles, where searching every placed triangle took 5 s and 1.3 GB. The rest of the audit takes about a second there.