#include #include #include #include #include #include #include #define BUFF_SIZE 4096 typedef struct { long long pawns; long long knights; long long bishops; long long rooks; long long queen; long long king; } sets; typedef struct { sets white; sets black; bool whiteToMove; } game; typedef struct { int From; int To; } move; 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); int pawnMove(game *g, move *moves); long long fullSet(sets *s) { return s->bishops ^ s->king ^ s->knights ^ s->pawns ^ s->queen ^ s->rooks; } long long fullSetBoth(game *g) { return fullSet(&g->white) ^ fullSet(&g->black); } void print_bitboard(long long bitboard) { for (int i = 63; i >= 0; i--) { // Check if the i-th bit is set if ((bitboard >> i) & 1) { printf("1 "); } else { printf("0 "); } // Print a newline every 8 bits (for rows) if (i % 8 == 0) { printf("\n"); } } printf("\n"); } int main() { setbuf(stdin, NULL); setbuf(stdout, NULL); game *g = NULL; char line[BUFF_SIZE]; char *lineRest, *token; char ltz[] = "abcdefgh"; int cnt = 0; while (1) { (void)fgets(line, sizeof(line), stdin); size_t len = strlen(line); if (len - 1) line[len - 1] = '\0'; token = strtok_r(line, " ", &lineRest); if (!strcmp("uci", token)) { printf("id name RatChess 0.0\n"); printf("id author rat<3\n"); printf("uciok\n"); } else if (!strcmp("quit", token)) { return 0; } else if (!strcmp("setoption", token)) { } else if (!strcmp("position", token)) { token = strtok_r(lineRest, " ", &lineRest); if (!strcmp("fen", token)) { g = fenGame(lineRest + 1); for (int i = 0; i < 6; i++) token = strtok_r(lineRest, " ", &lineRest); } else { g = fenGame("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); } playMoves(g, lineRest); printf("info pawns\n"); // print_bitboard(fullSetBoth(g)); } else if (!strcmp("ucinewgame", token)) { } else if (!strcmp("isready", token)) { printf("readyok\n"); } else if (!strcmp("go", token)) { move mov[64]; int cnt = pawnMove(g, mov); move *m = &mov[0]; char *end = ""; int yTo, xTo, yFrom, xFrom; xTo = m->To % 8; yTo = m->To / 8 + 1; xFrom = m->From % 8; yFrom = m->From / 8 + 1; if ((g->whiteToMove && yTo == 8) || (!g->whiteToMove && yTo == 1)) { end = "q\n"; } else { end = "\n"; } printf("bestmove %c%d%c%d%s", ltz[xFrom], yFrom, ltz[xTo], yTo, end); } } } 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; size_t pos = 0; game *g; g = malloc(sizeof(game)); memset(g, 0, sizeof(game)); while (str[pos] != '\0' && str[pos] != ' ') { char current_char = *str; if (isdigit(*str)) { int empty_squares = *str - '0'; file += empty_squares; str++; continue; } if (current_char == '/') { rank--; file = 0; str++; continue; } long long bit = 1LL << (rank * 8 + file); long long *set = charToSet(g, *str); if (set) *set |= bit; file++; str++; } 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) { char c = move[4]; if (g->whiteToMove) c = toupper(c); set = charToSet(g, c); } *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; } } int pawnMove(game *g, move *moves) { long long pawns = g->whiteToMove ? g->white.pawns : g->black.pawns; long long enemy = g->whiteToMove ? fullSet(&g->black) : fullSet(&g->white); long long occupied = fullSetBoth(g); int movdir = g->whiteToMove ? 8 : -8; int capLeft = g->whiteToMove ? 7 : -9; int capRight = g->whiteToMove ? 9 : -7; size_t index = 0; for (int i = 0; i < 64; ++i) { long long bit = 1LL << i; if (!(pawns & bit)) continue; // forword int to = i + movdir; if (to >= 0 && to < 64 && !(occupied & (1LL << to))) { moves[index++] = (move){.From = i, .To = to}; } // left to = i + capLeft; if (i % 8 > 0 && (to >= 0 && to < 64) && (enemy & (1LL << to))) { moves[index++] = (move){.From = i, .To = to}; } // right to = i + capRight; if (i % 8 < 7 && (to >= 0 && to < 64) && (enemy & (1LL << to))) { moves[index++] = (move){.From = i, .To = to}; } } return index; }