Scripts
Node scripts run from the command line rather than in the browser. Scripts for the Bricks investigation are on Brick Scripts.
Findings & Puzzle Data Management
puzzle-cli.js— An interactive terminal version of Puzzle Design plus Solve: pick a piece supply, constraints, a board (from the board library, or drawn by hand) and a title, save the puzzle tofindings/as JSON, and solve it, with solutions drawn as colored grids. Flat puzzles go to the fast solver; anything else runs the general solver, which Ctrl-C stops early. Pass a saved puzzle's key or JSON path to open it, and add--solveto solve it and exit.cache-loop-solutions.js— Solves the Loop puzzle (unlimited copies of one piece on a square floor, allowed to stack upward) for each of its pieces (VLL, 1x2x3, APL, PQA, L+3, PQO, VPL, PQR, PLR+, P, L, A, T, P2, L2, A2, T2, LLR, V2, VVV, R+3, V2P, BAV, G, G2, Tx, Tx2, Y, Y2, K and K2; name some to redo just those) on every floor from 1x1 to 9x9 (10x10 for the BAV), and writes each size's unique solutions, in the order Solve Quickly lists them, to its own file,results/loop-solutions/<piece>/<size>.json(so the Loop page loads only the size it shows), plus an index of every size's solution count, keeping at most 1000 per size (the VLL's 7x7 has 221; the 1x2x3 passes 1000 from 5x5 up). The Loop page lets you choose a size and solution and shows it as a model with roads and trees on every piece.extend-loop-solutions.js— Scans more of the Loop puzzle's solutions for every piece and size whose search isn't finished: carries each search on from exactly where it stopped (nothing is searched twice), for another 1000 new solutions by default (--chunk N;--minutes Mcaps each size's search, 5 by default;--size 9x9or piece names narrow it down), colors and scores them, and keeps the 1000 highest-scoring of every solution scanned so far. Kept solutions keep their scan numbers, so links like?select=P_4x4_476_0still work, and the Loop page shows how far each search has got ("Solution 123 of 3000+", or "of 3456" once it's finished). Then it redoes the single loops and 2-colorability of the pieces it extended. Where each search stopped, and every solution it has found (as short hashes), is kept inresults/loop-resume/, which isn't copied to the site. A size cached before those files existed is searched again up to where it stopped the first time it's extended.color-loop-solutions.js— Works out the colors of the Loop page's piece, size, solution and rim squares ahead of time: for every cached solution and rim, runs Fix all from a bare piece and records whether it leaves unfixable problems, passes (no road meets a tree and a connected group of roads and blanks touches every piece), or neither, inresults/loop-colors.json; the page's squares are then colored by score (seescore-loop-solutions.js). It also records, per solution and rim, whether roads can make a single loop over every piece, inresults/loop-circuits.json, and whether that loop works on no other solution of the same piece, size and rim (the page marks those as unique road patterns: ★ when every layout of the size has been checked, ☆ when only some have);--circuitsredoes just that. Uses all but one CPU core and takes about half an hour for all pieces; name pieces to redo just those. Rerun it aftercache-loop-solutions.js, or after changing how the Loop stats or fixes work.score-loop-solutions.js— Scores every cached Loop solution and writesresults/loop-scores.json(with each solution's Asymmetries measurement too) for the Loop page's score line, histogram and top 10 lists: 0 unless at some rim Fix all leaves no road meeting a tree and a connected group of roads and blanks touching every piece (perresults/loop-colors.json), otherwise the Scoring rubric's score, reusingSingletonScore. Takes about 10 minutes; rerun it aftercache-loop-solutions.jsorcolor-loop-solutions.js. With--boardit only redoes each solution's Rectangle Pairs and Fault Lines measurements (for the Loop page's histogram filters), in about two minutes.solo-loop-solutions.js— For every cached Loop solution and rim with a single loop (perresults/loop-circuits.json), works out whether that loop closes up on a single piece (adding road only to faces no copy shows) and, if so, whether the piece's ground then colors in two alternating colors that never meet without a road between them on the assembled puzzle, intoresults/loop-solo.json. The Loop page's 2-colorable histogram toggle reads it. Takes under a minute; rerun it aftercolor-loop-solutions.js.unique-loop-solutions.js— For every scored Loop solution with no single loop at any rim, works out whether its road pattern is unique: whether it solves any other kept layout of its piece and size at its scoring rim, so that every visible edge (where two visible faces meet) has zero or two roads. Its road pattern is what the Loop page's All button gives: the roads and trees it's scored with, a road on every blank visible edge, then Fix all. Writesresults/loop-unique.json, which the page reads for its ★ (every layout of the size checked) and ☆ (only some) marks; loops get theirs fromcolor-loop-solutions.js. Takes about 3 minutes;extend-loop-solutions.jsreruns it.check-loop-solutions.js— For each of the Loop puzzle's cached 7x7 solutions (or another piece or size, with--piece 1x2x3/--size 5x5), runs the Loop page's Fix all, then fails the solution if any piece has no visible roads or blanks, any visible edge has a road meeting a tree, or any piece is isolated (no road could ever reach another piece past the trees). Shows a progress bar, then prints how many pass and which. Starts from a bare piece like the page;--original-marksstarts from the original roads and trees instead.generate-findings.js— One-line wrapper aroundPuzzleSeriesGenerator.persistToFindings(), reporting how many findings it wrote.generate-piece-series.js— Builds a PuzzleSeries of "fill a box with infinite copies of one piece" puzzles across a range of board shapes for a given piece, and persists them asfindings/JSON files.split-batch.js— Splits a downloaded batch-export JSON file (from Objects's "Download local-only objects" button) back into individual per-object JSON files infindings/.delete-all.js— Deletes a top-level finding and everything nested under it (e.g. a PuzzleSeries and all its Puzzles), except any descendant also reachable from some other top-level finding.