Merge branch 'master' of woodyfolsom.net:/opt/git/cs8803p4

Conflicts:
	src/model/comPlayer/MonteCarloComPlayer.java
This commit is contained in:
Woody Folsom
2012-04-29 15:02:06 -04:00
10 changed files with 193 additions and 85 deletions

View File

@@ -11,16 +11,16 @@ public class Move {
private final TileColor color; private final TileColor color;
private final CellPointer cp; private final CellPointer cp;
public Move(TileColor color, int row, int column) { public Move(TileColor tlClr, CellPointer cllPntr) {
cp = new CellPointer(row,column);
this.color = color;
}
public Move(CellPointer cllPntr, TileColor tlClr) {
cp = cllPntr; cp = cllPntr;
color = tlClr; color = tlClr;
} }
public Move(TileColor color, int row, int column) {
cp = new CellPointer(row, column);
this.color = color;
}
public CellPointer getCell() { public CellPointer getCell() {
return cp; return cp;
} }

View File

@@ -20,12 +20,32 @@ public class Referee implements Runnable {
public static final String PLAYER_TURN = "Waiting for the player's move."; public static final String PLAYER_TURN = "Waiting for the player's move.";
public static boolean[] getBoardState(Board brd) {
boolean[] boardState = new boolean[(Board.NUM_COLS * Board.NUM_ROWS * (Board.TileColor
.values().length - 1))];
int i = 0;
for (int r = 0; r < Board.NUM_ROWS; r++) {
for (int c = 0; c < Board.NUM_COLS; c++) {
boardState[i] = (brd.getTile(r, c) == TileColor.BLUE);
boardState[i + 1] = (brd.getTile(r, c) == TileColor.GREEN);
boardState[i + 2] = (brd.getTile(r, c) == TileColor.RED);
boardState[i + 3] = (brd.getTile(r, c) == TileColor.YELLOW);
i += 4;
}
}
return boardState;
}
private Board board; private Board board;
private BoardPanel boardPanel; private BoardPanel boardPanel;
private final Player computerPlayer;
private final Player computerPlayer;
private final HumanPlayer humanPlayer = new HumanPlayer(); private final HumanPlayer humanPlayer = new HumanPlayer();
private final MainFrame mf; private final MainFrame mf;
private PlayerModel playerModel = null; private PlayerModel playerModel = null;
public Referee(MainFrame mnFrm, String player, Player computerPlayer) { public Referee(MainFrame mnFrm, String player, Player computerPlayer) {
@@ -43,24 +63,6 @@ public class Referee implements Runnable {
initGame(); initGame();
} }
public boolean[] getBoardState() {
boolean[] boardState = new boolean[getPlayerModel().getNumInputNodes()];
int i = 0;
for (int r = 0; r < Board.NUM_ROWS; r++) {
for (int c = 0; c < Board.NUM_COLS; c++) {
boardState[i] = (board.getTile(r, c) == TileColor.BLUE);
boardState[i + 1] = (board.getTile(r, c) == TileColor.GREEN);
boardState[i + 2] = (board.getTile(r, c) == TileColor.RED);
boardState[i + 3] = (board.getTile(r, c) == TileColor.YELLOW);
i += 4;
}
}
return boardState;
}
public Player getComputerPlayer() { public Player getComputerPlayer() {
return computerPlayer; return computerPlayer;
} }
@@ -162,26 +164,30 @@ public class Referee implements Runnable {
System.out System.out
.println("Interrupted while waiting for human to move!"); .println("Interrupted while waiting for human to move!");
} else { } else {
Move mv = humanPlayer.getMove(board); Move mv = humanPlayer.getMove(board, playerModel);
if (board.getTile(mv.getCell().r, mv.getCell().c) == TileColor.NONE) { if (board.getTile(mv.getCell().r, mv.getCell().c) == TileColor.NONE) {
playToken(humanPlayer.getMove(board)); playToken(humanPlayer.getMove(board, playerModel));
getPlayerModel().train(getMoveArray(mv)); getPlayerModel().train(getBoardState(board),
getMoveArray(mv));
} else { } else {
humanPlayer.denyMove(); humanPlayer.denyMove();
} }
} }
} else { } else {
Move mv = computerPlayer.getMove(board); Move mv = computerPlayer.getMove(board, getPlayerModel());
playToken(mv); playToken(mv);
// TODO
// This is the call that gets a prediction of a user's move. // This is the call that gets a prediction of a user's move.
// Some changes will probably be necessary to put it in the // Some changes will probably be necessary to put it in the
// right place and also to get the node weights. But... all in // right place and also to get the node weights. But... all in
// due time. // due time.
getPlayerModel().getOutputNodes(getBoardState()); // UPDATE: I made a neural network agent. This call is in there
// now. If the current agent doesn't use the neural network,
// then this doesn't need to be called. It will just train on
// random, meaningless data.
// getPlayerModel().getOutputNodes(getBoardState(board));
} }
mf.updateMessage(getMessage()); mf.updateMessage(getMessage());

