Merge branch 'master' of woodyfolsom.net:/opt/git/cs8803p4
Conflicts: src/model/comPlayer/MonteCarloComPlayer.java
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
91
src/model/comPlayer/NeuralNetworkPlayer.java
Normal file
91
src/model/comPlayer/NeuralNetworkPlayer.java
Normal 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";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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]);
|
||||||
|
|||||||
Reference in New Issue
Block a user