Tiles
Wang tile laboratory.
Edit a tile set, pick a solver, and watch the backtracking search play back step by step.
How this works
This is a Wang tile laboratory: a Wang tile is a square (or hex/triangle/cube face) whose edges each carry a label. Two tiles may sit next to each other only when the labels on their touching edges match exactly -- any text works as a label (letters, numbers, or a shared placeholder like x for edges you want to freely match within your own tile set). Define a tile set as text below, pick a grid size, and the panel searches for a way to fill the grid so every shared edge matches.
Directed matching (square lattice only, #415): a label ending in ! (produces) or ? (requires) matches only its OPPOSITE polarity with the same base label -- Plan! matches Plan?, but never another Plan! or another Plan?. Plain, unsuffixed labels keep working exactly as before (equality); mixing a suffixed edge against a plain one on the same shared border never matches. Purely opt-in, one edge label at a time -- "load example" below has a small hand-authored pipeline showing it in use (#416; illustrative composition patterns, not aperiodic tile sets like "load preset"'s own corpus).
Notation depends on the lattice: square tiles are id N E S W (edge labels clockwise from north); hexagonal tiles are id e0 e1 e2 e3 e4 e5 (E, NE, NW, W, SW, SE); triangular tiles are id left right top bottom (an up- or down-pointing triangle only uses 3 of its 4 declared edges); cube tiles are id N S E W U D (the six face labels); corner-matched square tiles are id NE SE SW NW (4 CORNER labels instead of 4 edges -- two tiles match by agreeing on a shared corner, constraining diagonal neighbors too, not just orthogonal ones; see #388); linear (1D) tiles are id left right (only 2 edges -- a labeled domino placed in a single row; see #397).
Solver (square lattice): "Backtracking" places tiles left-to-right, top-to-bottom, checking each new tile against its already-placed neighbors, and backtracks out of dead ends -- turn on "Animate step by step" to watch the search happen. "Backtracking (torus/periodic)" additionally requires the grid to wrap edge-to-edge. "SAT cross-check" solves the same constraints with an independent SAT solver, as a check on the backtracking result. "Weighted random" (#398) is the same backtracking search, but tries each cell's compatible candidates in a weighted-random order instead of tile-array order -- set each tile's own weight in the palette above (higher = tried first more often) and a seed for reproducibility; it still finds a tiling whenever one exists, since weights only affect search order, never completeness. Symmetry expands every tile into its rotated/reflected variants before solving, so a tile set stays small to write but can be used in any orientation -- except a tile whose id ends in * (e.g. A*, square lattice only, #414), which stays orientation-locked at its drawn orientation even while the rest of the set expands, for a tile whose specific facing is meaningful and shouldn't be treated as interchangeable with its own rotations/reflections.
Below the grid (square lattice only): Entropy estimates -- via the transfer-matrix method -- how many distinct valid tilings exist per cell on average (higher = more freedom, near zero = a highly constrained tile set). Patch census counts how many distinct patches of each size actually occur in the solved grid -- the finite-size "language" entropy is itself derived from as a growth-rate limit. Diffraction/autocorrelation treat "where does tile X appear in the solved grid" as a pattern and plot its frequency spectrum and self-similarity: periodic tilings show sharp peaks, disordered ones show a diffuse cloud. Differentiable relaxation is an experimental alternate solver that optimizes a soft tile assignment via gradient descent instead of backtracking search, to see whether it converges to a valid tiling.
The linear (1D) lattice's own entropy readout is EXACT, not an approximation -- unlike the square lattice's strip-height transfer-matrix estimate above (which only converges to the true 2D entropy as strip height grows), a 1D tile chain's tile-to-tile adjacency IS already the full transfer relation, solog(dominant eigenvalue) is the whole answer, with no strip-height normalization needed.
Solve for a tiling to see its patch census.
Spectrum (log-scaled, DC centered)
Autocorrelation surface (zero-lag centered)
Solve for a tiling to see its diffraction pattern.