diff --git a/main.c b/main.c index 5b9faf3..947cff5 100644 --- a/main.c +++ b/main.c @@ -24,6 +24,9 @@ typedef struct { } game; game *fenGame(char *str); +void playMoves(game *g, char *moves); +long long *findSet(game *g, long long bit); +long long *charToSet(game *g, char c); void print_bitboard(long long bitboard) { for (int i = 63; i >= 0; i--) { @@ -64,7 +67,6 @@ int main() { return 0; } else if (!strcmp("setoption", token)) { } else if (!strcmp("position", token)) { - game *g; token = strtok_r(lineRest, " ", &lineRest); if (!strcmp("fen", token)) { g = fenGame(lineRest + 1); @@ -73,23 +75,55 @@ int main() { } else { g = fenGame("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); } - token = strtok_r(lineRest, " ", &lineRest); - if (!strcmp("moves", token)) { - // TODO - } - print_bitboard(g->white.pawns); - print_bitboard(g->black.pawns); + playMoves(g, lineRest); + printf("info pawns\n"); + print_bitboard(g->white.pawns | g->black.pawns); } else if (!strcmp("ucinewgame", token)) { } else if (!strcmp("isready", token)) { printf("readyok\n"); } else if (!strcmp("go", token)) { - printf("bestmove %c2%c4\n", ltz[cnt], ltz[cnt]); + if (g->whiteToMove) { + printf("bestmove %c2%c4\n", ltz[cnt], ltz[cnt]); + } else { + printf("bestmove %c7%c5\n", ltz[cnt], ltz[cnt]); + } cnt++; } } } +long long *charToSet(game *g, char c) { + switch (c) { + case 'P': + return &g->white.pawns; + case 'N': + return &g->white.knights; + case 'B': + return &g->white.bishops; + case 'R': + return &g->white.rooks; + case 'Q': + return &g->white.queen; + case 'K': + return &g->white.king; + case 'p': + return &g->black.pawns; + case 'n': + return &g->black.knights; + case 'b': + return &g->black.bishops; + case 'r': + return &g->black.rooks; + case 'q': + return &g->black.queen; + case 'k': + return &g->black.king; + default: + return NULL; + } +} + game *fenGame(char *str) { int rank = 7; int file = 0; @@ -116,49 +150,9 @@ game *fenGame(char *str) { } long long bit = 1LL << (rank * 8 + file); - switch (*str) { - case 'P': - g->white.pawns |= bit; - break; - case 'N': - g->white.knights |= bit; - break; - case 'B': - g->white.bishops |= bit; - break; - case 'R': - g->white.rooks |= bit; - break; - case 'Q': - g->white.queen |= bit; - break; - case 'K': - g->white.king |= bit; - break; - case 'p': - g->black.pawns |= bit; - break; - case 'n': - g->black.knights |= bit; - break; - case 'b': - g->black.bishops |= bit; - break; - case 'r': - g->black.rooks |= bit; - break; - case 'q': - g->black.queen |= bit; - break; - case 'k': - g->black.king |= bit; - break; - default: - fprintf(stderr, - "Error: Unknown piece character in FEN: %c at position %zu\n", - *str, pos); - break; - } + long long *set = charToSet(g, *str); + if (set) + *set |= bit; file++; str++; } @@ -166,3 +160,59 @@ game *fenGame(char *str) { g->whiteToMove = (*str == 'w') ? true : false; return g; } + +void playMoves(game *g, char *moves) { + char *move; + move = strtok_r(moves, " ", &moves); + move = strtok_r(moves, " ", &moves); + while (move) { + long long bit = 1LL << ((move[1] - '0' - 1) * 8 + (move[0] - 'a')); + long long *set = findSet(g, bit); + if (!set) { + printf("info fuck\n"); + return; + } + *set &= (~bit); + bit = 1LL << ((move[3] - '0' - 1) * 8 + (move[2] - 'a')); + long long *tmp = findSet(g, bit); + if (tmp) + *tmp &= (~bit); + if (strlen(move) == 5) { + set = charToSet(g, move[4]); + } + *set |= bit; + + move = strtok_r(moves, " ", &moves); + g->whiteToMove = !g->whiteToMove; + } +} + +long long *findSet(game *g, long long bit) { + if (g->white.pawns & bit) { + return &g->white.pawns; + } else if (g->white.knights & bit) { + return &g->white.knights; + } else if (g->white.bishops & bit) { + return &g->white.bishops; + } else if (g->white.rooks & bit) { + return &g->white.rooks; + } else if (g->white.queen & bit) { + return &g->white.queen; + } else if (g->white.king & bit) { + return &g->white.king; + } else if (g->black.pawns & bit) { + return &g->black.pawns; + } else if (g->black.knights & bit) { + return &g->black.knights; + } else if (g->black.bishops & bit) { + return &g->black.bishops; + } else if (g->black.rooks & bit) { + return &g->black.rooks; + } else if (g->black.queen & bit) { + return &g->black.queen; + } else if (g->black.king & bit) { + return &g->black.king; + } else { + return NULL; + } +} diff --git a/shell.nix b/shell.nix index b961719..ba4a69b 100644 --- a/shell.nix +++ b/shell.nix @@ -1,7 +1,7 @@ {pkgs ? import {}}: with pkgs; mkShell rec { - packages = [gdb clang-tools]; + packages = [gdb clang-tools uchess cutechess]; nativeBuildInputs = [ pkg-config gcc diff --git a/uchess.json b/uchess.json new file mode 100644 index 0000000..f02384e --- /dev/null +++ b/uchess.json @@ -0,0 +1,64 @@ +{ + "uciWhite": "rat", + "uciBlack": "rat", + "uciHint": "stockfish", + "uciEngines": [ + { + "name":"rat", + "engine":"./a.out", + "ponder":false + }, + { + "name": "stockfish", + "engine": "/nix/store/5d7aqjdak73qlsimiismbj0m1h9b566j-stockfish-17/bin/stockfish", + "hash": 128, + "ponder": false, + "ownBook": false, + "multiPV": 1, + "depth": 1, + "searchMoves": "", + "moveTime": 100, + "options": [ + { + "name": "skill level", + "value": "3" + } + ] + } + ], + "fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", + "activeTheme": "basic", + "theme": [ + { + "name": "basic", + "moveLabelBg": "#d0d0d0", + "moveLabelFg": "#000000", + "squareDark": "#d7d7d7", + "squareLight": "#ffffd7", + "squareHigh": "#ffff00", + "squareHint": "#ffd7af", + "squareCheck": "#ffafd7", + "white": "#080808", + "black": "#080808", + "msg": "#d70000", + "rank": "#9e9e9e", + "file": "#9e9e9e", + "prompt": "#d70000", + "meterBase": "#585858", + "meterMid": "#0", + "meterNeutral": "#00d7ff", + "meterWin": "#87ffd7", + "meterLose": "#d75f5f", + "playerNames": "#0", + "score": "#9e9e9e", + "moveBox": "#0", + "emoji": "#0", + "input": "#0", + "advantage": "#9e9e9e" + } + ], + "whitePiece": "cpu", + "blackPiece": "cpu", + "whiteName": "", + "blackName": "" +}