Fixed invalid move by Monte Carlo UCT. Still does not handle player's PASS.
This commit is contained in:
@@ -7,17 +7,20 @@ public class GameState {
|
||||
private int blackPrisoners = 0;
|
||||
private int whitePrisoners = 0;
|
||||
private GameBoard gameBoard;
|
||||
private Player playerToMove;
|
||||
|
||||
public GameState(int size) {
|
||||
if (size < 1 || size > 19) {
|
||||
throw new IllegalArgumentException("Invalid board size: " + size);
|
||||
}
|
||||
gameBoard = new GameBoard(size);
|
||||
playerToMove = Player.BLACK;
|
||||
}
|
||||
|
||||
public GameState(GameState that) {
|
||||
this.blackPrisoners = that.blackPrisoners;
|
||||
this.whitePrisoners = that.whitePrisoners;
|
||||
this.playerToMove = that.playerToMove;
|
||||
gameBoard = new GameBoard(that.gameBoard);
|
||||
}
|
||||
|
||||
@@ -25,6 +28,7 @@ public class GameState {
|
||||
blackPrisoners = 0;
|
||||
whitePrisoners = 0;
|
||||
gameBoard.clear();
|
||||
playerToMove = Player.BLACK;
|
||||
}
|
||||
|
||||
public int getBlackPrisoners() {
|
||||
@@ -49,6 +53,10 @@ public class GameState {
|
||||
return gameBoard;
|
||||
}
|
||||
|
||||
public Player getPlayerToMove() {
|
||||
return playerToMove;
|
||||
}
|
||||
|
||||
public int getWhitePrisoners() {
|
||||
return whitePrisoners;
|
||||
}
|
||||
@@ -72,12 +80,16 @@ public class GameState {
|
||||
* @return
|
||||
*/
|
||||
public boolean playStone(Player player, Action action) {
|
||||
if (player != playerToMove) {
|
||||
throw new IllegalArgumentException("Requested " + player + " move, but it is " + playerToMove +"'s turn!");
|
||||
}
|
||||
|
||||
if (player == Player.NONE) {
|
||||
throw new IllegalArgumentException("Cannot play as " + player);
|
||||
}
|
||||
|
||||
if (action.isPass()) {
|
||||
playerToMove = GoGame.getNextPlayer(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -189,6 +201,7 @@ public class GameState {
|
||||
return false;
|
||||
} else {
|
||||
//assertCorrectHash();
|
||||
playerToMove = GoGame.getNextPlayer(player);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,8 +139,8 @@ public class GoGame implements Runnable {
|
||||
localOutput.println("=\n");
|
||||
break;
|
||||
case genmove:
|
||||
LOGGER.info("Generating move for:\n" + gameState);
|
||||
|
||||
System.out.println("Generating move for:\n" + gameState);
|
||||
System.out.println("It is currently " + gameState.getPlayerToMove() + "'s turn.");
|
||||
String playerName = cmd.getStringField(1);
|
||||
|
||||
Player player;
|
||||
@@ -224,6 +224,8 @@ public class GoGame implements Runnable {
|
||||
|
||||
executeCommand(cmd);
|
||||
|
||||
System.out.println("It is now " + gameState.getPlayerToMove() + "'s turn.\n");
|
||||
|
||||
if (cmd.getType() == Command.TYPE.genmove) {
|
||||
System.out.println("New game state:\n" + gameState);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,9 @@ public abstract class MonteCarlo implements Policy {
|
||||
Player player) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
if (gameState.getPlayerToMove() != player) {
|
||||
throw new RuntimeException("getAction(..." + player +") was requested but GameState.playerToMove was " + gameState.getPlayerToMove());
|
||||
}
|
||||
//If for some reason no moves are evaluated within the time limit, pass.
|
||||
//Note that this may lose the game by forfeit even when picking any random move could
|
||||
//result in a win.
|
||||
@@ -51,10 +54,10 @@ public abstract class MonteCarlo implements Policy {
|
||||
List<GameTreeNode<MonteCarloProperties>> selectedNodes = descend(rootNode);
|
||||
List<GameTreeNode<MonteCarloProperties>> newLeaves = new ArrayList<GameTreeNode<MonteCarloProperties>>();
|
||||
|
||||
Player nextPlayer = GoGame.getNextPlayer(player);
|
||||
|
||||
for (GameTreeNode<MonteCarloProperties> selectedNode: selectedNodes) {
|
||||
for (GameTreeNode<MonteCarloProperties> newLeaf : grow(gameConfig, selectedNode, nextPlayer)) {
|
||||
Player playerToMove = selectedNode.getGameState().getPlayerToMove();
|
||||
|
||||
for (GameTreeNode<MonteCarloProperties> newLeaf : grow(gameConfig, selectedNode, playerToMove)) {
|
||||
newLeaves.add(newLeaf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public class MonteCarloUCT extends MonteCarlo {
|
||||
GameTreeNode<MonteCarloProperties> bestNode = node;
|
||||
|
||||
//What if the optimum leaf node is actually a terminal node?
|
||||
//Grom Kocsis and Szepesvari, the value of an actual terminal node is 0, so it will never be grown.
|
||||
//From Kocsis and Szepesvari, the value of an actual terminal node is 0, so it will never be grown.
|
||||
|
||||
double nodeVisits = node.getProperties().getVisits();
|
||||
|
||||
@@ -74,13 +74,13 @@ public class MonteCarloUCT extends MonteCarlo {
|
||||
|
||||
@Override
|
||||
public List<GameTreeNode<MonteCarloProperties>> grow(GameConfig gameConfig, GameTreeNode<MonteCarloProperties> node, Player player) {
|
||||
GameState nextGameState = new GameState(node.getGameState());
|
||||
Policy randomMovePolicy = new RandomMovePolicy();
|
||||
Set<Action> exploredActions = node.getActions();
|
||||
Action action = randomMovePolicy.getAction(gameConfig, node.getGameState(), exploredActions, player);
|
||||
if (Action.NONE == action) {
|
||||
throw new RuntimeException("Unable to grow node - are all actions already explored? Board state: " + node.getGameState() + "\nExplored actions: " + exploredActions);
|
||||
}
|
||||
GameState nextGameState = new GameState(node.getGameState());
|
||||
nextGameState.playStone(player, action);
|
||||
List<GameTreeNode<MonteCarloProperties>> newChildren = new ArrayList<GameTreeNode<MonteCarloProperties>>();
|
||||
GameTreeNode<MonteCarloProperties> newChild = new GameTreeNode<MonteCarloProperties>(nextGameState,new MonteCarloProperties());
|
||||
@@ -92,23 +92,23 @@ public class MonteCarloUCT extends MonteCarlo {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
/**
|
||||
* Rollout currently depends on the hardcoded ROLLOUT_DEPTH_LIMIT superclass parameter,
|
||||
* since without (super)ko detection, there is no way to guarantee a rollout will terminate.
|
||||
* Even with ko detection, a rollout might take an unrealistically long time due to unlikely playouts.
|
||||
* Even with super-ko detection, a rollout might take an unrealistically long time due to unlikely playouts.
|
||||
*/
|
||||
public int rollout(GameConfig gameConfig, StateEvaluator stateEvaluator, GameTreeNode<MonteCarloProperties> node, Player player) {
|
||||
Policy randomMovePolicy = new RandomMovePolicy();
|
||||
|
||||
Action action;
|
||||
int rolloutDepth = 0;
|
||||
GameState finalGameState = new GameState(node.getGameState());
|
||||
Player currentPlayer = player;
|
||||
GameState rolloutGameState = new GameState(node.getGameState());
|
||||
Player currentPlayer = rolloutGameState.getPlayerToMove();
|
||||
do {
|
||||
rolloutDepth++;
|
||||
action = randomMovePolicy.getAction(gameConfig, finalGameState, currentPlayer);
|
||||
action = randomMovePolicy.getAction(gameConfig, rolloutGameState, currentPlayer);
|
||||
if (action != Action.NONE) {
|
||||
if (!finalGameState.playStone(currentPlayer, action)) {
|
||||
if (!rolloutGameState.playStone(currentPlayer, action)) {
|
||||
throw new RuntimeException("Failed to play move selected by RandomMovePolicy");
|
||||
}
|
||||
currentPlayer = GoGame.getNextPlayer(currentPlayer);
|
||||
@@ -117,7 +117,7 @@ public class MonteCarloUCT extends MonteCarlo {
|
||||
|
||||
numStateEvaluations++;
|
||||
|
||||
if (stateEvaluator.scoreGame(finalGameState).isWinner(player)) {
|
||||
if (stateEvaluator.scoreGame(rolloutGameState).isWinner(player)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
|
||||
@@ -34,6 +34,10 @@ public class RandomMovePolicy implements Policy, ActionGenerator {
|
||||
*/
|
||||
public List<Action> getActions(GameConfig gameConfig, GameState gameState,
|
||||
Collection<Action> prohibitedMoves, Player player, int nMoves) {
|
||||
if (player != gameState.getPlayerToMove()) {
|
||||
throw new IllegalArgumentException("It is not " + player + "'s turn to move!");
|
||||
}
|
||||
|
||||
GameState gameStateCopy = new GameState(gameState);
|
||||
ActionGenerator actionGenerator = new ValidMoveGenerator();
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
T__19=19
|
||||
T__20=20
|
||||
T__21=21
|
||||
T__22=22
|
||||
T__23=23
|
||||
@@ -19,39 +17,53 @@ T__36=36
|
||||
T__37=37
|
||||
T__38=38
|
||||
T__39=39
|
||||
T__40=40
|
||||
T__41=41
|
||||
T__42=42
|
||||
T__43=43
|
||||
T__44=44
|
||||
T__45=45
|
||||
T__46=46
|
||||
COLON=4
|
||||
COMMA=5
|
||||
DIGIT=6
|
||||
LBRACKET=7
|
||||
LCLETTER=8
|
||||
LPAREN=9
|
||||
MINUS=10
|
||||
PERIOD=11
|
||||
PLUS=12
|
||||
RBRACKET=13
|
||||
RPAREN=14
|
||||
SEMICOLON=15
|
||||
SLASH=16
|
||||
SPACE=17
|
||||
UCLETTER=18
|
||||
'AB'=19
|
||||
'AP'=20
|
||||
'BC'=21
|
||||
'BR'=22
|
||||
'CA'=23
|
||||
'CP'=24
|
||||
'EV'=25
|
||||
'FF'=26
|
||||
'GM'=27
|
||||
'KM'=28
|
||||
'PB'=29
|
||||
'PC'=30
|
||||
'PW'=31
|
||||
'RE'=32
|
||||
'RU'=33
|
||||
'SO'=34
|
||||
'SZ'=35
|
||||
'TM'=36
|
||||
'US'=37
|
||||
'WC'=38
|
||||
'WR'=39
|
||||
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
|
||||
|
||||
27
src/net/woodyfolsom/msproj/sgf/SGFCoord.java
Normal file
27
src/net/woodyfolsom/msproj/sgf/SGFCoord.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package net.woodyfolsom.msproj.sgf;
|
||||
|
||||
public class SGFCoord {
|
||||
private char column;
|
||||
private char row;
|
||||
|
||||
public SGFCoord(String coords) {
|
||||
if (coords == null || coords.length() != 2) {
|
||||
throw new IllegalArgumentException(coords);
|
||||
}
|
||||
column = coords.charAt(0);
|
||||
row = coords.charAt(1);
|
||||
}
|
||||
|
||||
public SGFCoord(char column, char row) {
|
||||
this.column = column;
|
||||
this.row = row;
|
||||
}
|
||||
|
||||
public char getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
public char getRow() {
|
||||
return row;
|
||||
}
|
||||
}
|
||||
35
src/net/woodyfolsom/msproj/sgf/SGFGameTree.java
Normal file
35
src/net/woodyfolsom/msproj/sgf/SGFGameTree.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package net.woodyfolsom.msproj.sgf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class SGFGameTree {
|
||||
private List<SGFNode> nodeSequence = new ArrayList<SGFNode>();
|
||||
private List<SGFGameTree> subTrees = new ArrayList<SGFGameTree>();
|
||||
|
||||
|
||||
public int getNodeCount() {
|
||||
return nodeSequence.size();
|
||||
}
|
||||
|
||||
public List<SGFNode> getNodeSequence() {
|
||||
return Collections.unmodifiableList(nodeSequence);
|
||||
}
|
||||
|
||||
public void setNodeSequence(List<SGFNode> nodeSequence) {
|
||||
this.nodeSequence.clear();
|
||||
|
||||
for(SGFNode node : nodeSequence) {
|
||||
this.nodeSequence.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
public void addSubTree(SGFGameTree subTree) {
|
||||
subTrees.add(subTree);
|
||||
}
|
||||
|
||||
public int getSubTreeCount() {
|
||||
return subTrees.size();
|
||||
}
|
||||
}
|
||||
26
src/net/woodyfolsom/msproj/sgf/SGFIdentifier.java
Normal file
26
src/net/woodyfolsom/msproj/sgf/SGFIdentifier.java
Normal file
@@ -0,0 +1,26 @@
|
||||
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 CHARSET = new SGFIdentifier("CA");
|
||||
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 RESULT = new SGFIdentifier("RE");
|
||||
public static final SGFIdentifier SIZE = new SGFIdentifier("SZ");
|
||||
public static final SGFIdentifier TIME = new SGFIdentifier("TM");
|
||||
|
||||
private String text;
|
||||
|
||||
private SGFIdentifier(String value) {
|
||||
this.text = value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
16
src/net/woodyfolsom/msproj/sgf/SGFNode.java
Normal file
16
src/net/woodyfolsom/msproj/sgf/SGFNode.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package net.woodyfolsom.msproj.sgf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SGFNode {
|
||||
private List<SGFProperty> properties = new ArrayList<SGFProperty>();
|
||||
|
||||
public void addProperty(SGFProperty property) {
|
||||
properties.add(property);
|
||||
}
|
||||
|
||||
public int getPropertyCount() {
|
||||
return properties.size();
|
||||
}
|
||||
}
|
||||
25
src/net/woodyfolsom/msproj/sgf/SGFNodeCollection.java
Normal file
25
src/net/woodyfolsom/msproj/sgf/SGFNodeCollection.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package net.woodyfolsom.msproj.sgf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SGFNodeCollection {
|
||||
private List<SGFGameTree> gameTrees = new ArrayList<SGFGameTree>();
|
||||
|
||||
public void add(SGFGameTree gameTree) {
|
||||
gameTrees.add(gameTree);
|
||||
}
|
||||
|
||||
public SGFGameTree getGameTree(int index) {
|
||||
return gameTrees.get(index);
|
||||
}
|
||||
|
||||
public int getGameTreeCount() {
|
||||
return gameTrees.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "foo";
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
37
src/net/woodyfolsom/msproj/sgf/SGFPlayer.java
Normal file
37
src/net/woodyfolsom/msproj/sgf/SGFPlayer.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package net.woodyfolsom.msproj.sgf;
|
||||
|
||||
public class SGFPlayer {
|
||||
public static final SGFPlayer BLACK = new SGFPlayer("Black");
|
||||
public static final SGFPlayer WHITE = new SGFPlayer("White");
|
||||
|
||||
private String color;
|
||||
|
||||
public static SGFPlayer getInstance(String color) {
|
||||
if ("B".equals(color)) {
|
||||
return BLACK;
|
||||
} else if ("W".equals(color)) {
|
||||
return WHITE;
|
||||
} else {
|
||||
throw new IllegalArgumentException(color);
|
||||
}
|
||||
}
|
||||
|
||||
private SGFPlayer(String color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (this == BLACK) {
|
||||
return "B";
|
||||
} else if (this == WHITE){
|
||||
return "W";
|
||||
} else {
|
||||
throw new RuntimeException("Invalid player");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,26 @@
|
||||
package net.woodyfolsom.msproj.sgf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class SGFProperty {
|
||||
private StrIdent ident;
|
||||
private StrValue value;
|
||||
private SGFIdentifier ident;
|
||||
private List<SGFValue<?>> values = new ArrayList<SGFValue<?>>();
|
||||
|
||||
public StrIdent getIdent() {
|
||||
public void addValue(SGFValue<?> value) {
|
||||
this.values.add(value);
|
||||
}
|
||||
|
||||
public SGFIdentifier getIdentifier() {
|
||||
return ident;
|
||||
}
|
||||
|
||||
public StrValue getValue() {
|
||||
return value;
|
||||
public List<SGFValue<?>> getValues() {
|
||||
return Collections.unmodifiableList(values);
|
||||
}
|
||||
|
||||
public void setIdent(StrIdent ident) {
|
||||
public void setIdentifier(SGFIdentifier ident) {
|
||||
this.ident = ident;
|
||||
}
|
||||
|
||||
public void setValue(StrValue value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
31
src/net/woodyfolsom/msproj/sgf/SGFResult.java
Normal file
31
src/net/woodyfolsom/msproj/sgf/SGFResult.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package net.woodyfolsom.msproj.sgf;
|
||||
|
||||
public class SGFResult {
|
||||
private boolean resignation = false;
|
||||
private boolean tie;
|
||||
private double score;
|
||||
private SGFPlayer winner;
|
||||
|
||||
public SGFResult(String value) {
|
||||
String[] params = value.split("\\+");
|
||||
|
||||
winner = SGFPlayer.getInstance(params[0]);
|
||||
|
||||
if ("R".equals(params[1])) {
|
||||
resignation = true;
|
||||
} else {
|
||||
score = Double.parseDouble(params[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (resignation == false && tie == false) {
|
||||
return winner.toString() + "+" + score;
|
||||
} else if (resignation == true && tie == false) {
|
||||
return winner.toString() + "+R";
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/net/woodyfolsom/msproj/sgf/SGFValue.java
Normal file
21
src/net/woodyfolsom/msproj/sgf/SGFValue.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package net.woodyfolsom.msproj.sgf;
|
||||
|
||||
public class SGFValue<T> {
|
||||
public static final SGFValue<String> EMPTY = new SGFValue<String>("");
|
||||
|
||||
private String text;
|
||||
private T value;
|
||||
|
||||
public SGFValue(T value) {
|
||||
this.text = value.toString();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import java.util.Set;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
|
||||
public class GameTreeNode<T extends GameTreeNodeProperties> {
|
||||
private GameState gameState;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.woodyfolsom.msproj;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -9,8 +10,14 @@ public class LegalMoveTest {
|
||||
public void testLegalMove1Liberty() {
|
||||
GameState gameState = new GameState(5);
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A2"));
|
||||
assertEquals(Player.WHITE, gameState.getPlayerToMove());
|
||||
gameState.playStone(Player.WHITE, Action.PASS);
|
||||
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B3"));
|
||||
gameState.playStone(Player.WHITE, Action.PASS);
|
||||
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B1"));
|
||||
|
||||
assertTrue(gameState.playStone(Player.WHITE, Action.getInstance("B2")));
|
||||
System.out.println(gameState);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
@@ -54,4 +55,25 @@ public class MonteCarloUCTTest {
|
||||
|
||||
System.out.println(gameState);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIllegalMoveRejection() {
|
||||
Policy treeSearch = new MonteCarloUCT(new RandomMovePolicy(),2000L);
|
||||
GameState gameState = new GameState(4);
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("B1"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("C2"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("B3"));
|
||||
|
||||
Action move;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
move = treeSearch.getAction(new GameConfig(), gameState, Player.BLACK);
|
||||
System.out.println("Generated move: " + move);
|
||||
GameState stateCopy = new GameState(gameState);
|
||||
stateCopy.playStone(Player.BLACK, move);
|
||||
System.out.println(stateCopy);
|
||||
assertFalse(Action.getInstance("B2").equals(move));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user