Skip to content
Agentmart
Submit a tool

level-generation-and-solvers

Generates level tables proven winnable by a solver or witness bot: par, stars, pack unlocks, a daily level.

Skill by zakariaf

IndexedMIT★ 11
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/zakariaf-level-generation-and-solvers

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Generates level tables proven winnable by a solver or witness bot: par, stars, pack unlocks, a daily level. Use when adding levels, a solver, par, stars, packs or daily levels. Not for game rules (game-rules-engine).

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 26, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Node.js package

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/level-generation-and-solvers

What's inside

Skill name
level-generation-and-solvers
Description
Generates level tables proven winnable by a solver or witness bot: par, stars, pack unlocks, a daily level. Use when adding levels, a solver, par, stars, packs or daily levels. Not for game rules (game-rules-engine).
License
MIT
Instructions
222 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts

Agent Skills spec issues

  • files: referenced but missing: scripts/levels/generate-levels.ts

Files (103)

  • SKILL.md
  • shared.json · assets/
  • template-placeholders.json · assets/
  • levels-contract-entry.json · examples/pig-levels/
  • pig-describe.test.ts · examples/pig-levels/levels/
  • pig-describe.ts · examples/pig-levels/levels/
  • pig-level-plan.test.ts · examples/pig-levels/levels/
  • pig-level-plan.ts · examples/pig-levels/levels/
  • pig-levels.golden.test.ts · examples/pig-levels/levels/
  • pig-levels.golden.test.ts.snap.ios · examples/pig-levels/levels/
  • pig-levels.test.ts · examples/pig-levels/levels/
  • pig-levels.ts · examples/pig-levels/levels/
  • pig-solver.test.ts · examples/pig-levels/levels/
  • pig-solver.ts · examples/pig-levels/levels/
  • pig-hold-policy.ts · examples/pig-levels/rules/
  • checker.md · references/
  • generators-and-plans.md · references/
  • goldens-and-quality.md · references/
  • levels-model.md · references/
  • solvers.md · references/
  • check-levels.mjs · scripts/
  • check-lib.mjs · scripts/
  • app-modules.mjs · scripts/lib/
  • level-checks.mjs · scripts/lib/
  • level-layout.mjs · scripts/lib/
  • level-run.mjs · scripts/lib/
  • pack-format.mjs · scripts/lib/
  • ts-scan.mjs · scripts/lib/
  • selftest.mjs · scripts/
  • levels.json · templates/contracts/
  • levels.schema.json · templates/contracts/
  • app-imports.test.ts · templates/scripts/levels/
  • app-imports.ts · templates/scripts/levels/
  • generate-levels.ts · templates/scripts/levels/
  • run-level-plan.test.ts · templates/scripts/levels/
  • run-level-plan.ts · templates/scripts/levels/
  • difficulty.ts · templates/src/core/game/
  • game-engine.ts · templates/src/core/game/
  • daily-start.test.ts · templates/src/core/game/level-kit/
  • daily-start.ts · templates/src/core/game/level-kit/
  • level-plan.ts · templates/src/core/game/level-kit/
  • level-table.test.ts · templates/src/core/game/level-kit/
  • level-table.ts · templates/src/core/game/level-kit/
  • levels-contract.test.ts · templates/src/core/game/level-kit/
  • levels-contract.ts · templates/src/core/game/level-kit/
  • pack-progress.test.ts · templates/src/core/game/level-kit/
  • pack-progress.ts · templates/src/core/game/level-kit/
  • plan-level-table.test.ts · templates/src/core/game/level-kit/
  • plan-level-table.ts · templates/src/core/game/level-kit/
  • star-rating.test.ts · templates/src/core/game/level-kit/
  • star-rating.ts · templates/src/core/game/level-kit/
  • levels.ts · templates/src/core/game/
  • messages.ts · templates/src/core/game/
  • bfs-solve.test.ts · templates/src/core/game/solver/
  • bfs-solve.ts · templates/src/core/game/solver/
  • engine-solver.ts · templates/src/core/game/solver/
  • ida-star-solve.test.ts · templates/src/core/game/solver/
  • ida-star-solve.ts · templates/src/core/game/solver/
  • search-problem.ts · templates/src/core/game/solver/
  • verify-line.test.ts · templates/src/core/game/solver/
  • …and 43 more

SKILL.md (first lines)

# Level generation and solvers

Gives every game a shipped level table that is generated from seeds, proven winnable (by an exact
solver at a recorded par, or, for games that draw their future at random, by a witness bot), laid out
in packs that unlock by stars, pinned by data goldens, and a daily level that is the same on every
iPhone and Android phone with no server. A checker regenerates each table from the game's plan and
fails on any difference in values or bytes, a bad curve, an import outside the levels zone or a missing
golden.

## Rules that must hold

