feat: Sprint 3 — Prestige Loop endless
Some checks failed
CI/CD — Build & Deploy / Build & Deploy (push) Failing after 35s

- Migration saves: saveVersion pattern + migrateSave lazy (v1→v2)
- Formule ADN rebalancée: log10 + clamp min 1 + cap bonus ×4
- Prestige Experience: modal fullscreen, preview ADN, stats run, best run
- Arbre V2: 25 nœuds, 3 capstones, post-capstones repeatables (scaling par tranche)
- Convergence évolutif Alpha→Omega (tier system)
- Reset arbre: 1 gratuit/prestige, payant linéaire au-delà
- Milestones prestige: 8 paliers (1→100), cosmétiques exclusifs, bonus gameplay
- balance.ts: constantes centralisées pour playtest
- 136 tests green, 0 regression
This commit is contained in:
2026-03-28 18:24:24 +01:00
parent f80f071c24
commit ed8cf87d4e
22 changed files with 1917 additions and 158 deletions

View File

@@ -188,6 +188,43 @@ Brief technique : `docs/SPRINT2.md`
---
## Sprint 3 — Prestige Loop (endless)
Brief technique : `docs/SPRINT3.md`
| Feature | Design |
|---------|--------|
| Migration saves | Pattern `saveVersion` + `migrateSave()` — backward compat Sprint 2, lazy au chargement |
| Prestige Experience | Écran redesigné (preview ADN, stats run, comparaison), animation reset, hooks audio-ready |
| Arbre V2 endless | ~30 nœuds (3 branches approfondies), capstones game-changers, post-capstone repeatable (scaling par tranche ×1.5/×1.8/×2.0), cross-branche |
| Milestones prestige | 8 paliers (1→100 prestiges), cosmétiques exclusifs + bonus gameplay légers |
| Reset arbre | 1 gratuit par prestige, payant linéaire au-delà (5 ADN × n). Build exportable (fondation Sprint 4 sharing) |
| Formule ADN rebalancée | `max(1, floor(50 × log10(t/1e6) × (1 + min(0.05×p, 3.0))))` — clamp + cap bonus ×4 |
### Capstones par branche
| Branche | Capstone | Effet |
|---------|----------|-------|
| Ponte (click) | **Ponte Automatique** | Auto-click 1/sec, scale avec upgrades ponte |
| Marais (production) | **Symbiose Totale** | Chaque générateur booste les autres (+2% par type possédé) |
| Adaptation (utility) | **Mémoire du Marais** | Offline cap 25%→75%, durée 2h→8h |
### Profils joueurs émergents
- **Joueur Ponte** : joue activement, optimise les clics, capstone = auto-click idle
- **Joueur Marais** : optimise les achats générateurs, capstone = boucle multiplicative
- **Joueur Adaptation** : joue casual 2-3×/jour, capstone = idle puissant
## Hors scope Sprint 3
- Boucle 3 (méta, events, leaderboard, cross-promo TetaRdPG)
- Son / musique (prévu Sprint 4+ — hooks audio posés dans prestige)
- Mobile responsive / client natif Godot (projet séparé envisagé)
- Monétisation effective (boutique cosmétique payante)
- Analytics joueur (event log backend — Sprint 4)
---
## Changelog
| Date | Changement |
@@ -195,3 +232,5 @@ Brief technique : `docs/SPRINT2.md`
| 2026-03-17 | GDD initial — sprint1-step1, stack React+TS+Vite, mécaniques core |
| 2026-03-20 | Refonte game-designer — Tetard Universe, Arbre d'Évolution, anti-triche backend, SuperOAuth, stack confirmée Express |
| 2026-03-28 | Sprint 1 livré (6/6). Sprint 2 briefé — offline gains courbe inversée, arbre 3 voies, cosmétiques récompenses |
| 2026-03-28 | Sprint 2 livré (3/3). Sprint 3 briefé — prestige loop endless, arbre V2 30 nœuds, capstones, milestones, formule ADN rebalancée |
| 2026-03-28 | Sprint 3 brainstorm — 5 décisions : saveVersion migration, formule ADN clamp+cap, scaling post-capstone par tranche, reset 1 gratuit/prestige + vision build-sharing, Convergence évolutif (Alpha→Omega, nœud unique à tiers) |

