Refactoring in progress.
Player and Action classes are now singletons (factory pattern) rather than String values. Implementing more general treesearch code for minimax, alpha-beta, monte carlo using simplified backup logic.
This commit is contained in:
73
src/net/woodyfolsom/msproj/Action.java
Normal file
73
src/net/woodyfolsom/msproj/Action.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package net.woodyfolsom.msproj;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Action {
|
||||
private static final Map<String, Action> actionMap = new HashMap<String,Action>();
|
||||
|
||||
private char column = 'x';
|
||||
private int row = 0;
|
||||
|
||||
//private Player player;
|
||||
private String move;
|
||||
|
||||
public static final Action NONE = new Action("NONE", /*Player.NONE,*/ 'x', 0);
|
||||
public static final Action PASS = new Action("PASS", /*Player.NONE,*/ 'x', 0);
|
||||
|
||||
private Action(String move, /*Player player,*/ char column, int row) {
|
||||
this.move = move;
|
||||
//this.player = player;
|
||||
this.column = column;
|
||||
this.row = row;
|
||||
}
|
||||
|
||||
public static final Action getInstance(/*String playerName,*/ String move) {
|
||||
if (move == null || "NONE".equals(move) || "PASS".equals(move)) {
|
||||
throw new IllegalArgumentException("Illegal move: " + move);
|
||||
}
|
||||
|
||||
if (actionMap.containsKey(move)) {
|
||||
return actionMap.get(move);
|
||||
}
|
||||
|
||||
/*
|
||||
Player player;
|
||||
if ("b".equals(playerName)) {
|
||||
player = Player.BLACK;
|
||||
} else if ("w".equals(playerName)) {
|
||||
player = Player.WHITE;
|
||||
} else {
|
||||
return Action.NONE;
|
||||
}*/
|
||||
|
||||
char col = move.charAt(0);
|
||||
int row = Integer.valueOf(move.substring(1));
|
||||
|
||||
Action action = new Action(move, col, row);
|
||||
actionMap.put(move, action);
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
public char getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
public int getRow() {
|
||||
return row;
|
||||
}
|
||||
|
||||
public boolean isNone() {
|
||||
return this == Action.NONE;
|
||||
}
|
||||
|
||||
public boolean isPass() {
|
||||
return this == Action.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return move;
|
||||
}
|
||||
}
|
||||
@@ -28,11 +28,11 @@ public class GameScore {
|
||||
return NORMALIZED_ZERO_SCORE + 2 * blackScore - ((int)(2 * (whiteScore + komi)));
|
||||
}
|
||||
|
||||
public double getScore(String color) {
|
||||
if ("w".equals(color)) {
|
||||
return getWhiteScore();
|
||||
} else if ("b".equals(color)) {
|
||||
public double getScore(Player color) {
|
||||
if (color == Player.BLACK) {
|
||||
return getBlackScore();
|
||||
} else if (color == Player.WHITE) {
|
||||
return getWhiteScore();
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
@@ -42,6 +42,14 @@ public class GameScore {
|
||||
return (double)whiteScore + komi;
|
||||
}
|
||||
|
||||
public boolean isWinner(String color) {
|
||||
if ("w".equals(color)) {
|
||||
return getWhiteScore() < NORMALIZED_ZERO_SCORE;
|
||||
} else {
|
||||
return getBlackScore() > NORMALIZED_ZERO_SCORE;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "B: " + blackScore + "W: "+ whiteScore+"K:" + komi;
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@ package net.woodyfolsom.msproj;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.woodyfolsom.msproj.policy.Policy;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
||||
@@ -60,28 +58,19 @@ public class GameState {
|
||||
return whitePrisoners;
|
||||
}
|
||||
|
||||
public boolean playStone(String player, String coord) {
|
||||
public boolean playStone(Player player, String move) {
|
||||
//Opponent passes? Just ignore it.
|
||||
if (Policy.PASS.equalsIgnoreCase(coord)) {
|
||||
Action action = Action.getInstance(move);
|
||||
|
||||
if (action.isPass()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//LOGGER.info("Playing " + player + " at " + coord);
|
||||
|
||||
char stoneColor;
|
||||
if ("b".equals(player)) {
|
||||
stoneColor = GameBoard.BLACK_STONE;
|
||||
} else if ("w".equals(player)) {
|
||||
stoneColor = GameBoard.WHITE_STONE;
|
||||
} else {
|
||||
if (action.isNone()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char col = coord.charAt(0);
|
||||
int row = Integer.valueOf(coord.substring(1));
|
||||
|
||||
//LOGGER.info("Playing " + stoneColor + " at " + col + row);
|
||||
return playStone(col,row, stoneColor);
|
||||
return playStone(player, action);
|
||||
}
|
||||
/**
|
||||
* Places a stone at the requested coordinate. Placement is legal if the
|
||||
@@ -97,20 +86,22 @@ public class GameState {
|
||||
* @param stone
|
||||
* @return
|
||||
*/
|
||||
public boolean playStone(char colLabel, int rowNum, char stoneSymbol) {
|
||||
char currentStone = gameBoard.getSymbolAt(colLabel, rowNum);
|
||||
public boolean playStone(Player player, Action action) {
|
||||
char currentStone = gameBoard.getSymbolAt(action.getColumn(), action.getRow());
|
||||
|
||||
if (currentStone != GameBoard.EMPTY_INTERSECTION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Place stone as requested, then check for (1) captured neighbors and (2) illegal move due to 0 liberties.
|
||||
gameBoard.setSymbolAt(colLabel, rowNum, stoneSymbol);
|
||||
char stoneSymbol = player.getStoneSymbol();
|
||||
gameBoard.setSymbolAt(action.getColumn(), action.getRow(), stoneSymbol);
|
||||
|
||||
//look for captured adjacent groups and increment the prisoner counter
|
||||
char opponentSymbol = GameBoard.getOpponentSymbol(stoneSymbol);
|
||||
char opponentSymbol = GameBoard.getOpponentSymbol(player.getStoneSymbol());
|
||||
|
||||
int col = GameBoard.getColumnIndex(colLabel);
|
||||
int row = rowNum - 1;
|
||||
int col = GameBoard.getColumnIndex(action.getColumn());
|
||||
int row = action.getRow() - 1;
|
||||
|
||||
int prisonerCount = 0;
|
||||
if (col > 0 && gameBoard.getSymbolAt(col-1, row) == opponentSymbol) {
|
||||
@@ -153,8 +144,8 @@ public class GameState {
|
||||
}
|
||||
|
||||
//Moved test for 0 liberties until after attempting to capture neighboring groups.
|
||||
if (0 == LibertyCounter.countLiberties(gameBoard, colLabel, rowNum, stoneSymbol)) {
|
||||
gameBoard.removeStone(colLabel,rowNum);
|
||||
if (0 == LibertyCounter.countLiberties(gameBoard, action.getColumn(), action.getRow(), stoneSymbol)) {
|
||||
gameBoard.removeStone(action.getColumn(),action.getRow());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -77,14 +77,24 @@ public class GoGame {
|
||||
case genmove:
|
||||
LOGGER.info("Generating move for:\n" + gameState);
|
||||
|
||||
String player = cmd.getStringField(1);
|
||||
String nextMove = moveGenerator.getAction(gameConfig, gameState,
|
||||
String playerName = cmd.getStringField(1);
|
||||
|
||||
Player player;
|
||||
if ("b".equals(playerName)) {
|
||||
player = Player.BLACK;
|
||||
} else if ("w".equals(playerName)) {
|
||||
player = Player.WHITE;
|
||||
} else {
|
||||
throw new RuntimeException("Invalid player name - cannot generator move for:" + cmd);
|
||||
}
|
||||
|
||||
Action nextMove = moveGenerator.getAction(gameConfig, gameState,
|
||||
player);
|
||||
|
||||
gameState.playStone(player, nextMove);
|
||||
LOGGER.info(new StateEvaluator(gameConfig).scoreGame(gameState));
|
||||
System.out.println("="
|
||||
+ nextMove.toLowerCase() + "\n");
|
||||
+ nextMove.toString() + "\n");
|
||||
|
||||
break;
|
||||
case komi:
|
||||
@@ -109,7 +119,7 @@ public class GoGame {
|
||||
shutDown = true;
|
||||
break;
|
||||
case play:
|
||||
if (gameState.playStone(cmd.getStringField(1), cmd
|
||||
if (gameState.playStone(Player.getInstance(cmd.getStringField(1)), cmd
|
||||
.getStringField(2).toUpperCase())) {
|
||||
System.out.println("=\n");
|
||||
} else {
|
||||
@@ -147,4 +157,18 @@ public class GoGame {
|
||||
private static void configureLogging() {
|
||||
DOMConfigurator.configure("log4j.xml");
|
||||
}
|
||||
|
||||
public static Player getColorToPlay(Player player, boolean playAsOpponent) {
|
||||
if (playAsOpponent) {
|
||||
if (player == Player.WHITE) {
|
||||
return Player.BLACK;
|
||||
} else if (player == Player.BLACK) {
|
||||
return Player.WHITE;
|
||||
} else {
|
||||
return Player.NONE;
|
||||
}
|
||||
} else {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/net/woodyfolsom/msproj/Player.java
Normal file
38
src/net/woodyfolsom/msproj/Player.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package net.woodyfolsom.msproj;
|
||||
|
||||
public class Player {
|
||||
public static final Player BLACK = new Player("BLACK", GameBoard.BLACK_STONE);
|
||||
public static final Player NONE = new Player("NONE", GameBoard.EMPTY_INTERSECTION);
|
||||
public static final Player WHITE = new Player("WHITE", GameBoard.WHITE_STONE);
|
||||
|
||||
private char stoneSymbol;
|
||||
private String name;
|
||||
|
||||
private Player(String name, char stoneSymbol) {
|
||||
this.name = name;
|
||||
this.stoneSymbol = stoneSymbol;
|
||||
}
|
||||
|
||||
public static Player getInstance(String stoneSymbol) {
|
||||
if ("b".equals(stoneSymbol)) {
|
||||
return Player.BLACK;
|
||||
} else if ("w".equals(stoneSymbol)) {
|
||||
return Player.WHITE;
|
||||
} else {
|
||||
return Player.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
public char getStoneSymbol() {
|
||||
return stoneSymbol;
|
||||
}
|
||||
|
||||
public boolean isNone() {
|
||||
return "NONE".equals(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,14 @@ package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
|
||||
public interface ActionGenerator {
|
||||
public static final int ALL_ACTIONS = 0;
|
||||
|
||||
public List<String> getActions(GameConfig gameConfig, GameState gameState,
|
||||
String color, int numActions);
|
||||
public List<Action> getActions(GameConfig gameConfig, GameState gameState,
|
||||
Player color, int numActions);
|
||||
}
|
||||
|
||||
@@ -2,55 +2,55 @@ package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.GoGame;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
import net.woodyfolsom.msproj.StateEvaluator;
|
||||
|
||||
//import org.apache.log4j.Logger;
|
||||
|
||||
public class AlphaBeta implements Policy {
|
||||
//private static final Logger LOGGER = Logger.getLogger(AlphaBeta.class
|
||||
// .getName());
|
||||
private static final int DEFAULT_RECURSIVE_PLAYS = 3;
|
||||
private static final int DEFAULT_RECURSIVE_PLAYS = 1;
|
||||
private final ValidMoveGenerator validMoveGenerator = new ValidMoveGenerator();
|
||||
|
||||
private String bestPick = Policy.PASS;
|
||||
private Action bestPick = Action.PASS;
|
||||
|
||||
@Override
|
||||
public String getAction(GameConfig gameConfig, GameState gameState,
|
||||
String initialColor) {
|
||||
public Action getAction(GameConfig gameConfig, GameState gameState,
|
||||
Player player) {
|
||||
|
||||
int alpha = Integer.MIN_VALUE;
|
||||
int beta = Integer.MAX_VALUE;
|
||||
|
||||
if ("b".equals(initialColor)) {
|
||||
getMaxValue(gameConfig, gameState, initialColor, false,
|
||||
if (player == Player.BLACK) {
|
||||
getMaxValue(gameConfig, gameState, player, false,
|
||||
DEFAULT_RECURSIVE_PLAYS * 2, alpha, beta);
|
||||
return bestPick;
|
||||
} else if ("w".equals(initialColor)) {
|
||||
getMinValue(gameConfig, gameState, initialColor, false,
|
||||
} else if (player == Player.WHITE) {
|
||||
getMinValue(gameConfig, gameState, player, false,
|
||||
DEFAULT_RECURSIVE_PLAYS * 2, alpha, beta);
|
||||
return bestPick;
|
||||
} else {
|
||||
return Policy.PASS;
|
||||
return Action.PASS;
|
||||
}
|
||||
}
|
||||
|
||||
private int getMaxValue(GameConfig gameConfig, GameState gameState,
|
||||
String initialColor, boolean playAsOpponent, int recursionLevel,
|
||||
Player initialColor, boolean playAsOpponent, int recursionLevel,
|
||||
int alpha, int beta) {
|
||||
if (terminalTest(recursionLevel)) {
|
||||
return getUtility(gameConfig, gameState);
|
||||
}
|
||||
|
||||
String colorPlaying = getColorToPlay(initialColor, playAsOpponent);
|
||||
Player colorPlaying = GoGame.getColorToPlay(initialColor, playAsOpponent);
|
||||
|
||||
List<String> validMoves = validMoveGenerator.getActions(gameConfig,
|
||||
List<Action> validMoves = validMoveGenerator.getActions(gameConfig,
|
||||
gameState, colorPlaying, ActionGenerator.ALL_ACTIONS);
|
||||
|
||||
int value = Integer.MIN_VALUE;
|
||||
|
||||
for (String nextMove : validMoves) {
|
||||
for (Action nextMove : validMoves) {
|
||||
GameState nextState = new GameState(gameState);
|
||||
|
||||
if (!nextState.playStone(colorPlaying, nextMove)) {
|
||||
@@ -78,20 +78,20 @@ public class AlphaBeta implements Policy {
|
||||
}
|
||||
|
||||
private int getMinValue(GameConfig gameConfig, GameState gameState,
|
||||
String initialColor, boolean playAsOpponent, int recursionLevel,
|
||||
Player initialColor, boolean playAsOpponent, int recursionLevel,
|
||||
int alpha, int beta) {
|
||||
if (terminalTest(recursionLevel)) {
|
||||
return getUtility(gameConfig, gameState);
|
||||
}
|
||||
|
||||
String colorPlaying = getColorToPlay(initialColor, playAsOpponent);
|
||||
Player colorPlaying = GoGame.getColorToPlay(initialColor, playAsOpponent);
|
||||
|
||||
List<String> validMoves = validMoveGenerator.getActions(gameConfig,
|
||||
List<Action> validMoves = validMoveGenerator.getActions(gameConfig,
|
||||
gameState, colorPlaying, ActionGenerator.ALL_ACTIONS);
|
||||
|
||||
int value = Integer.MAX_VALUE;
|
||||
|
||||
for (String nextMove : validMoves) {
|
||||
for (Action nextMove : validMoves) {
|
||||
GameState nextState = new GameState(gameState);
|
||||
|
||||
if (!nextState.playStone(colorPlaying, nextMove)) {
|
||||
@@ -126,19 +126,4 @@ public class AlphaBeta implements Policy {
|
||||
StateEvaluator stateEvaluator = new StateEvaluator(gameConfig);
|
||||
return stateEvaluator.scoreGame(gameState).getAggregateScore();
|
||||
}
|
||||
|
||||
private String getColorToPlay(String color, boolean playAsOpponent) {
|
||||
if (playAsOpponent) {
|
||||
if ("w".equals(color)) {
|
||||
return "b";
|
||||
} else if ("b".equals(color)) {
|
||||
return "w";
|
||||
} else {
|
||||
return "?"; // invalid color will cause randomMoveGenerator to
|
||||
// PASS
|
||||
}
|
||||
} else {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,57 +4,66 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
|
||||
public abstract class GameTreeNode {
|
||||
private GameConfig gameConfig;
|
||||
public class GameTreeNode {
|
||||
private GameState gameState;
|
||||
private GameTreeNode parent;
|
||||
private Map<String, GameTreeNode> children = new HashMap<String, GameTreeNode>();
|
||||
private String player;
|
||||
private int numVisits;
|
||||
private int numWins;
|
||||
private Map<Action, GameTreeNode> children = new HashMap<Action, GameTreeNode>();
|
||||
|
||||
public GameTreeNode(GameConfig gameConfig, GameState gameState,
|
||||
String player) {
|
||||
this.gameConfig = gameConfig;
|
||||
public GameTreeNode(GameState gameState) {
|
||||
this.gameState = gameState;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public void addChild(String action, GameTreeNode child) {
|
||||
public void addChild(Action action, GameTreeNode child) {
|
||||
children.put(action, child);
|
||||
child.parent = this;
|
||||
}
|
||||
|
||||
public Set<String> getActions() {
|
||||
public Set<Action> getActions() {
|
||||
return children.keySet();
|
||||
}
|
||||
|
||||
public GameTreeNode getChild(String action) {
|
||||
public GameTreeNode getChild(Action action) {
|
||||
return children.get(action);
|
||||
}
|
||||
|
||||
public int getChildrenSize() {
|
||||
public int getNumChildren() {
|
||||
return children.size();
|
||||
}
|
||||
|
||||
public GameConfig getGameConfig() {
|
||||
return gameConfig;
|
||||
}
|
||||
|
||||
public GameState getGameState() {
|
||||
return gameState;
|
||||
}
|
||||
|
||||
public GameTreeNode getParent() {
|
||||
return parent;
|
||||
public int getNumVisits() {
|
||||
return numVisits;
|
||||
}
|
||||
|
||||
public String getPlayer() {
|
||||
return player;
|
||||
public int getNumWins() {
|
||||
return numWins;
|
||||
}
|
||||
|
||||
public GameTreeNode getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isTerminal() {
|
||||
return children.size() == 0;
|
||||
}
|
||||
|
||||
public void incrementVisits() {
|
||||
numVisits++;
|
||||
}
|
||||
|
||||
public void incrementWins() {
|
||||
numWins++;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +1,44 @@
|
||||
package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
//import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameScore;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.GoGame;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
import net.woodyfolsom.msproj.StateEvaluator;
|
||||
|
||||
//import org.apache.log4j.Logger;
|
||||
|
||||
|
||||
public class Minimax implements Policy {
|
||||
//private static final Logger LOGGER = Logger.getLogger(Minimax.class.getName());
|
||||
|
||||
private static final int DEFAULT_RECURSIVE_PLAYS = 1;
|
||||
|
||||
private final ValidMoveGenerator validMoveGenerator = new ValidMoveGenerator();
|
||||
|
||||
@Override
|
||||
public String getAction(GameConfig gameConfig, GameState gameState,
|
||||
String color) {
|
||||
public Action getAction(GameConfig gameConfig, GameState gameState,
|
||||
Player color) {
|
||||
MoveCandidate moveCandidate = findBestMinimaxResult(
|
||||
DEFAULT_RECURSIVE_PLAYS * 2,
|
||||
gameConfig, gameState, color, false, Policy.PASS);
|
||||
gameConfig, gameState, color, false, Action.PASS);
|
||||
|
||||
return moveCandidate.move;
|
||||
}
|
||||
|
||||
private MoveCandidate findBestMinimaxResult(int recursionLevels,
|
||||
GameConfig gameConfig, GameState gameState,
|
||||
String initialColor, boolean playAsOpponent, String bestPrevMove) {
|
||||
Player initialColor, boolean playAsOpponent, Action bestPrevMove) {
|
||||
|
||||
StateEvaluator stateEvaluator = new StateEvaluator(gameConfig);
|
||||
List<MoveCandidate> randomMoveCandidates = new ArrayList<MoveCandidate>();
|
||||
|
||||
String colorPlaying = getColorToPlay(initialColor, playAsOpponent);
|
||||
Player colorPlaying = GoGame.getColorToPlay(initialColor, playAsOpponent);
|
||||
|
||||
List<String> validMoves = validMoveGenerator.getActions(gameConfig,
|
||||
List<Action> validMoves = validMoveGenerator.getActions(gameConfig,
|
||||
gameState, colorPlaying, ActionGenerator.ALL_ACTIONS);
|
||||
|
||||
for (String randomMove : validMoves) {
|
||||
for (Action randomMove : validMoves) {
|
||||
GameState stateCopy = new GameState(gameState);
|
||||
stateCopy.playStone(colorPlaying, randomMove);
|
||||
if (recursionLevels > 1) {
|
||||
@@ -77,19 +74,4 @@ public class Minimax implements Policy {
|
||||
return bestMove;
|
||||
}
|
||||
}
|
||||
|
||||
private String getColorToPlay(String color, boolean playAsOpponent) {
|
||||
if (playAsOpponent) {
|
||||
if ("w".equals(color)) {
|
||||
return "b";
|
||||
} else if ("b".equals(color)) {
|
||||
return "w";
|
||||
} else {
|
||||
return "?"; // invalid color will cause randomMoveGenerator to
|
||||
// PASS
|
||||
}
|
||||
} else {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +1,81 @@
|
||||
package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
|
||||
public abstract class MonteCarlo implements Policy {
|
||||
protected Policy movePolicy;
|
||||
protected long searchTimeLimit;
|
||||
protected volatile long elapsedTime = 0L;
|
||||
|
||||
public MonteCarlo(Policy movePolicy, long searchTimeLimit) {
|
||||
this.movePolicy = movePolicy;
|
||||
this.searchTimeLimit = searchTimeLimit;
|
||||
}
|
||||
|
||||
public abstract MonteCarloTreeNode descend(MonteCarloTreeNode node);
|
||||
/**
|
||||
* Descend the tree from the specified node and return a list of nodes to grow.
|
||||
*
|
||||
* @param node
|
||||
* @return
|
||||
*/
|
||||
public abstract List<GameTreeNode> descend(GameTreeNode node);
|
||||
|
||||
@Override
|
||||
public String getAction(GameConfig gameConfig, GameState gameState,
|
||||
String initialColor) {
|
||||
long initialTime = System.currentTimeMillis();
|
||||
public Action getAction(GameConfig gameConfig, GameState gameState,
|
||||
Player initialColor) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
//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.
|
||||
|
||||
String bestMove = Policy.PASS;
|
||||
GameTreeNode rootNode = new GameTreeNode(gameState);
|
||||
|
||||
MonteCarloTreeNode rootNode = new MonteCarloTreeNode(gameConfig, gameState, initialColor);
|
||||
MonteCarloTreeNode selectedNode;
|
||||
while (System.currentTimeMillis() - initialTime < searchTimeLimit) {
|
||||
do {
|
||||
//TODO these return types may need to be lists for some MC methods
|
||||
selectedNode = descend(rootNode);
|
||||
selectedNode = grow(selectedNode);
|
||||
int reward = rollout(selectedNode);
|
||||
update(selectedNode, reward);
|
||||
List<GameTreeNode> selectedNodes = descend(rootNode);
|
||||
List<GameTreeNode> newLeaves = new ArrayList<GameTreeNode>();
|
||||
|
||||
for (GameTreeNode selectedNode: selectedNodes) {
|
||||
for (GameTreeNode newLeaf : grow(selectedNode)) {
|
||||
newLeaves.add(newLeaf);
|
||||
}
|
||||
}
|
||||
|
||||
return bestMove;
|
||||
for (GameTreeNode newLeaf : newLeaves) {
|
||||
int reward = rollout(newLeaf);
|
||||
update(newLeaf, reward);
|
||||
}
|
||||
|
||||
public abstract MonteCarloTreeNode grow(MonteCarloTreeNode node);
|
||||
elapsedTime = System.currentTimeMillis() - startTime;
|
||||
} while (elapsedTime < searchTimeLimit);
|
||||
|
||||
public abstract int rollout(MonteCarloTreeNode node);
|
||||
|
||||
public abstract void update(MonteCarloTreeNode node, int reward);
|
||||
|
||||
static String getColorToPlay(String color, boolean playAsOpponent) {
|
||||
if (playAsOpponent) {
|
||||
if ("w".equals(color)) {
|
||||
return "b";
|
||||
} else if ("b".equals(color)) {
|
||||
return "w";
|
||||
} else {
|
||||
return "?"; // invalid color will cause randomMoveGenerator to
|
||||
// PASS
|
||||
return getBestAction(rootNode);
|
||||
}
|
||||
} else {
|
||||
return color;
|
||||
|
||||
public long getElapsedTime() {
|
||||
return elapsedTime;
|
||||
}
|
||||
|
||||
public abstract Action getBestAction(GameTreeNode node);
|
||||
|
||||
public abstract List<GameTreeNode> grow(GameTreeNode node);
|
||||
|
||||
public abstract int rollout(GameTreeNode node);
|
||||
|
||||
public abstract void update(GameTreeNode node, int reward);
|
||||
|
||||
public long getSearchTimeLimit() {
|
||||
return searchTimeLimit;
|
||||
}
|
||||
|
||||
public int doRollout() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
|
||||
public class MonteCarloTreeNode extends GameTreeNode {
|
||||
private int numVisits;
|
||||
private int numWins;
|
||||
|
||||
public MonteCarloTreeNode(GameConfig gameConfig, GameState gameState,
|
||||
String player) {
|
||||
super(gameConfig, gameState, player);
|
||||
}
|
||||
|
||||
public int getNumVisits() {
|
||||
return numVisits;
|
||||
}
|
||||
|
||||
public void setNumVisits(int numVisits) {
|
||||
this.numVisits = numVisits;
|
||||
}
|
||||
|
||||
public int getNumWins() {
|
||||
return numWins;
|
||||
}
|
||||
|
||||
public void setNumWins(int numWins) {
|
||||
this.numWins = numWins;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
|
||||
public class MonteCarloUCT extends MonteCarlo {
|
||||
|
||||
@@ -8,25 +12,63 @@ public class MonteCarloUCT extends MonteCarlo {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MonteCarloTreeNode descend(MonteCarloTreeNode node) {
|
||||
public List<GameTreeNode> descend(GameTreeNode node) {
|
||||
double bestScore = (double) node.getNumWins() / node.getNumVisits();
|
||||
GameTreeNode bestNode = node;
|
||||
|
||||
//This appears slightly redundant with getBestAction() but it is not -
|
||||
//descend() may pick the current node rather than a child to expand (if a child has a good score but high/low uncertainty)
|
||||
//but getBestAction specifically asks for the optimum action to take from the current node,
|
||||
//even if it results in a worse next state.
|
||||
for (Action action : node.getActions()) {
|
||||
GameTreeNode childNode = node.getChild(action);
|
||||
double childScore = (double) childNode.getNumWins() / childNode.getNumVisits();
|
||||
if (childScore >= bestScore) {
|
||||
bestScore = childScore;
|
||||
bestNode = childNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestNode == node) {
|
||||
List<GameTreeNode> bestNodeList = new ArrayList<GameTreeNode>();
|
||||
bestNodeList.add(bestNode);
|
||||
return bestNodeList;
|
||||
} else {
|
||||
return descend(bestNode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action getBestAction(GameTreeNode node) {
|
||||
Action bestAction = Action.NONE;
|
||||
double bestScore = Double.NEGATIVE_INFINITY;
|
||||
|
||||
for (Action action : node.getActions()) {
|
||||
GameTreeNode childNode = node.getChild(action);
|
||||
double childScore = (double) childNode.getNumWins() / childNode.getNumVisits();
|
||||
if (childScore >= bestScore) {
|
||||
bestScore = childScore;
|
||||
bestAction = action;
|
||||
}
|
||||
}
|
||||
|
||||
return bestAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GameTreeNode> grow(GameTreeNode node) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MonteCarloTreeNode grow(MonteCarloTreeNode node) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int rollout(MonteCarloTreeNode node) {
|
||||
public int rollout(GameTreeNode node) {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(MonteCarloTreeNode node, int reward) {
|
||||
public void update(GameTreeNode node, int reward) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameScore;
|
||||
|
||||
public class MoveCandidate {
|
||||
public final String move;
|
||||
public final Action move;
|
||||
public final GameScore score;
|
||||
|
||||
public MoveCandidate(String move, GameScore score) {
|
||||
public MoveCandidate(Action move, GameScore score) {
|
||||
this.move = move;
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
|
||||
|
||||
public interface Policy {
|
||||
static final String PASS = "PASS";
|
||||
public String getAction(GameConfig gameConfig, GameState gameState, String color);
|
||||
public Action getAction(GameConfig gameConfig, GameState gameState, Player player);
|
||||
}
|
||||
@@ -3,8 +3,10 @@ package net.woodyfolsom.msproj.policy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
|
||||
|
||||
public class RandomMovePolicy implements Policy {
|
||||
@@ -12,14 +14,15 @@ public class RandomMovePolicy implements Policy {
|
||||
/**
|
||||
* Does NOT modify the gameState.
|
||||
*/
|
||||
public String getAction(GameConfig gameConfig, GameState gameState,
|
||||
String color) {
|
||||
public Action getAction(GameConfig gameConfig, GameState gameState,
|
||||
Player color) {
|
||||
GameState gameStateCopy = new GameState(gameState);
|
||||
List<String> emptyCoordinates = gameStateCopy.getEmptyCoords();
|
||||
|
||||
while (emptyCoordinates.size() > 0) {
|
||||
String randomMove = emptyCoordinates
|
||||
.get((int) (Math.random() * emptyCoordinates.size()));
|
||||
Action randomMove = Action.getInstance(emptyCoordinates
|
||||
.get((int) (Math.random() * emptyCoordinates.size())));
|
||||
|
||||
if (gameStateCopy.playStone(color, randomMove)) {
|
||||
return randomMove;
|
||||
} else {
|
||||
@@ -27,7 +30,7 @@ public class RandomMovePolicy implements Policy {
|
||||
}
|
||||
}
|
||||
|
||||
return PASS;
|
||||
return Action.PASS;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,15 +45,15 @@ public class RandomMovePolicy implements Policy {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<String> genMoves(GameConfig gameConfig, GameState gameState,
|
||||
String color, int nMoves) {
|
||||
public List<Action> genMoves(GameConfig gameConfig, GameState gameState,
|
||||
Player color, int nMoves) {
|
||||
GameState gameStateCopy = new GameState(gameState);
|
||||
List<String> emptyCoordinates = gameStateCopy.getEmptyCoords();
|
||||
List<String> randomMoves = new ArrayList<String>();
|
||||
List<Action> randomMoves = new ArrayList<Action>();
|
||||
|
||||
while (emptyCoordinates.size() > 0 && randomMoves.size() < nMoves) {
|
||||
String randomMove = emptyCoordinates
|
||||
.get((int) (Math.random() * emptyCoordinates.size()));
|
||||
Action randomMove = Action.getInstance(emptyCoordinates
|
||||
.get((int) (Math.random() * emptyCoordinates.size())));
|
||||
if (gameStateCopy.playStone(color, randomMove)) {
|
||||
randomMoves.add(randomMove);
|
||||
}
|
||||
@@ -58,7 +61,7 @@ public class RandomMovePolicy implements Policy {
|
||||
}
|
||||
|
||||
if (randomMoves.size() == 0) {
|
||||
randomMoves.add(PASS);
|
||||
randomMoves.add(Action.PASS);
|
||||
}
|
||||
|
||||
return randomMoves;
|
||||
|
||||
@@ -3,8 +3,10 @@ package net.woodyfolsom.msproj.policy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
|
||||
//import org.apache.log4j.Logger;
|
||||
|
||||
@@ -12,23 +14,24 @@ public class ValidMoveGenerator implements ActionGenerator {
|
||||
//private static final Logger LOGGER = Logger.getLogger(ValidMoveGenerator.class.getName());
|
||||
|
||||
@Override
|
||||
public List<String> getActions(GameConfig gameConfig, GameState gameState,
|
||||
String color, int nMoves) {
|
||||
public List<Action> getActions(GameConfig gameConfig, GameState gameState,
|
||||
Player color, int nMoves) {
|
||||
|
||||
GameState gameStateCopy = new GameState(gameState);
|
||||
List<String> emptyCoordinates = gameStateCopy.getEmptyCoords();
|
||||
List<String> validMoves = new ArrayList<String>();
|
||||
List<Action> validMoves = new ArrayList<Action>();
|
||||
|
||||
while (emptyCoordinates.size() > 0) {
|
||||
String nextMove = emptyCoordinates.remove(emptyCoordinates.size()-1);
|
||||
Action nextMove = Action.getInstance(emptyCoordinates.remove(emptyCoordinates.size()-1));
|
||||
if (gameStateCopy.playStone(color, nextMove)) {
|
||||
validMoves.add(nextMove);
|
||||
gameStateCopy = new GameState(gameState); // play successful? regenerate copy of gameState
|
||||
}
|
||||
}
|
||||
|
||||
//Passing is always a VALID move. It may not be a GOOD move.
|
||||
if (validMoves.size() == 0) {
|
||||
validMoves.add(Policy.PASS);
|
||||
validMoves.add(Action.PASS);
|
||||
}
|
||||
|
||||
return validMoves;
|
||||
|
||||
@@ -4,27 +4,21 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import net.woodyfolsom.msproj.GameBoard;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameScore;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.StateEvaluator;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class CaptureTest {
|
||||
@Test
|
||||
public void testCapture() {
|
||||
GameState gameState = new GameState(5);
|
||||
gameState.playStone('A', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 3, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 1, GameBoard.BLACK_STONE);
|
||||
assertTrue(gameState.playStone('B', 2, GameBoard.WHITE_STONE));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B3"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B1"));
|
||||
assertTrue(gameState.playStone(Player.WHITE, Action.getInstance("B2")));
|
||||
|
||||
assertEquals(0,gameState.getBlackPrisoners());
|
||||
assertEquals(0,gameState.getWhitePrisoners());
|
||||
|
||||
assertTrue(gameState.playStone('C', 2, GameBoard.BLACK_STONE));
|
||||
assertTrue(gameState.playStone(Player.BLACK, Action.getInstance("C2")));
|
||||
|
||||
assertEquals(1,gameState.getBlackPrisoners());
|
||||
assertEquals(0,gameState.getWhitePrisoners());
|
||||
@@ -37,25 +31,25 @@ public class CaptureTest {
|
||||
GameConfig gameConfig = new GameConfig();
|
||||
GameState gameState = new GameState(5);
|
||||
|
||||
gameState.playStone('A', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 3, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 1, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('C', 4, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('D', 3, GameBoard.BLACK_STONE);
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B3"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B1"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("C4"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("D3"));
|
||||
|
||||
assertTrue(gameState.playStone('B', 2, GameBoard.WHITE_STONE));
|
||||
assertTrue(gameState.playStone('C', 3, GameBoard.WHITE_STONE));
|
||||
assertTrue(gameState.playStone(Player.WHITE, Action.getInstance("B2")));
|
||||
assertTrue(gameState.playStone(Player.WHITE, Action.getInstance("C3")));
|
||||
|
||||
assertEquals(0,gameState.getBlackPrisoners());
|
||||
assertEquals(0,gameState.getWhitePrisoners());
|
||||
|
||||
assertTrue(gameState.playStone('C', 2, GameBoard.BLACK_STONE));
|
||||
assertTrue(gameState.playStone(Player.BLACK, Action.getInstance("C2")));
|
||||
|
||||
assertEquals(2,gameState.getBlackPrisoners());
|
||||
assertEquals(0,gameState.getWhitePrisoners());
|
||||
|
||||
assertFalse(gameState.playStone('B', 2, GameBoard.WHITE_STONE));
|
||||
assertFalse(gameState.playStone('C', 3, GameBoard.WHITE_STONE));
|
||||
assertFalse(gameState.playStone(Player.WHITE, Action.getInstance("B2")));
|
||||
assertFalse(gameState.playStone(Player.WHITE, Action.getInstance("C3")));
|
||||
|
||||
System.out.println(gameState);
|
||||
|
||||
@@ -67,20 +61,21 @@ public class CaptureTest {
|
||||
public void testCaptureFromEye() {
|
||||
GameState gameState = new GameState(5);
|
||||
|
||||
gameState.playStone('A', 1, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('C', 1, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('A', 2, GameBoard.WHITE_STONE);
|
||||
gameState.playStone('B', 3, GameBoard.WHITE_STONE);
|
||||
gameState.playStone('C', 2, GameBoard.WHITE_STONE);
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A1"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("C1"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("B3"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("C2"));
|
||||
|
||||
//This capture should be allowed.
|
||||
assertTrue("Capture from within single eye should have been allowed but move was rejected.",
|
||||
gameState.playStone('B', 1, GameBoard.WHITE_STONE));
|
||||
|
||||
assertEquals(0,gameState.getBlackPrisoners());
|
||||
assertEquals(2,gameState.getWhitePrisoners());
|
||||
|
||||
System.out.println("State before WHITE move: ");
|
||||
System.out.println(gameState);
|
||||
|
||||
assertTrue("Capture from within single eye should have been allowed but move was rejected.",
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("B1")));
|
||||
|
||||
assertEquals("BLACK should have 0 prisoners.",0,gameState.getBlackPrisoners());
|
||||
assertEquals("WHITE should have 2 prisoners.",2,gameState.getWhitePrisoners());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,6 @@ package net.woodyfolsom.msproj;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import net.woodyfolsom.msproj.GameBoard;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class IllegalMoveTest {
|
||||
@@ -13,53 +10,57 @@ public class IllegalMoveTest {
|
||||
@Test
|
||||
public void testIllegalMoveOnOwnStone() {
|
||||
GameState gameState = new GameState(5);
|
||||
gameState.playStone('B', 3, GameBoard.BLACK_STONE);
|
||||
assertFalse(gameState.playStone('B', 3, GameBoard.BLACK_STONE));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B3"));
|
||||
assertFalse(gameState.playStone(Player.BLACK, Action.getInstance("B3")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIllegalMoveOnOtherStone() {
|
||||
GameState gameState = new GameState(5);
|
||||
gameState.playStone('B', 3, GameBoard.BLACK_STONE);
|
||||
assertFalse(gameState.playStone('B', 3, GameBoard.WHITE_STONE));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B3"));
|
||||
assertFalse(gameState.playStone(Player.WHITE, Action.getInstance("B3")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIllegalMoveNoLiberties() {
|
||||
GameState gameState = new GameState(5);
|
||||
gameState.playStone('A', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 3, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 1, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('C', 2, GameBoard.BLACK_STONE);
|
||||
assertFalse(gameState.playStone('B', 2, GameBoard.WHITE_STONE));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B1"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B3"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("C2"));
|
||||
System.out.println(gameState);
|
||||
assertFalse(gameState.playStone(Player.WHITE, Action.getInstance("B2")));
|
||||
System.out.println(gameState);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIllegalMoveFormsTrappedGroup() {
|
||||
GameState gameState = new GameState(9);
|
||||
gameState.playStone('A', 5, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 6, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 7, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('A', 8, GameBoard.BLACK_STONE);
|
||||
assertTrue(gameState.playStone('A', 6, GameBoard.WHITE_STONE));
|
||||
assertFalse(gameState.playStone('A', 7, GameBoard.WHITE_STONE));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A5"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B6"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B7"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A8"));
|
||||
assertTrue(gameState.playStone(Player.WHITE, Action.getInstance("A6")));
|
||||
assertFalse(gameState.playStone(Player.WHITE, Action.getInstance("A7")));
|
||||
System.out.println(gameState);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIllegalMoveFormsTrappedGroup2() {
|
||||
GameState gameState = new GameState(9);
|
||||
gameState.playStone('G', 1, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('H', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('H', 3, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('J', 4, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('A', 8, GameBoard.BLACK_STONE);
|
||||
assertTrue(gameState.playStone('H', 1, GameBoard.WHITE_STONE));
|
||||
assertTrue(gameState.playStone('J', 2, GameBoard.WHITE_STONE));
|
||||
assertTrue(gameState.playStone('J', 3, GameBoard.WHITE_STONE));
|
||||
System.out.println(gameState);
|
||||
assertFalse(gameState.playStone('J', 1, GameBoard.WHITE_STONE));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("G1"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("H2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("H3"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("J4"));
|
||||
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A8"));
|
||||
|
||||
assertTrue(gameState.playStone(Player.WHITE, Action.getInstance("H1")));
|
||||
assertTrue(gameState.playStone(Player.WHITE, Action.getInstance("J2")));
|
||||
assertTrue(gameState.playStone(Player.WHITE, Action.getInstance("J3")));
|
||||
|
||||
System.out.println("State before move: ");
|
||||
System.out.println(gameState);
|
||||
assertFalse("Play by WHITE at J1 should have failed.",gameState.playStone(Player.WHITE, Action.getInstance("J1")));
|
||||
}
|
||||
}
|
||||
@@ -2,19 +2,16 @@ package net.woodyfolsom.msproj;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import net.woodyfolsom.msproj.GameBoard;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class LegalMoveTest {
|
||||
@Test
|
||||
public void testLegalMove1Liberty() {
|
||||
GameState gameState = new GameState(5);
|
||||
gameState.playStone('A', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 3, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 1, GameBoard.BLACK_STONE);
|
||||
assertTrue(gameState.playStone('B', 2, GameBoard.WHITE_STONE));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B3"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B1"));
|
||||
assertTrue(gameState.playStone(Player.WHITE, Action.getInstance("B2")));
|
||||
System.out.println(gameState);
|
||||
}
|
||||
}
|
||||
@@ -3,87 +3,85 @@ package net.woodyfolsom.msproj;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import net.woodyfolsom.msproj.GameBoard;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameScore;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.StateEvaluator;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
public class StateEvaluatorTest {
|
||||
GameConfig gameConfig = new GameConfig();
|
||||
|
||||
@Test
|
||||
public void testScoreEmptyBoard() {
|
||||
GameState gameState = new GameState(5);
|
||||
GameScore gameScore = new StateEvaluator(gameConfig).scoreGame(gameState);
|
||||
GameScore gameScore = new StateEvaluator(gameConfig)
|
||||
.scoreGame(gameState);
|
||||
|
||||
assertEquals(0.0,gameScore.getWhiteScore(),0.5);
|
||||
assertEquals(0.0,gameScore.getBlackScore(),0.5);
|
||||
assertEquals(0.0, gameScore.getWhiteScore(), 0.5);
|
||||
assertEquals(0.0, gameScore.getBlackScore(), 0.5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScoreFirstMove() {
|
||||
GameState gameState = new GameState(5);
|
||||
gameState.playStone('B',3,GameBoard.BLACK_STONE);
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B3"));
|
||||
|
||||
GameScore gameScore = new StateEvaluator(gameConfig).scoreGame(gameState);
|
||||
GameScore gameScore = new StateEvaluator(gameConfig)
|
||||
.scoreGame(gameState);
|
||||
|
||||
System.out.println(gameScore.getScoreReport());
|
||||
|
||||
assertEquals(0.0,gameScore.getWhiteScore(),0.5);
|
||||
assertEquals(25.0,gameScore.getBlackScore(),0.5);
|
||||
assertEquals(0.0, gameScore.getWhiteScore(), 0.5);
|
||||
assertEquals(25.0, gameScore.getBlackScore(), 0.5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScoreTiedAtMove2() {
|
||||
GameState gameState = new GameState(5);
|
||||
|
||||
gameState.playStone('B',3,GameBoard.BLACK_STONE);
|
||||
gameState.playStone('A',1,GameBoard.WHITE_STONE);
|
||||
GameScore gameScore = new StateEvaluator(gameConfig).scoreGame(gameState);
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B3"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("A1"));
|
||||
GameScore gameScore = new StateEvaluator(gameConfig)
|
||||
.scoreGame(gameState);
|
||||
|
||||
System.out.println(gameScore.getScoreReport());
|
||||
|
||||
assertEquals(1.0,gameScore.getWhiteScore(),0.5);
|
||||
assertEquals(1.0,gameScore.getBlackScore(),0.5);
|
||||
assertEquals(1.0, gameScore.getWhiteScore(), 0.5);
|
||||
assertEquals(1.0, gameScore.getBlackScore(), 0.5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScoreTerritory() {
|
||||
GameState gameState = new GameState(5);
|
||||
|
||||
gameState.playStone('A',2,GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B',3,GameBoard.BLACK_STONE);
|
||||
gameState.playStone('C',2,GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B',1,GameBoard.BLACK_STONE);
|
||||
gameState.playStone('E',5,GameBoard.WHITE_STONE);
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B3"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("C2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B1"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("E5"));
|
||||
|
||||
System.out.println(gameState);
|
||||
GameScore gameScore = new StateEvaluator(gameConfig).scoreGame(gameState);
|
||||
GameScore gameScore = new StateEvaluator(gameConfig)
|
||||
.scoreGame(gameState);
|
||||
|
||||
System.out.println(gameScore.getScoreReport());
|
||||
|
||||
assertEquals(1.0,gameScore.getWhiteScore(),0.5);
|
||||
assertEquals(6.0,gameScore.getBlackScore(),0.5);
|
||||
//Black should be up by 5 if Black's territory at A1 & B2 is scored correctly.
|
||||
assertEquals(1.0, gameScore.getWhiteScore(), 0.5);
|
||||
assertEquals(6.0, gameScore.getBlackScore(), 0.5);
|
||||
// Black should be up by 5 if Black's territory at A1 & B2 is scored
|
||||
// correctly.
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCaptureAggScore() {
|
||||
GameState gameState = new GameState(9);
|
||||
gameState.playStone('A', 2, GameBoard.WHITE_STONE);
|
||||
gameState.playStone('B', 1, GameBoard.WHITE_STONE);
|
||||
gameState.playStone('C', 2, GameBoard.WHITE_STONE);
|
||||
gameState.playStone('B', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("B1"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("C2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B2"));
|
||||
|
||||
GameState moveToA1 = new GameState(gameState);
|
||||
GameState capAtB3 = new GameState(gameState);
|
||||
|
||||
moveToA1.playStone("w","A1");
|
||||
capAtB3.playStone("w", "B3");
|
||||
moveToA1.playStone(Player.WHITE, Action.getInstance("A1"));
|
||||
capAtB3.playStone(Player.WHITE, Action.getInstance("B3"));
|
||||
|
||||
System.out.println(moveToA1);
|
||||
System.out.println(capAtB3);
|
||||
@@ -94,7 +92,7 @@ public class StateEvaluatorTest {
|
||||
|
||||
System.out.println("Score at A1: " + scoreA1);
|
||||
System.out.println("Score at B3: " + scoreB3);
|
||||
//moving as white, lower is better
|
||||
// moving as white, lower is better
|
||||
assertTrue(scoreA1 > scoreB3);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,5 @@
|
||||
package net.woodyfolsom.msproj;
|
||||
|
||||
import net.woodyfolsom.msproj.GameBoard;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.TerritoryMarker;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class TerritoryFinderTest {
|
||||
@@ -11,11 +7,11 @@ public class TerritoryFinderTest {
|
||||
public void testMarkTerritory() {
|
||||
GameState gameState = new GameState(5);
|
||||
|
||||
gameState.playStone('A',2,GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B',3,GameBoard.BLACK_STONE);
|
||||
gameState.playStone('C',2,GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B',1,GameBoard.BLACK_STONE);
|
||||
gameState.playStone('E',5,GameBoard.WHITE_STONE);
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B3"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("C2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B1"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("E5"));
|
||||
|
||||
TerritoryMarker.markTerritory(gameState.getGameBoard());
|
||||
System.out.println(gameState);
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import net.woodyfolsom.msproj.GameBoard;
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.policy.AlphaBeta;
|
||||
import net.woodyfolsom.msproj.policy.Policy;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -15,43 +13,40 @@ public class AlphaBetaTest {
|
||||
public void testGenmoveAsW() {
|
||||
Policy treeSearch = new AlphaBeta();
|
||||
GameState gameState = new GameState(6);
|
||||
gameState.playStone('A', 2, GameBoard.WHITE_STONE);
|
||||
gameState.playStone('B', 1, GameBoard.WHITE_STONE);
|
||||
gameState.playStone('C', 2, GameBoard.WHITE_STONE);
|
||||
gameState.playStone('B', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("B1"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("C2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B2"));
|
||||
|
||||
Action move = treeSearch.getAction(new GameConfig(), gameState, Player.WHITE);
|
||||
|
||||
String move = treeSearch.getAction(new GameConfig(), gameState, "b");
|
||||
System.out.println(gameState);
|
||||
|
||||
System.out.println("Generated move: " + move);
|
||||
assertEquals("Expected B3 but was: " + move, "B3", move);
|
||||
gameState.playStone("b", move);
|
||||
|
||||
assertEquals("Expected B3 but was: " + move, Action.getInstance("B3"), move);
|
||||
gameState.playStone(Player.WHITE, move);
|
||||
System.out.println("Final board state:");
|
||||
System.out.println(gameState);
|
||||
|
||||
assertEquals(Policy.PASS,
|
||||
treeSearch.getAction(new GameConfig(), gameState, "?"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenmoveAsB() {
|
||||
Policy treeSearch = new AlphaBeta();
|
||||
GameState gameState = new GameState(6);
|
||||
gameState.playStone('A', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 1, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('C', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 2, GameBoard.WHITE_STONE);
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B1"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("C2"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("B2"));
|
||||
|
||||
Action move = treeSearch.getAction(new GameConfig(), gameState, Player.BLACK);
|
||||
|
||||
String move = treeSearch.getAction(new GameConfig(), gameState, "b");
|
||||
System.out.println(gameState);
|
||||
|
||||
System.out.println("Generated move: " + move);
|
||||
assertEquals("Expected B3 but was: " + move, "B3", move);
|
||||
gameState.playStone("b", move);
|
||||
assertEquals("Expected B3 but was: " + move, Action.getInstance("B3"), move);
|
||||
gameState.playStone(Player.BLACK, move);
|
||||
|
||||
System.out.println("Final board state:");
|
||||
System.out.println(gameState);
|
||||
|
||||
assertEquals(Policy.PASS,
|
||||
treeSearch.getAction(new GameConfig(), gameState, "?"));
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,52 @@
|
||||
package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import net.woodyfolsom.msproj.GameBoard;
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.policy.Policy;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
public class MinimaxTest {
|
||||
|
||||
@Test
|
||||
public void testGenmove() {
|
||||
Policy moveGenerator = new Minimax();
|
||||
GameState gameState = new GameState(5);
|
||||
gameState.playStone('A', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 1, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('C', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 4, GameBoard.BLACK_STONE);
|
||||
public void testGenmoveAsW() {
|
||||
Policy treeSearch = new Minimax();
|
||||
GameState gameState = new GameState(6);
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("B1"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("C2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B2"));
|
||||
|
||||
String move = moveGenerator.getAction(new GameConfig(), gameState, "w");
|
||||
System.out.println("Generated move: " + move);
|
||||
gameState.playStone("w", move);
|
||||
Action move = treeSearch.getAction(new GameConfig(), gameState,
|
||||
Player.WHITE);
|
||||
|
||||
System.out.println(gameState);
|
||||
|
||||
assertEquals(Policy.PASS,moveGenerator.getAction(new GameConfig(), gameState, "?"));
|
||||
System.out.println("Generated move: " + move);
|
||||
assertEquals("Expected B3 but was: " + move, "B3", move);
|
||||
gameState.playStone(Player.WHITE, move);
|
||||
|
||||
System.out.println(gameState);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenmoveAsB() {
|
||||
Policy treeSearch = new Minimax();
|
||||
GameState gameState = new GameState(6);
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B1"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("C2"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("B2"));
|
||||
|
||||
Action move = treeSearch.getAction(new GameConfig(), gameState,
|
||||
Player.BLACK);
|
||||
|
||||
System.out.println(gameState);
|
||||
|
||||
System.out.println("Generated move: " + move);
|
||||
assertEquals("Expected B3 but was: " + move, "B3", move);
|
||||
gameState.playStone(Player.BLACK, move);
|
||||
|
||||
System.out.println(gameState);
|
||||
}
|
||||
|
||||
53
test/net/woodyfolsom/msproj/policy/MonteCarloUCTTest.java
Normal file
53
test/net/woodyfolsom/msproj/policy/MonteCarloUCTTest.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
import net.woodyfolsom.msproj.policy.Policy;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class MonteCarloUCTTest {
|
||||
@Test
|
||||
public void testGenmoveAsW() {
|
||||
Policy treeSearch = new MonteCarloUCT(new RandomMovePolicy(),2000L);
|
||||
GameState gameState = new GameState(6);
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("B1"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("C2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B2"));
|
||||
|
||||
Action move = treeSearch.getAction(new GameConfig(), gameState, Player.WHITE);
|
||||
|
||||
System.out.println(gameState);
|
||||
|
||||
System.out.println("Generated move: " + move);
|
||||
assertEquals("Expected B3 but was: " + move, "B3", move);
|
||||
gameState.playStone(Player.WHITE, move);
|
||||
|
||||
System.out.println(gameState);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenmoveAsB() {
|
||||
Policy treeSearch = new MonteCarloUCT(new RandomMovePolicy(),2000L);
|
||||
GameState gameState = new GameState(6);
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B1"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("C2"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("B2"));
|
||||
|
||||
Action move = treeSearch.getAction(new GameConfig(), gameState, Player.BLACK);
|
||||
|
||||
System.out.println(gameState);
|
||||
|
||||
System.out.println("Generated move: " + move);
|
||||
assertEquals("Expected B3 but was: " + move, "B3", move);
|
||||
gameState.playStone(Player.BLACK, move);
|
||||
|
||||
System.out.println(gameState);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +1,56 @@
|
||||
package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import net.woodyfolsom.msproj.GameBoard;
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.policy.Policy;
|
||||
import net.woodyfolsom.msproj.policy.RandomMovePolicy;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
public class RandomTest {
|
||||
|
||||
@Test
|
||||
public void testGenmove() {
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testGenmoveForNone() {
|
||||
Policy moveGenerator = new RandomMovePolicy();
|
||||
GameState gameState = new GameState(5);
|
||||
moveGenerator.getAction(new GameConfig(), gameState, "b");
|
||||
moveGenerator.getAction(new GameConfig(), gameState, Player.BLACK);
|
||||
gameState = new GameState(5);
|
||||
moveGenerator.getAction(new GameConfig(), gameState, "w");
|
||||
moveGenerator.getAction(new GameConfig(), gameState, Player.WHITE);
|
||||
|
||||
assertEquals(Policy.PASS,moveGenerator.getAction(new GameConfig(), gameState, "?"));
|
||||
|
||||
System.out.println(gameState);
|
||||
assertEquals(Action.PASS, moveGenerator.getAction(new GameConfig(), gameState, Player.NONE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlternativeToIllegalMove() {
|
||||
GameState gameState = new GameState(4);
|
||||
gameState.playStone('A', 1, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('A', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('A', 3, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('A', 4, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 1, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A1"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A3"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("A4"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B1"));;
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B2"));
|
||||
|
||||
//gameState.playStone('B', 3, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('B', 4, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('C', 2, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('C', 3, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('C', 4, GameBoard.BLACK_STONE);
|
||||
gameState.playStone('D', 4, GameBoard.BLACK_STONE);
|
||||
assertTrue(gameState.playStone('C', 1, GameBoard.WHITE_STONE));
|
||||
assertTrue(gameState.playStone('D', 2, GameBoard.WHITE_STONE));
|
||||
assertTrue(gameState.playStone('D', 3, GameBoard.WHITE_STONE));
|
||||
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("B4"));
|
||||
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("C2"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("C3"));
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("C4"));
|
||||
|
||||
gameState.playStone(Player.BLACK, Action.getInstance("D4"));
|
||||
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("C1"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("D2"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("D3"));
|
||||
|
||||
System.out.println("State before random WHITE move selection:");
|
||||
System.out.println(gameState);
|
||||
//This is correct - checked vs. MFOG
|
||||
assertEquals("B3", new RandomMovePolicy().getAction(new GameConfig(), gameState, "w"));
|
||||
assertEquals(Action.getInstance("B3"), new RandomMovePolicy().getAction(new GameConfig(), gameState, Player.WHITE));
|
||||
|
||||
System.out.println(gameState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package net.woodyfolsom.msproj.policy;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.woodyfolsom.msproj.GameBoard;
|
||||
import net.woodyfolsom.msproj.Action;
|
||||
import net.woodyfolsom.msproj.GameConfig;
|
||||
import net.woodyfolsom.msproj.GameState;
|
||||
import net.woodyfolsom.msproj.policy.ValidMoveGenerator;
|
||||
import net.woodyfolsom.msproj.Player;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -26,18 +27,22 @@ public class ValidMoveGeneratorTest {
|
||||
A B C D E
|
||||
*/
|
||||
GameState gameState = new GameState(5);
|
||||
gameState.playStone('A', 2, GameBoard.WHITE_STONE);
|
||||
gameState.playStone('B', 1, GameBoard.WHITE_STONE);
|
||||
gameState.playStone('B', 4, GameBoard.WHITE_STONE);
|
||||
gameState.playStone('C', 2, GameBoard.WHITE_STONE);
|
||||
assertFalse(gameState.playStone('A', 1, GameBoard.BLACK_STONE));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("A2"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("B1"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("B4"));
|
||||
gameState.playStone(Player.WHITE, Action.getInstance("C2"));
|
||||
|
||||
assertFalse(gameState.playStone(Player.BLACK, Action.getInstance("A1")));
|
||||
|
||||
List<Action> validMoves = new ValidMoveGenerator().getActions(new GameConfig(), gameState, Player.BLACK,0);
|
||||
|
||||
List<String> validMoves = new ValidMoveGenerator().getActions(new GameConfig(), gameState, "b",0);
|
||||
assertTrue(validMoves.size() > 0);
|
||||
for (String vm : validMoves) {
|
||||
|
||||
for (Action vm : validMoves) {
|
||||
System.out.println(vm);
|
||||
}
|
||||
assertFalse(validMoves.contains("A1"));
|
||||
|
||||
assertFalse(validMoves.contains(Action.getInstance("A1")));
|
||||
|
||||
System.out.println(gameState);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user