(function() {
	var WIDTH  = 52;
	var HEIGHT = 16;
	var CELL_SIZE = 5;
	var colors = ["#fff", "#cf5", "#b1e14d"];
	
	var population_history = [];
	var HISTORY_SIZE = 3;
	
	var context, configuration;
	
	window.addEventListener("load",	function () {
		var my_screen = document.getElementById("life");
		context = my_screen.getContext("2d");
	
		start_life();
	
		window.setInterval(draw, 100);
	}, false);
	
	function start_life() {
		population_history = [];
		configuration = [];
		for (var x = 0; x < WIDTH; ++x) {
			configuration[x] = [];
			for (var y = 0; y < HEIGHT; ++y)
				configuration[x][y] = Math.floor(Math.random() * 100) % 5 == 0 ? alive() : 0;
		}
	
		population_history.push(configuration);
	}
	
	function draw() {
		var x, y;
	
		for (x = 0; x < WIDTH; ++x)
			for (y = 0; y < HEIGHT; ++y) {
				context.fillStyle = colors[configuration[x][y]];
				context.fillRect(x*CELL_SIZE+x, y*CELL_SIZE+y, CELL_SIZE, CELL_SIZE);
			}
	
		population_history.push(configuration);
		if (population_history.length > HISTORY_SIZE) population_history.shift();
	
		update_configuration();
		if (!check_vital_signs()) {
			start_life();
		};
	}
	
	function check_vital_signs() {
		var compare_to;
	
		var alive = false;
	
		for (var n = 0; n < population_history.length; ++n) {
			var alive = false;
	
			compare_to = population_history[n];
			for (var x = 0; x < WIDTH; ++x) {
				for (var y = 0; y < HEIGHT; ++y) {
					if (compare_to[x][y] != configuration[x][y]) {
						alive = true;
						break;
					}
				}
	
				if (alive) break;
			}
	
			if (!alive) return alive;
		}
	
		return alive;
	}
	
	function count_neighbors(world, x, y) {
		var i, j;
		var new_x, new_y;
		var neighbors = 0;
	
		for (i = -1; i <= 1; ++i)
			for (j = -1; j <= 1; ++j) {
				new_x = x + i;
				new_y = y + j;
	
				/* -1 % 16 == -1 ... not 15 */
				if (new_x < 0) new_x = new_x + WIDTH;
				else if (new_x > WIDTH-1) new_x = new_x - WIDTH;
				if (new_y < 0) new_y = new_y + HEIGHT;
				else if (new_y > HEIGHT-1) new_y = new_y - HEIGHT;
	
				if (new_x == x && new_y == y) continue;
	
				if (is_alive(world[new_x][new_y]))
					++neighbors;
			}
	
		return neighbors;
	}
	
	function alive() {
		return colors.length-1;
	}
	
	function is_alive(cell) {
		return cell == alive();
	}
	
	function update_configuration(world) {
		var x, y, num_neighbors, new_state;
		var new_configuration = [];
	
		for (x = 0; x < WIDTH; ++x) {
			new_configuration[x] = [];
			for (y = 0; y < HEIGHT; ++y) {	
				num_neighbors = count_neighbors(configuration, x, y);
	
				new_state = configuration[x][y];
	
				if (num_neighbors == 3) new_state = alive();
				else if (num_neighbors == 2 && is_alive(configuration[x][y])) new_state = new_state;
				else new_state--;
	
				if (new_state < 0) new_state = 0;
	
				new_configuration[x][y] = new_state;
			}
		}
	
		configuration = new_configuration;
	}
})();