package player.gamer.clojure; import util.game.GameRepository; import util.gdl.grammar.GdlPool; import util.gdl.grammar.GdlSentence; import util.logging.GamerLogger; import util.match.Match; import clojure.lang.RT; import clojure.lang.Var; import player.gamer.Gamer; import player.gamer.clojure.stubs.ClojureLegalGamerStub; import player.gamer.exception.MetaGamingException; import player.gamer.exception.MoveSelectionException; /** * ClojureGamer is a superclass that allows you to hook Clojure gamers into the * rest of the Java framework. In order to do this, do the following: * * 1) Create a subclass of ClojureGamer that overrides getClojureGamerFile() and * getClojureGamerName() to indicate where the Clojure source code file is. * This is the Java stub that refers to the real Clojure gamer class. * * 2) Create the Clojure source code file, in the /src_clj/ directory in the root * directory for this project. Make sure that the stub points to this class, * and that the Clojure class is a valid subclass of Gamer. * * For examples where this has already been done, see @ClojureLegalGamerStub, * which is implemented in Clojure and hook into the Java framework using the * ClojureGamer stub. * * @author Sam Schreiber */ public abstract class ClojureGamer extends Gamer { Gamer theClojureGamer; protected abstract String getClojureGamerFile(); protected abstract String getClojureGamerName(); public ClojureGamer() { super(); try { // Load the Clojure script -- as a side effect this initializes the runtime. RT.loadResourceScript(getClojureGamerFile() + ".clj"); // Get a reference to the gamer-generating function. Var gamerVar = RT.var("gamer_namespace", getClojureGamerName()); // Call it! theClojureGamer = (Gamer)gamerVar.invoke(); } catch(Exception e) { GamerLogger.logError("GamePlayer", "Caught exception in Clojure 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 getClojureGamerFile() and getClojureGamerName(), and then // implement the real methods in the actual Clojure gamer. Essentially, any // subclass of this class is a Java-implementation stub for the actual real // Clojure implementation. @Override public final void metaGame(long timeout) throws MetaGamingException { theClojureGamer.setMatch(getMatch()); theClojureGamer.setRoleName(getRoleName()); try { theClojureGamer.metaGame(timeout); } catch(RuntimeException e) { GamerLogger.logError("GamePlayer", "Caught exception in Clojure stateMachineMetaGame:"); GamerLogger.logStackTrace("GamePlayer", e); } } @Override public final GdlSentence selectMove(long timeout) throws MoveSelectionException { theClojureGamer.setMatch(getMatch()); theClojureGamer.setRoleName(getRoleName()); try { return theClojureGamer.selectMove(timeout); } catch(RuntimeException e) { GamerLogger.logError("GamePlayer", "Caught exception in Clojure stateMachineSelectMove:"); GamerLogger.logStackTrace("GamePlayer", e); return null; } } @Override public final String getName() { try { return theClojureGamer.getName(); } catch(RuntimeException e) { GamerLogger.logError("GamePlayer", "Caught exception in Clojure getName:"); GamerLogger.logStackTrace("GamePlayer", e); return this.getClass().getSimpleName(); } } // TODO: This code should be put somewhere more general. public static void main(String args[]) { try { Gamer g = new ClojureLegalGamerStub(); System.out.println(g.getName()); Match m = new Match("", 1000, 1000, GameRepository.getDefaultRepository().getGame("conn4")); g.setMatch(m); g.setRoleName(GdlPool.getProposition(GdlPool.getConstant("xplayer"))); g.metaGame(1000); System.out.println(g.selectMove(1000)); } catch(Exception e) { e.printStackTrace(); } } }