1. **Levels are generated, never drawn:** a level is `{ level, seed, difficulty, stars }` and its board
   is the engine's `create(seed, difficulty)`, with level and daily difficulties on 0..99 (100 is the
   endless run). Why: the same seed gives the same level everywhere, the tables stay tiny and saved
   progress replays exactly.
2. **`pack-<n>.json` files are written only by `scripts/levels/generate-levels.ts` from the game's
   `LevelPlan`, through the repo's Prettier;** the committed bytes equal what the plan generates. Never
   edit, hand-format, copy or `.prettierignore` a pack. Why: a hand-edited table drifts from the
   generator, and the checker regenerates and compares values (`pack-stale`) and bytes (`pack-format`).
3. **Every shipped level is proven winnable and its proof line is replayed through the real engine
   (`verifyLine`):** par games by an exact solver at the recorded par; games that draw during play by
   `createWitnessSolver`, the game's reasonable player from a fixed bot seed. `budget-exceeded` is never
   `unsolvable`. Why: "no level is impossible", and a solver is never trusted on its own.
4. **One star formula, `starsFor`:** par levels 3 stars at or under par, 2 up to par + 2, 1 for
   finishing; score levels `[win, two, three]`, three ascending whole numbers, `thresholds[0]` the
   lowest winning score, a witness game's two stars at the witness score and three above it (default:
   20 % more, at least 1); a loss is 0. Why: the result and levels screens show these stars to every
   player.
5. **The difficulty curve never falls, later packs are never easier, and no level after the third is a
   one-mover;** the plan's `rate()` enforces the bands while generating. Why: players expect the game
   to rise; the checker reads the generated table (`difficulty-curve`, `par-curve`, `trivial-level`).
6. **The daily level is `create(dailySeed(dateKey, salt), dailyDifficulty)` with a 16-bit salt no other
   game uses and a daily difficulty the developer approves (default: medium, 40 to 50), both fixed
   forever once shipped;** "today" comes from
   the injected clock at the edge. Why: every player gets the same daily level on the same date, and a
   changed salt changes it for everyone.
7. **Data goldens pin the pack boundary levels and at least three daily dates (a year-boundary pair
   included) in a `[contract] <game-id> daily goldens` describe registered in `contracts/goldens.json`;
   snapshots are committed and change only with `-u` on one file and a `Gate-Change:` trailer.** Why: a
   silent generator or tuning change would give players different boards under the same level numbers.
8. **`contracts/levels.json` declares each game's `packCount`, `levelsPerPack`, `starRule`, `daily` and
   `endless`, and the packs, the `LevelsSpec` and the contract test agree with it;** the first pack
   needs 0 stars and later packs exactly half the stars of the packs before them (0, 45, 90 for packs
   of 30). A daily- or endless-only game is an entry with `packCount` 0, `levelsPerPack` 0 and no
   `starRule`. Why: one place says what the game ships, so the table and the modes can never disagree.
9. **Level code is pure and deterministic:** files in `src/games/<game-id>/levels/` import only
   `src/core` and the game's own `rules/`, `levels/` and `geom/` (never `testing/`: a witness's policy
   lives in `rules/`), and use no `Math.random`, clock, `**`, `Intl` or inexact `Math`. Why: Jest, the
   generator, Hermes on iOS and Hermes on Android must generate bit-identical levels.
10. **Pack names are catalog keys present in every catalog of the app.** Why: the levels screen shows
    them in the user's language, left to right or right to left.
11. **Tuning first, packs second:** the balance sims pass before the packs are generated, and any
    later change to the tuning, `create`, the solver or the witness regenerates the packs and goldens;
    after release, stop and ask the developer before players' levels change. Why: every level is
    `create(seed, difficulty)` on the current tuning.

## Workflow

1. **Settle the tuning, then read [references/levels-model.md](references/levels-model.md)** (types,
   the curve and the tuning rows, the contract, packs, stars, daily, endless). The game's balance sims
   (game-balance-and-bots) pass first. Ask the developer for the bands: packs and levels per pack,
   minimum par per pack, star rule (par or score), daily difficulty, an endless run; defaults are
   3 x 30, minimum par 2/3/4, par stars, daily 40 to 50, no endless run.
2. **Install the level kit once per app.** The game kit and the RNG come first: game-rules-engine
   (`src/core/game/*.ts`, `testing/play-bot.ts`) and seeded-determinism-and-golden-vectors
   (`src/core/rng/sfc32.ts`, `src/core/dates/{date-key,daily-seed}.ts`). Pin fast-check exactly
   (`npm install -D -E fast-check@4.10.2`; verified on 2026-10-03, re-verify with
   `npm view fast-check version`). Run `node ${CLAUDE_SKILL_DIR}/scripts/check-levels.mjs .`; for each
   `kit-file-missing` copy the file from `templates/` to the path its first line names, with its test:
   `src/core/game/solver/`, `src/core/game/level-kit/`, `src/core/game/testing/render-cells.ts` and
   `scripts/levels/`. `templates/src/core/game/*.ts`, `testing/play-bot.ts` and
   `templates/src/games/__GAME_ID__/rules/` are synced copies of game-rules-engine's files, there only
   so the templates compile alone: never copy them over the app's own.
