BIG EGG · Refonte terminée · Les 7 phases sont livrées
Les sept phases sont livrées et validées. Ce document reste le registre de référence : décisions, raisonnement archivé et état final.
Registre
| Décision | Retenu | |
|---|---|---|
D1 | Portée | Les 7 phases d'affilée, sans interruption, mais suite de tests validée à chaque frontière de phase. Copie de sauvegarde datée avant chaque phase. |
D2 | Couche override | Dès le départ — quatre couches complètes. |
D3 | Empilement | Clé par effet. Une instance par application, groupées par stack_key ; stack = expiration par pile, stack_refresh = expiration commune. |
D4 | Champs | Liste validée. Les champs d'auteur déjà définis dans l'outil deviennent adressables en plus, automatiquement. |
D5 | Réactivité | Recalcul global via state_changed. |
D6 | Adresses | Préfixe element. supprimé. Les collections sont racines directes. |
D7 | Équipement | Prévu : arme, armure, objet, consommables, 1 à 3 skills, sets distincts resto/donjon. Les 7 phases livrent le substrat, pas l'équipement lui-même. |
D8 | Fusion compteurs | fact_values fait foi. |
fact.boss_defeated
player.attack_damage
enemies.fungling.total_killed
recipes.fried_egg.total_cooked
upgrade_nodes.hot_pan.purchased
Les racines forment un vocabulaire fermé : les noms de collections du fichier maître, plus fact, player, run et meta. Le premier segment se valide par simple appartenance à cet ensemble.
Des sets distincts resto/donjon rendent player.attack_damage dépendant de la scène active. Le fournisseur d'équipement est donc conçu dès le départ autour d'emplacements et d'un contexte courant, même si aucun équipement n'existe encore.
Issu des échanges précédents, et inchangé.
enemies, ingredients, recipes, upgrade_nodes, customer_profiles — ceux du fichier maître.flat, scaling, global, override, combinées à des positions fixes.set, add, multiply, min, max, toggle. Aucune expression, aucune condition imbriquée : ce n'est pas un langage de script.set → add → multiply, puis tri par source. Corrige le bug d'ordre d'achat repéré dans get_game_variable_components().final = (base + Σflat) × (coef_base + Σscaling) × (1 + Σglobal) × Πoverride
→ minimum → maximum → arrondi
Archive
Conservé pour mémoire : ces choix sont tranchés (voir le registre plus haut). Les options non retenues restent documentées afin qu'on sache, dans six mois, pourquoi elles ont été écartées — et ce qu'il faudrait rouvrir pour changer d'avis.
Deux écarts par rapport à mes recommandations : D1 (les 7 phases plutôt que 1-3) et D2 (override tout de suite). Les deux sont assumés et encadrés — D1 par la validation à chaque frontière de phase et les sauvegardes datées.
Le plan complet fait sept phases. Rien n'oblige à tout faire d'un coup.
Pourquoi A. Tu valides l'ergonomie de l'adressage — celle que tu utiliseras tous les jours dans l'outil — avant d'engager le calcul des stats, qui est la partie où une erreur se voit le moins et coûte le plus. Les phases suivantes restent ouvertes et ne redemandent aucun travail jeté.
override tout de suite, ou trois couches pour commencer ?override est le seul vrai facteur multiplicatif : il s'applique isolément au lieu de se cumuler avec les autres.
Pourquoi A. Aucun effet de ton jeu n'en a besoin aujourd'hui, et ajouter la couche plus tard ne casse rien : c'est un champ supplémentaire, les données existantes restent valides sans migration. C'est une décision réversible à bas coût — autant ne pas la payer maintenant.
Trois fungling empoisonnent le joueur. Poison : 3 dégâts/seconde par pile, maximum 3 piles.
Pourquoi A. C'est le seul des deux où max_stacks garantit réellement un plafond de dégâts — donc le seul équilibrable. B reste disponible effet par effet quand tu le veux explicitement.
Fournis automatiquement pour toutes les entités d'une collection, sans rien déclarer.
| Collection | Champs automatiques |
|---|---|
enemies | total_killed, total_spawned, times_damaged_player |
ingredients | owned, total_collected, total_spent |
recipes | total_cooked, total_served, can_cook |
upgrade_nodes | purchased, state |
customer_profiles | total_served, total_left_angry |
Faible enjeu. Ajouter un champ plus tard, c'est une ligne dans le catalogue. Ne bloque pas sur cette liste — dis-moi juste s'il en manque un que tu sais déjà vouloir.
Pourquoi A. C'est le cas où la bonne pratique générale n'est pas la bonne application : à cette échelle, B n'apporte aucun gain mesurable et ajoute des abonnements fantômes et des ordres de mise à jour subtils. Et comme Registry.write() est le point de passage unique, B reste greffable plus tard sans rien réécrire.
Ton exemple disait element.monsters.id.variable. En gardant les noms du fichier maître, ça donne :
// ton exemple
element.monsters.turkey_clown.total_killed
// ce que ça devient réellement
element.enemies.turkey_clown.total_killed
Pourquoi confirmer. Ce préfixe sera tapé dans chaque condition et chaque effet, pour toujours. Si tu préfères entity. ou data. à element., c'est maintenant — après, c'est une migration de toutes les données.
Il n'existe aucun système d'arme ou d'équipement dans le jeu aujourd'hui. J'ai proposé que l'équipement soit une source dérivée — lue en direct depuis l'emplacement équipé, jamais stockée dans la table.
Aujourd'hui, la seule source dérivée est upgrade:. Je construis quand même l'interface de fournisseur — elle coûte presque rien — mais je ne construis pas d'équipement tant que tu ne le demandes pas.
Ce que ça change. Si l'équipement arrive bientôt, je dimensionne l'interface pour plusieurs emplacements dès la phase 5. Sinon, un fournisseur unique suffit.
statistics et fact_values ?Aujourd'hui le même compteur est écrit dans deux dictionnaires, et load_game() contient de la logique de réconciliation. La phase 2 les fusionne. Si ta sauvegarde actuelle a divergé entre les deux, il faut une règle.
Pourquoi A. Cohérence avec ce qui était affiché. En pratique les deux valeurs sont presque toujours identiques — c'est une règle de sûreté, pas un cas courant.
Suivi
Une copie de sauvegarde datée est prise avant chaque phase, dans _backups/. La suite complète — parse éditeur, smoke test, upgrade return, lint PHP et JS — doit être verte avant de passer à la suivante.
| Phase | Contenu | État | |
|---|---|---|---|
0 | Sauvegarde initiale | Copie complète avant toute modification | fait |
1 | Résolveur d'adresses | AddressCatalog + Registry, catalogue de champs, traduction des conditions héritées. Aucune donnée modifiée. | fait |
2 | Compteurs unifiés | statistics supprimé, compteurs par entité alimentés par le jeu, dungeon.gd:68 supprimé. Sauvegarde 6 avec migration. | fait |
3 | Sélecteur dans l'outil | Listes en cascade, validation PHP miroir, schéma 8, 27 conditions migrées vers des adresses. | fait |
4 | Crochets d'événement | 9 points de jeu instrumentés, effets déclaratifs plats validés des deux côtés, éditeur de crochets pour 5 collections. | fait |
5 | Couches et sources | Quatre couches, sources nommées, expirations, ordre set → add → multiply imposé. Bug de déterminisme corrigé. | fait |
6 | Effets temporaires | Collection effects, porteurs d'effets, empilement avec expiration par pile, drapeaux de capacité, persistance des effets du joueur. | fait |
7 | Retrait du format hérité | Le runtime ne connaît plus que les adresses et les couches. L'outil reste tolérant à l'import. | fait |
Le substrat, oui. L'équipement lui-même, non. Armes, armures, emplacements, skills activables et sets par contexte sont une fonctionnalité distincte, à construire une fois ce socle en place.