package fr.iut_fbleau.Avalam;
import fr.iut_fbleau.GameAPI.AbstractPly;
import fr.iut_fbleau.GameAPI.Player;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* La classe InteractionController
*
* Gère l'interaction entre l'utilisateur et le moteur du jeu Avalam.
* Elle permet :
* - la sélection d'une tour
* - le calcul des coups légaux
* - la validation d'un déplacement
* - l'application d'un coup
* - la mise à jour de l'affichage via BoardView
*
* Cette classe ne réalise aucun affichage direct.
*/
public class InteractionController {
//Attributs
/** Référence au moteur du jeu Avalam. */
private AvalamBoard board;
/** Ligne de la tour sélectionnée (-1 si aucune). */
private int selectedRow = -1;
/** Colonne de la tour sélectionnée (-1 si aucune). */
private int selectedCol = -1;
/** Liste des coups légaux (sous forme de points). */
private List legalMoves = new ArrayList<>();
/** Référence à la vue du plateau pour rafraîchir l'affichage. */
private BoardView view;
//Constructeur
/**
* Construit le contrôleur d'interactions.
*
* @param board moteur du jeu Avalam
* @param view vue du plateau
*/
public InteractionController(AvalamBoard board, BoardView view) {
this.board = board;
this.view = view;
}
//Méthodes
/**
* Retourne la liste des cases jouables.
*
* @return liste des coups légaux
*/
public List getLegalMoves() {
return legalMoves;
}
/**
* Appelé lorsqu’un pion est cliqué dans BoardView.
* Gère :
* - la sélection d’une tour
* - la désélection
* - la tentative de déplacement
*
* @param r ligne cliquée
* @param c colonne cliquée
*/
public void onPieceClicked(int r, int c) {
// Si on clique la même case ⇒ désélection
if (r == selectedRow && c == selectedCol) {
clearSelection();
view.refresh();
return;
}
// Si aucune sélection : on sélectionne un pion appartenant au joueur courant
Tower t = board.getTowerAt(r, c);
if (t != null && t.getColor().toPlayer() == board.getCurrentPlayer()) {
selectTower(r, c);
view.refresh();
return;
}
// Sinon : tentons de jouer un coup (déplacement)
if (selectedRow != -1 && selectedCol != -1) {
tryMove(r, c);
}
}
/**
* Sélectionne une tour à la position (r,c).
*
* @param r ligne
* @param c colonne
*/
private void selectTower(int r, int c) {
selectedRow = r;
selectedCol = c;
computeLegalMoves();
}
/**
* Annule la sélection actuelle.
*/
private void clearSelection() {
selectedRow = -1;
selectedCol = -1;
legalMoves.clear();
}
/**
* Calcule les coups légaux à partir de la tour sélectionnée.
* Utilise l'itérateur fourni par AvalamBoard.
*/
private void computeLegalMoves() {
legalMoves.clear();
Iterator it = board.iterator();
while (it.hasNext()) {
AbstractPly p = it.next();
if (!(p instanceof AvalamPly)) continue;
AvalamPly ap = (AvalamPly) p;
// On ne garde que les coups dont la source correspond à la sélection
if (ap.getXFrom() == selectedRow && ap.getYFrom() == selectedCol) {
legalMoves.add(new Point(ap.getXTo(), ap.getYTo()));
}
}
}
/**
* Tente d’exécuter un déplacement vers la case (r,c).
*
* @param r ligne de destination
* @param c colonne de destination
*/
private void tryMove(int r, int c) {
// Vérifier si (r,c) est une destination légale
boolean isLegalDest = false;
for (Point p : legalMoves) {
if (p.x == r && p.y == c) {
isLegalDest = true;
break;
}
}
if (!isLegalDest) {
clearSelection(); // clic ailleurs = désélection
view.refresh();
return;
}
// Construire le coup
Player cur = board.getCurrentPlayer();
AvalamPly ply = new AvalamPly(cur, selectedRow, selectedCol, r, c);
// Vérifier via l’API
if (board.isLegal(ply)) {
// Appliquer via l’API
board.doPly(ply);
// Réinitialiser la sélection
clearSelection();
// Mise à jour de l'interface
view.onBoardUpdated();
} else {
// Coup impossible
clearSelection();
}
view.refresh();
}
}