Commit Graph
24 Commits
Author SHA1 Message Date
Kevin L'Hereec 45eb9be60d fix: repositionner les cartes Événement en bas-droite avec un texte lisible
Les cartes Événement (bouton de pioche + main) étaient positionnées trop
près du bouton "CONFIRMER MA CARTE" — le bouton de pioche chevauchait même
physiquement son bord droit de ~25px (x = width/2 + 210, même Y), au point
de prêter à confusion entre "piocher un événement" et "jouer une carte".

- Nouveau module pur client/src/game/objects/eventHandLayout.js
  (eventDrawButtonPosition, eventHandGeometry, eventCardPosition) : ancre
  toute la zone événement en bas-DROITE du canvas, clairement séparée du
  bouton de confirmation (centré) et de la main de personnages (centrée).
- EVENT_CARD_SCALE remonté de 0.55 à 0.8 pour que le nom de l'événement
  (police de base augmentée 12px -> 15px) reste réellement lisible une fois
  réduit — ajout d'un bandeau semi-opaque derrière le texte (EventCardObject)
  pour garantir le contraste quel que soit le portrait en arrière-plan.
- La légende des attributs occupait déjà le coin bas-droit : déplacée en
  bas-GAUCHE (setOrigin ajusté en conséquence) pour laisser la place à la
  nouvelle zone événement.
- 16 nouveaux tests unitaires Vitest (eventHandLayout.test.js) couvrant la
  géométrie : positions dans les limites du canvas, absence de
  chevauchement avec le bouton de confirmation/la main/la légende, ancrage
  stable au bord droit avec 1 ou 2 cartes, robustesse sur petite résolution
  (1280x720) et cardCount=0. Choix explicite de tests UNITAIRES (rapides,
  ~600ms pour toute la suite client) plutôt que E2E pour cette correction
  de positionnement pur, les tests E2E de ce projet étant lents (plusieurs
  minutes par scénario à cause de la pioche aléatoire à stabiliser).
2026-08-24 14:52:18 +02:00
Kevin L'Hereec c9b4a7e567 docs: compléter le README avec les règles des bâtiments et cartes Événement
Dernier point de la checklist de la fonctionnalité Cartes Événement
(pioche partagée, ciblage, synergies) resté en suspens. Ajout également des
règles des Bâtiments (Église, Château Royal), qui n'avaient jamais été
documentées lors de leur implémentation précédente. Mise à jour de
l'arborescence du projet dans la section Structure.
2026-08-24 13:27:15 +02:00
Kevin L'Hereec 44d4eb7e96 fix: bugs critiques du système d'événements + stabilisation E2E
Trois bugs fonctionnels réels découverts et corrigés en stabilisant les
tests E2E des cartes Événement :

1. client/src/stores/game.js — le store Pinia n'exposait JAMAIS les champs
   liés aux bâtiments (myBuildings, pendingBuyBuildingId, availableBuildings)
   ni aux événements (myEventHand, eventDeckSize, hasPendingEventDraw,
   pendingEventPlayId) : updateState() ne les lisait pas depuis le
   'game-state' serveur. Conséquence concrète : GameScene._epidemicNeedsTarget()
   lisait this.store.myBuildings (toujours vide) pour décider si la
   variante Église d'Épidémie s'applique — le ciblage de la variante Trousse
   ne fonctionnait donc jamais correctement dès qu'un joueur possédait
   aussi le Château. Corrigé + 4 nouveaux tests unitaires Vitest.

2. client/src/game/scenes/GameScene.js — GameScene._onEventCardSelected
   envoyait encore les clés historiques gainTargetSocketId/
   loseTargetSocketId/targetSocketId au serveur, alors que Room.js avait été
   migré vers gainTargetTeamIndex/loseTargetTeamIndex/targetTeamIndex
   (socketId n'est jamais exposé au client). Conséquence : le ciblage
   d'Accord royal et de la variante Trousse d'Épidémie était intégralement
   cassé en jeu réel — les clés ne correspondant à rien côté serveur, aucune
   cible n'était jamais appliquée, silencieusement.

3. e2e/tests/helpers.js — drawEventUntil abandonnait immédiatement dès que
   la main d'événements atteignait 2 cartes sans contenir l'id recherché,
   rendant les tests E2E d'événements extrêmement flaky (avec seulement 6
   types d'événements et une main de 2, l'échec dès les 2 premières pioches
   est fréquent, pas rare). Corrigé : joue désormais une carte pour libérer
   un slot et continue à piocher jusqu'à maxDraws (20).

