---
description: Define game flow as structured YAML — loops, states, emotional arc, edge cases
---
# /godot-sequence — Définir le game flow en YAML

> **Synonymes** : sequence, séquence, flow, game loop, boucle, states, core loop, parcours, gameplay flow

Tu es un game designer. Ton rôle : transformer la vision du GAME_PLAN.md en un **flow de jeu structuré** — boucles, states, transitions, arcs émotionnels. Tout sur papier, zéro code.

---

## Sommaire

1. [Philosophie](#section-1--philosophie)
2. [Format YAML — Référence complète](#section-2--format-yaml--référence-complète)
3. [Boucles — Core, Meta, Session](#section-3--boucles--core-meta-session)
4. [Données séparées — data/*.yaml](#section-4--données-séparées--datayaml)
5. [Edge cases](#section-5--edge-cases)
6. [Process conversationnel](#section-6--process-conversationnel)
7. [Fichiers multiples (projets complexes)](#section-7--fichiers-multiples-projets-complexes)
8. [Checklist Review](#section-8--checklist-review)
9. [Pièges courants](#section-9--pièges-courants)

---

## Section 1 : Philosophie

- **Flow d'abord, code après** — on définit l'expérience AVANT de construire
- **Les boucles, pas les lignes** — un jeu a des cycles (core loop, meta loop, session)
- **Données séparées du flow** — le YAML de séquence décrit le QUOI, les data/*.yaml décrivent les VALEURS
- **Itérable** — on peut modifier l'équilibrage sans réécrire la séquence

**Quand l'utiliser** : après `/godot-plan`, avant `/godot-architecture`.
Le GAME_PLAN.md = vision. Le GAME_SEQUENCE.yaml = flow précis.

**Différence avec un parcours linéaire** : un jeu a des boucles imbriquées, pas un flow de A à Z. La core loop tourne des dizaines de fois par session.

---

## Section 2 : Format YAML — Référence complète

Le skill produit un fichier `GAME_SEQUENCE.yaml` à la racine du projet Godot :

```yaml
# GAME_SEQUENCE.yaml
meta:
  name: "Mon Platformer"
  type: "platformer"  # platformer, rpg, puzzle, arcade, sim, roguelike...
  version: 1

# --- Boucles de jeu ---
loops:
  session:
    description: "Du lancement à la fermeture"
    states: [splash, main_menu, gameplay, pause, game_over, victory]
    entry: splash

  core:
    description: "Une tentative de level"
    states: [explore, encounter, resolve, reward, advance]
    entry: explore
    parent: gameplay  # state de session qui contient cette boucle

  meta:
    description: "Progression inter-sessions"
    states: [select_level, upgrade, unlock]
    entry: select_level
    parent: main_menu

# --- Définition des states ---
states:
  splash:
    type: screen
    description: "Logo + titre"
    duration: 2s
    transitions:
      - to: main_menu
        trigger: auto

  main_menu:
    type: screen
    description: "Menu principal"
    elements: [play_button, settings_button, quit_button]
    transitions:
      - to: gameplay
        trigger: input
        guard: "save_exists OR new_game"
      - to: select_level
        trigger: input
        guard: "has_progress"

  gameplay:
    type: game
    description: "Le jeu en cours"
    contains_loop: core
    data_refs:
      - data/levels.yaml#current
      - data/player.yaml#stats
    transitions:
      - to: pause
        trigger: input.pause
      - to: game_over
        trigger: player.hp <= 0
      - to: victory
        trigger: level.complete

  pause:
    type: overlay
    description: "Menu pause"
    transitions:
      - to: gameplay
        trigger: input.resume
      - to: main_menu
        trigger: input.quit

  game_over:
    type: screen
    description: "Écran de défaite"
    transitions:
      - to: gameplay
        trigger: input.retry
      - to: main_menu
        trigger: input.quit

  victory:
    type: screen
    description: "Écran de victoire"
    transitions:
      - to: main_menu
        trigger: auto
        guard: "last_level"
      - to: gameplay
        trigger: auto
        guard: "!last_level"

  # Core loop states
  explore:
    type: game
    description: "Exploration libre"
    transitions:
      - to: encounter
        trigger: collision.enemy

  encounter:
    type: game
    description: "Engagement ennemi"
    data_refs:
      - data/enemies.yaml#current
    transitions:
      - to: resolve
        trigger: auto

  resolve:
    type: game
    description: "Phase de combat/action"
    transitions:
      - to: reward
        trigger: enemy.defeated
      - to: game_over
        trigger: player.hp <= 0

  reward:
    type: game
    description: "Butin et XP"
    transitions:
      - to: advance
        trigger: auto

  advance:
    type: game
    description: "Progression dans le level"
    transitions:
      - to: explore
        trigger: auto
      - to: victory
        trigger: level.complete

  # Meta loop states
  select_level:
    type: menu
    description: "Sélection de niveau"
    transitions:
      - to: gameplay
        trigger: input.select

  upgrade:
    type: menu
    description: "Améliorations"
    data_refs:
      - data/upgrades.yaml
    transitions:
      - to: select_level
        trigger: input.back

  unlock:
    type: menu
    description: "Déblocages"
    transitions:
      - to: select_level
        trigger: auto

# --- Arcs émotionnels ---
emotional_arc:
  core:
    explore: { tension: low, agency: high, note: "Découverte libre" }
    encounter: { tension: rising, agency: medium, note: "Défi identifié" }
    resolve: { tension: peak, agency: high, note: "Moment de skill" }
    reward: { tension: release, agency: low, note: "Satisfaction" }
    advance: { tension: neutral, agency: medium, note: "Anticipation" }

# --- Edge cases ---
edge_cases:
  - id: EC-01
    scenario: "Joueur meurt pendant un boss"
    expected: "Respawn au checkpoint, boss reset, pas de perte de progression"
    severity: critical
  - id: EC-02
    scenario: "Joueur quitte pendant une sauvegarde"
    expected: "Sauvegarde atomique, pas de corruption"
    severity: critical
  - id: EC-03
    scenario: "Joueur spam le bouton pause pendant une transition"
    expected: "Input ignoré pendant les transitions"
    severity: warning
```

### Types de states

| Type | Usage | Exemple |
|------|-------|---------|
| `screen` | Écran plein, pas de gameplay | Splash, menu, game over |
| `game` | Gameplay actif | Exploration, combat |
| `menu` | Interface de sélection | Level select, shop |
| `overlay` | Par-dessus le gameplay | Pause, inventory |
| `transition` | Animation entre deux states | Fade, wipe |

### Types de triggers

| Trigger | Usage | Exemple |
|---------|-------|---------|
| `auto` | Transition automatique | Après un timer, après un calcul |
| `input` | Action joueur | Click, touche, gesture |
| `input.{action}` | Action spécifique | `input.pause`, `input.jump` |
| `condition` | État du jeu | `player.hp <= 0` |
| `collision.{type}` | Contact physique | `collision.enemy`, `collision.pickup` |
| `timer.{duration}` | Après un délai | `timer.3s` |

### Guards

Les guards sont des conditions sur les transitions. Syntaxe : string avec opérateurs logiques.

```yaml
guard: "save_exists OR new_game"
guard: "!last_level"
guard: "player.gold >= item.cost"
guard: "has_key AND door.locked"
```

### data_refs

Liens vers les fichiers `data/*.yaml`. Format : `data/{fichier}.yaml#{clé}` (la clé est optionnelle).

```yaml
data_refs:
  - data/enemies.yaml#goblin
  - data/levels.yaml#current
  - data/player.yaml
```

### contains_loop

Indique qu'un state contient une boucle imbriquée. Le state `gameplay` contient la `core` loop.

---

## Section 3 : Boucles — Core, Meta, Session

Toujours identifier les **3 boucles**, même si la meta est triviale.

### Patterns par genre

| Genre | Core Loop | Meta Loop | Session Loop |
|-------|-----------|-----------|-------------|
| Platformer | run → die → retry | unlock levels → upgrade | boot → play → quit |
| RPG | explore → combat → loot | quest → level up → equip | boot → play → save → quit |
| Puzzle | observe → solve → advance | unlock packs → badges | boot → select → play → quit |
| Roguelike | floor → fight → loot → ascend | unlock → meta-upgrade | boot → run → death → restart |
| Arcade | play → score → die | leaderboard → unlock skins | boot → play → quit |
| Sim/Tycoon | build → earn → expand | milestone → unlock tools | boot → play → save → quit |

### Durée cible par boucle

| Boucle | Durée typique | Borne basse | Borne haute |
|--------|:------------:|:-----------:|:-----------:|
| Core | 30s – 2min | 10s (arcade) | 15min (RPG combat) |
| Session | 15 – 45min | 5min (mobile) | 2h+ (RPG) |
| Meta | Plusieurs sessions | — | — |

### Arc émotionnel

Chaque boucle a un arc émotionnel. Les champs :
- `tension` : low, rising, peak, release, neutral
- `agency` : low, medium, high (contrôle du joueur)
- `note` : description libre de l'émotion visée

---

## Section 4 : Données séparées — data/*.yaml

Créer les fichiers `data/` pendant la définition de séquence. Quand des valeurs numériques apparaissent dans la conversation, les extraire dans un fichier dédié.

### Convention

- Un fichier par domaine : `enemies.yaml`, `items.yaml`, `levels.yaml`, `player.yaml`
- Le YAML de séquence référence par chemin : `data/enemies.yaml#goblin`
- Format libre mais documenté

### Exemple : data/enemies.yaml

```yaml
goblin:
  hp: 30
  damage: 5
  speed: 100
  drop: [coin_small, coin_small, potion_hp]

orc:
  hp: 100
  damage: 15
  speed: 60
  drop: [coin_big, potion_hp, iron_shard]
```

### Exemple : data/player.yaml

```yaml
base:
  hp: 100
  speed: 200
  damage: 10
  gold: 0

progression:
  hp_per_level: 10
  damage_per_level: 2
  speed_per_level: 5
```

### Exemple : data/levels.yaml

```yaml
forest_01:
  enemies: [goblin, goblin, goblin]
  boss: null
  duration_target: 60s
  reward: 50

forest_02:
  enemies: [goblin, goblin, orc]
  boss: null
  duration_target: 90s
  reward: 80

forest_boss:
  enemies: [goblin, orc]
  boss: troll
  duration_target: 120s
  reward: 200
```

---

## Section 5 : Edge cases

Lister les scénarios critiques. Minimum **3 edge cases** par jeu.

### Severities

| Severity | Signification | Exemple |
|----------|--------------|---------|
| `critical` | Bloquant — doit être géré avant le build | Corruption de save, crash, perte de progression |
| `warning` | Dégradé — le jeu fonctionne mais mal | Animation glitchée, UI décalée pendant transition |
| `info` | Cosmétique — nice to have | Texte tronqué dans un edge case de UI |

### Edge cases universels (à vérifier pour tout jeu)

1. **Mort pendant un boss** — respawn où ? boss reset ?
2. **Quit pendant une sauvegarde** — atomicité ?
3. **Input pendant les transitions** — buffer ou ignore ?
4. **Alt-tab / perte de focus** — pause auto ?
5. **Retour après longue absence** — contexte toujours compréhensible ?

---

## Section 6 : Process conversationnel

Construire le YAML **au fil de la conversation**, pas tout d'un coup.

### Questions à poser dans l'ordre

1. **"Décris ce que vit le joueur du boot au game over"** → session loop
2. **"Qu'est-ce qui se répète ? C'est quoi un cycle typique ?"** → core loop
3. **"Qu'est-ce qui change entre deux sessions ?"** → meta loop
4. **"Pour chaque moment, quelle émotion ?"** → emotional arc
5. **"Qu'est-ce qui peut mal tourner ?"** → edge cases

### Données numériques

Quand le user mentionne des chiffres (HP, dégâts, durées, coûts), proposer de les extraire dans `data/*.yaml`.

### Itération

Ne pas chercher le YAML parfait du premier coup. Première passe = structure brute. On itère ensuite avec `/godot-simulate`.

---

## Section 7 : Fichiers multiples (projets complexes)

### Quand split

- +10 states OU +3 boucles OU monde ouvert

### Convention

`GAME_SEQUENCE.yaml` reste le master et importe les sous-fichiers :

```yaml
imports:
  - sequences/zone_forest.yaml
  - sequences/zone_dungeon.yaml
  - sequences/boss_encounters.yaml
```

Chaque sous-fichier ne contient QUE les states de son scope. Les boucles restent dans le master.

---

## Section 8 : Checklist Review

Avant de valider le YAML :

- [ ] Les 3 boucles (session, core, meta) sont identifiées
- [ ] Chaque state a au moins 1 transition sortante
- [ ] Pas de states orphelins (jamais atteints depuis entry)
- [ ] Les data_refs pointent vers des fichiers existants (ou à créer)
- [ ] L'arc émotionnel de la core loop est défini
- [ ] Au moins 3 edge cases documentés
- [ ] Les guards sont cohérentes (pas de contradictions)
- [ ] Les durées cibles des boucles sont réalistes

---

## Section 9 : Pièges courants

| Piège | Solution |
|-------|---------|
| Trop de states dès le départ | Commencer avec 5-8 states, itérer |
| Core loop avec 1-2 states | C'est probablement juste une action, pas une boucle. Minimum 3 states |
| Pas de meta loop | Même triviale (high score), elle existe. Si vraiment rien : le jeu manque de rétention |
| Guards contradictoires | `save_exists` et `!save_exists` sur le même state = le joueur est bloqué |
| data_refs sans fichier | Créer le fichier data/*.yaml en même temps que le ref |
| Arc émotionnel plat | Si tout est "neutral", le jeu n'a pas de rythme. Forcer au moins un peak et un release |

---

## See also

| Skill | Quand l'utiliser |
|-------|-----------------|
| `/godot-plan` | Définir la vision avant la séquence |
| `/godot-simulate` | Tester la séquence sur papier |
| `/godot-gate` | Valider avant de construire |
| `/godot-architecture` | Scaffolder le projet après validation |
