Auditing a game
A game folder checked against every rule and moved into its homes.
An audit reads one game folder, games/<game>/, against the rules the other guide pages give, lists what breaks one, and moves each finding into its home. Run it while the game is being written, before a piece is called done, and on picking up someone else's game. A game can pass its own tests and still break these rules.
1. The baseline
- List the game folder and each folder in it, and read every scene file, the definitions, and every rule, look, plugin and extension once.
- Note the game's kinds (the keys of
simin each<scene>.sim.ts), its scenes (prefabs.scenemanager.scenesin<game>.scene.json), its own plugins, and the plugins each scene lists. - Run every test file in the folder, one at a time, with
yarn vitest run <file>, oryarn test:view <file>for a view test. - Run
yarn tscand read its output for the game's files, andyarn eslint <file>on each*.extension.tsxand*.route.ts.
2. The checks
Each check is found with a search over the folder, then read in its file before it is listed. Quote every glob handed to grep, such as --include='*.ts', or zsh stops the command and the empty answer reads as clean.
| Area | What breaks a rule |
|---|---|
| Folder | A file not named after a kind, a scene or the game; a kind named after a scene, the game or a plugin; a change to Patchwork's own folders made for this game; a header that disagrees with its code |
| Pages | A rule, number, listener or scene name in a page; client.html that does not wrap predict; a dev.html override made after load |
| Numbers | A number or a shown word written in a rule or a look; a fixed value on a prefab; a changing field missing from its prefab; a page-only value on a row |
| Rules | Math.random, or Math.sin, ** and the like, in a rule; a die rolled with no seed; memory kept off the row; one kind importing another; a rule writing another kind's row; a seat's argument unchecked |
| Seats | The seat's thing or its score and lives on a row the player row spawns; the seat's row found as the first player row instead of with possessed; keys bound for every seat's row; a rule-only act on the player row a seat can send; a deadzone on the player prefab, which nothing reads and every seat is sent, in place of world.player.deadzone (in the manager's world when every scene uses the same one); no world.predict; no <game>.predict.test.ts |
| Looks | A plugin asked in setup; remove that does not take off what setup made; THREE or PIXI imported as a value; two looks that are copies; a plugin and a look both drawing one kind |
| Order | Plugins listed in the wrong order; the audio ledger's entry behind what raises a sound |
| Files | A fetch or a path in code; an entry's name in code; a catalogue url with no leading / |
| Sound | A sound played by a look; the cue table on the ledger; a cue a definition names that world.audio.cues lacks |
| Scenes | What every scene reads copied into each instead of the manager's world; a scene name in code; a menu or game-over screen that lists player |
| Feel | The three dts apart; a velocity stepped with Euler; a definition kept from an earlier read |
| Own plugins | Numbers of its own on world; listed in plugins instead of through shipped; browser state at the top of the file; a mod in the wrong folder |
| Extensions | A write or fetch of its own; an edit outside its change; a colour in code |
| Tests | A file with no test beside it; a value of the scene file typed into a test; a scene changed in memory; a press that pins no step; no replay test |
The guide page each rule comes from has the detail: Designing a kind, Designing a seat, Writing the look, Sound, Tuning feel, Building a plugin and Proving a game.
3. The list
Write one entry per finding, then one line for each check that found nothing and each that did not apply.
games/<game>/<file>:<line> what is there
rule: the rule it breaks
home: where it goes
with it: every file and test that uses it
4. Moving each finding
- Find every user of the name, field or key across the game folder, its tests and extensions included.
- Move it to its home and change every user. Renames go first.
- Change the tests that held the old place, and write the test the rule asks for. See each new check fail on the old code.
- Run the tests beside every file touched with
yarn vitest run <file>, thenyarn tsc, andyarn eslinton any extension or route touched. - Play it where what is drawn or how it plays changed:
index.html, andclient.htmlagainstnode --experimental-strip-types games/<game>/<game>.server.ts.
A finding whose home is missing in Patchwork is built there first, general and tested. Where a fix would change what the game does, the game's maker decides.
Checking it
Run the audit again over the folder. The list is empty.