zig-chess/src/chess/piece.zig

82 lines
2.6 KiB
Zig

const std = @import("std");
pub const Color = enum(u1) {
black = 0,
white = 1,
};
pub const PieceType = enum(u3) {
none = 0,
pawn = 1,
knight = 2,
bishop = 3,
rook = 4,
queen = 5,
king = 6,
};
pub fn encode(color: Color, piece_type: PieceType) u4 {
if (piece_type == .none) return 0;
return (@as(u4, @intFromEnum(color)) << 3) | @as(u4, @intFromEnum(piece_type));
}
pub fn typeOf(encoded: u4) PieceType {
const type_bits: u3 = @intCast(encoded & 0b111);
return @enumFromInt(type_bits);
}
pub fn colorOf(encoded: u4) ?Color {
if (typeOf(encoded) == .none) return null;
const color_bit: u1 = @intCast(encoded >> 3);
return @enumFromInt(color_bit);
}
pub fn fromFENChar(ch: u8) !u4 {
switch (ch) {
'P' => return encode(.white, .pawn),
'N' => return encode(.white, .knight),
'B' => return encode(.white, .bishop),
'R' => return encode(.white, .rook),
'Q' => return encode(.white, .queen),
'K' => return encode(.white, .king),
'p' => return encode(.black, .pawn),
'n' => return encode(.black, .knight),
'b' => return encode(.black, .bishop),
'r' => return encode(.black, .rook),
'q' => return encode(.black, .queen),
'k' => return encode(.black, .king),
else => return error.InvalidPieceType,
}
}
test "encode pieces uses low bits for type and bit 3 for color" {
try std.testing.expectEqual(@as(u4, 1), encode(.black, .pawn));
try std.testing.expectEqual(@as(u4, 6), encode(.black, .king));
try std.testing.expectEqual(@as(u4, 9), encode(.white, .pawn));
try std.testing.expectEqual(@as(u4, 14), encode(.white, .king));
try std.testing.expectEqual(@as(u4, 0), encode(.white, .none));
try std.testing.expectEqual(@as(u4, 10), encode(.white, .knight));
try std.testing.expectEqual(@as(u4, 3), encode(.black, .bishop));
}
test "fromFENChar encodes white and black pieces" {
try std.testing.expectEqual(encode(.white, .pawn), fromFENChar('P'));
try std.testing.expectEqual(encode(.black, .king), fromFENChar('k'));
}
test "fromFENChar rejects invalid character" {
try std.testing.expectError(error.InvalidPieceType, fromFENChar('x'));
}
test "typeOf returns correct type" {
try std.testing.expectEqual(.pawn, typeOf(9));
try std.testing.expectEqual(.king, typeOf(6));
try std.testing.expectEqual(.none, typeOf(0));
}
test "colorOf returns correct color" {
try std.testing.expectEqual(null, colorOf(0));
try std.testing.expectEqual(.white, colorOf(14));
try std.testing.expectEqual(.black, colorOf(3));
}