# 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.