Le point de départ
Le Président a beaucoup de règles qui se croisent : qui peut jouer quoi, quand on est coupé, comment on échange ses cartes avec la manche d’avant. Je voulais que ces règles tiennent dans un seul endroit lisible, et qu’un coup interdit soit refusé avec la raison.
Les choix qui comptent
Un réducteur pur
Le moteur est une fonction transition(état, action) qui ne modifie jamais son entrée et renvoie soit le nouvel état avec ses événements, soit la règle violée. Ça se teste en trois lignes, et ça rend impossible l’état « à moitié modifié ».
Un état par phase
Lobby, distribution, échanges, jeu, fin de manche : chaque phase a sa propre forme de données. Une action n’a de sens que dans la bonne phase, et le compilateur me le rappelle.
Un client sans règles
Le client Vue affiche ce qu’il reçoit. Il ne sait pas ce qui est jouable : le serveur le lui dit. Les schémas Zod valident chaque message entrant, et le protocole est documenté dans le dépôt.
Reprise de session
Recharger l’onglet restaure la partie. Pendant une absence, un bot joue à la place du joueur ; au retour, il récupère sa main telle qu’elle est. Quitter explicitement révoque la session.
Ce qui a été difficile
Le rythme des bots. Un bot qui joue instantanément est illisible ; un bot trop lent énerve. Le serveur cadence les coups pour que la table reste suivable.
Les tests de bout en bout : deux navigateurs qui jouent en même temps, la reprise après rechargement, une manche solo complète. Ils tournent sur trois largeurs (1440, 390 et 320 px) et sauvegardent des captures, pour voir si l’interface tient réellement sur mobile.
Ce que je ferais autrement
Les salons sont en mémoire, comme pour mes autres jeux. Et le moteur gagnerait à exposer l’historique des coups : il rendrait un rejeu de partie presque gratuit.