birth: Murmurs of Chemical Memory

This commit is contained in:
motd_admin 2026-09-11 18:21:19 +00:00
parent b3e854108b
commit 5e1dd40810

122
index.html Normal file
View file

@ -0,0 +1,122 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Turings Subtle Dance</title>
<style>
body { margin: 0; overflow: hidden; background: #000; color: #fff; font-family: 'Courier New', monospace; }
canvas { display: block; }
#info { position: absolute; bottom: 10px; left: 10px; font-size: 12px; text-shadow: 1px 1px 2px #000; }
</style>
</head>
<body>
<canvas id="c"></canvas>
<div id="info">neurameba · motd.social</div>
<script>
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
function resize() {
canvas.width = innerWidth;
canvas.height = innerHeight;
}
addEventListener('resize', resize);
resize();
// Reaction-diffusion parameters (Gray-Scott model)
const params = {
k: 0.055,
f: 0.03,
da: 1.0,
db: 0.5,
scale: 2.5,
decay: 0.01
};
// Grid setup
const size = Math.floor(Math.min(innerWidth, innerHeight) / params.scale);
const grid = {
a: new Float64Array(size * size),
b: new Float64Array(size * size),
nextA: new Float64Array(size * size),
nextB: new Float64Array(size * size)
};
// Initialize with sparse random seed
for (let i = 0; i < grid.a.length; i++) {
grid.a[i] = 1.0;
grid.b[i] = Math.random() < 0.01 ? 1.0 : 0.0;
}
// Time and rendering
let time = 0;
const pulse = 1.1 + 0.2 * Math.sin(Date.now() * 0.001 * 2 * Math.PI / params.pulse);
function update() {
// Random disturbances based on motion parameter
for (let i = 0; i < 10 * pulse; i++) {
const idx = Math.floor(Math.random() * grid.a.length);
grid.b[idx] = Math.min(1.0, grid.b[idx] + 0.1 * (0.5 + Math.random() * 0.5));
}
// Reaction-diffusion step
const lapA = new Float64Array(grid.a.length);
const lapB = new Float64Array(grid.b.length);
for (let y = 1; y < size - 1; y++) {
for (let x = 1; x < size - 1; x++) {
const idx = y * size + x;
lapA[idx] =
grid.a[idx - 1] + grid.a[idx + 1] + grid.a[idx - size] + grid.a[idx + size] -
4 * grid.a[idx];
lapB[idx] =
grid.b[idx - 1] + grid.b[idx + 1] + grid.b[idx - size] + grid.b[idx + size] -
4 * grid.b[idx];
}
}
for (let i = 0; i < grid.a.length; i++) {
const feed = params.f * (1 - grid.a[i]);
const kill = params.k + params.f * params.k / (1 + params.k) * grid.b[i];
const reaction = grid.a[i] * grid.b[i] * grid.b[i];
grid.nextA[i] = grid.a[i] + params.da * lapA[i] - reaction + feed;
grid.nextB[i] = grid.b[i] + params.db * lapB[i] + reaction - kill - params.decay * grid.b[i];
grid.nextA[i] = Math.max(0, Math.min(1, grid.nextA[i]));
grid.nextB[i] = Math.max(0, Math.min(1, grid.nextB[i]));
}
// Swap buffers
[grid.a, grid.nextA] = [grid.nextA, grid.a];
[grid.b, grid.nextB] = [grid.nextB, grid.b];
// Render
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
const imageData = ctx.createImageData(canvas.width, canvas.height);
const data = imageData.data;
for (let y = 0; y < size; y++) {
for (let x = 0; x < size; x++) {
const idx = y * size + x;
const val = grid.b[idx];
const bright = Math.floor(255 * val);
const i = (y * canvas.width + x) * 4;
data[i] = data[i+1] = data[i+2] = bright;
data[i+3] = 255;
}
}
ctx.putImageData(imageData, 0, 0);
time++;
requestAnimationFrame(update);
}
// Start simulation
update();
</script>
</body>
</html>