# Outil narratif pour Big Egg — analyse et proposition

29/09/2026 · Statut : **proposition, rien n'est codé**. À rediscuter avant tout chantier.

---

## 1. En bref

- **Taskmaster3000 est bien le générateur le plus avancé** de `chrono island`
  (c'est la « Branch 2 »). Les autres copies sont plus anciennes.
- **Big Egg a déjà le moteur narratif dans ses données**, et c'est la vraie
  surprise de l'analyse. Quêtes, déclencheurs, personnages à répliques
  conditionnelles, scènes, facts et objets de quête existent déjà, tous reliés
  par un langage d'adresses commun (`fact.x`, `quests.x.state`,
  `rooms.x.current`…). Tout a été construit sur la quête de Bob (schémas 86 à 90).
- Le vrai manque n'est donc pas un moteur. Il en manque deux autres choses :
  1. **voir d'un coup d'œil** une histoire aujourd'hui éclatée sur une douzaine
     d'onglets ;
  2. **planifier** ce qui n'existe pas encore sans polluer les données du jeu.
- **Recommandation : une vue « Trame » dans le gestionnaire de données.**
  - Elle **lit** les vraies données et en calcule le graphe automatiquement.
  - Elle ajoute un **calque de plan** séparé pour les idées : un fichier à
    part, hors du maître.
  - L'écriture directe (création rapide de fiches) vient plus tard et passe par
    le brouillon existant.
- Point clé : un arbre libre non connecté (le port de Taskmaster) ne coûterait
  **pas moins cher** que la vue connectée, et vieillirait mal (voir §7).

---

## 2. Vérification des générateurs de chrono island

| Emplacement | État |
|---|---|
| `GODOT/chrono-island/Taskmaster3000/` | **Le plus récent.** Seul à avoir `narrative/js/selection-popups.js`, `narrative-sidebar-v2.js` et le cœur unifié `core/data/master.json`. Sauvegardes du maître jusqu'au 10/02/2026. |
| `BACKUP TASKMASTER/` (racine, `Taskmaster3000`, `branch 1`, `_OLD`, `- Copy`) | Versions antérieures : narrative sans sidebar V2 ni popups, données en fichiers séparés. |
| `CONTEXTE GPT/` | Deux vieux exports `narrative_*.json`, sans code. |
| `sideprojects/` | Un tutoriel Blender, rien de narratif. |

