~macaptain/lkdo-chess

3d9d7975f54e09674c5de17039cd04f42c814dc0 — Michael Captain 8 months ago 5b88c91
Add bishop attack rays and rook attack rays functions
2 files changed, 140 insertions(+), 0 deletions(-)

M src/attack.zig
M test/attack.zig
M src/attack.zig => src/attack.zig +89 -0
@@ 165,3 165,92 @@ pub fn maskRookOccupancy(rook: Square) u64 {
    }
    return resetBit(bitboard, rook);
}

// Given a square occupied by a bishop and a bitboard of potentially blocking
// pieces, return a bitboard of attack rays from the bishop which terminate if
// the ray hits a block. The attack ray includes the blocking square.
pub fn bishopAttackRays(bishop: Square, block: u64) u64 {
    const sq = @enumToInt(bishop);
    const block_minus_sq = resetBit(block, bishop);
    const rank = @intCast(i8, sq / 8);
    const file = @intCast(i8, sq % 8);
    var bitboard: u64 = 0;
    var r = rank;
    var f = file;
    while (r <= 7 and f <= 7) : ({
        r += 1;
        f += 1;
    }) {
        const bit = @as(u64, 1) << @intCast(u6, 8 * r + f);
        bitboard |= bit;
        if (bit & block_minus_sq != 0) break;
    }
    r = rank;
    f = file;
    while (r >= 0 and f <= 7) : ({
        r -= 1;
        f += 1;
    }) {
        const bit = @as(u64, 1) << @intCast(u6, 8 * r + f);
        bitboard |= bit;
        if (bit & block_minus_sq != 0) break;
    }
    r = rank;
    f = file;
    while (r <= 7 and f >= 0) : ({
        r += 1;
        f -= 1;
    }) {
        const bit = @as(u64, 1) << @intCast(u6, 8 * r + f);
        bitboard |= bit;
        if (bit & block_minus_sq != 0) break;
    }
    r = rank;
    f = file;
    while (r >= 0 and f >= 0) : ({
        r -= 1;
        f -= 1;
    }) {
        const bit = @as(u64, 1) << @intCast(u6, 8 * r + f);
        bitboard |= bit;
        if (bit & block_minus_sq != 0) break;
    }
    return resetBit(bitboard, bishop);
}

// Given a square occupied by a rook and a bitboard of potentially blocking
// pieces, return a bitboard of attack rays from the rook which terminate if
// the ray hits a block. The attack ray includes the blocking square.
pub fn rookAttackRays(rook: Square, block: u64) u64 {
    const sq = @enumToInt(rook);
    const block_minus_sq = resetBit(block, rook);
    const rank = @intCast(i8, sq / 8);
    const file = @intCast(i8, sq % 8);
    var bitboard: u64 = 0;
    var f = file;
    var r = rank;
    while (r <= 7) : (r += 1) {
        const bit = @as(u64, 1) << @intCast(u6, 8 * r + f);
        bitboard |= bit;
        if (bit & block_minus_sq != 0) break;
    }
    r = rank;
    while (r >= 0) : (r -= 1) {
        const bit = @as(u64, 1) << @intCast(u6, 8 * r + f);
        bitboard |= bit;
        if (bit & block_minus_sq != 0) break;
    }
    r = rank;
    while (f >= 0) : (f -= 1) {
        const bit = @as(u64, 1) << @intCast(u6, 8 * r + f);
        bitboard |= bit;
        if (bit & block_minus_sq != 0) break;
    }
    f = file;
    while (f <= 7) : (f += 1) {
        const bit = @as(u64, 1) << @intCast(u6, 8 * r + f);
        bitboard |= bit;
        if (bit & block_minus_sq != 0) break;
    }
    return resetBit(bitboard, rook);
}

M test/attack.zig => test/attack.zig +51 -0
@@ 220,3 220,54 @@ test "rook in corner relevant occupancy bits" {

    expectEqual(bitboardFromSquares(expected_squares[0..]), maskRookOccupancy(rook));
}

test "bishop attack rays with blockers" {
    const bishop = Square.e5;
    const block_squares = [_]Square{
        Square.g3,
        Square.a1,
        Square.d6,
    };
    const block = bitboardFromSquares(block_squares[0..]);

    const expected_squares = [_]Square{
        Square.f6,
        Square.g7,
        Square.h8,
        Square.f4,
        Square.g3,
        Square.d4,
        Square.c3,
        Square.b2,
        Square.a1,
        Square.d6,
    };

    expectEqual(bitboardFromSquares(expected_squares[0..]), bishopAttackRays(bishop, block));
}

test "rook attack rays with blockers" {
    const rook = Square.d5;
    const block_squares = [_]Square{
        Square.d8,
        Square.g5,
        Square.c5,
    };
    const block = bitboardFromSquares(block_squares[0..]);

    const expected_squares = [_]Square{
        Square.d6,
        Square.d7,
        Square.d8,
        Square.e5,
        Square.f5,
        Square.g5,
        Square.d4,
        Square.d3,
        Square.d2,
        Square.d1,
        Square.c5,
    };

    expectEqual(bitboardFromSquares(expected_squares[0..]), rookAttackRays(rook, block));
}