From 054cd41cf631417abed2975d4c372866043c734e Mon Sep 17 00:00:00 2001 From: k Date: Tue, 21 Oct 2025 19:07:03 -0400 Subject: [PATCH 1/5] updated some types to u64 in c code --- headers/help.h | 4 ++-- src/help.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/headers/help.h b/headers/help.h index 7b57f31..eb142f0 100644 --- a/headers/help.h +++ b/headers/help.h @@ -2,8 +2,8 @@ #define HELP_H #include "types.h" -long long fullSet(sets *s); -long long fullSetBoth(game *g); +unsigned long long fullSet(sets *s); +unsigned long long fullSetBoth(game *g); void print_bitboard(long long bitboard); unsigned long long *findSet(game *g, long long bit); unsigned long long *charToSet(game *g, char c); diff --git a/src/help.c b/src/help.c index 3f84553..896544a 100644 --- a/src/help.c +++ b/src/help.c @@ -1,11 +1,11 @@ #include #include "types.h" -long long fullSet(sets *s) { +unsigned long long fullSet(sets *s) { return s->bishops | s->king | s->knights | s->pawns | s->queen | s->rooks; } -long long fullSetBoth(game *g) { +unsigned long long fullSetBoth(game *g) { return fullSet(&g->white) ^ fullSet(&g->black); } @@ -25,7 +25,7 @@ void print_bitboard(long long bitboard) { printf("\n"); } -long long *findSet(game *g, long long bit) { +unsigned long long *findSet(game *g, long long bit) { if (g->white.pawns & bit) { return &g->white.pawns; } else if (g->white.knights & bit) { @@ -55,7 +55,7 @@ long long *findSet(game *g, long long bit) { } } -long long *charToSet(game *g, char c) { +unsigned long long *charToSet(game *g, char c) { switch (c) { case 'P': return &g->white.pawns; From 10f81cf7f02df7880136fffe3eedd8df4cf14655 Mon Sep 17 00:00:00 2001 From: k Date: Tue, 21 Oct 2025 19:11:07 -0400 Subject: [PATCH 2/5] Updated types to use more zig types in zig code --- src/main.zig | 36 +++++++----------------------------- src/move.zig | 3 ++- src/types.zig | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 30 deletions(-) create mode 100644 src/types.zig diff --git a/src/main.zig b/src/main.zig index 4605998..eea0b45 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,28 +1,6 @@ const std = @import("std"); const mov = @import("move.zig"); -const c = @cImport({ - @cInclude("main.h"); - @cInclude("types.h"); - @cInclude("help.h"); - @cInclude("eval.h"); - @cInclude("moves.h"); -}); - -const uciTag = enum { - text, - move, - game, - exit, - pass, -}; - -const uciRet = union(uciTag) { - text: []const u8, - move: []u8, - game: *c.game, - exit: void, - pass: void, -}; +const types = @import("types.zig"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; @@ -31,7 +9,7 @@ pub fn main() !void { const stdin = std.io.getStdIn(); var reader = stdin.reader(); - var game: *c.game = uciPos("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", alloc); + var game: *types.game = uciPos("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", alloc); defer alloc.destroy(game); while (true) { const line = try reader.readUntilDelimiterAlloc(alloc, '\n', std.math.maxInt(usize)); @@ -58,7 +36,7 @@ pub fn main() !void { } } -fn uci(str: []const u8, game: *c.game, alloc: std.mem.Allocator) uciRet { +fn uci(str: []const u8, game: *types.game, alloc: std.mem.Allocator) types.uciRet { const pos = std.mem.indexOfAny(u8, str, " \t\n\r") orelse str.len; const tok = str[0..pos]; if (std.mem.eql(u8, tok, "uci")) return .{ .text = "id name RatChess 0.1\nid author rat<3\nuciok\n" }; @@ -69,7 +47,7 @@ fn uci(str: []const u8, game: *c.game, alloc: std.mem.Allocator) uciRet { return .{ .pass = {} }; } -fn uciPos(str: []const u8, alloc: std.mem.Allocator) *c.game { +fn uciPos(str: []const u8, alloc: std.mem.Allocator) *types.game { const pos = std.mem.indexOfAny(u8, str, " \t\n\r") orelse str.len; const tok = str[0..pos]; //var game = fenGame("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", alloc); @@ -82,7 +60,7 @@ fn uciPos(str: []const u8, alloc: std.mem.Allocator) *c.game { return fenGame("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", alloc); //this should be an error } -fn fenGame(str: []const u8, alloc: std.mem.Allocator) [*c]c.game { +fn fenGame(str: []const u8, alloc: std.mem.Allocator) *types.game { var pos: u8 = 0; var space: u8 = 0; const g = alloc.create(c.game) catch return null; @@ -118,8 +96,8 @@ fn playMoves(game: [*c]c.game, str: []const u8) [*c]c.game { return game; } -fn uciGo(game: *c.game, alloc: std.mem.Allocator) []u8 { - var moves = std.ArrayList(c.move).init(alloc); +fn uciGo(game: *types.game, alloc: std.mem.Allocator) []u8 { + var moves = std.ArrayList(types.move).init(alloc); defer moves.deinit(); const str = alloc.alloc(u8, 5) catch unreachable; const m = c.move{ .From = 0, .To = 8, .Promo = 0 }; diff --git a/src/move.zig b/src/move.zig index e3be055..29cb32d 100644 --- a/src/move.zig +++ b/src/move.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const types = @import("types.zig"); const c = @cImport({ @cInclude("main.h"); @cInclude("types.h"); @@ -7,7 +8,7 @@ const c = @cImport({ @cInclude("moves.h"); }); -pub fn moveTypeToStr(move: c.move, buf: []u8) void { +pub fn moveTypeToStr(move: types.move, buf: []u8) void { const xTo = @mod(move.To, 8); const yTo = @divTrunc(move.To, 8); const xFrom = @mod(move.From, 8); diff --git a/src/types.zig b/src/types.zig new file mode 100644 index 0000000..c9c627a --- /dev/null +++ b/src/types.zig @@ -0,0 +1,46 @@ +const c = @cImport({ + @cInclude("main.h"); + @cInclude("types.h"); + @cInclude("help.h"); + @cInclude("eval.h"); + @cInclude("moves.h"); +}); + +const uciTag = enum { + text, + move, + game, + exit, + pass, +}; + +pub const uciRet = union(uciTag) { + text: []const u8, + move: []u8, + game: *game, + exit: void, + pass: void, +}; +const set = struct { + pawns: u64, + knights: u64, + bishops: u64, + rooks: u64, + queen: u64, + king: u64, +}; +pub const game = struct { + black: set, + white: set, + whiteToMove: bool, +}; +pub const move = struct { + From: u32, + To: u32, + Promo: u8, +}; +// struct { +// To: u8, +// From: u8, +// Promo: u8, +// }; From 6af6a16a77987e7215350db736fadfb4aaf2b5fc Mon Sep 17 00:00:00 2001 From: k Date: Tue, 21 Oct 2025 19:13:10 -0400 Subject: [PATCH 3/5] added stock fish for move eval in uchess --- shell.nix | 2 +- uchess.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/shell.nix b/shell.nix index f1155e7..7a33694 100644 --- a/shell.nix +++ b/shell.nix @@ -1,7 +1,7 @@ {pkgs ? import {}}: with pkgs; mkShell rec { - packages = [gdb zls uchess cutechess]; + packages = [gdb zls uchess cutechess stockfish]; nativeBuildInputs = [ zig ]; diff --git a/uchess.json b/uchess.json index f02384e..47b5786 100644 --- a/uchess.json +++ b/uchess.json @@ -5,12 +5,12 @@ "uciEngines": [ { "name":"rat", - "engine":"./a.out", + "engine":"./zig-out/bin/RatChess", "ponder":false }, { "name": "stockfish", - "engine": "/nix/store/5d7aqjdak73qlsimiismbj0m1h9b566j-stockfish-17/bin/stockfish", + "engine": "/nix/store/xrzjqi5m9yphj4p5wgpvnamxs38ap0wv-stockfish-17/bin/stockfish", "hash": 128, "ponder": false, "ownBook": false, From 7cded275f23d9e9f534632d61d1de5d6ea24ea54 Mon Sep 17 00:00:00 2001 From: k Date: Tue, 21 Oct 2025 19:16:21 -0400 Subject: [PATCH 4/5] updated fenGame function. --- src/main.zig | 55 +++++++++++++++++++++++++--------------------------- src/move.zig | 14 +++++++++++++ 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/main.zig b/src/main.zig index eea0b45..f6253df 100644 --- a/src/main.zig +++ b/src/main.zig @@ -50,11 +50,10 @@ fn uci(str: []const u8, game: *types.game, alloc: std.mem.Allocator) types.uciRe fn uciPos(str: []const u8, alloc: std.mem.Allocator) *types.game { const pos = std.mem.indexOfAny(u8, str, " \t\n\r") orelse str.len; const tok = str[0..pos]; - //var game = fenGame("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", alloc); if (std.mem.eql(u8, tok, "fen")) return fenGame(str[pos..], alloc); if (std.mem.eql(u8, tok, "startpos")) { var game = fenGame("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", alloc); - game = playMoves(game, str[pos..]); + game = mov.playMoves(game, str[pos..]); return game; } return fenGame("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", alloc); //this should be an error @@ -63,47 +62,43 @@ fn uciPos(str: []const u8, alloc: std.mem.Allocator) *types.game { fn fenGame(str: []const u8, alloc: std.mem.Allocator) *types.game { var pos: u8 = 0; var space: u8 = 0; - const g = alloc.create(c.game) catch return null; + var g = alloc.create(types.game) catch unreachable; + g.* = std.mem.zeroes(types.game); for (str) |chr| { - if (pos > 64) { - if (chr == ' ') space += 1; - if (space == 1 and chr == 'b') g.whiteToMove = false; - if (space == 1 and chr == 'w') g.whiteToMove = true; + if (chr == ' ') { + space += 1; + continue; + } + if (space == 1) { + if (chr == 'b') g.whiteToMove = false; + if (chr == 'w') g.whiteToMove = true; + //continue; + break; + } + + if (std.ascii.isDigit(chr)) { + pos += @truncate(chr - '0'); continue; } - if (std.ascii.isDigit(chr)) pos += @truncate(chr - '0'); if (chr == '/') continue; - const set: [*c]c_ulonglong = c.charToSet(g, chr); + const set: *u64 = mov.charToSet(g, chr); const bit: u64 = @as(u64, 1) << @truncate(pos); - if (set != null) - set.* |= @as(c_ulonglong, bit); + set.* |= bit; pos += 1; } return g; } -fn playMoves(game: [*c]c.game, str: []const u8) [*c]c.game { - if (str.len < 4) return game; - var splitItr = std.mem.splitSequence(u8, str, " "); - while (splitItr.next()) |moveString| { - var move: c.move = .{ .To = 0, .From = 0, .Promo = 0 }; - if (moveString.len < 4) continue; - move.From = (moveString[0] - 'a') + (moveString[1] - '1') * 8; - move.To = (moveString[2] - 'a') + (moveString[3] - '1') * 8; - move.Promo = if (moveString.len == 5) moveString[4] else 0; - c.makeMove(game, &move); - } - return game; -} - fn uciGo(game: *types.game, alloc: std.mem.Allocator) []u8 { var moves = std.ArrayList(types.move).init(alloc); defer moves.deinit(); const str = alloc.alloc(u8, 5) catch unreachable; - const m = c.move{ .From = 0, .To = 8, .Promo = 0 }; - moves.append(m) catch return str; - _ = game; - mov.moveTypeToStr(m, str); + mov.knightMove(game, &moves); + if (moves.capacity == 0) { + @memcpy(str.ptr, "err"); + return str; + } + mov.moveTypeToStr(moves.items[0], str); return str; } @@ -152,4 +147,6 @@ test "uci position" { defer alloc.destroy(out.game); try std.testing.expect(out == .game); try std.testing.expect(out.game.whiteToMove == true); + try std.testing.expect(out.game.white.king != 0); + try std.testing.expect(out.game.black.king != 0); } diff --git a/src/move.zig b/src/move.zig index 29cb32d..f658614 100644 --- a/src/move.zig +++ b/src/move.zig @@ -21,6 +21,20 @@ pub fn moveTypeToStr(move: types.move, buf: []u8) void { buf[4] = move.Promo; } +pub fn playMoves(game: *types.game, str: []const u8) *types.game { + if (str.len < 4) return game; + var splitItr = std.mem.splitSequence(u8, str, " "); + while (splitItr.next()) |moveString| { + var move: types.move = .{ .To = 0, .From = 0, .Promo = 0 }; + if (moveString.len < 4) continue; + move.From = (moveString[0] - 'a') + (moveString[1] - '1') * 8; + move.To = (moveString[2] - 'a') + (moveString[3] - '1') * 8; + move.Promo = if (moveString.len == 5) moveString[4] else 0; + c.makeMove(@ptrCast(game), @ptrCast(&move)); + } + return game; +} + // pub fn pawnMove(arr: std.ArrayList(c.move)) void { // const move = c.move{ .From = 8, .To = 16, .Promo = 0 }; // } From 1d41b76fa8078d6354e87baff691d9d06aff1283 Mon Sep 17 00:00:00 2001 From: k Date: Tue, 21 Oct 2025 19:18:41 -0400 Subject: [PATCH 5/5] added helper functions for move --- src/move.zig | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/move.zig b/src/move.zig index f658614..70f0dca 100644 --- a/src/move.zig +++ b/src/move.zig @@ -35,6 +35,36 @@ pub fn playMoves(game: *types.game, str: []const u8) *types.game { return game; } +pub fn charToSet(g: *types.game, chr: u8) *u64 { + return switch (chr) { + 'P' => &g.white.pawns, + 'N' => &g.white.knights, + 'B' => &g.white.bishops, + 'R' => &g.white.rooks, + 'Q' => &g.white.queen, + 'K' => &g.white.king, + 'p' => &g.black.pawns, + 'n' => &g.black.knights, + 'b' => &g.black.bishops, + 'r' => &g.black.rooks, + 'q' => &g.black.queen, + 'k' => &g.black.king, + else => { + std.log.err("you should not be here ${c}$", .{chr}); + unreachable; + }, + }; +} + // pub fn pawnMove(arr: std.ArrayList(c.move)) void { // const move = c.move{ .From = 8, .To = 16, .Promo = 0 }; // } +fn bitboardToMoves(start: u8, moves: u64, arr: *std.ArrayList(types.move)) void { + var lmoves = moves; + while (lmoves != 0) { + const pos = @ctz(lmoves); + const m: types.move = .{ .From = start, .Promo = 0, .To = pos }; + lmoves = lmoves & ~@as(u64, 1) << @truncate(pos); + arr.append(m) catch unreachable; + } +}