Taskmaster contient quatre outils : **Narrative** (le canevas d'histoire),
**Scheduler** (frise temporelle de la boucle), **Locations** (carte des lieux)
et des pages de **Gestion** (acteurs, intrigues, facts, segments).

---

## 3. Ce que fait Taskmaster, et ce qu'il vaut pour Big Egg

### Modèle de données (`core/data/master.json`)

- `intrigues` (≈13) : fils d'histoire colorés.
- `actors` (≈38), `locations` (≈50), `environments`.
- `facts` (≈437) : clé, type, valeur par défaut, politique de remise à zéro
  par boucle.
- `master_segments` (≈175) : titre, résumé, texte, intrigues, acteurs, lieu,
  **conditions** (facts reliés par un opérateur ET/OU), **conséquences**
  (facts), parents/enfants, branche principale, et un bloc `scheduler`
  (temps de début/fin, états d'acteurs).

Sa meilleure idée : une **flèche se trace toute seule** quand la conséquence
d'un segment est la condition d'un autre.

### Taille du code narratif

| Fichier | Lignes |
|---|---|
| `narrative.js` | 3 888 |
| `connections.js` | 1 168 |
| `narrative-sidebar-v2.js` (0.9-alpha, inachevée) | 1 087 |
| `canvas.js` | 1 045 |
| `selection-popups.js` | 368 |
| CSS narrative | ≈ 2 250 |
| `core/api.php` | 1 146 |

### À reprendre

- Canevas : déplacement, zoom de 25 à 200 %, glisser-déposer, grille magnétique.
- Flèches automatiques conséquence → condition, avec interrupteur d'affichage.
- Couleurs par intrigue, filtres, filtre « branche principale ».
- Suivi : liste de tâches, segments marqués `!!` (à continuer) et `%%` (à déterminer).
- Popups de multi-sélection avec bouton « + Nouveau ».
- Annuler / refaire.

### À laisser

- **Scheduler et temps** : la boucle temporelle est propre à Chrono Island.
- **Environnements et carte des lieux** : Big Egg a des salles tirées par un
  générateur de plongée, pas une carte.
- **Champs doublés** hérités de migrations successives : `title`/`titre`,
  `actor_ids`/`personnages`, `intrigue_ids`/`intrigues`,
  `position`/`x`/`y`/`taille`… Chaque segment porte deux fois ses données.
- Pages de migration, API `core/` séparée, sidebar V2 inachevée (conditions
  ET/OU et connexions marquées « à finaliser »).

**Verdict** : reprendre les **idées** et des **morceaux** du canevas et des
flèches, pas porter l'application telle quelle.

---

## 4. Ce que Big Egg a déjà

| Besoin | Où il vit déjà | Remarque |
|---|---|---|
| **Acteurs** | `characters` : nom, style de boîte, portrait 3D, **répliques conditionnelles** | Incarnés dans une salle par un `room_elements` de genre `npc` ou `shop` (`character: "bob"`). Aussi `customer_profiles` (client spécial `bob_guest`) et `employees`. |
| **Quêtes** | `quests` : journal, étapes, donneur, portée, plat à mettre de côté | État `quests.x.state` (0 inconnue, 1 en cours, 2 réussie, 3 échouée) et étape `quests.x.stage`. |
| **Moments** | `story_triggers` : conditions **qui deviennent** vraies, lieu (restaurant, donjon ou partout), une fois ou répétable, scène, effets `on_fired` | Motif du « fait réarmé » pour les moments répétables. |
| **Scènes** | `story_scenes` : texte, dialogue, choix, attente, déplacement, **valeur** (`set_value`), aller à… | Une scène peut faire avancer une quête. |
| **Conditions** | Langage d'adresses (`AddressCatalog`, miroir JS dans l'éditeur) | Liste lue en **ET** ; opérateurs `==`, `>=`, `truthy`, `falsy`… |
| **États** | `game_facts` (portées `run`, `dimension`, `meta` ; catégorie `story`) | 4 facts pour Bob. |
| **Objets** | `key_items` (`owned`, portée, perdu au KO, consommé…) | |
| **Salles** | `rooms` : **111 salles** (d1 à d4, `ft_*`, salles spéciales Bob, Musicalo, MLD) | Conditions d'apparition, `replaces` (remplace un niveau avec une chance), vagues conditionnelles, `on_enter`, `on_cleared`. |
| **Récompenses** | ⚠ `rewards` désigne les **bonus de plongée** (roguelite), pas des récompenses de quête. | Une récompense de quête est aujourd'hui un **effet** : `weapons.egg_launcher.owned = true`. |

### La quête de Bob, telle qu'elle existe aujourd'hui

Pour lire cette seule quête, il faut ouvrir **plus de 25 fiches dans une
douzaine d'onglets** :

- 1 quête, 1 personnage (4 répliques) ;
- 9 déclencheurs et une douzaine de scènes ;
- 4 facts, 1 objet de quête, 1 plat, 1 client spécial, 1 employé, 1 arme ;
- 5 salles et 1 élément PNJ.

Ce que ces fiches racontent, en résumé :

```
salle d1_l04 (serre)  ──►  déclencheur « El Tuna, 1re rencontre »  ──►  quests.bob.state = 1
                                                                          │
client bob_guest attablé ──► « Bob entre au restaurant » ──► stage = 1 ◄──┘
                                                               │
             salle « planque de Bob » (apparaît si state==1 et stage>=1) ◄┘
                    │  PNJ bob_npc  ──  disparaît si fact.bob_angry
                    │  on_cleared ──► fact.bob_after_fight ──► « Bob s'excuse »
                    ▼
      plat servi / objet bob_dish_to_go ──► state = 2 ──► « Bob donne le Lance-œufs »
                                                          └─► weapons.egg_launcher.owned
```

**Aucune vue du projet ne montre ce schéma aujourd'hui.** C'est exactement le
trou que l'outil doit combler.

---

## 5. Où vivent les conditions : salle, PNJ, ou les deux ?

**Les deux, et c'est une bonne chose.** Chaque couche répond à une question
différente, et le jeu les sépare déjà proprement :

| Question | Où | Exemple Bob |
|---|---|---|
| La salle existe-t-elle dans cette plongée ? | `rooms.x.conditions` (+ `replaces`) | La planque n'apparaît que si la quête est en cours et à l'étape 1 ou plus. |
| Qui s'y bat ? | `rooms.x.waves[].conditions` | Bob revient combattre si `fact.bob_angry`. |
| Le PNJ est-il là ? | `room_elements.x.vanish_conditions`, `required_item` | `bob_npc` disparaît quand Bob est fâché. |
| Que dit-il ? | `characters.x.dialogues[].conditions` (la première vraie gagne) | `bob_bye` → `bob_fed` → `bob_waiting` → `bob_hungry` |
| Quand un moment se joue-t-il ? | `story_triggers.x.conditions` + lieu | « El Tuna » : en entrant dans la serre, quête inconnue, sans lance-œufs. |
| Qu'est-ce que ça change ? | `on_fired`, `on_enter`, `on_cleared`, valeur dans une scène | `quests.bob_hungry_horse.state = 1` |

**Règle proposée** :

- la **salle** dit *où* et *si* ;
- le **PNJ** dit *qui* et *quoi dire* ;
- le **déclencheur** dit *quand* ;
- la **quête** tient le *journal* et *l'état*.

L'outil ne doit pas inventer un cinquième endroit : il doit **montrer les
quatre ensemble**.

### Le OU

Le langage de Big Egg n'a **pas de OU**, contrairement à Taskmaster. Le jeu le
contourne déjà de trois façons :

- plusieurs répliques pour un même personnage ;
- plusieurs déclencheurs pour un même moment ;
- un champ de comptage, comme `purchased_parents >= 1` pour dire « au moins un
  parent acheté ».

Le plan peut accepter un OU libre, signalé « à traduire » au moment de le
réaliser.

---

## 6. Récompenses : la liste qui manque

Tu as raison, il manque un endroit où **nommer et choisir** une récompense.
Bonne nouvelle : ce catalogue **se calcule** à partir des adresses que le jeu
permet déjà d'écrire.

| Catégorie | Adresse écrite | Exemple |
|---|---|---|
| Arme | `weapons.<id>.owned` | Lance-œufs |
| Objet de quête | `key_items.<id>.owned` (+/−) | Plat à emporter de Bob |
| Matériau | `ingredients.<id>.owned` | 25 viandes de dindon |
| Pièces | `player.coins` | |
| Déblocage | `fact.<id>` lu ailleurs par une condition | `fact.bob_joined` → Bob embauchable gratuitement |
| Bonus de plongée | collection `rewards`, `reward_choices` d'une salle | à part : ce n'est pas une récompense de quête |

Le sélecteur afficherait les noms (`display_name`) groupés par catégorie, avec
une entrée « + à créer » qui reste du texte dans le plan tant que la fiche
n'existe pas.

**Question ouverte** : faut-il une fiche nommée « récompense de quête »
réutilisable, ou l'effet sur une adresse suffit-il ? Je pencherais pour
l'effet seul au départ, puisque le catalogue calculé donne déjà les noms.

---

## 7. Trois niveaux d'ambition

| | A. Arbre libre (port de Taskmaster) | **B. Vue « Trame » connectée en lecture + plan** | C. Écriture directe |
|---|---|---|---|
| Voit ce qui existe dans le jeu | Non | **Oui, automatiquement** | Oui |
| Planifie ce qui n'existe pas | Oui | **Oui (calque de plan)** | Oui |
| Double saisie | Oui : tout est retapé | Non | Non |
| Dérive des noms dans le temps | Rapide | Nulle sur le réel | Nulle |
| Risque sur les données du jeu | Aucun | **Aucun** (fichier séparé) | Réel : l'auteur publie en parallèle |
| Coût | Moyen : le port traîne 8 000 lignes et leur dette | **Moyen** | Gros |
| Impact Godot | Aucun | **Aucun** | Aucun direct, mais passe par la publication |

A et B coûtent à peu près pareil, parce que le port de Taskmaster demande de
démêler le scheduler et les champs doublés. B rapporte beaucoup plus. C doit
venir **après** B, une fois que tu auras vécu avec la vue.

---

## 8. Proposition détaillée : niveau B

### 8.1 Emplacement

Un **module à part dans le gestionnaire de données**, comme `balance.js` ou
`audio_editor.js` : `assets/trame.js`, plus un onglet « Trame » dans le groupe
Histoire.

Pourquoi là plutôt qu'une page séparée ? Parce que le module profite de ce que
le gestionnaire a déjà :

- l'objet `data` déjà chargé, **brouillon compris** : on voit ce qu'on vient de
  saisir, même non publié ;
- les noms affichés, et la navigation par référence (un clic sur un nœud ouvre
  sa fiche dans l'onglet voisin) ;
- **pas de second écrivain** concurrent sur les données. C'est le risque connu :
  tu publies depuis le navigateur pendant que je travaille.

### 8.2 Le graphe calculé

**Nœuds** :

- Quête ;
- Moment (déclencheur) ;
- Réplique (personnage × rang) ;
- Scène ;
- Salle ;
- PNJ (élément de salle) ;
- État (une adresse : fact, objet, `quests.x.state`…) ;
- Récompense.

**Arêtes** :

- **Écrit → lit** : un effet qui écrit l'adresse P est relié à toute condition
  qui lit P. C'est la flèche automatique de Taskmaster, mais calculée depuis
  les vrais champs plutôt que depuis du texte tapé. Les effets comptés sont
  `on_fired`, `on_enter`, `on_cleared`, valeur de scène, `on_taken`, etc.
- **Structure** : déclencheur → scène, réplique → scène, salle → PNJ, PNJ →
  personnage, quête → donneur, choix de scène → branche.

**Regroupement par quête** : on part de tout ce qui lit ou écrit
`quests.<id>.*`, puis on suit les facts que ces fiches touchent. Le plan peut
corriger à la main un rattachement faux.

### 8.3 Les contrôles gratuits

Le graphe donne un **vérificateur de cohérence narrative** presque sans effort
supplémentaire :

- **lu mais jamais écrit** : condition morte, la quête est bloquée ;
- **écrit mais jamais lu** : l'effet ne sert à rien ;
- salle d'une quête qui ne peut jamais apparaître, déclencheur au lieu
  inatteignable ;
- scène référencée mais absente, personnage que **aucun PNJ n'incarne** ;
- réplique masquée : une réplique sans condition placée au-dessus d'autres.

C'est la famille de pannes « config bien remplie que rien n'émet », invisible
des tests d'exécution comme des tests de données.

### 8.4 Le calque de plan

Un fichier `tools/game-data-manager/data/narrative_plan.json`, suivi par git
mais **hors du maître** : pas de schéma, pas de publication, rien côté Godot.

Il contient :

- les positions des nœuds et les couleurs d'intrigue ;
- des **cartes d'idée**. Chacune a :
  - un titre et un résumé ;
  - des acteurs, réels ou « à créer » ;
  - une salle ou un moment de la partie (dimension), réels ou « à créer » ;
  - des conditions, en texte libre ou en adresse ;
  - une récompense, prise dans le catalogue ou en texte ;
  - un statut : idée, à faire ou en jeu ;
  - les marqueurs `!!` et `%%` de Taskmaster ;
- des liens manuels entre cartes ;
- le **rattachement** d'une carte à une fiche réelle quand elle est faite :
  la carte en pointillés devient pleine.

Option : une carte peut citer « ligne N du Sheet ».

### 8.5 Vues et filtres

- Par quête, par personnage, par salle ou dimension.
- **Chaîne d'une adresse** : tout ce qui touche `fact.bob_joined`.
- Branche principale seule.
- Réel seul, plan seul, ou les deux.

### 8.6 Hors périmètre de B

Aucune écriture dans `draft.json` ni dans le maître, aucun changement Godot.
Validation : un test JS ciblé, comme `story_tools_browser_test.js`.

---

## 9. Plus tard (niveau C) : création rapide

Depuis une carte d'idée : « Créer ce fact / cet objet / ce déclencheur /
cette quête ». L'outil crée une **fiche squelette dans le brouillon**, avec les
mêmes fonctions que le bouton « Ajouter » de l'éditeur. La publication normale
et sa validation PHP restent le seul passage vers le jeu. À envisager seulement
après quelques semaines d'usage de B.

---

## 10. Découpage suggéré

1. **Preuve sur Bob** : le graphe en lecture sur la seule quête de Bob. On doit
   y retrouver les 25 fiches et leurs liens, plus les contrôles « lu / écrit ».
   Si ce schéma ne t'aide pas, on arrête là, à faible coût.
2. **Canevas** repris de Taskmaster : déplacement, zoom, glisser, positions
   mémorisées dans le plan.
3. **Calque de plan** : cartes d'idée, statuts, suivi `!!` / `%%`.
4. **Sélecteurs** : catalogue de récompenses, acteurs, salles, conditions
   (adresses existantes ou texte).
5. *(C)* création de fiches squelettes.

---

## 11. Éléments que tu n'as pas cités, mais qui comptent

- **Durée ou portée** : `run`, `dimension` ou `meta`. Une quête qui repart de
  zéro à chaque dimension ne s'écrit pas comme une quête de méta.
- **Lieu du moment** : restaurant, donjon ou partout.
- **Une fois ou répétable.**
- **Moment de la partie** : dimension 1 à 4, rang d'apparition des salles.
- **Client spécial** et **plat de quête** : Bob vient manger au restaurant.
- **Employé débloqué** : Bob rejoint la brigade.
- **Textes à traduire** (`Loc`) et **sons** d'une scène.

---

## 12. Questions pour la suite

1. **Onglet** dans le gestionnaire de données, ou **page à part** ?
2. Tu veux planifier d'abord **une quête précise**, ou **l'arc global** (KMLD,
   Musicalo, MLD, dimensions 1 à 4…) ?
3. Récompense de quête : l'**effet sur une adresse** suffit-il, ou veux-tu une
   **fiche nommée** réutilisable ?
4. As-tu besoin du **OU** dans le plan ?
5. On commence par la **preuve sur Bob** (étape 1) ?
