quest'n'click 4.5.0 · r1

Built for quest'n'click 4.5.0, revision r1. Whether it is published, and which one is current, is recorded at publication.json.

Playtests

Français · Type: how-to · Audience: author · Context: engine repository, created project · Status: ready · Applies from: 3.9.0

The solver tells you the game can be finished. It cannot tell you where a person gets stuck. A playtest can: players share their session from the pause menu, you drop the files into the game, and playtests replays them on the current content and sums them up.

What you get

A report of how real people played: play time per room, where they stalled, the hints they saw, the minigames they played, where each one stopped, the taps that just missed a target, and a heat map on the puzzle graph keyed like the solver's. The sessions stay in the game and are replayed by every later check, so you also learn when a content change makes an old session no longer replay.

Context and versions

Prerequisites

Where to run the commands

Testing like a player

Each check catches something the others miss. Run them in this order:

StepCommand (engine repository)Catches
Validatenpm run validatebroken ids, missing Look lines, long lines, flags never set
Solvenpm run solvedead ends, an unreachable ending, items never used
Walkthrough testnpm test (tests/demo-walkthrough.test.ts for the demo)a scripted full playthrough on the real engine
Screenshotsnpm run e2ewhat the solver cannot see: a character on a table, a line cut by the edge
A real phonenpm run dev:lan, landscapethumb size, readability, sound, the rotate screen
Sealed endingnpm run seal, npm run build, npm run check:spoilersthe ending text never in the clear
A personthe steps belowwhat nobody on the team can see any more

In a created project, npm run verify runs validate, solve, the translation status, the lint and the playtests; the other rows have no quest-n-click command, see Checking your game. The Studio's Check tab runs validate and solve in one place.

Then hand the phone to someone who has never seen the game, and stay silent. Every time they hesitate more than a minute, write it down: it is a missing Look line, a vague hint, or an exit nobody saw.

Steps

  1. Send the game's URL. Say only: "play as you like; when you stop, finished or not, open the pause menu and tap Share session". Do not explain a puzzle, even when asked: write down the question.
  1. The tester shares the session. Share session (the pause menu's row, named by ui.shareSession) makes a file <game>-<date>-<time>.session.json and sends it through the phone's share sheet (Web Share), or downloads it where the browser cannot share. The file holds the inputs since the game started, as ids and indices only (no journal text, no name), the time of each input, the device family (ios, android or desktop, nothing finer), and the near misses: a tap on nothing within 24 px of a target, by room and target. The tester sends it the way they like.

Guarantee · session-ids-only · referenced · executed on aff6caab7514 · scope self-checked by the author (AI), not reviewed A shared playtest session has a timestamp on every step and an empty journal, and a line the game said during the play is not in the file.

  1. Drop the files into the game and commit them:

    • engine repository: games/<id>/playtests/ (npm run audit scans that folder with the rest of games/);
    • created project: game/playtests/.

    Only files whose name ends in .session.json are read.

  1. Replay and read the report.

    # in the engine repository
    npm run playtests -- --out=.cache/playtests
    
    # in a created project
    npx quest-n-click playtests --out=.cache/playtests
    

    It replays every file on the current content and prints, as Markdown: play time per room (a gap over a minute between two inputs counts as a pause), where players stall (the same action three times in a row without effect), the hints shown, the minigames played, where each player stopped, the near misses, and the sessions the content has outgrown. --out writes report.md, report.json and heat.svg (the puzzle graph, heated by the players); --json prints the report on stdout and nothing else; --dir=<folder> reads another folder.

  1. Turn the report into work. A stall is a puzzle to clue better, a near miss a hotspot to widen, an abandon a place to look at. In the Studio's Check tab, the puzzle graph's heat can come from the players instead of the solver.
  1. Keep the sessions as a gate. The sessions stay in the game. Once the content changes they may no longer replay:

    • without --strict (what verify:game, npm run build and a created project's verify and build run), a diverged session is reported, not an error, so a content change never blocks a push;
    • with --strict (the release gate: verify:release and release-check in the engine repository, quest-n-click release in a created project, and the weekly prove workflow), a diverged session is an error, exit 1: re-record it or delete it.

    --strict alone asks for no number of sessions: zero sessions pass it, and it says so.

  1. For a release tested by players, ask for quotas.

    # in the engine repository: verify:commercial, then 5 sessions that still replay, 3 played to the end, 2 device families
    npm run verify:field
    
    # in either context, your own numbers
    npm run playtests -- --strict --require=5 --require-completed=3 --require-devices=2
    npx quest-n-click playtests --strict --require=5 --require-completed=3 --require-devices=2
    

    A diverged session counts for nothing; device families are counted once each. One quota missed is an error, and so is no session at all. verify:field is not a step of release-check (decision D12): it is what a release tested by players needs. The maintainer's field pass is described in Field passes.

Sessions: the unit of reproduction

The engine records every input since the game started or a save was loaded (actions, map, character switches, script steps) with the answers given on the way (choice answers, random draws). Besides Share session, the game's save menu, the dev panel and the Studio's Play tab export it as <game>-session.json. A tester's bug report is that file and a screenshot.

# in the engine repository
npm run replay -- session.json
npm run replay -- session.json --upTo=40 --json

npm run replay plays it back without a display and prints the journal, the semantic journal (4.1.11) and the final state. It exits 1 at the first entry whose outcome differs from the recording, or when its semantic journal differs from the file's. --upTo=N stops earlier; --json is for scripts. A created project has no replay command: play a session in the Studio's Play tab (Play and replay a session). The solver's solution is a session too (npm run solve -- --json gives steps), which is what npm run e2e taps through. The file's format is in File formats.

Expected result, and how to check it

The command ends with N session(s) replayed in … s, and nothing diverged. With --out, open report.md and heat.svg. With --strict and quotas, the exit code is 0.

Common errors

SymptomCauseFix
no playtests in games/<id>/playtestsThe folder is empty, or the files do not end in .session.json (the save menu's export is <game>-session.json)Use Share session, or rename the file to end in .session.json.
✖ <file>: recorded on game "x", not "y" (exit 1)A session of another gameMove it to that game's folder.
⚠ <file>: recorded with save version N, the game is at MThe save version changed sinceA warning: the replay may diverge.
… diverged (content changed since: re-record or delete)The content has outgrown the sessionRe-record it, or delete it. With --strict this is exit 1.
✖ [<id>] field quotas missed: … (exit 1)Fewer sessions, completed runs or device families than askedCollect more sessions, from other kinds of device.

Files or data changed

The session files you add to playtests/. --out writes into the folder you give it (.cache/playtests above). Nothing else is written.

Recovery or going back

A session is a plain file: delete it, or replace it with a fresh recording. Nothing else depends on it.

References


Edit the source of this page · Report an error