0x46cd289b…3484sent to0xa184990f…4d6d·#25,288,730·view on Etherscan
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));