diff options
Diffstat (limited to 'client/lib/life.js')
| -rw-r--r-- | client/lib/life.js | 312 |
1 files changed, 262 insertions, 50 deletions
diff --git a/client/lib/life.js b/client/lib/life.js index e5df868..301535d 100644 --- a/client/lib/life.js +++ b/client/lib/life.js @@ -1,78 +1,290 @@ - -let w, h, a, b, notes, assign -function init(z, fn){ +let w, h, a, b, notes, assign; +function init(z, fn) { // really bad - notes = z - assign = fn - build() - setTempo(50) + notes = z; + assign = fn; + build(); + setTempo(50); } -function build(){ - w = notes.length - h = notes[0].length - a = a || new Array(w) - b = b || new Array(w) +function build() { + w = notes.length; + h = notes[0].length; + a = a || new Array(w); + b = b || new Array(w); for (var i = 0; i < w; i++) { - a[i] = a[i] || new Array(h) - b[i] = b[i] || new Array(h) + a[i] = a[i] || new Array(h); + b[i] = b[i] || new Array(h); for (var j = 0; j < h; j++) { - a[i][j] = b[i][j] = (notes[i][j] && notes[i][j].playing) ? 1 : 0 + a[i][j] = b[i][j] = notes[i][j] && notes[i][j].playing ? 1 : 0; } } } -let timeout, delay = 1200 // ~120 bpm -function toggle(){ - build() +let timeout, + delay = 1200; // ~120 bpm +function toggle() { + build(); if (timeout) { - clearTimeout(timeout) - timeout = null - } - else { - step() + clearTimeout(timeout); + timeout = null; + } else { + step(); } } -function assign_item(freq,state){ - b[freq.i][freq.j] = state ? 1 : 0 +function assign_item(freq, state) { + b[freq.i][freq.j] = state ? 1 : 0; } -function setTempo(bpm){ - console.log('bpm:', bpm) - delay = 60000/bpm +function setTempo(bpm) { + console.log("bpm:", bpm); + delay = 60000 / bpm; } -function swap () { - var tmp = a - a = b - b = tmp +function swap() { + var tmp = a; + a = b; + b = tmp; } function step() { - clearTimeout(timeout) - timeout = setTimeout(step, delay) - swap() - let i, j, ni, pi, nj, pj, score, state + clearTimeout(timeout); + timeout = setTimeout(step, delay); + swap(); + let i, j, ni, pi, nj, pj, score, state; for (i = 0; i < w; i++) { for (j = 0; j < h; j++) { - ni = i === 0 ? w-1 : i-1 - pi = i === w-1 ? 0 : i+1 - nj = j === 0 ? h-1 : j-1 - pj = j === h-1 ? 0 : j+1 - score = a[ni][nj] + a[ni][j] + a[ni][pj] + a[i][nj] + a[i][pj] + a[pi][nj] + a[pi][j] + a[pi][pj] - state = fitness(a[i][j], score) - b[i][j] = state + ni = i === 0 ? w - 1 : i - 1; + pi = i === w - 1 ? 0 : i + 1; + nj = j === 0 ? h - 1 : j - 1; + pj = j === h - 1 ? 0 : j + 1; + score = + a[ni][nj] + + a[ni][j] + + a[ni][pj] + + a[i][nj] + + a[i][pj] + + a[pi][nj] + + a[pi][j] + + a[pi][pj]; + state = fitness(a[i][j], score); + b[i][j] = state; if (a[i][j] !== state) { - assign(notes[i][j], state) + assign(notes[i][j], state); } } } } -function fitness (old, score) { +function fitness(old, score) { if (old === 1) { - if (score === 2 || score === 3) return 1 + if (score === 2 || score === 3) return 1; } else { - if (score === 3) return 1 + if (score === 3) return 1; } - return 0 + return 0; } function isRunning() { - return !!timeout + return !!timeout; } -export default { init, step, assign_item, toggle, setTempo, isRunning }
\ No newline at end of file +export default { init, step, assign_item, toggle, setTempo, isRunning }; + +///// grid functions + +const gliderShape = [ + [0, 0, 0, 0, 0], + [0, 1, 1, 1, 0], + [0, 0, 0, 1, 0], + [0, 0, 1, 0, 0], + [0, 0, 0, 0, 0], +]; +const gliderShapeFlip = gliderShape.map((a) => a.slice(0).reverse()); +const gliderShapes = [ + gliderShape, + gliderShapeFlip, + gliderShape.slice(0).reverse(), + gliderShapeFlip.slice(0).reverse(), +]; +function glider() { + const x = Math.floor(Math.random() * ws); + const y = Math.floor(Math.random() * hs); + const shape = choice(gliderShapes); + weave(x, y, shape); +} +function weave(x, y, shape) { + const xmag = shape.length; + const ymag = shape[0].length; + let i, j, px, py; + for (i = 0; i < xmag; i++) { + for (j = 0; j < ymag; j++) { + px = (x + i) % ws; + py = (y + j) % hs; + assign(notes[px][py], shape[i][j]); + } + } +} +function forEach(f) { + let i, j, note, s; + for (i = 0; i < ws; i++) { + for (j = 0; j < hs; j++) { + note = notes[i][j]; + s = f(i, j, note.playing); + assign(note, s); + } + } +} +function clone() { + let i, j; + let a = []; + for (i = 0; i < ws; i++) { + a[i] = []; + for (j = 0; j < hs; j++) { + a[i][j] = notes[i][j].playing; + } + } + return a; +} +function move(dx, dy) { + let a = clone(); + forEach((x, y, state) => { + x = (x + dx + ws) % ws; + y = (y + dy + hs) % hs; + return a[x][y]; + }); +} +function clear() { + forEach(() => { + return false; + }); +} +function stripex(odd) { + odd = !!odd; + forEach((x) => { + return x % 2 ? odd : !odd; + }); +} +function stripey(odd) { + odd = !!odd; + forEach((x, y) => { + return y % 2 ? odd : !odd; + }); +} +function checker(odd, n) { + odd = !!odd; + n = n || 1; + forEach((x, y) => { + return Math.floor(x / n) % 2 ^ Math.floor(y / n) % 2 ? odd : !odd; + }); +} +function noise(n) { + n = n || 0.5; + n = n * n; + forEach(() => { + return Math.random() < n; + }); +} + +///////////////////////// + +let life_bpm = 50; +window.addEventListener("keydown", keydown, true); +function keydown(e) { + // console.log(e.keyCode) + if (e.altKey || e.ctrlKey || e.metaKey) return; + switch (e.keyCode) { + case 32: // space + life.toggle(); + break; + case 188: // comma + life_bpm += e.shiftKey ? 1 : 5; + life.setTempo(life_bpm); + break; + case 190: // period + life_bpm -= e.shiftKey ? 1 : 5; + life_bpm = Math.max(1, life_bpm); + life.setTempo(life_bpm); + break; + case 37: // left + move(1, 0); + break; + case 38: // up + move(0, 1); + break; + case 39: // right + move(-1, 0); + break; + case 40: // down + move(0, -1); + break; + case 71: // g + glider(); + break; + case 83: // s + swap_instrument(); + break; + case 67: // c + clear(); + break; + case 87: // w + clear(); + break; + case 78: // n + noise(0.5); + break; + case 69: // e + stripex(Math.random() < 0.5); + break; + case 82: // r + stripey(Math.random() < 0.5); + break; + case 84: // t + checker(Math.random() < 0.5, 1); + break; + case 89: // y + checker(Math.random() < 0.5, 2); + break; + case 85: // u + checker(Math.random() < 0.5, 3); + break; + case 73: // i + checker(Math.random() < 0.5, 4); + break; + case 79: // o + checker(Math.random() < 0.5, 5); + break; + case 80: // p + checker(Math.random() < 0.5, 6); + break; + case 219: // [ + checker(Math.random() < 0.5, 7); + break; + case 221: // ] + checker(Math.random() < 0.5, 11); + break; + case 49: // 1 + noise(0.1); + break; + case 50: // 2 + noise(0.2); + break; + case 51: // 3 + noise(0.3); + break; + case 52: // 4 + noise(0.4); + break; + case 53: // 5 + noise(0.5); + break; + case 54: // 6 + noise(0.6); + break; + case 55: // 7 + noise(0.7); + break; + case 56: // 8 + noise(0.8); + break; + case 57: // 9 + noise(0.9); + break; + case 48: // 0 + noise(1); + break; + } +} |
