still need to do checkmate

This commit is contained in:
rheaa 2025-05-20 00:29:36 +02:00
parent 61c5de7ee3
commit 9b93fe4081
5 changed files with 490 additions and 308 deletions

View File

@ -1,17 +1,17 @@
package backend; package backend;
import java.util.ArrayList;
import java.util.Random;
public class AutoPlayer { public class AutoPlayer {
private final Random rnd = new Random();
/** /**
* returns the best Move to try on provided board for active player * Picks a random legal move for the active player.
* @param board */
* @return public Move computeBestMove(Board board) {
*/ ArrayList<Move> moves = board.generateLegalMoves();
public Move computeBestMove(Board board) { if (moves.isEmpty()) return null;
return moves.get(rnd.nextInt(moves.size()));
return null; }
}
} }

View File

@ -4,310 +4,477 @@ import java.util.ArrayList;
import java.util.Stack; import java.util.Stack;
public class Board { public class Board {
private int width, height;
private ArrayList<Piece> pieces;
private int turnNumber;
private boolean isWhiteTurn;
private Integer selectedX, selectedY;
private ArrayList<int[]> highlightedSquares = new ArrayList<>();
private Stack<Move> moveHistory = new Stack<>();
private int width, height; // Castling rights
private ArrayList<Piece> pieces; private boolean canCastleWK = true, canCastleWQ = true;
private int turnNumber; private boolean canCastleBK = true, canCastleBQ = true;
private boolean isWhiteTurn;
private Integer selectedX, selectedY;
private ArrayList<int[]> highlightedSquares = new ArrayList<>();
private Stack<Move> moveHistory = new Stack<>();
public Board(int colNum, int lineNum) { public Board(int colNum, int lineNum) {
this.width = colNum; this.width = colNum;
this.height = lineNum; this.height = lineNum;
this.turnNumber = 0; this.turnNumber = 0;
this.isWhiteTurn = true; this.isWhiteTurn = true;
this.pieces = new ArrayList<>(); this.pieces = new ArrayList<>();
this.selectedX = null; }
this.selectedY = null;
}
public int getWidth() { public Board(String[] array) {
return width; 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() { public Board(Board other) {
return height; 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() { public int getWidth() { return width; }
return turnNumber; public int getHeight() { return height; }
} public int getTurnNumber() { return turnNumber; }
public boolean isTurnWhite() { return isWhiteTurn; }
public boolean isTurnWhite() { public void populateBoard() {
return isWhiteTurn; 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) { public void cleanBoard() {
removePieceAt(x, y); pieces.clear();
pieces.add(new Piece(x, y, isWhite, type)); moveHistory.clear();
} highlightedSquares.clear();
turnNumber = 0;
isWhiteTurn = true;
canCastleWK = canCastleWQ = canCastleBK = canCastleBQ = true;
}
public void populateBoard() { @Override
PieceType[] backRow = { public String toString() {
PieceType.Rook, PieceType.Knight, PieceType.Bishop, PieceType.Queen, StringBuilder sb = new StringBuilder();
PieceType.King, PieceType.Bishop, PieceType.Knight, PieceType.Rook 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++) { public String[] toFileRep() {
pieces.add(new Piece(x, 1, false, PieceType.Pawn)); // Black pawns String[] out = new String[height + 1];
pieces.add(new Piece(x, 6, true, PieceType.Pawn)); // White pawns 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++) { public ArrayList<Piece> getPieces() {
pieces.add(new Piece(x, 0, false, backRow[x])); // Black back row return new ArrayList<>(pieces);
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<Piece> getPieces() {
return new ArrayList<>(pieces);
}
public void userTouch(int x, int y) { public void setPiece(boolean w, PieceType t, int x, int y) {
Piece clickedPiece = getPieceAt(x, y); removePieceAt(x,y);
pieces.add(new Piece(x,y,w,t));
}
// No selection yet public void userTouch(int x, int y) {
if (selectedX == null || selectedY == null) { Piece clicked = getPieceAt(x,y);
if (clickedPiece != null && clickedPiece.isWhite() == isWhiteTurn) { if (selectedX == null) {
selectedX = x; if (clicked != null && clicked.isWhite() == isWhiteTurn) {
selectedY = y; selectedX = x;
highlightedSquares = computeLegalMoves(clickedPiece); selectedY = y;
} highlightedSquares = computeLegalMoves(clicked);
return; }
} 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 // en passant detection
if (selectedX == x && selectedY == y) { if (cap == null && sel.getType() == PieceType.Pawn && x != selectedX) {
selectedX = null; int dir = sel.isWhite() ? -1 : 1;
selectedY = null; Move last = moveHistory.isEmpty() ? null : moveHistory.peek();
highlightedSquares.clear(); Piece behind = getPieceAt(x, y - dir);
return; 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 Move m = new Move(
for (int[] move : highlightedSquares) { selectedX, selectedY,
if (move[0] == x && move[1] == y) { x, y,
Piece selectedPiece = getPieceAt(selectedX, selectedY); sel.isWhite(), sel.getType(),
Piece captured = getPieceAt(x, y); cap
);
playMove(m);
break;
}
}
selectedX = selectedY = null;
highlightedSquares.clear();
}
// Store move for undo public boolean isSelected(int x, int y) {
Move m = new Move( return selectedX != null && selectedX == x && selectedY == y;
selectedX, selectedY, x, y, }
selectedPiece.isWhite(), selectedPiece.getType(), captured
);
moveHistory.push(m);
removePieceAt(x, y); // capture public boolean isHighlighted(int x, int y) {
removePieceAt(selectedX, selectedY); for (int[] mv : highlightedSquares) {
pieces.add(new Piece(x, y, selectedPiece.isWhite(), selectedPiece.getType())); if (mv[0] == x && mv[1] == y) return true;
}
return false;
}
turnNumber++; public void playMove(Move m) {
isWhiteTurn = !isWhiteTurn; if (m == null) return;
break;
}
}
selectedX = null; // castling rook reposition
selectedY = null; if (m.getType() == PieceType.King && Math.abs(m.getToX() - m.getFromX()) == 2) {
highlightedSquares.clear(); 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) { // normal or en passant capture
return selectedX != null && selectedY != null && selectedX == x && selectedY == y; 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() { // move the piece
// TODO: Part 3 - Save removePieceAt(m.getFromX(), m.getFromY());
return null; pieces.add(new Piece(
} m.getToX(), m.getToY(),
m.isWhite(), m.getType()
));
public Board(String[] array) { // moving piece castling rights
// TODO: Part 3 - Load 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) { moveHistory.push(m);
for (int[] move : highlightedSquares) { turnNumber++;
if (move[0] == x && move[1] == y) return true; isWhiteTurn = !isWhiteTurn;
} }
return false;
}
public void undoLastMove() { public void undoLastMove() {
if (moveHistory.isEmpty()) return; 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 // move piece back
removePieceAt(lastMove.getToX(), lastMove.getToY()); removePieceAt(m.getToX(), m.getToY());
pieces.add(new Piece(
m.getFromX(), m.getFromY(),
m.isWhite(), m.getType()
));
// Restore original piece // restore capture
pieces.add(new Piece( if (m.getCapturedPiece() != null) {
lastMove.getFromX(), Piece c = m.getCapturedPiece();
lastMove.getFromY(), pieces.add(new Piece(
lastMove.isWhite(), c.getX(), c.getY(),
lastMove.getType() c.isWhite(), c.getType()
)); ));
}
// Restore captured piece, if any turnNumber--;
if (lastMove.getCapturedPiece() != null) { isWhiteTurn = !isWhiteTurn;
Piece p = lastMove.getCapturedPiece(); // note: castling rights are not fully restored in this simple undo
pieces.add(new Piece(p.getX(), p.getY(), p.isWhite(), p.getType())); }
}
turnNumber--; public ArrayList<Move> generateLegalMoves() {
isWhiteTurn = !isWhiteTurn; ArrayList<Move> all = new ArrayList<>();
} for (Piece p : pieces) {
if (p.isWhite() == isWhiteTurn) {
public Board(Board board) { for (int[] d : computeLegalMoves(p)) {
// TODO: Part 4 - Clone Piece cap = getPieceAt(d[0], d[1]);
} all.add(new Move(
p.getX(), p.getY(),
public void playMove(Move move) { d[0], d[1],
// TODO: Part 4 - AutoPlayer 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) { private boolean clearPath(int x1, int y1, int x2, int y2) {
pieces.removeIf(p -> p.getX() == x && p.getY() == y); 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) { private boolean isSquareAttacked(int x, int y, boolean byWhite) {
for (Piece p : pieces) { for (Piece p : pieces) {
if (p.getX() == x && p.getY() == y) return p; if (p.isWhite() == byWhite && attacksSquare(p, x, y))
} return true;
return null; }
} return false;
}
private ArrayList<int[]> computeLegalMoves(Piece piece) { // --- Original helpers ---
ArrayList<int[]> moves = new ArrayList<>(); private Piece getPieceAt(int x, int y) {
int x = piece.getX(); for (Piece p : pieces)
int y = piece.getY(); if (p.getX() == x && p.getY() == y) return p;
boolean isWhite = piece.isWhite(); 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()) { private void slide(ArrayList<int[]> out, int x, int y, boolean w, int[][] dirs) {
case Pawn: for (int[] d : dirs) {
int dir = isWhite ? -1 : 1; for (int i = 1; i < 8; i++) {
int startRow = isWhite ? 6 : 1; 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) { private ArrayList<int[]> computeLegalMoves(Piece p) {
moves.add(new int[]{x, y + dir}); ArrayList<int[]> out = new ArrayList<>();
if (y == startRow && getPieceAt(x, y + 2 * dir) == null) { int x = p.getX(), y = p.getY();
moves.add(new int[]{x, y + 2 * dir}); boolean w = p.isWhite();
} switch (p.getType()) {
} case Pawn:
for (int dx = -1; dx <= 1; dx += 2) { int dir = w ? -1 : 1, sr = w ? 6 : 1;
int nx = x + dx; if (in(x, y + dir) && getPieceAt(x, y + dir) == null) {
int ny = y + dir; out.add(new int[]{x, y + dir});
if (nx >= 0 && nx < width && ny >= 0 && ny < height) { if (y == sr && getPieceAt(x, y + 2*dir) == null) {
Piece target = getPieceAt(nx, ny); out.add(new int[]{x, y + 2*dir});
if (target != null && target.isWhite() != isWhite) { }
moves.add(new int[]{nx, ny}); }
} for (int dx : new int[]{-1,1}) {
} int nx = x + dx, ny = y + dir;
} if (in(nx, ny)) {
break; Piece t = getPieceAt(nx, ny);
if (t != null && t.isWhite() != w) {
case Rook: out.add(new int[]{nx, ny});
addSlidingMoves(moves, x, y, isWhite, new int[][]{{1,0},{-1,0},{0,1},{0,-1}}); }
break; }
}
case Bishop: if (!moveHistory.isEmpty()) {
addSlidingMoves(moves, x, y, isWhite, new int[][]{{1,1},{1,-1},{-1,1},{-1,-1}}); Move last = moveHistory.peek();
break; if (last.getType() == PieceType.Pawn
&& Math.abs(last.getFromY() - last.getToY()) == 2
case Queen: && last.getToY() == y
addSlidingMoves(moves, x, y, isWhite, new int[][]{ && Math.abs(last.getToX() - x) == 1
{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1} ) {
}); int ex = last.getToX(), ey = y + dir;
break; if (in(ex, ey) && getPieceAt(ex, ey) == null)
out.add(new int[]{ex, ey});
case Knight: }
int[][] knightMoves = { }
{x+1, y+2}, {x+1, y-2}, {x-1, y+2}, {x-1, y-2}, break;
{x+2, y+1}, {x+2, y-1}, {x-2, y+1}, {x-2, y-1} case Rook:
}; slide(out, x, y, w, new int[][]{{1,0},{-1,0},{0,1},{0,-1}});
for (int[] move : knightMoves) { break;
int nx = move[0]; case Bishop:
int ny = move[1]; slide(out, x, y, w, new int[][]{{1,1},{1,-1},{-1,1},{-1,-1}});
if (nx >= 0 && nx < width && ny >= 0 && ny < height) { break;
Piece target = getPieceAt(nx, ny); case Queen:
if (target == null || target.isWhite() != isWhite) { slide(out, x, y, w, new int[][]{
moves.add(new int[]{nx, ny}); {1,0},{-1,0},{0,1},{0,-1},
} {1,1},{1,-1},{-1,1},{-1,-1}
} });
} break;
break; case Knight:
int[][] knightMoves = {{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}};
case King: for (int[] m : knightMoves) {
for (int dx = -1; dx <= 1; dx++) { int nx = x + m[0], ny = y + m[1];
for (int dy = -1; dy <= 1; dy++) { if (in(nx, ny)) {
if (dx == 0 && dy == 0) continue; Piece t = getPieceAt(nx, ny);
int nx = x + dx; if (t == null || t.isWhite() != w)
int ny = y + dy; out.add(new int[]{nx, ny});
if (nx >= 0 && nx < width && ny >= 0 && ny < height) { }
Piece target = getPieceAt(nx, ny); }
if (target == null || target.isWhite() != isWhite) { break;
moves.add(new int[]{nx, ny}); 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;
break; if (in(nx, ny)) {
Piece t = getPieceAt(nx, ny);
default: if (t == null || t.isWhite() != w)
break; out.add(new int[]{nx, ny});
} }
return moves; }
} boolean opp = !w;
if (!isSquareAttacked(x, y, opp)) {
private void addSlidingMoves(ArrayList<int[]> moves, int x, int y, boolean isWhite, int[][] directions) { if (w && x == 4 && y == 7) {
for (int[] dir : directions) { if (canCastleWK && getPieceAt(5,7) == null && getPieceAt(6,7) == null
for (int i = 1; i < 8; i++) { && !isSquareAttacked(5,7,opp) && !isSquareAttacked(6,7,opp))
int nx = x + dir[0] * i; out.add(new int[]{6,7});
int ny = y + dir[1] * i; if (canCastleWQ && getPieceAt(3,7) == null && getPieceAt(2,7) == null
if (nx < 0 || nx >= width || ny < 0 || ny >= height) break; && getPieceAt(1,7) == null && !isSquareAttacked(3,7,opp)
Piece target = getPieceAt(nx, ny); && !isSquareAttacked(2,7,opp))
if (target == null) { out.add(new int[]{2,7});
moves.add(new int[]{nx, ny}); }
} else { if (!w && x == 4 && y == 0) {
if (target.isWhite() != isWhite) { if (canCastleBK && getPieceAt(5,0) == null && getPieceAt(6,0) == null
moves.add(new int[]{nx, ny}); && !isSquareAttacked(5,0,opp) && !isSquareAttacked(6,0,opp))
} out.add(new int[]{6,0});
break; 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;
}
}

View File

@ -108,3 +108,6 @@ public class Game extends Thread {
} }
} }

View File

@ -1,29 +1,40 @@
// src/backend/Move.java
package backend; package backend;
public class Move { public class Move {
private int fromX, fromY; private final int fromX, fromY, toX, toY;
private int toX, toY; private final boolean white;
private boolean isWhite; private final PieceType type;
private PieceType type; private final PieceType promotion; // null if none
private Piece capturedPiece;
public Move(int fromX, int fromY, int toX, int toY, boolean isWhite, PieceType type, Piece capturedPiece) { public Move(int fromX, int fromY, int toX, int toY,
this.fromX = fromX; boolean white, PieceType type, PieceType promotion) {
this.fromY = fromY; this.fromX = fromX;
this.toX = toX; this.fromY = fromY;
this.toY = toY; this.toX = toX;
this.isWhite = isWhite; this.toY = toY;
this.type = type; this.white = white;
this.capturedPiece = capturedPiece; this.type = type;
} this.promotion= promotion;
}
// Getters public int getFromX() { return fromX; }
public int getFromX() { return fromX; } public int getFromY() { return fromY; }
public int getFromY() { return fromY; } public int getToX() { return toX; }
public int getToX() { return toX; } public int getToY() { return toY; }
public int getToY() { return toY; } public boolean isWhite() { return white; }
public boolean isWhite() { return isWhite; } public PieceType getType() { return type; }
public PieceType getType() { return type; } public PieceType getPromotion() { return promotion; }
public Piece getCapturedPiece() { return capturedPiece; }
@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; }
} }

View File

@ -30,3 +30,4 @@ public class Piece {
return isWhite; return isWhite;
} }
} }