From 17aa7c7ccb5427a841635d8321770ac870d39a0a Mon Sep 17 00:00:00 2001 From: ElnuDev Date: Mon, 13 Mar 2023 18:38:34 -0700 Subject: [PATCH] Prevent moving into check, implement checkmate detection --- src/Board.java | 31 +++++++++++++++++++++++++++---- src/Piece.java | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/Board.java b/src/Board.java index 66d5385..17a01f3 100644 --- a/src/Board.java +++ b/src/Board.java @@ -15,6 +15,8 @@ public class Board { // Colors are represented in hexadecimal, so we can write the hex literal by prefixing the color code with 0x static final Color BLACK = new Color(0x6c595c); static final Color WHITE = new Color(0xab9b8e); + King blackKing; + King whiteKing; final DrawingPanel panel; final Graphics graphics; @@ -50,7 +52,13 @@ public class Board { } else if(j == 2 || j == 5){ set(j, i, new Bishop(i==0, panel)); } else if(j == 4){ - set(j, i, new King(i==0, panel)); + if (i == 0) { + blackKing = new King(true, panel); + set(j, i, blackKing); + } else { + whiteKing = new King(false, panel); + set(j, i, whiteKing); + } } else { set(j, i, new Queen(i==0, panel)); } @@ -90,13 +98,15 @@ public class Board { set(coordinate.x, coordinate.y, piece); } - public void move(int fromX, int fromY, int toX, int toY) { + public Piece move(int fromX, int fromY, int toX, int toY) { + Piece captured = get(toX, toY); set(toX, toY, get(fromX, fromY)); set(fromX, fromY, null); + return captured; } - public void move(BoardCoordinate from, BoardCoordinate to) { - move(from.x, from.y, to.x, to.y); + public Piece move(BoardCoordinate from, BoardCoordinate to) { + return move(from.x, from.y, to.x, to.y); } // Mouse down event handler @@ -123,6 +133,19 @@ public class Board { for (BoardCoordinate legalMove : legalMoves) { if (newCoordinate.equals(legalMove)) { move(dragging, newCoordinate); + // QUICK TESTING CODE + Piece movedPiece = get(newCoordinate); + King oppositeKing = movedPiece.black ? whiteKing : blackKing; + BoardCoordinate oppositeKingPosition = null; + boolean inCheck = false; + for (BoardCoordinate move : movedPiece.getLegalMoves(newCoordinate, this)) { + if (get(move) == oppositeKing) { + oppositeKingPosition = move; + inCheck = true; + break; + } + } + if (inCheck && oppositeKing.getLegalMoves(oppositeKingPosition, this).size() == 0) System.out.println("Checkmate"); break; } } diff --git a/src/Piece.java b/src/Piece.java index e092656..c4e0b66 100644 --- a/src/Piece.java +++ b/src/Piece.java @@ -1,5 +1,6 @@ import java.awt.*; import java.awt.image.ImageObserver; +import java.lang.reflect.Array; import java.util.ArrayList; public abstract class Piece { @@ -16,6 +17,10 @@ public abstract class Piece { public abstract ArrayList getPossibleMoves(BoardCoordinate position, Board board); public ArrayList getLegalMoves(BoardCoordinate position, Board board) { + return getLegalMoves(position, board, true); + } + + public ArrayList getLegalMoves(BoardCoordinate position, Board board, boolean doCheckChecks) { ArrayList legalMoves = getPossibleMoves(position, board); for (int i = 0; i < legalMoves.size(); i++) { BoardCoordinate possibleMove = legalMoves.get(i); @@ -28,7 +33,11 @@ public abstract class Piece { possibleMove.x < 0 || possibleMove.y < 0 || possibleMove.x >= Board.BOARD_SIZE || - possibleMove.y >= Board.BOARD_SIZE) { + possibleMove.y >= Board.BOARD_SIZE || + + // is in check + (doCheckChecks && isInCheck(position, possibleMove, board)) + ) { legalMoves.remove(i); i--; } @@ -37,6 +46,28 @@ public abstract class Piece { return legalMoves; } + boolean isInCheck(BoardCoordinate from, BoardCoordinate to, Board board) { + boolean isInCheck = false; + Piece captured = board.move(from, to); + outer: for (int y = 0; y < Board.BOARD_SIZE; y++) { + for (int x = 0; x < Board.BOARD_SIZE; x++) { + Piece piece = board.get(x, y); + if (piece == null || piece.black == black) continue; + ArrayList legalMoves = piece.getLegalMoves(new BoardCoordinate(x, y), board, false); + for (BoardCoordinate move : legalMoves) { + Piece pieceAtMove = board.get(move); + if (pieceAtMove instanceof King) { + isInCheck = true; + break outer; + } + } + } + } + board.move(to, from); + board.set(to, captured); + return isInCheck; + } + // The Piece class doesn't store position, // so when drawing we need to be provided this along with a graphics context when drawing public void draw(Graphics graphics, ImageObserver observer, int x, int y) {