xxxxxxxxxx
129
/**
* Made by Koei Ural - @KoeiUral
*
* Inspired by The Coding Train (Daniel Shiffman): https://youtu.be/Ggxt06qSAe4
* Color palette by Daniel Shiffman: https://editor.p5js.org/codingtrain/sketches/1w8yOaaDS
*
* Implementation of N-color Wolfram CA with totalistic rule
* Reference: New Kind of Science (https://www.wolframscience.com/nks/p66--more-cellular-automata/)
*
*/
const DEFAULT_W = 640;
const DEFAULT_H = 480;
const CHANGE_PROB = 0.04;
const MIN_SIZE = 4;
const MAX_SIZE = 10;
const MIN_DEPTH = 3;
const MAX_DEPTH = 7;
let cellSize = 0 ;
let colorDepth = 0;
let ruleSet;
let cellList = [];
let history = [];
let palette = [];
let cols;
let x, y;
let len;
function initCellList() {
// Init the cell size and color depth accoring to min max
cellSize = floor(random(MIN_SIZE, MAX_SIZE));
colorDepth = floor(random(MIN_DEPTH, MAX_DEPTH));
// Compute the number of cells in canvas w.
let cellNbr = floor(DEFAULT_W / cellSize);
// Init the cell list to 0
for (let i = 0; i < cellNbr; i++) {
cellList[i] = 0;
}
// Set middle cell to a value different from 0
cellList[floor(cellNbr / 2)] = floor(random(1, colorDepth));
// Compute rule value and set
let ruleValue = floor(random(pow(colorDepth, colorDepth * 3 - 2)));
ruleSet = ruleValue.toString(colorDepth).padStart(colorDepth * 3 - 2, "0");
// Debug info
console.log("Cell Size:" + cellSize + " Color Depth:" + colorDepth +" Rule:" + ruleValue);
}
function setup() {
// Create the P5 Canvas
canvas = createCanvas(DEFAULT_W, DEFAULT_H);
noStroke();
// Coding Train Color Palette :-)
palette = [color(11, 106, 136), color(25, 297, 244), color(112, 50, 126),
color(146, 83, 161), color(164, 41, 99), color(236, 1, 90),
color(240, 99, 164), color(241, 97, 100), color(248, 158, 79)
];
// Shuffle the color palette
shuffle(palette, true);
// Init the Automata paramters
initCellList();
}
function draw() {
// Store last cell row in history
history.push(cellList);
// Change rule
if (random(1) < CHANGE_PROB) {
let ruleValue = floor(random(pow(colorDepth, colorDepth * 3 - 2)));
ruleSet = ruleValue.toString(colorDepth).padStart(colorDepth * 3 - 2, "0");
cellList[floor(cellList.length / 2)] = floor(random(1, colorDepth));
console.log("New Rule:" + ruleValue);
}
// Check if bottom reached
cols = height / cellSize;
if (history.length > cols + 1) {
history.splice(0, 1);
}
// Display history
background(0);
y = 0;
for (let cells of history) {
x = 0;
for (let i = 0; i < cells.length; i++) {
x += cellSize;
if (cells[i] != 0) {
fill(palette[cells[i]]);
square(x, y, cellSize);
}
}
// Move to the next row.
y += cellSize;
}
// Prepare an array for the next generation of cells.
let nextCells = [];
// Iterate over each cell to calculate its next state.
len = cellList.length;
for (let i = 0; i < len; i++) {
// Calculate the states of neighboring cells
let left = cellList[(i - 1 + len) % len];
let right = cellList[(i + 1) % len];
let state = cellList[i];
// Create a string representing the state of the cell and its neighbors.
let sum = left + state + right;
nextCells[i] = parseInt(ruleSet[sum], colorDepth);
}
// Update the cells array for the next generation.
cellList = nextCells;
}