Show GoProgram.java syntax highlighted
package geronimo.hoshigo.model.external;
import geronimo.hoshigo.model.GoProgramConfig;
import geronimo.hoshigo.model.game.Game;
import geronimo.hoshigo.model.game.GameState;
import geronimo.hoshigo.model.game.Move;
import geronimo.hoshigo.model.game.Score;
import geronimo.hoshigo.model.goban.GoColor;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Vector;
/**
* Classe abstraite definissant le comportement commun
* de tous le programme de go qui fonctionnent dans HoshiGo
* Fait abstraction de l'implementation des actions sur le jeu (jouer un coup,
* annuler un coup, vider le goban...) mais implante les comportement de
* synchronisation d'une programme avec une partie qui vient de changer d'état,
* qui doit être initialisée, etc...
*/
public abstract class GoProgram
{
// uri du fichier executable
protected final String target;
// argument de lancement du fichier executable
protected final String arguments;
// nom du programme
private final String name;
// version du programme
protected String version;
// options de lancement du programme
protected Collection<String> options;
// process du programme
protected Process programProcess;
// flux d'entree du programme
private PrintStream programInput;
// flux de sortie du programme
private BufferedReader programOutput;
// dernier état du jeu
// permet de connaitre la différence entre le jeu courrant et la dernière
// mise à jour du programme de go
protected GameState lastGameState;
// komi courrant pour le programme
private float programKomi;
/**
* Constructeur
* @param programConfig configuration du programme
* @param options option de lancements du programmes
*/
public GoProgram(GoProgramConfig programConfig, List<String> options)
{
super();
// initialisation des champs
this.arguments = programConfig.arguments;
this.name = programConfig.name;
this.target = programConfig.target;
this.options = options;
this.lastGameState = null;
this.programProcess = null;
this.programKomi = -1;
this.programInput = null;
this.programOutput =null;
}
/**
* Envoie une commande au programme de go
* @param command commande à envoyer
*/
protected void sendCommand(String command)
{
if (this.programProcess != null)
{
this.programInput.println(command);
this.programInput.flush();
}
}
/**
* @return la prochaine ligne envoyée par le programme
* @throws GoProgramException
* @throws IOException
*/
protected String getResponse() throws GoProgramException
{
try
{ if (this.programProcess != null)
{
return this.programOutput.readLine();
}
else
{
return "";
}
}
catch (IOException e)
{
throw new GoProgramException("Erreur de lecture sortie du programme "+
e.getMessage());
}
}
/**
* @return le nom du programme
*/
public final String getName()
{
return this.name;
}
/**
* lancement du processus du programme
* @throws GoProgramException
*/
public void launchProgram() throws GoProgramException
{
if (this.programProcess == null)
{
List<String> arguments = new Vector<String>();
// creation de la ligne de commande
arguments.add(this.target);
// ajoute les tokens des arguments
for (String s : this.arguments.split("\\s"))
{
arguments.add(s);
}
// passe toutes les options et les splite selon les blancs
for (String s : this.options)
{
for (String tok : s.split("\\s"))
{
arguments.add(tok);
}
}
ProcessBuilder pf = new ProcessBuilder(arguments);
try
{
this.programProcess = pf.start();
this.programInput =
new PrintStream(this.programProcess.getOutputStream());
this.programOutput =
new BufferedReader(new InputStreamReader(
this.programProcess.getInputStream()));
//
Thread.sleep(300);
// verifie que le programme n'ait pas envoyé un message d'erreur
if (this.programProcess.getErrorStream().available() != 0)
{
throw new GoProgramException("Erreur au lancement de " +
this.getName() + " : " +
(new BufferedReader(new InputStreamReader(
this.programProcess.getErrorStream())).
readLine()));
}
}
catch (IOException e)
{
throw new GoProgramException(
"Erreur inattendue lors du lancement de " +
this.getName());
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* Tue le processus du programme externe
*/
public void killProgram()
{
if (this.programProcess != null)
{
this.programProcess.destroy();
this.programInput = null;
this.programOutput = null;
this.programProcess = null;
}
}
/**
* Synchronize l'état du jeu avec celui de la partie donnée en argument
* @param game le jeu avec lequel synchronizer
* @throws GoProgramException
*/
public void synchronizeWithGame(Game game) throws GoProgramException
{
// synchronise le komi
this.synchronizeKomi(game);
if (game.contains(this.lastGameState))
{
if (this.lastGameState != game.getCurrentGameState())
{
this.playStateSequence(
game.getStatesSequenceBeetween(this.lastGameState,
game.getCurrentGameState()));
this.lastGameState = game.getCurrentGameState();
}
}
else
{
this.initializeGame(game);
}
}
private void synchronizeKomi(Game game) throws GoProgramException
{
if (game.komi != this.programKomi)
{
this.setKomi(game.komi);
this.programKomi = game.komi;
}
}
/**
* initialise la partie du programme avec le jeu donné en paramètre
* @param game le jeu à entrer dans le programme
* @throws GoProgramException
*/
public void initializeGame(Game game) throws GoProgramException
{
this.clearBoard(game.getCurrentGameState().getGoban().size);
// synchronise le komi
this.synchronizeKomi(game);
List<GameState> allGameStates = game.getCurrentGameState().getAllParents();
allGameStates.add(0,game.getCurrentGameState());
Collections.reverse(allGameStates);
this.playStateSequence(allGameStates);
this.lastGameState = game.getCurrentGameState();
}
/**
* Joue la séquence de coups pour passer tous les états de la liste donnée
* en argument
* @param stateSequence
* @throws GoProgramException
*/
private void playStateSequence(List<GameState> stateSequence) throws GoProgramException
{
Iterator<GameState> i = stateSequence.iterator();
GameState source;
GameState target;
if (i.hasNext())
{
target = i.next();
while(i.hasNext())
{
source = target;
target = i.next();
if (source.getParent() != null
&& target.equals(source.getParent()))
{
this.undo(); //revient en arrière
}
else if (target.getParent() != null
&& source.equals(target.getParent()))
{
this.play(target.lastMove); // joue un coup
}
}
}
}
/**
* Vide le goban du programme et change éventuellement sa taille
* @throws GoProgramException
*/
protected abstract void clearBoard(int gobanSize) throws GoProgramException;
/**
* arrête gentillement le programme
*/
public abstract void stopProgram();
/**
* @return le nom du programme
*/
public abstract String getProgramName() throws GoProgramException;
/**
* @return la version du programme
* @throws GoProgramException
*/
public abstract String getProgramVersion() throws GoProgramException;
/**
* @param color la couleur du joueur
* @return l'ensemble de coups légaux
* @throws GoProgramException
*/
public abstract Set<Move> getLegalMovesFor(GoColor color) throws GoProgramException;
/**
* @return le score de la partie
* @throws GoProgramException
*/
public abstract Score getScore() throws GoProgramException;
/**
* Génère le coup joué par le programme parmi un ensemble de coups possibles
* @param color couleur du joueur dont on veut savoir son prochain coup
* @return le coup joué par le programme
* @throws GoProgramException
*/
public abstract Move genMove(GoColor color) throws GoProgramException;
/**
* Indique au programme de go qu'il y a un coup qui a été joué
* @param move le coup qui a été joué
* @throws GoProgramException
*/
public abstract void play(Move move) throws GoProgramException;
/**
* Met à jour la valeur du komi d'une partie
* @param komi nouvelle valeur du komi
* @throws GoProgramException
*/
public abstract void setKomi(float komi) throws GoProgramException;
/**
* Demande au programme de go d'annuler le dernier mouvements
* @throws GoProgramException
*/
public abstract void undo() throws GoProgramException;
}
See more files for this project here