GZPVUGLJGD3VGLIK7JDABQ24E5SWN5CYRDGI6PIAFZ2BIMRDMANQC
YVNKHIU4ENET52Y5BD5WFA23EVTQ4ZQQLIAZRRA4AN44TXUTNRCQC
BL3ZR4OWJM54HFXUNMUZKB5YQYVBT7ETFIXCOXWL6S5SZFM6IFDQC
TDHJSFFSJZBEZFMDHPLRSVB6CIVJ7AWGGNIC3WUCADQLQSIQKXDAC
SNMQLFZFCV5XTPRLSD7SV4RPVOGUVJOYCZAKI5ATCEPSI5JMGVAAC
XARNBDT4A5X6F3WFC5YNZBV5RNZ5GBRYOWKAK5R6HSTPBNIXTHDAC
FR6N5DIUYYWT5BBOIBOX3GCSEKZIINSGT4F4CWM6YA2XLQEOU4ZQC
}
return attacks;
}
fn attackWithBlocker(blocks: Chess.BoardType, square: Chess.Square, piece: Chess.Pieces) Chess.BoardType {
const rank = @intCast(isize, square.rank());
const file = @intCast(isize, square.file());
const moves = switch (piece) {
.bishop => [_][2]i3{
.{ -1, -1 },
.{ -1, 1 },
.{ 1, -1 },
.{ 1, 1 },
},
.rook => [_][2]i3{
.{ -1, 0 },
.{ 1, 0 },
.{ 0, -1 },
.{ 0, 1 },
},
else => unreachable,
};
var attacks: Chess.BoardType = 0;
for (moves) |m| {
var step: i5 = 1;
while (step < Chess.SIZE) : (step += 1) {
const dr = rank + m[0] * step;
const df = file + m[1] * step;
if (m[0] > 0 and dr > 7) break;
if (m[0] < 0 and dr < 0) break;
if (m[1] > 0 and df > 7) break;
if (m[1] < 0 and df < 0) break;
const s = @intCast(u6, dr * Chess.SIZE + df);
const mask = @intCast(Chess.BoardType, @as(Chess.BoardType, 1) << s);
attacks |= mask;
// stop when we hit a blocker
if (mask & blocks != 0) break;
}
try std.testing.expectEqual(bb.board, got);
}
{ // rook d4
bb.board = 0;
bb.setSlice(&[_]Chess.Square{ .b4, .d3, .d5 });
const got = attackWithBlocker(bb.board, .d4, .rook);
bb.board = 0;
bb.setSlice(&[_]Chess.Square{ .c4, .b4, .d3, .d5, .e4, .f4, .g4, .h4 });
try std.testing.expectEqual(bb.board, got);
}
{ // rook h8
bb.board = 0;
bb.setSlice(&[_]Chess.Square{.b8});
const got = attackWithBlocker(bb.board, .h8, .rook);
bb.board = 0;
bb.setSlice(&[_]Chess.Square{ .b8, .c8, .d8, .e8, .f8, .g8, .h7, .h6, .h5, .h4, .h3, .h2, .h1 });
try std.testing.expectEqual(bb.board, got);
}
}
}
pub fn riderBlocker(self: @This(), square: Square, piece: Pieces) BoardType {
const rank = @intCast(isize, square.rank());
const file = @intCast(isize, square.file());
const moves = switch (piece) {
.bishop => [_][2]i3{
.{ -1, -1 },
.{ -1, 1 },
.{ 1, -1 },
.{ 1, 1 },
},
.rook => [_][2]i3{
.{ -1, 0 },
.{ 1, 0 },
.{ 0, -1 },
.{ 0, 1 },
},
else => unreachable,
};
var blockers: BoardType = 0;
for (moves) |m| {
var step: i5 = 1;
while (step < SIZE) : (step += 1) {
const dr = rank + m[0] * step;
const df = file + m[1] * step;
if (m[0] > 0 and dr > 7) break;
if (m[0] < 0 and dr < 0) break;
if (m[1] > 0 and df > 7) break;
if (m[1] < 0 and df < 0) break;
const s = @intCast(u6, dr * SIZE + df);
const mask = @intCast(BoardType, @as(BoardType, 1) << s);
blockers |= mask;
// stop when we hit a blocker
if (mask & self.board != 0) break;
}
}
return blockers;
test "riderBlocker" {
var bb: BitBoard = .{};
{ // bishop d4
bb.board = 0;
bb.setSlice(&[_]Square{ .c3, .b6, .f2 });
const got = bb.riderBlocker(.d4, .bishop);
bb.board = 0;
bb.setSlice(&[_]Square{ .c3, .f2, .e3, .c5, .b6, .e5, .f6, .g7, .h8 });
try std.testing.expectEqual(bb.board, got);
}
{ // rook d4
bb.board = 0;
bb.setSlice(&[_]Square{ .b4, .d3, .d5 });
const got = bb.riderBlocker(.d4, .rook);
bb.board = 0;
bb.setSlice(&[_]Square{ .c4, .b4, .d3, .d5, .e4, .f4, .g4, .h4 });
try std.testing.expectEqual(bb.board, got);
}
{ // rook h8
bb.board = 0;
bb.setSlice(&[_]Square{.b8});
const got = bb.riderBlocker(.h8, .rook);
bb.board = 0;
bb.setSlice(&[_]Square{ .b8, .c8, .d8, .e8, .f8, .g8, .h7, .h6, .h5, .h4, .h3, .h2, .h1 });
try std.testing.expectEqual(bb.board, got);
}
}