First working implementation of ANN which is trained using GameResults.

The PassFilter simply outputs BlackWins and WhiteWins (Range 0 - 1 but not presently clamped).
In principle, this type of feedforward ANN can be used to decide whether a PASS will result in blackwins or whitewins at any stage.
The goal is for the network to learn that passing while losing when valid moves exist is bad, but passing while winning is relatively harmless later in the game.
This commit is contained in:
2012-11-17 18:40:31 -05:00
parent d9d6ecda80
commit aca8320600
37 changed files with 1040 additions and 544 deletions

View File

@@ -139,7 +139,7 @@ blackRank
whiteRank whiteRank
: 'WR'; : 'WR';
komi : 'KM'; komi : 'KM' | 'KoMi';
result : 'RE' result : 'RE'
| 'REsult' | 'REsult'
@@ -169,7 +169,7 @@ copyright
username: 'US'; username: 'US';
comment : 'C'; comment : 'C' | 'Comment';
strValue strValue
: (STRVALUE)+; : (STRVALUE)+;
@@ -191,10 +191,13 @@ PLUS : '+';
SLASH : '/'; SLASH : '/';
STRVALUE : (UCLETTER | LCLETTER | MINUS | DIGIT | SPACE | PERIOD | COMMA | PLUS | SLASH | COLON )+;
LPAREN : '(' ; LPAREN : '(' ;
RPAREN : ')';
STRVALUE : (UCLETTER | LCLETTER | MINUS | DIGIT | SPACE | PERIOD | COMMA | PLUS | SLASH | COLON | LPAREN | RPAREN )+;
SEMICOLON : ';' ; SEMICOLON : ';' ;
fragment UCLETTER : 'A'..'Z'; fragment UCLETTER : 'A'..'Z';
@@ -207,8 +210,6 @@ LBRACKET
RBRACKET RBRACKET
: ']'; : ']';
RPAREN : ')';
//CR : '\r'{$channel=HIDDEN;}; //CR : '\r'{$channel=HIDDEN;};
//NEWLINE : '\n'{$channel=HIDDEN;}; //NEWLINE : '\n'{$channel=HIDDEN;};

View File

