const gridSize = 8; //min=5 max=20 step=1
const gridMargin = -18; //min=-50 max=50 step=1
const shapePoints = 16; //min=4 max=30 step=2
const pointDistance = .24; //min=0 max=3 step=.01
const shapeSize = 1.22; //min=.01 max=10 step=.01
const shapeRotation = 0; //min=0 max=360 step=1

// You can find the Turtle API reference here: https://turtletoy.net/syntax
Canvas.setpenopacity(1);

// Global code will be evaluated once.
const turtle = new Turtle();
const grid = (new Grid(gridSize, 0, 200 - gridMargin - gridMargin));

const gridIterator = grid.iterator();

const template = Array
    .from({length: shapePoints})
    .map((v, i, a) => 
        [[
            (i%2 == 0? 1: 1-pointDistance) * shapeSize,
            2 * Math.PI * i / (a.length) + Math.PI * shapeRotation / 180
        ]].map(b => [b[0] * Math.sin(b[1]), b[0] * -Math.cos(b[1])]).pop())
    .map(pt => scale2(pt, grid.cellSize / 2))

function walk(i) {
    const cellItem = gridIterator.next();
    if(cellItem.done) return false;
    
    template.forEach((pt, i, a) => {
        turtle.jump(add2(cellItem.value.center, pt));
        turtle.goto(add2(cellItem.value.center, a[(i+1)%a.length]));
    });

    return true;
}

////////////////////////////////////////////////////////////////
// Square Grid utility code - Created by Jurgen Westerhof 2023
// https://turtletoy.net/turtle/4633bef396
////////////////////////////////////////////////////////////////
function Grid(size, spacing, canvasSize = 200, location = [0, 0], cellProperties = {}) {
    function add2(a, b) { return [a[0]+b[0], a[1]+b[1]]; }
    class Grid {
        constructor(size, spacing, canvasSize, location, cellProperties) {
            this.size = size;this.spacing = spacing;this.cellProperties = cellProperties;this.iterateMax = this.size**2 - 1;
            this.canvasSize = canvasSize;this.location = location;this.cellSize = (Math.max(0.1, (canvasSize - (size-1)*spacing)) / size);
        }
        getCellByIndex(i) {const col = i % this.size;const row = i / this.size | 0;return this.getCellByCoord(col, row);}
        getCellByCoord(col, row) {const vertice = (i) => (i + .5) * this.cellSize + i * this.spacing - this.canvasSize / 2;return {center: add2(this.location, [vertice(col), vertice(row)]),column: col,row: row,index: row * this.size + col,size: this.cellSize,spacing: this.spacing,properties: this.cellProperties,};}
        *iterator() {for(let i = 0; i <= this.iterateMax; i++) {yield this.getCellByIndex(i);}}
    }
    return new Grid(size, spacing, canvasSize, location, cellProperties);
}

////////////////////////////////////////////////////////////////
// 2D Vector Math utility code - Created by several Turtletoy users
////////////////////////////////////////////////////////////////
function norm2(a) { return scale2(a, 1/len2(a)); }
function add2(a, b) { return [a[0]+b[0], a[1]+b[1]]; }
function sub2(a, b) { return [a[0]-b[0], a[1]-b[1]]; }
function mul2(a, b) { return [a[0]*b[0], a[1]*b[1]]; }
function scale2(a, s) { return mul2(a, [s,s]); }
function lerp2(a,b,t) { return [a[0]*(1-t) + b[0]*t, a[1]*(1-t) + b[1]*t]; }
function lenSq2(a) { return a[0]**2+a[1]**2; }
function len2(a) { return Math.sqrt(lenSq2(a)); }
function rot2(a) { return [Math.cos(a), -Math.sin(a), Math.sin(a), Math.cos(a)]; }
function trans2(m, a) { return [m[0]*a[0]+m[2]*a[1], m[1]*a[0]+m[3]*a[1]]; } //Matrix(2x1) x Matrix(2x2)
function dist2(a,b) { return Math.hypot(...sub2(a,b)); }
function dot2(a,b) { return a[0]*b[0]+a[1]*b[1]; }
function cross2(a,b) { return a[0]*b[1] - a[1]*b[0]; }
function multiply2(a2x2, a) { return [(a[0]*a2x2[0])+(a[1]*a2x2[1]),(a[0]*a2x2[2])+(a[1]*a2x2[3])]; } //Matrix(2x2) x Matrix(1x2)
function intersect_info2(as, ad, bs, bd) {
    const d = [bs[0] - as[0], bs[1] - as[1]];
    const det = bd[0] * ad[1] - bd[1] * ad[0];
    if(det === 0) return false;
    const res = [(d[1] * bd[0] - d[0] * bd[1]) / det, (d[1] * ad[0] - d[0] * ad[1]) / det];
    return [...res, add2(as, scale2(ad, res[0]))];
}
function intersect_ray2(a, b, c, d) {
    const i = intersect_info2(a, b, c, d);
    return i === false? i: i[2];
}
function segment_intersect2(a,b,c,d, inclusive = true) {
    const i = intersect_info2(a, sub2(b, a), c, sub2(d, c));
    if(i === false) return false;
    const t = inclusive? 0<=i[0]&&i[0]<=c&&0<=i[1]&&i[1]<=1: 0<i[0]&&i[0]<1&&0<i[1]&&i[1]<1;
    return t?i[2]:false;
}
function eq2(a,b) { return a[0]==b[0]&&a[1]==b[1]; }
function clamp2(a, tl, br) { return [Math.max(Math.min(br[0], a[0]), tl[0]), Math.max(Math.min(br[1], a[1]), tl[1])]; }