diff --git a/src/backend/Board.java b/src/backend/Board.java index 1a8fd1d..f458d5a 100644 --- a/src/backend/Board.java +++ b/src/backend/Board.java @@ -631,5 +631,40 @@ public void playMove(Move move) { } return score; } + public enum GameResult { + ONGOING, // game still in progress + DRAW, // stalemate (or other draw condition) + WHITE_WINS, // black is checkmated + BLACK_WINS // white is checkmated + } + + /** + * @return the current game result: ONGOING, DRAW, WHITE_WINS or BLACK_WINS. + */ + public GameResult getGameResult() { + // if White is checkmated → Black wins + if (isCheckmate(true)) return GameResult.BLACK_WINS; + // if Black is checkmated → White wins + if (isCheckmate(false)) return GameResult.WHITE_WINS; + // if side to move has no legal moves but is not in check → stalemate + if (isStalemate(true) || isStalemate(false)) return GameResult.DRAW; + return GameResult.ONGOING; + } + + /** + * @param whitePlayer whose turn we're checking for stalemate + * @return true if whitePlayer is not in check and has no legal moves + */ + private boolean isStalemate(boolean whitePlayer) { + // must not be in check + if (isInCheck(whitePlayer)) return false; + // and have no legal moves + for (Piece p : pieces) { + if (p.isWhite() == whitePlayer && !getLegalMoves(p).isEmpty()) { + return false; + } + } + return true; + } +} -} \ No newline at end of file diff --git a/src/backend/Game.java b/src/backend/Game.java index 49ce7f5..6e889a2 100644 --- a/src/backend/Game.java +++ b/src/backend/Game.java @@ -1,6 +1,8 @@ package backend; import windowInterface.MyInterface; +import backend.Board.GameResult; + import java.nio.file.Path; import java.nio.file.Files; import java.nio.charset.StandardCharsets; @@ -16,6 +18,7 @@ public class Game extends Thread { private int LINE_NUM = 8; private int loopDelay = 250; private boolean[] activationAIFlags; + private boolean gameOver = false; // ← track when the game ends public Game(MyInterface mjfParam) { mjf = mjfParam; @@ -35,17 +38,19 @@ public class Game extends Thread { board = new Board(lines.toArray(new String[0])); // refresh UI for the new board state: mjf.update(board.getTurnNumber(), board.isTurnWhite()); + checkGameOver(); } // ─────────────────────────────────────────────────────────────────────── - public int getWidth() { return board.getWidth(); } - public int getHeight() { return board.getHeight(); } + public int getWidth() { return board.getWidth(); } + public int getHeight() { return board.getHeight(); } @Override public void run() { - while(true) { + while (!gameOver) { aiPlayerTurn(); mjf.update(board.getTurnNumber(), board.isTurnWhite()); + checkGameOver(); try { Thread.sleep(loopDelay); } catch (InterruptedException e) { e.printStackTrace(); } } @@ -58,7 +63,9 @@ public class Game extends Thread { private void aiPlayerTurn() { if (isAITurn()) { Move bestMove = aiPlayer.getBestMoveUsingNegamax(board, 2); - if (bestMove != null) board.playMove(bestMove); + if (bestMove != null) { + board.playMove(bestMove); + } } } @@ -67,7 +74,11 @@ public class Game extends Thread { System.out.println("Click out of bounds"); return; } - if (!isAITurn()) board.userTouch(x, y); + if (!isAITurn()) { + board.userTouch(x, y); + mjf.update(board.getTurnNumber(), board.isTurnWhite()); + checkGameOver(); + } } public void setPiece(boolean isWhite, PieceType type, int x, int y) { @@ -89,6 +100,8 @@ public class Game extends Thread { public void setBoard(String[] array) { board = new Board(array); + mjf.update(board.getTurnNumber(), board.isTurnWhite()); + checkGameOver(); } public Iterable getPieces() { @@ -105,9 +118,28 @@ public class Game extends Thread { public void undoLastMove() { board.undoLastMove(); + mjf.update(board.getTurnNumber(), board.isTurnWhite()); + gameOver = false; // allow play to continue after undo } public void toggleAI(boolean isWhite) { activationAIFlags[isWhite ? 1 : 0] = !activationAIFlags[isWhite ? 1 : 0]; } + + // ─── WIN/LOSE/DRAW logic ─────────────────────────────────────────────── + private void checkGameOver() { + GameResult res = board.getGameResult(); + if (res != GameResult.ONGOING) { + String msg; + switch (res) { + case WHITE_WINS: msg = "White wins!"; break; + case BLACK_WINS: msg = "Black wins!"; break; + case DRAW: msg = "Draw!"; break; + default: msg = ""; break; + } + mjf.setStepBanner(msg); + gameOver = true; + } + } + // ─────────────────────────────────────────────────────────────────────── }