Specification · format 0xC7

The intent language.

Ninety bytes describe a world: what kind of matter it is made of, how that matter answers gravity, which parts of it like to touch, how coarse it settles, how long it settles for, what must be true of it and how far down. A receiver builds the world; the world never travels. This is the document a fourth receiver would be written from.

Why this exists

Three implementations, no specification.

There are three independent receivers of this format and until now the only description of it lived in comments across their three files. That is not something a fourth implementer can work from, and it is not something anyone can check a claim against.

Writing it down is also a test. Two words of this language were discovered by finding that a receiver was choosing something the sender thought it had said, how far down a mark reaches, and how long a stage settles for. Both were found by building a second receiver and by auditing what the first one still decided alone. Every rule below that is not a field in the message is here because leaving it unstated produced a measurable defect, and the measurement is quoted with it.

A receiver can be checked against thirteen reference worlds without installing anything. Two of them are multi-stage, so a receiver that gets the sequencing wrong fails exactly those; one pair is the same world written in two formats and must produce the identical fingerprint; another pair differs in exactly two bytes and must not. Run the vectors.

The message

Header, then one block a stage.

All integers are unsigned unless stated. Signed bytes are two's complement. There is no padding and no alignment: a message is exactly as long as its contents.

Header: 6 bytes

bytesizefieldmeaning
01version0xC7. A receiver that does not recognise the byte must refuse the message rather than guess at it.
1–44seedBig-endian. Selects which world of this kind. Two messages differing only here describe the same world and produce different ones.
51stage countAt least one. Stages are applied in order and the field carries forward.

Each stage: 21 bytes, then its objects

bytesizefieldmeaning
+06abundanceOne signed byte a material, value ÷ 64. How common each is before anything else acts on it.
+66gravity responseOne signed byte a material, ÷ 64. Positive rises, negative sinks. This is what stratifies a world; there is no heightmap.
+126affinityOne signed byte, ÷ 64, for each of the six pairs (1,2) (3,4) (4,5) (0,3) (0,1) (2,3). Which materials like to touch.
+181grain0.30 + b ÷ 255 × 1.9. The temperature the stage settles to. Above roughly 1.1 this model no longer equilibrates and the result is whatever the settling froze, legitimate, and the receiver should say so.
+191settling budgetEighths of a sweep per cell of width: sweeps = max(64, round(b × n ÷ 8)). Never raw sweeps, see the rule below.
+201object count0–255. The marks that must be true of this stage.

Each object: 6 bytes for a dot, 3 + 3n for a path of n bends

bytesizefieldmeaning
+01kind and radiusTop two bits: 0 = dot, 1 = path. Low six bits: radius ÷ 1024, as a fraction of the field's width, so a mark is between 1/1024 and 63/1024 of the world across, and there is no way to say anything larger. Kinds 2 and 3 are unassigned; a receiver must refuse a message using them rather than treat them as a dot.
+11material, and countA dot uses the low three bits for material. A path uses the top three bits for material and the low five for the number of bends, so a path has at most 31. Three bits hold 0–7 but only 0–5 exist; the reference receivers clamp 6 and 7 to 5, which is a decision worth stating because silently clamping and refusing are both defensible and they are not the same.
+21depthTwo bits of anchor, three of start, three of thickness. Start and thickness are in eighths of the block. Anchors: 0 the whole column, 1 under the surface of the matter, 2 up from the floor, 3 above the surface.
+33 eachpositionTwelve bits of x then twelve of y, each ÷ 4095, as fractions of the field. One pair for a dot; one per bend for a path.

A path of n bends costs 3 + 3n against 6n for the same shape as dots, so it is cheaper past one bend, but the reason to have it is that it is one object, which is what lets a sender say "a river runs from here to there" rather than "there is water here, and here, and here".

Positions and radii are fractions of the field, never cells, which is what lets the same message be realized at any size. Depth is in eighths of the block for the same reason.

On the wire the bytes are base64url with padding stripped, so a message travels as a link.

Rules that are not fields

What a conforming receiver must do.

These are stated once here rather than carried in every message. Each is followed by what happened when it was left unstated, because a rule whose reason is lost is a rule the next person deletes.

Clamps carry forward

A mark keeps holding after its own stage ends; a later mark at the same cell overrides it. Clearing clamps between stages measured 0.000% survival for every stage but the last, against a 10–21% control proving the marks had landed, so a sender could ask for an ore seam and receive a world without one.

Every stage's marks are checked

Not only the last stage's. They are all promises about the finished world once clamps carry. Check them against what was stamped at the time, not against a re-reading of the finished field: a surface-relative mark sits under terrain that no longer exists, and re-lifting it reported 98.3% for a build in which nothing had gone wrong.

The settling schedule is normative, not advisory

Ramp linearly from 0.30 to the stage's grain over the first three quarters of the budget, then hold. This was first written as the weaker rule "finish the ramp before the budget ends", on the reading that where the anneal starts and what shape it takes were the receiver's own business. Measured against a seed-to-seed noise floor of 0.17–0.51 points, that is wrong: at the flat receiver's own default every one of those choices moves the finished world's composition above the floor: the start by up to 0.74 points, the shape by up to 0.83, the ramp fraction by 1.32 to 1.67. They are smaller than the budget's 5.23 and they are not zero, so a receiver that picks its own schedule produces a measurably different world from one that follows this. Ramping across the whole budget remains the worst of them, because the field then never spends a sweep at the temperature it was asked for.

