From 7db158376623c09993e19f66f0a9a0f43e2a37fd Mon Sep 17 00:00:00 2001 From: felix-vi Date: Sun, 23 Nov 2025 17:29:28 +0100 Subject: [PATCH] =?UTF-8?q?ajout=20de=20la=20logique=20des=20r=C3=A8gles?= =?UTF-8?q?=20de=20coups?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 8 + README.md | 64 +++ fr/iut_fbleau/Avalam/AvalamBoard.java | 510 ++++++++++++++++-- fr/iut_fbleau/Avalam/AvalamPly.java | 129 +++++ fr/iut_fbleau/GameAPI/AbstractBoard.class | Bin 2065 -> 0 bytes fr/iut_fbleau/GameAPI/AbstractGame.class | Bin 2148 -> 0 bytes .../GameAPI/AbstractGamePlayer.class | Bin 431 -> 0 bytes fr/iut_fbleau/GameAPI/AbstractPly.class | Bin 417 -> 0 bytes fr/iut_fbleau/GameAPI/IBoard.class | Bin 636 -> 0 bytes fr/iut_fbleau/GameAPI/Player.class | Bin 998 -> 0 bytes fr/iut_fbleau/GameAPI/Result.class | Bin 1042 -> 0 bytes 11 files changed, 677 insertions(+), 34 deletions(-) create mode 100644 fr/iut_fbleau/Avalam/AvalamPly.java delete mode 100644 fr/iut_fbleau/GameAPI/AbstractBoard.class delete mode 100644 fr/iut_fbleau/GameAPI/AbstractGame.class delete mode 100644 fr/iut_fbleau/GameAPI/AbstractGamePlayer.class delete mode 100644 fr/iut_fbleau/GameAPI/AbstractPly.class delete mode 100644 fr/iut_fbleau/GameAPI/IBoard.class delete mode 100644 fr/iut_fbleau/GameAPI/Player.class delete mode 100644 fr/iut_fbleau/GameAPI/Result.class diff --git a/Makefile b/Makefile index 3ed12b8..6d73b81 100644 --- a/Makefile +++ b/Makefile @@ -38,3 +38,11 @@ clean: # === Recompile + run === re: clean build run + +# === Génération de la Javadoc === +DOC_DIR = doc +javadoc: + @echo "===> Génération de la Javadoc..." + @mkdir -p $(DOC_DIR) + @javadoc -d $(DOC_DIR) -sourcepath $(SRC_DIR) -subpackages fr.iut_fbleau.Avalam + @echo "✔ Javadoc générée dans $(DOC_DIR)/" diff --git a/README.md b/README.md index 3f2fc48..3b63058 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,70 @@ Dans un second temps, on fera des bots le plus efficace possible (probablement u Le jeu de notre groupe est **Avalam**. +## Compilation et exécution + +### Compilation +```bash +make build +``` + +### Exécution +```bash +make run +``` + +### Nettoyage +```bash +make clean +``` + +### Recompiler et exécuter +```bash +make re +``` + +### Générer la Javadoc +```bash +make javadoc +``` + +## Architecture du projet + +### Structure des classes principales + +- **`AvalamBoard`** : Implémentation du plateau de jeu conforme à l'API `AbstractBoard` + - Gère l'état du plateau (grille 9x9) + - Valide les règles d'Avalam + - Applique et annule les coups + - Détecte la fin de partie et calcule le résultat + +- **`AvalamPly`** : Représente un coup dans le jeu + - Stocke les coordonnées de départ et d'arrivée + - Stocke la hauteur de la tour source (pour l'annulation) + +- **`Tower`** : Représente une tour de pions + - Stocke la couleur du sommet et la hauteur + +- **`Color`** : Énumération des couleurs des joueurs + - COLOR1 (Jaune) et COLOR2 (Rouge) + +### Logique du jeu + +Le plateau est représenté par une grille 9x9 où chaque case contient : +- `null` : case vide (trou) +- `ArrayList` : tour de pions (chaque Integer = 1 pour PLAYER1, 2 pour PLAYER2) + +### Règles implémentées + +- ✅ Validation des limites du plateau +- ✅ Vérification que la case source n'est pas vide +- ✅ Vérification que la case destination n'est pas vide (pas de trou) +- ✅ Vérification que la destination est voisine (horizontal, vertical ou diagonal) +- ✅ Vérification que la hauteur totale après déplacement ≤ 5 +- ✅ Déplacement de toute la pile (pas partiel) +- ✅ Détection de fin de partie (plus aucun coup possible) +- ✅ Calcul du résultat (nombre de tours possédées par chaque joueur) + ## Présentation [Avalam](https://escaleajeux.fr/?principal=/jeu/avaxl?) Sur un plateau de jeu, les joueurs disposent de 24 pions chacun. Le but est de créer de petites tours avec son pion de couleur au-dessus. Pour ce faire, chaque joueur déplace son pion sur une tour ou déplace une tour sur un autre pion. La personne ayant le plus de pions sur le dessus des tours gagne. diff --git a/fr/iut_fbleau/Avalam/AvalamBoard.java b/fr/iut_fbleau/Avalam/AvalamBoard.java index c675d96..329b1cc 100644 --- a/fr/iut_fbleau/Avalam/AvalamBoard.java +++ b/fr/iut_fbleau/Avalam/AvalamBoard.java @@ -10,74 +10,516 @@ import java.util.Iterator; import java.util.ArrayList; import java.util.Deque; import java.util.ArrayDeque; +import java.util.NoSuchElementException; +/** + * Implémentation du plateau de jeu Avalam conforme à l'API AbstractBoard. + * + *