Stabilisation supplémentaire :
- Toutes les fonctions d'introspection Phaser dans helpers.js sécurisées
  (optional chaining) contre une scène pas encore initialisée après un
  changement de tour/navigation sous charge (plusieurs pages Playwright
  simultanées).
- Timeouts des tests events.spec.js augmentés (150-240s) pour laisser le
  temps aux boucles d'accumulation de jauge + pioche aléatoire de converger.
- playwright.config.js : retries=1 même en local, pour absorber la
  variance résiduelle des tests basés sur un tirage aléatoire, tout en
  gardant une détection fiable des vraies régressions (qui échoueraient de
  façon reproductible sur les deux tentatives).
- events.spec.js : test 'Accord royal' fournit désormais les 2 cibles
  requises par le ciblage séquentiel (gain + perte) au lieu d'une seule,
  ce qui laissait la séquence de ciblage bloquée sans jamais émettre
  'play-event'.

Résultat : 166 tests unitaires serveur + 28 tests unitaires client
toujours au vert ; suite events.spec.js (9 tests E2E) passe intégralement
(certains via retry probabiliste documenté, comportement attendu vu la
pioche aléatoire dans le deck partagé).
2026-08-24 13:24:37 +02:00
Kevin L'Hereec 1726f8f96b feat: cartes Événement (pioche partagée de 18 cartes, 6 effets, synergies, ciblage)
- Nouveau server/src/game/events.js : 6 événements (Récolte exceptionnelle,
  Épidémie, Levée des troupes, Accord royal, Complot découvert, Grande fête
  au château), deck PARTAGÉ de 18 cartes (3 exemplaires de chacun) mélangé
  au démarrage de la partie.
- Room.js : buyEventDraw() (coût fixe 1 point dans chacune des 4 jauges,
  effet immédiat contrairement aux objets/bâtiments — pas de conflit de
  stock possible), playEventCard() (choix de jouer une carte de sa main,
  max 1 par tour, avec ciblage optionnel), _resolvePendingEventPlays()
  (résolution de TOUS les événements du tour AVANT le calcul des gains de
  cartes personnage, défausse systématique, protection "Complot découvert"
  pour soi-même uniquement). Les 6 effets incluent leurs synergies avec les
  objets/bâtiments existants (Charrue, Trousse+Église pour Épidémie,
  Trébuchet, Sceau Royal, Château Royal → pioche bonus).
