{
  "schema": "leumas.docs.page/1",
  "id": "adapter:domain/puzzles",
  "slug": "adapters/domain/puzzles",
  "kind": "capabilities",
  "bucket": "package",
  "title": "puzzles — logic-puzzle generator + solver pack",
  "name": "puzzles",
  "eyebrow": "logic-puzzle generator + solver pack",
  "chip": null,
  "summary": "Logic-puzzle generator and solver pack (pure JavaScript, zero dependencies). Generate, solve and validate classic pencil-and-paper puzzles: Sudoku (generate by difficulty easy/medium/hard/expert...",
  "keywords": [
    "puzzles",
    "logic-puzzle",
    "sudoku",
    "mazes",
    "clue",
    "diagonals",
    "n-queens",
    "knight"
  ],
  "audience": "both",
  "funnel": {
    "product": null,
    "cta": null
  },
  "body": "# puzzles — logic-puzzle generator + solver pack\n\nPure JavaScript (zero npm dependencies, Node built-ins only) adapter system for **generating,\nsolving and validating classic logic puzzles**. Every randomized tool accepts an optional `seed`\nfor reproducible, deterministic output. All results are plain JSON-serializable objects.\n\nContract: `export default { metadata, adapters: { <tool>: (args) => result } }`. Each tool takes a\nsingle args object (an HTTP POST body maps 1:1 onto a call).\n\n## Tools\n\n| Tool | Args | Returns |\n|---|---|---|\n| `sudokuGenerate` | `{ difficulty?: 'easy'\\|'medium'\\|'hard'\\|'expert', seed? }` | `{ puzzle, solution, clues, blanks, string }` — a uniquely-solvable 9×9 puzzle + its solution |\n| `sudokuSolve` | `{ puzzle }` (2D array, flat 81 array, or 81-char string; `0`/`.` = blank) | `{ solved, unique, solution, string }` |\n| `sudokuValidate` | `{ puzzle }` | `{ valid, complete, filled, blanks, conflicts }` — checks row/col/box conflicts |\n| `mazeGenerate` | `{ width?=15, height?=15, seed? }` | `{ grid, ascii, svg, start, end, width, height }` — a perfect maze |\n| `mazeSolve` | `{ maze }` (an object from `mazeGenerate`) | `{ solved, path, length, start, end }` — BFS shortest path |\n| `wordSearchGenerate` | `{ words?, size?, theme?, directions?=8, seed? }` | `{ grid, rows, words, unplaced, answerKey, size }` |\n| `nonogramFromGrid` | `{ grid }` (2D truthy/`1`/`#`/`x`) | `{ rowClues, colClues, width, height, filled, solution }` |\n| `magicSquare` | `{ n }` (odd, doubly-even, or singly-even; not 2) | `{ square, magicConstant, verified, n }` |\n| `nQueens` | `{ n }` (n≥4 for solutions, ≤20) | `{ count, first, board, allSolutions?, n }` |\n| `knightsTour` | `{ n, start?=[0,0] }` | `{ board, path, complete, visited, n }` — Warnsdorff's heuristic |\n| `listThemes` | `{}` | `{ themes, counts }` — word-search word banks |\n\n### Encodings\n- **Sudoku** boards: `0` (or `.`) is a blank. `string` output is the 81-char row-major form.\n- **Maze** `grid[y][x]` is a wall bitmask — `N=1, E=2, S=4, W=8`; a **cleared** bit is an open\n  passage. `start` is `[0,0]`, `end` is `[width-1, height-1]`. `ascii` uses `#` walls / spaces;\n  `svg` is a self-contained inline SVG string.\n- **Word search** `answerKey` entries are `{ word, row, col, dx, dy }`; the word occupies\n  `grid[row + dy*i][col + dx*i]` for `i = 0..len-1`. `directions: 4` = orthogonal only, `8` = with\n  diagonals. When `words` is omitted, words are drawn from the `theme` bank (see `listThemes`).\n- **Magic square** covers all three parities: Siamese method (odd `n`), diagonal-flip (doubly-even\n  `n % 4 === 0`), Strachey method (singly-even `n % 4 === 2`). `verified` re-checks every row,\n  column and both diagonals against `magicConstant`.\n- **N-Queens** `first` is an array where index = row and value = the queen's column. For `n ≤ 12`\n  all solutions are enumerated (`allSolutions` + full `count`); for larger `n` the exact `count` is\n  still returned but only the first board is materialized.\n- **Knight's tour** `board[r][c]` is the move index (0-based) at which the knight lands there.\n\n## Usage\n\n```js\nimport puzzles from './index.js';\nconst { adapters } = puzzles;\n\nconst sudoku = adapters.sudokuGenerate({ difficulty: 'hard', seed: 42 });\nconst solved = adapters.sudokuSolve({ puzzle: sudoku.puzzle });\n\nconst maze = adapters.mazeGenerate({ width: 20, height: 20, seed: 7 });\nconst route = adapters.mazeSolve({ maze });      // route.path = [[x,y], …]\n\nadapters.wordSearchGenerate({ words: ['CAT', 'DOG'], size: 12, seed: 3 });\nadapters.magicSquare({ n: 5 });                  // → { magicConstant: 65, verified: true, … }\nadapters.nQueens({ n: 8 });                      // → { count: 92, … }\nadapters.knightsTour({ n: 8 });                  // → { complete: true, visited: 64, … }\n```\n\n## DRY boundary\n\nThis pack owns **logic puzzles**: deterministic puzzle *structure* + constraint *solving*. It does\nnot overlap its neighbors:\n\n- **`dice`** owns generic randomness — dice rolls, shuffles, coin flips, weighted loot, random\n  pick. If you just need a random draw, use `dice`, not this pack.\n- **`fortune`** owns novelty & trivia — fortune cookies, Magic 8-Ball, would-you-rather, trivia\n  Q&A, jokes. The themed word banks in `data/wordbanks.json` here are **grid fodder** for word\n  searches, not a trivia/quiz dataset.\n\nRandomness inside this pack exists only to *generate a puzzle instance*; it is always reproducible\nvia `seed`.\n\n## Files\n\n- `index.js` — all tools + inlined helpers (seeded mulberry32 PRNG, solvers). No cross-pack imports.\n- `metadata.json` — discovery metadata; `inputs[0].options` lists every tool name.\n- `data/wordbanks.json` — themed uppercase word banks for `wordSearchGenerate`.\n",
  "source": {
    "path": "shared/engines/adapters/domain/puzzles/README.md",
    "blobSha": "",
    "commit": "",
    "committedAt": "",
    "provenance": "no-git",
    "bytes": 4978,
    "hash": "b03199195c5458182d62e844f445fa0c70b3a551"
  },
  "urls": {
    "html": "/p/adapters/domain/puzzles",
    "json": "/docs/adapters/domain/puzzles.json",
    "md": "/docs/adapters/domain/puzzles.md"
  },
  "links": {
    "composes": [],
    "usedBy": [],
    "product": [],
    "howTo": [],
    "skills": []
  }
}