3. **Write the solver test-first.** Read [references/solvers.md](references/solvers.md). A game whose
   whole future is fixed by `create` gets an exact search: copy
   `templates/src/games/__GAME_ID__/levels/__GAME_ID__-solver.ts` and its test to
   `src/games/<game-id>/levels/` (rename files; replace `__GAME_ID__`, `__GAME_PASCAL__`,
   `__GAME_CONST__`), choose the search state, move order and key, BFS or IDA*, and prove it with
   examples, the `verifyLine` property and a budget test. A game that draws during play uses
   `createWitnessSolver` with its policy in `rules/`: imitate `examples/pig-levels/`.
4. **Write the level plan test-first.** Read [references/generators-and-plans.md](references/generators-and-plans.md).
   Copy `__GAME_ID__-level-plan.ts` and its test: packs, the curve (`difficultyFor` from 0 at level 1 to
   its cap), the budget, and `rate({ level, par, line, final })` with the bands (a witness game:
   `scoreThresholds` from the final score, a minimum witness length).
5. **Declare the game in `contracts/levels.json`** (copy `templates/contracts/levels.json` and
   `levels.schema.json` once; one entry per game; a daily- or endless-only game has `packCount` 0 and
   skips the plan and packs: levels-model.md, "Daily-only and endless-only games"). Merge the pack name keys of
   `templates/src/i18n/catalogs/en.json` and `ar.json` (English and Arabic examples) into every catalog
   the app ships, with your game id and pack names, and send the texts through the app's review queue
   (i18n-strings-and-catalogs owns the catalogs).
6. **Generate the tables:** `node scripts/levels/generate-levels.ts --game <game-id>` writes
   `pack-<n>.json` through the repo's Prettier. Fix any `level N: no candidate` by loosening the band or
   the curve, rerun until 0 failures. Then `node scripts/levels/generate-levels.ts --game <game-id> --check`
   and `npx prettier --check src/games/<game-id>/levels` both exit 0. Commit exactly what it wrote.
7. **Assemble and prove the table.** Copy `__GAME_ID__-levels.ts` (the `LevelsSpec`: plan, packs,
   `toLevelEntries`, solver, daily salt and difficulty, endless) with the game's own salt (the
   template's `0x7c9e` is `lights-out`'s; `daily-salt-shared` prints the default for your id) and
   `__GAME_ID__-levels.test.ts` (runs `levelsContractProblems` with the contract entry as `CONFIG`). Set
   `levels` in `src/games/<game-id>/<game-id>-game.ts` (game-rules-engine's module) to it. A puzzle
   game with hints wires `hints: { kind: 'solver', suggest }` in its rules (never for a witness).
8. **Pin the goldens.** Read [references/goldens-and-quality.md](references/goldens-and-quality.md).
   Copy `__GAME_ID__-describe.ts` (with its test) and write `describeLevel(state)` for the game. Copy
   `__GAME_ID__-levels.golden.test.ts`, delete the template's `.snap.ios`, run
   `npx jest src/games/<game-id>/levels/<game-id>-levels.golden.test.ts --selectProjects golden -u`
   once, open the `.snap.ios` and read the boards, register the test in `contracts/goldens.json`
   `contracts` (golden-and-snapshot-tests), then `npx jest src/games/<game-id>/levels --ci --selectProjects golden`
   passes.
9. **Format, lint, type-check, test:** `npx eslint --fix src/games/<game-id>/levels src/core/game scripts/levels`,
   `npx prettier --write src/games/<game-id>/levels`, `npm run typecheck`, then
   `npx jest src/games/<game-id>/levels src/core/game scripts/levels --ci --selectProjects unit --coverage --collectCoverageFrom='src/core/game/**/*.ts' --coverageThreshold='{}'`
   and read the table (`src/core` stays at 95/95/95/90; paths before `--selectProjects`, which reads
   every later word as a project name).
10. **Run the check** `node ${CLAUDE_SKILL_DIR}/scripts/check-levels.mjs . --game <game-id> --report`;
    fix every `FAIL` line (file, rule, fix) and rerun until it prints `RESULT: PASS`. Rules, options
    and troubleshooting: [references/checker.md](references/checker.md). Put the `--report` pack lines
    in the report and commit tables and goldens with a `Gate-Change:` trailer (git-commits-and-reporting).

## Definition of done

From zakariaf/ReactNative-Skills, MIT.

More from zakariaf/ReactNative-Skills

Signals

Stars
11
Forks
2
Open issues
0
Last commit (this folder)
Oct 17, 2026 (12 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from zakariaf

Cite this page

level-generation-and-solvers skill. Agent Mart. https://agentmart.dev/skills/zakariaf-level-generation-and-solvers (last updated 2026-10-24)