about summary refs log blame commit diff stats
path: root/html/plains/enemies.js
blob: 3d40c3eed3414c409cae9a666388c247c1365353 (plain) (tree)
735c449 pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/*
identity        I   a → a
constant        K   a → b → a
apply           A   (a → b) → a → b
thrush          T   a → (a → b) → b
duplication     W   (a → a → b) → a → b
flip            C   (a → b → c) → b → a → c
compose         B   (b → c) → (a → b) → a → c
substitution    S   (a → b → c) → (a → b) → a → c
chain           S_³ (a → b → c) → (b → a) → b → c
converge        S2³ (b → c → d) → (a → b) → (a → c) → a → d
psi             P   (b → b → c) → (a → b) → a → a → c
fix-point4      Y   (a → a) → a

ref:
https://www.willtaylor.blog/combinators-and-church-encoding-in-javscript/
*/

const I  = x => x
const K  = x => y => x
const A  = f => x => f (x)
const T  = x => f => f (x)
const W  = f => x => f (x) (x)
const C  = f => y => x => f (x) (y)
const B  = f => g => x => f (g (x))
const S  = f => g => x => f (x) (g (x))
const S_ = f => g => x => f (g (x)) (x)
const S2 = f => g => h => x => f (g (x)) (h (x))
const P  = f => g => x => y => f (g (x)) (g (y))
const Y  = f => (g => g (g)) (g => f (x => g (g) (x)))

// validate combinators
// I(1) // 1
// K(1)(2) // 1
// A(I)(1) // 1
// T(1)(I) // 1
// W(I)(1) // 1
// C(I)(1)(2) // 1
// B(I)(I)(1) // 1
// S(I)(I)(1) // 1
// S_(I)(I)(1) // 1
// S2(I)(I)(I)(1) // 1
// P(I)(I)(1)(2) // 1
// Y(I)(1) // 1

(function() {
    console.log('validating combinators');
    console.assert(I(1) === 1, 'I failed');
    console.assert(K(1)(2) === 1, 'K failed');
    console.assert(A(I)(1) === 1, 'A failed');
    console.assert(T(1)(I) === 1, 'T failed');
    console.assert(W(I)(1) === 1, 'W failed'); // FIXME: Does this really work?
    console.assert(C(I)(1)(2) === 1, 'C failed');
    console.assert(B(I)(I)(1) === 1, 'B failed');
    console.assert(S(I)(I)(1) === 1, 'S failed');
    console.assert(S_(I)(I)(1) === 1, 'S_ failed');
    console.assert(S2(I)(I)(I)(1) === 1, 'S2 failed');
    console.assert(P(I)(I)(1)(2) === 1, 'P failed');
    console.assert(Y(I)(1) === 1, 'Y failed');
}());


// Count the number of live neighbors of a cell
const countLiveNeighbors = B (A (B (A (B (A (K (A (I)))))))) (A (B (A (K (A (I))))))
const isAlive = cell => count => (cell && (count === 2 || count === 3)) || (!cell && count === 3)
const rules = B (A (B (A (K (A (I)))))) (A (B (A (K (A (I))))))
const nextState = B (A (B (A (K (A (I)))))) (A (B (A (K (A (I))))))
const nextBoardState = B (A (B (A (K (A (I)))))) (A (B (A (K (A (I))))))


// validate countLiveNeighbors rules
(function() {
    // FIXME: I think I messed up these test values, maybe?
    // FIXME: I also don't think this'll work given that the combinators will only grok 1 arg that is another combinator...right?
    console.log('validating countLiveNeighbors');
    console.assert(countLiveNeighbors([[true, false, true], [false, true, false], [true, false, true]], 1, 1) === 4, 'countLiveNeighbors 1 failed');
    console.assert(countLiveNeighbors([[true, false, true], [false, true, false], [true, false, true]], 0, 0) === 2, 'countLiveNeighbors 2 failed');
    console.assert(countLiveNeighbors([[true, false, true], [false, true, false], [true, false, true]], 2, 2) === 4, 'countLiveNeighbors 3 failed');
    console.assert(countLiveNeighbors([[true, false, true], [false, true, false], [true, false, true]], 0, 2) === 2, 'countLiveNeighbors 4 failed');
    console.assert(countLiveNeighbors([[true, false, true], [false, true, false], [true, false, true]], 2, 0) === 2, 'countLiveNeighbors 5 failed');
}());

// validate isAlive rules
(function() {
    console.log('validating isAlive');
    console.assert(isAlive(true)(2) === true, 'isAlive 1 failed');
    console.assert(isAlive(true)(3) === true, 'isAlive 2 failed');
    console.assert(isAlive(true)(4) === false, 'isAlive 3 failed');
    console.assert(isAlive(false)(3) === true, 'isAlive 4 failed');
    console.assert(isAlive(false)(2) === false, 'isAlive 5 failed');
}());

// validate rules
(function() {
    console.log('validating rules');
    console.assert(rules(true)(2) === true, 'rules 1 failed');
    // console.assert(rules(true)(3) === true, 'rules 2 failed');
    // console.assert(rules(true)(4) === false, 'rules 3 failed');
    // console.assert(rules(false)(3) === true, 'rules 4 failed');
    // console.assert(rules(false)(2) === false, 'rules 5 failed');
}());

// validate nextState rules
(function() {
    // FIXME: something is up with Bluebird I think...
    console.log('validating nextState');
    console.assert(nextState(true)(2) === true, 'nextState 1 failed');
    console.assert(nextState(true)(3) === true, 'nextState 2 failed');
    console.assert(nextState(true)(4) === false, 'nextState 3 failed');
    console.assert(nextState(false)(3) === true, 'nextState 4 failed');
    console.assert(nextState(false)(2) === false, 'nextState 5 failed');
}());

// validate nextBoardState rules
(function() {
    console.log('validating nextBoardState');
    const board = [
        [false, false, false],
        [true, true, true],
        [false, false, false]
    ];
    const nextBoard = [
        [false, true, false],
        [false, true, false],
        [false, true, false]
    ];
    console.assert(JSON.stringify(nextBoardState(board)) === JSON.stringify(nextBoard), 'nextBoardState 1 failed');
}());