Game can now be run using java -jar GoGame.jar.

Rather than relying on the kgsGtp.jar application to run GoGame,
the GoGame agent calls the GtpClient using PipedInput/OutputStreams.
This commit is contained in:
cs6601
2012-09-06 09:43:32 -04:00
parent d4acc5beda
commit ca6863b43e
8 changed files with 110 additions and 74 deletions

View File

@@ -5,5 +5,6 @@
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="lib" path="lib/junit-4.10.jar"/> <classpathentry kind="lib" path="lib/junit-4.10.jar"/>
<classpathentry kind="lib" path="lib/log4j-1.2.16.jar"/> <classpathentry kind="lib" path="lib/log4j-1.2.16.jar"/>
<classpathentry kind="lib" path="lib/kgsGtp.jar"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

View File

@@ -48,7 +48,8 @@
<jar jarfile="${dist}/GoGame.jar"> <jar jarfile="${dist}/GoGame.jar">
<fileset dir="${build}" excludes="**/*Test.class" /> <fileset dir="${build}" excludes="**/*Test.class" />
<manifest> <manifest>
<attribute name="Main-Class" value="cs6601.p1.GoGame" /> <attribute name="Main-Class" value="net.woodyfolsom.msproj.GoGame" />
<attribute name="Class-Path" value="kgsGtp.jar log4j-1.2.16.jar"/>
</manifest> </manifest>
</jar> </jar>
</target> </target>

View File

@@ -1 +0,0 @@
java -jar kgsGtp.jar kgsGtp.ini

View File

@@ -9,5 +9,4 @@ reconnect=t
automatch.rank=25k automatch.rank=25k
rules=chinese rules=chinese
rules.boardSize=9 rules.boardSize=9
rules.time=0 rules.time=0
rules.komi=5.5

BIN
lib/kgsGtp.jar Normal file

Binary file not shown.

View File

