# MOLECULES — a proposal (Lane A, round 2)

**Status: PROTOTYPE + argument.** Nothing here is wired into boot. Pickups are Lane B's
systems, their economy is Lane C's, object art is Lane D's — this document is a pitch to all
three, plus a working renderer they can take or leave.

Fly it: `web/dev/laneA_molecules.html` · code: `web/js/world/molecule.js` ·
evidence: `docs/shots/laneA/round2_molecule_pickups.png` (the set + roles),
`round2_molecule_materials.png` (flat vs matcap vs space-filling, in the real canal),
`round2_molecules_in_canal.png`, `round2_molecules_truescale.png`

---

## The pitch in one line

**The pickups already in L2 are molecules — so draw them as molecules.**

C authored `nutrient`, `mucin`, `B12`, `antacid ammo` before any of this existed. Those aren't
game-flavoured names; they're the actual biochemistry of a digestive tract. Glucose, cobalamin
and bicarbonate are *real compounds with known shapes*. We don't have to invent a pickup
language — we have to stop hiding the one the fiction already handed us.

## Why this is free sciency-ness, and why it isn't educational

The game does not explain anything and should not start. Nobody needs to know what ATP is.
But a purine reads as *chemistry* to anyone alive, the way a circuit diagram reads as
*electronics* — because it is the real notation, not an impression of one. **The game gets to
feel sciency by not faking it**, which is cheaper than faking it and better.

Consider what's already true: an **eosinophil** is a real white blood cell. **Candida** is a
real yeast. A **bolus** is a real mass of chewed food. The **hiatus** is a real anatomical
choke point. **GUTS is already a science game** — C built it that way. It just doesn't *look*
like one yet, because everything on screen is tinted tissue.

## The one rule that makes it all work: CPK is the scanner

**Everything the ship's scanner has identified is drawn in CPK colours. Everything it hasn't
is monochrome tinted tissue.**

CPK is the standard element palette — oxygen red, nitrogen blue, phosphorus orange, sulfur
yellow, metals pink. Every chemistry textbook and protein viewer on earth uses it. Against six
biomes of tinted tissue, **a CPK molecule is the only saturated foreign colour on screen**, so
it reads as artificial, valuable and targetable at a glance — *with no HUD marker*
(`round2_molecules_in_canal.png` is the proof: a glucose in the esophagus, unmissable).

That's ART_BIBLE's synthetic-scanner fiction paying rent: the ship identifies a compound and
colours it in. → **Lane E**: this is a free HUD language. Accent a readout in an element's CPK
colour and it belongs to that compound with no legend.

## The division of labour: procedural geometry, generated materials

**MODELBEAST makes the materials. Procedural makes the shapes.** Both halves matter and they
are not in competition — the first version of this doc framed it as "don't use the GPU", which
was the wrong axis and is corrected below.

**Geometry is not a generation problem, because a molecule's shape is already known exactly.**
Glucose is a hexagonal ring because it is a hexagonal ring. FLUX + TRELLIS would give a
plausible blob, in 3–8 minutes, that a chemist clocks as wrong instantly and that can never be
re-derived. Ball-and-stick from an atom list is exact, rebuilds in milliseconds, and is **one
draw call per molecule** (measured: 7 molecules = 7 draws, 26.5k tris total; glucose alone is
3.7k tris / 1 draw).

**Material is exactly a generation problem**, and it's what separates a diagram from an object
— see the next section.

### What MODELBEAST *did* do: the materials (round 2, second pass)

Geometry is exact and free. **Material is where the GPU earns its keep** — and it's the whole
difference between a textbook diagram and a game object. GUTS has no real-time lights by law,
so a **matcap** (a lit-sphere image) is the only way to make something look *made of* anything.

Five greyscale matcaps, flux_local, **69 seconds, $0.00, 68 KB total**:

| matcap | elements | what it does |
|---|---|---|
| `mol_glass` | O, N | **the big win.** Oxygen becomes a deep red glass marble with internal glow. |
| `mol_matte` | C | graphite soot. Carbon is scaffold, and now it reads as scaffold. |
| `mol_chrome` | Co, Fe, Na | polished metal — B₁₂'s cobalt is a chrome bearing in a cage. |
| `mol_molten` | P | ATP's phosphate tail is incandescent, and **pulses** (`uTime`, free). |
| `mol_pearl` | H | soft satin white; hydrogens stop shouting. |

