OOP_3B2_Project/src/backend/Board.java

435 lines
11 KiB
Java

package backend;
import java.util.ArrayList;
public class Board {
private int colNum;
private int lineNum;
private Piece[][] board;
private int x;
private int y;
private int turns;
private boolean whiteTurn;
private boolean enPassant;
private int pawnX;
private int pawnY;
private int enPassantX;
private int enPassantY;
private boolean whiteRookLeft;
private boolean whiteRookRight;
private boolean blackRookLeft;
private boolean blackRookRight;
private boolean whiteKing;
private boolean blackKing;
private boolean castlingRight;
private boolean castlingLeft;
ArrayList<String> states;
// CONSTRUCTOR
public Board(int colNum, int lineNum) {
this.colNum = colNum;
this.lineNum = lineNum;
this.board = new Piece[lineNum][colNum];
this.x = -1;
this.y = -1;
turns = 0;
whiteTurn = true;
enPassant = false;
pawnX = -1;
pawnY = -1;
enPassantX = -1;
enPassantY = -1;
whiteRookLeft = false;
whiteRookRight = false;
blackRookLeft = false;
blackRookRight = false;
whiteKing = false;
blackKing = false;
castlingRight = false;
castlingLeft = false;
states = new ArrayList<>();
}
// GETTERS
public int getWidth() {
return this.colNum;
}
public int getHeight() {
return this.lineNum;
}
public int getTurnNumber() {
return turns;
}
public boolean isTurnWhite() {
return whiteTurn;
}
// INITIALISE THE BOARD
public void initialise() {
x = -1;
y = -1;
turns = 0;
whiteTurn = true;
enPassant = false;
pawnX = -1;
pawnY = -1;
enPassantX = -1;
enPassantY = -1;
whiteRookLeft = false;
whiteRookRight = false;
blackRookLeft = false;
blackRookRight = false;
whiteKing = false;
blackKing = false;
states = new ArrayList<>();
}
public void setPiece(boolean isWhite, PieceType type, int x, int y) {
board[y][x] = new Piece(isWhite, type, x, y);
}
public void populateBoard() {
for (int i = 0; i < lineNum; i++) {
boolean white = (i > 5);
if (i == 1 || i == 6) {
for (int j = 0; j < colNum; j++) {
setPiece(white, PieceType.Pawn, j, i);
}
}
else if (i == 0 || i == 7){
setPiece(white, PieceType.Rook, 0, i);
setPiece(white, PieceType.Rook, 7, i);
setPiece(white, PieceType.Knight, 1, i);
setPiece(white, PieceType.Knight, 6, i);
setPiece(white, PieceType.Bishop, 2, i);
setPiece(white, PieceType.Bishop, 5, i);
setPiece(white, PieceType.Queen, 3, i);
setPiece(white, PieceType.King, 4, i);
}
}
states.add(toString());
}
public void cleanBoard() {
initialise();
for (int i = 0; i < lineNum; i++) {
for (int j = 0; j < colNum; j++) {
board[i][j] = null;
}
}
}
// WRITE THE BOARD AS A READABLE STRING
public String toString() {
String str = "";
// iterate through lines
for (int i = 0; i < lineNum; i++) {
// iterate through columns
for (int j = 0; j < colNum; j++) {
// write the corresponding letters depending on the piece on the board
if (board[i][j] == null) {
str += " ";
}
else if (board[i][j].isWhite()) {
str += "W" + board[i][j].getType().getSummary();
}
else if (board[i][j].isWhite() == false) {
str += "B" + board[i][j].getType().getSummary();
}
if (j != colNum-1) {
str += ",";
}
}
str += "\n";
}
String turn = "B";
if (isTurnWhite()) {
turn = "W";
}
str += turn;
return str;
}
// LIST THE PIECES OF THE BOARD
public ArrayList<Piece> getPieces() {
ArrayList<Piece> pieces = new ArrayList<>();
for (int i = 0; i < colNum; i++) {
for (int j = 0; j < lineNum; j++) {
if (board[j][i] != null) {
pieces.add(board[j][i]);
}
}
}
return pieces;
}
public boolean inBoard(int x, int y) {
if (x > -1 && x < colNum && y > -1 && y < lineNum) {
return true;
}
return false;
}
public Piece getPieceAt(int x, int y) {
if (inBoard(x,y)) {
return board[y][x];
}
return null;
}
// PROCESS THE USER CLICK
public void userTouch(int x, int y) {
// there have been no preselected location (no piece is selected)
if (this.x == -1 && this.y == -1) {
// if the location selected has a piece and the piece has the right color
if (board[y][x] != null && board[y][x].isWhite() == whiteTurn) {
// update coordinates
this.x = x;
this.y = y;
}
}
// a piece is already selected (so the new click is where the user wants to move the piece)
else {
Move move = new Move(this.x,this.y,x,y);
// if the new location is the same as before, de-selects the piece and no move happens
if (this.x == x && this.y == y || board[this.y][this.x] == null) {
this.x = -1;
this.y = -1;
}
// the new location is highlighted, meaning it is a legal displacement
else if (isHighlighted(x,y)) {
// handling en passant
if (this.enPassant == true && board[this.y][this.x].getType() == PieceType.Pawn && x == enPassantX && y == enPassantY) {
board[pawnY][pawnX] = null;
playMove(move);
}
// castling to the left
else if (this.castlingLeft && x == this.x-2) {
if (board[this.y][this.x].isWhite()) {
// rook displacement (white left)
playMove(new Move(0,7,x+1,y));
}
else {
// rook displacement (black left)
playMove(new Move(0,0,x+1,y));
}
// king displacement
playMove(move);
}
// castling to the right
else if (this.castlingRight && x == this.x+2) {
if (board[this.y][this.x].isWhite()) {
// rook displacement (white right)
playMove(new Move(7,7,x-1,y));
}
else {
// rook displacement (black right)
playMove(new Move(7,0,x-1,y));
}
// king displacement
playMove(move);
}
// basic legal move
else {
// verify if the pawn goes two steps forward (to know if en passant will be possible for the opponent)
if (board[this.y][this.x].getType() == PieceType.Pawn && (y == this.y+2 || y == this.y-2)) {
enPassant = true;
pawnX = x;
pawnY = y;
}
else {
enPassant = false;
pawnX = -1;
pawnX = -1;
}
// check if rooks or kings are beeing moved to enable (or not) castling later
if (board[this.y][this.x].getType() == PieceType.Rook) {
if (this.x == 0) {
if (board[this.y][this.x].isWhite() && whiteRookLeft == false) {
whiteRookLeft = true;
}
else if (board[this.y][this.x].isWhite() == false && blackRookLeft == false) {
blackRookLeft = true;
}
}
else if (this.x == 7) {
if (board[this.y][this.x].isWhite() && whiteRookRight == false) {
whiteRookRight = true;
}
else if (board[this.y][this.x].isWhite() == false && blackRookRight == false) {
blackRookRight = true;
}
}
}
else if (board[this.y][this.x].getType() == PieceType.King) {
if (board[this.y][this.x].isWhite()) {
whiteKing = true;
}
else if (board[this.y][this.x].isWhite() == false) {
blackKing = true;
}
}
playMove(move);
}
turns += 1;
this.x = -1;
this.y = -1;
whiteTurn = !whiteTurn;
}
}
}
public boolean isSelected(int x, int y) {
if (this.x == x && this.y == y) {
return true;
}
return false;
}
/* saving-loading feature :*/
public String[] toFileRep() {
String myFile = toString();
String[] myArray = myFile.split("\n");
return myArray;
}
public Board(String[] array) {
this.colNum = 8;
this.lineNum = 8;
this.board = new Piece[lineNum][colNum];
this.x = -1;
this.y = -1;
//this.turns = turns;
String[] line;
boolean white;
for (int j = 0; j < colNum; j++) {
line = array[j].split(",");
for (int i = 0; i < lineNum; i++) {
if (line[i].charAt(0) != ' ') {
white = false;
if (line[i].charAt(0) == 'W') {
white = true;
}
Piece piece = new Piece(white, PieceType.fromSummary(line[i].charAt(1)), i, j);
board[j][i] = new Piece(piece);
}
}
}
if (array[lineNum] == "B") {
whiteTurn = false;
}
else {
whiteTurn = true;
}
}
/* The following methods require more work ! */
public boolean isHighlighted(int x, int y) {
boolean king;
boolean rookRight;
boolean rookLeft;
if (this.x != -1 && this.y != -1) {
if (board[this.y][this.x].isWhite()) {
king = whiteKing;
rookRight = whiteRookRight;
rookLeft = whiteRookLeft;
}
else {
king = blackKing;
rookRight = blackRookRight;
rookLeft = blackRookLeft;
}
MoveCalculator legalMoves = new MoveCalculator(this.board);
ArrayList<int[]> moves = legalMoves.getMove(board[this.y][this.x].getType(), board[this.y][this.x].isWhite(), this.x, this.y, king, rookRight, rookLeft, enPassant, pawnX, pawnY);
this.castlingLeft = legalMoves.getCastlingLeft();
this.castlingRight = legalMoves.getCastlingRight();
this.enPassantX = legalMoves.getEnPassantX();
this.enPassantY = legalMoves.getEnPassantY();
for (int i = 0; i < moves.size(); i++) {
if (x == moves.get(i)[0] && y == moves.get(i)[1]) {
return true;
}
}
}
return false;
}
public void undoLastMove() {
if (this.turns > 0) {
states.remove(this.turns);
this.turns = turns - 1;
//this.board = new Piece[lineNum][colNum];
this.x = -1;
this.y = -1;
String[] undo = states.get(turns).split("\n");
Board newBoard = new Board(undo);
this.board = newBoard.board;
if (undo[lineNum] == "B" || turns == 0) {
whiteTurn = true;
}
else {
whiteTurn = false;
}
}
}
public Board(Board board) {
Piece[][] newBoard = new Piece[lineNum][colNum];
for (int i = 0; i < colNum; i++) {
for (int j = 0; j < lineNum; j++) {
Piece piece = board.getPieceAt(i,j);
if (piece != null) {
newBoard[j][i] = new Piece(piece);
}
}
}
}
public void playMove(Move move) {
board[move.getFromY()][move.getFromX()].setX(move.getToX());
board[move.getFromY()][move.getFromX()].setY(move.getToY());
board[move.getToY()][move.getToX()] = board[move.getFromY()][move.getFromX()];
board[move.getFromY()][move.getFromX()] = null;
for (int x = 0; x < colNum; x++) {
for (int y = 0; y < lineNum; y++) {
canPromote(x, y);
}
}
this.states.add(toString());
}
ArrayList<Piece> promoPieces= new ArrayList<>();
boolean promotion;
private boolean canPromote(int x, int y) {
if (board[y][x] != null && board[y][x].getType() == PieceType.Pawn) {
boolean isWhite = board[y][x].isWhite(); // ✅ Declare 'isWhite' here
if ((isWhite && y == 0) || (!isWhite && y == 7)) {
board[y][x] = new Piece(isWhite, PieceType.Queen, x, y); // ✅ Now valid
return true;
}
}
return false;
}
}