memoscan
← all memos

Memo 0xea821eb4…068300 on Ethereum

type){ case 'flower': m = buildFlower(seed); break; case 'field': m = buildField(seed, spec.fieldType); break; case 'mirror': m = buildMirror(seed, spec.mode); break; case 'weave': m = buildWeave(seed); break; case 'bands': m = buildC64Token(seed); break; case 'bloom-breathe': m = buildBloom(seed, 'breathe'); break; case 'bloom-exhale': m = buildBloom(seed, 'exhale'); break; case 'rain': m = buildRain(seed); break; case 'cellular': m = buildCellular(seed); break; case 'fireworks': m = buildFireworks(seed); break; case 'snake': m = buildSnake(seed); break; case 'julia': m = buildJulia(seed); break; case 'plasma': m = buildPlasma(seed); break; case 'spiral': m = buildSpiral(seed); break; case 'starfield': m = buildStarfield(seed); break; case 'lissajous': m = buildLissajous(seed); break; case 'joystick': m = buildJoystick(seed); break; case 'frog': m = buildFrog(seed); break; default: m = buildC64Token(seed); } return rollCharSetForModel(m); } function startLoop(canvas, spec, salt, opts){ const model = buildFromSpec(spec, salt); const cell = Math.max(1, Math.floor((canvas.width || 512) / model.N)); canvas.width = canvas.height = model.N * cell; const ctx = canvas.getContext('2d'); drawC64Frame(ctx, model, 0, opts || {}); // synchronous first frame (snapshot-safe) function frame(now){ const t = (now % LOOP_MS) / LOOP_MS; drawC64Frame(ctx, model, t, opts || {}); requestAnimationFrame(frame); } requestAnimationFrame(frame); return model; } /* ====== seed-driven rendering (mint-time randomness) ====== The contract assigns each token a 256-bit seed at mint time. EVERYTHING about the token — family AND all within-family traits — derives from that single seed, so nothing is predictable before the mint tx lands in a block. 23 families, weight-picked. The four newest (Plasma/Spiral/Starfield/ Lissajous) carry w<1 so they land slightly rarer than the rest. */ const FAMILY_SPECS = [ { type:'flower' }, { type:'field', fieldType:'hbars' }, { type:'field', fieldType:'tunnel' }, { type:'field', fieldType:'rays' }, { type:'field', fieldType:'pulse' }, { type:'field', fieldType:'diag' }, { type:'mirror', mode:'h' }, { type:'mirror', mode:'v' }, { type:'mirror', mode:'d' }, { type:'mirror', mode:'quad' }, { type:'weave' }, { type:'bands' }, { type:'bloom-breathe' }, { type:'bloom-exhale' }, { type:'rain' }, { type:'cellular' }, { type:'fireworks' }, { type:'snake' }, { type:'julia' }, { type:'plasma', w:0.75 }, { type:'spiral', w:0.75 }, { type:'starfield', w:0.75 }, { type:'lissajous', w:0.75 }, { type:'joystick', w:0.75 }, { type:'frog', w:0.05 }, // ultra-rare easter egg (~5 of 2048) ]; function pickFamilyIndex(rf){ let total = 0; for(const f of FAMILY_SPECS) total += (f.w || 1); let x = rf() * total; for(let i = 0; i < FAMILY_SPECS.length; i++){ x -= (FAMILY_SPECS[i].w || 1); if(x <= 0) return i; } return FAMILY_SPECS.length - 1; } function buildFromSeed(seedStr){ // family chosen from an independent sub-stream so it doesn't bias the // within-family trait rolls (which run off the raw seedStr) const rf = makeRng(seedStr + ':family'); const fam = FAMILY_SPECS[pickFamilyIndex(rf)]; return buildFromSpec({ ...fam, seed: seedStr }, ''); } const FAMILY_LABELS = ['Flowers','Stripes','Tunnel','Rays','Pulse','Diagonal','Mirror H','Mirror V','Mirror D','Kaleidoscope','Weave','Bands','Bloom Breathe','Bloom Exhale','Rain','Cellular','Fireworks','Snake','Julia','Plasma','Spiral','Starfield','Lissajous','Joystick','Frog']; // Canonical seed -> labeled traits. Same family pick + within-family rolls the // renderer uses, surfaced as the published trait names. function traitsFromSeed(seedStr){ const rf = makeRng(seedStr + ':family'); const idx = pickFamilyIndex(rf); const family = FAMILY_LABELS[idx] || 'Unknown'; const m = buildFromSeed(seedStr); const colors = (m.colorCount != null) ? m.colorCount : (m.palette ? m.palette.length : null); const t = []; t.push(['Family', family]); t.push(['Density', String(m.N)]); if (colors != null) t.push(['Colors', String(colors)]); t.push(['Palette', m.palMode === 'colodore' ? 'Colodore' : 'Pepto']); t.push(['Char Set', m.charSet || 'Blocks']); if (m.base) t.push(['Mirror Base', ({diag:'Chevrons',bars:'Bars',rings:'Rings',wave:'Waves'})[m.base] || m.base]); // (Bloom Mode trait dropped: the Bloom Breathe / Bloom Exhale family already says it.) if (m.pattern) t.push(['Pattern', m.pattern]); if (m.form) t.push(['Form', m.form]); if (m.variant) t.push(['Variant', ({triangle:'Triangle',carpet:'Carpet',xor:'XOR'})[m.variant] || m.variant]); if (m.eye) { const g = m.eye.gaze; t.push(['Gaze', g <= 3 ? 'Calm' : g <= 5 ? 'Darting' : 'Frantic']); t.push(['Blink', (['Unblinking','Steady','Twitchy','Spasmodic'])[m.eye.blink] || 'Steady']); t.push(['Eye Fill', ({solid:'Solid',grid:'Grid',pattern:'Pattern'})[m.eye.fill] || 'Solid']); t.push(['Eye Color', ({0:'Void',1:'White',2:'Red',3:'Cyan',4:'Purple',5:'Green',6:'Blue',7:'Yellow',8:'Orange',9:'Brown',10:'High AF',11:'Dark Grey',12:'Grey',13:'Light Green',14:'Light Blue',15:'Light Grey'})[m.eye.light] || 'White']); t.push(['Eye Animation', m.eye.anim === 'sclera' ? 'Strobe' : m.eye.anim === 'pupil' ? 'Void Strobe' : 'None']); } t.push(['Tears', (m.eye && m.eye.tears) ? 'On' : 'Off']); t.push(['CRT Bend', (m.fx && m.fx.crt > 0) ? 'On' : 'Off']); t.push(['Chroma Split', (m.fx && m.fx.chroma > 0) ? 'On' : 'Off']); return { family: family, traits: t }; } function startLoopFromSeed(canvas, seedStr, opts){ const model = buildFromSeed(seedStr); const cell = Math.max(1, Math.floor((canvas.width || 512) / model.N)); canvas.width = canvas.height = model.N * cell; const ctx = canvas.getContext('2d'); drawC64Frame(ctx, model, 0, opts || {}); // synchronous first frame (snapshot-safe) function frame(now){ const t = (now % LOOP_MS) / LOOP_MS; drawC64Frame(ctx, model, t, opts || {}); requestAnimationFrame(frame); } requestAnimationFrame(frame); return model; } global.Nervous = { version: '1.1.0', build: buildFromSpec, buildFromSeed, traitsFromSeed, drawFrame: drawC64Frame, applyPostFx, startLoop, startLoopFromSeed, LOOP_MS, }; })(typeof globalThis !== 'undefined' ? globalThis : (typeof window !== 'undefined' ? window : this));