
var rule    = 110;   // rule number in Wolfram notation
var width   = 450;
var length  = 450;
var output  = new Array(width);
var current = new Array(width);

function automate(line, last)
{
    for(cell = 0; cell < width; cell++)
    {
        left  = cell - 1;
        if(left < 0) { left = width - 1; }

        right = cell + 1;
        if(right == width) { right = 0; }

        choice = 0;
        if(last[left])  { choice |= 0x04; }
        if(last[cell])  { choice |= 0x02; }
        if(last[right]) { choice |= 0x01; }

        current[cell] = ((rule >> choice) & 0x01) == 1;

        output[cell] = current[cell] ? '\u25a0' : ' ';
    }
    output[cell] = '\n';
    addLine(output.join(""));

    if(line < length)
    {
        setTimeout(function () { automate(++line, current.slice()) }, 0);
    }
}

var automaton;

// for IE oddities
var ie      = false;
var ieText  = "";

function addLine(data)
{
    if(ie) // normalization bug with <pre> innerHTML in IE
    {
        ieText = ieText.concat(data);
        automaton.innerText = ieText;
    }
    else
    {
        automaton.innerHTML = automaton.innerHTML.concat(data);
    }
}

window.onload = function()
{
    automaton = document.getElementById("automaton");
    if(navigator.appName == "Opera")
    {
        automaton.style.letterSpacing = "-1em";
        automaton.style.lineHeight = "1.25em";
    }
    if(navigator.appName.indexOf("Explorer") != -1)
    {
        ie = true;
    }

    // setup a random first line
    var last = new Array(width);
    for(i = 0; i < width; i++)
    {
        last[i] = Math.random() > .5;
    }

    automate(0, last);
}
