diff --git a/src/backend/AutoPlayer.java b/src/backend/AutoPlayer.java index a988a22..e012d20 100644 --- a/src/backend/AutoPlayer.java +++ b/src/backend/AutoPlayer.java @@ -1,17 +1,17 @@ package backend; +import java.util.ArrayList; +import java.util.Random; + public class AutoPlayer { - - - /** - * returns the best Move to try on provided board for active player - * @param board - * @return - */ - public Move computeBestMove(Board board) { - - return null; - } - - + private final Random rnd = new Random(); + + /** + * Picks a random legal move for the active player. + */ + public Move computeBestMove(Board board) { + ArrayList moves = board.generateLegalMoves(); + if (moves.isEmpty()) return null; + return moves.get(rnd.nextInt(moves.size())); + } } diff --git a/src/backend/Board.java b/src/backend/Board.java index 5feea4b..94eabe9 100644 --- a/src/backend/Board.java +++ b/src/backend/Board.java @@ -4,310 +4,477 @@ import java.util.ArrayList; import java.util.Stack; public class Board { + private int width, height; + private ArrayList pieces; + private int turnNumber; + private boolean isWhiteTurn; + private Integer selectedX, selectedY; + private ArrayList highlightedSquares = new ArrayList<>(); + private Stack moveHistory = new Stack<>(); - private int width, height; - private ArrayList pieces; - private int turnNumber; - private boolean isWhiteTurn; - private Integer selectedX, selectedY; - private ArrayList highlightedSquares = new ArrayList<>(); - private Stack moveHistory = new Stack<>(); + // Castling rights + private boolean canCastleWK = true, canCastleWQ = true; + private boolean canCastleBK = true, canCastleBQ = true; - public Board(int colNum, int lineNum) { - this.width = colNum; - this.height = lineNum; - this.turnNumber = 0; - this.isWhiteTurn = true; - this.pieces = new ArrayList<>(); - this.selectedX = null; - this.selectedY = null; - } + public Board(int colNum, int lineNum) { + this.width = colNum; + this.height = lineNum; + this.turnNumber = 0; + this.isWhiteTurn = true; + this.pieces = new ArrayList<>(); + } - public int getWidth() { - return width; - } + public Board(String[] array) { + this(array[0].split(",").length, array.length - 1); + this.isWhiteTurn = array[height].equals("W"); + for (int y = 0; y < height; y++) { + String[] row = array[y].split(","); + for (int x = 0; x < width; x++) { + String t = row[x]; + if (!t.equals("..")) { + boolean w = t.charAt(0) == 'W'; + PieceType tp = PieceType.fromSummary(t.charAt(1)); + pieces.add(new Piece(x, y, w, tp)); + } + } + } + } - public int getHeight() { - return height; - } + public Board(Board other) { + this(other.width, other.height); + this.turnNumber = other.turnNumber; + this.isWhiteTurn = other.isWhiteTurn; + this.canCastleWK = other.canCastleWK; + this.canCastleWQ = other.canCastleWQ; + this.canCastleBK = other.canCastleBK; + this.canCastleBQ = other.canCastleBQ; + this.pieces = new ArrayList<>(); + for (Piece p : other.pieces) { + this.pieces.add(new Piece(p.getX(), p.getY(), p.isWhite(), p.getType())); + } + } - public int getTurnNumber() { - return turnNumber; - } + public int getWidth() { return width; } + public int getHeight() { return height; } + public int getTurnNumber() { return turnNumber; } + public boolean isTurnWhite() { return isWhiteTurn; } - public boolean isTurnWhite() { - return isWhiteTurn; - } + public void populateBoard() { + PieceType[] back = { + PieceType.Rook, PieceType.Knight, PieceType.Bishop, PieceType.Queen, + PieceType.King, PieceType.Bishop, PieceType.Knight, PieceType.Rook + }; + // black pawns + back + for (int x = 0; x < width; x++) { + pieces.add(new Piece(x,1,false,PieceType.Pawn)); + pieces.add(new Piece(x,0,false,back[x])); + } + // white pawns + back + for (int x = 0; x < width; x++) { + pieces.add(new Piece(x,6,true,PieceType.Pawn)); + pieces.add(new Piece(x,7,true,back[x])); + } + canCastleWK = canCastleWQ = canCastleBK = canCastleBQ = true; + } - public void setPiece(boolean isWhite, PieceType type, int x, int y) { - removePieceAt(x, y); - pieces.add(new Piece(x, y, isWhite, type)); - } + public void cleanBoard() { + pieces.clear(); + moveHistory.clear(); + highlightedSquares.clear(); + turnNumber = 0; + isWhiteTurn = true; + canCastleWK = canCastleWQ = canCastleBK = canCastleBQ = true; + } - public void populateBoard() { - PieceType[] backRow = { - PieceType.Rook, PieceType.Knight, PieceType.Bishop, PieceType.Queen, - PieceType.King, PieceType.Bishop, PieceType.Knight, PieceType.Rook - }; + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + Piece p = getPieceAt(x,y); + sb.append(p == null + ? ".." + : (p.isWhite() ? "W" : "B") + p.getType().getSummary()); + if (x < width - 1) sb.append(","); + } + sb.append("\n"); + } + sb.append(isWhiteTurn ? "W" : "B").append("\n"); + return sb.toString(); + } - for (int x = 0; x < width; x++) { - pieces.add(new Piece(x, 1, false, PieceType.Pawn)); // Black pawns - pieces.add(new Piece(x, 6, true, PieceType.Pawn)); // White pawns - } + public String[] toFileRep() { + String[] out = new String[height + 1]; + for (int y = 0; y < height; y++) { + StringBuilder row = new StringBuilder(); + for (int x = 0; x < width; x++) { + Piece p = getPieceAt(x,y); + row.append(p == null + ? ".." + : (p.isWhite() ? "W" : "B") + p.getType().getSummary()); + if (x < width - 1) row.append(","); + } + out[y] = row.toString(); + } + out[height] = isWhiteTurn ? "W" : "B"; + return out; + } - for (int x = 0; x < width; x++) { - pieces.add(new Piece(x, 0, false, backRow[x])); // Black back row - pieces.add(new Piece(x, 7, true, backRow[x])); // White back row - } - } - - public void cleanBoard() { - pieces.clear(); - turnNumber = 0; - isWhiteTurn = true; - selectedX = null; - selectedY = null; - highlightedSquares.clear(); - moveHistory.clear(); - } - //create the board - public String toString() { - StringBuilder sb = new StringBuilder(); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - Piece p = getPieceAt(x, y); - if (p != null) { - sb.append(p.isWhite() ? "W" : "B"); - sb.append(p.getType().getSummary()); - } else { - sb.append("- "); - } - sb.append(" "); - } - sb.append("\n"); - } - return sb.toString(); - } - - public ArrayList getPieces() { - return new ArrayList<>(pieces); - } + public ArrayList getPieces() { + return new ArrayList<>(pieces); + } - public void userTouch(int x, int y) { - Piece clickedPiece = getPieceAt(x, y); + public void setPiece(boolean w, PieceType t, int x, int y) { + removePieceAt(x,y); + pieces.add(new Piece(x,y,w,t)); + } - // No selection yet - if (selectedX == null || selectedY == null) { - if (clickedPiece != null && clickedPiece.isWhite() == isWhiteTurn) { - selectedX = x; - selectedY = y; - highlightedSquares = computeLegalMoves(clickedPiece); - } - return; - } + public void userTouch(int x, int y) { + Piece clicked = getPieceAt(x,y); + if (selectedX == null) { + if (clicked != null && clicked.isWhite() == isWhiteTurn) { + selectedX = x; + selectedY = y; + highlightedSquares = computeLegalMoves(clicked); + } + return; + } + if (selectedX == x && selectedY == y) { + selectedX = selectedY = null; + highlightedSquares.clear(); + return; + } + for (int[] mv : highlightedSquares) { + if (mv[0] == x && mv[1] == y) { + Piece sel = getPieceAt(selectedX, selectedY); + Piece cap = getPieceAt(x, y); - // Click again to unselect - if (selectedX == x && selectedY == y) { - selectedX = null; - selectedY = null; - highlightedSquares.clear(); - return; - } + // en passant detection + if (cap == null && sel.getType() == PieceType.Pawn && x != selectedX) { + int dir = sel.isWhite() ? -1 : 1; + Move last = moveHistory.isEmpty() ? null : moveHistory.peek(); + Piece behind = getPieceAt(x, y - dir); + if (behind != null + && behind.getType() == PieceType.Pawn + && last != null + && last.getType() == PieceType.Pawn + && Math.abs(last.getFromY() - last.getToY()) == 2 + && last.getToX() == behind.getX() + && last.getToY() == behind.getY()) { + cap = behind; + } + } - // Try to move - for (int[] move : highlightedSquares) { - if (move[0] == x && move[1] == y) { - Piece selectedPiece = getPieceAt(selectedX, selectedY); - Piece captured = getPieceAt(x, y); + Move m = new Move( + selectedX, selectedY, + x, y, + sel.isWhite(), sel.getType(), + cap + ); + playMove(m); + break; + } + } + selectedX = selectedY = null; + highlightedSquares.clear(); + } - // Store move for undo - Move m = new Move( - selectedX, selectedY, x, y, - selectedPiece.isWhite(), selectedPiece.getType(), captured - ); - moveHistory.push(m); + public boolean isSelected(int x, int y) { + return selectedX != null && selectedX == x && selectedY == y; + } - removePieceAt(x, y); // capture - removePieceAt(selectedX, selectedY); - pieces.add(new Piece(x, y, selectedPiece.isWhite(), selectedPiece.getType())); + public boolean isHighlighted(int x, int y) { + for (int[] mv : highlightedSquares) { + if (mv[0] == x && mv[1] == y) return true; + } + return false; + } - turnNumber++; - isWhiteTurn = !isWhiteTurn; - break; - } - } + public void playMove(Move m) { + if (m == null) return; - selectedX = null; - selectedY = null; - highlightedSquares.clear(); - } + // castling rook reposition + if (m.getType() == PieceType.King && Math.abs(m.getToX() - m.getFromX()) == 2) { + int y = m.isWhite() ? 7 : 0; + if (m.getToX() - m.getFromX() == 2) { + removePieceAt(7, y); + pieces.add(new Piece(5, y, m.isWhite(), PieceType.Rook)); + } else { + removePieceAt(0, y); + pieces.add(new Piece(3, y, m.isWhite(), PieceType.Rook)); + } + } - public boolean isSelected(int x, int y) { - return selectedX != null && selectedY != null && selectedX == x && selectedY == y; - } + // normal or en passant capture + if (m.getCapturedPiece() != null) { + removePieceAt( + m.getCapturedPiece().getX(), + m.getCapturedPiece().getY() + ); + } + // update opponent's castling rights if rook was captured + if (m.getCapturedPiece() != null && m.getCapturedPiece().getType() == PieceType.Rook) { + Piece cap = m.getCapturedPiece(); + if (cap.isWhite()) { + if (cap.getX() == 0 && cap.getY() == 7) canCastleWQ = false; + if (cap.getX() == 7 && cap.getY() == 7) canCastleWK = false; + } else { + if (cap.getX() == 0 && cap.getY() == 0) canCastleBQ = false; + if (cap.getX() == 7 && cap.getY() == 0) canCastleBK = false; + } + } - public String[] toFileRep() { - // TODO: Part 3 - Save - return null; - } + // move the piece + removePieceAt(m.getFromX(), m.getFromY()); + pieces.add(new Piece( + m.getToX(), m.getToY(), + m.isWhite(), m.getType() + )); - public Board(String[] array) { - // TODO: Part 3 - Load - } + // moving piece castling rights + if (m.getType() == PieceType.King) { + if (m.isWhite()) canCastleWK = canCastleWQ = false; + else canCastleBK = canCastleBQ = false; + } + if (m.getType() == PieceType.Rook) { + if (m.isWhite()) { + if (m.getFromX() == 0 && m.getFromY() == 7) canCastleWQ = false; + if (m.getFromX() == 7 && m.getFromY() == 7) canCastleWK = false; + } else { + if (m.getFromX() == 0 && m.getFromY() == 0) canCastleBQ = false; + if (m.getFromX() == 7 && m.getFromY() == 0) canCastleBK = false; + } + } - public boolean isHighlighted(int x, int y) { - for (int[] move : highlightedSquares) { - if (move[0] == x && move[1] == y) return true; - } - return false; - } + moveHistory.push(m); + turnNumber++; + isWhiteTurn = !isWhiteTurn; + } - public void undoLastMove() { - if (moveHistory.isEmpty()) return; + public void undoLastMove() { + if (moveHistory.isEmpty()) return; + Move m = moveHistory.pop(); - Move lastMove = moveHistory.pop(); + // undo castling rook move + if (m.getType() == PieceType.King && Math.abs(m.getToX() - m.getFromX()) == 2) { + int y = m.isWhite() ? 7 : 0; + if (m.getToX() - m.getFromX() == 2) { + removePieceAt(5, y); + pieces.add(new Piece(7, y, m.isWhite(), PieceType.Rook)); + } else { + removePieceAt(3, y); + pieces.add(new Piece(0, y, m.isWhite(), PieceType.Rook)); + } + } - // Remove moved piece from destination - removePieceAt(lastMove.getToX(), lastMove.getToY()); + // move piece back + removePieceAt(m.getToX(), m.getToY()); + pieces.add(new Piece( + m.getFromX(), m.getFromY(), + m.isWhite(), m.getType() + )); - // Restore original piece - pieces.add(new Piece( - lastMove.getFromX(), - lastMove.getFromY(), - lastMove.isWhite(), - lastMove.getType() - )); + // restore capture + if (m.getCapturedPiece() != null) { + Piece c = m.getCapturedPiece(); + pieces.add(new Piece( + c.getX(), c.getY(), + c.isWhite(), c.getType() + )); + } - // Restore captured piece, if any - if (lastMove.getCapturedPiece() != null) { - Piece p = lastMove.getCapturedPiece(); - pieces.add(new Piece(p.getX(), p.getY(), p.isWhite(), p.getType())); - } + turnNumber--; + isWhiteTurn = !isWhiteTurn; + // note: castling rights are not fully restored in this simple undo + } - turnNumber--; - isWhiteTurn = !isWhiteTurn; - } - - public Board(Board board) { - // TODO: Part 4 - Clone - } - - public void playMove(Move move) { - // TODO: Part 4 - AutoPlayer - } + public ArrayList generateLegalMoves() { + ArrayList all = new ArrayList<>(); + for (Piece p : pieces) { + if (p.isWhite() == isWhiteTurn) { + for (int[] d : computeLegalMoves(p)) { + Piece cap = getPieceAt(d[0], d[1]); + all.add(new Move( + p.getX(), p.getY(), + d[0], d[1], + p.isWhite(), p.getType(), + cap + )); + } + } + } + return all; + } - // ========== Helper Methods ========== + // --- New attack-detection helpers --- + private boolean attacksSquare(Piece p, int targetX, int targetY) { + int x = p.getX(), y = p.getY(); + boolean w = p.isWhite(); + int dx = targetX - x, dy = targetY - y; + switch (p.getType()) { + case Pawn: + int dir = w ? -1 : 1; + return dy == dir && Math.abs(dx) == 1; + case Knight: + return (Math.abs(dx)==1 && Math.abs(dy)==2) + || (Math.abs(dx)==2 && Math.abs(dy)==1); + case Bishop: + if (Math.abs(dx) != Math.abs(dy)) return false; + return clearPath(x, y, targetX, targetY); + case Rook: + if (dx!=0 && dy!=0) return false; + return clearPath(x, y, targetX, targetY); + case Queen: + if (dx==0 || dy==0 || Math.abs(dx)==Math.abs(dy)) + return clearPath(x, y, targetX, targetY); + return false; + case King: + return Math.max(Math.abs(dx), Math.abs(dy)) == 1; + default: + return false; + } + } - private void removePieceAt(int x, int y) { - pieces.removeIf(p -> p.getX() == x && p.getY() == y); - } + private boolean clearPath(int x1, int y1, int x2, int y2) { + int stepX = Integer.signum(x2 - x1); + int stepY = Integer.signum(y2 - y1); + int cx = x1 + stepX, cy = y1 + stepY; + while (cx != x2 || cy != y2) { + if (getPieceAt(cx, cy) != null) return false; + cx += stepX; cy += stepY; + } + return true; + } - private Piece getPieceAt(int x, int y) { - for (Piece p : pieces) { - if (p.getX() == x && p.getY() == y) return p; - } - return null; - } + private boolean isSquareAttacked(int x, int y, boolean byWhite) { + for (Piece p : pieces) { + if (p.isWhite() == byWhite && attacksSquare(p, x, y)) + return true; + } + return false; + } - private ArrayList computeLegalMoves(Piece piece) { - ArrayList moves = new ArrayList<>(); - int x = piece.getX(); - int y = piece.getY(); - boolean isWhite = piece.isWhite(); + // --- Original helpers --- + private Piece getPieceAt(int x, int y) { + for (Piece p : pieces) + if (p.getX() == x && p.getY() == y) return p; + return null; + } + private void removePieceAt(int x, int y) { + pieces.removeIf(p -> p.getX() == x && p.getY() == y); + } + private boolean in(int x, int y) { + return x >= 0 && x < width && y >= 0 && y < height; + } - switch (piece.getType()) { - case Pawn: - int dir = isWhite ? -1 : 1; - int startRow = isWhite ? 6 : 1; + private void slide(ArrayList out, int x, int y, boolean w, int[][] dirs) { + for (int[] d : dirs) { + for (int i = 1; i < 8; i++) { + int nx = x + d[0]*i, ny = y + d[1]*i; + if (!in(nx, ny)) break; + Piece t = getPieceAt(nx, ny); + if (t == null) { + out.add(new int[]{nx, ny}); + } else { + if (t.isWhite() != w) out.add(new int[]{nx, ny}); + break; + } + } + } + } - if (getPieceAt(x, y + dir) == null) { - moves.add(new int[]{x, y + dir}); - if (y == startRow && getPieceAt(x, y + 2 * dir) == null) { - moves.add(new int[]{x, y + 2 * dir}); - } - } - for (int dx = -1; dx <= 1; dx += 2) { - int nx = x + dx; - int ny = y + dir; - if (nx >= 0 && nx < width && ny >= 0 && ny < height) { - Piece target = getPieceAt(nx, ny); - if (target != null && target.isWhite() != isWhite) { - moves.add(new int[]{nx, ny}); - } - } - } - break; - - case Rook: - addSlidingMoves(moves, x, y, isWhite, new int[][]{{1,0},{-1,0},{0,1},{0,-1}}); - break; - - case Bishop: - addSlidingMoves(moves, x, y, isWhite, new int[][]{{1,1},{1,-1},{-1,1},{-1,-1}}); - break; - - case Queen: - addSlidingMoves(moves, x, y, isWhite, new int[][]{ - {1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1} - }); - break; - - case Knight: - int[][] knightMoves = { - {x+1, y+2}, {x+1, y-2}, {x-1, y+2}, {x-1, y-2}, - {x+2, y+1}, {x+2, y-1}, {x-2, y+1}, {x-2, y-1} - }; - for (int[] move : knightMoves) { - int nx = move[0]; - int ny = move[1]; - if (nx >= 0 && nx < width && ny >= 0 && ny < height) { - Piece target = getPieceAt(nx, ny); - if (target == null || target.isWhite() != isWhite) { - moves.add(new int[]{nx, ny}); - } - } - } - break; - - case King: - for (int dx = -1; dx <= 1; dx++) { - for (int dy = -1; dy <= 1; dy++) { - if (dx == 0 && dy == 0) continue; - int nx = x + dx; - int ny = y + dy; - if (nx >= 0 && nx < width && ny >= 0 && ny < height) { - Piece target = getPieceAt(nx, ny); - if (target == null || target.isWhite() != isWhite) { - moves.add(new int[]{nx, ny}); - } - } - } - } - break; - - default: - break; - } - return moves; - } - - private void addSlidingMoves(ArrayList moves, int x, int y, boolean isWhite, int[][] directions) { - for (int[] dir : directions) { - for (int i = 1; i < 8; i++) { - int nx = x + dir[0] * i; - int ny = y + dir[1] * i; - if (nx < 0 || nx >= width || ny < 0 || ny >= height) break; - Piece target = getPieceAt(nx, ny); - if (target == null) { - moves.add(new int[]{nx, ny}); - } else { - if (target.isWhite() != isWhite) { - moves.add(new int[]{nx, ny}); - } - break; - } - } - } - } - -} + private ArrayList computeLegalMoves(Piece p) { + ArrayList out = new ArrayList<>(); + int x = p.getX(), y = p.getY(); + boolean w = p.isWhite(); + switch (p.getType()) { + case Pawn: + int dir = w ? -1 : 1, sr = w ? 6 : 1; + if (in(x, y + dir) && getPieceAt(x, y + dir) == null) { + out.add(new int[]{x, y + dir}); + if (y == sr && getPieceAt(x, y + 2*dir) == null) { + out.add(new int[]{x, y + 2*dir}); + } + } + for (int dx : new int[]{-1,1}) { + int nx = x + dx, ny = y + dir; + if (in(nx, ny)) { + Piece t = getPieceAt(nx, ny); + if (t != null && t.isWhite() != w) { + out.add(new int[]{nx, ny}); + } + } + } + if (!moveHistory.isEmpty()) { + Move last = moveHistory.peek(); + if (last.getType() == PieceType.Pawn + && Math.abs(last.getFromY() - last.getToY()) == 2 + && last.getToY() == y + && Math.abs(last.getToX() - x) == 1 + ) { + int ex = last.getToX(), ey = y + dir; + if (in(ex, ey) && getPieceAt(ex, ey) == null) + out.add(new int[]{ex, ey}); + } + } + break; + case Rook: + slide(out, x, y, w, new int[][]{{1,0},{-1,0},{0,1},{0,-1}}); + break; + case Bishop: + slide(out, x, y, w, new int[][]{{1,1},{1,-1},{-1,1},{-1,-1}}); + break; + case Queen: + slide(out, x, y, w, new int[][]{ + {1,0},{-1,0},{0,1},{0,-1}, + {1,1},{1,-1},{-1,1},{-1,-1} + }); + break; + case Knight: + int[][] knightMoves = {{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}}; + for (int[] m : knightMoves) { + int nx = x + m[0], ny = y + m[1]; + if (in(nx, ny)) { + Piece t = getPieceAt(nx, ny); + if (t == null || t.isWhite() != w) + out.add(new int[]{nx, ny}); + } + } + break; + case King: + for (int dx = -1; dx <= 1; dx++) + for (int dy = -1; dy <= 1; dy++) { + if (dx == 0 && dy == 0) continue; + int nx = x + dx, ny = y + dy; + if (in(nx, ny)) { + Piece t = getPieceAt(nx, ny); + if (t == null || t.isWhite() != w) + out.add(new int[]{nx, ny}); + } + } + boolean opp = !w; + if (!isSquareAttacked(x, y, opp)) { + if (w && x == 4 && y == 7) { + if (canCastleWK && getPieceAt(5,7) == null && getPieceAt(6,7) == null + && !isSquareAttacked(5,7,opp) && !isSquareAttacked(6,7,opp)) + out.add(new int[]{6,7}); + if (canCastleWQ && getPieceAt(3,7) == null && getPieceAt(2,7) == null + && getPieceAt(1,7) == null && !isSquareAttacked(3,7,opp) + && !isSquareAttacked(2,7,opp)) + out.add(new int[]{2,7}); + } + if (!w && x == 4 && y == 0) { + if (canCastleBK && getPieceAt(5,0) == null && getPieceAt(6,0) == null + && !isSquareAttacked(5,0,opp) && !isSquareAttacked(6,0,opp)) + out.add(new int[]{6,0}); + if (canCastleBQ && getPieceAt(3,0) == null && getPieceAt(2,0) == null + && getPieceAt(1,0) == null && !isSquareAttacked(3,0,opp) + && !isSquareAttacked(2,0,opp)) + out.add(new int[]{2,0}); + } + } + break; + } + return out; + } +} \ No newline at end of file diff --git a/src/backend/Game.java b/src/backend/Game.java index 4c64f70..96d8340 100644 --- a/src/backend/Game.java +++ b/src/backend/Game.java @@ -108,3 +108,6 @@ public class Game extends Thread { } } + + + diff --git a/src/backend/Move.java b/src/backend/Move.java index 50f4873..b29b164 100644 --- a/src/backend/Move.java +++ b/src/backend/Move.java @@ -1,29 +1,40 @@ +// src/backend/Move.java package backend; public class Move { - private int fromX, fromY; - private int toX, toY; - private boolean isWhite; - private PieceType type; - private Piece capturedPiece; + private final int fromX, fromY, toX, toY; + private final boolean white; + private final PieceType type; + private final PieceType promotion; // null if none - public Move(int fromX, int fromY, int toX, int toY, boolean isWhite, PieceType type, Piece capturedPiece) { - this.fromX = fromX; - this.fromY = fromY; - this.toX = toX; - this.toY = toY; - this.isWhite = isWhite; - this.type = type; - this.capturedPiece = capturedPiece; - } + public Move(int fromX, int fromY, int toX, int toY, + boolean white, PieceType type, PieceType promotion) { + this.fromX = fromX; + this.fromY = fromY; + this.toX = toX; + this.toY = toY; + this.white = white; + this.type = type; + this.promotion= promotion; + } - // Getters - public int getFromX() { return fromX; } - public int getFromY() { return fromY; } - public int getToX() { return toX; } - public int getToY() { return toY; } - public boolean isWhite() { return isWhite; } - public PieceType getType() { return type; } - public Piece getCapturedPiece() { return capturedPiece; } + public int getFromX() { return fromX; } + public int getFromY() { return fromY; } + public int getToX() { return toX; } + public int getToY() { return toY; } + public boolean isWhite() { return white; } + public PieceType getType() { return type; } + public PieceType getPromotion() { return promotion; } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Move)) return false; + Move m = (Move)o; + return fromX==m.fromX && fromY==m.fromY + && toX==m.toX && toY==m.toY + && white==m.white && type==m.type; + } + @Override public int hashCode() { return fromX*31+fromY*7+toX*13+toY; } } + diff --git a/src/backend/Piece.java b/src/backend/Piece.java index 035a321..b8bbe2b 100644 --- a/src/backend/Piece.java +++ b/src/backend/Piece.java @@ -30,3 +30,4 @@ public class Piece { return isWhite; } } +