**The trick that makes it cheap is Lane D's own law, applied to spheres**: author the
*luminance*, tint in-shader. `derive_maps` greyscales every matcap already, so one glass ball
serves oxygen *and* nitrogen at their own CPK hues. Five balls dress the whole periodic table
we care about, and they pack into one strip atlas indexed per-vertex by `aMat` — so **a
molecule is still exactly one draw call** no matter how many materials its atoms are made of.
`?matcap=0` falls back to the built-in fake-lit path: the assets-optional law holds.

Two things that only showed up by rendering it, both fixed:
- **Tint × luminance darkens twice.** CPK carbon is already 0.4 and a matte ball averages 0.5,
  so soot × soot vanished — the first pass sank glucose, caffeine and the cobalt into the
  background. Floored the matcap at 0.22, the same floor the fallback's key light has always
  had.
- **The molten matcap was my own bad prompt**: I asked for an "incandescent white hot *core*"
  and got exactly that — a black ball with a hot spot, so the phosphorus lost its orange
  entirely. Re-rolled asking for the *whole sphere* to glow. Lesson for the kit, next to the
  organ/tissue one: **a matcap is a luminance lookup, so a dark-dominant ball makes a
  dark-dominant object.** Ask for bright, always.

### What the canal decided: space-filling wins for pickups

`buildMolecule(id, {repr})` now does `'ball-stick'` (default) or `'space-filling'` — every atom
at its real van der Waals radius, no sticks, atoms merging into one solid lump. A/B'd at real
pickup size against the real L2 wall, same camera (`round2_molecule_materials.png`):

**Ball-and-stick goes spindly and starts dissolving. Space-filling holds its silhouette — and
it is CHEAPER** (21k vs 26k tris across the set: no bond cylinders). It's also more true, since
that *is* how a molecule occupies space.

→ **Recommendation to B**: `space-filling` for anything in flight, `ball-stick` for hero, UI,
the medal card and the collect close-up — where the chemistry is legible and worth reading.
The obvious LOD (blob far, sticks near) is untested and I'm not claiming it.

**The split, and it's a principle, not a preference:**

