function step() {
for (let i = 0; i < data.length; i++) {
let currentCell = data[i];
let neighborSum = 0;
if (currentCell.row == 0 && currentCell.column == 0) {
neighborSum =
data[currentCell.b].alive +
data[currentCell.r].alive +
data[currentCell.br].alive;
}
else if (currentCell.row == 0 && currentCell.column == columns - 1) {
neighborSum =
data[currentCell.b].alive +
data[currentCell.l].alive +
data[currentCell.bl].alive;
}
else if (currentCell.row == rows - 1 && currentCell.column == 0) {
neighborSum =
data[currentCell.t].alive +
data[currentCell.r].alive +
data[currentCell.tr].alive;
}
else if (currentCell.row == rows - 1 && currentCell.column == columns - 1) {
neighborSum =
data[currentCell.t].alive +
data[currentCell.l].alive +
data[currentCell.tl].alive;
}
//check if this cell is on the top edge
else if (currentCell.row == 0) {
//edge cells have 5 neighbors
neighborSum =
data[currentCell.b].alive +
data[currentCell.l].alive +
data[currentCell.r].alive +
data[currentCell.br].alive +
data[currentCell.bl].alive;
}
//check if this cell is on the bottom edge
else if (currentCell.row == rows - 1) {
neighborSum =
data[currentCell.t].alive +
data[currentCell.l].alive +
data[currentCell.r].alive +
data[currentCell.tr].alive +
data[currentCell.tl].alive;
}
//check if this cell is on the left-hand edge
else if (currentCell.column == 0) {
neighborSum =
data[currentCell.t].alive +
data[currentCell.b].alive +
data[currentCell.r].alive +
data[currentCell.tr].alive +
data[currentCell.br].alive;
}
//check if this cell is on the right-hand edge
else if (currentCell.column == columns - 1) {
neighborSum =
data[currentCell.t].alive +
data[currentCell.b].alive +
data[currentCell.l].alive +
data[currentCell.tl].alive +
data[currentCell.bl].alive;
}
//if all the checks above fail, this cell is an interior cell
else {
//interior cells have 8 neighbors
neighborSum =
data[currentCell.t].alive +
data[currentCell.b].alive +
data[currentCell.l].alive +
data[currentCell.r].alive +
data[currentCell.tr].alive +
data[currentCell.tl].alive +
data[currentCell.br].alive +
data[currentCell.bl].alive;
}
//Rules of the Game
//this sim uses the *survive* property to determine if the cell should live or die in the next generation
// These rules are *Conway's Game of Life*
// Any live cell with two or three live neighbors survives.
// Any dead cell with three live neighbors becomes a live cell.
// All other live cells die in the next generation. Similarly, all other dead cells stay dead.
// is the cell dead?
if (currentCell.alive == 0) {
//the cell is dead
if (neighborSum == 3) {
//if the cell is dead with three live neighbors, becem alie
currentCell.survive = 1;
} else {
//otherwise stay dead
currentCell.survive = 0;
}
} else {
//the cell is alive...
if (neighborSum == 2 || neighborSum == 3) {
//the living cell has 2 or 3 live neighbors, so it survives
currentCell.survive = 1;
} else {
//the cell dies
currentCell.survive = 0;
}
}
}
//replace the alive property with survive
//this seems unnecessary, right? why not just update alive directly above?
//if we do, things get really buggy, can you think of why?
//zach didn't catch it, and pulled out lots of hair trying to solve it!
for (let i = 0; i < data.length; i++) {
let currentCell = data[i];
currentCell.alive = currentCell.survive;
}
//update the visualization with a data join
d3.select('#mainSvg')
.selectAll('.automaton')
.data(data)
.transition()
.duration(generationalDelay)
.delay((d, i) => i / 10)
.attr('fill', function(d) {
if (d.alive == 1) {
return 'black';
} else {
return 'white';
}
});
}