summaryrefslogtreecommitdiff
path: root/client/lib/life.js
diff options
context:
space:
mode:
Diffstat (limited to 'client/lib/life.js')
-rw-r--r--client/lib/life.js312
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;
+ }
+}