Noise once, at the beginning

The field is seeded from the message's seed before the first stage and never re-seeded. Later stages begin from what earlier ones left.

Say which regime you are in

A receiver that settles past the mixing window is handing over a frozen configuration, not a sample. It should report that rather than presenting the two as the same thing.

The sampler

Without this, none of the above is enough.

The message layout says what a world is. It does not say how to build one, and two receivers that agree on every byte will still build different worlds unless they agree on this too. That is not hypothetical: writing this section is what found it.

Three receivers implemented this format from each other's source rather than from a document, and two of them derived the second word of the random seed differently from the sender, one with the wrong constant, one with an ordinary multiply where an exact 32-bit one was needed. Both built worlds that held 100% of the constraints and looked entirely correct. They were simply different worlds, for 99.5% of seeds.

Site index

x + n·(y + n·z) in a solid, y·n + x in a plane. The random stream is keyed on this index, not on a thread id, so an implementation may reorder or compact its work however it likes and still produce the identical field.

Update order

Chromatic. A sweep is two passes: first every site whose coordinate sum is even, then every site whose sum is odd. Within a pass the sites are conditionally independent, so their order does not matter, which is what makes the field reproducible on a machine that runs them all at once.

Epoch numbering

A stage's sweeps are numbered from the sum of all preceding stages' sweep counts, so no two stages share a stream. The value fed to the generator is epoch × 2 + parity.

The two seed words

s0 is the message's seed. s1 is the exact 32-bit product of the seed and 0x9E3779B1, exact, not a floating-point multiply: the true product needs up to 64 bits, a double carries 53, and the low half is what the generator uses. In JavaScript that is Math.imul. Getting this wrong changes the world for 99.5% of seeds and for none of the small even ones, which is how it survived being tested.

The generator

h(x): x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16, all in 32-bit unsigned arithmetic. A site's draw is h(h(index ^ s0 ^ epoch × 0x9E3779B9) ^ s1), taken as its top 24 bits over 2²⁴.

The choice

Gibbs: each site takes a new material drawn from the distribution its six (or four) neighbours and the gravity term imply, at the stage's current temperature. A clamped site is skipped entirely, it is a boundary condition, not a variable. The conformance receiver does this in integers throughout, with a lookup table for the exponential, which is what lets the same fingerprints appear on a different implementation.

The sampler is specified this precisely because it has to survive a change of implementation, and it does: the reference vectors reproduce exactly under two independent compilers for the shader language, three code generators, and execution on both a graphics processor and an ordinary one. Two receivers realizing the same message at the same size must produce a bit-identical field. The two 64³ receivers here do, and that check exists because without a number to compare, two implementations can disagree for as long as nobody looks, both holding every constraint, both plausible.

Limits

Measured, not assumed.

Places where the language does not deliver what a careless reading of it would promise. Composition drift is the change in what fraction of the world each material occupies, in percentage points.

Resolution has a floor 0.35–0.98 pp

The same message realized at 256² and 1024² against 512², and at 96³ and 128³ against 64³, agrees on what the world is made of to about a point, the same world in more detail. At 32³ it does not: 3.27 points adrift, and flat across a sixteen-fold range of budgets, so it is the size and not the settling. The floor sits between 32 and 64.

The budget is part of the world, not of the machine up to 5.58 pp

It is in the message for a reason. At 512² and grain 1.62, realizing one message at 350 versus 1400 sweeps moves the composition by up to 5.58 points. Inside the mixing window it moves it by under a fifth of a point while moving 63% of the cells, which is the same message giving another draw of the same world.

Cell-by-cell difference is the wrong statistic 43–63% vs 10–27%

It is higher inside the window where the model equilibrates than outside it, because an equilibrated chain keeps drawing fresh independent samples while a frozen one stays near where it got to. Use composition to ask whether two realizations are the same world; it is also the only statistic that works across two different sizes.

The vocabulary is not in the bytes six materials

The message numbers materials 0–5 and says how each behaves. It does not say what they are called or what colour they are. Two receivers can agree on every byte, build identical worlds, and tell a reader they are standing on different things. Agree the vocabulary out of band, or expect that.

Edits are not in the language

What a player does to a world (mining, blasting) is not expressible here. The language describes worlds; a replay log describes a session, and conflating the two would make the message a program rather than a description. The playable receiver states this on screen rather than quietly rolling the edits into the byte count.

Earlier formats

An addition may extend the language.

It may not change what the words already there meant. A receiver should read these; the conformance vectors include messages in each.

0xC5No depth byte and no budget byte. Every mark means the whole column, and the settling budget is the literal 1400 sweeps those messages were written against.
0xC6Depth present, budget absent. Budget is again the literal 1400.
0xC7Current. Both present.

The check that this held: the same world written in 0xC5 and in 0xC6 lands on the identical fingerprint in a flat receiver, which has no depth axis and ignores the new byte. When the budget was added, all eleven existing vectors came back bit-identical.

The receivers

Three, none of which can write.

A receiver that can also encode is a receiver that can quietly agree with itself, so only the sender has an encoder.

The sender authors a message and realizes it flat, at 256² to 2048². The solid receiver realizes the same bytes as a 64³ block. The playable world realizes them as somewhere to stand, and reports what fraction of the sender's constraints survived into it. The measurement is where the rules above came from, and the vectors are how a fourth receiver would check itself.