About this technique →
truchet/sketch.js
// Truchet Tiles
//
// A grid of randomly-rotated tiles. Three tile types:
//   "Quarter Arcs"   — the classic Truchet: two opposite quarter-circle arcs
//   "Diagonal Lines" — a diagonal line, 10PRINT style
//   "Triangles"      — filled triangle in one corner (Smith variant)
//
// Random seed is fixed from p.randomSeed() on setup so each build is stable.

export const PARAMS = {
  cellSize: { value: 60, min: 20, max: 200, step: 5, label: "Cell Size", folder: "Structure", rebuildOnChange: true },
  pattern:  { value: "Quarter Arcs", options: ["Quarter Arcs", "Diagonal Lines", "Triangles"], label: "Tile Type", folder: "Structure" },
  fg:       { value: "#e8d8a8", type: "color", label: "Lines", folder: "Appearance" },
  bg:       { value: "#1c1c1c", type: "color", label: "Background", folder: "Appearance" },
  strokeW:  { value: 5, min: 1, max: 24, step: 0.5, label: "Stroke Width", folder: "Appearance" },
};

export function sketchSetup(p, w, h) {
  p.randomSeed(42);
  return {};
}

export function sketchDraw(p, w, h, params) {
  // Re-seed every draw for deterministic results
  p.randomSeed(42);

  const cs  = params.cellSize;
  const cols = Math.ceil(w / cs) + 1;
  const rows = Math.ceil(h / cs) + 1;

  p.background(params.bg);
  p.stroke(params.fg);
  p.strokeWeight(params.strokeW);
  p.noFill();

  for (let row = 0; row < rows; row++) {
    for (let col = 0; col < cols; col++) {
      const rot = Math.floor(p.random(4)); // 0..3 rotations of 90°
      const x = col * cs;
      const y = row * cs;

      p.push();
      p.translate(x + cs / 2, y + cs / 2);
      p.rotate((p.HALF_PI) * rot);

      if (params.pattern === "Quarter Arcs") {
        // Two quarter-circle arcs from opposite corners
        // Arc from bottom-left corner (rotated frame: -cs/2, cs/2)
        p.arc(-cs / 2, cs / 2, cs, cs, -p.HALF_PI, 0);
        // Arc from top-right corner
        p.arc(cs / 2, -cs / 2, cs, cs, p.PI, p.PI + p.HALF_PI);
      } else if (params.pattern === "Diagonal Lines") {
        // Single diagonal line corner to corner
        p.line(-cs / 2, -cs / 2, cs / 2, cs / 2);
      } else {
        // Triangles: filled triangle in bottom-left corner (Smith variant)
        p.fill(params.fg);
        p.triangle(-cs / 2, -cs / 2, cs / 2, -cs / 2, -cs / 2, cs / 2);
        p.noFill();
      }

      p.pop();
    }
  }
}