refactor fieldStream, handles oscillators

This commit is contained in:
Sorrel Bri 2020-05-24 15:54:41 -07:00
parent 9c52a320eb
commit 32762e6ca8
3 changed files with 180 additions and 30 deletions

View file

@ -40,6 +40,9 @@ class CellStream extends Stream {
addLiveNeighbor() {
this.head.addLiveNeighbor();
}
setLiving() {
this.head.setLiving();
}
}
const cellStream = (living = false, liveNeighbors = 0) => {

View file

@ -12,9 +12,10 @@ class GameField {
}
})
);
for (let key in fieldMap) {
this.map[key] = cellStream(true, 0);
}
Object.entries(fieldMap).forEach(
([key, [live, neighbors]]) =>
(this.map[key] = cellStream(live, neighbors))
);
// instead of implementing multiple GameFields, clear irrelevant keys and expand Game Field as needed
// discrete Field expansion should only happen in View (to keep view fields centered)
}
@ -35,19 +36,43 @@ class FieldStream extends Stream {
}
}
const seedMap = (map, [key, seed]) => {
map[key] = seed;
return map;
};
const isLiving = ([key, cell]) => cell.living === true;
const incrementLiveNeighbors = (field) => ([key]) =>
getNeighbors(key).forEach((neighbor) => field.addLiveNeighbor(neighbor));
const makeSeed = ([key, cell]) => [key, [cell.living, cell.liveNeighbors]];
const makeSeedNextGen = ([key, cell]) => {
cell.setLiving();
return [key, [cell.living, 0]];
};
const fieldStream = ({ fieldArray, fieldMap }) => {
return new FieldStream(new GameField({ fieldArray, fieldMap }), function () {
// calculate liveNeighbors for all cells on first next call
for (const key in this.map) {
getNeighbors(key).forEach((neighbor) => this.addLiveNeighbor(neighbor));
Object.entries(this.map)
.filter(isLiving)
.forEach(incrementLiveNeighbors(this));
// generate seed for next Stream with liveNeighbors
const mapWithLiveNeighbors = Object.entries(this.map)
.map(makeSeed)
.reduce(seedMap, {});
// return next stream
return new FieldStream(
new GameField({ fieldMap: mapWithLiveNeighbors }),
function () {
// determine living cells for next generation
const nextGeneration = Object.entries(this.map)
.map(makeSeedNextGen)
.reduce(seedMap, {});
// seed next Stream
return fieldStream({ fieldMap: nextGeneration });
}
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)
// const gameFields = new Array(1).fill(new GameField({}));

View file

@ -7,9 +7,9 @@ describe("Game Field seeds living Cells with array", () => {
];
const fieldMap = {
"0,0": true,
"0,2": true,
"1,1": true,
"0,0": [true, 0],
"0,2": [true, 0],
"1,1": [true, 0],
};
const gameArraySeed = new GameField({ fieldArray });
const gameMapSeed = new GameField({ fieldMap });
@ -85,13 +85,13 @@ describe("fieldStream.next calculates liveNeighbors", () => {
});
const fieldMap = {
"0,1": true,
"0,2": true,
"1,0": true,
"1,1": true,
"1,3": true,
"2,1": true,
"2,2": true,
"0,1": [true, 0],
"0,2": [true, 0],
"1,0": [true, 0],
"1,1": [true, 0],
"1,3": [true, 0],
"2,1": [true, 0],
"2,2": [true, 0],
};
const testStream2 = fieldStream({ fieldMap });
[
@ -128,27 +128,149 @@ describe("fieldStream.next calculates liveNeighbors", () => {
});
});
describe.skip("fieldStream.next tests still lifes", () => {
describe("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 streamBlock = fieldStream({ fieldArray: blockArray });
[
["-1,-1", false],
["-1,0", false],
["-1,1", false],
["-1,2", false],
["0,-1", false],
["0,0", true],
["0,1", true],
["0,2", false],
["1,-1", false],
["1,0", true],
["1,1", true],
["1,2", false],
["2,-1", false],
["2,0", false],
["2,1", false],
["2,2", false],
].forEach(([key, live]) => {
test(`after one generation of Block, ${key} alive: ${live}`, () => {
expect(streamBlock.next.next.map[key].living).toEqual(live);
});
});
const beehiveMap = {
"0,1": true,
"0,2": true,
"1,0": true,
"1,3": true,
"2,1": true,
"2,2": true,
"0,1": [true, 0],
"0,2": [true, 0],
"1,0": [true, 0],
"1,3": [true, 0],
"2,1": [true, 0],
"2,2": [true, 0],
};
const streamBeehive = fieldStream({ fieldMap: beehiveMap });
[
["-1,0", false],
["-1,1", false],
["-1,2", false],
["-1,3", false],
["0,-1", false],
["0,0", false],
["0,1", true],
["0,2", true],
["0,3", false],
["0,4", false],
["1,-1", false],
["1,0", true],
["1,1", false],
["1,2", false],
["1,3", true],
["1,4", false],
["2,-1", false],
["2,0", false],
["2,1", true],
["2,2", true],
["2,3", false],
["2,4", false],
["3,0", false],
["3,1", false],
["3,2", false],
["3,3", false],
].forEach(([key, live]) => {
test(`after one generation of Beehive, ${key} alive: ${live}`, () => {
expect(streamBeehive.next.next.map[key].living).toEqual(live);
});
});
const boatArray = [
[1, 1, 0],
[1, 0, 1],
[0, 1, 0],
];
const streamBoat = fieldStream({ fieldArray: boatArray });
[
["-1,-1", false],
["-1,0", false],
["-1,1", false],
["-1,2", false],
["0,-1", false],
["0,0", true],
["0,1", true],
["0,2", false],
["1,-1", false],
["1,0", true],
["1,1", false],
["1,2", true],
["1,3", false],
["2,-1", false],
["2,0", false],
["2,1", true],
["2,2", false],
["2,3", false],
["3,0", false],
["3,1", false],
["3,2", false],
].forEach(([key, live]) => {
test(`after one generation of Beehive, ${key} alive: ${live}`, () => {
expect(streamBoat.next.next.map[key].living).toEqual(live);
});
});
});
describe("fieldStream.next tests oscillators", () => {
const blinkerArray = [
[0, 1, 0],
[0, 1, 0],
[0, 1, 0],
];
const streamBlinker = fieldStream({ fieldArray: blinkerArray });
[
["0,0", false],
["0,1", false],
["0,2", false],
["1,0", true],
["1,1", true],
["1,2", true],
["2,0", false],
["2,1", false],
["2,2", false],
].forEach(([key, live]) => {
test(`after one generation of blinker, ${key} alive: ${live}`, () => {
expect(streamBlinker.next.next.map[key].living).toEqual(live);
});
});
[
["0,0", false],
["0,1", true],
["0,2", false],
["1,0", false],
["1,1", true],
["1,2", false],
["2,0", false],
["2,1", true],
["2,2", false],
].forEach(([key, live]) => {
test(`after two generations of blinker, ${key} alive: ${live}`, () => {
console.log(streamBlinker.next.next.map);
expect(streamBlinker.next.next.next.next.map[key].living).toEqual(live);
});
});
});