| kind | how | why |
|---|---|---|
| **Small molecules** — glucose, ATP, caffeine, bicarbonate, capsaicin, B12, ions | **procedural ball-and-stick** | exact geometry is known; generation can only degrade it |
| **Proteins / enzymes** — pepsin, trypsin, lipase, mucin | **MODELBEAST** (flux → sf3d → trellis) | real ones are 3000-atom blobs; nobody reads their structure. A blob is the honest render, and PIPELINE says blobby organics are TRELLIS's sweet spot |
| **Cells / creatures** — eosinophil, candida, bolus, ENDO-1 | **MODELBEAST** (Lane D's round-2 headline, gated on concept sign-off) | organic, no canonical geometry, exactly what it's for |

So MODELBEAST still does the heavy lifting — on the things where invention is the right answer.

## The library (built, rendering, in the sheet)

Every one of these is really in the human gut. That constraint does the design work: the pickup
table *is* the biochemistry of digestion, so nothing has to be invented and the fiction is
automatic.

| molecule | proposed role | why it's the right object |
|---|---|---|
| **Glucose** `C₆H₁₂O₆` | nutrient / score | Food. The reason the canal exists. Common, stacks. |
| **ATP** `C₁₀H₁₆N₅O₁₃P₃` | **boost** | Literally the cell's energy currency. The orange triphosphate tail *is* the charge — a body spends ATP by snapping one off. A boost pickup that visibly carries three charges is a diagram of its own mechanic. |
| **Bicarbonate** `HCO₃⁻` | **antacid ammo** | Already in L2. `HCO₃⁻ + HCl → salt + H₂O + CO₂` is the real reaction that neutralises stomach acid — fire it into the acid sea and it genuinely fizzes. |
| **Caffeine** `C₈H₁₀N₄O₂` | **overdrive** | Really absorbed through the gut wall. Everyone knows what it does to a body: throttle up, twitchier, wears off badly. Needs no tutorial. |
| **Capsaicin** `C₁₈H₂₇NO₃` | **burn hazard** | Chilli. Long greasy tail + aromatic ring = a silhouette that reads *wrong* across a room, and it tumbles unlike any compact pickup. Free readability. |
| **Vitamin B₁₂** `C₆₃H₈₈CoN₁₄O₁₄P` | **rare treasure** | C already authored B12 as a pickup. It's the most complex vitamin and the *only one with a metal at its heart* — a cobalt in a corrin cage. It renders as a jewel in a setting. |
| **Water** `H₂O` | trickle / chaff | Everywhere, worth a sliver. The size floor. |

**Size is a free rarity signal.** `buildMolecule(id, {unit})` keeps molecules at their TRUE
relative sizes: water is a speck, B12 is a chandelier (`round2_molecules_truescale.png`). The
player learns what's worth chasing before reading a single colour, and it costs nothing because
it's just true. (`{fit}` normalises them all to one size instead, if a pickup must occupy a
fixed box — B's call.)

## Cheap next molecules, if this lands

- **Ions as basic ammo/energy**: Na⁺, K⁺, Cl⁻, Ca²⁺ — single coloured spheres, ~30 tris, and
  they're the real electrolytes. Violet, green, purple: instant colour-coded ammo types.
- **Ethanol** `C₂H₅OH` — a *powerdown*. Controls drift, aim lags. Funny, real, gut-absorbed.
- **Vitamin C** `C₆H₈O₆` — coat repair (it's the antioxidant). Pairs with B12 as a vitamin tier.
- **Mucin** — the coat itself, and it's already a pickup. It's a glycoprotein → MODELBEAST blob,
  not ball-and-stick. Good first test of the split above.
- **HCl** — the acid sea's own molecule. One green Cl, one white H. The sea could *shed* them.

## Other ways to be sciency that cost ~nothing

1. **Show the real pH.** L3's identity is "ambient pH drains the coat". Stomach pH really is
   ~1.5–3.5. A HUD readout ticking `pH 1.8` as you descend is instantly sciency, is true, and
   is one number. → Lane E / C.
2. **Name the real reaction when it fires.** Antacid hit → `HCO₃⁻ + HCl → NaCl + H₂O + CO₂↑`
   flashed for half a second in the feed. Never explained. Reads as an instrument log.
3. **Let CO₂ be the fizz.** The bicarbonate reaction really produces gas. Bubbles from a
   neutralised acid patch are the reaction being visible, not a particle effect.
4. **The enemies are already real** — lean in. `eosinophil_swarm` is a real immune response to
   an invader. The player IS the invader. That's the whole game's joke and it's science.

## What I'd need from each lane

- **→ C**: are these the roles you want? The economy is yours. If `nutrient` should be glucose
  and `antacid` bicarbonate, they're built. Tell me which molecules a level needs.
- **→ B**: `buildMolecule(id, {fit|unit, detail, material})` returns one `THREE.Mesh`, one draw,
  `.userData` carries name/formula/role. Share ONE material across all of them (colour is
  per-vertex, so they still batch). Use `detail: 1` for live pickups, `2` for hero/close.
- **→ D**: this doesn't touch your pack and doesn't want your GPU time. It *asks* for the split
  above — proteins and cells are yours, small molecules are arithmetic. Your round-2 hero list
  is unaffected.
- **→ E**: CPK as the scanner's identification language is a free HUD palette. `ELEMENTS` in
  `molecule.js` exports the hexes.
- **→ F**: `world/molecule.js` sits in my dir because it's my dir, not because molecules are
  "world". If this is adopted it probably wants a shared `web/js/fx/` — your call.

## Honest limitations

- **Geometry is idealised, not crystallographic**: correct connectivity, ring sizes and bond
  orders, believable angles, authored mostly flat because a flat ring reads instantly and spins
  well. Real molecules pucker (glucose is a chair, not a hexagon). This is a game, not PyMOL —
  but nobody should mistake this table for a structure database later.
- **The B12 is a simplified corrin core** — the real thing has a nucleotide tail and far more
  side chains. It reads as "jewel in a cage", which is the job.
- **Not performance-tested at pickup density.** 7 on screen is 7 draws / 26k tris (13 draws /
  87k with the canal behind them). Fifty would want instancing or a merged batch, and neither
  exists yet.
- **The matcap atlas is built at runtime from a canvas.** Fine, but it means a one-frame hitch
  on first build and it bypasses `assets.matcap()` (it reads `assets.get('matcaps', …).url` —
  the documented floor — and loads the images itself, because an atlas needs pixels and
  `matcap()` hands back a `THREE.Texture` that may not have decoded yet). If this is adopted,
  baking the atlas offline in `derive_maps.py` would be tidier and D may prefer it.
- **`repr: 'space-filling'` hides the bonds by definition**, so a molecule's *chemistry* stops
  being readable — that's the trade for silhouette, and it's why ball-stick stays the default
  for anything the player is meant to look AT rather than fly at.
