237 lines
		
	
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			237 lines
		
	
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
var grid = document.getElementById("grid");
 | 
						|
 | 
						|
var cellsize = 60;
 | 
						|
 | 
						|
function xCoord(i, j) {
 | 
						|
    var x = i + j/2;
 | 
						|
    if (x > width - 1) {
 | 
						|
        x = x - width;
 | 
						|
    }
 | 
						|
    return x;
 | 
						|
}
 | 
						|
 | 
						|
function yCoord(i, j) {
 | 
						|
    return Math.sqrt(3)*j/2;
 | 
						|
}
 | 
						|
 | 
						|
var width;
 | 
						|
var height;
 | 
						|
var cells;
 | 
						|
 | 
						|
function initialize() {
 | 
						|
    width = Math.ceil(window.innerWidth / cellsize) + 1;
 | 
						|
    height = Math.ceil(window.innerHeight / (cellsize*Math.sqrt(3)/2)) + 1;
 | 
						|
 | 
						|
    cells = new Array(width);
 | 
						|
    for (var i = 0; i < width; ++i) {
 | 
						|
        cells[i] = new Array(height);
 | 
						|
        for (var j = 0; j < height; ++j) {
 | 
						|
            cells[i][j] = document.createElement("div");
 | 
						|
            cells[i][j].classList.add("cell");
 | 
						|
            cells[i][j].classList.add("alive");
 | 
						|
 | 
						|
            spiral = document.createElement("img");
 | 
						|
            spiral.classList.add("spiral");
 | 
						|
            spiral.src = "spiral.svg";
 | 
						|
            cells[i][j].appendChild(spiral);
 | 
						|
 | 
						|
            hex = document.createElement("img");
 | 
						|
            hex.classList.add("hex");
 | 
						|
            hex.src = "hex.svg";
 | 
						|
            cells[i][j].appendChild(hex);
 | 
						|
 | 
						|
            cells[i][j].style.position = "absolute";
 | 
						|
            cells[i][j].style.left = xCoord(i, j)*cellsize + "px";
 | 
						|
            cells[i][j].style.bottom = yCoord(i, j)*cellsize + "px";
 | 
						|
            grid.appendChild(cells[i][j]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    for (var i = 0; i < width; ++i) {
 | 
						|
        for (var j = 0; j < height; ++j) {
 | 
						|
            if (Math.floor(Math.random()*2) === 0) {
 | 
						|
                kill(i, j);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
function cleanup() {
 | 
						|
    for (var i = width - 1; i >= 0; --i) {
 | 
						|
        for (var j = height - 1; j >= 0; --j) {
 | 
						|
            grid.removeChild(cells[i][j]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
function prebirth(i, j) {
 | 
						|
    cells[i][j].classList.add("birthing");
 | 
						|
}
 | 
						|
function prekill(i, j) {
 | 
						|
    cells[i][j].classList.add("dying");
 | 
						|
}
 | 
						|
function birth(i, j) {
 | 
						|
    cells[i][j].classList.remove("dead");
 | 
						|
    cells[i][j].classList.add("alive");
 | 
						|
}
 | 
						|
function kill(i, j) {
 | 
						|
    cells[i][j].classList.remove("alive");
 | 
						|
    cells[i][j].classList.add("dead");
 | 
						|
}
 | 
						|
function update(i, j) {
 | 
						|
    var cl = cells[i][j].classList;
 | 
						|
    if (cl.contains("birthing")) {
 | 
						|
        cl.remove("birthing");
 | 
						|
        birth(i, j);
 | 
						|
    }
 | 
						|
    if (cl.contains("dying")) {
 | 
						|
        cl.remove("dying");
 | 
						|
        kill(i, j);
 | 
						|
    }
 | 
						|
}
 | 
						|
function isAlive(i, j) {
 | 
						|
    return !cells[i][j].classList.contains("dead");
 | 
						|
}
 | 
						|
 | 
						|
function rotate(a) {
 | 
						|
    a.push(a.shift());
 | 
						|
}
 | 
						|
 | 
						|
function arraysEq(a, b) {
 | 
						|
    if (a.length !== b.length) {
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    for (var i = 0; i < a.length; ++i) {
 | 
						|
        if (a[i] !== b[i]) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
function arraysRotatedEq(a, b) {
 | 
						|
    if (a.length !== b.length) {
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    for (var i = 0; i < a.length; ++i) {
 | 
						|
        if (arraysEq(a, b)) {
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
        rotate(b);
 | 
						|
    }
 | 
						|
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
function mod(m, n) {
 | 
						|
    return ((m % n) + n) % n;
 | 
						|
}
 | 
						|
 | 
						|
function ip(i) {
 | 
						|
    return mod(i-1, width);
 | 
						|
}
 | 
						|
function is(i) {
 | 
						|
    return mod(i+1, width);
 | 
						|
}
 | 
						|
function jp(j) {
 | 
						|
    return mod(j-1, height);
 | 
						|
}
 | 
						|
function js(j) {
 | 
						|
    return mod(j+1, height);
 | 
						|
}
 | 
						|
 | 
						|
function ll(i, j) {
 | 
						|
    return isAlive(ip(i), j);
 | 
						|
}
 | 
						|
function dl(i, j) {
 | 
						|
    return isAlive(i, jp(j));
 | 
						|
}
 | 
						|
function dr(i, j) {
 | 
						|
    return isAlive(is(i), jp(j));
 | 
						|
}
 | 
						|
function rr(i, j) {
 | 
						|
    return isAlive(is(i), j);
 | 
						|
}
 | 
						|
function ur(i, j) {
 | 
						|
    return isAlive(i, js(j));
 | 
						|
}
 | 
						|
function ul(i, j) {
 | 
						|
    return isAlive(ip(i), js(j));
 | 
						|
}
 | 
						|
 | 
						|
function neighbors(i, j) {
 | 
						|
    return [ll(i, j), dl(i, j), dr(i, j), rr(i, j), ur(i, j), ul(i, j)];
 | 
						|
}
 | 
						|
 | 
						|
function neighborsCount(i, j) {
 | 
						|
    return neighbors(i, j).filter(function (b) { return b; }).length;
 | 
						|
}
 | 
						|
 | 
						|
function golay(i, j) {
 | 
						|
    var n = neighbors(i, j);
 | 
						|
    var g1 = [true, true, false, false, false, false];
 | 
						|
    var g2 = [true, false, true, false, false, false];
 | 
						|
    return (arraysRotatedEq(n, g1) || arraysRotatedEq(n, g2));
 | 
						|
}
 | 
						|
 | 
						|
function preston(i, j) {
 | 
						|
    var n = neighbors(i, j);
 | 
						|
    var p1 = [true, true, false, false, false, false];
 | 
						|
    var p2 = [true, false, true, false, false, false];
 | 
						|
    return (isAlive(i, j) && (arraysRotatedEq(n, p1) || arraysRotatedEq(n, p2))) || (!isAlive(i, j) && neighborsCount(i, j) === 2);
 | 
						|
}
 | 
						|
 | 
						|
function golayStep() {
 | 
						|
    for (var i = 0; i < width; ++i) {
 | 
						|
        for (var j = 0; j < height; ++j) {
 | 
						|
            if (golay(i, j)) {
 | 
						|
                prebirth(i, j);
 | 
						|
            } else {
 | 
						|
                prekill(i, j);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    for (var i = 0; i < width; ++i) {
 | 
						|
        for (var j = 0; j < height; ++j) {
 | 
						|
            update(i, j);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
function prestonStep() {
 | 
						|
    for (var i = 0; i < width; ++i) {
 | 
						|
        for (var j = 0; j < height; ++j) {
 | 
						|
            if (preston(i, j)) {
 | 
						|
                prebirth(i, j);
 | 
						|
            } else {
 | 
						|
                prekill(i, j);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    for (var i = 0; i < width; ++i) {
 | 
						|
        for (var j = 0; j < height; ++j) {
 | 
						|
            update(i, j);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
initialize();
 | 
						|
 | 
						|
setInterval(prestonStep, 1000);
 | 
						|
 | 
						|
var showControls = false;
 | 
						|
 | 
						|
window.onclick = function () {
 | 
						|
    document.getElementById("controls").style.display = showControls ? "none" : "block";
 | 
						|
    showControls = !showControls;
 | 
						|
}
 | 
						|
 | 
						|
window.addEventListener('resize', function(event){
 | 
						|
    cleanup();
 | 
						|
    initialize();
 | 
						|
});
 |