diff --git a/LocalMain.java b/LocalMain.java
new file mode 100644
index 0000000..37b43bb
--- /dev/null
+++ b/LocalMain.java
@@ -0,0 +1,240 @@
+package ch.epfl.javass;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import ch.epfl.javass.gui.GraphicalPlayerAdapter;
+import ch.epfl.javass.jass.JassGame;
+import ch.epfl.javass.jass.MctsPlayer;
+import ch.epfl.javass.jass.PacedPlayer;
+import ch.epfl.javass.jass.Player;
+import ch.epfl.javass.jass.PlayerId;
+import ch.epfl.javass.net.RemotePlayerClient;
+import javafx.application.Application;
+import javafx.stage.Stage;
+
+/**
+ * An application to launch a Jass Game locally.
+ * @author Célia Houssiaux
+ * @author Charles Beauville
+ *
+ */
+public final class LocalMain extends Application {
+
+ private static final double MIN_TIME = 1.0;
+ private static final int WAIT_TIME = 1000;
+ private static final int TYPE_INDEX = 0;
+ private static final int NAME_INDEX = 1;
+ private static final int ADDRESS_INDEX = 2;
+ private static final int ITER_NBR_INDEX = 2;
+
+ /**
+ *
+ * @param args
+ * parametres donnés a l'application sous cette forme :
+ *
+ *
+ * {j1}…{j4} [{graine}] où :
+ * {jn} spécifie le joueur n, ainsi:
+ * h:{nom} un joueur humain nommé {nom}"
+ *
+ * s:{nom}:{n} un joueur simulé nommé {nom} qui itère l'algorithme MCTS {n} fois"
+ *
+ * r:{nom}:{adresse} un joueur distant nommé {nom} et sur le serveur d'adresse : {adresse}
+ *
+ * Les agruments {nom}, {n} et {adresses} sont optionnelles et ont pour valeurs par défaut :
+ *
+ * Aline, Bastien, Colette et David attribués dans l'ordre, à défaut de {nom}
+ *
+ * 10 000 iterations de MCTS, à défaut de {n}
+ * et localhost, à défaut de {adresse}.
+ *
+ */
+ public static void main(String[] args) {
+ launch(args);
+ }
+
+ @Override
+ public void start(Stage primaryStage) throws Exception {
+
+ List args = getParameters().getRaw();
+ Map players = new HashMap<>();
+ Map playerNames = new HashMap<>();
+
+ // Setting up the default values.
+ String[] defaultNames = { "Aline", "Bastien", "Colette", "David" };
+ int iterNbr = 10000;
+ Random rnd = new Random();
+ String adress = "localhost";
+
+ // Explaining the syntax if too much arguments are detected.
+ if (!(args.size() == 4 || args.size() == 5)) {
+ System.err.println(
+ "Utilisation: java ch.epfl.javass.LocalMain … [] où :");
+ System.err.println(" spécifie le joueur n, ainsi:");
+ System.err.println(" h: un joueur humain nommé ");
+ System.err.println(
+ " s:: un joueur simulé nommé qui itère l'algorithme MCTS fois");
+ System.err.println(
+ " r:: un joueur distant nommé et sur le serveur d'adresse : ");
+ System.err.println("");
+ System.err.println(
+ "Les agruments , et sont optionnelles et ont pour valeurs par défaut : ");
+ System.err.println(
+ " Aline, Bastien, Colette et David attribués dans l'ordre, à défaut de ,");
+ System.err
+ .println(" 10 000 iterations de MCTS, à défaut de ,");
+ System.err.println(" et localhost, à défaut de ,");
+
+ System.exit(1);
+ }
+
+ // Checking if the given seed is correct.
+ if (args.size() == 5) {
+ try {
+ rnd.setSeed(Long.parseLong(args.get(4)));
+ } catch (Exception NumberFormatException) {
+ System.err.println(
+ "Erreur : seed de génération aléatoire incorrect");
+ System.exit(1);
+ }
+ }
+
+ int gameSeed = rnd.nextInt();
+
+ for (int i = 0; i < PlayerId.COUNT; i++) {
+ String[] playerInfo = args.get(i).split(":", -1);
+
+ String playerType = playerInfo[TYPE_INDEX];
+
+ if (!(playerType.equals("h") || playerType.equals("s")
+ || playerType.equals("r"))) {
+ System.err
+ .println("Erreur : spécification de joueur invalide : "
+ + args.get(i));
+ System.exit(1);
+ }
+
+ if (playerInfo.length > 3) {
+ System.err
+ .println("Erreur : trop de composantes sur le joueur : "
+ + args.get(i));
+ System.exit(1);
+ }
+
+ // Handles the case where the type argument is "h", creates a
+ // GraphicalPlayerAdapter.
+ if (playerType.equals("h")) {
+
+ // Check if their aren't too many components.
+ if (playerInfo.length > 2) {
+ System.err.println(
+ "Erreur : trop de composantes sur le joueur : "
+ + args.get(i));
+ System.exit(1);
+ }
+
+ // Creates the GraphicalPlayerAdapter.
+ players.put(PlayerId.ALL.get(i), new GraphicalPlayerAdapter());
+
+ // Assigns the given name to the player if it is correct.
+ if (playerInfo.length > 1)
+ if (!playerInfo[NAME_INDEX].isEmpty())
+ playerNames.put(PlayerId.ALL.get(i), playerInfo[NAME_INDEX]);
+ else
+ playerNames.put(PlayerId.ALL.get(i), defaultNames[i]);
+ else
+ playerNames.put(PlayerId.ALL.get(i), defaultNames[i]);
+ }
+
+ // Handles the case where the type argument is "r", creates a
+ // RemotePlayerClient.
+ if (playerType.equals("r")) {
+
+ // Sets the adress to the given argument if it isn't null.
+ if (playerInfo.length > 1)
+ if (!playerInfo[ADDRESS_INDEX].isEmpty())
+ adress = playerInfo[ADDRESS_INDEX];
+
+ try {
+ // Creates the RemotePlayerClient, quits if it can't
+ // connect.
+ players.put(PlayerId.ALL.get(i),
+ new RemotePlayerClient(adress));
+ } catch (Exception IOError) {
+ System.err.println(
+ "Erreur : Connexion impossible au joueur simulé : "
+ + args.get(i));
+ System.exit(1);
+ }
+
+ // Assigns the given name to the player if it is correct.
+ if (playerInfo.length > 1)
+ if (!playerInfo[NAME_INDEX].isEmpty())
+ playerNames.put(PlayerId.ALL.get(i), playerInfo[NAME_INDEX]);
+ else
+ playerNames.put(PlayerId.ALL.get(i), defaultNames[i]);
+ else
+ playerNames.put(PlayerId.ALL.get(i), defaultNames[i]);
+ }
+
+ // Handles the case where the type argument is "s", creates a
+ // MCTSPlayer.
+ if (playerType.equals("s")) {
+
+ // Sets the number of iteration to the given argument if it is
+ // correct.
+ if (playerInfo.length > 1)
+ if (!playerInfo[ITER_NBR_INDEX].isEmpty()) {
+ try {
+ iterNbr = Integer
+ .parseInt(playerInfo[ITER_NBR_INDEX]);
+ } catch (Exception NumberFormatException) {
+ System.err.println(
+ "Erreur : Nombre d'iterations du MCTS non valide pour le joueur simulé : "
+ + args.get(i));
+ System.exit(1);
+ }
+ if (iterNbr < 10) {
+ System.err.println(
+ "Erreur : Nombre d'iterations du MCTS non valide pour le joueur simulé : "
+ + args.get(i));
+ System.exit(1);
+ }
+ }
+
+ // Creates the simulated player.
+ players.put(PlayerId.ALL.get(i),
+ new PacedPlayer(new MctsPlayer(PlayerId.ALL.get(i),
+ rnd.nextLong(), iterNbr), MIN_TIME));
+
+ // Assigns the given name to the player if it is correct.
+ if (playerInfo.length > 1)
+ if (!playerInfo[NAME_INDEX].isEmpty())
+ playerNames.put(PlayerId.ALL.get(i), playerInfo[NAME_INDEX]);
+ else
+ playerNames.put(PlayerId.ALL.get(i), defaultNames[i]);
+ else
+ playerNames.put(PlayerId.ALL.get(i), defaultNames[i]);
+
+ }
+ }
+
+ // Launches the game with the givem arguments
+ Thread gameThread = new Thread(() -> {
+ JassGame g = new JassGame(gameSeed, players, playerNames);
+ while (!g.isGameOver()) {
+ g.advanceToEndOfNextTrick();
+ try {
+ Thread.sleep(WAIT_TIME);
+ } catch (Exception e) {
+ }
+ }
+ });
+ gameThread.setDaemon(true);
+ gameThread.start();
+ }
+
+}
diff --git a/Preconditions.java b/Preconditions.java
new file mode 100644
index 0000000..c7f01a2
--- /dev/null
+++ b/Preconditions.java
@@ -0,0 +1,33 @@
+package ch.epfl.javass;
+
+/**
+ * Gives a set of function to test conditions.
+ * @author Charles BEAUVILLE
+ * @author Celia HOUSSIAUX
+ *
+ */
+public final class Preconditions {
+ private Preconditions() {}
+
+ /**
+ * Checks if a boolean expression is true or throws exception.
+ * @param b boolean expression on the arguments.
+ * @throws IllegalArgumentException if b is false.
+ */
+ public static void checkArgument(boolean b) {
+ if(!b)
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Checks if an index is positive and inferior to a size.
+ * @throws IndexOutOfBoundsException if the index is bigger than the size or negative.
+ * @return the given index if it is valid.
+ */
+ public static int checkIndex(int index, int size) {
+ if(index < 0 || index >= size)
+ throw new IndexOutOfBoundsException();
+
+ return index;
+ }
+}
diff --git a/RemoteMain.java b/RemoteMain.java
new file mode 100644
index 0000000..6994db9
--- /dev/null
+++ b/RemoteMain.java
@@ -0,0 +1,41 @@
+package ch.epfl.javass;
+
+import java.io.IOException;
+
+import ch.epfl.javass.gui.GraphicalPlayerAdapter;
+import ch.epfl.javass.net.RemotePlayerServer;
+import javafx.application.Application;
+import javafx.stage.Stage;
+
+/**
+ * An application to launch a Jass Game remotely.
+ * @author Célia Houssiaux
+ * @author Charles Beauville
+ *
+ */
+public final class RemoteMain extends Application{
+
+ /**
+ * Starts a Remote game once the client connects.
+ * @param args no arguments are needed to start a remote game
+ */
+ public static void main(String[] args) {
+ launch(args);
+ }
+
+ @Override
+ public void start(Stage primaryStage) throws Exception {
+ Thread gameThread = new Thread(() -> {
+ try {
+ new RemotePlayerServer(new GraphicalPlayerAdapter()).run();
+ } catch (IOException e) {
+ throw new Error(e);
+ }
+ });
+ gameThread.setDaemon(true);
+ gameThread.start();
+
+ System.out.println("La partie commencera à la connexion du client…");
+ }
+
+}