package player.gamer.python;
import util.gdl.grammar.GdlSentence;
import util.logging.GamerLogger;
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;
import player.gamer.Gamer;
import player.gamer.exception.MetaGamingException;
import player.gamer.exception.MoveSelectionException;
/**
* PythonGamer is a superclass that allows you to hook Python gamers into the
* rest of the Java framework. In order to do this, do the following:
*
* 1) Create a subclass of PythonGamer that overrides getPythonGamerName() and
* getPythonGamerModule() to indicate where the Python source code file is.
* This is the Java stub that refers to the real Python gamer class.
*
* 2) Create the Python source code file, in the /src_py/ directory in the root
* directory for this project. Make sure that the stub points to this class,
* and that the Python class is a valid subclass of Gamer.
*
* For examples where this has already been done, see @PythonLegalGamerStub and
* @PythonRandomGamerStub, which are both implemented in Python and hook into
* the Java framework using the PythonGamer stubs.
*
* @author Sam
* @author evancox
*/
public abstract class PythonGamer extends Gamer
{
Gamer thePythonGamer;
protected abstract String getPythonGamerName();
protected abstract String getPythonGamerModule();
public PythonGamer() {
super();
try {
// Load in the Python gamer, using a Jython intepreter.
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec("from " + getPythonGamerModule() + " import " + getPythonGamerName());
PyObject thePyClass = interpreter.get(getPythonGamerName());
PyObject PyGamerObject = thePyClass.__call__();
thePythonGamer = (Gamer)PyGamerObject.__tojava__(Gamer.class);
} catch(Exception e) {
GamerLogger.logError("GamePlayer", "Caught exception in Python initialization:");
GamerLogger.logStackTrace("GamePlayer", e);
}
}
// The following methods are overriden as 'final' because they should not
// be changed in subclasses of this class. Subclasses of this class should
// only implement getPythonGamerName() and getPythonGamerModule(), and then
// implement the real methods in the actual Python gamer. Essentially, any
// subclass of this class is a Java-implementation stub for the actual real
// Python implementation.
@Override
public final void metaGame(long timeout) throws MetaGamingException {
thePythonGamer.setMatch(getMatch());
thePythonGamer.setRoleName(getRoleName());
try {
thePythonGamer.metaGame(timeout);
} catch(RuntimeException e) {
GamerLogger.logError("GamePlayer", "Caught exception in Python stateMachineMetaGame:");
GamerLogger.logStackTrace("GamePlayer", e);
}
}
@Override
public final GdlSentence selectMove(long timeout) throws MoveSelectionException {
thePythonGamer.setMatch(getMatch());
thePythonGamer.setRoleName(getRoleName());
try {
return thePythonGamer.selectMove(timeout);
} catch(RuntimeException e) {
GamerLogger.logError("GamePlayer", "Caught exception in Python stateMachineSelectMove:");
GamerLogger.logStackTrace("GamePlayer", e);
return null;
}
}
@Override
public final String getName() {
try {
return thePythonGamer.getName();
} catch(RuntimeException e) {
GamerLogger.logError("GamePlayer", "Caught exception in Python getName:");
GamerLogger.logStackTrace("GamePlayer", e);
return this.getClass().getSimpleName();
}
}
}