const std = @import("std");
pub fn main() !void {
var bit_board: BitBoard = .{ .board = 0 };
bit_board.show();
}
const Square = enum(BoardType) {
// zig fmt: off
a8, b8, c8, d8, e8, f8, g8, h8,
a7, b7, c7, d7, e7, f7, g7, h7,
a6, b6, c6, d6, e6, f6, g6, h6,
a5, b5, c5, d5, e5, f5, g5, h5,
a4, b4, c4, d4, e4, f4, g4, h4,
a3, b3, c3, d3, e3, f3, g3, h3,
a2, b2, c2, d2, e2, f2, g2, h2,
a1, b1, c1, d1, e1, f1, g1, h1,
// zig fmt: on
fn int(self: @This()) u6 {
return @intCast(u6, @enumToInt(self));
}
};
const SIZE = 8;
const BoardType = u64;
const BitBoard = packed struct(BoardType) {
board: BoardType = 0,
fn set(self: *@This(), square: Square) void {
self.board |= @as(BoardType, 1) << square.int();
}
fn isSet(self: @This(), square: Square) bool {
return (self.board & @as(BoardType, 1) << square.int() != 0);
}
fn unSet(self: *@This(), square: Square) void {
self.board &= @as(BoardType, 0) << square.int();
}
fn flip(self: *@This(), square: Square) void {
self.board ^= @as(BoardType, 1) << square.int();
}
// pop removes the bit if set
fn pop(self: *@This(), square: Square) void {
if (self.isSet(square))
self.board ^= @as(BoardType, 1) << square.int();
}
fn show(self: @This()) void {
var rank: usize = 0;
while (rank < SIZE) : (rank += 1) {
var file: usize = 0;
while (file < SIZE) : (file += 1) {
if (file == 0) std.debug.print("{d}| ", .{SIZE - rank});
const square = @intCast(u6, rank * SIZE + file);
const mask: usize = if (self.board & (@as(BoardType, 1) << square) != 0) 1 else 0;
std.debug.print("{d} ", .{mask});
}
std.debug.print("\n", .{});
}
std.debug.print("{s:>18}\n", .{"---------------"});
std.debug.print("{s:>18}\n", .{"a b c d e f g h"});
std.debug.print("\nBitBoard: {d}\n", .{self.board});
}
};
test "BitBoard" {
{ // set, unSet
var bb: BitBoard = .{};
try std.testing.expectEqual(@as(BoardType, 0), bb.board);
bb.set(.a8);
try std.testing.expectEqual(@as(BoardType, 1), bb.board);
bb.unSet(.a8);
bb.set(.h1);
const exp = @as(BoardType, 1) << @as(u6, 63);
try std.testing.expectEqual(exp, bb.board);
}
{ // flip
var bb: BitBoard = .{};
bb.set(.e4);
try std.testing.expect(bb.isSet(.e4));
bb.set(.f1);
try std.testing.expect(bb.isSet(.f1));
bb.flip(.e4);
bb.flip(.f1);
try std.testing.expectEqual(@as(BoardType, 0), bb.board);
bb.flip(.f1); // sets f1 again
try std.testing.expectEqual(
@as(BoardType, @as(BoardType, 1) << @enumToInt(Square.f1)),
bb.board,
);
}
{ // pop
var bb: BitBoard = .{};
bb.set(.e4);
bb.set(.f1);
bb.pop(.e4);
bb.pop(.f1);
bb.set(.g3);
try std.testing.expectEqual(
@as(BoardType, @as(BoardType, 1) << @enumToInt(Square.g3)),
bb.board,
);
bb.pop(.e4); // does nothing
try std.testing.expectEqual(
@as(BoardType, @as(BoardType, 1) << @enumToInt(Square.g3)),
bb.board,
);
}
}