diff --git a/src/chess/Bishop.java b/src/chess/Bishop.java index 634f564..7f6d1a6 100644 --- a/src/chess/Bishop.java +++ b/src/chess/Bishop.java @@ -22,6 +22,6 @@ public class Bishop extends ChessPiece { @Override public ArrayList getMoves() { - return new ArrayList(super.getDiagonalMoves(b.size())); + return prune(super.getDiagonalMoves(b.size())); } } diff --git a/src/chess/Board.java b/src/chess/Board.java index b6a4941..13ed094 100644 --- a/src/chess/Board.java +++ b/src/chess/Board.java @@ -56,9 +56,9 @@ public class Board { // if we were unable to set the piece down we failed to move the piece if (!set(m, selectedPiece)) return false; + selectedPiece.move(m); // run special conditions. Only matters for pieces which have special conditions, since is defaulted to empty body. - if (movedPiece != null) - selectedPiece.applySpecialMove(m); + selectedPiece.applySpecialMove(m); set(x, y, null); return true; } @@ -66,6 +66,8 @@ public class Board { } public ChessPiece get(Move m){ + if (m == null) + return null; return get(m.getX(), m.getY()); } @@ -78,10 +80,12 @@ public class Board { } public boolean set(Move m, ChessPiece piece) { + if (m == null) + return false; return set(m.getX(), m.getY(), piece); } - protected boolean set(int x, int y, ChessPiece piece){ + public boolean set(int x, int y, ChessPiece piece){ if (x < 0 || x >= board.length) return false; if (y < 0 || y >= board.length) @@ -90,6 +94,14 @@ public class Board { return true; } + protected Move checkIfMoveValid(Move m, boolean isWhite){ + if (m == null) + return null; + if (get(m) != null && get(m).isWhite == isWhite) + return null; + return m; + } + public int size(){ return board.length; } diff --git a/src/chess/ChessPiece.java b/src/chess/ChessPiece.java index 5a960ad..bf4365a 100644 --- a/src/chess/ChessPiece.java +++ b/src/chess/ChessPiece.java @@ -8,7 +8,7 @@ public abstract class ChessPiece { protected Board b; protected int x, y; protected boolean isInDanger, isWhite; - protected boolean isFirstMove = true; + protected int moveCount = 0; public ChessPiece(Board b, boolean isWhite, int x, int y) { this.b = b; @@ -29,11 +29,16 @@ public abstract class ChessPiece { } public boolean isFirstMove(){ - return isFirstMove; + return moveCount < 1; + } + public boolean isSecondMove(){ + return moveCount <= 1; } - public void setMoved(){ - isFirstMove = false; + public void move(Move m){ + this.x = m.getX(); + this.y = m.getY(); + this.moveCount++; } public abstract ArrayList getMoves(); @@ -42,26 +47,81 @@ public abstract class ChessPiece { protected ArrayList getCardinalMoves(int length){ ArrayList moves = new ArrayList(); + // cardinals for (int i = 1; i <= length; i++){ - // cardinals - moves.add(new Move(x - i, y)); - moves.add(new Move(x + i, y)); - moves.add(new Move(x, y - i)); - moves.add(new Move(x, y + i)); + if (add(moves, new Move(x - i, y))) + break; + } + for (int i = 1; i <= length; i++){ + if (add(moves, new Move(x + i, y))) + break; + } + for (int i = 1; i <= length; i++){ + if (add(moves, new Move(x, y - i))) + break; + } + for (int i = 1; i <= length; i++){ + if (add(moves, new Move(x, y + i))) + break; } return moves; } protected ArrayList getDiagonalMoves(int length){ ArrayList moves = new ArrayList(); + // diagonals for (int i = 1; i <= length; i++){ - // cardinals - moves.add(new Move(x - i, y - i)); - moves.add(new Move(x + i, y + i)); - moves.add(new Move(x + i, y - i)); - moves.add(new Move(x - i, y + i)); + if (add(moves, new Move(x - i, y - i))) + break; + } + for (int i = 1; i <= length; i++){ + if (add(moves, new Move(x - i, y + i))) + break; + } + for (int i = 1; i <= length; i++){ + if (add(moves, new Move(x + i, y - i))) + break; + } + for (int i = 1; i <= length; i++){ + if (add(moves, new Move(x + i, y + i))) + break; } return moves; } + protected ArrayList prune(ArrayList moves){ + var prunedMoves = new ArrayList(); + // get rid of impossible moves + for (Move m : moves){ + if (m == null) + continue; + if (m.getX() < 0 || m.getX() >= b.size()) + continue; + if (m.getY() < 0 || m.getY() >= b.size()) + continue; + prunedMoves.add(m); + } + + return prunedMoves; + } + + /** + * Checks to make sure that the proposed move is valid. + * @param moves array to add to + * @param move move to add to the array + * @return true if we need to stop here. (Break the loop) + */ + private boolean add(ArrayList moves, Move move){ + var m = b.get(move); + if (m != null && m.isWhite != isWhite) { + moves.add(b.checkIfMoveValid(move, isWhite)); + return true; + } else { + if (m != null) + return true; + moves.add(b.checkIfMoveValid(move, isWhite)); + } + return false; + } + } diff --git a/src/chess/King.java b/src/chess/King.java index 7fe8025..486ec09 100644 --- a/src/chess/King.java +++ b/src/chess/King.java @@ -25,22 +25,22 @@ public class King extends ChessPiece { ArrayList moves = new ArrayList(); moves.addAll(super.getCardinalMoves(1)); moves.addAll(super.getDiagonalMoves(1)); - if (isFirstMove){ + if (isFirstMove()){ ChessPiece rook = null; // castling if (isWhite){ if ((rook = b.get(0, 0)) != null && checkIfRookValid(rook)) - moves.add(new Move(2, 0, Move.SpecialConditions.leftCastle)); + moves.add(b.checkIfMoveValid(new Move(2, 0, Move.SpecialConditions.leftCastle), isWhite)); if ((rook = b.get(b.size() - 1, 0)) != null && checkIfRookValid(rook)) - moves.add(new Move(b.size() - 2, 0, Move.SpecialConditions.rightCastle)); + moves.add(b.checkIfMoveValid(new Move(b.size() - 2, 0, Move.SpecialConditions.rightCastle), isWhite)); } else { if ((rook = b.get(0, b.size()-1)) != null && checkIfRookValid(rook)) - moves.add(new Move(2, b.size()-1, Move.SpecialConditions.leftCastle)); + moves.add(b.checkIfMoveValid(new Move(2, b.size()-1, Move.SpecialConditions.leftCastle), isWhite)); if ((rook = b.get(b.size() - 1, b.size()-1)) != null && checkIfRookValid(rook)) - moves.add(new Move(b.size() - 2, b.size()-1, Move.SpecialConditions.rightCastle)); + moves.add(b.checkIfMoveValid(new Move(b.size() - 2, b.size()-1, Move.SpecialConditions.rightCastle), isWhite)); } } - return moves; + return prune(moves); } @Override @@ -54,9 +54,9 @@ public class King extends ChessPiece { private void castleRight(){ // casting has to move the rook on the right size of the king from white's perspective - if (this.isWhite) - b.set(b.size()-3, 0, b.get(b.size()-1, 0)); - else + if (this.isWhite) { + b.set(b.size() - 3, 0, b.get(b.size() - 1, 0)); + } else b.set(b.size()-3, b.size()-1, b.get(b.size()-1, b.size()-1)); } diff --git a/src/chess/Knight.java b/src/chess/Knight.java index 9329d84..cc8ef4e 100644 --- a/src/chess/Knight.java +++ b/src/chess/Knight.java @@ -23,14 +23,14 @@ public class Knight extends ChessPiece { @Override public ArrayList getMoves() { ArrayList moves = new ArrayList(); - moves.add(new Move(x + 2, y + 1)); - moves.add(new Move(x + 2, y - 1)); - moves.add(new Move(x - 2, y + 1)); - moves.add(new Move(x - 2, y - 1)); - moves.add(new Move(x - 1, y - 2)); - moves.add(new Move(x + 1, y - 2)); - moves.add(new Move(x - 1, y + 2)); - moves.add(new Move(x + 1, y + 2)); - return moves; + moves.add(b.checkIfMoveValid(new Move(x + 2, y + 1), isWhite)); + moves.add(b.checkIfMoveValid(new Move(x + 2, y - 1), isWhite)); + moves.add(b.checkIfMoveValid(new Move(x - 2, y + 1), isWhite)); + moves.add(b.checkIfMoveValid(new Move(x - 2, y - 1), isWhite)); + moves.add(b.checkIfMoveValid(new Move(x - 1, y - 2), isWhite)); + moves.add(b.checkIfMoveValid(new Move(x + 1, y - 2), isWhite)); + moves.add(b.checkIfMoveValid(new Move(x - 1, y + 2), isWhite)); + moves.add(b.checkIfMoveValid(new Move(x + 1, y + 2), isWhite)); + return prune(moves); } } diff --git a/src/chess/Pawn.java b/src/chess/Pawn.java index 808b37f..4c210f1 100644 --- a/src/chess/Pawn.java +++ b/src/chess/Pawn.java @@ -24,38 +24,45 @@ public class Pawn extends ChessPiece { public ArrayList getMoves() { ArrayList moves = new ArrayList(); if (isWhite) { - moves.add(new Move(x, y + 1)); - if (isFirstMove) - moves.add(new Move(x, y + 2)); + moves.add(b.checkIfMoveValid(pawnForwardMoveValid(new Move(x, y + 1)), isWhite)); + if (isFirstMove()) + moves.add(b.checkIfMoveValid(new Move(x, y + 2), isWhite)); } else { - moves.add(new Move(x, y - 1)); - if (isFirstMove) - moves.add(new Move(x, y - 2)); + moves.add(b.checkIfMoveValid(pawnForwardMoveValid(new Move(x, y - 1)), isWhite)); + if (isFirstMove()) + moves.add(b.checkIfMoveValid(new Move(x, y - 2), isWhite)); } ChessPiece neighbour = null; if (isWhite){ // En passant if ((neighbour = b.get(x-1, y)) != null && checkNeighbourEnPassant(neighbour)) - moves.add(new Move(x-1, y + 1, Move.SpecialConditions.leftEnPassant)); + moves.add(b.checkIfMoveValid(pawnForwardMoveValid(new Move(x-1, y + 1, Move.SpecialConditions.leftEnPassant)), isWhite)); // En passant if ((neighbour = b.get(x+1, y)) != null && checkNeighbourEnPassant(neighbour)) - moves.add(new Move(x+1, + 1, Move.SpecialConditions.rightEnPassant)); + moves.add(b.checkIfMoveValid(pawnForwardMoveValid(new Move(x+1, + 1, Move.SpecialConditions.rightEnPassant)), isWhite)); } else { // unfortunately have to flip the direction depending on player type // En passant if ((neighbour = b.get(x-1, y)) != null && checkNeighbourEnPassant(neighbour)) - moves.add(new Move(x-1, y - 1, Move.SpecialConditions.leftEnPassant)); + moves.add(b.checkIfMoveValid(pawnForwardMoveValid(new Move(x-1, y - 1, Move.SpecialConditions.leftEnPassant)), isWhite)); // En passant if ((neighbour = b.get(x+1, y)) != null && checkNeighbourEnPassant(neighbour)) - moves.add(new Move(x+1, - 1, Move.SpecialConditions.rightEnPassant)); + moves.add(b.checkIfMoveValid(pawnForwardMoveValid(new Move(x+1, - 1, Move.SpecialConditions.rightEnPassant)), isWhite)); } - return moves; + return prune(moves); + } + + private Move pawnForwardMoveValid(Move m){ + // basically prevent a pawn from moving into the enemy head on. + if (b.get(m) != null) + return null; + return m; } private boolean checkNeighbourEnPassant(ChessPiece neighbour){ - return neighbour instanceof Pawn && ((Pawn) neighbour).isFirstMove() && neighbour.isWhite != this.isWhite; + return neighbour instanceof Pawn && neighbour.isSecondMove() && neighbour.isWhite != this.isWhite; } @Override @@ -69,15 +76,15 @@ public class Pawn extends ChessPiece { private void enPassantLeft(){ if (isWhite) - b.set(x-1, y, null); + b.set(x, y-1, null); else - b.set(x+1, y, null); + b.set(x, y+1, null); } private void enPassantRight(){ if (isWhite) - b.set(x+1, y, null); + System.out.println(b.set(x, y-1, null)); else - b.set(x-1, y, null); + b.set(x, y-1, null); } } diff --git a/src/chess/Queen.java b/src/chess/Queen.java index 9739f33..4d5e4d5 100644 --- a/src/chess/Queen.java +++ b/src/chess/Queen.java @@ -25,6 +25,6 @@ public class Queen extends ChessPiece { ArrayList moves = new ArrayList(); moves.addAll(super.getCardinalMoves(b.size())); moves.addAll(super.getDiagonalMoves(b.size())); - return moves; + return prune(moves); } } diff --git a/src/chess/Rook.java b/src/chess/Rook.java index 2847c83..a085515 100644 --- a/src/chess/Rook.java +++ b/src/chess/Rook.java @@ -20,6 +20,6 @@ public class Rook extends ChessPiece { @Override public ArrayList getMoves() { - return new ArrayList(super.getCardinalMoves(b.size())); + return prune(super.getCardinalMoves(b.size())); } } diff --git a/src/ui/Display.java b/src/ui/Display.java index d990269..b1318c3 100644 --- a/src/ui/Display.java +++ b/src/ui/Display.java @@ -51,7 +51,7 @@ public class Display extends JFrame implements MouseListener { } if (selectionPointX != -1 && selectionPointY != -1) { int localPointX = (selectionPointX - xOffset) / width; - int localPointY = (b.size() - 1) - ((selectionPointY - yOffset) / height); + int localPointY = ((selectionPointY - yOffset) / height); for (Move m : moves){ if (m.getX() == localPointX && m.getY() == localPointY){ b.movePiece(piece.getPosition(), new Move(localPointX, localPointY)); @@ -68,9 +68,10 @@ public class Display extends JFrame implements MouseListener { // handle user input (mouse clicking) if (selectionPointX != -1 && selectionPointY != -1){ int localPointX = (selectionPointX - xOffset) / width; - int localPointY = (b.size()-1) - ((selectionPointY - yOffset) / height); + int localPointY = ((selectionPointY - yOffset) / height); var piece = b.get(localPointX, localPointY); if (piece != null) { + System.out.println(localPointX + " LL " + localPointY); movingPointX = localPointX; movingPointY = localPointY; } @@ -80,7 +81,7 @@ public class Display extends JFrame implements MouseListener { } private void drawSelectionRect(Graphics g, Move m){ - g.drawRect(xOffset + (m.getX() * width), yOffset + ((b.size()-1 - m.getY()) * height), width, height); + g.drawRect(xOffset + (m.getX() * width), yOffset + (m.getY() * height), width, height); } public boolean update(){