['#000F08', '#136F63', '#E0CA3C'];
const aspect_ratio = 9 / 11
if (windowWidth > windowHeight) {
createCanvas(aspect_ratio * windowHeight, windowHeight, SVG);
createCanvas(windowWidth, windowWidth / aspect_ratio, SVG);
function rule_length(num_states, neighbourhood_size) {
return pow(num_states, neighbourhood_size);
function generate_rule(num_states, neighbourhood_size) {
const length = rule_length(num_states, neighbourhood_size);
return Array.apply(null, Array(length)).map(() => floor(random() * num_states));
function next_state(num_states, rule, neighbourhood) {
const state = neighbourhood
.map((state) => state.toString())
.reduce((acc, val) => val + acc)
const index = parseInt(state, num_states);
function rule_to_int(rule, base) {
return parseInt(rule.reduce((str, x) => x.toString() + str), base);
function int_to_rule(num, base, rule_length) {
let rule = num.toString(base);
rule= Array.from({...rule,length:rule_length}, (v,i) => parseInt(v ?? '0') );
RULE = generate_rule(BASE, 3);
const margin = floor((width - (square_size * grid_x)) / 2);
const grid_y = floor((height - (2 * margin)) / square_size);
translate(margin, margin);
scale(square_size, square_size);
let curr_state = Array.apply(null, Array(grid_x)).map(() => floor(random() * BASE));
let new_state = Array.apply(null, Array(grid_x)).map(() => 0);
for (let y = 0; y < grid_y; y++) {
for (let x = 0; x < grid_x; x++) {
const left_index = (x - 1) < 0 ? grid_x - 1 : (x - 1);
const right_index = (x + 1) % grid_x;
const curr = curr_state[x];
const neighbourhood = [curr_state[left_index], curr, curr_state[right_index]];
const next = next_state(BASE, RULE, neighbourhood);
fill(palette[curr % palette.length]);
curr_state = [...new_state];
save(`3s1d_${rule_to_int(RULE, BASE)}`);