Devlog 0x6 - isSquareAttacked & Back To School
Devlog 0x6. Today, I implemented and tested the isSquareAttacked function, which determines whether a given square on the board is attacked by a specific side (white or black). This function is central to many chess-engine calculations—for instance, evaluating checks, pins, and tactical possibilities.
What isSquareAttacked Does
-
Pawn Attacks
- Checks if the square is attacked by pawns of the opposite color.
- Uses pawnAttacks and the corresponding pawn bitboards (P for white, p for black).
-
Knight Attacks
- Uses the precomputed knightAttacks[square] to see if any knight of the attacking side (white N, black n) sits on those squares.
-
Bishop Attacks
- Employs the getBishopAttacks function, passing in the current square and the combined occupancy bitboard.
- Looks for a bishop on the attacking side’s bishop bitboard (B for white, b for black).
-
Rook Attacks
- Uses getRookAttacks similarly, checking occupancy to determine possible rook paths.
- Checks if any rook of the attacking side (R for white, r for black) can attack the target square.
-
Queen Attacks
- Calls getQueenAttacks, again factoring in all pieces on the board for sliding attacks.
- Considers whether a queen (Q for white, q for black) can attack the square.
-
King Attacks
- Checks the single-square king moves with the precomputed kingAttacks[square] array.
- Verifies if the opposing king (K for white, k for black) is adjacent.
If none of these checks return true, it is safe to conclude that the square is not under attack, and the function returns false.
Implementation Details
fn isSquareAttacked(square: u6, side: u2) bool {
//attacked by white pawns
if ((side == @intFromEnum(bitboard.side.white) and ((pawnAttacks[@intFromEnum(bitboard.side.black)][square] & bitboard.bitboards[@intFromEnum(bitboard.pieceEncoding.P)])) != 0)) return true;
//attacked by black pawns
if ((side == @intFromEnum(bitboard.side.black) and ((pawnAttacks[@intFromEnum(bitboard.side.white)][square] & bitboard.bitboards[@intFromEnum(bitboard.pieceEncoding.p)])) != 0)) return true;
//attacked by knights
if ((knightAttacks[square] & (if (side == @intFromEnum(bitboard.side.white)) bitboard.bitboards[@intFromEnum(bitboard.pieceEncoding.N)] else bitboard.bitboards[@intFromEnum(bitboard.pieceEncoding.n)])) != 0) return true;
//attacked by bishops
if ((getBishopAttacks(square, bitboard.occupancies[@intFromEnum(bitboard.side.both)]) & (if (side == @intFromEnum(bitboard.side.white)) bitboard.bitboards[@intFromEnum(bitboard.pieceEncoding.B)] else bitboard.bitboards[@intFromEnum(bitboard.pieceEncoding.b)])) != 0) return true;
//attacked by rooks
if ((getRookAttacks(square, bitboard.occupancies[@intFromEnum(bitboard.side.both)]) & (if (side == @intFromEnum(bitboard.side.white)) bitboard.bitboards[@intFromEnum(bitboard.pieceEncoding.R)] else bitboard.bitboards[@intFromEnum(bitboard.pieceEncoding.r)])) != 0) return true;
//attacked by queens
if ((getQueenAttacks(square, bitboard.occupancies[@intFromEnum(bitboard.side.both)]) & (if (side == @intFromEnum(bitboard.side.white)) bitboard.bitboards[@intFromEnum(bitboard.pieceEncoding.Q)] else bitboard.bitboards[@intFromEnum(bitboard.pieceEncoding.q)])) != 0) return true;
//attacked by kings
if ((kingAttacks[square] & (if (side == @intFromEnum(bitboard.side.white)) bitboard.bitboards[@intFromEnum(bitboard.pieceEncoding.K)] else bitboard.bitboards[@intFromEnum(bitboard.pieceEncoding.k)])) != 0) return true;
return false;
}
I certainly wouldn't call it beautiful code, but it functions to correctly tell if a given piece is being attacked. Remember that:
- bitboard: Our global structure that holds bitboards for each piece type and occupancy.
- pawnAttacks, knightAttacks, kingAttacks: Precomputed attack patterns for faster lookups.
- getBishopAttacks, getRookAttacks, getQueenAttacks: Functions that dynamically calculate sliding-piece attacks based on occupancy.
Next Steps and Back to School
Next up is beginning move generation. As I go back to school today, I expect development of my chess engine to slow down slightly, but I will continue working on it every day to the best of my ability. Here's my courseload for the coming semester at Colorado School of Mines:
- Discrete Mathematics
- Linear Algebra
- Differential Equations
- Data Structures and Algorithms
- Cornerstone Design
- Beginning Weight Training
As you can see, I have a lot of math ahead of me, so prepare for some writeups to help me solidify my understanding of these topics. Thanks a bunch for reading, and I'll see you tomorrow :)