Add files via upload
Added files for launching the game locally or remotely
This commit is contained in:
parent
77327c8c33
commit
539223ae07
240
LocalMain.java
Normal file
240
LocalMain.java
Normal file
@ -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 :
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {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}.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
launch(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(Stage primaryStage) throws Exception {
|
||||||
|
|
||||||
|
List<String> args = getParameters().getRaw();
|
||||||
|
Map<PlayerId, Player> players = new HashMap<>();
|
||||||
|
Map<PlayerId, String> 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 <j1>…<j4> [<graine>] où :");
|
||||||
|
System.err.println("<jn> spécifie le joueur n, ainsi:");
|
||||||
|
System.err.println(" h:<nom> un joueur humain nommé <nom>");
|
||||||
|
System.err.println(
|
||||||
|
" s:<nom>:<n> un joueur simulé nommé <nom> qui itère l'algorithme MCTS <n> fois");
|
||||||
|
System.err.println(
|
||||||
|
" r:<nom>:<adresse> un joueur distant nommé <nom> et sur le serveur d'adresse : <adresse>");
|
||||||
|
System.err.println("");
|
||||||
|
System.err.println(
|
||||||
|
"Les agruments <nom>, <n> et <adresses> 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 <nom>,");
|
||||||
|
System.err
|
||||||
|
.println(" 10 000 iterations de MCTS, à défaut de <n>,");
|
||||||
|
System.err.println(" et localhost, à défaut de <adresse>,");
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
33
Preconditions.java
Normal file
33
Preconditions.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
41
RemoteMain.java
Normal file
41
RemoteMain.java
Normal file
@ -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…");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user