@@ -1,7 +1,14 @@
package net.woodyfolsom.msproj; package net.woodyfolsom.msproj;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintWriter;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Properties;
import net.woodyfolsom.msproj.Command.TYPE; import net.woodyfolsom.msproj.Command.TYPE;
import net.woodyfolsom.msproj.policy.AlphaBeta; import net.woodyfolsom.msproj.policy.AlphaBeta;
@@ -13,8 +20,11 @@ import net.woodyfolsom.msproj.policy.RandomMovePolicy;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator; import org.apache.log4j.xml.DOMConfigurator;
import com.gokgs.client.gtp.GtpClient;
import com.gokgs.client.gtp.Options;
public class GoGame { public class GoGame implements Runnable {
private static final String PROPS_FILE = "kgsGtp.ini";
private static final int INVALID_MOVE_GENERATOR = 1; private static final int INVALID_MOVE_GENERATOR = 1;
private static final Logger LOGGER = Logger.getLogger(GoGame.class private static final Logger LOGGER = Logger.getLogger(GoGame.class
.getName()); .getName());
@@ -22,20 +32,74 @@ public class GoGame {
private boolean shutDown = false; private boolean shutDown = false;
private GameConfig gameConfig = new GameConfig(); private GameConfig gameConfig = new GameConfig();
private GameState gameState = new GameState(9); private GameState gameState = new GameState(9);
private GtpClient client = null;
private Policy moveGenerator; private Policy moveGenerator;
private Properties properties;
public GoGame(Policy moveGenerator) { private PipedOutputStream remoteOutput = new PipedOutputStream();
this.moveGenerator = moveGenerator; private PipedInputStream localInput = new PipedInputStream(remoteOutput);
private PipedOutputStream localOutputInner = new PipedOutputStream();
private PipedInputStream remoteInput = new PipedInputStream(localOutputInner);
private PrintWriter localOutput = new PrintWriter(localOutputInner);
public OutputStream getOutputStream() {
return remoteOutput;
} }
public static void main(String[] args) { public InputStream getInputStream() {
return remoteInput;
}
public Properties getProperties() {
return properties;
}
public GoGame(Policy moveGenerator, String propFileName) throws IOException {
this.moveGenerator = moveGenerator;
this.properties = new Properties();
FileInputStream fis = null;
try {
fis = new FileInputStream(propFileName);
properties.load(fis);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ioe) {
LOGGER.info(ioe.getMessage());
}
}
}
}
public void run() {
play();
}
public static void main(String[] args) throws IOException {
configureLogging(); configureLogging();
if (args.length == 0) { if (args.length == 0) {
Policy defaultMoveGenerator = new MonteCarloUCT(new RandomMovePolicy(), 2000L); Policy defaultMoveGenerator = new MonteCarloUCT(new RandomMovePolicy(), 5000L);
LOGGER.info("No MoveGenerator specified. Using default: " + defaultMoveGenerator.getClass().getName()); LOGGER.info("No MoveGenerator specified. Using default: " + defaultMoveGenerator.toString());
new GoGame(defaultMoveGenerator).play();
GoGame goGame = new GoGame(defaultMoveGenerator, PROPS_FILE);
new Thread(goGame).start();
System.out.println("Creating GtpClient");
goGame.client = new GtpClient(goGame.getInputStream(), goGame.getOutputStream(), new Options(goGame.getProperties(), LOGGER.getName()));
System.out.println("GtpClient created");
System.out.println("Invoking GtpClient.go()...");
if (goGame.client.go()) {
System.out.println("GtpClient.go() succeeded.");
} else {
System.out.println("GtpClient.go() failed.");
}
} else { } else {
new GoGame(createPolicy(args[0])).play(); new GoGame(createPolicy(args[0]), PROPS_FILE).play();
} }
} }
@@ -60,19 +124,19 @@ public class GoGame {
switch (cmd.getType()) { switch (cmd.getType()) {
case INVALID: case INVALID:
LOGGER.info("Invalid command ignored: " + cmd.getText()); LOGGER.info("Invalid command ignored: " + cmd.getText());
System.out.println("? Invalid command: " + cmd.getText() + "\n"); localOutput.println("? Invalid command: " + cmd.getText() + "\n");
break; break;
case boardsize: case boardsize:
gameState = new GameState(cmd.getIntField(1)); gameState = new GameState(cmd.getIntField(1));
System.out.println("=\n"); localOutput.println("=\n");
break; break;
case clear_board: case clear_board:
gameState.clearBoard(); gameState.clearBoard();
System.out.println("=\n"); localOutput.println("=\n");
break; break;
case final_status_list: case final_status_list:
LOGGER.info(new StateEvaluator(gameConfig).scoreGame(gameState)); LOGGER.info(new StateEvaluator(gameConfig).scoreGame(gameState));
System.out.println("=\n"); localOutput.println("=\n");
break; break;
case genmove: case genmove:
LOGGER.info("Generating move for:\n" + gameState); LOGGER.info("Generating move for:\n" + gameState);
@@ -93,13 +157,13 @@ public class GoGame {
gameState.playStone(player, nextMove); gameState.playStone(player, nextMove);
LOGGER.info(new StateEvaluator(gameConfig).scoreGame(gameState)); LOGGER.info(new StateEvaluator(gameConfig).scoreGame(gameState));
System.out.println("=" localOutput.println("="
+ nextMove.toString() + "\n"); + nextMove.toString() + "\n");
break; break;
case komi: case komi:
gameConfig.setKomi(cmd.getDoubleField(1)); gameConfig.setKomi(cmd.getDoubleField(1));
System.out.println("=\n"); localOutput.println("=\n");
break; break;
case list_commands: case list_commands:
StringBuilder sb = new StringBuilder("= "); StringBuilder sb = new StringBuilder("= ");
@@ -109,45 +173,60 @@ public class GoGame {
sb.append("\n"); sb.append("\n");
} }
} }
System.out.println(sb.toString()); System.out.println("Sending response: " + sb.toString());
localOutput.println(sb.toString());
System.out.println("Response sent.");
break; break;
case name: case name:
System.out.println("= CS6601P1\n"); localOutput.println("= CS6601P1\n");
break; break;
case quit: case quit:
System.out.println("=\n"); localOutput.println("=\n");
shutDown = true; shutDown = true;
break; break;
case play: case play:
if (gameState.playStone(Player.getInstance(cmd.getStringField(1)), cmd if (gameState.playStone(Player.getInstance(cmd.getStringField(1)), cmd
.getStringField(2).toUpperCase())) { .getStringField(2).toUpperCase())) {
System.out.println("=\n"); localOutput.println("=\n");
} else { } else {
String errMsg = "Unable to make requested play: " String errMsg = "Unable to make requested play: "
+ cmd.getText(); + cmd.getText();
LOGGER.info(errMsg); LOGGER.info(errMsg);
LOGGER.info("GameState: " + gameState); LOGGER.info("GameState: " + gameState);
System.out.println("?" + errMsg + "\n"); localOutput.println("?" + errMsg + "\n");
} }
LOGGER.info(new StateEvaluator(gameConfig).scoreGame(gameState)); LOGGER.info(new StateEvaluator(gameConfig).scoreGame(gameState));
break; break;
case version: case version:
System.out.println("= 0.1\n"); localOutput.println("= 0.1\n");
break; break;
default: default:
LOGGER.warn("An error occured. Unhandled command: " + cmd); LOGGER.warn("An error occured. Unhandled command: " + cmd);
} }
localOutput.flush();
} }
public void play() { public void play() {
byte[] buf = new byte[128]; byte[] buf = new byte[128];
int inputLength; int inputLength;
try { try {
while (!shutDown && (inputLength = System.in.read(buf)) > 0) { while (!shutDown && (inputLength = localInput.read(buf)) > 0) {
System.out.println("Waiting for input");
String commandText = new String(buf, 0, inputLength, String commandText = new String(buf, 0, inputLength,
Charset.forName("UTF-8")); Charset.forName("UTF-8"));
System.out.println("Input received: " + commandText);
LOGGER.info("Command received: " + commandText); LOGGER.info("Command received: " + commandText);
executeCommand(CommandParser.parse(commandText));
Command cmd = CommandParser.parse(commandText);
executeCommand(cmd);
if (cmd.getType() == Command.TYPE.genmove) {
System.out.println("New game state:\n" + gameState);
}
} }
} catch (IOException ioe) { } catch (IOException ioe) {
LOGGER.warn(ioe.getMessage()); LOGGER.warn(ioe.getMessage());

View File

@@ -1,48 +0,0 @@
package net.woodyfolsom.msproj;
public class GtpClient {
/**
* Create a new GTP Client.
*
* @param in
* An input stream that will give us any responses from the
* engine.
* @param out
* An output stream that will go to the engine with our commands.
* @param args
* Our options.
*/
public GtpClient(java.io.InputStream in, java.io.OutputStream out,
Options options) {
}
/**
* Connect to the server and operate the GTP interface.
*
* @return <code>true</code> on success, <code>false</code> if we were
* unable to do what was requested.
*/
public boolean go() {
return false;
}
}
class Options {
/**
* Construct a new set of options for the kgsGtp client by pulling values
* out of a set of properties. Any values that we use will be removed from
* the properties, so anything left over is unused.
*
* @param props
* The properties that holds our options as string values.
* @param logName
* The name of the java logger that we will construct.
* @throws IllegalArgumentException
* If any required values are missing or if any illegal values
* are detected.
*/
public Options(java.util.Properties props, String logName) {
}
}

View File

@@ -139,4 +139,9 @@ public class MonteCarloUCT extends MonteCarlo {
Collection<Action> prohibitedActions, Player player) { Collection<Action> prohibitedActions, Player player) {
throw new UnsupportedOperationException("Prohibited actions not supported by this class."); throw new UnsupportedOperationException("Prohibited actions not supported by this class.");
} }
@Override
public String toString() {
return "MonteCarloUCT";
}
} }