X3FYJUNL5ORLRC7TW3C5OMNZOX4JEWL73RXOQZLRKLAUBVNARIMAC CWEVCXXC3D5NLLIFIYEWTXHPLX4EU5XH3YUUTMV7GYBLSQXT5VPQC RNEXG5IFDKMHSUR6RMNTI3Y32ORLVMZ6UJYKHLV2XBMT2QONBTVQC A46B5KNQFPTZEIL2JZKD2CQELGU3COE6FGTV2ABS5U7DVTVDGEBQC FOORIA7SEZCLKDBNMV6KEDTQOJJVAH57BQFBRSQMET6FERJPHCVQC GLTWBA5NKQIHAL23SWKCFOZQH62W6B3LX4RC5GFQUEQUIYN4OKSAC WSRRWTTVBE2K6NKPS54CXMY3QYK5YTDRGEH3YJ53VQ2XW5UM5O2QC THYIOCFC72V4ZMTLMGRGRIBARXT2LPSQCL2XNOIBI22QRVYUMIYQC TB4YBE4CMWCLSKJ43QF6IU5HVYUUO33BLXVG7XDRLJS3IFIBQLYAC NYVHTMLLUMBKBQSWO6SQDQ5KFACQLNCBRDDM5BH3OU6WWT54KC2AC LWF4H4TMNZYUKTCVDALXQLBE3U5AXQJ3LLNUJJ7YGTLG6T2O33JAC WZNDXPQM23LLYDZ3ZCTB4GOVRJLL7PMSEPSYBVFX6AOTJOZ5YYZQC 6S6HHKOXBQ5ARL7S7PKMPDIAH3VTPOAPWWSMGY37RP2R2U662FBAC 2CU67A3QXXPH722WBAL74O6P2N2RRXFBQVPT3A5QAXTUCQ3UUU5AC DKK2G2S3X7KFEJBHGLUEVTBBW6UBR36XR7ZBUWG5GO6JYXWGJOOAC const std = @import("std");const Str = []const u8;const SIZE = @import("Board.zig").SIZE;const BitMove = @import("Board.zig").BitMove;const GameState = @import("Board.zig").GameState;const MoveList = @import("Board.zig").MoveList;const search = @import("search.zig");pub fn parseGo(gs: *GameState, in: Str) !Str {if (std.mem.containsAtLeast(u8, in, 1, "depth")) {// go depth <some val>const depth = try std.fmt.parseUnsigned(u4, in[9..], 10);return search.bestMove(gs, depth);}// TODO: different time controls...return search.bestMove(gs, 6);}pub fn parsePosition(gs: *GameState, in: Str) !void {var words = std.mem.tokenize(u8, in, " ");if (words.next()) |position| {if (position[0] != 'p') {return error.InvalidPosition;}} else return error.InvalidPosition;if (words.next()) |start| {switch (start[0]) {'s' => {// startpostry gs.parseFEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");},'f' => {// fenconst end = std.mem.indexOf(u8, in, "moves");if (end) |e| {try gs.parseFEN(in[13 .. e - 1]);for ([_]u3{ 0, 1, 2, 3, 4, 5 }) |_| {_ = words.next();}} else {try gs.parseFEN(in[13..]);return;}},else => return error.InvalidPosition,}} else return error.InvalidPosition;if (words.next()) |moves| {if (moves[0] != 'm') return error.InvalidPosition;while (words.next()) |move| {const m = try parseMove(gs.*, move);_ = gs.makeMove(m, .all);}}}fn parseMove(gs: GameState, in: Str) !BitMove {var move: BitMove = .{ .source = undefined, .target = undefined, .piece = undefined };move.source = @intToEnum(Square, (in[0] - 'a' + (8 - (in[1] - '0')) * SIZE));move.target = @intToEnum(Square, (in[2] - 'a' + (8 - (in[3] - '0')) * SIZE));var ml = try MoveList.init(0);try gs.generateMoves(&ml);for (ml.slice()) |ml_move| {if (move.source == ml_move.source and move.target == ml_move.target) {move = ml_move;// if there is a promotion, check if it is the right oneif (move.prom != .none) {switch (move.prom) {.N => if (in[4] != 'N') continue,.n => if (in[4] != 'n') continue,.B => if (in[4] != 'B') continue,.b => if (in[4] != 'b') continue,.R => if (in[4] != 'R') continue,.r => if (in[4] != 'r') continue,.Q => if (in[4] != 'Q') continue,.q => if (in[4] != 'q') continue,else => unreachable,}}return move;}}return error.IllegalMove;}const Square = @import("Board.zig").Square;const Chess = @import("Chess.zig");test "UCI - parseMove" {var gs = try GameState.init("rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R w KQ - 1 8");{// gs.show();const got = try parseMove(gs, "d7c8B");try std.testing.expectEqual(Square.d7, got.source);try std.testing.expectEqual(Square.c8, got.target);try std.testing.expectEqual(Chess.PE.B, got.prom);try std.testing.expectEqual(true, got.capture);try std.testing.expectEqual(Chess.PE.P, got.piece);// _ = gs.makeMove(got, .all);// gs.show();}{// gs.show();const got = parseMove(gs, "d7d8");try std.testing.expectError(error.IllegalMove, got);}}test "UCI - parsePosition" {var gs = try GameState.init(null);{try parsePosition(&gs, "position startpos");// gs.show();}{try parsePosition(&gs, "position startpos moves e2e4 e7e5");// gs.show();}{try parsePosition(&gs, "position fen 8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - -");// gs.show();}{try parsePosition(&gs, "position fen 8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 1 moves g2g4 c7c5");// gs.show();}}
}pub fn parseGo(self: *@This(), in: Str) !Str {if (std.mem.containsAtLeast(u8, in, 1, "depth")) {// go depth <some val>const depth = try std.fmt.parseUnsigned(u4, in[9..], 10);return self.searchPosition(depth);}// TODO: different time controls...return self.searchPosition(6);
pub fn parsePosition(self: *@This(), in: Str) !void {var words = std.mem.tokenize(u8, in, " ");if (words.next()) |position| {if (position[0] != 'p') {return error.InvalidPosition;}} else return error.InvalidPosition;
if (words.next()) |start| {switch (start[0]) {'s' => {// startpostry self.parseFEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");},'f' => {// fenconst end = std.mem.indexOf(u8, in, "moves");if (end) |e| {try self.parseFEN(in[13 .. e - 1]);for ([_]u3{ 0, 1, 2, 3, 4, 5 }) |_| {_ = words.next();}} else {try self.parseFEN(in[13..]);return;}},else => return error.InvalidPosition,}} else return error.InvalidPosition;if (words.next()) |moves| {if (moves[0] != 'm') return error.InvalidPosition;while (words.next()) |move| {const m = try self.parseMove(move);_ = self.makeMove(m, .all);}}}fn parseMove(self: @This(), in: Str) !BitMove {var move: BitMove = .{ .source = undefined, .target = undefined, .piece = undefined };move.source = @intToEnum(Square, (in[0] - 'a' + (8 - (in[1] - '0')) * SIZE));move.target = @intToEnum(Square, (in[2] - 'a' + (8 - (in[3] - '0')) * SIZE));var ml = try MoveList.init(0);try self.generateMoves(&ml);for (ml.slice()) |ml_move| {if (move.source == ml_move.source and move.target == ml_move.target) {move = ml_move;// if there is a promotion, check if it is the right oneif (move.prom != .none) {switch (move.prom) {.N => if (in[4] != 'N') continue,.n => if (in[4] != 'n') continue,.B => if (in[4] != 'B') continue,.b => if (in[4] != 'b') continue,.R => if (in[4] != 'R') continue,.r => if (in[4] != 'r') continue,.Q => if (in[4] != 'Q') continue,.q => if (in[4] != 'q') continue,else => unreachable,}}return move;}}return error.IllegalMove;}fn parseFEN(self: *@This(), in: []const u8) !void {
pub fn parseFEN(self: *@This(), in: []const u8) !void {
}fn sideAttacks(self: *const @This(), color: Chess.Colors) BoardType {var ret: BoardType = 0;for (std.enums.values(Square)) |square| {if (isSquareAttacked(self, @enumToInt(square), color)) {ret |= @as(BoardType, 1) << @enumToInt(square);}}return ret;
var bb = BitBoard{};const got = game.sideAttacks(.white);bb = @bitCast(BitBoard, got);
var got: BoardType = 0;for (std.enums.values(Square)) |square| {if (game.isSquareAttacked(@enumToInt(square), .white)) {got |= @as(BoardType, 1) << @enumToInt(square);}}
}test "UCI - parseMove" {var gs = try GameState.init("rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R w KQ - 1 8");{// gs.show();const got = try gs.parseMove("d7c8B");try std.testing.expectEqual(Square.d7, got.source);try std.testing.expectEqual(Square.c8, got.target);try std.testing.expectEqual(Chess.PE.B, got.prom);try std.testing.expectEqual(true, got.capture);try std.testing.expectEqual(Chess.PE.P, got.piece);// _ = gs.makeMove(got, .all);// gs.show();}{// gs.show();const got = gs.parseMove("d7d8");try std.testing.expectError(error.IllegalMove, got);}
test "UCI - parsePosition" {var gs = try GameState.init(null);{try gs.parsePosition("position startpos");// gs.show();}{try gs.parsePosition("position startpos moves e2e4 e7e5");// gs.show();}{try gs.parsePosition("position fen 8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - -");// gs.show();}{try gs.parsePosition("position fen 8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 1 moves g2g4 c7c5");// gs.show();}}