View File

@@ -4,20 +4,21 @@ import model.Board;
import model.Move; import model.Move;
import model.comPlayer.generator.AlphaBetaMoveGenerator; import model.comPlayer.generator.AlphaBetaMoveGenerator;
import model.comPlayer.generator.MoveGenerator; import model.comPlayer.generator.MoveGenerator;
import model.playerModel.PlayerModel;
public class AlphaBetaComPlayer implements Player { public class AlphaBetaComPlayer implements Player {
private MoveGenerator moveGenerator = new AlphaBetaMoveGenerator(); private final MoveGenerator moveGenerator = new AlphaBetaMoveGenerator();
@Override
public Move getMove(Board board) {
return moveGenerator.genMove(board, false);
}
@Override @Override
public void denyMove() { public void denyMove() {
throw new UnsupportedOperationException("Not implemented"); throw new UnsupportedOperationException("Not implemented");
} }
@Override
public Move getMove(Board board, PlayerModel player) {
return moveGenerator.genMove(board, false);
}
@Override @Override
public boolean isReady() { public boolean isReady() {
return true; // always ready to play a random valid move return true; // always ready to play a random valid move

View File

@@ -1,32 +1,16 @@
package model.comPlayer; package model.comPlayer;
import model.Board; import model.Board;
import model.Board.TileColor;
import model.CellPointer; import model.CellPointer;
import model.Move; import model.Move;
import model.Board.TileColor; import model.playerModel.PlayerModel;
public class HumanPlayer implements Player { public class HumanPlayer implements Player {
private CellPointer cell = CellPointer.NONE; private CellPointer cell = CellPointer.NONE;
private boolean ready = false;
private TileColor color = TileColor.BLUE; private TileColor color = TileColor.BLUE;
private boolean ready = false;
@Override
public void denyMove() {
ready = false;
}
public TileColor getColor() {
return color;
}
@Override
public Move getMove(Board board) {
ready = false;
return new Move(cell, color);
}
public void decrementColor() { public void decrementColor() {
TileColor[] colors = Board.TileColor.values(); TileColor[] colors = Board.TileColor.values();
@@ -47,6 +31,22 @@ public class HumanPlayer implements Player {
color = colors[currentColor]; color = colors[currentColor];
} }
@Override
public void denyMove() {
ready = false;
}
public TileColor getColor() {
return color;
}
@Override
public Move getMove(Board board, PlayerModel player) {
ready = false;
return new Move(color, cell);
}
public void incrementColor() { public void incrementColor() {
TileColor[] colors = Board.TileColor.values(); TileColor[] colors = Board.TileColor.values();
int currentColor = -1; int currentColor = -1;

View File

@@ -4,22 +4,23 @@ import model.Board;
import model.Move; import model.Move;
import model.comPlayer.generator.MinimaxMoveGenerator; import model.comPlayer.generator.MinimaxMoveGenerator;
import model.comPlayer.generator.MoveGenerator; import model.comPlayer.generator.MoveGenerator;
import model.playerModel.PlayerModel;
public class MinimaxComPlayer implements Player{ public class MinimaxComPlayer implements Player {
private MoveGenerator moveGenerator = new MinimaxMoveGenerator(); private final MoveGenerator moveGenerator = new MinimaxMoveGenerator();
public MinimaxComPlayer() { public MinimaxComPlayer() {
super(); super();
} }
@Override @Override
public Move getMove(Board board) { public void denyMove() {
return moveGenerator.genMove(board, false); throw new UnsupportedOperationException("Not implemented");
} }
@Override @Override
public void denyMove() { public Move getMove(Board board, PlayerModel player) {
throw new UnsupportedOperationException("Not implemented"); return moveGenerator.genMove(board, false);
} }
@Override @Override

View File

@@ -4,12 +4,13 @@ import model.Board;
import model.Move; import model.Move;
import model.comPlayer.generator.MonteCarloMoveGenerator; import model.comPlayer.generator.MonteCarloMoveGenerator;
import model.comPlayer.generator.MoveGenerator; import model.comPlayer.generator.MoveGenerator;
import model.playerModel.PlayerModel;
public class MonteCarloComPlayer implements Player { public class MonteCarloComPlayer implements Player {
private MoveGenerator moveGenerator = new MonteCarloMoveGenerator(); private MoveGenerator moveGenerator = new MonteCarloMoveGenerator();
@Override @Override
public Move getMove(Board board) { public Move getMove(Board board, PlayerModel playerModel) {
return moveGenerator.genMove(board, false); return moveGenerator.genMove(board, false);
} }

View File

@@ -0,0 +1,91 @@
package model.comPlayer;
import model.Board;
import model.Board.TileColor;
import model.Move;
import model.Referee;
import model.playerModel.Node;
import model.playerModel.PlayerModel;
public class NeuralNetworkPlayer implements Player {
public static int getSmallest(double[] list) {
int index = 0;
for (int i = 0; i < list.length; i++) {
if (list[index] < list[i]) {
index = i;
}
}
return index;
}
@Override
public void denyMove() {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public Move getMove(Board board, PlayerModel player) {
Move mv = null;
Node[] nodes = player.getOutputNodes(Referee.getBoardState(board));
TileColor color = TileColor.BLUE;
double[] colorStrengths = new double[4];
colorStrengths[0] = nodes[0].strength();
colorStrengths[1] = nodes[1].strength();
colorStrengths[2] = nodes[2].strength();
colorStrengths[3] = nodes[3].strength();
switch (getSmallest(colorStrengths)) {
case 1:
color = TileColor.GREEN;
break;
case 2:
color = TileColor.RED;
break;
case 3:
color = TileColor.YELLOW;
break;
case 0:
default:
color = TileColor.BLUE;
}
int index = 4;
for (int i = 4; i < nodes.length; i++) {
if (nodes[i].strength() > nodes[index].strength()) {
index = i;
}
}
int i = 4;
loop: for (int r = 0; r < Board.NUM_ROWS; r++) {
for (int c = 0; c < Board.NUM_COLS; c++) {
if (i == index) {
mv = new Move(color, r, c);
break loop;
}
else {
i++;
}
}
}
return mv;
}
@Override
public boolean isReady() {
return true;
}
@Override
public String toString() {
return "Neural Network Player";
}
}

View File

@@ -2,21 +2,27 @@ package model.comPlayer;
import model.Board; import model.Board;
import model.Move; import model.Move;
import model.playerModel.PlayerModel;
public interface Player { public interface Player {
/** /**
* Instructs the Player to retract the last move. * Instructs the Player to retract the last move.
*/ */
public void denyMove(); public void denyMove();
/** /**
* Gets the player's move given the board state. Blocks if player is not ready. * Gets the player's move given the board state. Blocks if player is not
* ready.
*
* @param board * @param board
* @return * @return
*/ */
public Move getMove(Board board); public Move getMove(Board board, PlayerModel player);
/** /**
* Returns true if the player is ready to make a move (getMove() does not block). * Returns true if the player is ready to make a move (getMove() does not
* block).
*
* @return * @return
*/ */
public boolean isReady(); public boolean isReady();

View File

@@ -3,16 +3,21 @@ package model.comPlayer;
import java.util.Random; import java.util.Random;
import model.Board; import model.Board;
import model.Board.TileColor;
import model.CellPointer; import model.CellPointer;
import model.Move; import model.Move;
import model.Board.TileColor; import model.playerModel.PlayerModel;
public class RandomComPlayer implements Player { public class RandomComPlayer implements Player {
private final Random rand = new Random(); private final Random rand = new Random();
@Override @Override
public Move getMove(Board board) { public void denyMove() {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public Move getMove(Board board, PlayerModel player) {
TileColor tile = TileColor.BLUE; TileColor tile = TileColor.BLUE;
int r = -1; int r = -1;
int c = -1; int c = -1;
@@ -38,12 +43,7 @@ public class RandomComPlayer implements Player {
tile = TileColor.YELLOW; tile = TileColor.YELLOW;
} }
return new Move(new CellPointer(r, c), tile); return new Move(tile, new CellPointer(r, c));
}
@Override
public void denyMove() {
throw new UnsupportedOperationException("Not implemented");
} }
@Override @Override

View File

@@ -203,7 +203,9 @@ public class PlayerModel implements Serializable {
} }
} }
public void train(boolean[] example) { public void train(boolean[] boardState, boolean[] example) {
getOutputNodes(boardState);
if (example.length == outputNode.length) { if (example.length == outputNode.length) {
for (int i = 0; i < outputNode.length; i++) { for (int i = 0; i < outputNode.length; i++) {
outputNode[i].learn(example[i]); outputNode[i].learn(example[i]);