OOP_2B3_Project/src/backend/Move.java

244 lines
8.6 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package backend;
import java.util.ArrayList;
public class Move {
private Piece movedPiece;
private int fromX, fromY;
private int toX, toY;
private Piece capturedPiece;
public Move(Piece movedPiece, int fromX, int fromY, int toX, int toY, Piece capturedPiece) {
this.movedPiece = movedPiece;
this.fromX = fromX;
this.fromY = fromY;
this.toX = toX;
this.toY = toY;
this.capturedPiece = capturedPiece;
}
public Piece getMovedPiece() { return movedPiece; }
public int getFromX() { return fromX; }
public int getFromY() { return fromY; }
public int getToX() { return toX; }
public int getToY() { return toY; }
public Piece getCapturedPiece() { return capturedPiece; }
public static ArrayList<int[]> getPossibleMoves(Board board, Piece piece) {
ArrayList<int[]> raw = new ArrayList<>();
int x = piece.getX(), y = piece.getY();
switch (piece.getType()) {
case Pawn:
addPawnMoves(board, piece, raw);
break;
case Rook:
addLinearMoves(board, piece, raw, new int[][]{{1,0},{-1,0},{0,1},{0,-1}});
break;
case Bishop:
addLinearMoves(board, piece, raw, new int[][]{{1,1},{1,-1},{-1,1},{-1,-1}});
break;
case Queen:
addLinearMoves(board, piece, raw, new int[][]{
{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}});
break;
case King:
addKingMoves(board, piece, raw);
break;
case Knight:
addKnightMoves(board, piece, raw);
break;
}
// ── Now filter out any that leave you in check ──
ArrayList<int[]> legal = new ArrayList<>();
for (int[] m : raw) {
Board copy = new Board(board);
copy.playMove(new Move(piece, x, y, m[0], m[1],
board.getPieceAt(m[0], m[1])));
if (!copy.isInCheck(piece.isWhite())) {
legal.add(m);
}
}
return legal;
}
private static void addPawnMoves(Board b, Piece p, ArrayList<int[]> out) {
int x = p.getX(), y = p.getY(), dir = p.isWhite() ? -1 : 1;
// 1-step forward
int ny = y + dir;
if (isInsideBoard(b,x,ny) && b.getPieceAt(x,ny)==null) {
out.add(new int[]{x,ny});
// 2-step forward
int start = p.isWhite() ? 6 : 1, ny2 = y + 2*dir;
if (y==start && isInsideBoard(b,x,ny2) && b.getPieceAt(x,ny2)==null) {
out.add(new int[]{x,ny2});
}
}
// Captures
for (int dx : new int[]{-1,1}) {
int cx = x+dx, cy = ny;
if (isInsideBoard(b,cx,cy)) {
Piece t = b.getPieceAt(cx,cy);
if (t!=null && t.isWhite()!=p.isWhite())
out.add(new int[]{cx,cy});
}
}
// En Passant
Move last = b.getLastMove();
if (last!=null
&& last.getMovedPiece().getType()==PieceType.Pawn
&& last.getMovedPiece().isWhite()!=p.isWhite()
&& Math.abs(last.getToY()-last.getFromY())==2
&& last.getToY()==y
&& Math.abs(last.getToX()-x)==1) {
int epX = last.getToX();
int epY = y + dir;
if (isInsideBoard(b,epX,epY)) {
out.add(new int[]{epX,epY});
}
}
}
private static void addKingMoves(Board b, Piece p, ArrayList<int[]> out) {
int x = p.getX(), y = p.getY();
// Normal 1-square
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 (isInsideBoard(b,nx,ny)) {
Piece t = b.getPieceAt(nx,ny);
if (t==null || t.isWhite()!=p.isWhite())
out.add(new int[]{nx,ny});
}
}
// Castling
if (!p.hasMoved() && !b.isInCheck(p.isWhite())) {
int[] rookXs = {0, b.getWidth()-1};
for (int rookX : rookXs) {
Piece rook = b.getPieceAt(rookX,y);
if (rook!=null
&& rook.getType()==PieceType.Rook
&& rook.isWhite()==p.isWhite()
&& !rook.hasMoved()) {
int dir = (rookX < x ? -1 : 1);
boolean pathClear = true;
for (int cx = x+dir; cx!=rookX; cx+=dir) {
if (b.getPieceAt(cx,y)!=null) { pathClear=false; break; }
}
if (!pathClear) continue;
// Check the king does not pass through check
boolean ok = true;
int stepX = x;
for (int i=1;i<=2;i++) {
stepX += dir;
Board tmp = new Board(b);
tmp.playMove(new Move(p, x,y,stepX,y, null));
if (tmp.isInCheck(p.isWhite())) {
ok = false;
break;
}
}
if (ok) out.add(new int[]{ x + 2*dir, y });
}
}
}
}
private static void addKnightMoves(Board b, Piece p, ArrayList<int[]> out) {
int x=p.getX(), y=p.getY();
int[][] d = {{1,2},{2,1},{-1,2},{-2,1},{1,-2},{2,-1},{-1,-2},{-2,-1}};
for (int[] dd : d) {
int nx=x+dd[0], ny=y+dd[1];
if (isInsideBoard(b,nx,ny)) {
Piece t=b.getPieceAt(nx,ny);
if (t==null||t.isWhite()!=p.isWhite()) out.add(new int[]{nx,ny});
}
}
}
private static void addLinearMoves(Board b, Piece p, ArrayList<int[]> out, int[][] dirs){
int x=p.getX(), y=p.getY();
for (int[] d: dirs) {
int nx=x+d[0], ny=y+d[1];
while(isInsideBoard(b,nx,ny)) {
Piece t=b.getPieceAt(nx,ny);
if (t==null) out.add(new int[]{nx,ny});
else {
if (t.isWhite()!=p.isWhite()) out.add(new int[]{nx,ny});
break;
}
nx+=d[0]; ny+=d[1];
}
}
}
private static boolean isInsideBoard(Board b,int x,int y){
return x>=0 && x<b.getWidth() && y>=0 && y<b.getHeight();
}
/**
* Returns all pseudo-legal moves for this piece,
* i.e. exactly the same code you had in your original
* getPossibleMoves before you added the check-filter.
*/
public static ArrayList<int[]> getAllPseudoLegalMoves(Board board, Piece piece) {
ArrayList<int[]> moves = new ArrayList<>();
int x = piece.getX(), y = piece.getY();
switch (piece.getType()) {
case Pawn:
// EXACTLY the same pawn logic you already had (including *NOT* flagging hasMoved,
// but you can include en passant here if you like)
addPawnMoves(board, piece, moves);
break;
case Rook:
addLinearMoves(board, piece, moves, new int[][]{{1,0},{-1,0},{0,1},{0,-1}});
break;
case Bishop:
addLinearMoves(board, piece, moves, new int[][]{{1,1},{1,-1},{-1,1},{-1,-1}});
break;
case Queen:
addLinearMoves(board, piece, moves, new int[][]{
{1,0},{-1,0},{0,1},{0,-1},
{1,1},{1,-1},{-1,1},{-1,-1}
});
break;
case King:
// **RAW** king moves: only onesquare steps, no castling
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 (isInsideBoard(board, nx, ny)) {
Piece p = board.getPieceAt(nx, ny);
if (p == null || p.isWhite() != piece.isWhite()) {
moves.add(new int[]{nx, ny});
}
}
}
}
break;
case Knight:
// same as before
int[][] d = {{1,2},{2,1},{-1,2},{-2,1},{1,-2},{2,-1},{-1,-2},{-2,-1}};
for (int[] dd : d) {
int nx = x + dd[0], ny = y + dd[1];
if (isInsideBoard(board, nx, ny)) {
Piece p = board.getPieceAt(nx, ny);
if (p == null || p.isWhite() != piece.isWhite()) {
moves.add(new int[]{nx, ny});
}
}
}
break;
}
return moves;
}
}