### Mutated concentric circles

This didn't come out like it looked in my head, but it's sort of fun anyway.
Interesting variations:
- Mutated concentric circles (variation)
- Mutated concentric circles (variation)
- Mutated concentric circles (variation)

```// LL 2021

const iterations = 200; // min=1 max=1000 step=1
const inner_size = 10; // min=1 max=100 step=1
const point_count = 300; // min=10 max=1000 step=1
const loop_count = 20;  // min=0 max=20 step=1
const grow_fract = -50; // min=-101 max=1000 step=1
const spread = 1; // min=0 max=100 step=1
const mult = 2; // min=1 max=20 step=.01
const use_max = 1; // min=0 max=1 step=1 (No,Yes)
const seed = 0; // min=0 max=100 step=1
const style = 0; // min=0 max=1 step=1 (Lines (fast),Polygons (slow))

Canvas.setpenopacity(1);

const turtle = new Turtle();

function walk(i) {
if (i==0) {
rng = new RNG(seed);
polygons = new Polygons();
circle = new Circle(inner_size, point_count);
circle_max = circle.dup();
}

const a = i * Math.PI/2 / Math.max(1, iterations-1);
const d = 0; //1;

//if (i==1)
circle.draw(a, d, circle_max);

const more_to_draw = circle.mutate();
if (!more_to_draw) return false;

circle_max.recordMax(circle);

//sleep(100);

return i + 1 < iterations;
}

class Circle {
constructor(size, count, points=undefined) {
this.size = size;
this.count = count;

if (points === undefined) {
this.points = [];
const astep = Math.PI * 2 / this.count;
for (var i=0, a=0; i<this.count; i++, a+=astep) {
const x = size * Math.cos(a);
const y = size * Math.sin(a);
this.points.push(x); // ,y);
this.points.push(y);
}
} else {
this.points = [...points];
}
}

dup() {
return new Circle(this.size, this.count, this.points);
}

recordMax(circle) {
for (var i=0; i<this.points.length && i<circle.points.length; i++) {
this.points[i] = smax(this.points[i], circle.points[i]);
}
}

draw(a, d, circle_max) {
const points = [];
for (var i=0; i<this.count && i<circle_max.count; i++) {
var x = this.points[i*2+0];
var y = this.points[i*2+1];
if (use_max) {
x = smax(x, circle_max.points[i*2+0]);
y = smax(y, circle_max.points[i*2+1]);
}
points.push([x, y]);
}
drawPoints(points, a, d);
}

mutate() {
var more_to_draw = loop_count < 1;

const grow = 1 + grow_fract / 1000;
for (var i = 0; i < this.points.length; i++) {
this.points[i] *= grow;
}

for (var loop = 0; loop < loop_count; loop++) {
const index = (this.count * rng.nextFloat()) | 0;
this.points[index * 2 + 0] *= mult;
this.points[index * 2 + 1] *= mult;

const new_points = [...this.points];
for (var i = 0; i < this.count; i++) {
const this_len = Math.hypot(this.points[i * 2], this.points[i * 2 + 1]);
var total_len = 0;
var len_count = 0;
const ii = (i + this.points.length + j) % (this.count);
total_len += Math.hypot(this.points[ii * 2], this.points[ii * 2 + 1]);;
}
const nlen = total_len / len_count;
const factor = nlen / this_len;
new_points[i*2+0] *= factor;
new_points[i*2+1] *= factor;

more_to_draw |= Math.abs(new_points[i*2]) < 100 && Math.abs(new_points[i*2+1]) < 100 && Math.abs(new_points[i*2]) > 1 && Math.abs(new_points[i*2+1]) > 1;
}
this.points = new_points;
}

return more_to_draw;
}
}

function smax(v1, v2) {
const v = Math.max(Math.abs(v1), Math.abs(v2)) * Math.sign(v1);
return v;
}

function sleep(ms) { start=Date.now(); while (Date.now()-start<ms); }

// Random with seed
function RNG(t){return new class{constructor(t){this.m=2147483648,this.a=1103515245,this.c=12345,this.state=t||Math.floor(Math.random()*(this.m-1))}nextFloat(){return this.state=(this.a*this.state+this.c)%this.m,this.state/(this.m-1)}}(t)}

function drawPoints(points, hatching_angle = 0, hatching_distance = 0) {
if (style == 0) {
turtle.jump(points[points.length-1]);
points.forEach(p=>turtle.goto(p));
} else {
const p1 = polygons.create();