Able to export SGF files from successful games.
This commit is contained in:
134
data/SGF.g
134
data/SGF.g
@@ -44,36 +44,42 @@ $sgfProperty = new SGFProperty();
|
|||||||
| (strIdent{$sgfProperty.setIdentifier($strIdent.sgfIdent);}) ((LBRACKET RBRACKET){$sgfProperty.addValue(SGFValue.EMPTY);})
|
| (strIdent{$sgfProperty.setIdentifier($strIdent.sgfIdent);}) ((LBRACKET RBRACKET){$sgfProperty.addValue(SGFValue.EMPTY);})
|
||||||
| (strIdent{$sgfProperty.setIdentifier($strIdent.sgfIdent);}) ((LBRACKET strValue RBRACKET){$sgfProperty.addValue(new SGFValue<String>($strValue.text));})+
|
| (strIdent{$sgfProperty.setIdentifier($strIdent.sgfIdent);}) ((LBRACKET strValue RBRACKET){$sgfProperty.addValue(new SGFValue<String>($strValue.text));})+
|
||||||
|
|
||||||
| (result{$sgfProperty.setIdentifier(SGFIdentifier.RESULT);}) ((LBRACKET resValue RBRACKET){$sgfProperty.addValue(new SGFValue<SGFResult>(new SGFResult($resValue.text)));})+
|
| (result{$sgfProperty.setIdentifier(SGFIdentifier.RESULT);}) ((LBRACKET strValue RBRACKET){$sgfProperty.addValue(new SGFValue<SGFResult>(new SGFResult($strValue.text)));})+
|
||||||
|
|
||||||
| (komi{$sgfProperty.setIdentifier(SGFIdentifier.KOMI);}) ((LBRACKET realValue RBRACKET){$sgfProperty.addValue(new SGFValue<Double>(Double.parseDouble($realValue.text)));})+
|
| (komi{$sgfProperty.setIdentifier(SGFIdentifier.KOMI);}) ((LBRACKET realValue RBRACKET){$sgfProperty.addValue(new SGFValue<Double>(Double.parseDouble($realValue.text)));})+
|
||||||
| (coordIdent{$sgfProperty.setIdentifier($coordIdent.sgfIdent);})((LBRACKET coordValue RBRACKET){$sgfProperty.addValue(new SGFValue<SGFCoord>(new SGFCoord($coordValue.text)));})+
|
| (coordIdent{$sgfProperty.setIdentifier($coordIdent.sgfIdent);})((LBRACKET coordValue RBRACKET){$sgfProperty.addValue(new SGFValue<SGFCoord>(new SGFCoord($coordValue.text)));})+
|
||||||
;
|
;
|
||||||
|
|
||||||
//playerIdent is a disambiguating rule
|
//playerIdent is a disambiguating rule
|
||||||
playerIdent returns [SGFIdentifier sgfPlayer]
|
playerIdent returns [SGFIdentifier sgfPlayer]
|
||||||
: {(input.LT(1).getText().equals("W"))}? strIdent {$sgfPlayer = $strIdent.sgfIdent;}
|
: {(input.LT(1).getText().equals("W"))}? strIdent {$sgfPlayer = $strIdent.sgfIdent;}
|
||||||
| {(input.LT(1).getText().equals("B"))}? strIdent {$sgfPlayer = $strIdent.sgfIdent;}
|
| {(input.LT(1).getText().equals("B"))}? strIdent {$sgfPlayer = $strIdent.sgfIdent;}
|
||||||
|
| {(input.LT(1).getText().equals("White"))}? strIdent {$sgfPlayer = $strIdent.sgfIdent;}
|
||||||
|
| {(input.LT(1).getText().equals("Black"))}? strIdent {$sgfPlayer = $strIdent.sgfIdent;}
|
||||||
;
|
;
|
||||||
|
|
||||||
strIdent returns [SGFIdentifier sgfIdent]
|
strIdent returns [SGFIdentifier sgfIdent]
|
||||||
: charEnc{$sgfIdent = SGFIdentifier.CHARSET;}
|
: charEnc{$sgfIdent = SGFIdentifier.CHARSET;}
|
||||||
| source
|
| source{$sgfIdent = SGFIdentifier.SOURCE;}
|
||||||
| blackCountry
|
| blackCountry{$sgfIdent = SGFIdentifier.COUNTRY_BLACK;}
|
||||||
| whiteCountry
|
| whiteCountry{$sgfIdent = SGFIdentifier.COUNTRY_WHITE;}
|
||||||
| event
|
| event{$sgfIdent = SGFIdentifier.EVENT;}
|
||||||
| playerBlack
|
| playerBlack{$sgfIdent = SGFIdentifier.PLAYER_BLACK;}
|
||||||
| playerWhite
|
| playerWhite{$sgfIdent = SGFIdentifier.PLAYER_WHITE;}
|
||||||
| blackRank
|
| blackRank{$sgfIdent = SGFIdentifier.RANK_BLACK;}
|
||||||
| whiteRank
|
| whiteRank{$sgfIdent = SGFIdentifier.RANK_WHITE;}
|
||||||
| result
|
| rules{$sgfIdent = SGFIdentifier.RULES;}
|
||||||
| rules
|
| place{$sgfIdent = SGFIdentifier.PLACE;}
|
||||||
| place
|
| application{$sgfIdent = SGFIdentifier.APPLICATION;}
|
||||||
| application
|
|
||||||
| copyright
|
| copyright
|
||||||
| username
|
| username
|
||||||
| date
|
| date{$sgfIdent = SGFIdentifier.DATE;}
|
||||||
|
| 'Black'{$sgfIdent = SGFIdentifier.MOVE_BLACK;}
|
||||||
|
| 'White'{$sgfIdent = SGFIdentifier.MOVE_WHITE;}
|
||||||
| 'B'{$sgfIdent = SGFIdentifier.MOVE_BLACK;}
|
| 'B'{$sgfIdent = SGFIdentifier.MOVE_BLACK;}
|
||||||
| 'W'{$sgfIdent = SGFIdentifier.MOVE_WHITE;}
|
| 'W'{$sgfIdent = SGFIdentifier.MOVE_WHITE;}
|
||||||
|
| view{$sgfIdent = SGFIdentifier.VIEW;} //this is not really a strIdent, but is a placeholder since I don't use this info
|
||||||
|
| comment{$sgfIdent = SGFIdentifier.COMMENT;}
|
||||||
//SGF grammar proper allows extensions, but this reader does not
|
//SGF grammar proper allows extensions, but this reader does not
|
||||||
; //if this is matched from rule playerIdent, the value is thrown away - this rule alone
|
; //if this is matched from rule playerIdent, the value is thrown away - this rule alone
|
||||||
//lack the context to disambiguate the single-character player movement IDs.
|
//lack the context to disambiguate the single-character player movement IDs.
|
||||||
@@ -90,48 +96,65 @@ numIdent returns [SGFIdentifier sgfIdent]
|
|||||||
| time{$sgfIdent = SGFIdentifier.TIME;};
|
| time{$sgfIdent = SGFIdentifier.TIME;};
|
||||||
|
|
||||||
numValue returns [SGFValue<Integer> sgfValue]
|
numValue returns [SGFValue<Integer> sgfValue]
|
||||||
: (DIGIT+){$sgfValue = new SGFValue<Integer>(Integer.parseInt($numValue.text));};
|
: (STRVALUE){$sgfValue = new SGFValue<Integer>(Integer.parseInt($numValue.text));};
|
||||||
|
|
||||||
realIdent
|
realIdent
|
||||||
: komi;
|
: komi;
|
||||||
|
|
||||||
resValue //'R' is resign
|
|
||||||
: playerIdent PLUS ('R' | realValue);
|
|
||||||
|
|
||||||
realValue
|
realValue
|
||||||
: DIGIT+ PERIOD DIGIT+;
|
: STRVALUE;
|
||||||
|
|
||||||
coordValue returns [SGFCoord sgfCoord]
|
coordValue returns [SGFCoord sgfCoord]
|
||||||
: LCLETTER LCLETTER {$sgfCoord = new SGFCoord($text);}
|
: STRVALUE {$sgfCoord = new SGFCoord($coordValue.text);}
|
||||||
;
|
;
|
||||||
|
|
||||||
fileFormat
|
fileFormat
|
||||||
: 'FF';
|
: 'FF';
|
||||||
game : 'GM';
|
|
||||||
size : 'SZ';
|
game : 'GM' | 'GaMe';
|
||||||
|
|
||||||
|
size : 'SZ' | 'SiZe';
|
||||||
|
|
||||||
|
view : 'VW' | 'VieW';
|
||||||
|
|
||||||
charEnc : 'CA';
|
charEnc : 'CA';
|
||||||
|
|
||||||
source : 'SO';
|
source : 'SO';
|
||||||
|
|
||||||
blackCountry
|
blackCountry
|
||||||
: 'BC';
|
: 'BC';
|
||||||
|
|
||||||
whiteCountry
|
whiteCountry
|
||||||
: 'WC';
|
: 'WC';
|
||||||
event : 'EV';
|
|
||||||
|
event : 'EV' | 'EVent';
|
||||||
|
|
||||||
playerBlack
|
playerBlack
|
||||||
: 'PB';
|
: 'PB' | 'PlayerBlack';
|
||||||
playerWhite
|
playerWhite
|
||||||
: 'PW';
|
: 'PW' | 'PlayerWhite';
|
||||||
blackRank
|
blackRank
|
||||||
: 'BR';
|
: 'BR';
|
||||||
|
|
||||||
whiteRank
|
whiteRank
|
||||||
: 'WR';
|
: 'WR';
|
||||||
|
|
||||||
komi : 'KM';
|
komi : 'KM';
|
||||||
result : 'RE';
|
|
||||||
|
result : 'RE'
|
||||||
|
| 'REsult'
|
||||||
|
;
|
||||||
|
|
||||||
rules : 'RU';
|
rules : 'RU';
|
||||||
place : 'PC';
|
|
||||||
|
place : 'PC' | 'PlaCe';
|
||||||
|
|
||||||
application
|
application
|
||||||
: 'AP';
|
: 'AP';
|
||||||
|
|
||||||
time : 'TM';
|
time : 'TM';
|
||||||
date : 'DT';
|
|
||||||
|
date : 'DT' | 'DaTe';
|
||||||
|
|
||||||
addBlack returns [SGFIdentifier sgfIdent]
|
addBlack returns [SGFIdentifier sgfIdent]
|
||||||
: 'AB'{$sgfIdent = SGFIdentifier.ADD_BLACK;}
|
: 'AB'{$sgfIdent = SGFIdentifier.ADD_BLACK;}
|
||||||
@@ -143,19 +166,40 @@ addWhite returns [SGFIdentifier sgfIdent]
|
|||||||
|
|
||||||
copyright
|
copyright
|
||||||
: 'CP';
|
: 'CP';
|
||||||
|
|
||||||
username: 'US';
|
username: 'US';
|
||||||
|
|
||||||
strValue : (UCLETTER | LCLETTER | MINUS | DIGIT | SPACE | PERIOD | COMMA | PLUS | SLASH | COLON)+;
|
comment : 'C';
|
||||||
|
|
||||||
|
strValue
|
||||||
|
: (STRVALUE)+;
|
||||||
|
|
||||||
|
SPACE : ' ';
|
||||||
|
|
||||||
|
fragment DIGIT : '0'..'9';
|
||||||
|
|
||||||
|
COLON : ':';
|
||||||
|
|
||||||
|
MINUS : '-';
|
||||||
|
|
||||||
|
fragment PERIOD : '.';
|
||||||
|
|
||||||
|
COMMA : ',';
|
||||||
|
|
||||||
|
PLUS : '+';
|
||||||
|
|
||||||
|
SLASH : '/';
|
||||||
|
|
||||||
|
|
||||||
|
STRVALUE : (UCLETTER | LCLETTER | MINUS | DIGIT | SPACE | PERIOD | COMMA | PLUS | SLASH | COLON )+;
|
||||||
|
|
||||||
LPAREN : '(' ;
|
LPAREN : '(' ;
|
||||||
|
|
||||||
SEMICOLON : ';' ;
|
SEMICOLON : ';' ;
|
||||||
|
|
||||||
UCLETTER : 'A'..'Z';
|
fragment UCLETTER : 'A'..'Z';
|
||||||
|
|
||||||
LCLETTER : 'a'..'z';
|
fragment LCLETTER : 'a'..'z';
|
||||||
|
|
||||||
DIGIT : '0'..'9';
|
|
||||||
|
|
||||||
LBRACKET
|
LBRACKET
|
||||||
: '[';
|
: '[';
|
||||||
@@ -165,20 +209,6 @@ RBRACKET
|
|||||||
|
|
||||||
RPAREN : ')';
|
RPAREN : ')';
|
||||||
|
|
||||||
COLON : ':';
|
//CR : '\r'{$channel=HIDDEN;};
|
||||||
|
|
||||||
MINUS : '-';
|
//NEWLINE : '\n'{$channel=HIDDEN;};
|
||||||
|
|
||||||
SPACE : ' ';
|
|
||||||
|
|
||||||
PERIOD : '.';
|
|
||||||
|
|
||||||
COMMA : ',';
|
|
||||||
|
|
||||||
PLUS : '+';
|
|
||||||
|
|
||||||
SLASH : '/';
|
|
||||||
|
|
||||||
CR : '\r'{$channel=HIDDEN;};
|
|
||||||
|
|
||||||
NEWLINE : '\n'{$channel=HIDDEN;};
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ DaTe[1968]
|
|||||||
PlaCe[]
|
PlaCe[]
|
||||||
|
|
||||||
|
|
||||||
REsult[Black wins by four points]
|
REsult[B+4]
|
||||||
|
|
||||||
|
|
||||||
C[This was the first of a two game match on 9x9, played
|
C[This was the first of a two game match on 9x9, played
|
||||||
|
|||||||
118
src/net/woodyfolsom/msproj/GameRecord.java
Normal file
118
src/net/woodyfolsom/msproj/GameRecord.java
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
package net.woodyfolsom.msproj;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class GameRecord {
|
||||||
|
public enum RULES { JAPANESE, CHINESE }
|
||||||
|
|
||||||
|
private GoPlayer playerBlack;
|
||||||
|
private GoPlayer playerWhite;
|
||||||
|
//private int numTurns = 0;
|
||||||
|
private List<Action> moves = new ArrayList<Action>();
|
||||||
|
private List<GameState> gameStates = new ArrayList<GameState>();
|
||||||
|
private Map<Integer, List<String>> comments = new HashMap<Integer,List<String>>();
|
||||||
|
private RULES rules = RULES.CHINESE;
|
||||||
|
|
||||||
|
public GameRecord(GameConfig gameConfig) {
|
||||||
|
gameStates.add(new GameState(gameConfig));
|
||||||
|
//initial 'move' of Action.NONE allows for a game that starts with a board setup
|
||||||
|
moves.add(Action.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a comment for the current turn.
|
||||||
|
* @param comment
|
||||||
|
*/
|
||||||
|
public void addComment(String comment) {
|
||||||
|
if (comments.containsKey(getNumTurns())) {
|
||||||
|
comments.get(getNumTurns()).add(comment);
|
||||||
|
} else {
|
||||||
|
List<String> newComments = new ArrayList<String>();
|
||||||
|
newComments.add(comment);
|
||||||
|
comments.put(getNumTurns(),newComments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getComments(Integer turn) {
|
||||||
|
if (comments.containsKey(turn)) {
|
||||||
|
return Collections.unmodifiableList(comments.get(turn));
|
||||||
|
} else {
|
||||||
|
return new ArrayList<String>(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameConfig getGameConfig() {
|
||||||
|
return gameStates.get(0).getGameConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameState getGameState(Integer turn) {
|
||||||
|
return gameStates.get(turn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action getMove(int turn) {
|
||||||
|
return moves.get(turn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumTurns() {
|
||||||
|
return gameStates.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getPlayerToMove(int turn) {
|
||||||
|
return gameStates.get(turn).getPlayerToMove();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getPlayerToMove() {
|
||||||
|
return gameStates.get(getNumTurns()).getPlayerToMove();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameResult getResult() {
|
||||||
|
return gameStates.get(getNumTurns()).getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RULES getRules() {
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFinished() {
|
||||||
|
return gameStates.get(getNumTurns()).isTerminal();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean play(Player player, Action action) {
|
||||||
|
if (isFinished()) {
|
||||||
|
System.out.println("Unable to play " + action + " as " + player + " because the game is finished.");
|
||||||
|
return false; //cannot make any more moves, game is over
|
||||||
|
}
|
||||||
|
|
||||||
|
GameState nextState = new GameState(gameStates.get(getNumTurns()));
|
||||||
|
if (nextState.playStone(player, action)) {
|
||||||
|
gameStates.add(nextState);
|
||||||
|
moves.add(action);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
//TODO allow relay of an SGF to force making an invalid move?
|
||||||
|
//It may be possible historically for a mistake to have been made,
|
||||||
|
//and recorded.
|
||||||
|
System.out.println("Invalid move" + " by " + player + ": " + action);
|
||||||
|
return false; //invalid move for this player at this time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlayer(Player player, String name, String country, String rank) {
|
||||||
|
if (player == Player.BLACK) {
|
||||||
|
playerBlack = new GoPlayer();
|
||||||
|
playerBlack.setName(name);
|
||||||
|
playerBlack.setRank(rank);
|
||||||
|
playerBlack.setCountry(country);
|
||||||
|
} else if (player == Player.WHITE) {
|
||||||
|
playerWhite = new GoPlayer();
|
||||||
|
playerWhite.setName(name);
|
||||||
|
playerWhite.setRank(rank);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Invalid color: " + player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
src/net/woodyfolsom/msproj/GoPlayer.java
Normal file
42
src/net/woodyfolsom/msproj/GoPlayer.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package net.woodyfolsom.msproj;
|
||||||
|
|
||||||
|
|
||||||
|
public class GoPlayer {
|
||||||
|
private String country;
|
||||||
|
private String name;
|
||||||
|
private String rank;
|
||||||
|
|
||||||
|
public String getCountry() {
|
||||||
|
return country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCountry(String country) {
|
||||||
|
this.country = country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRank() {
|
||||||
|
return rank;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRank(String rank) {
|
||||||
|
this.rank = rank;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toSGF(Player color) {
|
||||||
|
if (color == Player.BLACK) {
|
||||||
|
return "PB[" + name + "]BR[" + rank + "]BC[" + country + "]";
|
||||||
|
} else if (color == Player.WHITE) {
|
||||||
|
return "PW[" + name + "]WR[" + rank + "]WC[" + country + "]";
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Invalid player color: " + color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,18 +36,25 @@ public class Referee {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GameResult play(GameConfig gameConfig) {
|
public GameResult play(GameConfig gameConfig) {
|
||||||
GameState gameState = new GameState(gameConfig);
|
GameRecord gameRecord = new GameRecord(gameConfig);
|
||||||
|
|
||||||
System.out.println("Game started.");
|
System.out.println("Game started.");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (!gameState.isTerminal()) {
|
while (!gameRecord.isFinished()) {
|
||||||
|
GameState gameState = gameRecord.getGameState(gameRecord.getNumTurns());
|
||||||
System.out.println(gameState);
|
System.out.println(gameState);
|
||||||
|
|
||||||
Player currentPlayer = gameState.getPlayerToMove();
|
Player playerToMove = gameRecord.getPlayerToMove();
|
||||||
Action action = getPolicy(currentPlayer).getAction(gameConfig,
|
Policy policy = getPolicy(playerToMove);
|
||||||
gameState, currentPlayer);
|
Action action = policy.getAction(gameConfig,
|
||||||
gameState.playStone(currentPlayer, action);
|
gameState, playerToMove);
|
||||||
|
|
||||||
|
if (gameRecord.play(playerToMove, action)) {
|
||||||
|
policy.setState(gameRecord.getGameState(gameRecord.getNumTurns()));
|
||||||
|
} else {
|
||||||
|
System.out.println("Move rejected - try again.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
System.out
|
System.out
|
||||||
@@ -56,7 +63,7 @@ public class Referee {
|
|||||||
return GameResult.VOID;
|
return GameResult.VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameResult result = gameState.getResult();
|
GameResult result = gameRecord.getResult();
|
||||||
|
|
||||||
System.out.println("Game over. Result: " + result);
|
System.out.println("Game over. Result: " + result);
|
||||||
|
|
||||||
@@ -68,7 +75,7 @@ public class Referee {
|
|||||||
+ ".sgf");
|
+ ".sgf");
|
||||||
FileOutputStream fos = new FileOutputStream(sgfFile);
|
FileOutputStream fos = new FileOutputStream(sgfFile);
|
||||||
try {
|
try {
|
||||||
SGFWriter.writeSGF(gameState, fos);
|
SGFWriter.write(fos, gameRecord);
|
||||||
System.out
|
System.out
|
||||||
.println("Game saved as " + sgfFile.getAbsolutePath());
|
.println("Game saved as " + sgfFile.getAbsolutePath());
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -2,21 +2,45 @@ package net.woodyfolsom.msproj;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
import net.woodyfolsom.msproj.sgf.SGFIdentifier;
|
|
||||||
|
|
||||||
public class SGFWriter {
|
public class SGFWriter {
|
||||||
|
|
||||||
public static void writeSGF(GameState gameState, OutputStream os)
|
public static void write(OutputStream os, GameRecord gameRecord)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
writeNode(os, SGFIdentifier.FILE_FORMAT, Integer.valueOf(4));
|
OutputStreamWriter writer = new OutputStreamWriter(os);
|
||||||
}
|
|
||||||
|
|
||||||
private static void writeNode(OutputStream os, SGFIdentifier sgfIdent,
|
writer.write("(");
|
||||||
Object nodeValue) throws IOException {
|
|
||||||
os.write(sgfIdent.toString().getBytes());
|
writer.write(";FF[4]GM[1]");
|
||||||
os.write("[".getBytes());
|
|
||||||
os.write(nodeValue.toString().getBytes());
|
GameConfig gameConfig = gameRecord.getGameConfig();
|
||||||
os.write("];".getBytes());
|
|
||||||
|
writer.write("SZ[" + gameConfig.getSize() + "]");
|
||||||
|
writer.write("KM[" + gameConfig.getKomi() + "]");
|
||||||
|
|
||||||
|
for (int i = 1; i <= gameRecord.getNumTurns(); i++) {
|
||||||
|
Player player = gameRecord.getPlayerToMove(i-1);
|
||||||
|
if (Player.BLACK == player) {
|
||||||
|
writer.write(";B[");
|
||||||
|
} else if (Player.WHITE == player) {
|
||||||
|
writer.write(";W[");
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Invalid player: " + player);
|
||||||
|
}
|
||||||
|
Action action = gameRecord.getMove(i);
|
||||||
|
String sgfCoord;
|
||||||
|
if (action.isPass()) {
|
||||||
|
sgfCoord = "";
|
||||||
|
} else {
|
||||||
|
sgfCoord = action.toString().toLowerCase().substring(0,1);
|
||||||
|
char row = (char) ('a' + gameConfig.getSize() - Integer.valueOf(action.toString().substring(1)).intValue());
|
||||||
|
sgfCoord = sgfCoord + row;
|
||||||
|
}
|
||||||
|
writer.write(sgfCoord + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.write(")");
|
||||||
|
writer.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,39 +1,54 @@
|
|||||||
package net.woodyfolsom.msproj.gui;
|
package net.woodyfolsom.msproj.gui;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.KeyListener;
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
import javax.swing.JButton;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
import net.woodyfolsom.msproj.Action;
|
import net.woodyfolsom.msproj.Action;
|
||||||
import net.woodyfolsom.msproj.GameConfig;
|
import net.woodyfolsom.msproj.GameConfig;
|
||||||
import net.woodyfolsom.msproj.GameState;
|
import net.woodyfolsom.msproj.GameState;
|
||||||
import net.woodyfolsom.msproj.Player;
|
import net.woodyfolsom.msproj.Player;
|
||||||
|
|
||||||
public class Goban extends JFrame implements KeyListener {
|
public class Goban extends JFrame {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
//private GameState gameState;
|
|
||||||
private GridPanel gridPanel;
|
private GridPanel gridPanel;
|
||||||
|
|
||||||
/*
|
|
||||||
public static void main(String[] args) {
|
|
||||||
Goban goban = new Goban();
|
|
||||||
goban.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
||||||
goban.setVisible(true);
|
|
||||||
goban.pack();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public Goban(GameConfig gameConfig, Player guiPlayer) {
|
public Goban(GameConfig gameConfig, Player guiPlayer) {
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
this.gridPanel = new GridPanel(gameConfig, guiPlayer);
|
this.gridPanel = new GridPanel(gameConfig, guiPlayer);
|
||||||
add(gridPanel,BorderLayout.CENTER);
|
add(gridPanel,BorderLayout.CENTER);
|
||||||
addKeyListener(this);
|
|
||||||
|
|
||||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
|
|
||||||
|
JButton passBtn = new JButton("Pass");
|
||||||
|
JButton resignBtn = new JButton("Resign");
|
||||||
|
|
||||||
|
passBtn.addActionListener(new ActionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent arg0) {
|
||||||
|
gridPanel.addAction(Action.PASS);
|
||||||
|
}});
|
||||||
|
|
||||||
|
resignBtn.addActionListener(new ActionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent arg0) {
|
||||||
|
gridPanel.addAction(Action.RESIGN);
|
||||||
|
}});
|
||||||
|
|
||||||
|
JPanel bottomPanel = new JPanel();
|
||||||
|
bottomPanel.add(passBtn);
|
||||||
|
bottomPanel.add(resignBtn);
|
||||||
|
|
||||||
|
add(bottomPanel, BorderLayout.SOUTH);
|
||||||
pack();
|
pack();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,32 +59,5 @@ public class Goban extends JFrame implements KeyListener {
|
|||||||
public void setGameState(GameState gameState) {
|
public void setGameState(GameState gameState) {
|
||||||
gridPanel.setGameState(gameState);
|
gridPanel.setGameState(gameState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void keyPressed(KeyEvent arg0) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
}
|
||||||
public void keyReleased(KeyEvent arg0) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void keyTyped(KeyEvent arg0) {
|
|
||||||
switch (arg0.getKeyChar())
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
case 't' :
|
|
||||||
case 'T' :
|
|
||||||
//Player currentPlayer = GoGame.getNextPlayer(gameState.getPlayerToMove());
|
|
||||||
//System.out.println("Switching players. Current player is now " + currentPlayer);
|
|
||||||
//gameState.
|
|
||||||
break;*/
|
|
||||||
default :
|
|
||||||
System.out.println("Ignoring unbound key: " + arg0.getKeyChar());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -76,8 +76,12 @@ public class GridPanel extends JPanel implements MouseListener,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addAction(Action action) {
|
||||||
|
actionQueue.add(action);
|
||||||
|
}
|
||||||
|
|
||||||
public Action getAction() {
|
public Action getAction() {
|
||||||
int timeLimit = 10;
|
int timeLimit = 30;
|
||||||
TimeUnit timeUnit = TimeUnit.SECONDS;
|
TimeUnit timeUnit = TimeUnit.SECONDS;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -212,6 +216,7 @@ public class GridPanel extends JPanel implements MouseListener,
|
|||||||
|
|
||||||
public void setGameState(GameState gameState) {
|
public void setGameState(GameState gameState) {
|
||||||
this.gameState = gameState;
|
this.gameState = gameState;
|
||||||
|
this.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -176,4 +176,10 @@ public class AlphaBeta implements Policy {
|
|||||||
throw new UnsupportedOperationException(
|
throw new UnsupportedOperationException(
|
||||||
"Prohibited actions not supported by this class.");
|
"Prohibited actions not supported by this class.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(GameState gameState) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package net.woodyfolsom.msproj.policy;
|
package net.woodyfolsom.msproj.policy;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import net.woodyfolsom.msproj.Action;
|
import net.woodyfolsom.msproj.Action;
|
||||||
@@ -20,7 +19,6 @@ public class HumanGuiInput implements Policy {
|
|||||||
public Action getAction(GameConfig gameConfig, GameState gameState,
|
public Action getAction(GameConfig gameConfig, GameState gameState,
|
||||||
Player player) {
|
Player player) {
|
||||||
Action action = null;
|
Action action = null;
|
||||||
String input = "";
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
System.out.println(player
|
System.out.println(player
|
||||||
@@ -30,8 +28,6 @@ public class HumanGuiInput implements Policy {
|
|||||||
action = goban.getAction();
|
action = goban.getAction();
|
||||||
|
|
||||||
if (action.isNone()) {
|
if (action.isNone()) {
|
||||||
System.out.println("No move was made within 10 seconds. Hurry up!");
|
|
||||||
System.out.println(gameState);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} while (action == null);
|
} while (action == null);
|
||||||
@@ -51,4 +47,9 @@ public class HumanGuiInput implements Policy {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(GameState gameState) {
|
||||||
|
goban.setGameState(gameState);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,4 +70,10 @@ public class HumanKeyboardInput implements Policy {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(GameState gameState) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,4 +149,10 @@ public class Minimax implements Policy {
|
|||||||
throw new UnsupportedOperationException(
|
throw new UnsupportedOperationException(
|
||||||
"Prohibited actions not supported by this class.");
|
"Prohibited actions not supported by this class.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(GameState gameState) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ import net.woodyfolsom.msproj.tree.GameTreeNode;
|
|||||||
import net.woodyfolsom.msproj.tree.MonteCarloProperties;
|
import net.woodyfolsom.msproj.tree.MonteCarloProperties;
|
||||||
|
|
||||||
public abstract class MonteCarlo implements Policy {
|
public abstract class MonteCarlo implements Policy {
|
||||||
protected static final int ROLLOUT_DEPTH_LIMIT = 400;
|
protected static final int ROLLOUT_DEPTH_LIMIT = 100;
|
||||||
|
|
||||||
protected int numStateEvaluations = 0;
|
protected int numStateEvaluations = 0;
|
||||||
protected Policy movePolicy;
|
protected Policy movePolicy;
|
||||||
@@ -113,10 +113,6 @@ public abstract class MonteCarlo implements Policy {
|
|||||||
return searchTimeLimit;
|
return searchTimeLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int doRollout() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumStateEvaluations() {
|
public int getNumStateEvaluations() {
|
||||||
return numStateEvaluations;
|
return numStateEvaluations;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,4 +196,10 @@ public class MonteCarloUCT extends MonteCarlo {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "MonteCarloUCT";
|
return "MonteCarloUCT";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(GameState gameState) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -15,4 +15,6 @@ public interface Policy {
|
|||||||
Collection<Action> prohibitedActions, Player player);
|
Collection<Action> prohibitedActions, Player player);
|
||||||
|
|
||||||
public int getNumStateEvaluations();
|
public int getNumStateEvaluations();
|
||||||
|
|
||||||
|
public void setState(GameState gameState);
|
||||||
}
|
}
|
||||||
@@ -83,4 +83,10 @@ public class RandomMovePolicy implements Policy, ActionGenerator {
|
|||||||
Player player) {
|
Player player) {
|
||||||
return getActions(gameConfig, gameState, player, 1).get(0);
|
return getActions(gameConfig, gameState, player, 1).get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(GameState gameState) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -147,4 +147,10 @@ public class RootParallelization implements Policy {
|
|||||||
qValues = policy.getQvalues(gameConfig, gameState, player);
|
qValues = policy.getQvalues(gameConfig, gameState, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(GameState gameState) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
T__20=20
|
||||||
T__21=21
|
T__21=21
|
||||||
T__22=22
|
T__22=22
|
||||||
T__23=23
|
T__23=23
|
||||||
@@ -24,46 +25,68 @@ T__43=43
|
|||||||
T__44=44
|
T__44=44
|
||||||
T__45=45
|
T__45=45
|
||||||
T__46=46
|
T__46=46
|
||||||
|
T__47=47
|
||||||
|
T__48=48
|
||||||
|
T__49=49
|
||||||
|
T__50=50
|
||||||
|
T__51=51
|
||||||
|
T__52=52
|
||||||
|
T__53=53
|
||||||
|
T__54=54
|
||||||
|
T__55=55
|
||||||
|
T__56=56
|
||||||
|
T__57=57
|
||||||
COLON=4
|
COLON=4
|
||||||
COMMA=5
|
COMMA=5
|
||||||
CR=6
|
DIGIT=6
|
||||||
DIGIT=7
|
LBRACKET=7
|
||||||
LBRACKET=8
|
LCLETTER=8
|
||||||
LCLETTER=9
|
LPAREN=9
|
||||||
LPAREN=10
|
MINUS=10
|
||||||
MINUS=11
|
PERIOD=11
|
||||||
NEWLINE=12
|
PLUS=12
|
||||||
PERIOD=13
|
RBRACKET=13
|
||||||
PLUS=14
|
RPAREN=14
|
||||||
RBRACKET=15
|
SEMICOLON=15
|
||||||
RPAREN=16
|
SLASH=16
|
||||||
SEMICOLON=17
|
SPACE=17
|
||||||
SLASH=18
|
STRVALUE=18
|
||||||
SPACE=19
|
UCLETTER=19
|
||||||
UCLETTER=20
|
'AB'=20
|
||||||
'AB'=21
|
'AP'=21
|
||||||
'AP'=22
|
'AW'=22
|
||||||
'AW'=23
|
'B'=23
|
||||||
'B'=24
|
'BC'=24
|
||||||
'BC'=25
|
'BR'=25
|
||||||
'BR'=26
|
'Black'=26
|
||||||
'CA'=27
|
'C'=27
|
||||||
'CP'=28
|
'CA'=28
|
||||||
'DT'=29
|
'CP'=29
|
||||||
'EV'=30
|
'DT'=30
|
||||||
'FF'=31
|
'DaTe'=31
|
||||||
'GM'=32
|
'EV'=32
|
||||||
'KM'=33
|
'EVent'=33
|
||||||
'PB'=34
|
'FF'=34
|
||||||
'PC'=35
|
'GM'=35
|
||||||
'PW'=36
|
'GaMe'=36
|
||||||
'R'=37
|
'KM'=37
|
||||||
'RE'=38
|
'PB'=38
|
||||||
'RU'=39
|
'PC'=39
|
||||||
'SO'=40
|
'PW'=40
|
||||||
'SZ'=41
|
'PlaCe'=41
|
||||||
'TM'=42
|
'PlayerBlack'=42
|
||||||
'US'=43
|
'PlayerWhite'=43
|
||||||
'W'=44
|
'RE'=44
|
||||||
'WC'=45
|
'REsult'=45
|
||||||
'WR'=46
|
'RU'=46
|
||||||
|
'SO'=47
|
||||||
|
'SZ'=48
|
||||||
|
'SiZe'=49
|
||||||
|
'TM'=50
|
||||||
|
'US'=51
|
||||||
|
'VW'=52
|
||||||
|
'VieW'=53
|
||||||
|
'W'=54
|
||||||
|
'WC'=55
|
||||||
|
'WR'=56
|
||||||
|
'White'=57
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class SGFGameTree {
|
|||||||
return subTrees.size();
|
return subTrees.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toLateXmoves(Player player) {
|
public String toLateXmoves(Player player, int boardSize) {
|
||||||
StringBuilder latexSB = new StringBuilder();
|
StringBuilder latexSB = new StringBuilder();
|
||||||
SGFNode.TYPE nodeType;
|
SGFNode.TYPE nodeType;
|
||||||
SGFIdentifier sgfIdent;
|
SGFIdentifier sgfIdent;
|
||||||
@@ -73,7 +73,8 @@ public class SGFGameTree {
|
|||||||
} else {
|
} else {
|
||||||
latexSB.append(column);
|
latexSB.append(column);
|
||||||
}
|
}
|
||||||
latexSB.append(19 - sgfCoord.getRow() + 'a');
|
char row = sgfCoord.getRow();
|
||||||
|
latexSB.append(boardSize - row + 'a');
|
||||||
nMoves++;
|
nMoves++;
|
||||||
}
|
}
|
||||||
if (nMoves == 0) {
|
if (nMoves == 0) {
|
||||||
@@ -83,7 +84,20 @@ public class SGFGameTree {
|
|||||||
return latexSB.toString();
|
return latexSB.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toLateX() {
|
public int getBoardSize() {
|
||||||
|
for (SGFNode node : nodeSequence) {
|
||||||
|
SGFNode.TYPE nodeType = node.getType();
|
||||||
|
switch (nodeType) {
|
||||||
|
case ROOT:
|
||||||
|
return Integer.valueOf(node.getFirstValue(SGFIdentifier.SIZE).getText());
|
||||||
|
default:
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Cannot get board size: SGFNode with identifier SZ was not found in any nodeSequence of type ROOT.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toLateX(int boardSize) {
|
||||||
StringBuilder latexSB = new StringBuilder();
|
StringBuilder latexSB = new StringBuilder();
|
||||||
|
|
||||||
// Somewhat convoluted logic here because the grammar does not require
|
// Somewhat convoluted logic here because the grammar does not require
|
||||||
@@ -97,7 +111,7 @@ public class SGFGameTree {
|
|||||||
case ROOT:
|
case ROOT:
|
||||||
latexSB.append("\\gobansize");
|
latexSB.append("\\gobansize");
|
||||||
latexSB.append("{");
|
latexSB.append("{");
|
||||||
latexSB.append(node.getFirstValue(SGFIdentifier.SIZE));
|
latexSB.append(boardSize);
|
||||||
latexSB.append("}\n");
|
latexSB.append("}\n");
|
||||||
latexSB.append("\\shortstack{\\showfullgoban\\\\");
|
latexSB.append("\\shortstack{\\showfullgoban\\\\");
|
||||||
SGFResult result = (SGFResult) node.getFirstValue(
|
SGFResult result = (SGFResult) node.getFirstValue(
|
||||||
@@ -120,4 +134,15 @@ public class SGFGameTree {
|
|||||||
sgfFormatString.append(")");
|
sgfFormatString.append(")");
|
||||||
return sgfFormatString.toString();
|
return sgfFormatString.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
stringBuilder.append("(");
|
||||||
|
for (SGFNode node : nodeSequence) {
|
||||||
|
stringBuilder.append(node.toString());
|
||||||
|
}
|
||||||
|
stringBuilder.append(")");
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,29 @@ package net.woodyfolsom.msproj.sgf;
|
|||||||
public class SGFIdentifier {
|
public class SGFIdentifier {
|
||||||
public static final SGFIdentifier ADD_BLACK = new SGFIdentifier("AB");
|
public static final SGFIdentifier ADD_BLACK = new SGFIdentifier("AB");
|
||||||
public static final SGFIdentifier ADD_WHITE = new SGFIdentifier("AW");
|
public static final SGFIdentifier ADD_WHITE = new SGFIdentifier("AW");
|
||||||
|
public static final SGFIdentifier APPLICATION = new SGFIdentifier("AP");
|
||||||
|
public static final SGFIdentifier COUNTRY_BLACK = new SGFIdentifier("BC");
|
||||||
|
public static final SGFIdentifier COUNTRY_WHITE = new SGFIdentifier("WC");
|
||||||
public static final SGFIdentifier CHARSET = new SGFIdentifier("CA");
|
public static final SGFIdentifier CHARSET = new SGFIdentifier("CA");
|
||||||
|
public static final SGFIdentifier COMMENT = new SGFIdentifier("C");
|
||||||
|
public static final SGFIdentifier DATE = new SGFIdentifier("DT");
|
||||||
|
public static final SGFIdentifier EVENT = new SGFIdentifier("EV");
|
||||||
public static final SGFIdentifier FILE_FORMAT = new SGFIdentifier("FF");
|
public static final SGFIdentifier FILE_FORMAT = new SGFIdentifier("FF");
|
||||||
public static final SGFIdentifier GAME = new SGFIdentifier("GM");
|
public static final SGFIdentifier GAME = new SGFIdentifier("GM");
|
||||||
public static final SGFIdentifier KOMI = new SGFIdentifier("KM");
|
public static final SGFIdentifier KOMI = new SGFIdentifier("KM");
|
||||||
public static final SGFIdentifier MOVE_BLACK = new SGFIdentifier("B");
|
public static final SGFIdentifier MOVE_BLACK = new SGFIdentifier("B");
|
||||||
public static final SGFIdentifier MOVE_WHITE = new SGFIdentifier("W");
|
public static final SGFIdentifier MOVE_WHITE = new SGFIdentifier("W");
|
||||||
|
public static final SGFIdentifier PLACE = new SGFIdentifier("PC");
|
||||||
|
public static final SGFIdentifier PLAYER_BLACK = new SGFIdentifier("PB");
|
||||||
|
public static final SGFIdentifier PLAYER_WHITE = new SGFIdentifier("PW");
|
||||||
|
public static final SGFIdentifier RANK_BLACK = new SGFIdentifier("RB");
|
||||||
|
public static final SGFIdentifier RANK_WHITE = new SGFIdentifier("RW");
|
||||||
public static final SGFIdentifier RESULT = new SGFIdentifier("RE");
|
public static final SGFIdentifier RESULT = new SGFIdentifier("RE");
|
||||||
|
public static final SGFIdentifier RULES = new SGFIdentifier("RU");
|
||||||
public static final SGFIdentifier SIZE = new SGFIdentifier("SZ");
|
public static final SGFIdentifier SIZE = new SGFIdentifier("SZ");
|
||||||
|
public static final SGFIdentifier SOURCE = new SGFIdentifier("SO");
|
||||||
public static final SGFIdentifier TIME = new SGFIdentifier("TM");
|
public static final SGFIdentifier TIME = new SGFIdentifier("TM");
|
||||||
|
public static final SGFIdentifier VIEW = new SGFIdentifier("VW");
|
||||||
|
|
||||||
private String text;
|
private String text;
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public class SGFNode {
|
public class SGFNode {
|
||||||
public enum TYPE {
|
public enum TYPE {
|
||||||
ROOT, MOVE_BLACK, MOVE_WHITE, EMPTY
|
ROOT, MOVE_BLACK, MOVE_WHITE, EMPTY, COMMENT
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<SGFProperty> properties = new ArrayList<SGFProperty>();
|
private List<SGFProperty> properties = new ArrayList<SGFProperty>();
|
||||||
@@ -18,6 +18,8 @@ public class SGFNode {
|
|||||||
type = TYPE.MOVE_BLACK;
|
type = TYPE.MOVE_BLACK;
|
||||||
} else if (sgfIdent == SGFIdentifier.MOVE_WHITE) {
|
} else if (sgfIdent == SGFIdentifier.MOVE_WHITE) {
|
||||||
type = TYPE.MOVE_WHITE;
|
type = TYPE.MOVE_WHITE;
|
||||||
|
} else if (sgfIdent == SGFIdentifier.COMMENT) {
|
||||||
|
type = TYPE.COMMENT;
|
||||||
} else {
|
} else {
|
||||||
type = TYPE.ROOT;
|
type = TYPE.ROOT;
|
||||||
}
|
}
|
||||||
@@ -59,4 +61,14 @@ public class SGFNode {
|
|||||||
|
|
||||||
return sgfFormatString;
|
return sgfFormatString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
stringBuilder.append(";");
|
||||||
|
for (SGFProperty property : properties) {
|
||||||
|
stringBuilder.append(property.toString());
|
||||||
|
}
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,25 +24,30 @@ public class SGFNodeCollection {
|
|||||||
StringBuilder latexFormatString = new StringBuilder("");
|
StringBuilder latexFormatString = new StringBuilder("");
|
||||||
SGFGameTree gameTree = gameTrees.get(0);
|
SGFGameTree gameTree = gameTrees.get(0);
|
||||||
|
|
||||||
latexFormatString.append(gameTree.toLateXmoves(Player.BLACK));
|
int boardSize = gameTree.getBoardSize();
|
||||||
latexFormatString.append(gameTree.toLateXmoves(Player.WHITE));
|
latexFormatString.append(gameTree.toLateXmoves(Player.BLACK, boardSize));
|
||||||
|
latexFormatString.append(gameTree.toLateXmoves(Player.WHITE, boardSize));
|
||||||
latexFormatString.append("\\begin{center}\n");
|
latexFormatString.append("\\begin{center}\n");
|
||||||
latexFormatString.append(gameTree.toLateX());
|
latexFormatString.append(gameTree.toLateX(boardSize));
|
||||||
latexFormatString.append("\\end{center}");
|
latexFormatString.append("\\end{center}");
|
||||||
|
|
||||||
return latexFormatString.toString();
|
return latexFormatString.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is an alias for toString().
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public String toSGF() {
|
public String toSGF() {
|
||||||
String sgfFormatString = "";
|
return toString();
|
||||||
for (SGFGameTree gameTree : gameTrees) {
|
|
||||||
sgfFormatString += gameTree.toSGF();
|
|
||||||
}
|
|
||||||
return sgfFormatString;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toSGF();
|
StringBuilder sbuilder = new StringBuilder();
|
||||||
|
for (SGFGameTree gameTree : gameTrees) {
|
||||||
|
sbuilder.append(gameTree.toString());
|
||||||
|
}
|
||||||
|
return sbuilder.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -36,4 +36,15 @@ public class SGFProperty {
|
|||||||
|
|
||||||
return sgfFormatString;
|
return sgfFormatString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder(identifier.toString());
|
||||||
|
for (SGFValue<?> value : values) {
|
||||||
|
stringBuilder.append("[");
|
||||||
|
stringBuilder.append(value.toString());
|
||||||
|
stringBuilder.append("]");
|
||||||
|
}
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
(;FF[4]GM[1]SZ[19]CA[UTF-8]SO[gokifu.com]BC[kr]WC[cn]EV[]PB[Lee Sedol]BR[9p]PW[Gu Li]WR[9p]KM[7.5]
|
|
||||||
DT[2012-09-16]RE[W+R];B[qd];W[dc];B[dq];W[do];B[pp];W[cq];B[de];W[cg];B[cc];W[gc];B[gd];W[hd];B[fc]
|
|
||||||
;W[fd];B[ge];W[fb];B[hc];W[ec];B[gb];W[fc];B[id];W[cd];B[he];W[oc];B[pe];W[qk];B[qi];W[qn];B[qo]
|
|
||||||
;W[pn];B[np];W[oj];B[oi];W[ni];B[nj];W[pi];B[oh];W[pj];B[ph];W[qh];B[qg];W[rh];B[ri];W[rg];B[rf]
|
|
||||||
;W[oo];B[op];W[mj];B[mc];W[nk];B[cr];W[cp];B[gq];W[md];B[nc];W[qf];B[sh];W[pg];B[sg];W[od];B[nd]
|
|
||||||
;W[oe];B[ne];W[nf];B[qg];W[og];B[nh];W[mh];B[mg];W[ng];B[qh];W[mf];B[lg];W[lf];B[ld];W[qc];B[rc]
|
|
||||||
;W[pb];B[rb];W[kg];B[lh];W[mi];B[dl];W[br];B[ce];W[bd];B[dg];W[dh];B[be];W[eg];B[fe];W[dd];B[df]
|
|
||||||
;W[ci];B[gl];W[fh];B[ad];W[bc];B[dr];W[dm];B[em];W[cm];B[gg];W[gh];B[jq];W[fo];B[il];W[hg];B[ho]
|
|
||||||
;W[lo];B[lq];W[kp];B[kq];W[ee];B[ef];W[ff];B[ed];W[gp];B[hq];W[ee];B[pf];W[of];B[ed];W[gn];B[ei]
|
|
||||||
;W[eh];B[ii];W[kd];B[kc];W[ke];B[nb];W[fl];B[fk];W[ek];B[fj];W[dj];B[gf];W[gm];B[kh];W[jh];B[jg]
|
|
||||||
;W[ig];B[jf];W[jd];B[je];W[kf];B[ki];W[jc];B[kb];W[jb];B[ib];W[ja];B[ob];W[ic];B[ih];W[ha];B[hb]
|
|
||||||
;W[ga];B[ma];W[hh];B[hk];W[kl];B[kk];W[jk];B[jj];W[lk];B[bg];W[bh];B[cf];W[ch];B[ag];W[ac];B[el]
|
|
||||||
;W[fm];B[ae];W[rn];B[ro];W[fq];B[fr];W[so];B[sp];W[sn];B[rp];W[gj];B[hj];W[ej];B[fi];W[gi];B[gk]
|
|
||||||
;W[bj];B[jl];W[kj];B[ik];W[fg];B[ee];W[eq];B[er];W[km];B[bs];W[ar];B[rk];W[rl];B[qj];W[no];B[mp]
|
|
||||||
;W[ql];B[qb];W[ia];B[hd];W[pc];B[pa];W[jo];B[hm];W[dp])
|
|
||||||
@@ -49,6 +49,7 @@ public class CollectionTest {
|
|||||||
SGFParser parser = new SGFParser(tokens);
|
SGFParser parser = new SGFParser(tokens);
|
||||||
SGFNodeCollection nodeCollection = parser.collection();
|
SGFNodeCollection nodeCollection = parser.collection();
|
||||||
|
|
||||||
assertEquals(TEST_LATEX, nodeCollection.toLateX());
|
String actualLaTeX = nodeCollection.toLateX();
|
||||||
|
assertEquals(TEST_LATEX, actualLaTeX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,4 +31,24 @@ public class SGFParserTest {
|
|||||||
System.out.println("");
|
System.out.println("");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse9x9() throws RecognitionException, IOException {
|
||||||
|
FileInputStream fis = new FileInputStream(new File(
|
||||||
|
"data/games/pro9x9/game001.sgf"));
|
||||||
|
ANTLRStringStream in = new ANTLRInputStream(fis);
|
||||||
|
SGFLexer lexer = new SGFLexer(in);
|
||||||
|
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
|
SGFParser parser = new SGFParser(tokens);
|
||||||
|
SGFNodeCollection nodeCollection = parser.collection();
|
||||||
|
|
||||||
|
System.out.println("To SGF:");
|
||||||
|
System.out.println(nodeCollection.toSGF());
|
||||||
|
System.out.println("");
|
||||||
|
|
||||||
|
System.out.println("To LaTeX:");
|
||||||
|
System.out.println(nodeCollection.toLateX());
|
||||||
|
System.out.println("");
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user