Skip to content

Instantly share code, notes, and snippets.

@KrofDrakula
Created December 8, 2012 13:56
Show Gist options
  • Save KrofDrakula/4240350 to your computer and use it in GitHub Desktop.
Save KrofDrakula/4240350 to your computer and use it in GitHub Desktop.
Game of Life
function Cell(x, y) {
this.x = x;
this.y = y;
}
function World(cells) {
this.cells = cells || [];
}
Array.prototype.hasCell = function(cell) {
if (arguments.length == 2) cell = new Cell(arguments[0], arguments[1]);
return this.filter(function(c) {
return c.x == cell.x && c.y == cell.y;
}, this).length > 0;
};
World.prototype.advanceStep = function(){
var candidates = this.computeCandidates(),
newState = [];
candidates.forEach(function(cell) {
var neighbours = this.findNeighbours(cell);
if (neighbours.length == 2 && this.cells.hasCell(cell) || neighbours.length == 3)
newState.push(cell);
}, this);
this.cells = newState;
};
World.prototype.computeCandidates = function() {
var candidates = [];
this.cells.forEach(function(cell) {
for (var y = cell.y - 1; y <= cell.y + 1; y++)
for (var x = cell.x - 1; x <= cell.x + 1; x++) {
var c = new Cell(x, y);
if (!candidates.hasCell(c)) candidates.push(c);
}
});
return candidates;
};
World.prototype.findNeighbours = function(cell) {
if (arguments.length == 2) {
cell = new Cell(arguments[0], arguments[1]);
}
return this.cells.filter(function(c) {
var dx = Math.pow(c.x - cell.x, 2),
dy = Math.pow(c.y - cell.y, 2);
return (dx + dy > 0) && (dx + dy <= 2);
});
}
World.prototype.render = function() {
var xs = this.cells.map(function(cell){ return cell.x; });
var ys = this.cells.map(function(cell){ return cell.y; });
var minX = Math.min.apply(Math, xs) - 2;
var maxX = Math.max.apply(Math, xs) + 2;
var minY = Math.min.apply(Math, ys) - 2;
var maxY = Math.max.apply(Math, ys) + 2;
console.log();
for (var y = minY; y <= maxY; y++) {
for (var x = minX; x <= maxX; x++) {
if (this.cells.hasCell(x, y)) {
process.stdout.write('X ');
} else {
process.stdout.write('- ');
}
}
console.log();
}
}
exports.World = World;
exports.Cell = Cell;
// npm install mocha chai
require('chai').should();
var gol = require('./gol'),
World = gol.World,
Cell = gol.Cell;
describe('Game of Life', function() {
describe('an empty world', function() {
it('should have no cells', function() {
var w = new World();
w.cells.length.should.equal(0);
});
it('should stay dead', function() {
var w = new World();
w.advanceStep();
w.cells.length.should.equal(0);
});
});
describe('simple structures', function() {
it('should store cells correctly', function() {
var w = new World([
new Cell(0,0)
]);
w.cells.length.should.equal(1);
w.cells.push(new Cell(1,0));
w.cells.length.should.equal(2);
});
it('should correctly count neighbours', function() {
var w = new World([
new Cell(0,0),
new Cell(0,1),
new Cell(0,2)
]);
w.findNeighbours(0, -2).length.should.equal(0);
w.findNeighbours(0, -1).length.should.equal(1);
w.findNeighbours(w.cells[0]).length.should.equal(1);
w.findNeighbours(w.cells[1]).length.should.equal(2);
w.findNeighbours(w.cells[2]).length.should.equal(1);
w.findNeighbours(0, 3).length.should.equal(1);
w.findNeighbours(0, 4).length.should.equal(0);
});
});
describe('too small world', function() {
it('should not survive', function() {
var w = new World([
new Cell(0, 0)
]);
w.advanceStep();
w.cells.length.should.equal(0);
});
});
describe('line', function() {
it('should rotate', function() {
var w = new World([
new Cell(0, 0),
new Cell(1, 0),
new Cell(2, 0)
]);
w.advanceStep();
w.cells.hasCell(new Cell(1, -1)).should.be.true;
w.cells.hasCell(new Cell(1, 0)).should.be.true;
w.cells.hasCell(new Cell(1, 1)).should.be.true;
w.cells.length.should.equal(3);
});
});
describe('glider', function() {
it('should have a period of four generations', function() {
});
});
describe('render', function() {
it('should render', function() {
var w = new World([
new Cell(0, 0),
new Cell(1, 0),
new Cell(2, 0)
]);
w.render();
w.advanceStep();
w.render();
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment