xxxxxxxxxx
116
let pg;
let currentGen;
let cellSize = 1; // Size of each cell (rect)
let cols, rows;
let gen = 0;
let rulesets = [
[30], // Rule 30 (Chaotic)
[90], // Rule 90 (Symmetric)
[110], // Rule 110 (Complexity edge)
[150], // Rule 150 (Checkerboard)
[10], [111], [82], [113], [23], [91], [1], [2], [122], [0], [0], [0]
];
let noiseScale = 0.0018; // Scale for Perlin noise
function setup() {
createCanvas(512, 1024);
cols = width / cellSize;
rows = height / cellSize;
pg = createGraphics(width, height);
currentGen = new Array(cols);
reset();
// Create buttons
let resetButton = createButton('Reset & Shuffle');
resetButton.position(10, height + 20);
resetButton.mousePressed(() => {
shuffleRulesets();
reset();
});
let saveButton = createButton('Save as JPG');
saveButton.position(120, height + 20);
saveButton.mousePressed(() => {
save(pg, 'cellular_automata.jpg');
});
}
function draw() {
// Display the buffer
image(pg, 0, 0);
if (gen < rows) {
generateNextGen();
}
}
function reset() {
// Clear PGraphics and start a new automaton
pg.background(0);
noiseSeed(int(random(213213141)));
// Initialize the first generation with random values (0 or 1)
for (let i = 0; i < cols; i++) {
currentGen[i] = int(random(2)); // Randomly choose 0 or 1
}
gen = 0;
drawGen(); // Draw the first generation
}
function drawGen() {
for (let i = 0; i < cols; i++) {
if (currentGen[i] == 1) {
pg.fill(255 - random(5));
} else {
pg.fill(random(5));
}
pg.noStroke();
pg.rect(i * cellSize, gen * cellSize, cellSize, cellSize);
}
}
function generateNextGen() {
let nextGen = new Array(cols);
for (let i = 1; i < cols - 1; i++) {
let left = currentGen[i - 1];
let center = currentGen[i];
let right = currentGen[i + 1];
// Use Perlin noise to select a ruleset based on position
let noiseVal = noise(i * noiseScale, gen * noiseScale * 0.94);
// Quantize noise into 4 discrete steps
//noiseVal = round(noiseVal * 8) / 8.0;
// play with this
//noiseVal *= sin(noiseVal * 12.8132 - gen * 0.013 * sin(i * 0.017031) * 0.96) * 0.5 + 0.5;
let selectedRule = int(map(noiseVal, 0, 1, 0, rulesets.length - 1));
nextGen[i] = applyRule(left, center, right, rulesets[selectedRule][0]);
}
currentGen = nextGen;
gen++;
drawGen();
}
function applyRule(a, b, c, rule) {
let bits = "" + a + b + c;
let index = parseInt(bits, 2);
return (rule >> index) & 1;
}
// Shuffle the rulesets array
function shuffleRulesets() {
for (let i = rulesets.length - 1; i > 0; i--) {
let j = int(random(i + 1));
let temp = rulesets[i];
rulesets[i] = rulesets[j];
rulesets[j] = temp;
}
}