Making a game

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

  1. List the game folder and each folder in it, and read every scene file, the definitions, and every rule, look, plugin and extension once.
  2. Note the game's kinds (the keys of sim in each <scene>.sim.ts), its scenes (prefabs.scenemanager.scenes in <game>.scene.json), its own plugins, and the plugins each scene lists.
  3. Run every test file in the folder, one at a time, with yarn vitest run <file>, or yarn test:view <file> for a view test.
  4. Run yarn tsc and read its output for the game's files, and yarn eslint <file> on each *.extension.tsx and *.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.

AreaWhat breaks a rule
FolderA 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
PagesA rule, number, listener or scene name in a page; client.html that does not wrap predict; a dev.html override made after load
NumbersA 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
RulesMath.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
SeatsThe 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
LooksA 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
OrderPlugins listed in the wrong order; the audio ledger's entry behind what raises a sound
FilesA fetch or a path in code; an entry's name in code; a catalogue url with no leading /
SoundA sound played by a look; the cue table on the ledger; a cue a definition names that world.audio.cues lacks
ScenesWhat 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
FeelThe three dts apart; a velocity stepped with Euler; a definition kept from an earlier read
Own pluginsNumbers 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
ExtensionsA write or fetch of its own; an edit outside its change; a colour in code
TestsA 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/&lt;game&gt;/&lt;file&gt;:&lt;line&gt;   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

  1. Find every user of the name, field or key across the game folder, its tests and extensions included.
  2. Move it to its home and change every user. Renames go first.
  3. 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.
  4. Run the tests beside every file touched with yarn vitest run <file>, then yarn tsc, and yarn eslint on any extension or route touched.
  5. Play it where what is drawn or how it plays changed: index.html, and client.html against node --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.