Cette classe gère : + *

+ * + *

Le plateau est représenté par une grille où chaque case contient : + *

+ * + * @author AMARY Aurelien, DICK Adrien, FELIX-VIMALARATNAM Patrick, RABAN Hugo + * @version 1.0 + */ public class AvalamBoard extends AbstractBoard { + /** Hauteur maximale d'une tour (règle d'Avalam : 5 pions maximum) */ private int max_height = 5; + /** Résultat de la partie (null si la partie n'est pas terminée) */ private Result result; + /** Indique si la partie est terminée */ private boolean gameOver; + /** Taille du plateau (9x9) */ private int array_length = 9; + /** + * Grille du plateau de jeu. + * Chaque ArrayList<Integer> représente une tour, où chaque Integer est un joueur + * (1=PLAYER1, 2=PLAYER2). null représente une case vide (trou). + */ private ArrayList[][] grid = new ArrayList[this.array_length][this.array_length]; + /** + * Constructeur par défaut. + * Charge le plateau depuis le fichier par défaut (fr/iut_fbleau/Res/Plateau.txt). + */ public AvalamBoard(){ - super(Player.PLAYER1, new ArrayDeque<>()); - - //création du tableau - - this.gameOver = false; - this.result = null; + // Charger depuis le fichier par défaut + this("fr/iut_fbleau/Res/Plateau.txt"); } + /** + * Constructeur avec chargement depuis un fichier. + * + * @param filePath Chemin vers le fichier contenant la configuration du plateau + */ + public AvalamBoard(String filePath) { + super(Player.PLAYER1, new ArrayDeque<>()); + + // Initialisation de la grille + for (int i = 0; i < array_length; i++) { + for (int j = 0; j < array_length; j++) { + grid[i][j] = null; + } + } + + // Charger depuis le fichier + Tower[][] towerGrid = fr.iut_fbleau.Avalam.logic.BoardLoader.loadFromFile(filePath); + for (int i = 0; i < array_length; i++) { + for (int j = 0; j < array_length; j++) { + if (towerGrid[i][j] != null) { + grid[i][j] = new ArrayList<>(); + // Convertir Tower en ArrayList + Color color = towerGrid[i][j].getColor(); + int playerValue = (color == Color.COLOR1) ? 1 : 2; + for (int k = 0; k < towerGrid[i][j].getHeight(); k++) { + grid[i][j].add(playerValue); + } + } + } + } + + this.gameOver = false; + this.result = null; + updateGameState(); + } + + /** + * Vérifie si la partie est terminée. + * + * @return true si la partie est terminée (plus aucun coup possible) + */ @Override public boolean isGameOver() { return this.gameOver; } + /** + * Retourne le résultat de la partie. + * + * @return Le résultat (WIN/LOSS/DRAW du point de vue de PLAYER1), ou null si la partie n'est pas terminée + */ @Override public Result getResult() { return this.result; } - public boolean In_range(int x_tower_play, int y_tower_play, int x_tower_destination, int x_tower_destination){ - boolean in_table = true; - if (x_tower_play >= 0 && x_tower_play < 9){ - in_table = false; - } - else if (y_tower_play >= 0 && y_tower_play < 9){ - in_table = false; - } - else if (x_tower_destination >= 0 && x_tower_destination < 9){ - in_table = false; - } - else if (x_tower_destination >= 0 && x_tower_destination < 9){ - in_table = false; - } - return in_table; + /** + * Vérifie si les coordonnées sont dans les limites du plateau. + * + * @param x Coordonnée X + * @param y Coordonnée Y + * @return true si les coordonnées sont valides (dans [0, 8]) + */ + public boolean inRange(int x, int y) { + return x >= 0 && x < array_length && y >= 0 && y < array_length; } - @Override - public boolean isLegal(AbstractPly c, int x_tower_play, int y_tower_play, int x_tower_destination, int x_tower_destination) { - if (this.gameOver) { - throw new NullPointerException("Le jeu est terminé"); + /** + * Vérifie si deux cases sont voisines (horizontal, vertical ou diagonal). + * + * @param x1 Coordonnée X de la première case + * @param y1 Coordonnée Y de la première case + * @param x2 Coordonnée X de la deuxième case + * @param y2 Coordonnée Y de la deuxième case + * @return true si les deux cases sont voisines (distance de 1 case maximum) + */ + private boolean isNeighbor(int x1, int y1, int x2, int y2) { + int dx = Math.abs(x1 - x2); + int dy = Math.abs(y1 - y2); + return (dx <= 1 && dy <= 1) && !(dx == 0 && dy == 0); + } + + /** + * Retourne la hauteur d'une tour (nombre de pions). + * + * @param x Coordonnée X de la case + * @param y Coordonnée Y de la case + * @return La hauteur de la tour (0 si la case est vide) + */ + private int getTowerHeight(int x, int y) { + if (grid[x][y] == null) { + return 0; } - - if (!(c instanceof NimPly)) { + return grid[x][y].size(); + } + + /** + * Retourne le joueur propriétaire d'une tour (celui du sommet). + * + * @param x Coordonnée X de la case + * @param y Coordonnée Y de la case + * @return Le joueur propriétaire (PLAYER1 ou PLAYER2), ou null si la case est vide + */ + private Player getTowerOwner(int x, int y) { + if (grid[x][y] == null || grid[x][y].isEmpty()) { + return null; + } + int topPlayer = grid[x][y].get(grid[x][y].size() - 1); + return (topPlayer == 1) ? Player.PLAYER1 : Player.PLAYER2; + } + + /** + * Vérifie si un coup est légal selon les règles d'Avalam. + * + *

Un coup est légal si : + *

    + *
  • Le jeu n'est pas terminé
  • + *
  • Le coup est un AvalamPly
  • + *
  • C'est le tour du bon joueur
  • + *
  • Les coordonnées sont dans les limites du plateau
  • + *
  • La case source n'est pas vide
  • + *
  • La case destination n'est pas vide (pas de trou)
  • + *
  • La destination est voisine de la source
  • + *
  • La hauteur totale après déplacement ne dépasse pas max_height (5)
  • + *
+ * + * @param c Le coup à vérifier + * @return true si le coup est légal, false sinon + */ + @Override + public boolean isLegal(AbstractPly c) { + if (this.gameOver) { return false; } - NimPly coup = (NimPly) c; + if (!(c instanceof AvalamPly)) { + return false; + } + AvalamPly coup = (AvalamPly) c; + + // Vérifier que c'est le bon joueur if (coup.getPlayer() != getCurrentPlayer()) { return false; } - - if (In_range(x_tower_play, y_tower_play, x_tower_destination, x_tower_destination)){ + + int xFrom = coup.getXFrom(); + int yFrom = coup.getYFrom(); + int xTo = coup.getXTo(); + int yTo = coup.getYTo(); + + // Vérifier que les coordonnées sont dans les limites + if (!inRange(xFrom, yFrom) || !inRange(xTo, yTo)) { return false; } - // Vérifier que le nombre d'allumettes est valide - int nbAllumettes = coup.getNombreAllumettesPrises(); - return // modifier IsgameOver + // Règle : On ne peut pas déplacer depuis une case vide + if (grid[xFrom][yFrom] == null || grid[xFrom][yFrom].isEmpty()) { + return false; + } + + // Règle : On ne peut pas poser sur une case vide (trou) + if (grid[xTo][yTo] == null) { + return false; + } + + // Règle : La destination doit être voisine + if (!isNeighbor(xFrom, yFrom, xTo, yTo)) { + return false; + } + + // Règle : On déplace toute la pile + int heightFrom = getTowerHeight(xFrom, yFrom); + int heightTo = getTowerHeight(xTo, yTo); + + // Règle : La hauteur totale après déplacement ne doit pas dépasser max_height + if (heightFrom + heightTo > max_height) { + return false; + } + + return true; } -} \ No newline at end of file + /** + * Applique un coup sur le plateau. + * + *

Le coup déplace toute la tour de la case source vers la case destination. + * La méthode met également à jour l'historique et change de joueur via l'appel à super.doPly(). + * + * @param c Le coup à appliquer + * @throws IllegalStateException si le coup n'est pas légal + */ + @Override + public void doPly(AbstractPly c) { + if (!isLegal(c)) { + throw new IllegalStateException("Coup illégal : " + c); + } + + AvalamPly coup = (AvalamPly) c; + int xFrom = coup.getXFrom(); + int yFrom = coup.getYFrom(); + int xTo = coup.getXTo(); + int yTo = coup.getYTo(); + + // Stocker la hauteur de la source avant le déplacement (pour undo) + int sourceHeight = getTowerHeight(xFrom, yFrom); + coup.setSourceHeight(sourceHeight); + + // Déplacer toute la pile de la source vers la destination + // On empile les pions de la source sur ceux de la destination + ArrayList sourceTower = grid[xFrom][yFrom]; + ArrayList destTower = grid[xTo][yTo]; + + // Ajouter tous les pions de la source à la destination + for (Integer pion : sourceTower) { + destTower.add(pion); + } + + // Vider la case source + grid[xFrom][yFrom] = null; + + // Appeler la méthode parente pour gérer l'historique et changer de joueur + super.doPly(c); + + // Mettre à jour l'état du jeu + updateGameState(); + } + + /** + * Annule le dernier coup joué. + * + *

Restaure l'état du plateau avant le dernier coup. + * La méthode met également à jour l'historique et change de joueur via l'appel à super.undoPly(). + * + * @throws IllegalStateException si aucun coup n'a été joué ou si la hauteur source n'est pas définie + */ + @Override + public void undoPly() { + AbstractPly lastPly = getLastPlyFromHistory(); + if (lastPly == null) { + throw new IllegalStateException("Aucun coup à annuler"); + } + + AvalamPly coup = (AvalamPly) lastPly; + int xFrom = coup.getXFrom(); + int yFrom = coup.getYFrom(); + int xTo = coup.getXTo(); + int yTo = coup.getYTo(); + int sourceHeight = coup.getSourceHeight(); + + if (sourceHeight < 0) { + throw new IllegalStateException("Impossible d'annuler : hauteur source non définie"); + } + + // La destination contient maintenant : destination_avant + source + // On doit retirer les derniers sourceHeight pions pour reconstruire la source + ArrayList destTower = grid[xTo][yTo]; + ArrayList sourceTower = new ArrayList<>(); + + // Retirer les derniers pions de la destination (ceux qui venaient de la source) + for (int i = 0; i < sourceHeight; i++) { + if (destTower.isEmpty()) { + throw new IllegalStateException("Erreur lors de l'annulation : tour destination vide"); + } + sourceTower.add(0, destTower.remove(destTower.size() - 1)); + } + + // Remettre la tour source à sa place + grid[xFrom][yFrom] = sourceTower; + + // Si la destination est vide après annulation, la mettre à null + if (destTower.isEmpty()) { + grid[xTo][yTo] = null; + } + + // Appeler la méthode parente + super.undoPly(); + + // Mettre à jour l'état du jeu + updateGameState(); + } + + /** + * Met à jour l'état du jeu (gameOver et result). + * + *

Vérifie s'il reste des coups possibles. Si aucun coup n'est possible : + *

    + *
  • Marque la partie comme terminée (gameOver = true)
  • + *
  • Calcule le score de chaque joueur (nombre de tours possédées)
  • + *
  • Détermine le résultat (WIN/LOSS/DRAW du point de vue de PLAYER1)
  • + *
+ */ + private void updateGameState() { + // Vérifier s'il y a encore des coups possibles + boolean hasLegalMove = false; + Iterator it = iterator(); + if (it.hasNext()) { + hasLegalMove = true; + } + + if (!hasLegalMove) { + this.gameOver = true; + // Calculer le résultat + int scorePlayer1 = 0; + int scorePlayer2 = 0; + + for (int i = 0; i < array_length; i++) { + for (int j = 0; j < array_length; j++) { + Player owner = getTowerOwner(i, j); + if (owner == Player.PLAYER1) { + scorePlayer1++; + } else if (owner == Player.PLAYER2) { + scorePlayer2++; + } + } + } + + // Result est du point de vue de PLAYER1 + if (scorePlayer1 > scorePlayer2) { + this.result = Result.WIN; + } else if (scorePlayer1 < scorePlayer2) { + this.result = Result.LOSS; + } else { + this.result = Result.DRAW; + } + } else { + this.gameOver = false; + this.result = null; + } + } + + /** + * Retourne un itérateur sur tous les coups légaux possibles pour le joueur actuel. + * + *

Cet itérateur est utilisé par les bots pour explorer les coups possibles. + * + * @return Un itérateur sur tous les coups légaux + */ + @Override + public Iterator iterator() { + return new LegalMovesIterator(); + } + + /** + * Itérateur sur tous les coups légaux possibles. + * + *

Parcourt toutes les cases source possibles et trouve toutes les destinations valides + * pour chaque source, en respectant les règles d'Avalam. + */ + private class LegalMovesIterator implements Iterator { + private int currentX = 0; + private int currentY = 0; + private int currentDestX = -1; + private int currentDestY = -1; + private AbstractPly nextMove = null; + + public LegalMovesIterator() { + findNextMove(); + } + + @Override + public boolean hasNext() { + return nextMove != null; + } + + @Override + public AbstractPly next() { + if (nextMove == null) { + throw new NoSuchElementException(); + } + AbstractPly move = nextMove; + findNextMove(); + return move; + } + + private void findNextMove() { + nextMove = null; + + // Parcourir toutes les cases source possibles + while (currentX < array_length) { + // Si on a une case source valide + if (grid[currentX][currentY] != null && !grid[currentX][currentY].isEmpty()) { + // Chercher une destination valide + while (currentDestX < array_length) { + currentDestY++; + if (currentDestY >= array_length) { + currentDestY = 0; + currentDestX++; + } + + if (currentDestX >= array_length) { + break; + } + + // Vérifier si ce mouvement est légal + if (isNeighbor(currentX, currentY, currentDestX, currentDestY) && + grid[currentDestX][currentDestY] != null && + getTowerHeight(currentX, currentY) + getTowerHeight(currentDestX, currentDestY) <= max_height) { + + nextMove = new AvalamPly(getCurrentPlayer(), currentX, currentY, currentDestX, currentDestY); + return; + } + } + } + + // Passer à la case suivante + currentY++; + if (currentY >= array_length) { + currentY = 0; + currentX++; + } + currentDestX = -1; + currentDestY = -1; + } + } + } + + /** + * Crée une copie indépendante du plateau. + * + *

Cette méthode est utilisée pour empêcher la triche : les bots reçoivent une copie + * du plateau et ne peuvent pas modifier l'état original. + * + * @return Une copie indépendante du plateau + */ + @Override + public IBoard safeCopy() { + AvalamBoard copy = new AvalamBoard(true); + // Réinitialiser l'état sans charger depuis le fichier + copy.gameOver = this.gameOver; + copy.result = this.result; + copy.max_height = this.max_height; + + // Copier la grille + for (int i = 0; i < array_length; i++) { + for (int j = 0; j < array_length; j++) { + if (grid[i][j] != null) { + copy.grid[i][j] = new ArrayList<>(grid[i][j]); + } else { + copy.grid[i][j] = null; + } + } + } + + return copy; + } + + /** + * Constructeur privé pour safeCopy(). + * Crée un plateau vide sans charger depuis un fichier. + * + * @param empty Paramètre inutilisé, présent uniquement pour différencier ce constructeur + */ + private AvalamBoard(boolean empty) { + super(Player.PLAYER1, new ArrayDeque<>()); + // Initialisation de la grille vide + for (int i = 0; i < array_length; i++) { + for (int j = 0; j < array_length; j++) { + grid[i][j] = null; + } + } + this.gameOver = false; + this.result = null; + } +} diff --git a/fr/iut_fbleau/Avalam/AvalamPly.java b/fr/iut_fbleau/Avalam/AvalamPly.java new file mode 100644 index 0000000..80b1317 --- /dev/null +++ b/fr/iut_fbleau/Avalam/AvalamPly.java @@ -0,0 +1,129 @@ +package fr.iut_fbleau.Avalam; + +import fr.iut_fbleau.GameAPI.AbstractPly; +import fr.iut_fbleau.GameAPI.Player; + +/** + * Représente un coup dans le jeu Avalam. + * Un coup consiste à déplacer une tour de la position (xFrom, yFrom) + * vers la position (xTo, yTo). + * + * @author AMARY Aurelien, DICK Adrien, FELIX-VIMALARATNAM Patrick, RABAN Hugo + * @version 1.0 + */ +public class AvalamPly extends AbstractPly { + /** Coordonnée X de la case source */ + private int xFrom; + /** Coordonnée Y de la case source */ + private int yFrom; + /** Coordonnée X de la case destination */ + private int xTo; + /** Coordonnée Y de la case destination */ + private int yTo; + /** Hauteur de la tour source (utilisée pour l'annulation de coup) */ + private int sourceHeight; + + /** + * Constructeur par défaut d'un coup Avalam. + * La hauteur de la source sera définie automatiquement lors de l'application du coup. + * + * @param joueur Le joueur qui effectue le coup + * @param xFrom Coordonnée X de la case source + * @param yFrom Coordonnée Y de la case source + * @param xTo Coordonnée X de la case destination + * @param yTo Coordonnée Y de la case destination + */ + public AvalamPly(Player joueur, int xFrom, int yFrom, int xTo, int yTo) { + super(joueur); + this.xFrom = xFrom; + this.yFrom = yFrom; + this.xTo = xTo; + this.yTo = yTo; + this.sourceHeight = -1; // Sera défini lors du doPly + } + + /** + * Constructeur avec hauteur de la source spécifiée. + * Utilisé principalement pour l'annulation de coups. + * + * @param joueur Le joueur qui effectue le coup + * @param xFrom Coordonnée X de la case source + * @param yFrom Coordonnée Y de la case source + * @param xTo Coordonnée X de la case destination + * @param yTo Coordonnée Y de la case destination + * @param sourceHeight Hauteur de la tour source avant le déplacement + */ + public AvalamPly(Player joueur, int xFrom, int yFrom, int xTo, int yTo, int sourceHeight) { + super(joueur); + this.xFrom = xFrom; + this.yFrom = yFrom; + this.xTo = xTo; + this.yTo = yTo; + this.sourceHeight = sourceHeight; + } + + /** + * Retourne la coordonnée X de la case source. + * + * @return La coordonnée X de la case source + */ + public int getXFrom() { + return xFrom; + } + + /** + * Retourne la coordonnée Y de la case source. + * + * @return La coordonnée Y de la case source + */ + public int getYFrom() { + return yFrom; + } + + /** + * Retourne la coordonnée X de la case destination. + * + * @return La coordonnée X de la case destination + */ + public int getXTo() { + return xTo; + } + + /** + * Retourne la coordonnée Y de la case destination. + * + * @return La coordonnée Y de la case destination + */ + public int getYTo() { + return yTo; + } + + /** + * Retourne la hauteur de la tour source. + * + * @return La hauteur de la tour source, ou -1 si non définie + */ + public int getSourceHeight() { + return sourceHeight; + } + + /** + * Définit la hauteur de la tour source. + * Cette méthode est appelée automatiquement lors de l'application du coup. + * + * @param height La hauteur de la tour source + */ + public void setSourceHeight(int height) { + this.sourceHeight = height; + } + + @Override + public String toString() { + return "AvalamPly{" + + "joueur=" + getPlayer() + + ", from=(" + xFrom + "," + yFrom + ")" + + ", to=(" + xTo + "," + yTo + ")" + + '}'; + } +} + diff --git a/fr/iut_fbleau/GameAPI/AbstractBoard.class b/fr/iut_fbleau/GameAPI/AbstractBoard.class deleted file mode 100644 index 5372ca6e2def738c8c6dc8c2530ba73c0d28ce28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2065 zcmX^0Z`VEs1_nola4rTW24;2!79Ivx1~x_pfvm)`ME#t^ymWp4q^#8B5=I6#o6Nk- z5<5l)W)00SP6iGJPId+^9tLg(9!3V`v?Be?(vtYJq@2{mQhoQt+*HQ^PkqOv;*z4o z+92}QAUpVY82A|k7#Y|zGK)*{iz*oz z1bx6xD=o>)(RWELEKRlMWDsHyW@ixLVGsqmMFyXtj124nK8}&DL53h*;yerzAT3Za zBW?yM25EK%86E~%202Csel(jH88{MCQrt3&ic1(7L^U7|K?);l%`lJ&3Oo#o3`&d) z+(oIm`DLk4^&%RYm>Sp_R2Uf)u{#(RcmX+;AXC+N7}PZMk}=?6Fk~=d zWDtRPB_OBLttdYiZilLdCJ~mfGng4`bPC5a`ea77#p7K{uUe)$RoIh6{Tc?!@}p`(zOUy_lTm#&bU zn5U4Gs!*DjlAo8##bC-{1xnD?Xwem1Qk0pOZmk){&S1;PfFr?pLQ^egaAta5Vo7OH zDkFm#BnlCU&xQ#9+gUR*7~zTyXj(@%*IF}-k%7fIKP8osf!`-HFV(L!Hz~C!Brz!` zm60KwMAL|KCCEzN;F84TY~REJs7<2jsU<#%#Uug7s2>>_xH5}D zMT37CDEBjKXhtzIaHgl01f>?2=9Dlp;5GrG!kUqRJ+s&clq?t-h)ds5j0_x^C847o?iy{LD0}}%ygAD@{0~4skWnf@n0u_u5j0|>Q zwmkzc10w?~g98H-gChe2gE6Q$XJBC9*V@j&sHMG?fn7^yD+BLF1_lO31}6pv1|bF( z1_lNh1{MZc22KV!20jLPs8P-gETH0mfe~zw7uaG31{tj_4D6d21eY=JYHeZ=+seSc zoPkSg6NBJZ26m9COh~4xGjK6zFo-Z{Ge|S&Ft{)AL=~- diff --git a/fr/iut_fbleau/GameAPI/AbstractGame.class b/fr/iut_fbleau/GameAPI/AbstractGame.class deleted file mode 100644 index 9c63903f185feb1d7de32a42c7c025003f6eaaa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2148 zcmX^0Z`VEs1_nolL@ov<24;2!79Ivx1~x_pfvm)`ME#t^ymWp4q^#8B5=I6#o6Nk- z5<5l)W)00SP6iGJPId+^9tLg(9!3VGv?Be?(vtYJq@2{mQhoQt+*HQ^PkqOv;*z4o z^1x5xz3e;3!T^OLfjKsKn=LXb5vL zC^Bg9FlaJpF*5L^XO^W#=9d=v=9i^1GB|7C@Gw*>uJC|4E+D58949(F47v<@j126V z#XhO&i881OI{G8i#3u%_e(kVFs--N3}a+qan4UkWn|#@$;?aj zE6q(xEec6Y%1LEps3X}tDtZUxGUlSvJVplI;F84TY~REJu(Q}1{23V(38rgC2Cm@z z(xT*4w@i>%1d)SG50u0h83dg2^GiU5W`S>NNk)E3F$Y5kBZC?wKouAjGK&=w6_RrD z^HVAnk~2~hOY{^x6+n4cp|n7cpN%1miy@pLf}J4}ln|pB8B{>VLdx;Xyt4f4RDDPS zf}~Bi#N?9vqDn@F8OTWtsu1D;kHox`oYZ0!pZxsn(gJHpbb<2~#2{o56pbO31*yoA zQ037`CSb`+P$QfZb8><+OH!>F8F)PN@=}YOa}tY-Q;XRdVi_4!G5mzhsq75#j0|%4 zl`=B0LHxy{$iTtC#K6G7#J~iq(ZDQz1_1^}1~)Lsgk%5)LgMo>`lYxQ37*t&{ zFfj0IZD(NA(%#CzuBEe;fp;SV0|O(27Xt%>5CaPX1A__!3xg^HCxaRTAA>s7C~pQv z1|J4j21c+!I~kb4Dl@dUFtG1r5M*SS#Sp5sg@G5s7iVPH#vpxwLD2`oS7v1J)z;a@ zpza6a>+WRGW@4DhAOPj)Gchb@5ZTRO9I3s7!E_gcH3P$T2K)WX|1Sk8*va6;$glzI z9gqvv7&sXi7z`LdrK|#j5rY2Gc@?2Wm u85p&+w=%GA1gqv}U|`^5U}j)o5M*Fs5MtnD5N2Uy5MU4l%L;+b5e5L^=xGT6 diff --git a/fr/iut_fbleau/GameAPI/AbstractPly.class b/fr/iut_fbleau/GameAPI/AbstractPly.class deleted file mode 100644 index 5a3a4d20f066e14f40c4519eb2abb9c8c4c97a13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 417 zcmX^0Z`VEs1_nn45iSNM24;2!79Ivx1~x_pfvm)`ME#t^ymWp4q^#8B5=I6#o6Nk- z5<5l)W)00SP6iGJPId+^9tLg(9!3Vmv?Be?(vtYJq@2{mQhoQt+*HQ^PkqOv;*z4o zw!XmMUjDnfr){E zfsug;lsEGaEYWn{3%s>p^2 z+w80v8CX;D19B>fbzT@F1AA#6R133)W*8#_M{#0Ws&jrpCBE>0M2Hz{1EN$RGq37iJJ)U|?Wm5M>Z!U}O+y kU|^790GZ6dz@)VSEF;0dz`(}9$iTqh%fQGW2{u6r0MzTEOaK4? diff --git a/fr/iut_fbleau/GameAPI/Player.class b/fr/iut_fbleau/GameAPI/Player.class deleted file mode 100644 index c659c8b3dfd9f18f69828f989b5b73e4ea30458f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 998 zcmX^0Z`VEs1_nn4eRc*WMh2O*BK^$LlK8ZwoYcfpefPxNRL1~M{eYar%G4rG21W)J z9tKthHbw^a03XLl*C0bi200&mdaOa3ICvO1ku({B#JG7Fco=vY8Q4|A9DPDvgBcm* zqw$->#lX)Xz|O$S!yw2Y#K^#!oRgoI%E%z1q3M&ASeB@tlbDyT@1K;Fnp|Sd#UR2U z%FZCh!ywKe!N|aeP~e(Zn#;(*UY3|sn(Cj%$Y830q}w?svAEb8Ng%kSC^IkJ8rcSr z0bui`co?J^WEdIPY%=pQOY9gK#E^}G>h#nM<6vOrVqj#D;$Ywe(TY3_N({;%kAvM% z%*ddqp-I5&j0|ir#VpSGDXEMM{63j^seYxoNvTC4iAg!Bj0{FtY}dpeqKpgzzNsY{ z`6&U3MTxnoC8V!f*sUxKybP=iQVh%tObihB=rHJl H-K7TrLd?jw diff --git a/fr/iut_fbleau/GameAPI/Result.class b/fr/iut_fbleau/GameAPI/Result.class deleted file mode 100644 index 4234ba934331213fdbeea51a1ec69d20b4ed21e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1042 zcmX^0Z`VEs1_nn4V|E56Mh2O*BK^$LlK8ZwoYcfpefPxNRL1~M{h-w1(wq`b21W)J z9tKthHbw^Ka8Ex*200&m>a9T8waPOv zGcYqSFtBTB%WP+m*@$5eNFOH?1A_nq80#{C^y>+5f#MkITzv)>kZT#l+4eFpMlx?= zU=EIC*~Gve9Lc(gfh!o(EgTH`40=$_K~T+lyBQcGg%p^#GbnCmUpt6~P7vWAJuzn5(UT}zTF{m@JGcYkgoN2&d2zIU!0Nw7+@&Et;