Prevent moving into check, implement checkmate detection

main
Elnu 2 years ago
parent 17b506922a
commit 17aa7c7ccb

@ -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 // 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 BLACK = new Color(0x6c595c);
static final Color WHITE = new Color(0xab9b8e); static final Color WHITE = new Color(0xab9b8e);
King blackKing;
King whiteKing;
final DrawingPanel panel; final DrawingPanel panel;
final Graphics graphics; final Graphics graphics;
@ -50,7 +52,13 @@ public class Board {
} else if(j == 2 || j == 5){ } else if(j == 2 || j == 5){
set(j, i, new Bishop(i==0, panel)); set(j, i, new Bishop(i==0, panel));
} else if(j == 4){ } 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 { } else {
set(j, i, new Queen(i==0, panel)); set(j, i, new Queen(i==0, panel));
} }
@ -90,13 +98,15 @@ public class Board {
set(coordinate.x, coordinate.y, piece); 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(toX, toY, get(fromX, fromY));
set(fromX, fromY, null); set(fromX, fromY, null);
return captured;
} }
public void move(BoardCoordinate from, BoardCoordinate to) { public Piece move(BoardCoordinate from, BoardCoordinate to) {
move(from.x, from.y, to.x, to.y); return move(from.x, from.y, to.x, to.y);
} }
// Mouse down event handler // Mouse down event handler
@ -123,6 +133,19 @@ public class Board {
for (BoardCoordinate legalMove : legalMoves) { for (BoardCoordinate legalMove : legalMoves) {
if (newCoordinate.equals(legalMove)) { if (newCoordinate.equals(legalMove)) {
move(dragging, newCoordinate); 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; break;
} }
} }

@ -1,5 +1,6 @@
import java.awt.*; import java.awt.*;
import java.awt.image.ImageObserver; import java.awt.image.ImageObserver;
import java.lang.reflect.Array;
import java.util.ArrayList; import java.util.ArrayList;
public abstract class Piece { public abstract class Piece {
@ -16,6 +17,10 @@ public abstract class Piece {
public abstract ArrayList<BoardCoordinate> getPossibleMoves(BoardCoordinate position, Board board); public abstract ArrayList<BoardCoordinate> getPossibleMoves(BoardCoordinate position, Board board);
public ArrayList<BoardCoordinate> getLegalMoves(BoardCoordinate position, Board board) { public ArrayList<BoardCoordinate> getLegalMoves(BoardCoordinate position, Board board) {
return getLegalMoves(position, board, true);
}
public ArrayList<BoardCoordinate> getLegalMoves(BoardCoordinate position, Board board, boolean doCheckChecks) {
ArrayList<BoardCoordinate> legalMoves = getPossibleMoves(position, board); ArrayList<BoardCoordinate> legalMoves = getPossibleMoves(position, board);
for (int i = 0; i < legalMoves.size(); i++) { for (int i = 0; i < legalMoves.size(); i++) {
BoardCoordinate possibleMove = legalMoves.get(i); BoardCoordinate possibleMove = legalMoves.get(i);
@ -28,7 +33,11 @@ public abstract class Piece {
possibleMove.x < 0 || possibleMove.x < 0 ||
possibleMove.y < 0 || possibleMove.y < 0 ||
possibleMove.x >= Board.BOARD_SIZE || 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); legalMoves.remove(i);
i--; i--;
} }
@ -37,6 +46,28 @@ public abstract class Piece {
return legalMoves; 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<BoardCoordinate> 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, // The Piece class doesn't store position,
// so when drawing we need to be provided this along with a graphics context when drawing // 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) { public void draw(Graphics graphics, ImageObserver observer, int x, int y) {