Published
Edited
Sep 7, 2019
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
canvas1 = {
const height = 600;
const context = DOM.context2d(width, height, 1);
context.canvas.style.imageRendering = "pixelated";
context.globalCompositeOperation = "copy";

// Initialize the first row.
let row1 = context.getImageData(0, 0, width, 1);

for (let i = 0; i < width; ++i) {
const rgba = [(i << 2) + 0, (i << 2) + 1, (i << 2) + 2, (i << 2) + 3];

const dice = Math.floor(Math.random()*3);
row1.data[rgba[3]] = 255;
row1.data[rgba[dice]] = (Math.random() < density) ? 255 : 0;

}

context.putImageData(row1, 0, 0);

let row2 = context.createImageData(width, 1);
for (let j = 1; true; ++j) {

// Read from the first row to write to the second.
for (let i = 0; i < width; ++i) {
const rgba = [(i << 2) + 0, // bitshifts indices to handle rgba image data
(i << 2) + 1,
(i << 2) + 2,
(i << 2) + 3];
row2.data[rgba[0]] = row2.data[rgba[1]] = row2.data[rgba[2]] = 0; // resets all pixels to black
row2.data[rgba[3]] = 255; // makes sure pixels are opaque

// For each cell, check its r, g and b values and get the corresponding 6 bit integers.
const L = BigInt(row1.data[((i > 0 ? i - 1 : width - 1) << 2) + 2]) ? 0b010000n // b (1 0 0)
: BigInt(row1.data[((i > 0 ? i - 1 : width - 1) << 2) + 0]) ? 0b100000n // r (2 0 0)
: BigInt(row1.data[((i > 0 ? i - 1 : width - 1) << 2) + 1]) ? 0b110000n : 0n; // g (3 0 0)
const E = BigInt(row1.data[(i << 2) + 2]) ? 0b000100n // b (0 1 0)
: BigInt(row1.data[(i << 2) + 0]) ? 0b001000n // r (0 2 0)
: BigInt(row1.data[(i << 2) + 1]) ? 0b001100n : 0n; // g (0 3 0)
const R = BigInt(row1.data[((i < width - 1 ? i + 1 : 0) << 2) + 2]) ? 0b000001n // b (0 0 1)
: BigInt(row1.data[((i < width - 1 ? i + 1 : 0) << 2) + 0]) ? 0b000010n // r (0 0 2)
: BigInt(row1.data[((i < width - 1 ? i + 1 : 0) << 2) + 1]) ? 0b000011n : 0n; // g (0 0 3)

// Match the combined input values with the ruleset
const v = matchRule(rules, (L | E | R));
// leave 0 as is and apply matched color value
if (v >= 0) row2.data[rgba[valToRGBindex(v)]] = 255;
}
// Swap the rows.
[row1, row2] = [row2, row1];

// Append until the canvas is full.
if (j < height) {
context.putImageData(row2, 0, j);
continue;
}

// Otherwise, shift the canvas up before appending the new row.
context.drawImage(context.canvas, 0, -1);
context.putImageData(row2, 0, height - 1);
yield context.canvas;
}
}
Insert cell
matchRule = function(ruleset, input) { // expects BigInt numbers to give exact results
/* Matches a given ruleset in 64 quaternaries (128 bit) to a 3 quaternaries (6 bit) input from the CA.
We can use the input to bitshift each of the logical results 1-3 to map to every possible rule combination.
These numbers can then be used as a bitmask to extract the rule-result combination out of the ruleset.
Note that:
- The input value has to be doubled to deal with quaternary results (0=00, 1=01, 2=10, 3=11)
- For results of 3=11 the bitmask will match also when only one of the 1s is found,
which is why we have to specify that the number is also divisible by 3
(maybe there is a more elegant solution to this problem).
*/
return (ruleset & (3n << input * 2n)) > 0n && (ruleset & (3n << input * 2n)) % 3n === 0n ? 3
: (ruleset & (2n << input * 2n)) > 0n ? 2
: (ruleset & (1n << input * 2n)) > 0n ? 1 : 0;
}
Insert cell
mutable rules_pre = 69783526441283310724926519385286465857n
/*
Nice examples:
69783526441283310724926519385286465857n
139805693759885363348928255353784661112n
Feel free to comment if you find something interesting, I'd love to take a look. (:
*/
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more