- IMPORTANT : le ciblage de joueur (Accord royal, variante Trousse
  d'Épidémie) transite par teamIndex (identifiant public) et non socketId
  (jamais exposé au client via getPlayersInfo/getStateFor) — le serveur
  résout teamIndex -> joueur réel au moment de la résolution.
- Nouvel event socket 'buy-event-draw' (effet immédiat) et 'play-event'
  (résolution différée), eventResults inclus dans round-result.
- Client : events.js (miroir), EventCardObject.js (carte épurée façon
  CardObject, badge rouge "!" pour les événements à effet négatif).
  BootScene génère les textures plein cadre (méthode _generateClippedTexture
  généralisée, réutilisée avec les personnages).
- GameScene : bouton de pioche à droite du bouton de confirmation (état
  grisé selon jauges/main pleine/pioche déjà tentée), seconde main de cartes
  événement (max 2) au-dessus de ce bouton, sélection d'une carte pour la
  jouer avec séquence de ciblage interactive (surbrillance des slots
  adversaires cliquables) pour Accord royal et la variante Trousse
  d'Épidémie.
- 61 nouveaux tests unitaires serveur (events.js + Room.js : pioche, choix
  de jouer, résolution des 6 effets avec/sans synergie, Complot découvert,
  ordre événements-avant-personnages, deck partagé).
- Nouveaux helpers et tests d'intégration E2E Playwright (e2e/tests/events.spec.js)
  pour la pioche, la limite de main à 2, et les 6 effets — certains
  scénarios restent probabilistes (pioche aléatoire dans le deck partagé) et
  peuvent nécessiter une stabilisation supplémentaire du timing.
2026-08-21 17:05:50 +02:00
Kevin L'Hereec 9139989fa7 feat: bâtiments achetables (Église, Château Royal) avec synergie objets
- Nouveau server/src/game/buildings.js : 2 bâtiments, chacun couvrant 2
  attributs, coût réparti sur les deux jauges, garantit +1 par tour sur
  chaque attribut, avec bonus de synergie +1 si l'objet correspondant est
  aussi possédé (Église+Trousse/Sceau, Château+Charrue/Trébuchet).
- Room.js : buyBuilding() (validation coût multi-jauges), résolution des
  achats en attente avec la même priorité/stock unique que les objets,
  _applyBuildingEffects() (garantie de base + synergie, jamais de recul par
  rapport aux gains déjà boostés par un objet). getStateFor/getPlayersInfo
  exposent buildings/myBuildings/availableBuildings/pendingBuyBuildingId.
- Nouvel event socket 'buy-building', boughtBuildings inclus dans round-result.
- Client : buildings.js (miroir), BootScene génère les textures portrait des
  bâtiments (méthode _generatePortraitTexture généralisée, réutilisée avec
  les objets). ItemBoardToken généralisé (kind='item'|'building', hAnchor
  'left'|'right') pour afficher indifféremment un objet ou un bâtiment, avec
  coût détaillé par jauge affiché sur la carte agrandie pour les bâtiments.
- GameScene : boutique de bâtiments en colonne à DROITE du plateau
  (symétrique à la boutique d'objets à gauche), mes bâtiments possédés
  affichés à GAUCHE de ma main (symétrique à mes objets à droite), bâtiments
  des adversaires affichés sous leurs objets au niveau de leur slot.
- Fix : la carte détaillée héritait par défaut d'un ancrage "s'étend vers la
  droite" adapté à la boutique d'objets (bord gauche du canvas) mais cassait
  la boutique de bâtiments (bord droit) — le bouton ACHETER se retrouvait
  hors du canvas et donc injoignable au clic. Ajout du paramètre hAnchor.
- 26 nouveaux tests unitaires serveur (buildings.js + Room.js : validations
  d'achat multi-jauges, priorité/stock unique, effets de base et synergie).
- 6 nouveaux tests E2E Playwright (boutique bâtiments : affichage, position,
  carte détaillée dans les limites du canvas, coût affiché, achat complet).
- Fix flakiness des tests E2E d'achat (item-shop + building-shop) : le mode
  'min' de playCard garantit désormais que l'adversaire joue sa carte la
  plus faible sur l'attribut ciblé, au lieu de simplement jouer un autre
  attribut (insuffisant, le gain dépend de la comparaison au voisin gauche).
2026-08-21 16:19:18 +02:00
Kevin L'Hereec 11cba0467b feat: écran de fin de partie + tests unitaires client et E2E Playwright
- Fix: UIScene n'était jamais lancée (active: false, jamais scene.launch)
  donc l'event 'game-over' du serveur n'était jamais affiché — la partie
  semblait ne pas avoir de fin. Remplacé par un panneau Vue dans GameView
  (vainqueur, classement trié, bouton Quitter via vue-router). UIScene.js
  supprimée (code mort).
- Extraction de client/src/utils/hudUtils.js (constantes ATTRS/couleurs et
  gaugePercent) depuis GameView.vue pour les rendre testables isolément.
- Tests unitaires client (Vitest) : store Pinia (game.js) et hudUtils
  (24 tests, client/test/unit/).
- Tests d'intégration E2E (Playwright, e2e/) avec de vrais clients
  Socket.io et rendu Phaser réel dans Chromium :
  * game-flow.spec.js : lobby → démarrage → main de 4 cartes → résolution
  * item-shop.spec.js : boutique, bouton désactivé si jauge insuffisante,
    achat retire l'objet pour tous + effet appliqué + affiché sur la table
  * game-over.spec.js : partie complète (12 tours) → panneau de fin
  webServer démarre automatiquement client+serveur ; ajout d'une route
  GET /health côté Express pour permettre à Playwright de détecter un
  serveur déjà démarré.
- README : documentation des 3 niveaux de tests (unitaires serveur,
  unitaires client, intégration E2E) et de la nouvelle arborescence.
2026-08-21 15:27:44 +02:00
Kevin L'Hereec 6a1c800253 feat: système d'objets achetables (boutique + effets permanents) et refonte visuelle
- Nouveaux personnages illustrés (12 PNG remplacés dans client/public/cards)
- 4 objets achetables (Trébuchet, Charrue, Trousse du Médecin, Sceau Royal)
  avec effets permanents (double_gain, guaranteed_gain, copy_best_in_game),
  stock unique par partie, priorité d'achat tournante entre joueurs
- Boutique en colonne à gauche du plateau : icônes compactes, carte détaillée
  agrandie au survol (taille découplée du displayScale du jeton), bouton
  ACHETER actif/grisé selon la jauge du joueur, retrait immédiat de la
  colonne une fois l'objet acheté (les autres remontent pour combler)
- Objets achetés affichés "posés sur la table" : à côté de la main pour soi,
  sous le slot de jeu pour les adversaires
- Icône du premier joueur (priorité d'achat) dans le HUD Vue
- Refonte des cartes personnage (CardObject) : portrait plein cadre épuré,
  valeurs d'attribut discrètes aux 4 coins
- Fix removePlayer : nettoyage de pendingBuys/pendingPlays et recalage de
  firstPlayerIndex à la déconnexion d'un joueur
- 77 tests unitaires serveur (node:test) : cards, items, Room, RoomManager
- README mis à jour avec les règles complètes du jeu
- .gitignore : exclusion de .idea/ et .serena/ (artefacts d'outils locaux)
2026-08-21 14:53:58 +02:00
kevin.lhereec da06ecaf2d fix: clip card images via Canvas 2D in BootScene, no Phaser mask needed 2026-08-17 14:30:03 +02:00
kevin.lhereec 4d09102464 fix: use BitmapMask inside container so image follows card during animations 2026-08-17 14:25:32 +02:00
kevin.lhereec 0a8c89610b fix: card image clipping via RenderTexture, remove white hover bg 2026-08-17 14:24:42 +02:00
kevin.lhereec c7672b1793 fix: ghost players on back - leaveRoom, store.reset, dynamic lobby slots 2026-08-17 14:18:27 +02:00
kevin.lhereec 6e384d5985 fix: card image cover ratio, title at bottom, badges above image 2026-08-17 14:15:43 +02:00
kevin.lhereec 60b545c42d feat: card portrait images loaded from public/cards/ 2026-08-17 14:11:20 +02:00
kevin.lhereec b46cb707cd feat: draw one card after each turn with slide-in animation 2026-08-17 12:07:47 +02:00
kevin.lhereec ec5a7ec2c3 fix: button depth 100 to stay above cards, fix inactive text color 2026-08-17 12:04:01 +02:00
kevin.lhereec 2b37d8167f fix: play slots count matches actual player count 2026-08-17 12:01:30 +02:00
kevin.lhereec abab58f6a4 fix: add BOTTOM_MARGIN to avoid Windows taskbar overlap 2026-08-17 12:00:43 +02:00
kevin.lhereec 3125823f42 feat: confirm button with pulse animation + ready counter (X/N players) 2026-08-17 11:57:55 +02:00
kevin.lhereec 91a1a9f4f0 feat: gauge scoring system (subtract left neighbor per attribute) 2026-08-17 11:54:23 +02:00
kevin.lhereec 25ab76c4ac fix: per-player phase state so 2nd player can still play after 1st played 2026-08-17 11:50:27 +02:00
kevin.lhereec 78adeb7920 fix: replace npm ci with npm install (no lockfile yet) 2026-08-17 11:45:33 +02:00
kevin.lhereec 8da1d1edc9 feat: dockerize client (nginx) and server (node) with docker-compose 2026-08-17 11:44:07 +02:00
kevin.lhereec 38814668e7 feat: 12 character cards with 4 color-coded attributes (food/war/health/diplo) 2026-08-17 11:41:46 +02:00
kevin.lhereec 1db221e468 feat: initial Regnum project structure (Vue3 + Phaser3 + Socket.io) 2026-08-17 11:34:55 +02:00