Able to export SGF files from successful games.
This commit is contained in:
128
data/SGF.g
128
data/SGF.g
@@ -44,7 +44,8 @@ $sgfProperty = new SGFProperty();
|
||||
| (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));})+
|
||||
|
||||
| (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)));})+
|
||||
| (coordIdent{$sgfProperty.setIdentifier($coordIdent.sgfIdent);})((LBRACKET coordValue RBRACKET){$sgfProperty.addValue(new SGFValue<SGFCoord>(new SGFCoord($coordValue.text)));})+
|
||||
;
|
||||
@@ -53,27 +54,32 @@ $sgfProperty = new SGFProperty();
|
||||
playerIdent returns [SGFIdentifier sgfPlayer]
|
||||
: {(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("White"))}? strIdent {$sgfPlayer = $strIdent.sgfIdent;}
|
||||
| {(input.LT(1).getText().equals("Black"))}? strIdent {$sgfPlayer = $strIdent.sgfIdent;}
|
||||
;
|
||||
|
||||
strIdent returns [SGFIdentifier sgfIdent]
|
||||
: charEnc{$sgfIdent = SGFIdentifier.CHARSET;}
|
||||
| source
|
||||
| blackCountry
|
||||
| whiteCountry
|
||||
| event
|
||||
| playerBlack
|
||||
| playerWhite
|
||||
| blackRank
|
||||
| whiteRank
|
||||
| result
|
||||
| rules
|
||||
| place
|
||||
| application
|
||||
| source{$sgfIdent = SGFIdentifier.SOURCE;}
|
||||
| blackCountry{$sgfIdent = SGFIdentifier.COUNTRY_BLACK;}
|
||||
| whiteCountry{$sgfIdent = SGFIdentifier.COUNTRY_WHITE;}
|
||||
| event{$sgfIdent = SGFIdentifier.EVENT;}
|
||||
| playerBlack{$sgfIdent = SGFIdentifier.PLAYER_BLACK;}
|
||||
| playerWhite{$sgfIdent = SGFIdentifier.PLAYER_WHITE;}
|
||||
| blackRank{$sgfIdent = SGFIdentifier.RANK_BLACK;}
|
||||
| whiteRank{$sgfIdent = SGFIdentifier.RANK_WHITE;}
|
||||
| rules{$sgfIdent = SGFIdentifier.RULES;}
|
||||
| place{$sgfIdent = SGFIdentifier.PLACE;}
|
||||
| application{$sgfIdent = SGFIdentifier.APPLICATION;}
|
||||
| copyright
|
||||
| username
|
||||
| date
|
||||
| date{$sgfIdent = SGFIdentifier.DATE;}
|
||||
| 'Black'{$sgfIdent = SGFIdentifier.MOVE_BLACK;}
|
||||
| 'White'{$sgfIdent = SGFIdentifier.MOVE_WHITE;}
|
||||
| 'B'{$sgfIdent = SGFIdentifier.MOVE_BLACK;}
|
||||
| '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
|
||||
; //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.
|
||||
@@ -90,48 +96,65 @@ numIdent returns [SGFIdentifier sgfIdent]
|
||||
| time{$sgfIdent = SGFIdentifier.TIME;};
|
||||
|
||||
numValue returns [SGFValue<Integer> sgfValue]
|
||||
: (DIGIT+){$sgfValue = new SGFValue<Integer>(Integer.parseInt($numValue.text));};
|
||||
: (STRVALUE){$sgfValue = new SGFValue<Integer>(Integer.parseInt($numValue.text));};
|
||||
|
||||
realIdent
|
||||
: komi;
|
||||
|
||||
resValue //'R' is resign
|
||||
: playerIdent PLUS ('R' | realValue);
|
||||
|
||||
realValue
|
||||
: DIGIT+ PERIOD DIGIT+;
|
||||
: STRVALUE;
|
||||
|
||||
coordValue returns [SGFCoord sgfCoord]
|
||||
: LCLETTER LCLETTER {$sgfCoord = new SGFCoord($text);}
|
||||
: STRVALUE {$sgfCoord = new SGFCoord($coordValue.text);}
|
||||
;
|
||||
|
||||
fileFormat
|
||||
: 'FF';
|
||||
game : 'GM';
|
||||
size : 'SZ';
|
||||
|
||||
game : 'GM' | 'GaMe';
|
||||
|
||||
size : 'SZ' | 'SiZe';
|
||||
|
||||
view : 'VW' | 'VieW';
|
||||
|
||||
charEnc : 'CA';
|
||||
|
||||
source : 'SO';
|
||||
|
||||
blackCountry
|
||||
: 'BC';
|
||||
|
||||
whiteCountry
|
||||
: 'WC';
|
||||
event : 'EV';
|
||||
|
||||
event : 'EV' | 'EVent';
|
||||
|
||||
playerBlack
|
||||
: 'PB';
|
||||
: 'PB' | 'PlayerBlack';
|
||||
playerWhite
|
||||
: 'PW';
|
||||
: 'PW' | 'PlayerWhite';
|
||||
blackRank
|
||||
: 'BR';
|
||||
|
||||
whiteRank
|
||||
: 'WR';
|
||||
|
||||
komi : 'KM';
|
||||
result : 'RE';
|
||||
|
||||
result : 'RE'
|
||||
| 'REsult'
|
||||
;
|
||||
|
||||
rules : 'RU';
|
||||
place : 'PC';
|
||||
|
||||
place : 'PC' | 'PlaCe';
|
||||
|
||||
application
|
||||
: 'AP';
|
||||
|
||||
time : 'TM';
|
||||
date : 'DT';
|
||||
|
||||
date : 'DT' | 'DaTe';
|
||||
|
||||
addBlack returns [SGFIdentifier sgfIdent]
|
||||
: 'AB'{$sgfIdent = SGFIdentifier.ADD_BLACK;}
|
||||
@@ -143,19 +166,40 @@ addWhite returns [SGFIdentifier sgfIdent]
|
||||
|
||||
copyright
|
||||
: 'CP';
|
||||
|
||||
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 : '(' ;
|
||||
|
||||
SEMICOLON : ';' ;
|
||||
|
||||
UCLETTER : 'A'..'Z';
|
||||
fragment UCLETTER : 'A'..'Z';
|
||||
|
||||
LCLETTER : 'a'..'z';
|
||||
|
||||
DIGIT : '0'..'9';
|
||||
fragment LCLETTER : 'a'..'z';
|
||||
|
||||
LBRACKET
|
||||
: '[';
|
||||
@@ -165,20 +209,6 @@ RBRACKET
|
||||
|
||||
RPAREN : ')';
|
||||
|
||||
COLON : ':';
|
||||
//CR : '\r'{$channel=HIDDEN;};
|
||||
|
||||
MINUS : '-';
|
||||
|
||||
SPACE : ' ';
|
||||
|
||||
PERIOD : '.';
|
||||
|
||||
COMMA : ',';
|
||||
|
||||
PLUS : '+';
|
||||
|
||||
SLASH : '/';
|
||||
|
||||
CR : '\r'{$channel=HIDDEN;};
|
||||
|
||||
NEWLINE : '\n'{$channel=HIDDEN;};
|
||||
//NEWLINE : '\n'{$channel=HIDDEN;};
|
||||
|
||||
@@ -28,7 +28,7 @@ DaTe[1968]
|
||||
PlaCe[]
|
||||
|
||||
|
||||
REsult[Black wins by four points]
|
||||
REsult[B+4]
|
||||
|
||||
|
||||
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) {
|
||||
GameState gameState = new GameState(gameConfig);
|
||||
GameRecord gameRecord = new GameRecord(gameConfig);
|
||||
|
||||
System.out.println("Game started.");
|
||||
|
||||
try {
|
||||
while (!gameState.isTerminal()) {
|
||||
while (!gameRecord.isFinished()) {
|
||||
GameState gameState = gameRecord.getGameState(gameRecord.getNumTurns());
|
||||
System.out.println(gameState);
|
||||
|
||||
Player currentPlayer = gameState.getPlayerToMove();
|
||||
Action action = getPolicy(currentPlayer).getAction(gameConfig,
|
||||
gameState, currentPlayer);
|
||||
gameState.playStone(currentPlayer, action);
|
||||
Player playerToMove = gameRecord.getPlayerToMove();
|
||||
Policy policy = getPolicy(playerToMove);
|
||||
Action action = policy.getAction(gameConfig,
|
||||
gameState, playerToMove);
|
||||
|
||||
if (gameRecord.play(playerToMove, action)) {
|
||||
policy.setState(gameRecord.getGameState(gameRecord.getNumTurns()));
|
||||
} else {
|
||||
System.out.println("Move rejected - try again.");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
System.out
|
||||
@@ -56,7 +63,7 @@ public class Referee {
|
||||
return GameResult.VOID;
|
||||
}
|
||||
|
||||
GameResult result = gameState.getResult();
|
||||
GameResult result = gameRecord.getResult();
|
||||
|
||||
System.out.println("Game over. Result: " + result);
|
||||
|
||||
@@ -68,7 +75,7 @@ public class Referee {
|
||||
+ ".sgf");
|
||||
FileOutputStream fos = new FileOutputStream(sgfFile);
|
||||
try {
|
||||
SGFWriter.writeSGF(gameState, fos);
|
||||
SGFWriter.write(fos, gameRecord);
|
||||
System.out
|
||||
.println("Game saved as " + sgfFile.getAbsolutePath());
|
||||
} finally {
|
||||
|
||||
@@ -2,21 +2,45 @@ package net.woodyfolsom.msproj;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import net.woodyfolsom.msproj.sgf.SGFIdentifier;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
public class SGFWriter {
|
||||
|
||||
public static void writeSGF(GameState gameState, OutputStream os)
|
||||
public static void write(OutputStream os, GameRecord gameRecord)
|
||||
throws IOException {
|
||||
writeNode(os, SGFIdentifier.FILE_FORMAT, Integer.valueOf(4));
|
||||
}
|
||||
OutputStreamWriter writer = new OutputStreamWriter(os);
|
||||
|
||||
private static void writeNode(OutputStream os, SGFIdentifier sgfIdent,
|
||||
Object nodeValue) throws IOException {
|
||||
os.write(sgfIdent.toString().getBytes());
|
||||
os.write("[".getBytes());
|
||||
os.write(nodeValue.toString().getBytes());
|
||||
os.write("];".getBytes());
|
||||
writer.write("(");
|
||||
|
||||
writer.write(";FF[4]GM[1]");
|
||||
|
||||
GameConfig gameConfig = gameRecord.getGameConfig();
|
||||
|
||||
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;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
|
||||
public class Goban extends JFrame implements KeyListener {
|
||||
public class Goban extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
//private GameState gameState;
|
||||
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) {
|
||||
setLayout(new BorderLayout());
|
||||
this.gridPanel = new GridPanel(gameConfig, guiPlayer);
|
||||
add(gridPanel,BorderLayout.CENTER);
|
||||
addKeyListener(this);
|
||||
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -45,31 +60,4 @@ public class Goban extends JFrame implements KeyListener {
|
||||
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() {
|
||||
int timeLimit = 10;
|
||||
int timeLimit = 30;
|
||||
TimeUnit timeUnit = TimeUnit.SECONDS;
|
||||
|
||||
try {
|
||||
@@ -212,6 +216,7 @@ public class GridPanel extends JPanel implements MouseListener,
|
||||
|
||||
public void setGameState(GameState gameState) {
|
||||
this.gameState = gameState;
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -176,4 +176,10 @@ public class AlphaBeta implements Policy {
|
||||
throw new UnsupportedOperationException(
|
||||
"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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
@@ -20,7 +19,6 @@ public class HumanGuiInput implements Policy {
|
||||
public Action getAction(GameConfig gameConfig, GameState gameState,
|
||||
Player player) {
|
||||
Action action = null;
|
||||
String input = "";
|
||||
|
||||
do {
|
||||
System.out.println(player
|
||||
@@ -30,8 +28,6 @@ public class HumanGuiInput implements Policy {
|
||||
action = goban.getAction();
|
||||
|
||||
if (action.isNone()) {
|
||||
System.out.println("No move was made within 10 seconds. Hurry up!");
|
||||
System.out.println(gameState);
|
||||
continue;
|
||||
}
|
||||
} while (action == null);
|
||||
@@ -51,4 +47,9 @@ public class HumanGuiInput implements Policy {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(GameState gameState) {
|
||||
goban.setGameState(gameState);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -70,4 +70,10 @@ public class HumanKeyboardInput implements Policy {
|
||||
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(
|
||||
"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;
|
||||
|
||||
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 Policy movePolicy;
|
||||
@@ -113,10 +113,6 @@ public abstract class MonteCarlo implements Policy {
|
||||
return searchTimeLimit;
|
||||
}
|
||||
|
||||
public int doRollout() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getNumStateEvaluations() {
|
||||
return numStateEvaluations;
|
||||
}
|
||||
|
||||
@@ -196,4 +196,10 @@ public class MonteCarloUCT extends MonteCarlo {
|
||||
public String toString() {
|
||||
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);
|
||||
|
||||
public int getNumStateEvaluations();
|
||||
|
||||
public void setState(GameState gameState);
|
||||
}
|
||||
@@ -83,4 +83,10 @@ public class RandomMovePolicy implements Policy, ActionGenerator {
|
||||
Player player) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(GameState gameState) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
T__20=20
|
||||
T__21=21
|
||||
T__22=22
|
||||
T__23=23
|
||||
@@ -24,46 +25,68 @@ T__43=43
|
||||
T__44=44
|
||||
T__45=45
|
||||
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
|
||||
COMMA=5
|
||||
CR=6
|
||||
DIGIT=7
|
||||
LBRACKET=8
|
||||
LCLETTER=9
|
||||
LPAREN=10
|
||||
MINUS=11
|
||||
NEWLINE=12
|
||||
PERIOD=13
|
||||
PLUS=14
|
||||
RBRACKET=15
|
||||
RPAREN=16
|
||||
SEMICOLON=17
|
||||
SLASH=18
|
||||
SPACE=19
|
||||
UCLETTER=20
|
||||
'AB'=21
|
||||
'AP'=22
|
||||
'AW'=23
|
||||
'B'=24
|
||||
'BC'=25
|
||||
'BR'=26
|
||||
'CA'=27
|
||||
'CP'=28
|
||||
'DT'=29
|
||||
'EV'=30
|
||||
'FF'=31
|
||||
'GM'=32
|
||||
'KM'=33
|
||||
'PB'=34
|
||||
'PC'=35
|
||||
'PW'=36
|
||||
'R'=37
|
||||
'RE'=38
|
||||
'RU'=39
|
||||
'SO'=40
|
||||
'SZ'=41
|
||||
'TM'=42
|
||||
'US'=43
|
||||
'W'=44
|
||||
'WC'=45
|
||||
'WR'=46
|
||||
DIGIT=6
|
||||
LBRACKET=7
|
||||
LCLETTER=8
|
||||
LPAREN=9
|
||||
MINUS=10
|
||||
PERIOD=11
|
||||
PLUS=12
|
||||
RBRACKET=13
|
||||
RPAREN=14
|
||||
SEMICOLON=15
|
||||
SLASH=16
|
||||
SPACE=17
|
||||
STRVALUE=18
|
||||
UCLETTER=19
|
||||
'AB'=20
|
||||
'AP'=21
|
||||
'AW'=22
|
||||
'B'=23
|
||||
'BC'=24
|
||||
'BR'=25
|
||||
'Black'=26
|
||||
'C'=27
|
||||
'CA'=28
|
||||
'CP'=29
|
||||
'DT'=30
|
||||
'DaTe'=31
|
||||
'EV'=32
|
||||
'EVent'=33
|
||||
'FF'=34
|
||||
'GM'=35
|
||||
'GaMe'=36
|
||||
'KM'=37
|
||||
'PB'=38
|
||||
'PC'=39
|
||||
'PW'=40
|
||||
'PlaCe'=41
|
||||
'PlayerBlack'=42
|
||||
'PlayerWhite'=43
|
||||
'RE'=44
|
||||
'REsult'=45
|
||||
'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();
|
||||
}
|
||||
|
||||
public String toLateXmoves(Player player) {
|
||||
public String toLateXmoves(Player player, int boardSize) {
|
||||
StringBuilder latexSB = new StringBuilder();
|
||||
SGFNode.TYPE nodeType;
|
||||
SGFIdentifier sgfIdent;
|
||||
@@ -73,7 +73,8 @@ public class SGFGameTree {
|
||||
} else {
|
||||
latexSB.append(column);
|
||||
}
|
||||
latexSB.append(19 - sgfCoord.getRow() + 'a');
|
||||
char row = sgfCoord.getRow();
|
||||
latexSB.append(boardSize - row + 'a');
|
||||
nMoves++;
|
||||
}
|
||||
if (nMoves == 0) {
|
||||
@@ -83,7 +84,20 @@ public class SGFGameTree {
|
||||
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();
|
||||
|
||||
// Somewhat convoluted logic here because the grammar does not require
|
||||
@@ -97,7 +111,7 @@ public class SGFGameTree {
|
||||
case ROOT:
|
||||
latexSB.append("\\gobansize");
|
||||
latexSB.append("{");
|
||||
latexSB.append(node.getFirstValue(SGFIdentifier.SIZE));
|
||||
latexSB.append(boardSize);
|
||||
latexSB.append("}\n");
|
||||
latexSB.append("\\shortstack{\\showfullgoban\\\\");
|
||||
SGFResult result = (SGFResult) node.getFirstValue(
|
||||
@@ -120,4 +134,15 @@ public class SGFGameTree {
|
||||
sgfFormatString.append(")");
|
||||
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 static final SGFIdentifier ADD_BLACK = new SGFIdentifier("AB");
|
||||
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 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 GAME = new SGFIdentifier("GM");
|
||||
public static final SGFIdentifier KOMI = new SGFIdentifier("KM");
|
||||
public static final SGFIdentifier MOVE_BLACK = new SGFIdentifier("B");
|
||||
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 RULES = new SGFIdentifier("RU");
|
||||
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 VIEW = new SGFIdentifier("VW");
|
||||
|
||||
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 enum TYPE {
|
||||
ROOT, MOVE_BLACK, MOVE_WHITE, EMPTY
|
||||
ROOT, MOVE_BLACK, MOVE_WHITE, EMPTY, COMMENT
|
||||
}
|
||||
|
||||
private List<SGFProperty> properties = new ArrayList<SGFProperty>();
|
||||
@@ -18,6 +18,8 @@ public class SGFNode {
|
||||
type = TYPE.MOVE_BLACK;
|
||||
} else if (sgfIdent == SGFIdentifier.MOVE_WHITE) {
|
||||
type = TYPE.MOVE_WHITE;
|
||||
} else if (sgfIdent == SGFIdentifier.COMMENT) {
|
||||
type = TYPE.COMMENT;
|
||||
} else {
|
||||
type = TYPE.ROOT;
|
||||
}
|
||||
@@ -59,4 +61,14 @@ public class SGFNode {
|
||||
|
||||
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("");
|
||||
SGFGameTree gameTree = gameTrees.get(0);
|
||||
|
||||
latexFormatString.append(gameTree.toLateXmoves(Player.BLACK));
|
||||
latexFormatString.append(gameTree.toLateXmoves(Player.WHITE));
|
||||
int boardSize = gameTree.getBoardSize();
|
||||
latexFormatString.append(gameTree.toLateXmoves(Player.BLACK, boardSize));
|
||||
latexFormatString.append(gameTree.toLateXmoves(Player.WHITE, boardSize));
|
||||
latexFormatString.append("\\begin{center}\n");
|
||||
latexFormatString.append(gameTree.toLateX());
|
||||
latexFormatString.append(gameTree.toLateX(boardSize));
|
||||
latexFormatString.append("\\end{center}");
|
||||
|
||||
return latexFormatString.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is an alias for toString().
|
||||
* @return
|
||||
*/
|
||||
public String toSGF() {
|
||||
String sgfFormatString = "";
|
||||
for (SGFGameTree gameTree : gameTrees) {
|
||||
sgfFormatString += gameTree.toSGF();
|
||||
}
|
||||
return sgfFormatString;
|
||||
return toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@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);
|
||||
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("");
|
||||
|
||||
}
|
||||
|
||||
@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