ContribuerTutorielPour contributeursS'applique de 4.1.11
Visite du code
This page in EnglishCette page sur le wiki GitHub
Une demi-heure avec le code ouvert : huit étapes, d'un tout petit jeu jusqu'au test qui prouve chaque partie. Chaque étape nomme les fichiers à lire et le test qui les montre à l'œuvre. Architecture est la même carte vue d'en haut.
Ce que vous allez construire
Pas une fonctionnalité : une image du moteur dans votre tête, faite en lisant du vrai code et en lançant le test de chaque étape. Il vous faut un dépôt préparé (Préparer son poste de développement) et un éditeur. Chaque test d'une étape se lance seul :
# dans le dépôt du moteur
npx vitest run <fichier>La visite suit le code de la 4.4.0 ; ses étapes datent de la 4.1.0 (et de la 4.1.1 pour le signal).
1. Déclarer un petit jeu
Lisez tests/fixtures/classics.ts : cinq tout petits jeux d'après les classiques
(insults, grog, dott, mansion, stan), chacun un GameDef de quelques lieux et règles. Une règle est
{ verb, a, b, if, do } ; do est une liste de commandes (Cmd, dans
src/engine/core/types/content.ts). Les types d'un jeu complet sont dans
src/engine/core/types/game.ts. La démo, écrite de la même façon mais plus
grande, est games/demo/.
# dans le dépôt du moteur
npx vitest run tests/classics.test.tsVous voyez chaque mécanique classique jouée jusqu'au bout par le vrai moteur.
2. Le compiler et le figer
compileGame dans src/engine/core/define.ts clone le contenu, remplit les valeurs
par défaut, le fige et donne à chaque règle, choix, sujet, écouteur et étape de script un id stable
(src/engine/core/content-ids.ts). Sauvegardes et sessions parlent avec ces
ids : renommer une réplique ne casse pas une sauvegarde.
# dans le dépôt du moteur
npx vitest run tests/compile.test.ts tests/stable-ids.test.ts3. Démarrer une partie
new Engine(game, layouts, presenter, store) puis newGame()
(src/engine/core/engine.ts). Dans les tests, le presenter est FakePresenter et le
stockage MemoryStore (src/engine/core/ports.ts) ; dans le navigateur, App
(src/engine/dom/app.ts) compose le moteur avec le DomPresenter, et bootGame
(src/engine/boot.ts) branche le tout.
# dans le dépôt du moteur
npx vitest run tests/core.test.ts -t "fixture game"4. Jouer une action
Engine.act y va, ouvre une entrée de session et appelle resolve
(src/engine/core/interactions.ts) : la règle que choisit findRule, sinon un
genre, sinon une réplique de repli. Ses commandes passent par exec et step
(src/engine/core/command-runtime.ts), chacune par son gestionnaire dans
src/engine/core/command-handlers.ts ; les événements et les scripts dans
src/engine/core/event-runtime.ts et
src/engine/core/script-runtime.ts.
# dans le dépôt du moteur
npx vitest run tests/core-runtime.test.tsChaque module d'exécution y est appelé seul, avec le moteur en premier argument.
5. Sauvegarder, charger, rejouer
saveEnvelope et parseSave (src/engine/core/save.ts) écrivent et vérifient une
sauvegarde ; migrate (src/engine/core/migrate.ts) fait suivre une ancienne ;
tests/save-v3.test.ts charge une sauvegarde par version depuis la 3.0 et la joue jusqu'à la fin. La session
(src/engine/core/session-runtime.ts) enregistre chaque entrée avec
l'empreinte de l'état qui suit ; replay (src/engine/tools/replay.ts) la rejoue et
nomme la première entrée qui diffère.
# dans le dépôt du moteur
npx vitest run tests/replay.test.ts -t "a recorded session"6. La même action dans le solveur
solve (src/engine/tools/solve/search.ts) prend un état de la frontière ;
makeExpander (src/engine/tools/solve/expansion.ts) joue sur un vrai
Engine chaque action qui vaut la peine, enregistre chaque transition (TryRecord,
src/engine/tools/solve/model.ts) et ce qu'elle a lu et écrit ; la recherche
les fusionne et rend son verdict. Ce dont un état est fait pour la recherche est dans
src/engine/tools/solve/abstractions.ts.
# dans le dépôt du moteur
npx vitest run tests/solver-contract.test.ts
npm run quality:baseline -- --checktests/memo.test.ts est un test lourd (des minutes) : il tourne dans la nightly et le candidat, ou seul avec
npx vitest run tests/memo.test.ts. Le comportement de chaque jeu est figé par tests/quality-baseline.json, que
quality:baseline -- --check compare (La référence de qualité).
7. Un signal du monde extérieur (4.1.1)
tests/fixtures/signals.ts déclare trois signaux ;
src/engine/reality/protocol.ts vérifie un signal signé avant de le lire ;
src/engine/reality/client.ts le vérifie, le donne à Engine.receive
(src/engine/core/reality-runtime.ts : appliqué au plus une fois, une entrée
de session), attend la sauvegarde durable, puis accuse réception. Le solveur propose des signaux selon une politique
(src/engine/tools/solve/scenarios.ts). Le Bridge de référence est
bridge/src/.
# dans le dépôt du moteur
npx vitest run tests/reality-engine.test.ts tests/reality-proof.test.ts tests/bridge.test.tstests/reality-engine.test.ts fait tomber le moteur à chaque frontière. Dans le navigateur, scripts/e2e-reality.mjs
joue le même chemin (npm run e2e:reality).
8. Trouver le test d'une chose
- Une commande : cherchez sa clé dans
tests/cmds.test.tsettests/core.test.ts. - Une règle de couche :
tests/boundaries.test.ts. - Les noms publics :
tests/api-surface.json. - Un comportement du navigateur : les scripts
scripts/e2e*.mjs(npm run e2e,e2e:taps,e2e:pwa,e2e:a11y…), que la CI lance sous Chromium et WebKit (et Firefox pour la PWA).
Quelle suite tourne où, et quand : Quels tests tournent quand.
Ce que vous avez appris
- Un jeu est une donnée, compilée et figée avec des ids stables : Architecture.
- Un seul moteur tourne dans le joueur, les tests et le solveur, derrière le port
Presenter. - Chaque partie a son test, et la référence fige l'ensemble : La référence de qualité.
Pour aller plus loin
- La boucle de développement : changer une commande de bout en bout.
- Frontières d'import : ce que chaque dossier peut importer.