GDD v1 (flow-locked hybrid movement, 5 biomes + secret, boss roster), TECH contracts (world API, level schema v0, bus events, manifest law), ART_BIBLE (synthetic scanner look), PIPELINE (MODELBEAST-first, fal gated), PROCESS (PROCITY lane/round law), charters A-F + ROUND1 instructions. Seed code: shell + boot + core (rng/bus/flags) + stub world (peristalsis shader tube, 1 draw / 102k tris, contract-complete) + qa.sh (GREEN). Verified in-browser; evidence docs/shots/laneF/round0_stub_tube.png. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
32 lines
1.2 KiB
JavaScript
32 lines
1.2 KiB
JavaScript
// core/rng.js (Lane F) — THE only randomness source in GUTS. qa.sh greps for violators.
|
|
// mulberry32: tiny, fast, deterministic. Same seed => same sequence, forever.
|
|
|
|
export function mulberry32(seed) {
|
|
let a = seed >>> 0;
|
|
return function () {
|
|
a |= 0; a = (a + 0x6D2B79F5) | 0;
|
|
let t = Math.imul(a ^ (a >>> 15), 1 | a);
|
|
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
|
|
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
};
|
|
}
|
|
|
|
// Named sub-streams so lanes don't perturb each other's sequences:
|
|
// rng('world'), rng('enemies'), ... each is an independent deterministic stream.
|
|
export function createRng(seed) {
|
|
const streams = new Map();
|
|
function hash(str) {
|
|
let h = 2166136261 >>> 0;
|
|
for (let i = 0; i < str.length; i++) { h ^= str.charCodeAt(i); h = Math.imul(h, 16777619); }
|
|
return h >>> 0;
|
|
}
|
|
const rng = (stream = 'main') => {
|
|
if (!streams.has(stream)) streams.set(stream, mulberry32((seed ^ hash(stream)) >>> 0));
|
|
return streams.get(stream);
|
|
};
|
|
rng.seed = seed;
|
|
rng.float = (stream, min = 0, max = 1) => min + rng(stream)() * (max - min);
|
|
rng.int = (stream, min, max) => Math.floor(rng.float(stream, min, max + 1));
|
|
return rng;
|
|
}
|