|
| 1 | +# MVP — Gameplay |
| 2 | + |
| 3 | +## Fonctionnalités implémentées |
| 4 | + |
| 5 | +- Lancer de dés aléatoire (2×d6) — tour par tour |
| 6 | +- Détection automatique des Doubles (d1 === d2) |
| 7 | +- Calcul du Lucky (distance minimale) et du Looser (distance maximale) |
| 8 | +- Gestion des égalités avec prolongations (Lucky et Looser indépendants) |
| 9 | +- Bonus de gorgées cumulé à chaque prolongation (+1 par prolongation) |
| 10 | +- Règles spéciales suspendues pendant les prolongations |
| 11 | +- Affichage des gorgées uniquement quand Lucky et Looser sont désignés |
| 12 | +- Enchaînement des tours (mémoire du Lucky pour l'annonce suivante) |
| 13 | + |
| 14 | +--- |
| 15 | + |
| 16 | +## Fichiers concernés |
| 17 | + |
| 18 | +| Fichier | Rôle | |
| 19 | +|---|---| |
| 20 | +| `frontend/src/app/components/GameScreen.tsx` | Moteur de jeu complet | |
| 21 | + |
| 22 | +--- |
| 23 | + |
| 24 | +## Phases d'un tour |
| 25 | + |
| 26 | +``` |
| 27 | +Annonce → Lancer → Résultats |
| 28 | + ↓ (égalité) |
| 29 | + Prolongation(s) |
| 30 | + ↓ (résolu) |
| 31 | + Résultats (gorgées) |
| 32 | +``` |
| 33 | + |
| 34 | +### Phase Annonce |
| 35 | + |
| 36 | +- **Tour 1** : annonce automatique = 12 ("le plus"), pas de saisie |
| 37 | +- **Tours suivants** : le Lucky saisit un nombre entre 2 et 12 |
| 38 | + - Rappel affiché : "le moins" pour 2, "le plus" pour 12 |
| 39 | + - Validation : entier dans `[2, 12]` obligatoire |
| 40 | + |
| 41 | +### Phase Lancer |
| 42 | + |
| 43 | +- Les joueurs lancent **un par un** dans l'ordre de la liste |
| 44 | +- Chaque lancer : |
| 45 | + - Animation 700 ms (🎲🎲 bounce) |
| 46 | + - Génération `d1 = rollD6()`, `d2 = rollD6()` |
| 47 | + - `score = d1 + d2` |
| 48 | + - `isDouble = d1 === d2` |
| 49 | +- Le résultat (faces + score) s'affiche immédiatement dans la liste |
| 50 | +- Badges **Double** et **Marchand** affichés en temps réel si les règles sont actives |
| 51 | +- Quand tous ont lancé → bouton "Voir les résultats" |
| 52 | + |
| 53 | +### Phase Résultats |
| 54 | + |
| 55 | +- Classement par distance croissante à l'annonce |
| 56 | +- `distance = |score - annonce|` |
| 57 | +- **Lucky** : distance minimale → fond jaune + 🏆 |
| 58 | +- **Looser** : distance maximale → fond rouge + 💀 |
| 59 | +- Si égalité Lucky **et** Looser → le Lucky est résolu en premier |
| 60 | +- Section "Gorgées" affichée uniquement quand les deux sont désignés |
| 61 | +- Bouton "Nouveau tour" disponible uniquement quand tout est résolu |
| 62 | + |
| 63 | +--- |
| 64 | + |
| 65 | +## Calcul des gorgées |
| 66 | + |
| 67 | +### Lucky |
| 68 | + |
| 69 | +| Situation | Gorgées de base | + Prolongations | |
| 70 | +|---|---|---| |
| 71 | +| Score différent de l'annonce | 1 | +1 par prolongation Lucky | |
| 72 | +| Score exact (distance = 0) | 2 | +1 par prolongation Lucky | |
| 73 | + |
| 74 | +### Looser |
| 75 | + |
| 76 | +| Situation | Gorgées de base | + Prolongations | |
| 77 | +|---|---|---| |
| 78 | +| Toujours | 1 | +1 par prolongation Looser | |
| 79 | + |
| 80 | +### Double *(si règle activée)* |
| 81 | + |
| 82 | +| Valeur du dé | Gorgées | |
| 83 | +|---|---| |
| 84 | +| 1 (score 2) | 1 gorgée **ou** fait relancer un joueur au choix | |
| 85 | +| 2 à 6 | Autant de gorgées que la valeur du dé | |
| 86 | + |
| 87 | +### Marchand de sable *(si règle activée)* |
| 88 | + |
| 89 | +- Score de 3 (1+2) → immunité totale ce tour |
| 90 | + |
| 91 | +--- |
| 92 | + |
| 93 | +## Gestion des égalités (prolongations) |
| 94 | + |
| 95 | +### Principe |
| 96 | + |
| 97 | +Une prolongation est déclenchée si plusieurs joueurs partagent la même distance minimale (Lucky) ou maximale (Looser). |
| 98 | + |
| 99 | +- Lucky et Looser sont résolus **indépendamment** |
| 100 | +- Les prolongations Lucky et Looser ont chacune leur propre compteur |
| 101 | +- Les règles spéciales (Double, Marchand) sont **suspendues** pendant les prolongations |
| 102 | + |
| 103 | +### Flux |
| 104 | + |
| 105 | +``` |
| 106 | +Égalité détectée sur le Lucky ou le Looser |
| 107 | + → bouton "Lancer la prolongation" affiché |
| 108 | + → Phase Prolongation : |
| 109 | + - Seuls les joueurs à égalité relancent (tour par tour) |
| 110 | + - Même annonce que le tour principal |
| 111 | + - Enjeu affiché = 1 + numéro de prolongation |
| 112 | + - Bouton "Résoudre la prolongation" |
| 113 | + → nouvelle égalité → même joueurs relancent encore |
| 114 | + → désignation → retour aux Résultats avec Lucky/Looser mis à jour |
| 115 | +``` |
| 116 | + |
| 117 | +### Calcul de l'enjeu en prolongation |
| 118 | + |
| 119 | +``` |
| 120 | +enjeu = gorgées_de_base + numéro_de_prolongation |
| 121 | +
|
| 122 | +Exemple : |
| 123 | + - Prolongation 1 Lucky → Lucky distribue 1 + 1 = 2 gorgées |
| 124 | + - Prolongation 2 Lucky → Lucky distribue 1 + 2 = 3 gorgées |
| 125 | + - Score exact + Prolongation 1 → Lucky distribue 2 + 1 = 3 gorgées |
| 126 | +``` |
| 127 | + |
| 128 | +### Version hard *(non implémentée)* |
| 129 | + |
| 130 | +Les gorgées sont **doublées** à chaque prolongation au lieu d'être incrémentées. |
| 131 | + |
| 132 | +``` |
| 133 | +enjeu = gorgées_de_base × 2^numéro_de_prolongation |
| 134 | +``` |
| 135 | + |
| 136 | +--- |
| 137 | + |
| 138 | +## Logique métier |
| 139 | + |
| 140 | +### Génération d'un dé |
| 141 | + |
| 142 | +```ts |
| 143 | +function rollD6(): number { |
| 144 | + return Math.ceil(Math.random() * 6); // 1 à 6 inclus |
| 145 | +} |
| 146 | +``` |
| 147 | + |
| 148 | +### Calcul Lucky / Looser |
| 149 | + |
| 150 | +```ts |
| 151 | +distance = Math.abs(score - announcement) |
| 152 | + |
| 153 | +Lucky → joueurs avec distance === Math.min(...distances) |
| 154 | +Looser → joueurs avec distance === Math.max(...distances) |
| 155 | + |
| 156 | +// Égalité : length > 1 → prolongation |
| 157 | +``` |
| 158 | + |
| 159 | +### Résolution d'une prolongation |
| 160 | + |
| 161 | +```ts |
| 162 | +// Lucky : re-calcul du min parmi les joueurs à égalité |
| 163 | +// Si toujours égalité → même liste relance, compteur incrémenté |
| 164 | +// Si désigné → result.luckyPlayers = [winner] |
| 165 | + |
| 166 | +// Idem pour Looser avec le max |
| 167 | +``` |
| 168 | + |
| 169 | +### État géré dans GameScreen |
| 170 | + |
| 171 | +| Variable | Type | Rôle | |
| 172 | +|---|---|---| |
| 173 | +| `round` | `number` | Numéro du tour en cours | |
| 174 | +| `phase` | `'announce' \| 'roll' \| 'results' \| 'prolongation'` | Phase active | |
| 175 | +| `announcement` | `number` | Score cible du tour | |
| 176 | +| `luckyPlayer` | `Player \| null` | Lucky du tour précédent (pour l'annonce) | |
| 177 | +| `rolledDice` | `DiceRoll[]` | Lancers du tour principal | |
| 178 | +| `rollerIndex` | `number` | Index du joueur courant en phase lancer | |
| 179 | +| `result` | `RoundResult \| null` | Résultat calculé du tour | |
| 180 | +| `luckyProlongations` | `number` | Nombre de prolongations Lucky résolues | |
| 181 | +| `looserProlongations` | `number` | Nombre de prolongations Looser résolues | |
| 182 | +| `prolongation` | `ProlongationState \| null` | État de la prolongation en cours | |
| 183 | + |
| 184 | +--- |
| 185 | + |
| 186 | +## Choix techniques |
| 187 | + |
| 188 | +**Tour par tour pour le lancer** |
| 189 | +Sur un seul appareil, chaque joueur prend le téléphone à son tour. Ça reproduit la prise en main physique et évite la saisie manuelle des scores. |
| 190 | + |
| 191 | +**Prolongations Lucky et Looser indépendantes** |
| 192 | +Les deux peuvent se produire dans le même tour (ex. 3 joueurs à distance 2, 2 joueurs à distance 5). Chacune a son propre compteur et son propre flux de relance. |
| 193 | + |
| 194 | +**Règles spéciales suspendues en prolongation** |
| 195 | +Pendant une prolongation, l'enjeu est uniquement les gorgées du pot. Les Doubles ou Marchands générés en prolongation ne sont pas comptabilisés — conformément aux règles du jeu. |
| 196 | + |
| 197 | +**Affichage des gorgées bloqué tant qu'une égalité subsiste** |
| 198 | +La section "Gorgées" et le bouton "Nouveau tour" n'apparaissent qu'une fois Lucky et Looser désignés. Cela évite d'afficher un résultat partiel et incomplet. |
| 199 | + |
| 200 | +**Mémoire du Lucky entre les tours** |
| 201 | +`luckyPlayer` est mis à jour en fin de tour. En cas d'égalité non résolue (ne devrait pas arriver), il reste `null` et l'affichage de l'annonce est générique ("Le Lucky"). |
0 commit comments