### 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.

```// 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

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 = [];
}
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);
}
```