feat: issues de rencontre par équipe (#55) #65

Merged
Reliodas merged 1 commit from feature/55-team-outcomes into develop 2026-06-22 06:40:23 +00:00
Owner

Closes #55.

Adapte les sorties de rencontre au groupe : un membre à terre ne termine plus abusivement le combat, et les survivants gardent leur état. Septième pierre du jalon 0.16.0 (dépend de #54). Le combat raisonne par équipe pour la victoire, la défaite et la fuite, et le retour à l'exploration repart avec un leader valide.

Changements & politiques

  • Acteur tombé ignoré : CombatController._resume() saute le tour d'un combattant mort (not actor.is_alive()). La chute d'un membre — leader inclus — ne termine donc pas le combat tant que son équipe a un survivant.
  • Victoire : neutralisation de toute l'équipe ennemie (déjà calculée par équipe en #54 via is_combat_over / _team_has_living).
  • Défaite (politique de groupe) : chute de tout le groupe → la politique 0.15.0 est conservée (World._handle_defeat recharge la dernière autosave).
  • Fuite (politique de groupe) : collective pour 0.16.0 — le groupe se désengage ensemble (le bouton « Fuir » termine la rencontre ; les hostiles non vaincus persistent comme avant).
  • Leader valide au retour : GameState.ensure_valid_leader() conserve le leader s'il est vivant, sinon désigne le premier membre actif vivant (ordre déterministe), ou "" si le groupe est entièrement à terre. Les membres tombés restent au roster (état « à terre »), jamais retirés ni dupliqués.
  • Survivants synchronisés : World._sync_surviving_allies() reporte la position de fin de combat de chaque compagnon vivant vers le monde (jeton suiveur + member_pos_by_map) ; si le protagoniste est tombé, le jeton joueur suit le nouveau leader. L'autosave reste émise au retour à l'exploration (victoire comme fuite).

Critères d'acceptation

  • la chute du leader ne termine pas le combat si un allié contrôlable peut continuer ;
  • la victoire exige la neutralisation de l'équipe ennemie ;
  • fuite et défaite ne perdent ni ne dupliquent les membres ;
  • le retour à l'exploration choisit un leader valide ;
  • les politiques sont documentées et testées avec au moins deux alliés et deux ennemis ;
  • le comportement solo reste inchangé.

Tests

Suite GUT complète verte : 260 tests / 858 assertions (depuis 255 / 824).

  • tests/unit/test_combat_outcomes.gd (2 alliés PLAYER + 2 gobelins) : la victoire exige les deux ennemis à terre ; la chute du leader ne termine pas le combat tant que des alliés contrôlables continuent (un acteur tombé n'est jamais joué) → victoire par survie d'équipe ; ensure_valid_leader() conserve un leader vivant, réélit un membre actif vivant quand le leader tombe (sans perdre/dupliquer de membre), et renvoie "" quand tout le groupe est à terre.
  • Tests de combat solo (test_combat_controller, test_world_combat_*) restent verts.

Validation manuelle (différée au #58)

La resynchronisation visuelle des jetons survivants et le repli du jeton joueur sur un nouveau leader (cas rare : protagoniste tombé mais victoire) seront vérifiés dans Godot au #58.

Closes #55. Adapte les sorties de rencontre au groupe : un membre à terre ne termine plus abusivement le combat, et les survivants gardent leur état. Septième pierre du jalon 0.16.0 (dépend de #54). Le combat raisonne par équipe pour la victoire, la défaite et la fuite, et le retour à l'exploration repart avec un leader valide. ## Changements & politiques - **Acteur tombé ignoré** : `CombatController._resume()` saute le tour d'un combattant mort (`not actor.is_alive()`). La chute d'un membre — **leader inclus** — ne termine donc pas le combat tant que son équipe a un survivant. - **Victoire** : neutralisation de **toute** l'équipe ennemie (déjà calculée par équipe en #54 via `is_combat_over` / `_team_has_living`). - **Défaite (politique de groupe)** : chute de **tout** le groupe → la politique 0.15.0 est conservée (`World._handle_defeat` recharge la dernière autosave). - **Fuite (politique de groupe)** : **collective** pour 0.16.0 — le groupe se désengage ensemble (le bouton « Fuir » termine la rencontre ; les hostiles non vaincus persistent comme avant). - **Leader valide au retour** : `GameState.ensure_valid_leader()` conserve le leader s'il est vivant, sinon désigne le premier membre actif vivant (ordre déterministe), ou "" si le groupe est entièrement à terre. **Les membres tombés restent au roster** (état « à terre »), jamais retirés ni dupliqués. - **Survivants synchronisés** : `World._sync_surviving_allies()` reporte la position de fin de combat de chaque compagnon vivant vers le monde (jeton suiveur + `member_pos_by_map`) ; si le protagoniste est tombé, le jeton joueur suit le nouveau leader. L'autosave reste émise au retour à l'exploration (victoire comme fuite). ## Critères d'acceptation - [x] la chute du leader ne termine pas le combat si un allié contrôlable peut continuer ; - [x] la victoire exige la neutralisation de l'équipe ennemie ; - [x] fuite et défaite ne perdent ni ne dupliquent les membres ; - [x] le retour à l'exploration choisit un leader valide ; - [x] les politiques sont documentées et testées avec au moins deux alliés et deux ennemis ; - [x] le comportement solo reste inchangé. ## Tests Suite GUT complète verte : **260 tests / 858 assertions** (depuis 255 / 824). - `tests/unit/test_combat_outcomes.gd` (2 alliés PLAYER + 2 gobelins) : la victoire exige les **deux** ennemis à terre ; la chute du leader **ne** termine **pas** le combat tant que des alliés contrôlables continuent (un acteur tombé n'est jamais joué) → victoire par survie d'équipe ; `ensure_valid_leader()` conserve un leader vivant, réélit un membre actif vivant quand le leader tombe (sans perdre/dupliquer de membre), et renvoie "" quand tout le groupe est à terre. - Tests de combat solo (`test_combat_controller`, `test_world_combat_*`) restent verts. ### Validation manuelle (différée au #58) La resynchronisation visuelle des jetons survivants et le repli du jeton joueur sur un nouveau leader (cas rare : protagoniste tombé mais victoire) seront vérifiés dans Godot au #58.
feat: évaluer victoire, défaite et fuite au niveau des équipes (#55)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
ci/woodpecker/pull_request_closed/woodpecker Pipeline was successful
7e221a9f33
Un combattant tombé (leader inclus) ne joue plus son tour : CombatController
saute les acteurs morts dans la boucle de tours, donc la chute d'un membre ne
termine pas le combat tant qu'un membre de son équipe survit. La victoire
exige la neutralisation de toute l'équipe ennemie ; la défaite est la chute
de tout le groupe (politique 0.15.0 conservée : rechargement autosave) ; la
fuite reste collective.

GameState.ensure_valid_leader() désigne un leader vivant parmi les membres
actifs au retour à l'exploration (les membres à terre restent au roster,
jamais retirés ni dupliqués). World synchronise les positions des survivants
vers le monde (jetons + member_pos_by_map) et fait suivre le jeton joueur au
nouveau leader si le protagoniste est tombé.

Tests : test_combat_outcomes.gd (victoire exige toute l'équipe ennemie à
terre ; chute du leader sans fin de combat tant qu'un allié PLAYER continue,
acteur mort jamais joué ; ensure_valid_leader conserve/réélit/échoue
proprement, 2 alliés + 2 ennemis). Cas solo inchangé. Suite 260 tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reliodas merged commit 51e44d1903 into develop 2026-06-22 06:40:23 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: jeux/beaulieu-sur-brume#65
No description provided.