Compare commits

..

No commits in common. "1d41b76fa8078d6354e87baff691d9d06aff1283" and "008abd64448f8416c9649356a4e8fb92b455b76c" have entirely different histories.

7 changed files with 68 additions and 134 deletions

View File

@ -2,8 +2,8 @@
#define HELP_H #define HELP_H
#include "types.h" #include "types.h"
unsigned long long fullSet(sets *s); long long fullSet(sets *s);
unsigned long long fullSetBoth(game *g); long long fullSetBoth(game *g);
void print_bitboard(long long bitboard); void print_bitboard(long long bitboard);
unsigned long long *findSet(game *g, long long bit); unsigned long long *findSet(game *g, long long bit);
unsigned long long *charToSet(game *g, char c); unsigned long long *charToSet(game *g, char c);

View File

@ -1,7 +1,7 @@
{pkgs ? import <nixpkgs> {}}: {pkgs ? import <nixpkgs> {}}:
with pkgs; with pkgs;
mkShell rec { mkShell rec {
packages = [gdb zls uchess cutechess stockfish]; packages = [gdb zls uchess cutechess];
nativeBuildInputs = [ nativeBuildInputs = [
zig zig
]; ];

View File

@ -1,11 +1,11 @@
#include <stdio.h> #include <stdio.h>
#include "types.h" #include "types.h"
unsigned long long fullSet(sets *s) { long long fullSet(sets *s) {
return s->bishops | s->king | s->knights | s->pawns | s->queen | s->rooks; return s->bishops | s->king | s->knights | s->pawns | s->queen | s->rooks;
} }
unsigned long long fullSetBoth(game *g) { long long fullSetBoth(game *g) {
return fullSet(&g->white) ^ fullSet(&g->black); return fullSet(&g->white) ^ fullSet(&g->black);
} }
@ -25,7 +25,7 @@ void print_bitboard(long long bitboard) {
printf("\n"); printf("\n");
} }
unsigned long long *findSet(game *g, long long bit) { long long *findSet(game *g, long long bit) {
if (g->white.pawns & bit) { if (g->white.pawns & bit) {
return &g->white.pawns; return &g->white.pawns;
} else if (g->white.knights & bit) { } else if (g->white.knights & bit) {
@ -55,7 +55,7 @@ unsigned long long *findSet(game *g, long long bit) {
} }
} }
unsigned long long *charToSet(game *g, char c) { long long *charToSet(game *g, char c) {
switch (c) { switch (c) {
case 'P': case 'P':
return &g->white.pawns; return &g->white.pawns;

View File

@ -1,6 +1,28 @@
const std = @import("std"); const std = @import("std");
const mov = @import("move.zig"); const mov = @import("move.zig");
const types = @import("types.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,
};
pub fn main() !void { pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; var gpa = std.heap.GeneralPurposeAllocator(.{}){};
@ -9,7 +31,7 @@ pub fn main() !void {
const stdin = std.io.getStdIn(); const stdin = std.io.getStdIn();
var reader = stdin.reader(); var reader = stdin.reader();
var game: *types.game = uciPos("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", alloc); var game: *c.game = uciPos("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", alloc);
defer alloc.destroy(game); defer alloc.destroy(game);
while (true) { while (true) {
const line = try reader.readUntilDelimiterAlloc(alloc, '\n', std.math.maxInt(usize)); const line = try reader.readUntilDelimiterAlloc(alloc, '\n', std.math.maxInt(usize));
@ -36,7 +58,7 @@ pub fn main() !void {
} }
} }
fn uci(str: []const u8, game: *types.game, alloc: std.mem.Allocator) types.uciRet { fn uci(str: []const u8, game: *c.game, alloc: std.mem.Allocator) uciRet {
const pos = std.mem.indexOfAny(u8, str, " \t\n\r") orelse str.len; const pos = std.mem.indexOfAny(u8, str, " \t\n\r") orelse str.len;
const tok = str[0..pos]; 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" }; if (std.mem.eql(u8, tok, "uci")) return .{ .text = "id name RatChess 0.1\nid author rat<3\nuciok\n" };
@ -47,58 +69,63 @@ fn uci(str: []const u8, game: *types.game, alloc: std.mem.Allocator) types.uciRe
return .{ .pass = {} }; return .{ .pass = {} };
} }
fn uciPos(str: []const u8, alloc: std.mem.Allocator) *types.game { fn uciPos(str: []const u8, alloc: std.mem.Allocator) *c.game {
const pos = std.mem.indexOfAny(u8, str, " \t\n\r") orelse str.len; const pos = std.mem.indexOfAny(u8, str, " \t\n\r") orelse str.len;
const tok = str[0..pos]; 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, "fen")) return fenGame(str[pos..], alloc);
if (std.mem.eql(u8, tok, "startpos")) { if (std.mem.eql(u8, tok, "startpos")) {
var game = fenGame("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", alloc); var game = fenGame("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", alloc);
game = mov.playMoves(game, str[pos..]); game = playMoves(game, str[pos..]);
return game; return game;
} }
return fenGame("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", alloc); //this should be an error 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) *types.game { fn fenGame(str: []const u8, alloc: std.mem.Allocator) [*c]c.game {
var pos: u8 = 0; var pos: u8 = 0;
var space: u8 = 0; var space: u8 = 0;
var g = alloc.create(types.game) catch unreachable; const g = alloc.create(c.game) catch return null;
g.* = std.mem.zeroes(types.game);
for (str) |chr| { for (str) |chr| {
if (chr == ' ') { if (pos > 64) {
space += 1; if (chr == ' ') space += 1;
continue; if (space == 1 and chr == 'b') g.whiteToMove = false;
} if (space == 1 and chr == 'w') g.whiteToMove = true;
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; continue;
} }
if (std.ascii.isDigit(chr)) pos += @truncate(chr - '0');
if (chr == '/') continue; if (chr == '/') continue;
const set: *u64 = mov.charToSet(g, chr); const set: [*c]c_ulonglong = c.charToSet(g, chr);
const bit: u64 = @as(u64, 1) << @truncate(pos); const bit: u64 = @as(u64, 1) << @truncate(pos);
set.* |= bit; if (set != null)
set.* |= @as(c_ulonglong, bit);
pos += 1; pos += 1;
} }
return g; return g;
} }
fn uciGo(game: *types.game, alloc: std.mem.Allocator) []u8 { fn playMoves(game: [*c]c.game, str: []const u8) [*c]c.game {
var moves = std.ArrayList(types.move).init(alloc); 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: *c.game, alloc: std.mem.Allocator) []u8 {
var moves = std.ArrayList(c.move).init(alloc);
defer moves.deinit(); defer moves.deinit();
const str = alloc.alloc(u8, 5) catch unreachable; const str = alloc.alloc(u8, 5) catch unreachable;
mov.knightMove(game, &moves); const m = c.move{ .From = 0, .To = 8, .Promo = 0 };
if (moves.capacity == 0) { moves.append(m) catch return str;
@memcpy(str.ptr, "err"); _ = game;
return str; mov.moveTypeToStr(m, str);
}
mov.moveTypeToStr(moves.items[0], str);
return str; return str;
} }
@ -147,6 +174,4 @@ test "uci position" {
defer alloc.destroy(out.game); defer alloc.destroy(out.game);
try std.testing.expect(out == .game); try std.testing.expect(out == .game);
try std.testing.expect(out.game.whiteToMove == true); 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);
} }

View File

@ -1,5 +1,4 @@
const std = @import("std"); const std = @import("std");
const types = @import("types.zig");
const c = @cImport({ const c = @cImport({
@cInclude("main.h"); @cInclude("main.h");
@cInclude("types.h"); @cInclude("types.h");
@ -8,7 +7,7 @@ const c = @cImport({
@cInclude("moves.h"); @cInclude("moves.h");
}); });
pub fn moveTypeToStr(move: types.move, buf: []u8) void { pub fn moveTypeToStr(move: c.move, buf: []u8) void {
const xTo = @mod(move.To, 8); const xTo = @mod(move.To, 8);
const yTo = @divTrunc(move.To, 8); const yTo = @divTrunc(move.To, 8);
const xFrom = @mod(move.From, 8); const xFrom = @mod(move.From, 8);
@ -21,50 +20,6 @@ pub fn moveTypeToStr(move: types.move, buf: []u8) void {
buf[4] = move.Promo; 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 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 { // pub fn pawnMove(arr: std.ArrayList(c.move)) void {
// const move = c.move{ .From = 8, .To = 16, .Promo = 0 }; // 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;
}
}

View File

@ -1,46 +0,0 @@
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,
// };

View File

@ -5,12 +5,12 @@
"uciEngines": [ "uciEngines": [
{ {
"name":"rat", "name":"rat",
"engine":"./zig-out/bin/RatChess", "engine":"./a.out",
"ponder":false "ponder":false
}, },
{ {
"name": "stockfish", "name": "stockfish",
"engine": "/nix/store/xrzjqi5m9yphj4p5wgpvnamxs38ap0wv-stockfish-17/bin/stockfish", "engine": "/nix/store/5d7aqjdak73qlsimiismbj0m1h9b566j-stockfish-17/bin/stockfish",
"hash": 128, "hash": 128,
"ponder": false, "ponder": false,
"ownBook": false, "ownBook": false,