@@ -28,7 +28,7 @@ DaTe[1968]
PlaCe[] PlaCe[]
REsult[Black wins by four points] REsult[B+4]
C[This was the second and last game in a two game match on 9x9, C[This was the second and last game in a two game match on 9x9,

View File

@@ -13,7 +13,7 @@ VieW[]
SiZe[9] SiZe[9]
KoMi[5 1/2] KoMi[5.5]
EVent[TV game] EVent[TV game]
@@ -31,7 +31,7 @@ DaTe[1992]
PlaCe[Osaka] PlaCe[Osaka]
REsult[White wins by 11 1/2] REsult[W+11.5]
Comment[ Comment[

View File

@@ -13,7 +13,7 @@ VieW[]
SiZe[9] SiZe[9]
KoMi[5 1/2] KoMi[5.5]
EVent[TV game] EVent[TV game]
@@ -31,7 +31,7 @@ DaTe[1992]
PlaCe[Osaka] PlaCe[Osaka]
REsult[Black wins by 1/2 point] REsult[B+0.5]
Comment[ Comment[

View File

@@ -13,7 +13,7 @@ VieW[]
SiZe[9] SiZe[9]
KoMi[5 1/2] KoMi[5.5]
EVent[TV game] EVent[TV game]
@@ -31,7 +31,7 @@ DaTe[1992]
PlaCe[Osaka] PlaCe[Osaka]
REsult[White wins by 4 1/2] REsult[W+4.5]
Comment[ Comment[

View File

@@ -13,7 +13,7 @@ VieW[]
SiZe[9] SiZe[9]
KoMi[5 1/2] KoMi[5.5]
EVent[TV game] EVent[TV game]
@@ -31,7 +31,7 @@ DaTe[1992]
PlaCe[Osaka] PlaCe[Osaka]
REsult[Black wins by 1/2] REsult[B+0.5]
Comment[ Comment[

View File

@@ -13,7 +13,7 @@ VieW[]
SiZe[9] SiZe[9]
KoMi[5 1/2] KoMi[5.5]
EVent[TV game] EVent[TV game]
@@ -31,7 +31,7 @@ DaTe[1992]
PlaCe[Osaka] PlaCe[Osaka]
REsult[Black wins by 5 1/2] REsult[B+5.5]
Comment[ Comment[

View File

@@ -13,7 +13,7 @@ VieW[]
SiZe[9] SiZe[9]
KoMi[5 1/2] KoMi[5.5]
EVent[TV game] EVent[TV game]
@@ -31,7 +31,7 @@ DaTe[1992]
PlaCe[Osaka] PlaCe[Osaka]
REsult[White wins by 3 1/2] REsult[W+3.5]
Comment[ Comment[

View File

@@ -13,7 +13,7 @@ VieW[]
SiZe[9] SiZe[9]
KoMi[5 1/2] KoMi[5.5]
EVent[TV game] EVent[TV game]
@@ -31,7 +31,7 @@ DaTe[1992]
PlaCe[Osaka] PlaCe[Osaka]
REsult[Black wins by 4 1/2] REsult[B+4.5]
Comment[ Comment[

BIN
data/networks/Pass1.nn Normal file

Binary file not shown.

1
data/test/scoretest1.sgf Normal file
View File

@@ -0,0 +1 @@
(;FF[4]GM[1]SZ[5]KM[3.5]RE[W+11.5];B[ad];W[bd];B[be];W[ed];B[dd];W[ba];B[cd];W[ca];B[ee];W[cb];B[];W[dc];B[db];W[ac];B[];W[ec];B[ae];W[bc];B[ce];W[cc];B[aa];W[de];B[be];W[];B[ce];W[ad];B[dd];W[];B[ea];W[eb];B[ae];W[];B[ee];W[da];B[bb];W[de];B[];W[])

View File

@@ -0,0 +1 @@
(;FF[4]GM[1]SZ[6]KM[1.5]RE[W+26.5];B[ab];W[ff];B[ca];W[df];B[de];W[ce];B[cf];W[ba];B[aa];W[eb];B[be];W[bf];B[dc];W[ea];B[bc];W[cc];B[dd];W[fc];B[ad];W[db];B[fd];W[fa];B[cb];W[ed];B[];W[ec];B[fe];W[af];B[cd];W[ef];B[];W[ae];B[];W[bd];B[];W[ac];B[bb];W[da];B[ad];W[ee];B[];W[cc];B[dc];W[dd];B[];W[ac];B[];W[fd];B[];W[ba];B[aa];W[cb];B[];W[ab];B[];W[bc];B[];W[])

View File

@@ -0,0 +1 @@
(;FF[4]GM[1]SZ[6]KM[1.5]RE[B+1.5];B[de];W[eb];B[af];W[ce];B[df];W[ef];B[cb];W[ff];B[cd];W[be];B[ee];W[db];B[ad];W[ea];B[ed];W[fc];B[fe];W[cc];B[bc];W[ef];B[];W[fa];B[ae];W[ba];B[];W[ac];B[];W[cf];B[ca];W[ec];B[dd];W[dc];B[bb];W[bd];B[];W[da];B[bf];W[ce];B[ab];W[];B[aa];W[be];B[];W[cf];B[];W[fd];B[];W[])

View File

@@ -0,0 +1 @@
(;FF[4]GM[1]SZ[6]KM[1.5]RE[W+16.5];B[bc];W[ff];B[fb];W[eb];B[ee];W[ce];B[de];W[ef];B[fe];W[df];B[ea];W[fc];B[];W[db];B[ed];W[fa];B[ab];W[fd];B[cd];W[aa];B[];W[cc];B[af];W[bb];B[bf];W[ec];B[cb];W[be];B[ca];W[dd];B[ac];W[cf];B[de];W[bd];B[ed];W[ae];B[ba];W[bf];B[];W[da];B[];W[fe];B[];W[ee];B[];W[ad];B[];W[])

View File

@@ -0,0 +1 @@
(;FF[4]GM[1]SZ[6]KM[1.5]RE[W+4.5];B[eb];W[bf];B[ff];W[dc];B[ba];W[bc];B[ce];W[cd];B[df];W[ee];B[be];W[af];B[ec];W[ca];B[ea];W[ed];B[fc];W[];B[ef];W[];B[fd];W[fe];B[cf];W[dd];B[cc];W[ad];B[bd];W[ae];B[fb];W[de];B[ab];W[ac];B[bb];W[];B[ce];W[];B[be];W[cb];B[df];W[aa];B[cf];W[bb];B[ff];W[];B[bd];W[];B[db];W[];B[da];W[];B[])

View File

@@ -0,0 +1 @@
(;FF[4]GM[1]SZ[6]KM[1.5]RE[B+25.5];B[ce];W[ef];B[eb];W[fe];B[ba];W[ee];B[be];W[bd];B[df];W[ae];B[dd];W[fb];B[ea];W[cd];B[fc];W[dc];B[cc];W[ad];B[fa];W[ca];B[cf];W[ed];B[db];W[de];B[af];W[aa];B[da];W[];B[fd];W[bc];B[ec];W[ab];B[cb];W[bb];B[dd];W[];B[ff];W[ee];B[ac];W[ed];B[bd];W[aa];B[ef];W[];B[ae];W[];B[de];W[];B[fe];W[ed];B[ab];W[];B[bc];W[];B[ee];W[];B[])

View File

@@ -0,0 +1 @@
(;FF[4]GM[1]SZ[6]KM[1.5]RE[B+2.5];B[eb];W[cb];B[ff];W[ed];B[ce];W[de];B[ba];W[bc];B[be];W[ee];B[ae];W[];B[df];W[aa];B[cc];W[ea];B[cf];W[ca];B[db];W[ac];B[fa];W[bd];B[ef];W[dd];B[fc];W[cd];B[ec];W[];B[dc];W[];B[da];W[bb];B[fe];W[fd];B[bf];W[];B[])

View File

@@ -0,0 +1,9 @@
Cumulative results for 3 games (BLACK=ROOT_PAR, WHITE=UCT)
1. W+26.5
2. B+1.5
3. W+16.5
Cumulative results for 3 games (BLACK=UCT, WHITE=ROOT_PAR)
1. W+4.5
2. B+25.5
3. B+2.5
Elapsed Time: 301.403 seconds.

View File

@@ -178,6 +178,39 @@ public class GameBoard {
return false; return false;
} }
public boolean isSelfFill(Action action, Player player) {
if (action.isNone() || action.isPass() || action.isResign()) {
return false;
}
int col = getColumnIndex(action.getColumn());
int row = action.getRow() - 1;
char stoneSymbol;
if (player == Player.BLACK) {
stoneSymbol = BLACK_STONE;
} else if (player == Player.WHITE) {
stoneSymbol = WHITE_STONE;
} else {
throw new RuntimeException("Invalid player " + player);
}
//checking the # liberties of this stone's 'string' would be a generalization of self-atari. This is a simple case.
if (col > 0 && getSymbolAt(col-1,row) != stoneSymbol) {
return false;
}
if (col < size - 1 && getSymbolAt(col+1,row) != stoneSymbol) {
return false;
}
if (row > 0 && getSymbolAt(col,row-1) != stoneSymbol) {
return false;
}
if (row < size -1 && getSymbolAt(col,row+1) != stoneSymbol) {
return false;
}
return true;
}
public boolean isTerritoryMarked() { public boolean isTerritoryMarked() {
return territoryMarked; return territoryMarked;
} }

View File

@@ -119,6 +119,10 @@ public class GameState {
return whitePrisoners; return whitePrisoners;
} }
public boolean isSelfFill(Action action, Player player) {
return gameBoard.isSelfFill(action, player);
}
/** /**
* Used for setting up the board. Places the player's stone at the specified coordinates. * Used for setting up the board. Places the player's stone at the specified coordinates.
* *

View File

@@ -18,6 +18,7 @@ public class SGFWriter {
writer.write("SZ[" + gameConfig.getSize() + "]"); writer.write("SZ[" + gameConfig.getSize() + "]");
writer.write("KM[" + gameConfig.getKomi() + "]"); writer.write("KM[" + gameConfig.getKomi() + "]");
writer.write("RE[" + gameRecord.getGameState(gameRecord.getNumTurns()).getResult() + "]");
for (int i = 1; i <= gameRecord.getNumTurns(); i++) { for (int i = 1; i <= gameRecord.getNumTurns(); i++) {
Player player = gameRecord.getPlayerToMove(i-1); Player player = gameRecord.getPlayerToMove(i-1);

View File

@@ -18,15 +18,14 @@ import net.woodyfolsom.msproj.policy.RandomMovePolicy;
import net.woodyfolsom.msproj.policy.RootParallelization; import net.woodyfolsom.msproj.policy.RootParallelization;
public class StandAloneGame { public class StandAloneGame {
private static final int DEFAULT_TURN_LENGTH = 2; // default turn is 2 private static final int DEFAULT_TURN_LENGTH = 1; // default turn is 2
// seconds; // seconds;
private static final double DEFAULT_KOMI = 5.5; private static final double DEFAULT_KOMI = 5.5;
private static final int DEFAULT_NUM_GAMES = 1; private static final int DEFAULT_NUM_GAMES = 1;
private static final int DEFAULT_SIZE = 9; private static final int DEFAULT_SIZE = 9;
enum PLAYER_TYPE { enum PLAYER_TYPE {
HUMAN, HUMAN_GUI, ROOT_PAR, UCT_FAST, UCT_SLOW, RANDOM HUMAN, HUMAN_GUI, ROOT_PAR, UCT, RANDOM
}; };
public static void main(String[] args) { public static void main(String[] args) {
@@ -39,8 +38,11 @@ public class StandAloneGame {
int nGames = DEFAULT_NUM_GAMES; int nGames = DEFAULT_NUM_GAMES;
int size = DEFAULT_SIZE; int size = DEFAULT_SIZE;
double komi = DEFAULT_KOMI; double komi = DEFAULT_KOMI;
int turnLength = DEFAULT_TURN_LENGTH;
switch (args.length) { switch (args.length) {
case 6:
turnLength = Integer.valueOf(args[5]);
case 5: case 5:
nGames = Integer.valueOf(args[4]); nGames = Integer.valueOf(args[4]);
case 4: case 4:
@@ -59,17 +61,14 @@ public class StandAloneGame {
+ "."); + ".");
} }
new StandAloneGame().playGame(parsePlayerType(args[0]), new StandAloneGame().playGame(parsePlayerType(args[0]),
parsePlayerType(args[1]), size, komi, nGames); parsePlayerType(args[1]), size, komi, nGames, turnLength);
} }
private static PLAYER_TYPE parsePlayerType(String playerTypeStr) { private static PLAYER_TYPE parsePlayerType(String playerTypeStr) {
if ("UCT_FAST".equalsIgnoreCase(playerTypeStr)) { if ("UCT".equalsIgnoreCase(playerTypeStr)) {
return PLAYER_TYPE.UCT_FAST; return PLAYER_TYPE.UCT;
} else if ("ROOT_PAR".equalsIgnoreCase(playerTypeStr)) { } else if ("ROOT_PAR".equalsIgnoreCase(playerTypeStr)) {
return PLAYER_TYPE.ROOT_PAR; return PLAYER_TYPE.ROOT_PAR;
} else if ("UCT_SLOW".equalsIgnoreCase(playerTypeStr)
|| "UCT".equalsIgnoreCase(playerTypeStr)) {
return PLAYER_TYPE.UCT_SLOW;
} else if ("HUMAN".equalsIgnoreCase(playerTypeStr)) { } else if ("HUMAN".equalsIgnoreCase(playerTypeStr)) {
return PLAYER_TYPE.HUMAN; return PLAYER_TYPE.HUMAN;
} else if ("HUMAN_GUI".equalsIgnoreCase(playerTypeStr)) { } else if ("HUMAN_GUI".equalsIgnoreCase(playerTypeStr)) {
@@ -82,16 +81,18 @@ public class StandAloneGame {
} }
public void playGame(PLAYER_TYPE playerType1, PLAYER_TYPE playerType2, public void playGame(PLAYER_TYPE playerType1, PLAYER_TYPE playerType2,
int size, double komi, int rounds) { int size, double komi, int rounds, int turnLength) {
long startTime = System.currentTimeMillis();
GameConfig gameConfig = new GameConfig(size); GameConfig gameConfig = new GameConfig(size);
gameConfig.setKomi(komi); gameConfig.setKomi(komi);
Referee referee = new Referee(); Referee referee = new Referee();
referee.setPolicy(Player.BLACK, referee.setPolicy(Player.BLACK,
getPolicy(playerType1, gameConfig, Player.BLACK)); getPolicy(playerType1, gameConfig, Player.BLACK, turnLength));
referee.setPolicy(Player.WHITE, referee.setPolicy(Player.WHITE,
getPolicy(playerType2, gameConfig, Player.WHITE)); getPolicy(playerType2, gameConfig, Player.WHITE, turnLength));
List<GameResult> round1results = new ArrayList<GameResult>(); List<GameResult> round1results = new ArrayList<GameResult>();
@@ -102,14 +103,16 @@ public class StandAloneGame {
List<GameResult> round2results = new ArrayList<GameResult>(); List<GameResult> round2results = new ArrayList<GameResult>();
referee.setPolicy(Player.BLACK, referee.setPolicy(Player.BLACK,
getPolicy(playerType2, gameConfig, Player.BLACK)); getPolicy(playerType2, gameConfig, Player.BLACK, turnLength));
referee.setPolicy(Player.WHITE, referee.setPolicy(Player.WHITE,
getPolicy(playerType1, gameConfig, Player.WHITE)); getPolicy(playerType1, gameConfig, Player.WHITE, turnLength));
for (int round = 0; round < rounds; round++) { for (int round = 0; round < rounds; round++) {
round2results.add(referee.play(gameConfig)); round2results.add(referee.play(gameConfig));
} }
DateFormat dateFormat = new SimpleDateFormat("yyMMddHHmmssZ"); long endTime = System.currentTimeMillis();
DateFormat dateFormat = new SimpleDateFormat("yyMMddHHmmss");
try { try {
@@ -123,6 +126,8 @@ public class StandAloneGame {
logResults(writer, round2results, playerType2.toString(), logResults(writer, round2results, playerType2.toString(),
playerType1.toString()); playerType1.toString());
writer.write("Elapsed Time: " + (endTime - startTime) / 1000.0 + " seconds.");
System.out.println("Game tournament saved as " System.out.println("Game tournament saved as "
+ txtFile.getAbsolutePath()); + txtFile.getAbsolutePath());
} finally { } finally {
@@ -136,7 +141,6 @@ public class StandAloneGame {
System.out.println("Unable to save game file due to IOException: " System.out.println("Unable to save game file due to IOException: "
+ ioe.getMessage()); + ioe.getMessage());
} }
} }
private void logResults(FileWriter writer, List<GameResult> results, private void logResults(FileWriter writer, List<GameResult> results,
@@ -158,20 +162,17 @@ public class StandAloneGame {
} }
private Policy getPolicy(PLAYER_TYPE playerType, GameConfig gameConfig, private Policy getPolicy(PLAYER_TYPE playerType, GameConfig gameConfig,
Player player) { Player player, int turnLength) {
switch (playerType) { switch (playerType) {
case HUMAN: case HUMAN:
return new HumanKeyboardInput(); return new HumanKeyboardInput();
case HUMAN_GUI: case HUMAN_GUI:
return new HumanGuiInput(new Goban(gameConfig, player)); return new HumanGuiInput(new Goban(gameConfig, player));
case ROOT_PAR: case ROOT_PAR:
return new RootParallelization(4, DEFAULT_TURN_LENGTH * 1000L * 3); return new RootParallelization(4, turnLength * 1000L);
case UCT_SLOW: case UCT:
return new MonteCarloUCT(new RandomMovePolicy(), return new MonteCarloUCT(new RandomMovePolicy(),
DEFAULT_TURN_LENGTH * 1000L * 3); turnLength * 1000L);
case UCT_FAST:
return new MonteCarloUCT(new RandomMovePolicy(),
DEFAULT_TURN_LENGTH * 1000L);
case RANDOM: case RANDOM:
return new RandomMovePolicy(); return new RandomMovePolicy();
default: default:

View File

@@ -0,0 +1,98 @@
package net.woodyfolsom.msproj.ann;
import java.util.Arrays;
import net.woodyfolsom.msproj.GameRecord;
import net.woodyfolsom.msproj.GameResult;
import net.woodyfolsom.msproj.GameState;
import net.woodyfolsom.msproj.Player;
import org.neuroph.core.learning.SupervisedTrainingElement;
import org.neuroph.core.learning.TrainingSet;
public class PassData {
public enum DATA_TYPE { TRAINING, TEST, VALIDATION };
public String[] inputs = { "BlackScore", "WhiteScore" };
public String[] outputs = { "BlackWins", "WhiteWins" };
private TrainingSet<SupervisedTrainingElement> testSet;
private TrainingSet<SupervisedTrainingElement> trainingSet;
private TrainingSet<SupervisedTrainingElement> valSet;
public PassData() {
testSet = new TrainingSet<SupervisedTrainingElement>(inputs.length, outputs.length);
trainingSet = new TrainingSet<SupervisedTrainingElement>(inputs.length, outputs.length);
valSet = new TrainingSet<SupervisedTrainingElement>(inputs.length, outputs.length);
}
public void addData(DATA_TYPE dataType, GameRecord gameRecord) {
GameState finalState = gameRecord.getGameState(gameRecord.getNumTurns());
GameResult result = finalState.getResult();
double maxScore = finalState.getGameConfig().getSize() * finalState.getGameConfig().getSize();
double whiteScore = Math.min(1.0, result.getWhiteScore() / maxScore);
double blackScore = Math.min(1.0, result.getBlackScore() / maxScore);
double blackWinner = result.isWinner(Player.BLACK) ? 1.0 : 0.0;
double whiteWinner = result.isWinner(Player.WHITE) ? 1.0 : 0.0;
addData(dataType, blackScore, whiteScore, blackWinner, whiteWinner);
}
public void addData(DATA_TYPE dataType, double...data ) {
double[] desiredInput = Arrays.copyOfRange(data,0,inputs.length);
double[] desiredOutput = Arrays.copyOfRange(data, inputs.length, data.length);
switch (dataType) {
case TEST :
testSet.addElement(new SupervisedTrainingElement(desiredInput, desiredOutput));
break;
case TRAINING :
trainingSet.addElement(new SupervisedTrainingElement(desiredInput, desiredOutput));
System.out.println("Added training input data: " + getInput(desiredInput) + ", output data: " + getOutput(desiredOutput));
break;
case VALIDATION :
valSet.addElement(new SupervisedTrainingElement(desiredInput, desiredOutput));
break;
default :
throw new UnsupportedOperationException("invalid dataType " + dataType);
}
}
public String getInput(double... inputValues) {
StringBuilder sbuilder = new StringBuilder();
boolean first = true;
for (int i = 0; i < outputs.length; i++) {
if (first) {
first = false;
} else {
sbuilder.append(",");
}
sbuilder.append(inputs[i]);
sbuilder.append(": ");
sbuilder.append(inputValues[i]);
}
return sbuilder.toString();
}
public String getOutput(double... outputValues) {
StringBuilder sbuilder = new StringBuilder();
boolean first = true;
for (int i = 0; i < outputs.length; i++) {
if (first) {
first = false;
} else {
sbuilder.append(",");
}
sbuilder.append(outputs[i]);
sbuilder.append(": ");
sbuilder.append(outputValues[i]);
}
return sbuilder.toString();
}
public TrainingSet<SupervisedTrainingElement> getTrainingSet() {
return trainingSet;
}
}

View File

@@ -2,22 +2,36 @@ package net.woodyfolsom.msproj.ann;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter; import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.woodyfolsom.msproj.Action;
import net.woodyfolsom.msproj.GameRecord; import net.woodyfolsom.msproj.GameRecord;
import net.woodyfolsom.msproj.Referee; import net.woodyfolsom.msproj.Referee;
import net.woodyfolsom.msproj.ann.PassData.DATA_TYPE;
import org.antlr.runtime.RecognitionException; import org.antlr.runtime.RecognitionException;
import org.neuroph.core.NeuralNetwork;
import org.neuroph.core.learning.SupervisedTrainingElement;
import org.neuroph.core.learning.TrainingSet;
import org.neuroph.nnet.MultiLayerPerceptron;
import org.neuroph.util.TransferFunctionType;
public class PassLearner implements NeuralNetLearner {
private NeuralNetwork neuralNetwork;
public PassLearner() {
reset();
}
public class PassLearner {
private File[] getDataFiles(String dirName) { private File[] getDataFiles(String dirName) {
File file = new File(dirName); File file = new File(dirName);
return file.listFiles(new FilenameFilter() { return file.listFiles(new FilenameFilter() {
@Override @Override
public boolean accept(File dir, String name) { public boolean accept(File dir, String name) {
// TODO Auto-generated method stub
return name.toLowerCase().endsWith(".sgf"); return name.toLowerCase().endsWith(".sgf");
} }
}); });
@@ -28,25 +42,86 @@ public class PassLearner {
} }
private void learnANN() { private void learnANN() {
for (File sgfFile : getDataFiles("data/games/pro9x9")) { List<GameRecord> parsedRecords = new ArrayList<GameRecord>();
for (File sgfFile : getDataFiles("data/tourney1")) {
System.out.println("Parsing " + sgfFile.getPath() + "..."); System.out.println("Parsing " + sgfFile.getPath() + "...");
parseSGF(sgfFile); try {
GameRecord gameRecord = parseSGF(sgfFile);
while (!gameRecord.isFinished()) {
System.out.println("Game is not finished, passing as player to move");
gameRecord.play(gameRecord.getPlayerToMove(), Action.PASS);
}
parsedRecords.add(gameRecord);
} catch (RecognitionException re) {
re.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
} }
PassData passData = new PassData();
for (GameRecord gameRecord : parsedRecords) {
System.out.println(gameRecord.getResult().getFullText());
passData.addData(DATA_TYPE.TRAINING, gameRecord);
}
System.out.println("PassData: ");
System.out.println(passData);
learn(passData.getTrainingSet());
getNeuralNetwork().setInput(0.75,0.25);
System.out.println("Output of ann(0.75,0.25): " + passData.getOutput(getNeuralNetwork().getOutput()));
getNeuralNetwork().setInput(0.25,0.50);
System.out.println("Output of ann(0.50,0.99): " + passData.getOutput(getNeuralNetwork().getOutput()));
getNeuralNetwork().save("data/networks/Pass.nn");
testNetwork(getNeuralNetwork(), passData.getTrainingSet());
} }
public void parseSGF(File sgfFile) { public GameRecord parseSGF(File sgfFile) throws IOException,
RecognitionException {
FileInputStream sgfInputStream; FileInputStream sgfInputStream;
try { sgfInputStream = new FileInputStream(sgfFile);
sgfInputStream = new FileInputStream(sgfFile); return Referee.replay(sgfInputStream);
GameRecord gameRecord = Referee.replay(sgfInputStream); }
// ...
} catch (FileNotFoundException fnfe) { @Override
fnfe.printStackTrace(); public NeuralNetwork getNeuralNetwork() {
} catch (RecognitionException re) { return neuralNetwork;
re.printStackTrace(); }
} catch (IOException ioe) {
ioe.printStackTrace(); @Override
} public void learn(TrainingSet<SupervisedTrainingElement> trainingSet) {
this.neuralNetwork.learn(trainingSet);
}
@Override
public void reset() {
this.neuralNetwork = new MultiLayerPerceptron(
TransferFunctionType.TANH, 2, 3, 2);
}
@Override
public void setNeuralNetwork(NeuralNetwork neuralNetwork) {
this.neuralNetwork = neuralNetwork;
}
private void testNetwork(NeuralNetwork nnet, TrainingSet<SupervisedTrainingElement> trainingSet) {
for (SupervisedTrainingElement trainingElement : trainingSet.elements()) {
nnet.setInput(trainingElement.getInput());
nnet.calculate();
double[] networkOutput = nnet.getOutput();
System.out.print("Input: "
+ Arrays.toString(trainingElement.getInput()));
System.out.println(" Output: " + Arrays.toString(networkOutput));
} }
} }
}

View File

@@ -37,8 +37,8 @@ public abstract class MonteCarlo implements Policy {
GameTreeNode<MonteCarloProperties> node); GameTreeNode<MonteCarloProperties> node);
private GameTreeNode<MonteCarloProperties> buildTree(GameConfig gameConfig, GameState gameState, Player player) { private GameTreeNode<MonteCarloProperties> buildTree(GameConfig gameConfig, GameState gameState, Player player) {
System.out.println(player + " is thinking for up to " //System.out.println(player + " is thinking for up to "
+ (searchTimeLimit / 1000.0) + " seconds..."); // + (searchTimeLimit / 1000.0) + " seconds...");
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
if (gameState.getPlayerToMove() != player) { if (gameState.getPlayerToMove() != player) {

View File

@@ -80,7 +80,22 @@ public class MonteCarloUCT extends MonteCarlo {
double bestScore = Double.NEGATIVE_INFINITY; double bestScore = Double.NEGATIVE_INFINITY;
GameTreeNode<MonteCarloProperties> bestChild = null; GameTreeNode<MonteCarloProperties> bestChild = null;
//int nActions = node.getNumChildren();
//GameState rootGameState = node.getGameState();
//boolean playerToMoveIsWinning = rootGameState.getResult().isWinner(rootGameState.getPlayerToMove());
//playerToMove is winning or only one move (PASS) is available
//boolean allowPass = playerToMoveIsWinning || nActions == 1;
for (Action action : node.getActions()) { for (Action action : node.getActions()) {
///HEURISTIC - work on ways of removing this go-specific logic /////
//If action is PASS and the play who moved is not the winner while other moves are available, don't pass
//i.e. don't pass when losing
//if (action.isPass() && !allowPass) {
// continue; //If the best rated action is PASS and I'm not winning and there are other valid actions,
// //keep searching.
//}
////////////////////////////////////////////////////////////////////
GameTreeNode<MonteCarloProperties> childNode = node GameTreeNode<MonteCarloProperties> childNode = node
.getChild(action); .getChild(action);
@@ -97,7 +112,7 @@ public class MonteCarloUCT extends MonteCarlo {
if (bestAction == Action.NONE) { if (bestAction == Action.NONE) {
System.out System.out
.println("MonteCarloUCT failed - no actions were found for the current game staet (not even PASS)."); .println("MonteCarloUCT failed - no actions were found for the current game state (not even PASS).");
} else { } else {
System.out.println("Action " + bestAction + " selected for " System.out.println("Action " + bestAction + " selected for "
+ node.getGameState().getPlayerToMove() + node.getGameState().getPlayerToMove()

View File

@@ -47,20 +47,41 @@ public class RandomMovePolicy implements Policy, ActionGenerator {
ActionGenerator.ALL_ACTIONS); ActionGenerator.ALL_ACTIONS);
List<Action> randomActions = new ArrayList<Action>(); List<Action> randomActions = new ArrayList<Action>();
//
boolean playerIsWinning = gameState.getResult().isWinner(player);
//
while (possibleActions.size() > 0 && randomActions.size() < nMoves) { while (possibleActions.size() > 0 && randomActions.size() < nMoves) {
Action randomAction = possibleActions Action randomAction = possibleActions
.remove((int) (Math.random() * possibleActions.size())); .remove((int) (Math.random() * possibleActions.size()));
randomActions.add(randomAction); if (isValidRandomAction(randomAction, player,playerIsWinning, gameState)) {
randomActions.add(randomAction);
}
} }
//if (randomActions.size() == 0) {
// randomActions.add(Action.NONE);
//}
//PASS is always the move of last resort if no valid moves exist
if (randomActions.size() == 0) { if (randomActions.size() == 0) {
randomActions.add(Action.NONE); randomActions.add(Action.PASS);
} }
//when to resign?
return randomActions; return randomActions;
} }
private boolean isValidRandomAction(Action action, Player player, boolean playerIsWinning, GameState gameState) {
//do not pass while losing
if (action.isPass()) {
return playerIsWinning;
}
//do not fill in my own eye
return !gameState.isSelfFill(action, player);
}
/** /**
* RandomMoveGenerator does not evaluate any states, but simply returns * RandomMoveGenerator does not evaluate any states, but simply returns
* elements of a set of uniformly distributed, distinct valid moves. * elements of a set of uniformly distributed, distinct valid moves.

View File

@@ -74,14 +74,24 @@ public class RootParallelization implements Policy {
double bestValue = 0.0; double bestValue = 0.0;
int totalRollouts = 0; int totalRollouts = 0;
int bestWins = 0; int bestWins = 0;
int nValidActions = totalReward.keySet().size(); int bestSims = 0;
//int nActions = totalReward.size();
//boolean playerToMoveIsWinning = gameState.getResult().isWinner(player);
//playerToMove is winning or only one move (PASS) is available
//boolean allowPass = playerToMoveIsWinning || nActions == 1;
for (Action action : totalReward.keySet()) for (Action action : totalReward.keySet())
{ {
if (action.isPass() && !gameState.getResult().isWinner(player) && nValidActions > 1) { //HEURISTIC - work on ways of removing this go-specific logic
continue; //If the best rated action is PASS and I'm not winning and there are other valid actions, //
//keep searching. //This heuristic must be duplicated here because RootPar. does not benefit
} //from MonteCarloUCT culling PASS just before returning from getAction().
//if (action.isPass() && !allowPass) {
// continue; //If the best rated action is PASS and I'm not winning and there are other valid actions,
// //keep searching.
//}
int totalWins = totalReward.get(action); int totalWins = totalReward.get(action);
int totalSims = numSims.get(action); int totalSims = numSims.get(action);
@@ -93,6 +103,7 @@ public class RootParallelization implements Policy {
bestAction = action; bestAction = action;
bestValue = value; bestValue = value;
bestWins = totalWins; bestWins = totalWins;
bestSims = totalSims;
} }
} }
@@ -102,9 +113,10 @@ public class RootParallelization implements Policy {
+ " with simulated win ratio of " + " with simulated win ratio of "
+ (bestValue * 100.0 + "% among " + numTrees + " parallel simulations.")); + (bestValue * 100.0 + "% among " + numTrees + " parallel simulations."));
System.out.println("It won " System.out.println("It won "
+ bestWins + " out of " + bestWins + " out of " + bestSims
+ totalRollouts + " rollouts among " + " rollouts among " + totalRollouts
+ " valid actions from the current state."); + " total rollouts (" + totalReward.keySet()
+ " possible actions) from the current state.");
return bestAction; return bestAction;
} }

View File

@@ -36,6 +36,8 @@ T__54=54
T__55=55 T__55=55
T__56=56 T__56=56
T__57=57 T__57=57
T__58=58
T__59=59
COLON=4 COLON=4
COMMA=5 COMMA=5
DIGIT=6 DIGIT=6
@@ -62,31 +64,33 @@ UCLETTER=19
'C'=27 'C'=27
'CA'=28 'CA'=28
'CP'=29 'CP'=29
'DT'=30 'Comment'=30
'DaTe'=31 'DT'=31
'EV'=32 'DaTe'=32
'EVent'=33 'EV'=33
'FF'=34 'EVent'=34
'GM'=35 'FF'=35
'GaMe'=36 'GM'=36
'KM'=37 'GaMe'=37
'PB'=38 'KM'=38
'PC'=39 'KoMi'=39
'PW'=40 'PB'=40
'PlaCe'=41 'PC'=41
'PlayerBlack'=42 'PW'=42
'PlayerWhite'=43 'PlaCe'=43
'RE'=44 'PlayerBlack'=44
'REsult'=45 'PlayerWhite'=45
'RU'=46 'RE'=46
'SO'=47 'REsult'=47
'SZ'=48 'RU'=48
'SiZe'=49 'SO'=49
'TM'=50 'SZ'=50
'US'=51 'SiZe'=51
'VW'=52 'TM'=52
'VieW'=53 'US'=53
'W'=54 'VW'=54
'WC'=55 'VieW'=55
'WR'=56 'W'=56
'White'=57 'WC'=57
'WR'=58
'White'=59

File diff suppressed because it is too large Load Diff

View File

@@ -41,6 +41,10 @@ public class SGFNode {
return properties.get(i).getValues().get(0); return properties.get(i).getValues().get(0);
} }
} }
if (identifier == SGFIdentifier.KOMI) {
System.out.println("This node does not contain " + identifier + ", using default value 0.0.");
return new SGFValue<Double>(0.0);
}
throw new RuntimeException( throw new RuntimeException(
"SGFNode does not contain a property with identifier '" "SGFNode does not contain a property with identifier '"
+ identifier + "'"); + identifier + "'");

View File

@@ -1,4 +1,4 @@
// $ANTLR 3.4 C:\\Users\\Woody\\Documents\\antlr\\SGF.g 2012-11-14 04:25:56 // $ANTLR 3.4 C:\\Users\\Woody\\Documents\\antlr\\SGF.g 2012-11-17 16:41:53
package net.woodyfolsom.msproj.sgf; package net.woodyfolsom.msproj.sgf;
import org.antlr.runtime.*; import org.antlr.runtime.*;
@@ -9,7 +9,7 @@ import java.util.ArrayList;
@SuppressWarnings({"all", "warnings", "unchecked"}) @SuppressWarnings({"all", "warnings", "unchecked"})
public class SGFParser extends Parser { public class SGFParser extends Parser {
public static final String[] tokenNames = new String[] { public static final String[] tokenNames = new String[] {
"<invalid>", "<EOR>", "<DOWN>", "<UP>", "COLON", "COMMA", "DIGIT", "LBRACKET", "LCLETTER", "LPAREN", "MINUS", "PERIOD", "PLUS", "RBRACKET", "RPAREN", "SEMICOLON", "SLASH", "SPACE", "STRVALUE", "UCLETTER", "'AB'", "'AP'", "'AW'", "'B'", "'BC'", "'BR'", "'Black'", "'C'", "'CA'", "'CP'", "'DT'", "'DaTe'", "'EV'", "'EVent'", "'FF'", "'GM'", "'GaMe'", "'KM'", "'PB'", "'PC'", "'PW'", "'PlaCe'", "'PlayerBlack'", "'PlayerWhite'", "'RE'", "'REsult'", "'RU'", "'SO'", "'SZ'", "'SiZe'", "'TM'", "'US'", "'VW'", "'VieW'", "'W'", "'WC'", "'WR'", "'White'" "<invalid>", "<EOR>", "<DOWN>", "<UP>", "COLON", "COMMA", "DIGIT", "LBRACKET", "LCLETTER", "LPAREN", "MINUS", "PERIOD", "PLUS", "RBRACKET", "RPAREN", "SEMICOLON", "SLASH", "SPACE", "STRVALUE", "UCLETTER", "'AB'", "'AP'", "'AW'", "'B'", "'BC'", "'BR'", "'Black'", "'C'", "'CA'", "'CP'", "'Comment'", "'DT'", "'DaTe'", "'EV'", "'EVent'", "'FF'", "'GM'", "'GaMe'", "'KM'", "'KoMi'", "'PB'", "'PC'", "'PW'", "'PlaCe'", "'PlayerBlack'", "'PlayerWhite'", "'RE'", "'REsult'", "'RU'", "'SO'", "'SZ'", "'SiZe'", "'TM'", "'US'", "'VW'", "'VieW'", "'W'", "'WC'", "'WR'", "'White'"
}; };
public static final int EOF=-1; public static final int EOF=-1;
@@ -51,6 +51,8 @@ public class SGFParser extends Parser {
public static final int T__55=55; public static final int T__55=55;
public static final int T__56=56; public static final int T__56=56;
public static final int T__57=57; public static final int T__57=57;
public static final int T__58=58;
public static final int T__59=59;
public static final int COLON=4; public static final int COLON=4;
public static final int COMMA=5; public static final int COMMA=5;
public static final int DIGIT=6; public static final int DIGIT=6;
@@ -329,7 +331,7 @@ public class SGFParser extends Parser {
int alt4=2; int alt4=2;
int LA4_0 = input.LA(1); int LA4_0 = input.LA(1);
if ( ((LA4_0 >= 20 && LA4_0 <= 57)) ) { if ( ((LA4_0 >= 20 && LA4_0 <= 59)) ) {
alt4=1; alt4=1;
} }
@@ -410,12 +412,12 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:37:2: ( ( numIdent ) ( ( LBRACKET numValue RBRACKET ) )+ | ( playerIdent ) ( ( LBRACKET RBRACKET ) )+ | ( playerIdent ) ( ( LBRACKET coordValue RBRACKET ) )+ | ( strIdent ) ( ( LBRACKET RBRACKET ) ) | ( strIdent ) ( ( LBRACKET strValue RBRACKET ) )+ | ( result ) ( ( LBRACKET strValue RBRACKET ) )+ | ( komi ) ( ( LBRACKET realValue RBRACKET ) )+ | ( coordIdent ) ( ( LBRACKET coordValue RBRACKET ) )+ ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:37:2: ( ( numIdent ) ( ( LBRACKET numValue RBRACKET ) )+ | ( playerIdent ) ( ( LBRACKET RBRACKET ) )+ | ( playerIdent ) ( ( LBRACKET coordValue RBRACKET ) )+ | ( strIdent ) ( ( LBRACKET RBRACKET ) ) | ( strIdent ) ( ( LBRACKET strValue RBRACKET ) )+ | ( result ) ( ( LBRACKET strValue RBRACKET ) )+ | ( komi ) ( ( LBRACKET realValue RBRACKET ) )+ | ( coordIdent ) ( ( LBRACKET coordValue RBRACKET ) )+ )
int alt12=8; int alt12=8;
switch ( input.LA(1) ) { switch ( input.LA(1) ) {
case 34:
case 35: case 35:
case 36: case 36:
case 48: case 37:
case 49:
case 50: case 50:
case 51:
case 52:
{ {
alt12=1; alt12=1;
} }
@@ -492,7 +494,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 47: case 49:
{ {
int LA12_3 = input.LA(2); int LA12_3 = input.LA(2);
@@ -636,7 +638,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 55: case 57:
{ {
int LA12_5 = input.LA(2); int LA12_5 = input.LA(2);
@@ -708,8 +710,8 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 32:
case 33: case 33:
case 34:
{ {
int LA12_6 = input.LA(2); int LA12_6 = input.LA(2);
@@ -781,8 +783,8 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 38: case 40:
case 42: case 44:
{ {
int LA12_7 = input.LA(2); int LA12_7 = input.LA(2);
@@ -854,8 +856,8 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 40: case 42:
case 43: case 45:
{ {
int LA12_8 = input.LA(2); int LA12_8 = input.LA(2);
@@ -999,7 +1001,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 56: case 58:
{ {
int LA12_10 = input.LA(2); int LA12_10 = input.LA(2);
@@ -1071,7 +1073,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 46: case 48:
{ {
int LA12_11 = input.LA(2); int LA12_11 = input.LA(2);
@@ -1143,8 +1145,8 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 39:
case 41: case 41:
case 43:
{ {
int LA12_12 = input.LA(2); int LA12_12 = input.LA(2);
@@ -1360,7 +1362,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 51: case 53:
{ {
int LA12_15 = input.LA(2); int LA12_15 = input.LA(2);
@@ -1432,8 +1434,8 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 30:
case 31: case 31:
case 32:
{ {
int LA12_16 = input.LA(2); int LA12_16 = input.LA(2);
@@ -1577,7 +1579,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 57: case 59:
{ {
int LA12_18 = input.LA(2); int LA12_18 = input.LA(2);
@@ -1721,7 +1723,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 54: case 56:
{ {
int LA12_20 = input.LA(2); int LA12_20 = input.LA(2);
@@ -1793,8 +1795,8 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 52: case 54:
case 53: case 55:
{ {
int LA12_21 = input.LA(2); int LA12_21 = input.LA(2);
@@ -1867,6 +1869,7 @@ public class SGFParser extends Parser {
} }
break; break;
case 27: case 27:
case 30:
{ {
int LA12_22 = input.LA(2); int LA12_22 = input.LA(2);
@@ -1938,13 +1941,14 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 44: case 46:
case 45: case 47:
{ {
alt12=6; alt12=6;
} }
break; break;
case 37: case 38:
case 39:
{ {
alt12=7; alt12=7;
} }
@@ -2518,7 +2522,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 47: case 49:
{ {
int LA13_2 = input.LA(2); int LA13_2 = input.LA(2);
@@ -2568,7 +2572,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 55: case 57:
{ {
int LA13_4 = input.LA(2); int LA13_4 = input.LA(2);
@@ -2593,8 +2597,8 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 32:
case 33: case 33:
case 34:
{ {
int LA13_5 = input.LA(2); int LA13_5 = input.LA(2);
@@ -2619,8 +2623,8 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 38: case 40:
case 42: case 44:
{ {
int LA13_6 = input.LA(2); int LA13_6 = input.LA(2);
@@ -2645,8 +2649,8 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 40: case 42:
case 43: case 45:
{ {
int LA13_7 = input.LA(2); int LA13_7 = input.LA(2);
@@ -2696,7 +2700,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 56: case 58:
{ {
int LA13_9 = input.LA(2); int LA13_9 = input.LA(2);
@@ -2721,7 +2725,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 46: case 48:
{ {
int LA13_10 = input.LA(2); int LA13_10 = input.LA(2);
@@ -2746,8 +2750,8 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 39:
case 41: case 41:
case 43:
{ {
int LA13_11 = input.LA(2); int LA13_11 = input.LA(2);
@@ -2822,7 +2826,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 51: case 53:
{ {
int LA13_14 = input.LA(2); int LA13_14 = input.LA(2);
@@ -2847,8 +2851,8 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 30:
case 31: case 31:
case 32:
{ {
int LA13_15 = input.LA(2); int LA13_15 = input.LA(2);
@@ -2898,7 +2902,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 57: case 59:
{ {
int LA13_17 = input.LA(2); int LA13_17 = input.LA(2);
@@ -2948,7 +2952,7 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 54: case 56:
{ {
int LA13_19 = input.LA(2); int LA13_19 = input.LA(2);
@@ -2973,8 +2977,8 @@ public class SGFParser extends Parser {
} }
} }
break; break;
case 52: case 54:
case 53: case 55:
{ {
int LA13_20 = input.LA(2); int LA13_20 = input.LA(2);
@@ -3000,6 +3004,7 @@ public class SGFParser extends Parser {
} }
break; break;
case 27: case 27:
case 30:
{ {
int LA13_21 = input.LA(2); int LA13_21 = input.LA(2);
@@ -3133,7 +3138,7 @@ public class SGFParser extends Parser {
alt14=1; alt14=1;
} }
break; break;
case 47: case 49:
{ {
alt14=2; alt14=2;
} }
@@ -3143,25 +3148,25 @@ public class SGFParser extends Parser {
alt14=3; alt14=3;
} }
break; break;
case 55: case 57:
{ {
alt14=4; alt14=4;
} }
break; break;
case 32:
case 33: case 33:
case 34:
{ {
alt14=5; alt14=5;
} }
break; break;
case 38: case 40:
case 42: case 44:
{ {
alt14=6; alt14=6;
} }
break; break;
case 40: case 42:
case 43: case 45:
{ {
alt14=7; alt14=7;
} }
@@ -3171,18 +3176,18 @@ public class SGFParser extends Parser {
alt14=8; alt14=8;
} }
break; break;
case 56: case 58:
{ {
alt14=9; alt14=9;
} }
break; break;
case 46: case 48:
{ {
alt14=10; alt14=10;
} }
break; break;
case 39:
case 41: case 41:
case 43:
{ {
alt14=11; alt14=11;
} }
@@ -3197,13 +3202,13 @@ public class SGFParser extends Parser {
alt14=13; alt14=13;
} }
break; break;
case 51: case 53:
{ {
alt14=14; alt14=14;
} }
break; break;
case 30:
case 31: case 31:
case 32:
{ {
alt14=15; alt14=15;
} }
@@ -3213,7 +3218,7 @@ public class SGFParser extends Parser {
alt14=16; alt14=16;
} }
break; break;
case 57: case 59:
{ {
alt14=17; alt14=17;
} }
@@ -3223,18 +3228,19 @@ public class SGFParser extends Parser {
alt14=18; alt14=18;
} }
break; break;
case 54: case 56:
{ {
alt14=19; alt14=19;
} }
break; break;
case 52: case 54:
case 53: case 55:
{ {
alt14=20; alt14=20;
} }
break; break;
case 27: case 27:
case 30:
{ {
alt14=21; alt14=21;
} }
@@ -3451,7 +3457,7 @@ public class SGFParser extends Parser {
case 17 : case 17 :
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:78:11: 'White' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:78:11: 'White'
{ {
match(input,57,FOLLOW_57_in_strIdent517); match(input,59,FOLLOW_59_in_strIdent517);
sgfIdent = SGFIdentifier.MOVE_WHITE; sgfIdent = SGFIdentifier.MOVE_WHITE;
@@ -3469,7 +3475,7 @@ public class SGFParser extends Parser {
case 19 : case 19 :
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:80:11: 'W' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:80:11: 'W'
{ {
match(input,54,FOLLOW_54_in_strIdent543); match(input,56,FOLLOW_56_in_strIdent543);
sgfIdent = SGFIdentifier.MOVE_WHITE; sgfIdent = SGFIdentifier.MOVE_WHITE;
@@ -3601,24 +3607,24 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:93:2: ( fileFormat | game | size | time ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:93:2: ( fileFormat | game | size | time )
int alt16=4; int alt16=4;
switch ( input.LA(1) ) { switch ( input.LA(1) ) {
case 34: case 35:
{ {
alt16=1; alt16=1;
} }
break; break;
case 35:
case 36: case 36:
case 37:
{ {
alt16=2; alt16=2;
} }
break; break;
case 48: case 50:
case 49: case 51:
{ {
alt16=3; alt16=3;
} }
break; break;
case 50: case 52:
{ {
alt16=4; alt16=4;
} }
@@ -3858,7 +3864,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:112:2: ( 'FF' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:112:2: ( 'FF' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:112:4: 'FF' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:112:4: 'FF'
{ {
match(input,34,FOLLOW_34_in_fileFormat727); match(input,35,FOLLOW_35_in_fileFormat727);
} }
@@ -3884,7 +3890,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:114:7: ( 'GM' | 'GaMe' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:114:7: ( 'GM' | 'GaMe' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g: // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:
{ {
if ( (input.LA(1) >= 35 && input.LA(1) <= 36) ) { if ( (input.LA(1) >= 36 && input.LA(1) <= 37) ) {
input.consume(); input.consume();
state.errorRecovery=false; state.errorRecovery=false;
} }
@@ -3918,7 +3924,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:116:7: ( 'SZ' | 'SiZe' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:116:7: ( 'SZ' | 'SiZe' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g: // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:
{ {
if ( (input.LA(1) >= 48 && input.LA(1) <= 49) ) { if ( (input.LA(1) >= 50 && input.LA(1) <= 51) ) {
input.consume(); input.consume();
state.errorRecovery=false; state.errorRecovery=false;
} }
@@ -3952,7 +3958,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:118:7: ( 'VW' | 'VieW' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:118:7: ( 'VW' | 'VieW' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g: // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:
{ {
if ( (input.LA(1) >= 52 && input.LA(1) <= 53) ) { if ( (input.LA(1) >= 54 && input.LA(1) <= 55) ) {
input.consume(); input.consume();
state.errorRecovery=false; state.errorRecovery=false;
} }
@@ -4012,7 +4018,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:122:8: ( 'SO' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:122:8: ( 'SO' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:122:10: 'SO' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:122:10: 'SO'
{ {
match(input,47,FOLLOW_47_in_source783); match(input,49,FOLLOW_49_in_source783);
} }
@@ -4064,7 +4070,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:128:2: ( 'WC' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:128:2: ( 'WC' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:128:4: 'WC' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:128:4: 'WC'
{ {
match(input,55,FOLLOW_55_in_whiteCountry804); match(input,57,FOLLOW_57_in_whiteCountry804);
} }
@@ -4090,7 +4096,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:130:7: ( 'EV' | 'EVent' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:130:7: ( 'EV' | 'EVent' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g: // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:
{ {
if ( (input.LA(1) >= 32 && input.LA(1) <= 33) ) { if ( (input.LA(1) >= 33 && input.LA(1) <= 34) ) {
input.consume(); input.consume();
state.errorRecovery=false; state.errorRecovery=false;
} }
@@ -4124,7 +4130,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:133:2: ( 'PB' | 'PlayerBlack' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:133:2: ( 'PB' | 'PlayerBlack' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g: // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:
{ {
if ( input.LA(1)==38||input.LA(1)==42 ) { if ( input.LA(1)==40||input.LA(1)==44 ) {
input.consume(); input.consume();
state.errorRecovery=false; state.errorRecovery=false;
} }
@@ -4158,7 +4164,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:135:2: ( 'PW' | 'PlayerWhite' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:135:2: ( 'PW' | 'PlayerWhite' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g: // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:
{ {
if ( input.LA(1)==40||input.LA(1)==43 ) { if ( input.LA(1)==42||input.LA(1)==45 ) {
input.consume(); input.consume();
state.errorRecovery=false; state.errorRecovery=false;
} }
@@ -4218,7 +4224,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:140:2: ( 'WR' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:140:2: ( 'WR' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:140:5: 'WR' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:140:5: 'WR'
{ {
match(input,56,FOLLOW_56_in_whiteRank861); match(input,58,FOLLOW_58_in_whiteRank861);
} }
@@ -4238,13 +4244,21 @@ public class SGFParser extends Parser {
// $ANTLR start "komi" // $ANTLR start "komi"
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:142:1: komi : 'KM' ; // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:142:1: komi : ( 'KM' | 'KoMi' );
public final void komi() throws RecognitionException { public final void komi() throws RecognitionException {
try { try {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:142:7: ( 'KM' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:142:7: ( 'KM' | 'KoMi' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:142:9: 'KM' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:
{ {
match(input,37,FOLLOW_37_in_komi871); if ( (input.LA(1) >= 38 && input.LA(1) <= 39) ) {
input.consume();
state.errorRecovery=false;
}
else {
MismatchedSetException mse = new MismatchedSetException(null,input);
throw mse;
}
} }
@@ -4270,7 +4284,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:144:9: ( 'RE' | 'REsult' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:144:9: ( 'RE' | 'REsult' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g: // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:
{ {
if ( (input.LA(1) >= 44 && input.LA(1) <= 45) ) { if ( (input.LA(1) >= 46 && input.LA(1) <= 47) ) {
input.consume(); input.consume();
state.errorRecovery=false; state.errorRecovery=false;
} }
@@ -4304,7 +4318,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:148:7: ( 'RU' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:148:7: ( 'RU' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:148:9: 'RU' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:148:9: 'RU'
{ {
match(input,46,FOLLOW_46_in_rules897); match(input,48,FOLLOW_48_in_rules901);
} }
@@ -4330,7 +4344,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:150:8: ( 'PC' | 'PlaCe' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:150:8: ( 'PC' | 'PlaCe' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g: // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:
{ {
if ( input.LA(1)==39||input.LA(1)==41 ) { if ( input.LA(1)==41||input.LA(1)==43 ) {
input.consume(); input.consume();
state.errorRecovery=false; state.errorRecovery=false;
} }
@@ -4364,7 +4378,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:153:2: ( 'AP' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:153:2: ( 'AP' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:153:4: 'AP' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:153:4: 'AP'
{ {
match(input,21,FOLLOW_21_in_application919); match(input,21,FOLLOW_21_in_application923);
} }
@@ -4390,7 +4404,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:155:6: ( 'TM' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:155:6: ( 'TM' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:155:8: 'TM' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:155:8: 'TM'
{ {
match(input,50,FOLLOW_50_in_time928); match(input,52,FOLLOW_52_in_time932);
} }
@@ -4416,7 +4430,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:157:7: ( 'DT' | 'DaTe' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:157:7: ( 'DT' | 'DaTe' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g: // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:
{ {
if ( (input.LA(1) >= 30 && input.LA(1) <= 31) ) { if ( (input.LA(1) >= 31 && input.LA(1) <= 32) ) {
input.consume(); input.consume();
state.errorRecovery=false; state.errorRecovery=false;
} }
@@ -4453,7 +4467,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:160:2: ( 'AB' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:160:2: ( 'AB' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:160:4: 'AB' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:160:4: 'AB'
{ {
match(input,20,FOLLOW_20_in_addBlack954); match(input,20,FOLLOW_20_in_addBlack958);
sgfIdent = SGFIdentifier.ADD_BLACK; sgfIdent = SGFIdentifier.ADD_BLACK;
@@ -4484,7 +4498,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:164:2: ( 'AW' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:164:2: ( 'AW' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:164:4: 'AW' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:164:4: 'AW'
{ {
match(input,22,FOLLOW_22_in_addWhite971); match(input,22,FOLLOW_22_in_addWhite975);
sgfIdent = SGFIdentifier.ADD_WHITE; sgfIdent = SGFIdentifier.ADD_WHITE;
@@ -4512,7 +4526,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:168:2: ( 'CP' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:168:2: ( 'CP' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:168:4: 'CP' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:168:4: 'CP'
{ {
match(input,29,FOLLOW_29_in_copyright983); match(input,29,FOLLOW_29_in_copyright987);
} }
@@ -4538,7 +4552,7 @@ public class SGFParser extends Parser {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:170:9: ( 'US' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:170:9: ( 'US' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:170:11: 'US' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:170:11: 'US'
{ {
match(input,51,FOLLOW_51_in_username990); match(input,53,FOLLOW_53_in_username994);
} }
@@ -4558,13 +4572,21 @@ public class SGFParser extends Parser {
// $ANTLR start "comment" // $ANTLR start "comment"
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:172:1: comment : 'C' ; // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:172:1: comment : ( 'C' | 'Comment' );
public final void comment() throws RecognitionException { public final void comment() throws RecognitionException {
try { try {
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:172:9: ( 'C' ) // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:172:9: ( 'C' | 'Comment' )
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:172:11: 'C' // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:
{ {
match(input,27,FOLLOW_27_in_comment998); if ( input.LA(1)==27||input.LA(1)==30 ) {
input.consume();
state.errorRecovery=false;
}
else {
MismatchedSetException mse = new MismatchedSetException(null,input);
throw mse;
}
} }
@@ -4613,7 +4635,7 @@ public class SGFParser extends Parser {
case 1 : case 1 :
// C:\\Users\\Woody\\Documents\\antlr\\SGF.g:175:5: STRVALUE // C:\\Users\\Woody\\Documents\\antlr\\SGF.g:175:5: STRVALUE
{ {
match(input,STRVALUE,FOLLOW_STRVALUE_in_strValue1009); match(input,STRVALUE,FOLLOW_STRVALUE_in_strValue1017);
} }
break; break;
@@ -4657,8 +4679,8 @@ public class SGFParser extends Parser {
public static final BitSet FOLLOW_gameTree_in_gameTree67 = new BitSet(new long[]{0x0000000000004200L}); public static final BitSet FOLLOW_gameTree_in_gameTree67 = new BitSet(new long[]{0x0000000000004200L});
public static final BitSet FOLLOW_RPAREN_in_gameTree72 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_RPAREN_in_gameTree72 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_node_in_sequence94 = new BitSet(new long[]{0x0000000000008002L}); public static final BitSet FOLLOW_node_in_sequence94 = new BitSet(new long[]{0x0000000000008002L});
public static final BitSet FOLLOW_SEMICOLON_in_node115 = new BitSet(new long[]{0x03FFFFFFFFF00002L}); public static final BitSet FOLLOW_SEMICOLON_in_node115 = new BitSet(new long[]{0x0FFFFFFFFFF00002L});
public static final BitSet FOLLOW_property_in_node118 = new BitSet(new long[]{0x03FFFFFFFFF00002L}); public static final BitSet FOLLOW_property_in_node118 = new BitSet(new long[]{0x0FFFFFFFFFF00002L});
public static final BitSet FOLLOW_numIdent_in_property140 = new BitSet(new long[]{0x0000000000000080L}); public static final BitSet FOLLOW_numIdent_in_property140 = new BitSet(new long[]{0x0000000000000080L});
public static final BitSet FOLLOW_LBRACKET_in_property146 = new BitSet(new long[]{0x0000000000040000L}); public static final BitSet FOLLOW_LBRACKET_in_property146 = new BitSet(new long[]{0x0000000000040000L});
public static final BitSet FOLLOW_numValue_in_property148 = new BitSet(new long[]{0x0000000000002000L}); public static final BitSet FOLLOW_numValue_in_property148 = new BitSet(new long[]{0x0000000000002000L});
@@ -4709,9 +4731,9 @@ public class SGFParser extends Parser {
public static final BitSet FOLLOW_username_in_strIdent479 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_username_in_strIdent479 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_date_in_strIdent491 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_date_in_strIdent491 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_26_in_strIdent504 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_26_in_strIdent504 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_57_in_strIdent517 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_59_in_strIdent517 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_23_in_strIdent530 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_23_in_strIdent530 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_54_in_strIdent543 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_56_in_strIdent543 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_view_in_strIdent556 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_view_in_strIdent556 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_comment_in_strIdent570 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_comment_in_strIdent570 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_addBlack_in_coordIdent616 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_addBlack_in_coordIdent616 = new BitSet(new long[]{0x0000000000000002L});
@@ -4724,22 +4746,20 @@ public class SGFParser extends Parser {
public static final BitSet FOLLOW_komi_in_realIdent688 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_komi_in_realIdent688 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_STRVALUE_in_realValue698 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_STRVALUE_in_realValue698 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_STRVALUE_in_coordValue713 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_STRVALUE_in_coordValue713 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_34_in_fileFormat727 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_35_in_fileFormat727 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_28_in_charEnc775 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_28_in_charEnc775 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_47_in_source783 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_49_in_source783 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_24_in_blackCountry793 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_24_in_blackCountry793 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_55_in_whiteCountry804 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_57_in_whiteCountry804 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_25_in_blackRank850 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_25_in_blackRank850 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_56_in_whiteRank861 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_58_in_whiteRank861 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_37_in_komi871 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_48_in_rules901 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_46_in_rules897 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_21_in_application923 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_21_in_application919 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_52_in_time932 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_50_in_time928 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_20_in_addBlack958 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_20_in_addBlack954 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_22_in_addWhite975 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_22_in_addWhite971 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_29_in_copyright987 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_29_in_copyright983 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_53_in_username994 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_51_in_username990 = new BitSet(new long[]{0x0000000000000002L}); public static final BitSet FOLLOW_STRVALUE_in_strValue1017 = new BitSet(new long[]{0x0000000000040002L});
public static final BitSet FOLLOW_27_in_comment998 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_STRVALUE_in_strValue1009 = new BitSet(new long[]{0x0000000000040002L});
} }

View File

@@ -0,0 +1,29 @@
package net.woodyfolsom.msproj;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class GameBoardTest {
@Test
public void testCapture() {
GameConfig gameConfig = new GameConfig(5);
GameState gameState = new GameState(gameConfig);
assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("A2")));
assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("B3")));
assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("B1")));
assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("C2")));
assertTrue(gameState.isSelfFill(Action.getInstance("B2"), Player.BLACK));
assertFalse(gameState
.isSelfFill(Action.getInstance("B2"), Player.WHITE));
assertFalse(gameState
.isSelfFill(Action.getInstance("B4"), Player.BLACK));
assertFalse(gameState
.isSelfFill(Action.getInstance("B4"), Player.BLACK));
System.out.println(gameState);
}
}

View File

@@ -1,28 +1,76 @@
package net.woodyfolsom.msproj; package net.woodyfolsom.msproj;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import net.woodyfolsom.msproj.GameResult; import net.woodyfolsom.msproj.GameResult;
import net.woodyfolsom.msproj.policy.MonteCarloUCT;
import net.woodyfolsom.msproj.policy.RandomMovePolicy;
import net.woodyfolsom.msproj.policy.RootParallelization;
import net.woodyfolsom.msproj.sgf.SGFLexer;
import net.woodyfolsom.msproj.sgf.SGFNodeCollection;
import net.woodyfolsom.msproj.sgf.SGFParser;
import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.junit.Test; import org.junit.Test;
public class GameScoreTest { public class GameScoreTest {
// public static final String endGameSGF =
// "(;FF[4]GM[1]SZ[9]KM[5.5];B[ef];W[ff];B[dg];W[aa];B[fc];W[da];B[cg];W[ei];B[gf]"
// +
// ";W[fi];B[ag];W[ii];B[bi];W[if];B[db];W[ci];B[cf];W[ih];B[bc];W[hb];B[eb];W[fh];B[ig];W[hc];B[be];W[he];B[gc];"
// +
// "W[id];B[cd];W[df];B[hf];W[ah];B[bh];W[fa];B[bg];W[fe];B[ec];W[eh];B[ee];W[bd];B[hg];W[ie];B[fg];W[ca];B[eg];"
// +
// "W[cb];B[ad];W[ba];B[ch];W[dh];B[gd];W[ic];B[ha];W[ab];B[gh];W[gb];B[ed];W[];B[])";
//public static final String endGameSGF = "(;FF[4]GM[1]SZ[9]KM[5.5]RE[W+0.5];B[ef];W[cb];B[fe];W[da];B[cd];W[hh];B[ed];W[cc];B[ci];W[bc];B[cg];W[fi];B[be];W[ea];B[hi];W[df];B[fd];W[bg];B[cf];W[aa];B[gd];W[ch];B[ad];W[dg];B[de];W[ge];B[bh];W[fa];B[ag];W[hd];B[if];W[bi];B[gf];W[bd];B[ah];W[gc];B[ff];W[ca];B[hf];W[dd];B[ce];W[ae];B[ga];W[hc];B[ac];W[gg];B[fg];W[fb];B[ie];W[dh];B[af];W[ec];B[dc];W[id];B[dd];W[eh];B[eb];W[gb];B[ae];W[ic];B[di];W[fh];B[ig];W[ab];B[ha];W[hg];B[hb];W[gi];B[ii];W[ia];B[fc];W[ba];B[eg];W[];B[db];W[];B[])";
public static final String endGameSGF = "(;FF[4]GM[1]SZ[6]KM[1.5]RE[B+0.5];B[bb];W[];B[ec];W[ef];B[ac];W[ed];B[ba];W[dc];B[cf];W[];B[])";
@Test @Test
public void testGetAggregateScoreZero() { public void testGetAggregateScoreZero() {
GameResult gameScore = new GameResult(0,0,19,0, true); GameResult gameScore = new GameResult(0, 0, 19, 0, true);
assertEquals(gameScore.getNormalizedZeroScore(), gameScore.getNormalizedScore()); assertEquals(gameScore.getNormalizedZeroScore(),
gameScore.getNormalizedScore());
} }
@Test @Test
public void testGetAggregateScoreBlackWinsNoKomi() { public void testGetAggregateScoreBlackWinsNoKomi() {
GameResult gameScore = new GameResult(25,2,19,0, true); GameResult gameScore = new GameResult(25, 2, 19, 0, true);
assertEquals(407, gameScore.getNormalizedScore()); assertEquals(407, gameScore.getNormalizedScore());
} }
@Test @Test
public void testGetAggregateScoreWhiteWinsWithKomi() { public void testGetAggregateScoreWhiteWinsWithKomi() {
GameResult gameScore = new GameResult(10,12,19,6.5, true); GameResult gameScore = new GameResult(10, 12, 19, 6.5, true);
assertEquals(357, gameScore.getNormalizedScore()); assertEquals(357, gameScore.getNormalizedScore());
} }
@Test
public void testScoreEndGame() throws IOException, RecognitionException {
InputStream is = new ByteArrayInputStream(endGameSGF.getBytes());
GameRecord gameRecord = Referee.replay(is);
assertEquals(11, gameRecord.getNumTurns());
GameState gameState9 = gameRecord.getGameState(9);
for (int i = 0; i < 5; i++) {
//Action action = new RootParallelization(4, 1000L).getAction(gameRecord.getGameConfig(), gameState9, Player.WHITE);
Action action = new MonteCarloUCT(new RandomMovePolicy(),1000L).getAction(gameRecord.getGameConfig(), gameState9, Player.WHITE);
System.out.println("Suggested action for "+Player.WHITE+": " + action);
}
gameState9.playStone(Player.WHITE, Action.PASS);
gameState9.playStone(Player.BLACK, Action.PASS);
assertTrue(gameState9.isTerminal());
System.out.println(gameState9.getResult());
}
} }

View File

@@ -0,0 +1,30 @@
package net.woodyfolsom.msproj.ann;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.neuroph.core.NeuralNetwork;
public class PassNetworkTest {
@Test
public void testSavedNetwork() {
NeuralNetwork passFilter = NeuralNetwork.load("data/networks/Pass1.nn");
passFilter.setInput(0.75,0.25);
passFilter.calculate();
PassData passData = new PassData();
double[] output = passFilter.getOutput();
System.out.println("Output: " + passData.getOutput(output));
assertTrue(output[0] > 0.50);
assertTrue(output[1] < 0.50);
passFilter.setInput(0.25,0.50);
passFilter.calculate();
output = passFilter.getOutput();
System.out.println("Output: " + passData.getOutput(output));
assertTrue(output[0] < 0.50);
assertTrue(output[1] > 0.50);
}
}