Skip to content

Commit

Permalink
Minimax algorithm now considers if a piece is in a jump sequence, sti…
Browse files Browse the repository at this point in the history
…ll not convinced it works though
  • Loading branch information
john committed Apr 30, 2016
1 parent 914d373 commit 00afb30
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 83 deletions.
145 changes: 91 additions & 54 deletions src/controller/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void requestMove(Move move) {
/* If the game is not in the middle of a jump sequence, move the thunk */
if (!inJumpSequence) {

Move thunkMove = getMinimaxMove(GameConstants.MAX_SEARCH_DEPTH);
Move thunkMove = getMinimaxMove(GameConstants.MAX_SEARCH_DEPTH, inJumpSequence);
if (thunkMove != null) {
if (thunkMove.isJump()) inJumpSequence = true;

Expand All @@ -62,8 +62,8 @@ public void requestMove(Move move) {
gamePanel.movePiece(thunkMove);

while (inJumpSequence) {
thunkMove = getMinimaxMove(GameConstants.MAX_SEARCH_DEPTH);
System.out.println("REPEATING MOVE");
thunkMove = getMinimaxMove(GameConstants.MAX_SEARCH_DEPTH, inJumpSequence);

if (thunkMove != null) {
if (movePromotesPiece(thunkMove)) {
inJumpSequence = false;
Expand Down Expand Up @@ -104,70 +104,107 @@ public Move getThunkMove() {
return null;
}
}

public Move getMinimaxMove(int depth, boolean currentlyIsInJumpSequence) {
// need to store the jump sequence at each call stack
Move bestMove = null;

public Move getMinimaxMove(int depth, boolean inJumpSequence) {
ArrayList<Board> boardFrontier = null;
ArrayList<Move> moveFrontier = null;
ArrayList<Integer> moveScores = new ArrayList<Integer>();

if (inJumpSequence) {
ArrayList<Board> boardFrontier = board.generateJumpFrontierForPiece(board.getLastPieceMoved());
ArrayList<Move> moveFrontier = board.generateJumpMovesForPiece(board.getLastPieceMoved());
ArrayList<Integer> moveScores = new ArrayList<Integer>();
/* Generate the frontier only for the piece that just moves */
boardFrontier = board.generateJumpFrontierForPiece(board.getLastPieceMoved());
moveFrontier = board.generateJumpMovesForPiece(board.getLastPieceMoved());

Color otherColor =
}
else {
ArrayList<Board> boardFrontier = board.generateFrontier(GameConstants.THUNK_COLOR);
ArrayList<Move> moveFrontier = board.generateAllMoves(GameConstants.THUNK_COLOR);
ArrayList<Integer> moveScores = new ArrayList<Integer>();

Color otherColor = GameConstants.THUNK_COLOR == Color.BLACK ?
Color.WHITE : Color.BLACK;
// Recurse for each one here
for (Board b : boardFrontier) {
moveScores.add(this.getMinimaxScore(otherColor, b, depth));
/* If we can't jump anymore, we can't make a move */
if (boardFrontier.isEmpty()) {
return null;
}

int maxScore = Integer.MIN_VALUE;


for (int i = 0; i < moveScores.size(); ++i) {
if (moveScores.get(i) > maxScore) {
bestMove = moveFrontier.get(i);
maxScore = moveScores.get(i);
}

} else {
/* Generate the frontier for all pieces */
boardFrontier = board.generateFrontier(GameConstants.THUNK_COLOR);
moveFrontier = board.generateAllMoves(GameConstants.THUNK_COLOR);
System.out.println("Board frontier size: " + boardFrontier.size());
System.out.println("Move frontier size: " + moveFrontier.size());
}

Color nextColor;
/* Determine the next color to move */
if (GameConstants.THUNK_COLOR == Color.BLACK && !inJumpSequence) {
nextColor = Color.WHITE;
} else {
nextColor = Color.BLACK;
}

/* Calculate the minimax score for each board in the frontier */
for (Board b : boardFrontier) {
moveScores.add(this.getMinimaxScore(nextColor, b, depth, inJumpSequence));
}

/* Determine the maximum minimax score and which move led to that score */
int maxScore = Integer.MIN_VALUE;
Move bestMove = null;

for (int i = 0; i < moveScores.size(); ++i) {
//System.out.println("score[" + i + "] = " + moveScores.get(i));
if (moveScores.get(i) > maxScore) {
//System.out.println("Best move is " + i);
bestMove = moveFrontier.get(i);
maxScore = moveScores.get(i);
}
}

return bestMove;
}

public int getMinimaxScore(Color color, Board b, int depth) {
public int getMinimaxScore(Color color, Board b, int depth, boolean inJumpSequence) {
ArrayList<Board> boardFrontier;
ArrayList<Integer> moveScores = new ArrayList<Integer>();

if (inJumpSequence) {
/* Generate the frontier only for the piece that just moves */
boardFrontier = b.generateJumpFrontierForPiece(b.getLastPieceMoved());

/* If we can't jump anymore, get out of the jump sequence */
if (boardFrontier.isEmpty()) {
inJumpSequence = false;
}
} else {
/* Generate the frontier for all pieces */
boardFrontier = b.generateFrontier(color);
}

/* If we have reached the maximum depth or an end state for the gam */
if (depth == 0 || b.getBlackPieces() == 0 || b.getWhitePieces() == 0
|| boardFrontier.size() == 0) {
Color otherColor = (color == Color.BLACK ? Color.WHITE : Color.BLACK);
return b.getHeuristic(otherColor);
}

Color nextColor;
/* Determine the next color to move */
if (GameConstants.THUNK_COLOR == Color.BLACK && !inJumpSequence) {
nextColor = Color.WHITE;
} else {
nextColor = Color.BLACK;
}

for (Board board : boardFrontier) {
int moveScore = getMinimaxScore(nextColor, board, depth - 1, inJumpSequence);
moveScores.add(moveScore);
}

if (color == GameConstants.THUNK_COLOR) {
/* Since these scores are obtained from when it is the other
* player's turn, we want to minimize....I think
*/
return Collections.max(moveScores);
}
else {
ArrayList<Board> boardFrontier = b.generateFrontier(color);
if (depth == 0 || b.getBlackPieces() == 0 || b.getWhitePieces() == 0
|| boardFrontier.size() == 0) {
Color otherColor = color == Color.BLACK ? Color.WHITE : Color.BLACK;
return b.getHeuristic(otherColor);
}

ArrayList<Integer> moveScores = new ArrayList<Integer>();

for (Board board : boardFrontier) {
Color nextColor = color == Color.BLACK ? Color.WHITE : Color.BLACK;
moveScores.add(getMinimaxScore(nextColor, board, depth - 1));
}

if (color == GameConstants.THUNK_COLOR) {
// Maximize
return Collections.max(moveScores);
}
else {
// Minimize
return Collections.min(moveScores);
}
// Minimize
return Collections.min(moveScores);
}

}

public void notifyClientWin() {
Expand Down
2 changes: 1 addition & 1 deletion src/controller/GameConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ public class GameConstants {
public static final Color THUNK_COLOR = Color.WHITE;
public static final Color USER_COLOR = Color.BLACK;
public static final int MAX_PASSIVE_MOVES = 50;
public static final int MAX_SEARCH_DEPTH = 2;
public static final int MAX_SEARCH_DEPTH = 4;
}
38 changes: 12 additions & 26 deletions src/model/Board.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,38 +153,24 @@ public ArrayList<Board> generateFrontier(Color color) {
*/
public ArrayList<Board> generateFrontierFromRegularMoves(Color color) {
ArrayList<Board> frontier = new ArrayList<Board>();
for (int i = 0; i < BOARD_SIZE; ++i) {
for (int j = 0; j < BOARD_SIZE; ++j) {
Piece p = this.representation[i][j];
if(null != p && p.getColor() == color) {
ArrayList<Move> moves = generateRegularMovesForPiece(this.representation[i][j]);
for (Move move : moves) {
Board board = new Board(this);
board.movePiece(move);
frontier.add(board);
}
}
}
ArrayList<Move> moves = generateAllRegularMoves(color);
for (Move move : moves) {
Board board = new Board(this);
board.movePiece(move);
frontier.add(board);
}
return frontier;
return frontier;
}

public ArrayList<Board> generateFrontierFromJumps(Color color) {
ArrayList<Board> frontier = new ArrayList<Board>();
for (int i = 0; i < BOARD_SIZE; ++i) {
for (int j = 0; j < BOARD_SIZE; ++j) {
Piece p = this.representation[i][j];
if (null != p && p.getColor() == color) {
ArrayList<Move> jump_moves = generateJumpMovesForPiece(this.representation[i][j]);
for (Move jump : jump_moves) {
Board board = new Board(this);
board.movePiece(jump);
frontier.add(board);
}
}
}
ArrayList<Move> moves = generateAllJumpMoves(color);
for (Move move : moves) {
Board board = new Board(this);
board.movePiece(move);
frontier.add(board);
}
return frontier;
return frontier;
}

public ArrayList<Move> generateMovesForPiece(Piece p) {
Expand Down
1 change: 0 additions & 1 deletion src/test/BoardTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
package test;

import model.Board;

public class BoardTest {
Expand Down
1 change: 0 additions & 1 deletion src/test/GameTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import controller.Game;
import model.Board;
import model.Color;
import view.CheckersWindow;

public class GameTest {
Expand Down

0 comments on commit 00afb30

Please sign in to comment.