JPK7SJDQWLCNDXJQEQQHXBN4Y677BPQ5QBL55GRZ55RSP4GK4L4AC EHBLDMND5ASGZTTLDLEA5RGQIAZTXZN4HBPGD5PB6FDGZGTJ33SQC BL3ZR4OWJM54HFXUNMUZKB5YQYVBT7ETFIXCOXWL6S5SZFM6IFDQC FR6N5DIUYYWT5BBOIBOX3GCSEKZIINSGT4F4CWM6YA2XLQEOU4ZQC 7SQSGQOZRCHN3GGWPNFI36K2R7YZMOPXZP3FP4PYDDOZML5YIYOQC 7T5U3ARTEEAORKCSJY763X5TJRGHCEQK3OW323YO5CZIM77EH77AC 3MEBL2ZUY2LI5LW6MK6B32F62TSVF46QVNIDB3Y4OWLAN4NT7KTAC QYOCQUIWNSZNLCPDJCKERKC6BXBUNTE6AJCFYL4WDRU32LFX37XQC O6734I3LMVTKXE5Y7FR3EDGSVIJQHFATUPJJCMRYXD7KLAN6E4UQC XCZABYMDLHLHXNTHZFCXPNP6VOCNYUROAQACE5SWBL5FJK2EB7WQC fn init(self: *@This()) void {self.parseFEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1") catch unreachable;
fn init(FEN: ?Str) !@This() {var gs = GameState{ .attacks = Attacks.init() };if (FEN != null)try gs.parseFEN(FEN.?)elsetry gs.parseFEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");return gs;
.N, .n => self.genMoves(board, piece),.B, .b => self.genMoves(board, piece),.R, .r => self.genMoves(board, piece),.Q, .q => self.genMoves(board, piece),
.N, .n => try self.genMoves(board, piece),.B, .b => try self.genMoves(board, piece),.R, .r => try self.genMoves(board, piece),.Q, .q => try self.genMoves(board, piece),.none => unreachable,
for ([_]u8{ 'q', 'r', 'b', 'n' }) |prom| {std.debug.print("pawn promotions {any}->{any}{c}\n", .{@intToEnum(Square, source_square),@intToEnum(Square, target_square),prom,
for (promote_options) |prom| {try self.moves.append(BitMove{.source = @intToEnum(Square, source_square),.target = @intToEnum(Square, target_square),.piece = piece,.prom = prom,
std.debug.print("pawn push double: {any}->{any}\n", .{@intToEnum(Square, source_square),@intToEnum(Square, double_target),
try self.moves.append(BitMove{.source = @intToEnum(Square, source_square),.target = @intToEnum(Square, double_target),.piece = piece,.double = true,
for ([_]u8{ 'q', 'r', 'b', 'n' }) |prom| {std.debug.print("pawn promotion attacks {any}->{any}{c}\n", .{@intToEnum(Square, source_square),@intToEnum(Square, target_square),prom,
for (promote_options) |prom| {try self.moves.append(BitMove{.source = @intToEnum(Square, source_square),.target = @intToEnum(Square, target_square),.piece = piece,.prom = prom,.capture = true,
std.debug.print("pawn attack: {any} -> {any}\n", .{@intToEnum(Square, source_square),@intToEnum(Square, target_square),
try self.moves.append(BitMove{.source = @intToEnum(Square, source_square),.target = @intToEnum(Square, target_square),.piece = piece,.capture = true,
std.debug.print("pawn enpassant capture: {any}->{any}\n", .{@intToEnum(Square, source_square),@intToEnum(Square, target_enpassant),
try self.moves.append(BitMove{.source = @intToEnum(Square, source_square),.target = @intToEnum(Square, target_enpassant),.piece = piece,.capture = true,
fn castlingMoves(self: @This()) void {const king_side = switch (self.side) {.white => [_]Square{ .f1, .g1 },.black => [_]Square{ .f8, .g8 },};const queen_side = switch (self.side) {.white => [_]Square{ .d1, .c1, .b1 },.black => [_]Square{ .d8, .c8, .b8 },};const attacked_king = switch (self.side) {.white => [_]Square{ .e1, .f1 },.black => [_]Square{ .e8, .f8 },};const attacked_queen = switch (self.side) {.white => [_]Square{ .e1, .d1 },.black => [_]Square{ .e8, .d8 },};
fn castlingMoves(self: *@This(), piece: PE) !void {{ // king-side castlingconst king_side = switch (self.side) {.white => [_]Square{ .f1, .g1 },.black => [_]Square{ .f8, .g8 },};const attacked_king = switch (self.side) {.white => [_]Square{ .e1, .f1 },.black => [_]Square{ .e8, .f8 },};
// king-side castlingif ((self.side == .white and self.castling.WK) or(self.side == .black and self.castling.BK)){// make sure king side is emptryfor (king_side) |square| {if (self.occupBoth() & @as(BoardType, 1) << square.int() != 0) return;}// check that castling squares are not attackedfor (attacked_king) |square| {if (self.isSquareAttacked(square, self.enemy)) return;}
if ((self.side == .white and self.castling.WK) or(self.side == .black and self.castling.BK)){const OK = blk: {// make sure king side is emptryfor (king_side) |square| {if (self.occupBoth() & @as(BoardType, 1) << square.int() != 0) break :blk false;}
// queen-side castlingif ((self.side == .white and self.castling.WQ) or(self.side == .black and self.castling.BQ)){// make sure queen side is emptryfor (queen_side) |square| {if (self.occupBoth() & @as(BoardType, 1) << square.int() != 0) return;}// check that castling squares are not attackedfor (attacked_queen) |square| {if (self.isSquareAttacked(square, self.enemy)) return;
break :blk true;};if (OK) {try self.moves.append(BitMove{.source = attacked_king[0],.target = king_side[1],.piece = piece,});}
std.debug.print("queen side castling\n", .{});
{ // queen-side castlingconst queen_side = switch (self.side) {.white => [_]Square{ .d1, .c1, .b1 },.black => [_]Square{ .d8, .c8, .b8 },};const attacked_queen = switch (self.side) {.white => [_]Square{ .e1, .d1 },.black => [_]Square{ .e8, .d8 },};if ((self.side == .white and self.castling.WQ) or(self.side == .black and self.castling.BQ)){const OK = blk: {// make sure queen side is emptryfor (queen_side) |square| {if (self.occupBoth() & @as(BoardType, 1) << square.int() != 0) break :blk false;}// check that castling squares are not attackedfor (attacked_queen) |square| {if (self.isSquareAttacked(square, self.enemy)) break :blk false;}break :blk true;};if (OK) {try self.moves.append(BitMove{.source = attacked_queen[0],.target = queen_side[1],.piece = piece,});}}
std.debug.print("{any} capture: {any}->{any}\n", .{piece,@intToEnum(Square, source_square),@intToEnum(Square, target_square),
try self.moves.append(BitMove{.source = @intToEnum(Square, source_square),.target = @intToEnum(Square, target_square),.piece = piece,.capture = true,
std.debug.print("{any} move: {any}->{any}\n", .{piece,@intToEnum(Square, source_square),@intToEnum(Square, target_square),
try self.moves.append(BitMove{.source = @intToEnum(Square, source_square),.target = @intToEnum(Square, target_square),.piece = piece,
var game = Game{ .attacks = Attacks.init() };game.init();try game.parseFEN("r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1");
var game = try GameState.init("r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1");
var game = Game{ .attacks = Attacks.init() };try game.parseFEN("r3k2r/p11pqpbp/bn2pnp1/2pPN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R b Kkq c6 0 1");
var gs = try GameState.init("r3k2r/p11pqpbp/bn2pnp1/2pPN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w Kkq c6 0 1");try gs.generateMoves();
game.generateMoves();
const Game = struct {state: GameState,history: std.ArrayList(BitMove),fn init(allocator: std.mem.Allocator) @This() {var game: Game = undefined;game.state = GameState.init(null) catch unreachable;game.history = std.ArrayList(BitMove).init(allocator);return game;}fn deinit(self: @This()) void {self.history.deinit();}};test "Game" {var game = Game.init(std.testing.allocator);defer game.deinit();