#include #include #include #include #include #include "bitboard.h" int square_index(int file, int rank) { return rank*8 + file; } int char_to_piece_index(char c) { switch (c) { case 'P': return P; case 'N': return N; case 'B': return B; case 'R': return R; case 'Q': return Q; case 'K': return K; case 'p': return p; case 'n': return n; case 'b': return b; case 'r': return r; case 'q': return q; case 'k': return k; default: return -1; } } int load_fen(struct Board *board, const char *fen) { // Reset the board first. Weird behavior when not zeroed. memset(board, 0, sizeof *board); board->ep_square = -1; int rank = 7, file = 0; const char *ptr = fen; // Place pieces into the board. while (*ptr && *ptr != ' ') { if (isdigit(*ptr)) { file += *ptr - '0'; ptr++; } else if (isalpha(*ptr)) { if (file >= 8) return -1; int piece = char_to_piece_index(*ptr); if (piece == -1) return -1; SET_BIT(board->pieces[piece], rank * 8 + file); file++; ptr++; } else if (*ptr == '/') { // Each rank must have exactly 8 files if (file != 8) return -1; rank--; file = 0; ptr++; } else { // Unexpected character return -1; } } if (rank != 0 || file != 8) return -1; ptr++; // Side to move. if (*ptr != 'w' && *ptr != 'b') return -1; board->side_to_move = (*ptr == 'w') ? WHITE : BLACK; ptr += 2; // Castling rights. board->castling_rights = 0; while (*ptr && *ptr != ' ') { switch (*ptr) { case 'K': board->castling_rights |= CASTLE_WK; break; case 'Q': board->castling_rights |= CASTLE_WQ; break; case 'k': board->castling_rights |= CASTLE_BK; break; case 'q': board->castling_rights |= CASTLE_BQ; break; case '-': break; default: return -1; } ptr++; } if (*ptr != ' ') return -1; ptr++; // En Passant square. if (*ptr == '-') { board->ep_square = -1; ptr += 2; } else { if (ptr[0] < 'a' || ptr[0] > 'h' || ptr[1] < '1' || ptr[1] > '8') return -1; // Strict FEN: Rank must be 3 or 6. char rank_char = ptr[1]; if (rank_char != '3' && rank_char != '6') return -1; int file = ptr[0] - 'a'; int rank = ptr[1] - '1'; board->ep_square = square_index(file, rank); ptr += 3; } // Parse halfmove clock for the game. board->halfmove_clock = atoi(ptr); while (*ptr && *ptr != ' ') ptr++; if (*ptr == ' ') ptr++; // Parse the fullmove number. board->fullmove_number = atoi(ptr); int num_pieces = 6; for (int i = 0; i < num_pieces; i++) { board->occ[WHITE] |= board->pieces[i]; // white board->occ[BLACK] |= board->pieces[i + 6]; // black } board->occ[BOTH] = board->occ[WHITE] | board->occ[BLACK]; return 0; }