<canvas width="320" height="178"></canvas>
const canvas = document.getElementsByTagName('canvas')[0];
const context = canvas.getContext('2d');
context.fillStyle = 'black';
context.fillRect(0, 0, 320, 178);

const width = 18;

function prrow(seed, frame, nextgen) {
    if (frame)
        setTimeout(prrow, 40, seed, frame-1, nextgen);
    else
        setTimeout(nextgen, 40);
    context.drawImage(canvas, 0, -1);
    context.fillStyle = 'rgb(190,173,81)';
    context.fillRect(0, 177, 320, 1);
    context.fillStyle = 'black';
    for (let i=1; i<=width; i++) {
      if (seed & 1)
        context.fillRect(16*i, 177, 16, 1);
      seed >>= 1;
    }
}

// initialize

let sets = [];
let cells = [];
for (let col=0; col < width; col++) {
    sets[col+1] = 1 << col;
    cells[col] = col + 1;
}

let verticals = 1 << (Math.random() * width);
prrow(verticals, 16, rowgen1);

function rowgen1() {
    function merge(a, b) {
        let id_a = cells[a];
        let id_b = cells[b];
        if (id_a == id_b)
            return;

        sets[id_a] |= sets[id_b];
        for (let col=0; col < width; col++) {
            if (sets[id_b] & 1)
                cells[col] = id_a;
            sets[id_b] >>= 1;
        }
    }

    for (let col = 0; col < width-2; col++) {
        if ((cells[col] != cells[col+2]) && (Math.random() < 0.5) && !(verticals & (1<<(col+3)))) {
            merge(col, col+1);
            merge(col+1, col+2);
        } else if ([(verticals & (1<<col)) && (verticals & (1<<(col+2))), !(verticals & (1<<(col+1)))][+(cells[col] != cells[col+2])]) {
            col++;
            let id = cells[col];
            cells[col] = 0;
            sets[id] ^= 1 << col;
        }
    }
    for (let col = 0; col < width-1; col++)
        if (cells[col] && cells[col+1] && (cells[col] != cells[col+1]))
            merge(col, col+1);

    let seed = 0;
    for (let id = 1; id <= width; id++)
        seed |= sets[id];

    prrow(seed, 16, rowgen2);
}

function rowgen2() {
    verticals = 0;
    for (let id in sets) {
        let set = sets[id];
        if (!set)
            continue;

        let mask;
        do { mask = Math.random() * (1 << width); }
        while (!(set & mask));
        set &= mask;
        verticals |= set;
        sets[id] = set;
    }
    for (let col = 0; col < width; col++) {
        if (!(verticals & (1<<col))) {
            let id = sets.indexOf(0);
            sets[id] = 1 << col;
            cells[col] = id;
        }
    }
    prrow(verticals, 16, rowgen1);
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.