Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Method Shortening Refactoring #68

Merged
merged 7 commits into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 63 additions & 58 deletions src/main/java/Entities/Locations/LocationBitboard.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
import Entities.Constants.FileAndRank;
import Entities.Constants.InitialPositions;

import java.util.HashMap;
import java.util.Map;

/**
* This class represents a chessboard using bitboards for each pieces location
* A new instance of this class should be created at the beginning of each game
Expand All @@ -15,7 +12,6 @@
* Castling will be tied to Entities.Pieces.King valid moves. We assume that if Entities.Pieces.King moves two spaces, we are castling.
*/
public class LocationBitboard {
private final Map<String, long[]> pieceBitboards = new HashMap<>();
public long[] whitePawn = new long[]{InitialPositions.WHITE_PAWN};
public long[] whiteRook = new long[]{InitialPositions.WHITE_ROOK};
public long[] whiteKnight = new long[]{InitialPositions.WHITE_KNIGHT};
Expand Down Expand Up @@ -80,10 +76,10 @@ public long locationBlackPawnMovedTwo() {
return blackPawnMovedTwo;
}
// Moved booleans for kings and rooks
public boolean getWhiteKingMoved(){
public boolean getWhiteKingNotMoved(){
return !whiteKingMoved;
}
public boolean getBlackKingMoved(){
public boolean getBlackKingNotMoved(){
return !blackKingMoved;
}
public boolean getLeftRookMovedW(){
Expand Down Expand Up @@ -152,24 +148,59 @@ private void update_piece(long[] pieceType, long from, long to, boolean turn) {
whitePawnMovedTwo = 0L;
blackPawnMovedTwo = 0L;

update_for_special_conditions(pieceType, from, to);

pieceType[0] = (pieceType[0] & ~from) | to; // Move the piece of pieceType

// Remove opponent piece at to
remove_opponent_piece_at_to(turn, to);

// Update all location variables: whiteLocations, blackLocations, occupied
updateLocationVariables();
}

// Move pieces for special chess rules: Castling, En Passant.
// Also updates instance variables in this class related to these rules.
private void update_for_special_conditions(long[] pieceType, long from, long to) {
if (!check_and_update_castling(pieceType, from, to)) {
if (!check_and_update_pawn(pieceType, from, to)) {
check_and_update_rook_moved(pieceType, from);
}
}
}

// Helper methods for update_piece

// Check if we are castling and update accordingly. Returns true if we castled.
private boolean check_and_update_castling(long[] pieceType, long from, long to) {
boolean checkedCastling = false;
if (pieceType[0] == whiteKing[0]) { // if we are moving a white king
if (from >>> 2 == to) { // castling to queen side
update_rook_for_castling(whiteRook, true, true);
} else if (from << 2 == to) { // castling to king side
update_rook_for_castling(whiteRook, false, true);
}
whiteKingMoved = true;
checkedCastling = true;
} else if (pieceType[0] == blackKing[0]) { // if we are moving a black king
if (from >>> 2 == to) { // castling to queen side
update_rook_for_castling(blackRook, true, false);
} else if (from << 2 == to) { // castling to king side
update_rook_for_castling(blackRook, false, false);
}
blackKingMoved = true;
} else if (pieceType[0] == whitePawn[0]) { // if we are moving a white pawn
checkedCastling = true;
}
return checkedCastling;
}

// Check if we are performing en passant. Update if opponent will be able to perform en passant next turn.
private boolean check_and_update_pawn(long[] pieceType, long from, long to) {
boolean movingPawn = false;
if (pieceType[0] == whitePawn[0]) { // if we are moving a white pawn
// if we are moving without capturing
if (((to & blackLocations) == 0L) &&
// if we are not moving straight forward when we are at Rank 5
// if we are not moving straight forward when we are at Rank 5
((from & FileAndRank.RANK_5) != 0L) && (to != (from << 8))) {
// then we perform en passant
update_en_passant(to, true);
Expand All @@ -178,6 +209,7 @@ private void update_piece(long[] pieceType, long from, long to, boolean turn) {
if (((from & FileAndRank.RANK_2) != 0L) && ((to & FileAndRank.RANK_4) != 0L)) {
whitePawnMovedTwo = to;
}
movingPawn = true;
} else if (pieceType[0] == blackPawn[0]) { // if we are moving a black pawn
// if we are moving without capturing
if (((to & whiteLocations) == 0L) &&
Expand All @@ -190,7 +222,14 @@ private void update_piece(long[] pieceType, long from, long to, boolean turn) {
if (((from & FileAndRank.RANK_7) != 0L) && ((to & FileAndRank.RANK_5) != 0L)) {
blackPawnMovedTwo = to;
}
} else if (pieceType[0] == whiteRook[0]) { // if we are moving a white rook
movingPawn = true;
}
return movingPawn;
}

// Update boolean instance variables for whether a rook moved
private void check_and_update_rook_moved(long[] pieceType, long from) {
if (pieceType[0] == whiteRook[0]) { // if we are moving a white rook
if (from == 1L) {
leftWhiteRookMoved = true;
}
Expand All @@ -204,24 +243,8 @@ else if (from == (1L << 7)) {
rightBlackRookMoved = true;
}
}

pieceType[0] = (pieceType[0] & ~from) | to; // Move the piece of pieceType

// Remove opponent piece at to
if (turn) { // White's turn
for (long[] blackPieceType : getBlackPieces()) {
blackPieceType[0] &= ~to;
}
} else {
for (long[] whitePieceType : getWhitePieces()) {
whitePieceType[0] &= ~to;
}
}
updateLocationVariables(); // Update all location variables: whiteLocations, blackLocations, occupied
}

// Helper methods for update_piece
private void update_rook_for_castling (long[] rookLocations, boolean direction, boolean color){
private void update_rook_for_castling (long[] rookLocations, boolean direction, boolean color) {
// direction == true for queen side, direction == false for king side
// color == true for White, color == false for Black
if (color) { // if moving a white king
Expand Down Expand Up @@ -251,42 +274,24 @@ private void update_en_passant (long to, boolean side) {
whitePawn[0] = whitePawn[0] & ~(to << 8);
}
}

// Remove opponent piece at to
private void remove_opponent_piece_at_to(boolean turn, long to) {
if (turn) { // White's turn
for (long[] blackPieceType : getBlackPieces()) {
blackPieceType[0] &= ~to;
}
} else {
for (long[] whitePieceType : getWhitePieces()) {
whitePieceType[0] &= ~to;
}
}
}
// ----------------------------------------------------------------------------------------------------------

/**
* Constructor for creating an instance of Entities.Locations.LocationBitboard.
* Initializes all the bitboards to the starting positions of the pieces
*/
public LocationBitboard(){
pieceBitboards.put("whitePawn", whitePawn);
pieceBitboards.put("whiteRook", whiteRook);
pieceBitboards.put("whiteKnight", whiteKnight);
pieceBitboards.put("whiteBishop", whiteBishop);
pieceBitboards.put("whiteQueen", whiteQueen);
pieceBitboards.put("whiteKing", whiteKing);
pieceBitboards.put("blackPawn", blackPawn);
pieceBitboards.put("blackRook", blackRook);
pieceBitboards.put("blackKnight", blackKnight);
pieceBitboards.put("blackBishop", blackBishop);
pieceBitboards.put("blackQueen", blackQueen);
pieceBitboards.put("blackKing", blackKing);
}

/* Unused Methods ->

public Map<String, Long> getAllPieces() {
Map<String, Long> bitboards = new HashMap<>();
for (Map.Entry<String, long[]> entry : pieceBitboards.entrySet()) {
bitboards.put(entry.getKey(), entry.getValue()[0]);
}
return bitboards;
}

public long getBitboard(String pieceType) {
return pieceBitboards.get(pieceType)[0];
}

public void setBitboard(String pieceType, long bitboard) {
pieceBitboards.get(pieceType)[0] = bitboard;
} */
public LocationBitboard(){}
}
62 changes: 40 additions & 22 deletions src/main/java/Entities/Pieces/King.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,34 +21,52 @@ public long valid_moves(long from, boolean side, LocationBitboard board) {
// Castling Move,
// Check for if King does not cross a space attacked will be done in ActualValidCalculator.
if (side) { // White
if (board.getWhiteKingMoved() && !board.getLeftRookMovedW()) {
long needsEmptyL = (1L << 1) | (1L << 2) | (1L << 3);
if ((board.getOccupied() & needsEmptyL) == 0L) {
kingCoverage |= (1L << 2);
}
kingCoverage = addWhiteKingCastlingMove(kingCoverage, board);
}
else { // Black
kingCoverage = addBlackKingCastlingMove(kingCoverage, board);
}
return kingCoverage;
}

// Returns kingCoverage with valid white king castling moves
private long addWhiteKingCastlingMove(long kingCoverage, LocationBitboard board) {
long updatedKingCoverage = kingCoverage;
if (board.getWhiteKingNotMoved() && !board.getLeftRookMovedW()) {
long needsEmptyL = (1L << 1) | (1L << 2) | (1L << 3);
if (((board.getOccupied() & needsEmptyL) == 0L) // No piece between king and rook
&& ((board.whiteRook[0] & 1L) != 0L)) { // There is a rook we can move
updatedKingCoverage |= (1L << 2);
}
if (board.getWhiteKingMoved() && !board.getRightRookMovedW()) {
long needsEmptyR = (1L << 5) | (1L << 6);
if ((board.getOccupied() & needsEmptyR) == 0L) {
kingCoverage |= (1L << 6);
}
}
if (board.getWhiteKingNotMoved() && !board.getRightRookMovedW()) {
long needsEmptyR = (1L << 5) | (1L << 6);
if ((board.getOccupied() & needsEmptyR) == 0L // No piece between king and rook
&& ((board.whiteRook[0] & (1L << 7)) != 0L)) { // There is a rook we can move
updatedKingCoverage |= (1L << 6);
}
}
else { // Black
if (board.getBlackKingMoved() && !board.getLeftRookMovedB()) {
long needsEmptyL = (1L << 57) | (1L << 58) | (1L << 59);
if ((board.getOccupied() & needsEmptyL) == 0L) {
kingCoverage |= (1L << 58);
}
return updatedKingCoverage;
}

// Returns kingCoverage with valid black king castling moves
private long addBlackKingCastlingMove(long kingCoverage, LocationBitboard board) {
long updatedKingCoverage = kingCoverage;
if (board.getBlackKingNotMoved() && !board.getLeftRookMovedB()) {
long needsEmptyL = (1L << 57) | (1L << 58) | (1L << 59);
if ((board.getOccupied() & needsEmptyL) == 0L // No piece between king and rook
&& ((board.blackRook[0] & (1L << 56)) != 0L)) { // There is a rook we can move
updatedKingCoverage |= (1L << 58);
}
if (board.getBlackKingMoved() && !board.getRightRookMovedB()) {
long needsEmptyR = (1L << 61) | (1L << 62);
if ((board.getOccupied() & needsEmptyR) == 0L) {
kingCoverage |= (1L << 62);
}
}
if (board.getBlackKingNotMoved() && !board.getRightRookMovedB()) {
long needsEmptyR = (1L << 61) | (1L << 62);
if ((board.getOccupied() & needsEmptyR) == 0L // No piece between king and rook
&& ((board.blackRook[0] & (1L << 63)) != 0L)) { // There is a rook we can move
updatedKingCoverage |= (1L << 62);
}
}
return kingCoverage;
return updatedKingCoverage;
}

public long attack_coverage(boolean side, LocationBitboard board) {
Expand Down
Loading
Loading