Vitruvian Man (extreme closeup)

A continuous-valued cellular automaton that randomly mutates and grows.

Log in to post a comment.

Canvas.setpenopacity(0.5);

const divs = 16;
const iters = 70*divs*divs;
const size = 2.125;
const mutationChance = 1/1000;
const majorMutationChance = 1/10000;
const randomGrowthFactor = 0.00125;
const mults = [
    [.075, .125, .075],
    [.125,  .2,  .125],
    [.075, .125, .075],
];

const turtle = new Turtle();
const minRadius = 0.5;
const maxRadius = 200/divs/2;
const extRadius = maxRadius-minRadius;
let state = [...Array(divs)].map(_ => [...Array(divs)].map(_ => Math.random()));
let ix = 0, iy = 0, step = 0;

function walk(i) {
    turtle.penup();
    turtle.goto(-100 + ix*2*maxRadius + maxRadius, -100 + iy*2*maxRadius + maxRadius - size*state[ix][iy]*extRadius - minRadius);
    turtle.pendown();
    turtle.circle(minRadius + size*state[ix][iy]*extRadius, 360, 40);
    ix++;
    if (ix===divs) {
        iy++;
        ix = 0;
    }
    if (iy===divs) {
        iy = 0;
        let newState = [...Array(divs)].map(_ => [...Array(divs)].map(_ => 0));
        for (let x = 0; x < divs; x++) {
            for (let y = 0; y < divs; y++) {
                if (Math.random() < majorMutationChance) {
                    newState[x][y] = 5 * Math.random();
                }
                else if (Math.random() < mutationChance) {
                    newState[x][y] = Math.random();
                }
                else {
                    const xm = (divs+x-1)%divs;
                    const xp = (x+1)%divs;
                    const ym = (divs+y-1)%divs;
                    const yp = (y+1)%divs;
                    newState[x][y] = state[xm][ym] * mults[0][0]
                                   + state[x][ym]  * mults[0][1]
                                   + state[xp][ym] * mults[0][2]
                                   + state[xm][y]  * mults[1][0]
                                   + state[x][y]   * mults[1][1]
                                   + state[xp][y]  * mults[1][2]
                                   + state[xm][yp] * mults[2][0]
                                   + state[x][yp]  * mults[2][1]
                                   + state[xp][yp] * mults[2][2]
                                   + Math.random() * randomGrowthFactor;
                }
            }
        }
        step++;
        state = newState;
    }
    return i < iters;
}