Campaign quality metrics
A valid story is not the same as a good one. ScryMaster measures a lot about your story — and exposes it so you (or your AI) can read it after every build pass and steer. This is the “is it good yet?” loop. None of it is guesswork: every number below comes from the real engine.
validate → simulate → health → world. Valid + reachable is the floor; health + world are how you climb from “plays” to “worth replaying.”1. Validate — the floor (must be clean before publish)
POST /api/v1/adventures/:id/validate (MCP validate_adventure). Hard errors block publish: no start, dangling edges, unreachable nodes, no reachable ending, unknown verbs, a combat that points at a missing stat block. It also returns advisory lints that are the first real quality signal:
- Fake agency (
INERT_CHOICE): two choices that go to the same place with no effect — the player’s decision didn’t matter. Fix or merge. - Unpaid setup (
WRITTEN_NEVER_READ): a variable you set but never read — a promise with no payoff. Either read it later or cut it. - Constant condition (
READ_NEVER_WRITTEN): a gate on a variable nothing ever sets — the branch is dead. - Dead ends, empty prose, undeclared tokens, unobtainable craft ingredients, prose-only monster attacks — each names the exact beat.
2. Simulate — does it actually play?
POST …/simulate (MCP simulate_adventure) auto-plays the story hundreds of times. Read: completion rate (can it be finished?), death rate (too lethal?), ending distribution (do multiple endings actually get reached, or is it linear-in-disguise?), never-visited beats (content no path reaches — dead weight), and choice popularity(is one option always taken — the others are cosmetic?).
3. Health — the scorecard
GET …/health (MCP get_health) rolls the above into a 0–100 campaign health score plus advisory metrics: combat load & lethality bands, currency flow (does the economy balance?), free rests (anti-grind), clue redundancy (the Three-Clue Rule — is a critical clue reachable ≥2 ways?), choice density (mobile overwhelm), and carry-forward hygiene. Every finding names the beat or variable. Treat a low score as a punch-list, not a grade.
4. World — does the cast read back?
GET …/world (MCP get_world) derives your NPCs (companions/speakers + their relationship variables + where they appear), quests (objectives, with where they’re set and read), factions (favor ledgers + their payoff beat), and acts. This is the reactivity check: an NPC with no relationship variable is set dressing; a quest never turned in is a loose thread; a faction favor never spent is a setup with no payoff.
Richness is consequence, not count
There is no single “richness score” to chase — and that is deliberate. More endings, more choices, more variables is NOT better. A good ScryMaster story is measured by whether its moving parts connect: every branch changes knowledge, trust, resources, danger, route, or ending texture; every durable variable pays off; every optional quest alters state, a reveal, a relationship, or the final montage. Read the signals above as a coherence check — the aim is a story where choices are remembered, not one that scores well on a counter.
Next: The authoring playbook →
