From f7f50f9ca8ac20d9b2d384d5eea4291404954bc8 Mon Sep 17 00:00:00 2001 From: Florent Madelaine Date: Fri, 19 Sep 2025 09:59:13 +0200 Subject: [PATCH] control loop in AbstractGame + minor update in API documentation + minor change of name in a getter --- .../fr/iut_fbleau/GameAPI/AbstractBoard.java | 29 ++++++---- .../fr/iut_fbleau/GameAPI/AbstractGame.java | 58 +++++++++++++++++++ .../javaAPI/fr/iut_fbleau/GameAPI/IBoard.java | 26 ++++++--- 3 files changed, 95 insertions(+), 18 deletions(-) create mode 100644 2024-25/javaAPI/fr/iut_fbleau/GameAPI/AbstractGame.java diff --git a/2024-25/javaAPI/fr/iut_fbleau/GameAPI/AbstractBoard.java b/2024-25/javaAPI/fr/iut_fbleau/GameAPI/AbstractBoard.java index d606ba2..26136e8 100644 --- a/2024-25/javaAPI/fr/iut_fbleau/GameAPI/AbstractBoard.java +++ b/2024-25/javaAPI/fr/iut_fbleau/GameAPI/AbstractBoard.java @@ -6,9 +6,13 @@ import java.util.Deque; /** * An abstract class implementing the interface IBoard. * - * used to implement some things to do with the update of the next player - * which is the same for all games and provides also a minimal - * implantation of the history mechanism. + * It is used to implement some things to do with the update of the next player + * which is the same for all turn taking games using a round robin and provides + * also a minimal implantation of the history mechanism. + * + * The current implantation works only for two players. + * + * */ public abstract class AbstractBoard implements IBoard{ @@ -40,7 +44,7 @@ public abstract class AbstractBoard implements IBoard{ /** * @return the current player */ - public Player getcurrentPlayer(){ + public Player getCurrentPlayer(){ return this.currentPlayer; } @@ -57,20 +61,18 @@ public abstract class AbstractBoard implements IBoard{ */ public abstract Result getResult(); + /** - * checker of legal moves from this position + * checker of the legality of a ply from this position * - * @throws NullPointerException if the game is over - * @return the iterator + * @return true iff the ply is legal */ public abstract boolean isLegal(AbstractPly c); - /** * constructor of Iterator over legal moves from this position * - * @throws NullPointerException if the game is over * @return the iterator */ public abstract Iterator iterator(); @@ -79,7 +81,8 @@ public abstract class AbstractBoard implements IBoard{ /** * Plays a given move on the plateau. - * Should update history using + * Should update history using removePlyFromHistory + * * @throws IllegalArgumentException if the move is always illegal (say from the wrong game) * @throws IllegalStateException if the move is not legal in this position * @@ -96,4 +99,10 @@ public abstract class AbstractBoard implements IBoard{ */ public abstract void undoPly(); + /** + * creates a safe copy of the board. + * + * @return the copy + */ + public abstract IBoard safeCopy(); } diff --git a/2024-25/javaAPI/fr/iut_fbleau/GameAPI/AbstractGame.java b/2024-25/javaAPI/fr/iut_fbleau/GameAPI/AbstractGame.java new file mode 100644 index 0000000..56e5e34 --- /dev/null +++ b/2024-25/javaAPI/fr/iut_fbleau/GameAPI/AbstractGame.java @@ -0,0 +1,58 @@ +package fr.iut_fbleau.GameAPI; + +import java.util.EnumMap; + +/** + * The abstract class for an Abstract Game. + * All inheriting classes should be turn taking games (see method run). + * + * The abstract game knows the model of the current game state (something implementing + * an IBoard). It handles the players by providing a map from the Player class + * (an enum for the player order in the game) to the abstractGamePlayer class + * (a class that can choose a Ply from any given position). + * + * The control loop in the run method selects the appropriate player, sends him + * what should be a copy of the current game state to help him make his decision. + * If a player returns an illegal move, an exception is thrown and the game stops. + * Otherwise, when the game finishes the method returns the result. + * + * The logic of the game rule is handled in the class IBoard. + * In particular, it is possible that the turn taking does not take form of a round + * robin and switches between players in a non uniform ad hoc fashion. + * + * Potential evolution of this class could take into account clocks for the players, + * which would be better handled here than in the Abstractboard class. + * + */ +public abstract class AbstractGame { + + // board this game is played on + private IBoard currentBoard; + + // a map from the enum Player to the genuine Player AbstractGamePlayer + private EnumMap mapPlayers; + + //NB. pas de constructeur possible on est abstrait, il faut faire une usine abstraite. + + + /** + * boucle de contrĂ´le du jeu. + * + * @throws IllegalStateException if a player proposes an IllegalMove at some point + * @return the Result of the game from the perspective of the first player. + */ + public Result run(){ + while(! currentBoard.isGameOver()) { + AbstractGamePlayer player = mapPlayers.get(currentBoard.getCurrentPlayer()); + IBoard board = currentBoard.safeCopy(); + AbstractPly ply = player.giveYourMove(board); + + if (currentBoard.isLegal(ply)) { + currentBoard.doPly(ply); + } + else throw new IllegalStateException("Player "+ player + " is a bloody cheat. I give up."); + } + + return currentBoard.getResult(); + } +} diff --git a/2024-25/javaAPI/fr/iut_fbleau/GameAPI/IBoard.java b/2024-25/javaAPI/fr/iut_fbleau/GameAPI/IBoard.java index 2bf6d91..505e09b 100644 --- a/2024-25/javaAPI/fr/iut_fbleau/GameAPI/IBoard.java +++ b/2024-25/javaAPI/fr/iut_fbleau/GameAPI/IBoard.java @@ -11,7 +11,7 @@ public interface IBoard { /** * @return the current player */ - public Player getcurrentPlayer(); + public Player getCurrentPlayer(); /** * Returns the game status @@ -27,10 +27,9 @@ public interface IBoard { public Result getResult(); /** - * checker of legal moves from this position + * checker of the legality of a ply from this position * - * @throws NullPointerException if the game is over - * @return the iterator + * @return true iff the ply is legal */ public boolean isLegal(AbstractPly c); @@ -39,7 +38,6 @@ public interface IBoard { /** * constructor of Iterator over legal moves from this position * - * @throws NullPointerException if the game is over * @return the iterator */ public Iterator iterator(); @@ -48,7 +46,7 @@ public interface IBoard { /** * Plays a given move on the plateau. - * Should update history using + * * @throws IllegalArgumentException if the move is always illegal (say from the wrong game) * @throws IllegalStateException if the move is not legal in this position * @@ -60,10 +58,22 @@ public interface IBoard { /** * Resets the plateau to the position before the last move. * - * @throws IllegalStateException if nothing to undo in history + * @throws IllegalStateException if nothing to undo * */ public void undoPly(); - + /** + * Creates a safe copy of the board. + * + * Intended to prevent cheating from a human via some interface, + * or from a bot playing via the API, or from a badly coded bot. + * + * Beware that the default implantation is unsafe and returns this. + * + * @return the copy + */ + public default IBoard safeCopy(){ + return this; + } }