[data] the firewall + parity mite, and accents chosen against the real GLB textures
FIREWALL machine on SIM's catcher shape (input-free catch-mite -> parity-mite), gated behind broadcast-parity-firewall; parity-mite canned item; two commissions that want The Correction alive. All 19 GLB'd machines accented from their actual albedo textures (mosquito-trap corrected to UV-violet, decode-asic to ice-blue). Validator +2: firewall shape guard + a mite-catcher-exists check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
e20ce1341b
commit
5e3bbff636
@ -55,6 +55,10 @@
|
||||
"flavor": "One (1) GIBBS WRAITH, willingly.",
|
||||
"wants": { "gibbs-wraith": 1 }, "rewardBandwidth": 900 },
|
||||
|
||||
{ "id": "correction-specimen",
|
||||
"flavor": "ONE (1) UNIT OF THE CORRECTION, ALIVE. Shell intact, checkmark lit, proboscis zip-tied. INVOICE ATTACHED. DO NOT READ THE INVOICE. We have been trying to get one to hold still since before the Reel Beds cooled, and you did it in an afternoon, with a forged seal and a drawer that only opens one way. We are not asking how. We are asking for another.",
|
||||
"wants": { "parity-mite": 1 }, "rewardBandwidth": 1000 },
|
||||
|
||||
{ "id": "feather-proof",
|
||||
"flavor": "3 GHOST FEATHERS. Gradient intact, tip genuinely transparent, no hard edge anywhere on the object. We have been sold nine hard mattes by nine suppliers who each insisted it was the same thing. It is not the same thing. Do not send a matte.",
|
||||
"wants": { "ghost-feather": 3 }, "rewardBandwidth": 1100 },
|
||||
@ -67,6 +71,10 @@
|
||||
"flavor": "One (1) beam of SODIUM LIGHT, 589nm, in its prism. We are aware who holds the prisms. We are aware what they call it when you take one. We are prepared to call it something else. 30 BLUE HOLES accepted as consolation if you lose your nerve.",
|
||||
"wants": { "sodium-light": 1, "blue-hole": 30 }, "rewardBandwidth": 1800 },
|
||||
|
||||
{ "id": "annual-correction-cull",
|
||||
"flavor": "STANDING ORDER: 5 PARITY MITES per collection, live, and 20 MELT alongside to prove they were mid-repair when you took them. The Correction files each absent technician as a clerical rounding error and dispatches five more to look into it. We would like you to keep having this problem — professionally, on retainer, forever.",
|
||||
"wants": { "parity-mite": 5, "melt": 20 }, "rewardBandwidth": 2100, "repeat": true },
|
||||
|
||||
{ "id": "sky-blue-mislabeled",
|
||||
"flavor": "600 MACROBLOCK BRICKS, sky-blue, MISLABELED REC2020. Purpose: none of your business.",
|
||||
"wants": { "macroblock-bricks": 600, "gamut-paint-rec2020": 6 }, "rewardBandwidth": 2400 },
|
||||
|
||||
@ -49,6 +49,7 @@
|
||||
|
||||
{ "id": "mosquito-swarm", "name": "MOSQUITO SWARM (LIVE)", "codex": "5:mosquito-swarms", "tier": 2, "color": "#d0ffb0" },
|
||||
{ "id": "gibbs-wraith", "name": "GIBBS WRAITH", "codex": "5:gibbs-wraiths", "tier": 2, "color": "#bfe0ff" },
|
||||
{ "id": "parity-mite", "name": "PARITY MITE (LIVE)", "codex": "5:parity-mites", "tier": 2, "color": "#dff5e6" },
|
||||
|
||||
{ "id": "alpha", "name": "ALPHA", "codex": "10:alpha", "tier": 1, "color": "#b8e8f0" },
|
||||
{ "id": "hard-matte", "name": "HARD MATTE", "codex": "10:hard-matte", "tier": 1, "color": "#e8e8e8" },
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{ "id": "seam-extractor", "name": "SEAM EXTRACTOR", "codex": "4:seam-extractor", "kind": "extractor",
|
||||
"footprint": { "x": 2, "y": 2 },
|
||||
"recipes": ["extract-mdat", "extract-bayer-grit", "extract-field-splinters", "extract-silver-frames"],
|
||||
"powerDraw": 2, "asset": "seam-extractor", "color": "#8a7a32",
|
||||
"powerDraw": 2, "asset": "seam-extractor", "color": "#8a7a32", "accent": "#48d6ff",
|
||||
"flavor": "The miner. Chews mdat seams and spits raw payload. The drill head is CRT-certified. Operators are not." },
|
||||
|
||||
{ "id": "belt", "name": "STREAM BELT", "codex": "4:belts", "kind": "belt",
|
||||
@ -20,50 +20,50 @@
|
||||
|
||||
{ "id": "demuxer", "name": "DEMUXER", "codex": "4:demuxer", "kind": "crafter",
|
||||
"footprint": { "x": 2, "y": 2 }, "recipes": ["demux-ore", "demux-container"], "powerDraw": 3,
|
||||
"asset": "demuxer", "color": "#4e5a62",
|
||||
"asset": "demuxer", "color": "#4e5a62", "accent": "#ff3fd4",
|
||||
"flavor": "The first splitter. Cleaves raw ore into brightness, colour, and pure directional intent." },
|
||||
{ "id": "demosaicer", "name": "DEMOSAICER", "codex": "4:demosaicer", "kind": "crafter",
|
||||
"footprint": { "x": 3, "y": 2 }, "recipes": ["demosaic-rggb", "demosaic-vng4", "demosaic-stripes"],
|
||||
"powerDraw": 5, "asset": "demosaicer", "color": "#6a5f52",
|
||||
"powerDraw": 5, "asset": "demosaicer", "color": "#6a5f52", "accent": "#4fffc4",
|
||||
"flavor": "Weaves checkerboard grit into full colour. Feed it stripes and it will jam and extrude MOIRÉ — as designed, as warned, as invoiced." },
|
||||
{ "id": "dct-press", "name": "DCT PRESS", "codex": "4:dct-press", "kind": "crafter",
|
||||
"footprint": { "x": 3, "y": 3 }, "recipes": ["press-color-plate", "press-anchor-slab"],
|
||||
"powerDraw": 8, "asset": "dct-press", "color": "#3f4348",
|
||||
"powerDraw": 8, "asset": "dct-press", "color": "#3f4348", "accent": "#3fffe0",
|
||||
"flavor": "Spatial into frequency. Slams pixel blocks into coefficient decks; run it backwards and an entire picture falls out of the slot." },
|
||||
{ "id": "quantizer", "name": "QUANTIZER", "codex": "4:quantizer", "kind": "crafter",
|
||||
"footprint": { "x": 2, "y": 2 }, "recipes": ["quantize", "quantize-crime", "skim-ringing"],
|
||||
"powerDraw": 4, "asset": "quantizer", "color": "#5e5148",
|
||||
"powerDraw": 4, "asset": "quantizer", "color": "#5e5148", "accent": "#ff3b57",
|
||||
"flavor": "The crusher, the moneymaker, the sin. Every bit it destroys becomes room to move. The dial goes to CRIME." },
|
||||
{ "id": "subsampler", "name": "SUBSAMPLER", "codex": "4:subsampler", "kind": "crafter",
|
||||
"footprint": { "x": 2, "y": 3 }, "recipes": ["subsample-422", "subsample-420", "pan-speckle"],
|
||||
"powerDraw": 4, "asset": "subsampler", "color": "#4a5560",
|
||||
"powerDraw": 4, "asset": "subsampler", "color": "#4a5560", "accent": "#e04fc8",
|
||||
"flavor": "Spins colour down to grade and vents the difference as bandwidth. Leaks by design. Place downwind of anything you are fond of." },
|
||||
{ "id": "mv-extractor", "name": "MV EXTRACTOR", "codex": "4:mv-extractor-and-p-caster", "kind": "crafter",
|
||||
"footprint": { "x": 2, "y": 2 }, "recipes": ["extract-motion"], "powerDraw": 5,
|
||||
"asset": "mv-extractor", "color": "#454b52",
|
||||
"asset": "mv-extractor", "color": "#454b52", "accent": "#3fd8ff",
|
||||
"flavor": "Watches the footage until it knows where the picture wants to go, then pipes the wanting off as fluid." },
|
||||
{ "id": "p-caster", "name": "P-CASTER", "codex": "4:mv-extractor-and-p-caster", "kind": "crafter",
|
||||
"footprint": { "x": 2, "y": 2 }, "recipes": ["cast-delta-wafer", "cast-janus-wafer"],
|
||||
"powerDraw": 4, "asset": "p-caster", "color": "#4d545c",
|
||||
"powerDraw": 4, "asset": "p-caster", "color": "#4d545c", "accent": "#6fa8ff",
|
||||
"flavor": "Prints instructions, not pictures. Each one is applied to whatever came before it — correct or otherwise." },
|
||||
{ "id": "gop-assembler", "name": "GOP ASSEMBLER", "codex": "4:gop-assembler", "kind": "crafter",
|
||||
"footprint": { "x": 3, "y": 2 },
|
||||
"recipes": ["assemble-gop", "assemble-gop-ibbp", "assemble-gop-i-only", "spool-offset-ribbon",
|
||||
"tally-stsz-ledger"],
|
||||
"powerDraw": 6, "asset": "gop-assembler", "color": "#7a6a44",
|
||||
"powerDraw": 6, "asset": "gop-assembler", "color": "#7a6a44", "accent": "#5fb0ff",
|
||||
"flavor": "One anchor, N wafers, one crate, per the cadence punch-card. Opening a sealed crate is a production verb here, not a crime." },
|
||||
{ "id": "mosh-reactor", "name": "MOSH REACTOR", "codex": "4:mosh-reactor", "kind": "crafter",
|
||||
"footprint": { "x": 3, "y": 3 }, "recipes": ["mosh"], "powerDraw": 8,
|
||||
"asset": "mosh-reactor", "color": "#52333e",
|
||||
"asset": "mosh-reactor", "color": "#52333e", "accent": "#ff7a3f",
|
||||
"flavor": "A decoder sealed in a vessel and starved of anchors. The I-frame leaves through the side airlock. The hallucination leaves through the front." },
|
||||
{ "id": "bloom-duplicator", "name": "P-FRAME DUPLICATOR", "codex": "4:bloom-loop", "kind": "crafter",
|
||||
"footprint": { "x": 1, "y": 1 },
|
||||
"recipes": ["tap-bloom", "bloom-grade-1", "bloom-grade-2", "bloom-grade-3", "bloom-grade-4", "bloom-grade-5"],
|
||||
"powerDraw": 6, "asset": "bloom-duplicator", "color": "#5a5060",
|
||||
"powerDraw": 6, "asset": "bloom-duplicator", "color": "#5a5060", "accent": "#ff9440",
|
||||
"flavor": "Stamps the same displacement onto the same cargo every lap. Grade 5 is visibly trying to leave its canister in one direction." },
|
||||
{ "id": "field-loom", "name": "FIELD LOOM", "codex": "4:field-loom", "kind": "crafter",
|
||||
"footprint": { "x": 3, "y": 2 }, "recipes": ["weave-fields", "loom-vhold-roll"],
|
||||
"powerDraw": 5, "asset": "field-loom", "color": "#3f5a44",
|
||||
"powerDraw": 5, "asset": "field-loom", "color": "#3f5a44", "accent": "#6ef58a",
|
||||
"flavor": "Weaves and unweaves time. The two halves of a splinter were captured a moment apart and have never agreed since." },
|
||||
{ "id": "telecine-puller", "name": "TELECINE PULLER", "codex": "4:telecine-puller", "kind": "crafter",
|
||||
"footprint": { "x": 2, "y": 2 }, "recipes": ["mill-judder", "wind-stts-metronome"], "powerDraw": 4,
|
||||
@ -76,20 +76,24 @@
|
||||
"flavor": "Nudges the offsets a few bytes so the decoder fetches garbage. Keep its buffer fed, or it splices itself." },
|
||||
{ "id": "mosquito-trap", "name": "MOSQUITO TRAP", "codex": "5:mosquito-swarms", "kind": "crafter",
|
||||
"footprint": { "x": 2, "y": 2 }, "recipes": ["bait-swarm"], "powerDraw": 3,
|
||||
"asset": "mosquito-trap", "color": "#2a2e24", "accent": "#d0ff60",
|
||||
"asset": "mosquito-trap", "color": "#2a2e24", "accent": "#a64fff",
|
||||
"flavor": "A bug-zapper shaped like a high-contrast edge — the one thing a mosquito swarm cannot resist. Bait it with fresh luma, collect what it catches, sell the catch to people who should know better." },
|
||||
{ "id": "firewall", "name": "FIREWALL", "codex": "5:parity-mites", "kind": "crafter",
|
||||
"footprint": { "x": 2, "y": 2 }, "recipes": ["catch-mite"], "powerDraw": 4,
|
||||
"asset": "firewall", "color": "#31383f", "accent": "#3fff7f",
|
||||
"flavor": "A drawer that opens only inward, painted with a compliance seal the Bitstream never issued. A parity mite cannot leave a deviation uncorrected, and a forged checkmark IS a deviation — so it climbs in to fix the seal, and the drawer disagrees. Ships live, to buyers who never ask how it is still, faintly, trying." },
|
||||
|
||||
{ "id": "artifact-bottler", "name": "ARTIFACT BOTTLER", "codex": "2:science-packs", "kind": "crafter",
|
||||
"footprint": { "x": 2, "y": 2 },
|
||||
"recipes": ["can-static", "mix-rec709", "mix-dci-p3", "mix-rec2020",
|
||||
"cut-sync-key", "bottle-container-pack", "forge-stss-keyring", "cut-ftyp-seal",
|
||||
"bottle-analog-pack", "bottle-spatial-pack", "bottle-temporal-pack"],
|
||||
"powerDraw": 4, "asset": "artifact-bottler", "color": "#566056",
|
||||
"powerDraw": 4, "asset": "artifact-bottler", "color": "#566056", "accent": "#7fe0d8",
|
||||
"flavor": "Bottles the triptych. Contents are shelf-stable in the legal sense, i.e. no law has been written that mentions them." },
|
||||
|
||||
{ "id": "decode-asic", "name": "DECODE ASIC", "codex": "4:decode-asic", "kind": "power",
|
||||
"footprint": { "x": 2, "y": 2 }, "recipes": [], "powerDraw": 0, "powerGen": 20,
|
||||
"asset": "decode-asic", "color": "#b9bec4", "accent": "#6fe8c0",
|
||||
"asset": "decode-asic", "color": "#b9bec4", "accent": "#8fe8ff",
|
||||
"flavor": "Cool, efficient, inflexible. Handles standard profiles and declines to imagine anything else. It will outlive you." },
|
||||
{ "id": "software-decoder", "name": "SOFTWARE DECODER", "codex": "4:software-decoder", "kind": "power",
|
||||
"footprint": { "x": 2, "y": 2 }, "recipes": [], "powerDraw": 0, "powerGen": 100,
|
||||
@ -113,7 +117,7 @@
|
||||
{ "id": "chroma-keyer", "name": "CHROMA KEYER", "codex": "10:chroma-keyer", "kind": "crafter",
|
||||
"footprint": { "x": 2, "y": 2 },
|
||||
"recipes": ["key-chroma", "key-hair", "key-semitransparent"], "powerDraw": 6,
|
||||
"asset": "chroma-keyer", "color": "#3a6a3a",
|
||||
"asset": "chroma-keyer", "color": "#3a6a3a", "accent": "#4fff30",
|
||||
"flavor": "Cheap, fast, and thirty-year-old maths. Weeps GREEN SPILL from its seams. Chokes on hair. Do not show it anything semi-transparent; it will decide the pixel belongs to neither of you." },
|
||||
{ "id": "roto-bench", "name": "ROTO BENCH", "codex": "10:roto-bench", "kind": "crafter",
|
||||
"footprint": { "x": 2, "y": 2 }, "recipes": ["roto-cutout", "roto-mixed"], "powerDraw": 2,
|
||||
@ -131,7 +135,7 @@
|
||||
|
||||
{ "id": "muxer", "name": "THE MUXER", "codex": "7:the-muxer", "kind": "crafter",
|
||||
"footprint": { "x": 5, "y": 5 }, "recipes": ["assemble-moov-brain", "mux-container"], "powerDraw": 40,
|
||||
"asset": "muxer", "color": "#6a7078",
|
||||
"asset": "muxer", "color": "#6a7078", "accent": "#ff3fd0",
|
||||
"flavor": "The rocket. A launch gantry embracing a container built of nested boxes, innermost a brain of index tape-reels. It ships the whole file at once, and the file is your entire shipping history, and there is no second launch." },
|
||||
|
||||
{ "id": "shipper", "name": "SCREEN UPLINK", "codex": "7:the-muxer", "kind": "shipper",
|
||||
|
||||
@ -88,6 +88,9 @@
|
||||
{ "id": "bait-swarm", "machine": "mosquito-trap", "inputs": {},
|
||||
"outputs": { "mosquito-swarm": 1 }, "ticks": 90, "bandwidth": 3 },
|
||||
|
||||
{ "id": "catch-mite", "machine": "firewall", "inputs": {},
|
||||
"outputs": { "parity-mite": 1 }, "ticks": 120, "bandwidth": 4 },
|
||||
|
||||
{ "id": "can-static", "machine": "artifact-bottler", "inputs": { "hf-dust": 4 },
|
||||
"outputs": { "static-canister": 1 }, "ticks": 30, "bandwidth": 3 },
|
||||
{ "id": "cut-sync-key", "machine": "artifact-bottler", "inputs": { "anchor-slab": 1, "moov-shard": 1 },
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
"unlocks": ["asic-cooler"] },
|
||||
{ "id": "broadcast-mosquito-farming", "era": "broadcast", "cost": { "analog-pack": 15, "spatial-pack": 10 },
|
||||
"unlocks": ["mosquito-trap", "bait-swarm"] },
|
||||
{ "id": "broadcast-parity-firewall", "era": "broadcast", "cost": { "spatial-pack": 15, "analog-pack": 10 },
|
||||
"unlocks": ["firewall", "catch-mite"] },
|
||||
|
||||
{ "id": "reel-silver-seams", "era": "reel", "cost": { "spatial-pack": 8 },
|
||||
"unlocks": ["extract-silver-frames"] },
|
||||
|
||||
@ -349,7 +349,9 @@ describe('recipes', () => {
|
||||
// is wildlife in the snapshot and never an item on a belt. LANE-SIM identifies a
|
||||
// trap by exactly this shape — an empty-input recipe yielding the swarm item — so
|
||||
// giving `bait-swarm` ingredients would quietly stop it being a trap at all.
|
||||
const CATCHES_WILDLIFE = new Set(['bait-swarm']);
|
||||
// Round 6: the FIREWALL joins the trap. It cans a live PARITY MITE the same way —
|
||||
// an input-free recipe whose "input" is a creature in the world, not cargo on a belt.
|
||||
const CATCHES_WILDLIFE = new Set(['bait-swarm', 'catch-mite']);
|
||||
const bad = recipes.filter((r) => Object.keys(r.inputs).length === 0)
|
||||
.filter((r) => !CATCHES_WILDLIFE.has(r.id))
|
||||
.filter((r) => machines.find((m) => m.id === r.machine)?.kind !== 'extractor')
|
||||
@ -366,6 +368,25 @@ describe('recipes', () => {
|
||||
expect(trap.outputs['mosquito-swarm']).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('the firewall keeps the shape LANE-SIM detects wildlife-catchers by', () => {
|
||||
// Round 6, coordinated with SIM: a firewall is spotted by recipe shape exactly like a
|
||||
// trap — empty inputs, output is the canned creature (here the parity mite). Ingredients
|
||||
// would silently demote it to an ordinary crafter that mints The Correction from nothing.
|
||||
const fw = recipes.find((r) => r.id === 'catch-mite')!;
|
||||
expect(Object.keys(fw.inputs)).toEqual([]);
|
||||
expect(fw.outputs['parity-mite']).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('something can catch the parity mite the fax orders alive', () => {
|
||||
// correction-specimen wants ONE UNIT OF THE CORRECTION, ALIVE. If nothing cans a mite,
|
||||
// the fax opens an order it can never fill and never celebrates its first catch.
|
||||
const catcher = recipes.find(
|
||||
(r) => (r.outputs['parity-mite'] ?? 0) > 0 && Object.keys(r.inputs).length === 0);
|
||||
expect(catcher, 'no input-free recipe cans a parity mite').toBeTruthy();
|
||||
const wanters = commissions.filter((c) => (c.wants['parity-mite'] ?? 0) > 0).map((c) => c.id);
|
||||
expect(wanters.length, 'no commission wants a canned mite').toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('every heat value is a 0..1 fraction per craft', () => {
|
||||
const bad = recipes.filter((r) => r.heat !== undefined && !(r.heat >= 0 && r.heat <= 1))
|
||||
.map((r) => `${r.id} -> heat ${r.heat}`);
|
||||
@ -707,12 +728,18 @@ describe('stations', () => {
|
||||
expect(malformed).toEqual([]);
|
||||
expect(duplicates(groups)).toEqual([]);
|
||||
|
||||
// A decoy that happens to decode onto a real hidden seam isn't a decoy, it's a leak.
|
||||
const hiddenTiles = new Set(seams.filter((s) => s.hidden).map((s) => `${s.rect.x},${s.rect.y}`));
|
||||
// A decoy that decodes onto ANY seam — hidden OR visible — isn't a decoy, it's a leak:
|
||||
// it hands the player a real dig site the station never meant to give away. Round 6:
|
||||
// the old check only guarded the three hidden 1x1 tiles, and two decoys (08127, 27503)
|
||||
// were quietly sitting on reel-beds-deep and broadcast-shelf-south. Now every decoy is
|
||||
// decoded to a tile and checked against every seam rect, and the leak is named.
|
||||
const point = (x: number, y: number): SeamRect => ({ x, y, w: 1, h: 1 });
|
||||
const leaks = (n.decoyPool as string[])
|
||||
.map((g) => ({ g, x: Number(g.slice(0, 2)) - 32, y: Number(g.slice(2, 4)) - 32 }))
|
||||
.filter(({ x, y }) => hiddenTiles.has(`${x},${y}`))
|
||||
.map(({ g, x, y }) => `decoy ${g} decodes to the real seam at (${x},${y})`);
|
||||
.flatMap(({ g, x, y }) =>
|
||||
seams
|
||||
.filter((s) => rectsOverlap(point(x, y), s.rect))
|
||||
.map((s) => `decoy ${g} decodes to (${x},${y}), inside real seam ${s.id}`));
|
||||
expect(leaks).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user