Skip to content

Commit

Permalink
Fixed Phase 2
Browse files Browse the repository at this point in the history
  • Loading branch information
mssalkhalifah committed Jul 12, 2020
1 parent 510e3f7 commit ab463a9
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 24 deletions.
25 changes: 11 additions & 14 deletions core/src/com/groupg/game/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,34 @@ public Game(MyGame myGame) {
}

public void update(float delta) {
Player player = (gameState.getCurrentTurn()) ? whitePlayer : blackPlayer;
player.update(delta);

gameBoard.update(delta, player.getMousePosition());
whitePlayer.update(delta);

gameBoard.update(delta, whitePlayer.getMousePosition());
gameState.update(delta);

// If is the black player turn
if (!gameState.getCurrentTurn()) {
int bestNextPosition = MiniMax.getBestOpeningPhaseMove(gameBoard, gameState);
player.setTouchPosition(PointsPosition.getPointPosition(bestNextPosition));
player.setAction(true);
MiniMax.getBestOpeningPhaseMove(gameBoard, gameState, blackPlayer);
}

if (player.isPlay() || blackPlayer.isAction()) {
if (whitePlayer.isPlay() && gameState.getCurrentTurn()) {
System.out.println("Current game board: \n" + gameBoard);
switch (gameState.getGameStates().peek()) {
case FIRST_PHASE:
gameState.firstPhase(player);
gameState.firstPhase(whitePlayer);
break;

case SECOND_PHASE:
gameState.secondPhase(player);
gameState.secondPhase(whitePlayer);
break;

case CAPTURE:
gameState.captureState(player);
gameState.captureState(whitePlayer);
break;

case MOVE:
gameState.movingState(player);
gameState.movingState(whitePlayer, false);
break;

case FINISH:
Expand All @@ -63,11 +62,9 @@ public void update(float delta) {
default:
throw new IllegalArgumentException("Unknown game state");
}
player.setAction(false);
//player.setAction(false);
System.out.println("Updated game board: \n" + gameBoard + "\n");
}

gameState.update(delta);
}

public void render(float delta, SpriteBatch batch) {
Expand Down
6 changes: 4 additions & 2 deletions core/src/com/groupg/game/GameState.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,10 @@ public void secondPhase(Player player) {
}
}

public void movingState(Player player) {
player.setSelectedPiece(board.getSelectPiece(player.getPieceColor(), player.getTouchPosition()));
public void movingState(Player player, boolean isAI) {
if (!isAI) {
player.setSelectedPiece(board.getSelectPiece(player.getPieceColor(), player.getTouchPosition()));
}
if (gameRule.checkMoveValid(player.getSelectedPiece().getPieceNumber(), player.getTouchPosition(), player.getPieceColor())) {
if (gameRule.checkMill(player.getSelectedPiece().getPieceNumber(), board.getBitBoard(player.getPieceColor()))) {
gameStates.pop();
Expand Down
41 changes: 38 additions & 3 deletions core/src/com/groupg/game/ai/GenerateMove.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.groupg.game.board.Board;
import com.groupg.game.board.PointsPosition;
import com.groupg.game.gameobject.PieceColor;
import com.groupg.game.gameobject.Point;

import java.util.ArrayList;
import java.util.BitSet;
Expand All @@ -13,10 +14,44 @@ public static ArrayList<Board> getMidPhasePossibleStates(Board currentBoardState

for (int i = 0; i < PointsPosition.NUMBER_OF_POINTS; i++) {
if (isMaximizer) {
// Get all possible move for the maximizer
if (currentBoardState.getBitBoard(PieceColor.BLACK).get(i)) {
Board copyCurrentBoard = currentBoardState.getCopy();
ArrayList<Integer> adjacentPosition = PointsPosition.getAdjacentLocation(i);
for (int location : adjacentPosition) {
if (copyCurrentBoard.isEmptyPoint(location)) {
copyCurrentBoard.getBitBoard(PieceColor.BLACK).set(location);
copyCurrentBoard.getBitBoard(PieceColor.BLACK).clear(i);

if (PointsPosition.checkMill(location, copyCurrentBoard.getBitBoard(PieceColor.BLACK))) {
possibleBoardStates = getAllRemoveStates(copyCurrentBoard, possibleBoardStates, true);
} else {
possibleBoardStates.add(copyCurrentBoard);
}
}
}
}
} else { // Get all possible move for the minimizer
if (currentBoardState.getBitBoard(PieceColor.WHITE).get(i)) {
Board copyCurrentBoard = currentBoardState.getCopy();
ArrayList<Integer> adjacentPosition = PointsPosition.getAdjacentLocation(i);
for (int location : adjacentPosition) {
if (copyCurrentBoard.isEmptyPoint(location)) {
copyCurrentBoard.getBitBoard(PieceColor.WHITE).set(location);
copyCurrentBoard.getBitBoard(PieceColor.WHITE).clear(i);

if (PointsPosition.checkMill(location, copyCurrentBoard.getBitBoard(PieceColor.WHITE))) {
possibleBoardStates = getAllRemoveStates(copyCurrentBoard, possibleBoardStates, false);
} else {
possibleBoardStates.add(copyCurrentBoard);
}
}
}
}
}
}
return null;

return possibleBoardStates;
}

public static ArrayList<Board> getOpeningPhasePossibleStates(Board currentBoardState, boolean isMaximizer) {
Expand All @@ -29,14 +64,14 @@ public static ArrayList<Board> getOpeningPhasePossibleStates(Board currentBoardS
if (isMaximizer) {
copyCurrentBoard.setPositionValue(PieceColor.BLACK, i);
if (PointsPosition.checkMill(i, copyCurrentBoard.getBitBoard(PieceColor.BLACK))) {
possibleBoardStates = (getAllRemoveStates(copyCurrentBoard, possibleBoardStates, true));
possibleBoardStates = getAllRemoveStates(copyCurrentBoard, possibleBoardStates, true);
} else {
possibleBoardStates.add(copyCurrentBoard);
}
} else {
copyCurrentBoard.setPositionValue(PieceColor.WHITE, i);
if (PointsPosition.checkMill(i, copyCurrentBoard.getBitBoard(PieceColor.WHITE))) {
possibleBoardStates = (getAllRemoveStates(copyCurrentBoard, possibleBoardStates, false));
possibleBoardStates = getAllRemoveStates(copyCurrentBoard, possibleBoardStates, false);
} else {
possibleBoardStates.add(copyCurrentBoard);
}
Expand Down
107 changes: 102 additions & 5 deletions core/src/com/groupg/game/ai/MiniMax.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
import com.groupg.game.board.Board;
import com.groupg.game.board.PointsPosition;
import com.groupg.game.gameobject.PieceColor;
import com.groupg.game.gameobject.Point;
import com.groupg.game.player.Player;

import java.util.ArrayList;
import java.util.BitSet;

public class MiniMax {
public static int count = 0;
public static Evaluation finalEvaluation = new Evaluation();

public static int getBestOpeningPhaseMove(Board board, GameState gameState) {
public static int getBestOpeningPhaseMove(Board board, GameState gameState, Player blackPlayer) {
int bestValue = Integer.MIN_VALUE;
int bestMovePosition = -1;

Expand All @@ -35,6 +36,8 @@ public static int getBestOpeningPhaseMove(Board board, GameState gameState) {
}
}
}
blackPlayer.setTouchPosition(PointsPosition.getPointPosition(bestMovePosition));
gameState.firstPhase(blackPlayer);
} else if (gameState.getGameStates().peek() == State.CAPTURE) {
for (int i = 0; i < PointsPosition.NUMBER_OF_POINTS; i++) {
if (!PointsPosition.checkMill(i, board.getBitBoard(PieceColor.WHITE))) {
Expand All @@ -53,15 +56,70 @@ public static int getBestOpeningPhaseMove(Board board, GameState gameState) {
}
}
}
System.out.println(bestMovePosition + "<- Best Move");
blackPlayer.setTouchPosition(PointsPosition.getPointPosition(bestMovePosition));
gameState.captureState(blackPlayer);
// System.out.println(bestMovePosition + "<- Best Move");
} else if (gameState.getGameStates().peek() == State.SECOND_PHASE) {
int currentPosition = -1;
for (int i = 0; i < PointsPosition.NUMBER_OF_POINTS; i++) {
if (board.getBitBoard(PieceColor.BLACK).get(i)) {
ArrayList<Integer> adjacentPosition = PointsPosition.getAdjacentLocation(i);
for (int location : adjacentPosition) {
if (board.isEmptyPoint(location)) {
// AI moves the piece
board.getBitBoard(PieceColor.BLACK).set(location);
board.getBitBoard(PieceColor.BLACK).clear(i);

int moveValue = miniMax(board, 5, Integer.MIN_VALUE, Integer.MAX_VALUE, false, gameState);

// Undo the move
board.getBitBoard(PieceColor.BLACK).clear(location);
board.getBitBoard(PieceColor.BLACK).set(i);

if (moveValue > bestValue) {
currentPosition = i;
bestMovePosition = location;
bestValue = moveValue;
}
}
}
}
}
blackPlayer.setTouchPosition(PointsPosition.getPointPosition(bestMovePosition));
blackPlayer.setSelectedPiece(board.getSelectPiece(PieceColor.BLACK, PointsPosition.getPointPosition(currentPosition)));
gameState.getGameStates().push(State.MOVE);
gameState.movingState(blackPlayer, true);
}

System.out.println("States visited = " + count);
count = 0;
return bestMovePosition;
}

private static int miniMax(Board board, int depth, int alpha, int beta, boolean isMaximizer, GameState gameState) {
switch (gameState.getGameStates().peek()) {
case FIRST_PHASE:
return miniMaxFirstPhase(board, depth, alpha, beta, isMaximizer, gameState);

case SECOND_PHASE:
return miniMaxSecondPhase(board, depth, alpha, beta, isMaximizer, gameState);

default:
if (gameState.getGameStates().peek() == State.CAPTURE) {
State temp = gameState.getGameStates().pop();
int moveValue = 0;
if (gameState.getGameStates().peek() == State.FIRST_PHASE) {
moveValue = miniMaxFirstPhase(board, depth, alpha, beta, isMaximizer, gameState);
} else if (gameState.getGameStates().peek() == State.SECOND_PHASE) {
moveValue = miniMaxSecondPhase(board, depth, alpha, beta, isMaximizer, gameState);
}
gameState.getGameStates().push(temp);
return moveValue;
}
}
throw new IllegalArgumentException("Invalid State");
}

private static int miniMaxFirstPhase(Board board, int depth, int alpha, int beta, boolean isMaximizer, GameState gameState) {
// If reached depth limit or no available legal move return the evaluation
if (depth == 0 || !checkAvailableLegalMove(board, isMaximizer, gameState)) {
return openingPhaseStaticEvaluation(board);
Expand Down Expand Up @@ -96,6 +154,45 @@ private static int miniMax(Board board, int depth, int alpha, int beta, boolean
}
}

private static int miniMaxSecondPhase(Board board, int depth, int alpha, int beta, boolean isMaximizer, GameState gameState) {
// If reached depth limit or no available legal move return the evaluation
if (depth == 0 || !checkAvailableLegalMove(board, isMaximizer, gameState)) {
return midPhaseStaticEvaluation(board);
}

ArrayList<Board> currentPossibleBoardStates;

if (isMaximizer) {
int maxEvaluation = Integer.MIN_VALUE;
currentPossibleBoardStates = GenerateMove.getMidPhasePossibleStates(board, true);
for (Board state : currentPossibleBoardStates) {
int evaluation = miniMax(state, depth - 1, alpha, beta, false, gameState);
maxEvaluation = Math.max(maxEvaluation, evaluation);
alpha = Math.max(alpha, evaluation);
if (beta <= alpha) {
break;
}
}
return maxEvaluation;
} else {
int minEvaluation = Integer.MAX_VALUE;
currentPossibleBoardStates = GenerateMove.getMidPhasePossibleStates(board, false);
for (Board state : currentPossibleBoardStates) {
int evaluation = miniMax(state, depth - 1, alpha, beta, true, gameState);
minEvaluation = Math.min(minEvaluation, evaluation);
beta = Math.min(beta, evaluation);
if (beta <= alpha) {
break;
}
}
return minEvaluation;
}
}

private static int midPhaseStaticEvaluation(Board board) {
return openingPhaseStaticEvaluation(board);
}

private static int openingPhaseStaticEvaluation(Board board) {
count++;

Expand Down Expand Up @@ -223,7 +320,7 @@ private static boolean checkAvailableLegalMove(Board board, boolean isMaximizer,
if (board.getBitBoard(PieceColor.BLACK).get(i)) blackPieces++;
}

//if (whitePieces < 3 || blackPieces < 3) return false;
if ((whitePieces < 3 || blackPieces < 3) && gameState.getGameStates().peek() == State.SECOND_PHASE) return false;

boolean[] availableMoves = new boolean[checkAvailableMoveBitBoard.size()];

Expand Down
1 change: 1 addition & 0 deletions core/src/com/groupg/game/player/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public void setPieceColor(PieceColor pieceColor) {

public void setTouchPosition(Vector3 touchPosition) {
this.touchPosition = touchPosition;
//camera.unproject(touchPosition);
}

public Vector3 getTouchPosition() {
Expand Down

0 comments on commit ab463a9

Please sign in to comment.