Only one problem when you change from white to black lines it randomly redraws the grid.
"Vibe Code" using ChatGPT (it works but took 2 hours of prompting)
Inspired by: machine.arm sketch 149
instagram.com/p/dawupp4ybsn/
Log in to post a comment.
// Architecture 002 — Nested Rectangles + colored connecting lines
// 10 November 2025
const opacity = 1;
Canvas.setpenopacity(opacity);
const turtle = new Turtle();
// ===== PARAMETERS =====
const parentMinX = -95;
const parentMaxX = 95;
const parentMinY = -95;
const parentMaxY = 95;
const canvasW = parentMaxX - parentMinX;
const canvasH = parentMaxY - parentMinY;
const baseCols = 8;
const baseRows = 8;
const mergeChance = 0.45;
const parentCellMinWidth = 20;
const parentCellMaxWidth = 80;
const parentCellMinHeight = 15;
const parentCellMaxHeight = 60;
const minInset = 0.1;
const maxInset = 0.3;
const innerMinWidth = 5;
const innerMaxWidth = 60;
const innerMinHeight = 5;
const innerMaxHeight = 60;
const innerPaddingX = 10;
const innerPaddingY = 10;
const connectorLines = 15; // min=1 max=50 step=1
// ===== DRAW MODE =====
const drawmode = 2; // min=0, max=2, step=1, (Black Lines, White Lines, Both)
// ===== GRID SETUP =====
function randomProportions(n) {
let vals = Array.from({ length: n }, () => 0.5 + Math.random());
const sum = vals.reduce((a, b) => a + b, 0);
return vals.map(v => v / sum);
}
const colWeights = randomProportions(baseCols);
const rowWeights = randomProportions(baseRows);
const colWidths = colWeights.map(w => w * canvasW);
const rowHeights = rowWeights.map(h => h * canvasH);
let colX = [parentMinX];
for (let i = 0; i < baseCols; i++) colX.push(colX[i] + colWidths[i]);
let rowY = [parentMinY];
for (let j = 0; j < baseRows; j++) rowY.push(rowY[j] + rowHeights[j]);
let filled = Array.from({ length: baseRows }, () => Array(baseCols).fill(false));
// ===== DRAW CELLS =====
for (let r = 0; r < baseRows; r++) {
for (let c = 0; c < baseCols; c++) {
if (filled[r][c]) continue;
// Merge cells
let mergeW = 1;
let mergeH = 1;
if (Math.random() < mergeChance && c < baseCols - 1 && !filled[r][c + 1]) mergeW = 2;
if (Math.random() < mergeChance && r < baseRows - 1 && !filled[r + 1][c]) mergeH = 2;
if (c + mergeW > baseCols) mergeW = 1;
if (r + mergeH > baseRows) mergeH = 1;
// Constrain size
const tempX2 = colX[c + mergeW];
const tempY2 = rowY[r + mergeH];
const tempWidth = tempX2 - colX[c];
const tempHeight = tempY2 - rowY[r];
if (tempWidth < parentCellMinWidth || tempWidth > parentCellMaxWidth) mergeW = 1;
if (tempHeight < parentCellMinHeight || tempHeight > parentCellMaxHeight) mergeH = 1;
// Mark cells filled
for (let rr = r; rr < r + mergeH; rr++) {
for (let cc = c; cc < c + mergeW; cc++) {
filled[rr][cc] = true;
}
}
// Parent rectangle
const x1 = colX[c];
const x2 = colX[c + mergeW];
const y1 = rowY[r];
const y2 = rowY[r + mergeH];
rectangle(x1, y1, x2, y2);
// ===== CHILD RECTANGLE =====
const w = x2 - x1;
const h = y2 - y1;
const insetFrac = minInset + Math.random() * (maxInset - minInset);
const maxInnerWByInset = w * (1 - insetFrac);
const maxInnerHByInset = h * (1 - insetFrac);
const maxInnerW = Math.min(innerMaxWidth, maxInnerWByInset, w - 2 * innerPaddingX);
const maxInnerH = Math.min(innerMaxHeight, maxInnerHByInset, h - 2 * innerPaddingY);
const randInnerW = innerMinWidth + Math.random() * Math.max(0, maxInnerW - innerMinWidth);
const randInnerH = innerMinHeight + Math.random() * Math.max(0, maxInnerH - innerMinHeight);
const ix1 = x1 + innerPaddingX + Math.random() * (w - randInnerW - 2 * innerPaddingX);
const iy1 = y1 + innerPaddingY + Math.random() * (h - randInnerH - 2 * innerPaddingY);
const ix2 = ix1 + randInnerW;
const iy2 = iy1 + randInnerH;
rectangle(ix1, iy1, ix2, iy2);
// ===== CONNECT CHILD TO PARENT =====
connectChildToParent(x1, y1, x2, y2, ix1, iy1, ix2, iy2, connectorLines, drawmode);
}
}
// ===== FUNCTIONS =====
function rectangle(xA, yA, xB, yB) {
turtle.penup();
turtle.goto(xA, yA);
turtle.pendown();
turtle.goto(xB, yA);
turtle.goto(xB, yB);
turtle.goto(xA, yB);
turtle.goto(xA, yA);
}
// Connect child rectangle to parent edges with colored lines
function connectChildToParent(px1, py1, px2, py2, cx1, cy1, cx2, cy2, lines, drawmode) {
// TOP EDGE → White
if (drawmode === 1 || drawmode === 2) {
for (let i = 0; i <= lines; i++) {
const t = i / lines;
const childX = cx1 + t * (cx2 - cx1);
turtle.penup();
turtle.goto(childX, cy1);
turtle.pendown();
const parentX = px1 + t * (px2 - px1);
turtle.goto(parentX, py1);
}
}
// RIGHT EDGE → White
if (drawmode === 1 || drawmode === 2) {
for (let i = 0; i <= lines; i++) {
const t = i / lines;
const childY = cy1 + t * (cy2 - cy1);
turtle.penup();
turtle.goto(cx2, childY);
turtle.pendown();
const parentY = py1 + t * (py2 - py1);
turtle.goto(px2, parentY);
}
}
// BOTTOM EDGE → Black
if (drawmode === 0 || drawmode === 2) {
for (let i = 0; i <= lines; i++) {
const t = i / lines;
const childX = cx1 + t * (cx2 - cx1);
turtle.penup();
turtle.goto(childX, cy2);
turtle.pendown();
const parentX = px1 + t * (px2 - px1);
turtle.goto(parentX, py2);
}
}
// LEFT EDGE → Black
if (drawmode === 0 || drawmode === 2) {
for (let i = 0; i <= lines; i++) {
const t = i / lines;
const childY = cy1 + t * (cy2 - cy1);
turtle.penup();
turtle.goto(cx1, childY);
turtle.pendown();
const parentY = py1 + t * (py2 - py1);
turtle.goto(px1, parentY);
}
}
}