Truchet tiles 📐

There are only 2 type of tiles (or 3 if you enable crossing lines) randomly placed on a grid.
Didn't realize this is also some kind of maze generator :)

---

Update: added a barrel transform on top of everything to make it more impressive.

Log in to post a comment.

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

function Barrel(b) { return p => { let s = (1+(p[0]**2 + p[1]**2)*b/1e4); return [p[0]*s, p[1]*s]; } }
function Scale(s) { return p => [p[0]*s, p[1]*s]; }
const turtle = new Tortoise();

const gridX = 15; // min=3, max=40, step=1
const gridY = 20; // min=3, max=40, step=1
const density = 8; // min=1, max=15, step=1
const INNER = 2; // min=0, max=5, step=1
const CROSSING_LINES = 0; // min=0, max=1, step=1
const NICE_CORNERS = 0; // min=0, max=1, step=1
const DRAW_GRID = 0; // min=0, max=1, step=1
const BARREL = 0.5; // min=0.0, max=2.0, step=0.001

turtle.addTransform(Scale(.85));
turtle.addTransform(Barrel(BARREL));

const sizeX = 190;
const sizeY = 190;
const offsetX = -sizeX * 0.5;
const offsetY = -sizeY * 0.5;
const tw = sizeX / gridX;
const th = sizeY / gridY;

// The walk function will be called until it returns false.
function walk(i) {
    const x = i % gridX;
    const y = i / gridX | 0;
    const totalTypes = CROSSING_LINES ? 3 : 2;
    let type = Math.random() * totalTypes | 0;
    
    if (NICE_CORNERS) {
        if (x == 0 || x == gridX-1) type = y % 2;
        if (y == 0 || y == gridY-1) type = x % 2;
        if (CROSSING_LINES) {
            if (x == 0 && (y == 0 || y == gridY-1) || x == gridX-1 && (y == 0 || y == gridY-1)) type = 2;
        }
    }
    tile(x,y, type);
    return i < gridX * gridY - 1;
}

function tile(x, y, type) {
    const left = x * tw;
    const top = y * th;
    const right = left + tw;
    const bottom = top + th;
    
    if (DRAW_GRID) rect(left, top, tw, th);
    
    for(let ii = INNER, lenii = density + 2; ii < lenii - (INNER/2|0); ii ++) {
        var r = ii/lenii;
        switch (type) {
            case 0:
                /*
                   ╱╱╱
                */
                line([lerp(left,right,r), bottom], [right, lerp(top,bottom,r)]);
                line([lerp(left,right,r), top], [left, lerp(top,bottom,r)]);
                break;
            case 1:
                /*
                    ╲╲╲
                */
                line([lerp(left,right,1-r), bottom], [left, lerp(top,bottom,r)]);
                line([lerp(left,right,1-r), top], [right, lerp(top,bottom,r)]);
                break;
            case 2:
                /*
                    ╬╬╬
                */
                line([left, lerp(top,bottom,r)], [right, lerp(top,bottom,r)]);
                line([lerp(left,right,r), top], [lerp(left,right,r), bottom]);
                break;
        }
    }
}

function line(a, b) {
    turtle.jump(a[0]+offsetX, a[1]+offsetY);
    turtle.goto(b[0]+offsetX, b[1]+offsetY);
}

function rect(x, y, w, h) {
    x += offsetX;
    y += offsetY;
    turtle.jump(x, y);
	turtle.goto(x + w, y);
	turtle.goto(x + w, y + h);
	turtle.goto(x, y + h);
	turtle.goto(x, y);
}

const lerp=(a,b,t)=>a+(b-a)*t;



////////////////////////////////////////////////////////////////
// Tortoise utility code (Minimal Turtle and Transforms)
// https://turtletoy.net/turtle/102cbd7c4d
////////////////////////////////////////////////////////////////

function Tortoise(x, y) {
    class Tortoise extends Turtle {
        constructor(x, y) {
            super(x, y);
            this.ps = Array.isArray(x) ? [...x] : [x || 0, y || 0];
            this.transforms = [];
        }
        addTransform(t) {
            this.transforms.push(t);
            this.jump(this.ps);
            return this;
        }
        applyTransforms(p) {
            if (!this.transforms) return p;
            let pt = [...p];
            this.transforms.map(t => { pt = t(pt); });
            return pt;
        }
        goto(x, y) {
            const p = Array.isArray(x) ? [...x] : [x, y];
            const pt = this.applyTransforms(p);
            if (this.isdown() && (this.pt[0]-pt[0])**2 + (this.pt[1]-pt[1])**2 > 4) {
               this.goto((this.ps[0]+p[0])/2, (this.ps[1]+p[1])/2);
               this.goto(p);
            } else {
                super.goto(pt);
                this.ps = p;
                this.pt = pt;
            }
        }
        position() { return this.ps; }
    }
    return new Tortoise(x,y);
}