315
docs/SPRINT3.md Normal file
View File

@@ -0,0 +1,315 @@
# SPRINT3.md — Prestige Loop
> Brief technique — Sprint 3
> Date : 2026-03-28
> Réf GDD : docs/GDD.md
> Dépend : Sprint 2 livré (3/3)
> Agents : game-designer (design) → build (implémentation)
---
## Objectif
Transformer le prestige d'une mécanique de reset en une **boucle de progression motivante et endless**. Le joueur doit sentir l'accélération à chaque génération, faire des choix de build durables, et viser des paliers qui récompensent la spécialisation.
---
## Pré-requis technique — Migration saves
> À traiter en amont de Step 1 — pas un step visible, mais bloquant.
### Pattern `saveVersion` + `migrateSave()` (décision session 2026-03-28)
Le GameState est stocké en JSON unique dans MySQL. Ajouter/modifier des champs
sans migration = `undefined` silencieux → NaN → bugs fantômes.
**Mécanisme :**
- Ajouter `saveVersion: number` au `GameState`
- Saves Sprint 2 existantes = version absente → traitées comme `v1`
- Sprint 3 = `v2`
- Fonction `migrateSave(state: unknown): GameState` appliquée au chargement
(frontend `useSaveSync` + backend `saveControllers`)
- `v1 → v2` : injecter defaults (`runStats` vide, `treeResetCount: 0`,
`freeResetAvailable: true`, `repeatableNodes: {}`, nouveaux nœuds arbre)
- Les 18 nœuds Sprint 2 conservent leur `id` — les nouveaux s'ajoutent
- Champ critique manquant → log warning + default safe (jamais de crash)
- Chaque sprint futur ajoute un step de migration (`v2 → v3`, etc.)
### Schéma DB
- `ALTER TABLE game_saves ADD COLUMN save_version INT DEFAULT 1`
- Pas de migration du JSON existant en DB — la migration est lazy (au chargement)
### Validation
- Charger une save Sprint 2 brute sur le nouveau code → `migrateSave` injecte v2
- Pas de perte de données, pas de reset forcé
- Les nœuds arbre existants (18) gardent leur position et état unlocked
---
## Steps
### Step 1 — Prestige Experience
**Scope :** Rendre le moment du prestige satisfaisant et informatif.
**Design :**
- Écran de prestige redesigné :
- Preview ADN gagné (avant de confirmer)
- Comparaison : "Run actuelle vs meilleure run" (durée, têtards, ADN)
- Compteur de générations (nombre total de prestiges)
- Statistiques de run persistées :
- Durée de la run
- Têtards produits (lifetime cette run)
- Vitesse de progression vs run précédente (% plus rapide / plus lent)
- Branche d'arbre principale utilisée
- Animation de reset : transition visuelle (le marais "renaît")
- Hooks audio-ready : prévoir les points d'ancrage pour le son (Sprint futur)
**Technique :**
- `PrestigeScreen.tsx` : composant modal fullscreen (pas un simple bouton)
- `RunStats` dans le GameState :
```ts
interface RunStats {
startedAt: number;
tadpolesProduced: number;
prestigeCount: number;
bestRun: {
duration: number;
tadpoles: number;
adn: number;
};
}
```
- Backend : persister `runStats` dans la save (même pattern save serveur)
- Rebalancer la formule prestige pour l'endless (voir section Formules)
**Critère done :** le joueur clique Prestige → voit un écran avec preview ADN + stats comparées → confirme → animation → nouvelle run. Les stats de la meilleure run sont persistées.
---
### Step 2 — Arbre d'Évolution V2 — Profondeur endless
**Scope :** Étendre l'arbre à ~30 nœuds avec capstones game-changers et scaling post-capstone infini.
**Design — Structure par branche :**
**Branche Ponte (click) — 8-10 nœuds :**
- Tier 1 : Ponte Améliorée (+100% click) — 1 ADN
- Tier 2 : Click Critique (5% chance ×10) — 5 ADN
- Tier 3 : Frénésie (click power +1% par click dans les 10 dernières sec, cap +50%) — 15 ADN
- Tier 3 alt (exclusif) : Concentration (+200% click, -25% idle) — 15 ADN
- Capstone : **Ponte Automatique** — auto-click 1/sec, scale avec upgrades ponte — 200 ADN
- Post-capstone (repeatable) : +5% auto-click speed, coût ×2 — départ 500 ADN
**Branche Marais (production) — 8-10 nœuds :**
- Tier 1 : Instinct Grégaire (+50% production tous générateurs) — 3 ADN
- Tier 2 : Spécialisation (un générateur au choix ×3) — 8 ADN
- Tier 3 : Écosystème (+10% prod par type de générateur possédé) — 25 ADN
- Tier 3 alt (exclusif) : Monoculture (un seul type ×5, les autres ×0.5) — 25 ADN
- Capstone : **Symbiose Totale** — chaque générateur booste les autres (+2% par type possédé) — 300 ADN
- Post-capstone (repeatable) : +1% symbiose, coût ×2 — départ 600 ADN
**Branche Adaptation (utility) — 8-10 nœuds :**
- Tier 1 : Mémoire Génétique (commence chaque run avec 100 têtards) — 2 ADN
- Tier 2 : Métabolisme Rapide (+25% offline cap) — 10 ADN
- Tier 3 : Héritage (conserve 5% des générateurs tier 1 entre prestiges) — 30 ADN
- Tier 3 alt (exclusif) : Mutation ADN (+25% ADN gagné au prestige) — 30 ADN
- Capstone : **Mémoire du Marais** — offline cap 25% → 75%, durée 2h → 8h — 250 ADN
- Post-capstone (repeatable) : +2% offline cap (au-delà de 75%), coût ×2 — départ 500 ADN
**Nœud cross-branche — Convergence (évolutif, décision session 2026-03-28) :**
Un seul nœud qui évolue quand le joueur atteint de nouveaux paliers de diversification.
Pattern `tier` sur le nœud — fondation pour d'autres nœuds évolutifs futurs.
```
Convergence Alpha (tier 1)
Condition : 1 capstone + tier 3 d'une 2e branche (~prestige 12-15)
Coût : 500 ADN
Effet : +10% à tous les effets de l'arbre
Convergence Omega (tier 2 — même nœud, upgrade auto)
Condition : 2 capstones atteintes
Coût : 500 ADN supplémentaires (total investi : 1000)
Effet : +10% tous effets + -20% coût post-capstones
```
Technique — champ `tier` sur `EvolutionNode` :
```ts
tier?: number; // 1 = Alpha, 2 = Omega (current level)
maxTier?: number; // 2
tierUpgradeCost?: number; // 500
tierUpgradeCondition?: string; // "2_capstones"
```
UX : notification "Convergence a évolué !" quand la condition tier 2 est remplie.
Le joueur voit sa récompense grandir — pas un 2e nœud à acheter séparément.
**Technique :**
- `DEFAULT_EVOLUTION_TREE` : ~30 nœuds (tree data structure, pas array)
- Ajouter `tier: number` et `repeatable: boolean` aux `EvolutionNode`
- `repeatableCount: number` dans le state pour les nœuds post-capstone
- UI : garder le layout 3 colonnes, ajouter scroll vertical par branche
- Capstones visuellement distincts (bordure dorée, icône spéciale)
- Cross-branche : section basse, verrouillée visuellement jusqu'aux conditions
- Convergence : badge évolutif (Alpha → Omega), indicateur de progression vers le prochain tier
**Reset arbre — 1 gratuit par prestige (décision session 2026-03-28) :**
Chaque prestige offre 1 reset gratuit (nouvelle génération = nouvelle chance de build).
Resets supplémentaires dans la même génération = payants.
```
freeResetAvailable: boolean // true après chaque prestige, false après usage
resetCostInGeneration: number = 5 × extraResetsUsed // linéaire, pas exponentiel
```
| Reset# (dans la même génération) | Coût ADN |
|----------------------------------|----------|
| 1er | Gratuit (offert par prestige) |
| 2e | 5 |
| 3e | 10 |
| 4e | 15 |
Pas punitif, encourage l'expérimentation, mais décourage le spam.
**Fondation build-sharing (Sprint 4+ vision) :**
Le build de l'arbre est exportable en string compacte (nœuds unlocked encodés).
Permet le partage de builds entre joueurs et les "runs prestige" communautaires.
→ Structurer l'arbre state pour faciliter l'export dès Sprint 3 :
`buildCode: string` = nœuds unlocked encodés base36 ou similaire.
**Critère done :** l'arbre affiche ~30 nœuds sur 3 branches + cross-branche, les capstones changent le gameplay de manière perceptible, les post-capstones sont achetables en boucle.
---
### Step 3 — Milestones de Prestige
**Scope :** Récompenser la persévérance avec des paliers de prestige qui débloquent cosmétiques exclusifs et bonus légers.
**Design :**
| Palier | Récompense | Type |
|--------|------------|------|
| 1 prestige | Badge "Première Génération" + ruban queue | cosmétique |
| 3 prestiges | Titre "Gardien Récurrent" | cosmétique |
| 5 prestiges | Start avec 1 Nid gratuit | gameplay léger |
| 10 prestiges | Skin "Têtard Ancestral" (body prestige) + couronne dorée | cosmétique |
| 15 prestiges | +5% offline cap permanent | gameplay léger |
| 25 prestiges | Cape d'algues ancestrales + aura prestige | cosmétique |
| 50 prestiges | Titre "Légende du Marais" + particules dorées permanentes | cosmétique |
| 100 prestiges | Skin "Têtard Primordial" (full set) | cosmétique |
- Les bonus gameplay sont **légers** — jamais assez pour casser l'économie
- Les cosmétiques prestige-only ne sont pas obtenables autrement (exclusivité = motivation)
- Écran milestones accessible depuis le menu prestige (progress bar vers le prochain palier)
**Technique :**
- `PrestigeMilestone` type :
```ts
interface PrestigeMilestone {
id: string;
threshold: number; // nombre de prestiges requis
reward: MilestoneReward;
claimed: boolean;
}
type MilestoneReward =
| { type: "cosmetic"; cosmeticId: string }
| { type: "bonus"; effect: EffectType; value: number }
| { type: "title"; title: string };
```
- Intégrer avec le système cosmétiques V1 existant — ajouter `source: "prestige_milestone"` aux cosmétiques
- UI : `MilestonesPanel.tsx` — liste verticale avec progress bar, claim button, preview reward
- Backend : valider les claims (le joueur ne peut pas claim un milestone sans le nombre de prestiges)
**Critère done :** atteindre 5 prestiges → notification milestone → claim → Nid gratuit actif + cosmétique dans l'inventaire.
---
## Formules — Rebalancing endless (décisions session 2026-03-28)
### Formule ADN (remplace l'actuelle)
Actuelle : `adn = floor(150 × sqrt(lifetime_tadpoles / 1e9))` — s'aplatit trop vite.
Nouvelle :
```
adn = max(1, floor(base × log10(tadpoles / threshold) × (1 + bonus)))
base = 50
threshold = 1e6 (1M têtards — seuil minimum pour prestige)
bonus = min(0.05 × prestigeCount, 3.0) // cap ×4 max à 80 prestiges
clamp = minimum 1 ADN si tadpoles >= threshold
```
| Run | Tadpoles | Prestige# | Bonus | ADN gagné |
|-----|----------|-----------|-------|-----------|
| 1 | 1M (seuil) | 0 | ×1.0 | **1** (clamp) |
| 1 | 10M | 0 | ×1.0 | **50** |
| 5 | 100M | 4 | ×1.20 | **120** |
| 15 | 1B | 14 | ×1.70 | **255** |
| 30 | 10B | 29 | ×2.45 | **430** |
| 80+ | 100B | 80 | ×4.00 | **800** (cap bonus atteint) |
La courbe log scale bien : récompense toujours plus, oblige à aller exponentiellement plus loin.
Le cap du bonus évite que l'endgame trivialise l'arbre.
### Courbe coût post-capstones — paliers par tranche
Le ×2 brut crée un mur après ~8 achats. Scaling par tranche :
```
Achats 1-5 : cost = base × 1.5^n
Achats 6-10 : cost = base × 1.5^5 × 1.8^(n-5)
Achats 11+ : cost = base × 1.5^5 × 1.8^5 × 2.0^(n-10)
```
| Achat# | Coût (base 500) | ~Runs nécessaires (400 ADN/run) |
|--------|-----------------|--------------------------------|
| 1 | 750 | ~2 |
| 5 | 3 797 | ~10 |
| 10 | 68 890 | ~172 |
| 15 | 2.2M | endgame long |
Chaque achat reste "quelques sessions" en mid-game, puis ralentit en endgame
sans frapper un mur infranchissable.
### Courbe coût nœuds standards
Définis manuellement par nœud (1, 3, 5, 8, 10, 15, 25, 30, 200, 250, 300, 500, 1000 ADN).
### Vérification d'équilibre
- Premier capstone : entre le 8e et 12e prestige (spécialisation une branche)
- Arbre "complet" (hors post-capstone) : ~15-20 prestiges
- Post-capstones : progression infinie, chaque achat = investissement plus lourd mais gain marginal
- Cross-branche : joueur dédié à 25+ prestiges
**Niveau de confiance : moyen** — les chiffres sont calibrés sur les formules mais devront être playtestés. Toutes les constantes centralisées dans `balance.ts` pour ajustement rapide.
---
## Résumé séquentiel
```
Migration saves → Step 1 (prestige experience) → Step 2 (arbre V2 endless) → Step 3 (milestones)
```
Step 1 = le moment. Step 2 = la profondeur. Step 3 = la motivation long terme.
---
## Risques identifiés
| Risque | Mitigation | Statut |
|--------|------------|--------|
| Formule ADN mal calibrée | Constantes dans `balance.ts`. Clamp min 1 + cap bonus ×4. Playtest après Step 1 | ✅ adressé |
| Capstones trop puissants (Ponte Auto trivialise) | Tester chaque capstone isolément. Auto-click = 1/sec de base | à tester |
| Post-capstone wall en late-game | Scaling par tranche (×1.5/×1.8/×2.0) au lieu de ×2 brut | ✅ adressé |
| Migration saves casse les joueurs existants | Pattern `saveVersion` + `migrateSave()` lazy. Saves Sprint 2 = v1, migrées automatiquement | ✅ adressé |
| Reset arbre frustrant | 1 gratuit par prestige + linéaire au-delà. Pas d'exponentiel | ✅ adressé |
| Arbre V2 complexe visuellement | Progressive disclosure : griser les nœuds non débloquables, tooltip clair | à tester |
| Build-sharing string : encodage fragile | Valider le décodage côté client. Nœud inconnu dans le code = ignoré (forward compat) | Sprint 4 |