Skip to content

Instantly share code, notes, and snippets.

@misterussell
Last active December 21, 2017 14:46
Show Gist options
  • Save misterussell/51f7ef8fccecd380de3b9ba07c702260 to your computer and use it in GitHub Desktop.
Save misterussell/51f7ef8fccecd380de3b9ba07c702260 to your computer and use it in GitHub Desktop.
A basic non-optimized Game of Life
/*
* getGeneration() takes an initial 2d array, and a integer n where n is the
* desired generation output
* the initial 2d array must immediately be converted into a toroidal array
* the left and right edges must be stitched together
* the top and bottom edges must be stiched together
* these indices have a total of 8 neighbors
* any live cell with n < 2 dies
* any live cell with 2 < n < 3 lives on gen x + 1
* any live cell with n < 3 dies
* any dead cell with n = 3 becomes alive
* toroidal stictching will be handled after we have been able to create and
* optimize the 2d life model
*/
function getGeneration(cells, generations){
// create a mutable copy of the array passed in
const initialGen = cells;
// create an array to store the new generations in
let genCache = [];
/* the goal for the later version is to keep the program aware of previous
* runs to assist with speeding up computation so we will initiate a hash for
* each cell. We multiply the x and y values with specific prime numbers so
* that we can keep the hashes unique. I have a feeling that we are going to
* need to give each cell more knowledge of itself so I am using this as a
* constructor
*/
for (var i = 0; i < generations; i++) {
const previousGen = genCache.length > 0
? generateNextState(generateGenState(genCache[genCache.length - 1]))
: initialGen
genCache.push(previousGen);
}
return genCache;
}
function generateGenState(rawCells) {
// first create the Cell constructor. In the first non-toroidal
function Cell(x, y, cellState, neighbors = 0) {
this.x = x;
this.y = y;
this.hash = (this.x * 15486047) + (this.y * 15487429);
this.isAlive = cellState;
this.neighbors = neighbors
}
// return a map of the current cell configuration passed in as cells
// I will refer to each level of the array as a terrain
let test = rawCells.map((terrian, i, arr) => {
return terrian.map((cell, p, arr2) => {
const cellState = Boolean(cell);
const above = arr[i - 1] !== undefined ? arr[i - 1][p] : 0;
const below = arr[i + 1] !== undefined ? arr[i + 1][p] : 0;
const right = arr2[p + 1] !== undefined ? arr2[p + 1] : 0;
const left = arr2[p - 1] !== undefined ? arr2[p - 1] : 0;
const abovePerps = arr[i - 1] !== undefined ? [arr[i - 1][p - 1], arr[i - 1][p + 1]] : [0, 0];
const belowPerps = arr[i + 1] !== undefined ? [arr[i + 1][p - 1], arr[i + 1][p + 1]] : [0, 0];
const neighbors = checkNeighbors([
// right left
right, left,
// above below
above, below,
// above perps
abovePerps[0], abovePerps[1],
// below perps
belowPerps[0], belowPerps[1]
]);
return new Cell(i + 1, p + 1, cellState, neighbors);
});
});
// console.log(test);
return test
}
function checkNeighbors(neighbors) {
let verifiedNeighbors = 0;
neighbors.forEach(neighbor => {
return neighbor === 1 ? verifiedNeighbors += 1 : null
})
return verifiedNeighbors;
}
function generateNextState(cells) {
return cells.map(terrain => {
return terrain.map(cell => {
const twoOrThree = (cell.neighbors === 2 || cell.neighbors === 3) ? 1 : 0;
const greaterThanThree = cell.neighbors > 3 ? 0 : twoOrThree;
const convertLive = cell.nieghbors < 2 ? 0 : greaterThanThree;
const convertDead = cell.neighbors === 3 ? 1 : 0
return cell.isAlive
? convertLive
: convertDead
});
})
}
let gen = [
[0,0,0,0,0],
[0,0,1,0,0],
[0,0,0,1,0],
[0,1,1,1,0],
[0,0,0,0,0]
]
console.log(getGeneration(gen, 12))
gen = [
[0,0,0,0,0],
[0,0,1,0,0],
[0,0,1,0,0],
[0,0,1,0,0],
[0,0,0,0,0]
]
console.log(getGeneration(gen, 4));
gen = [
[0,0,0,0,0,0],
[0,1,1,0,0,0],
[0,1,0,0,0,0],
[0,0,0,0,1,0],
[0,0,0,1,1,0],
[0,0,0,0,0,0]
]
console.log(getGeneration(gen, 4));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment