Newer
Older
# Capaci
## Description du projet : Présentation du jeu
On s'intéresse à Capaci, un jeu de stratégie abstrait à deux joueurs créé par Christian Roullier. Ce jeu est une fusion originale entre la dimension tactique des échecs et la logique circulaire du Chi-Fou-Mi (Pierre-Feuille-Ciseaux).
Chaque joueur dispose de 12 pièces (noires ou blanches). Chaque lot de pièces est constitué de :
* Quatre Pierres (🪨)
* Quatre Feuilles (📄)
* Quatre Ciseaux (✂️)
Le plateau de jeu est constitué de 6 lignes et 6 colonnes (36 cases). Au début de la partie, les pièces sont disposées sur les deux premières rangées de chaque camp selon une configuration prédéfinie précise (symétrie gauche/droite : Ciseaux, Pierre, Feuille...).
### Objectifs et Déplacement
Pour gagner, un joueur doit remplir l'une des deux conditions suivantes :
1. **L'Élimination :** Capturer toutes les pièces d'un même type chez l'adversaire (par exemple, lui prendre tous ses ciseaux).
2. **Le Blocage :** Faire en sorte que l'adversaire ne puisse plus jouer aucun coup légal.
Les joueurs jouent à tour de rôle. Le déplacement des pièces obéit à trois règles précises :
* **Direction :** Comme une Reine aux échecs (horizontalement, verticalement ou en diagonale).
* **Portée (Spécificité Capaci) :** La distance maximale qu'une pièce peut parcourir est égale au nombre de pièces voisines (amies et ennemies) situées sur les **4 cases orthogonales** (Haut, Bas, Gauche, Droite) adjacentes à sa position de départ. Une pièce isolée (0 voisin orthogonal) ne peut donc pas bouger.
* **Saut :** Les pièces peuvent passer par-dessus les autres pièces présentes sur le plateau.
### La Capture
La capture s'effectue en arrivant exactement sur une case occupée par l'adversaire. Elle respecte la hiérarchie du Chi-Fou-Mi :
* La Pierre capture les Ciseaux.
* Les Ciseaux capturent la Feuille.
* La Feuille capture la Pierre.
Dans un premier temps on va modéliser le matériel et les actions du jeu avec les diagrammes UML suivants.

### Classe PieceCapaci
Cette classe gère une pièce du jeu. Une pièce est caractérisée par un type et une couleur. Pour les représenter, on utilise des constantes entières publiques : `WHITE`, `BLACK` pour les couleurs, et `ROCK`, `PAPER`, `SCISSORS` pour les types. Le constructeur est privé pour imposer l'utilisation des méthodes statiques `initWhiteRock`, `initBlackScissors`, etc. afin de générer des pièces correctes à l'aide des constantes de classe.
Contrairement à une approche naïve, la pièce ne connaît pas sa position sur le plateau (pas d'attributs ligne/colonne) pour éviter la redondance d'information. Elle implémente `JsonSerializable` pour la sauvegarde future.
### Classe PlateauCapaci
Cette classe gère le plateau de jeu. Les constantes `NBROWS` (6) et `NBCOLS` (6) définissent la taille du plateau. La structure de données interne est un tableau à deux dimensions (`grid`) stockant les instances de `PieceCapaci`.
La méthode `initPartie` place les pièces selon la disposition officielle (Lignes 0/1 pour les Noirs, 4/5 pour les Blancs, avec l'ordre Ciseaux-Pierre-Feuille répété en miroir).
La méthode `getNeighborCount` est spécifique à la logique de ce jeu : elle prend en paramètres les coordonnées d'une case et retourne le nombre de pièces (amies et ennemies) situées uniquement sur les **4 cases orthogonales** (en croix) autour de la position. Cette valeur détermine la portée du mouvement.
### Classe ActionCapaci
Cette classe agit comme un moteur de règles (Service). Elle ne stocke pas l'état d'un mouvement en cours (pas d'attributs `fromRow`, `toRow`...), mais travaille directement sur le `PlateauCapaci` fourni à la construction.
* La méthode `isValidMove` prend en entrée les coordonnées de départ et d'arrivée. Elle vérifie si le mouvement est géométriquement correct (type Reine) et surtout si la distance parcourue respecte la contrainte de portée calculée via `PlateauCapaci::getNeighborCount` (règle des 4 voisins).
* La méthode `processCapture` gère la résolution du combat selon la hiérarchie du Chi-Fou-Mi (Pierre bat Ciseaux, etc.) lorsqu'une pièce arrive sur une case occupée.
* Les méthodes `isElimination` et `isBlocked` retournent un booléen indiquant si un joueur a perdu (soit par perte totale d'une famille de pièces, soit par impossibilité de jouer un coup légal).