diff --git a/src/backend/Audio.java b/src/backend/Audio.java new file mode 100644 index 0000000..6bd0354 --- /dev/null +++ b/src/backend/Audio.java @@ -0,0 +1,32 @@ +package backend; + +import javax.sound.sampled.*; + +public class Audio { + + // No static methods, so these are now instance methods + public void playMoveSound() { + playSound("moveSound.wav"); + } + + public void playCheckSound() { + playSound("check.wav"); + } + public void playCastkingSound() { + playSound("castling.wav"); + } + // Private helper method to avoid code duplication + private void playSound(String resourceName) { + try { + AudioInputStream audioIn = AudioSystem.getAudioInputStream( + Audio.class.getResource(resourceName) + ); + + Clip clip = AudioSystem.getClip(); + clip.open(audioIn); + clip.start(); + } catch (Exception e) { + System.err.println("Could not play " + resourceName); + e.printStackTrace();} + } +} diff --git a/src/backend/Board.java b/src/backend/Board.java index e71acf9..233b885 100644 --- a/src/backend/Board.java +++ b/src/backend/Board.java @@ -1,7 +1,7 @@ package backend; import java.util.ArrayList; - +import backend.Audio; public class Board { @@ -16,6 +16,7 @@ public class Board { private ArrayList moveHistory = new ArrayList<>(); private int[] enPassantTarget = null; private GameSoundManager soundManager; + public Board(int colNum, int lineNum) { @@ -148,6 +149,12 @@ public class Board { // Otherwise, try to move Piece selectedPiece = getPieceAt(selectedX, selectedY); + Audio audio = new Audio(); + if (isKingInCheck(false)) { + audio.playCheckSound(); + } else { + audio.playMoveSound(); + } if (selectedPiece == null) { // Somehow no piece at selected position (safety check) selectedX = null; @@ -172,6 +179,27 @@ public class Board { highlightedSquares.clear(); return; } + // Detect and apply castling rook move + if (selectedPiece.getType() == PieceType.King && Math.abs(x - selectedX) == 2) { + if (x == 6) { // Kingside + Piece rook = getPieceAt(7, selectedY); + if (rook != null) { + pieces.remove(rook); + Piece newRook = new Piece(rook.isWhite(), PieceType.Rook, 5, selectedY); + newRook.setHasMoved(true); + pieces.add(newRook); + } + } else if (x == 2) { // Queenside + Piece rook = getPieceAt(0, selectedY); + if (rook != null) { + pieces.remove(rook); + Piece newRook = new Piece(rook.isWhite(), PieceType.Rook, 3, selectedY); + newRook.setHasMoved(true); + pieces.add(newRook); + } + } + } + // Move is valid → capture if needed Piece target = getPieceAt(x, y); @@ -195,7 +223,9 @@ public class Board { pieces.remove(selectedPiece); // Add new piece at destination - setPiece(selectedPiece.isWhite(), selectedPiece.getType(), x, y); + Piece newPiece = new Piece(selectedPiece.isWhite(), selectedPiece.getType(), x, y); + newPiece.setHasMoved(true); // <--- Mark the piece as having moved + pieces.add(newPiece); // Update turn turnNumber++; @@ -350,7 +380,9 @@ public class Board { } // Restore moved piece to original location - setPiece(lastMove.isWhite(), lastMove.getType(), lastMove.getFromX(), lastMove.getFromY()); + Piece restored = new Piece(lastMove.isWhite(), lastMove.getType(), lastMove.getFromX(), lastMove.getFromY()); + restored.setHasMoved(false); // <--- assume undo reverts first move + pieces.add(restored); // Restore captured piece if there was one if (lastMove.getCapturedPiece() != null) { @@ -405,7 +437,9 @@ public class Board { pieces.remove(pieceToMove); // Add the moved piece at new location - setPiece(move.isWhite(), move.getType(), move.getToX(), move.getToY()); + Piece newPiece = new Piece(move.isWhite(), move.getType(), move.getToX(), move.getToY()); + newPiece.setHasMoved(true); // <--- Track movement + pieces.add(newPiece); // Save move to history moveHistory.add(move); @@ -466,8 +500,49 @@ public boolean isKingInCheck(boolean isWhite) { System.out.println("kingfound"); return false; // king is not in check } +private boolean canCastleKingside(boolean isWhite) { + int y = isWhite ? 7 : 0; + Piece king = getPieceAt(4, y); + Piece rook = getPieceAt(7, y); -public ArrayList computeLegalMoves(Piece piece) { + if (king == null || rook == null || king.hasMoved() || rook.hasMoved()) return false; + + if (!isEmpty(5, y) || !isEmpty(6, y)) return false; + if (isKingInCheck(isWhite)) return false; + + Board step1 = new Board(this); + step1.playMove(new Move(PieceType.King, isWhite, 4, y, 5, y, null)); + if (step1.isKingInCheck(isWhite)) return false; + + Board step2 = new Board(this); + step2.playMove(new Move(PieceType.King, isWhite, 4, y, 6, y, null)); + if (step2.isKingInCheck(isWhite)) return false; + + return true; +} + +private boolean canCastleQueenside(boolean isWhite) { + int y = isWhite ? 7 : 0; + Piece king = getPieceAt(4, y); + Piece rook = getPieceAt(0, y); + + if (king == null || rook == null || king.hasMoved() || rook.hasMoved()) return false; + + if (!isEmpty(1, y) || !isEmpty(2, y) || !isEmpty(3, y)) return false; + if (isKingInCheck(isWhite)) return false; + + Board step1 = new Board(this); + step1.playMove(new Move(PieceType.King, isWhite, 4, y, 3, y, null)); + if (step1.isKingInCheck(isWhite)) return false; + + Board step2 = new Board(this); + step2.playMove(new Move(PieceType.King, isWhite, 4, y, 2, y, null)); + if (step2.isKingInCheck(isWhite)) return false; + + return true; +} + + public ArrayList computeLegalMoves(Piece piece) { ArrayList moves = new ArrayList<>(); int x = piece.getX(); int y = piece.getY(); @@ -607,9 +682,18 @@ public ArrayList computeLegalMoves(Piece piece) { } } } - + + // Add castling moves if King hasn't moved + if (!piece.hasMoved()) { + if (canCastleKingside(piece.isWhite())) { + moves.add(new int[]{x + 2, y}); // Kingside castling + } + if (canCastleQueenside(piece.isWhite())) { + moves.add(new int[]{x - 2, y}); // Queenside castling + } + } } return moves; -} -} +} +} diff --git a/src/backend/GameSoundManager.java b/src/backend/GameSoundManager.java index 27553e7..6739866 100644 --- a/src/backend/GameSoundManager.java +++ b/src/backend/GameSoundManager.java @@ -46,5 +46,6 @@ public class GameSoundManager { public void stopAllSounds() { if (jblClip != null) jblClip.stop(); if (backgroundClip != null) backgroundClip.stop(); - } + } +} \ No newline at end of file diff --git a/src/backend/Move.java b/src/backend/Move.java index aada99a..803a6f6 100644 --- a/src/backend/Move.java +++ b/src/backend/Move.java @@ -6,6 +6,26 @@ public class Move { private boolean isWhite; private PieceType type; private Piece capturedPiece; + private boolean isCastlingMove = false; + private boolean isKingside = false; + + public boolean isCastlingMove() { + return isCastlingMove; + } + + public void setCastling(boolean isCastling, boolean isKingside) { + this.isCastlingMove = isCastling; + this.isKingside = isKingside; + } + + public boolean isKingsideCastling() { + return isCastlingMove && isKingside; + } + + public boolean isQueensideCastling() { + return isCastlingMove && !isKingside; + } + public Move(PieceType type, boolean isWhite, int fromX, int fromY, int toX, int toY, Piece capturedPiece) { this.fromX = fromX; @@ -23,8 +43,6 @@ public class Move { public int getToY() { return toY; } public boolean isWhite() { return isWhite; } public PieceType getType() { return type; } - public Piece getCapturedPiece() { return capturedPiece; } + public Piece getCapturedPiece() { return capturedPiece;} } - - diff --git a/src/backend/Piece.java b/src/backend/Piece.java index 853c074..6fef0f5 100644 --- a/src/backend/Piece.java +++ b/src/backend/Piece.java @@ -5,6 +5,16 @@ public class Piece { private PieceType type; private int x; private int y; + private boolean hasMoved = false; + + public boolean hasMoved() { + return hasMoved; + } + + public void setHasMoved(boolean hasMoved) { + this.hasMoved = hasMoved; + } + // Constructor public Piece(boolean isWhite, PieceType type, int x, int y) { @@ -42,9 +52,5 @@ public class Piece { } public void setX(int x) { - this.x = x; - } - } - - - + this.x = x; + }} diff --git a/src/backend/check.wav b/src/backend/check.wav new file mode 100644 index 0000000..ca1a471 Binary files /dev/null and b/src/backend/check.wav differ diff --git a/src/backend/moveSound.wav b/src/backend/moveSound.wav new file mode 100644 index 0000000..1c09160 Binary files /dev/null and b/src/backend/moveSound.wav differ