diff --git a/src/components/Cell.js b/src/components/Cell.js index 918f971..af60f89 100644 --- a/src/components/Cell.js +++ b/src/components/Cell.js @@ -31,9 +31,15 @@ class CellStream extends Stream { get living() { return this.head.living; } + get liveNeighbors() { + return this.head.liveNeighbors; + } set liveNeighbors(liveNeighbors) { this.head.liveNeighbors = liveNeighbors; } + addLiveNeighbor() { + this.head.addLiveNeighbor(); + } } const cellStream = (living = false, liveNeighbors = 0) => { diff --git a/src/components/GameField.js b/src/components/GameField.js index 204e54c..1e3133f 100644 --- a/src/components/GameField.js +++ b/src/components/GameField.js @@ -1,5 +1,5 @@ const { cellStream } = require("./Cell"); -const { Stream } = require("../utils"); +const { Stream, getNeighbors } = require("../utils"); class GameField { constructor({ fieldArray = [], fieldMap = {} }) { @@ -8,7 +8,7 @@ class GameField { fieldArray.forEach((subArray, majorIndex) => subArray.forEach((value, minorIndex) => { if (value > 0) { - this.map[`${majorIndex}-${minorIndex}`] = cellStream(true, 0); + this.map[`${majorIndex},${minorIndex}`] = cellStream(true, 0); } }) ); @@ -27,18 +27,26 @@ class FieldStream extends Stream { get map() { return this.head.map; } + addLiveNeighbor(key) { + if (this.map[key] === undefined) { + this.map[key] = new cellStream(false); + } + this.map[key].addLiveNeighbor(); + } } const fieldStream = ({ fieldArray, fieldMap }) => { return new FieldStream(new GameField({ fieldArray, fieldMap }), function () { // calculate liveNeighbors for all cells on first next call - - new FieldStream({}, function () { + for (const key in this.map) { + getNeighbors(key).forEach((neighbor) => this.addLiveNeighbor(neighbor)); + } + this.tail = function () { // call .next on all Cells on second next call - }); + }; + return this; }); }; - // as a stream -> fieldStream => Stream(GameField, () => Stream(fieldStream.computeNeighbors(), () => Stream(fieldStream.setLiving())) // instantiate table (orientation of major and minor axis dependent on viewport) diff --git a/src/test/GameField.test.js b/src/test/GameField.test.js index c9e040b..c60ef44 100644 --- a/src/test/GameField.test.js +++ b/src/test/GameField.test.js @@ -1,23 +1,22 @@ import { GameField, fieldStream } from "../components/GameField"; -const fieldArray = [ - [0, 1, 0], - [1, 0, 1], -]; - -const fieldMap = { - "0-0": true, - "0-2": true, - "1-1": true, -}; - describe("Game Field seeds living Cells with array", () => { + const fieldArray = [ + [0, 1, 0], + [1, 0, 1], + ]; + + const fieldMap = { + "0,0": true, + "0,2": true, + "1,1": true, + }; const gameArraySeed = new GameField({ fieldArray }); const gameMapSeed = new GameField({ fieldMap }); const streamArraySeed = fieldStream({ fieldArray }); const streamMapSeed = fieldStream({ fieldMap }); - ["0-1", "1-0", "1-2"].forEach((key) => { + ["0,1", "1,0", "1,2"].forEach((key) => { test(`Array seed: ${key} should equal living Cell`, () => { expect(gameArraySeed.map[key].living).toEqual(true); }); @@ -35,7 +34,7 @@ describe("Game Field seeds living Cells with array", () => { }); }); - ["0-0", "0-2", "1-1"].forEach((key) => { + ["0,0", "0,2", "1,1"].forEach((key) => { test(`Array seed: ${key} should equal undefined`, () => { expect(gameArraySeed.map[key]).toEqual(undefined); }); @@ -53,3 +52,103 @@ describe("Game Field seeds living Cells with array", () => { }); }); }); + +describe("fieldStream.next calculates liveNeighbors", () => { + const fieldArray = [ + [0, 1, 0], + [1, 0, 1], + ]; + const testStream = fieldStream({ fieldArray }); + [ + ["-1,0", 1], + ["-1,1", 1], + ["-1,2", 1], + ["0,-1", 1], + ["0,0", 2], + ["0,1", 2], + ["0,2", 2], + ["0,3", 1], + ["1,-1", 1], + ["1,0", 1], + ["1,1", 3], + ["1,2", 1], + ["1,3", 1], + ["2,-1", 1], + ["2,0", 1], + ["2,1", 2], + ["2,2", 1], + ["2,3", 1], + ].forEach(([key, liveNeighbors]) => { + test(`after .next ${key} in 1st should have ${liveNeighbors} liveNeighbors`, () => { + expect(testStream.next.map[key].liveNeighbors).toEqual(liveNeighbors); + }); + }); + + const fieldMap = { + "0,1": true, + "0,2": true, + "1,0": true, + "1,1": true, + "1,3": true, + "2,1": true, + "2,2": true, + }; + const testStream2 = fieldStream({ fieldMap }); + [ + ["-1,0", 1], + ["-1,1", 2], + ["-1,2", 2], + ["-1,3", 1], + ["0,-1", 1], + ["0,0", 3], + ["0,1", 3], + ["0,2", 3], + ["0,3", 2], + ["0,4", 1], + ["1,-1", 1], + ["1,0", 3], + ["1,1", 5], + ["1,2", 6], + ["1,3", 2], + ["1,4", 1], + ["2,-1", 1], + ["2,0", 3], + ["2,1", 3], + ["2,2", 3], + ["2,3", 2], + ["2,4", 1], + ["3,0", 1], + ["3,1", 2], + ["3,2", 2], + ["3,3", 1], + ].forEach(([key, liveNeighbors]) => { + test(`after .next ${key} in 2nd should have ${liveNeighbors} liveNeighbors`, () => { + expect(testStream2.next.map[key].liveNeighbors).toEqual(liveNeighbors); + }); + }); +}); + +describe.skip("fieldStream.next tests still lifes", () => { + const blockArray = [ + [1, 1], + [1, 1], + ]; + + streamBlock = fieldStream({ fieldArray: blockArray }); + ["0,0", "0,1", "1,0", "1,1"].forEach((key) => {}); + + const beehiveMap = { + "0,1": true, + "0,2": true, + "1,0": true, + "1,3": true, + "2,1": true, + "2,2": true, + }; + + const boatArray = [ + [1, 1, 0], + [1, 0, 1], + [0, 1, 0], + ]; +}); diff --git a/src/utils/index.js b/src/utils/index.js index ea07440..e2cd2b6 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -13,6 +13,21 @@ class Stream { } } +const getNeighbors = (key) => { + const [x, y] = key.split(",").map((str) => parseInt(str)); + return [ + [x - 1, y - 1], + [x - 1, y], + [x - 1, y + 1], + [x, y - 1], + [x, y + 1], + [x + 1, y - 1], + [x + 1, y], + [x + 1, y + 1], + ].map((arr) => arr.join(",")); +}; + module.exports = { Stream, + getNeighbors, };