#include "fen.hpp" #include "board.hpp" #include #include #include #include #include #include #include #include #include bool WHITE = true; bool BLACK = false; static void SetPiece(int i, PieceType type, bool color, Game *g) { if (i < 0 || i >= 64) { std::println("Fatal: piece outside board"); assert(false && "Malformed board"); exit(1); } g->pieces[i] = {.color = color, .type = type}; } static void clearBoard(Game *g) { for (auto &piece : g->pieces) { piece = {.color = false, .type = NONEPIECE}; } g->blackCastleKing = false; g->blackCastleQueen = false; g->whiteCastleKing = false; g->whiteCastleQueen = false; } enum parserState : std::uint8_t { BOARD, PLAYER_TO_MOVE, CASTLE, ENPASSANT, HALF_MOVE_CLOCK, FULL_MOVE_CLOCK, }; void setBoardFen(const std::string &fen, Game *g) { clearBoard(g); // example fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 int file = 0; int rank = 7; Position enpassant = {}; parserState parser_state = BOARD; for (uint i = 0; i < fen.length(); i++) { char c = fen[i]; if (c == ' ') { if (parser_state == BOARD) { parser_state = PLAYER_TO_MOVE; continue; } if (parser_state == PLAYER_TO_MOVE) { parser_state = CASTLE; continue; } if (parser_state == CASTLE) { parser_state = ENPASSANT; continue; } if (parser_state == ENPASSANT) { parser_state = HALF_MOVE_CLOCK; continue; } if (parser_state == HALF_MOVE_CLOCK) { parser_state = FULL_MOVE_CLOCK; continue; } } if (parser_state == ENPASSANT) { continue; } if (parser_state == CASTLE) { if (c == '-') { g->blackCastleKing = false; g->blackCastleQueen = false; g->whiteCastleKing = false; g->whiteCastleQueen = false; continue; } if (c == 'K') { g->whiteCastleKing = true; continue; } if (c == 'Q') { g->whiteCastleQueen = true; continue; } if (c == 'k') { g->blackCastleKing = true; continue; } if (c == 'q') { g->blackCastleQueen = true; continue; } } if (parser_state == PLAYER_TO_MOVE) { if (toupper(c) == 'W') { g->turn = WHITE; continue; } if (toupper(c) == 'B') { g->turn = BLACK; continue; } } if (parser_state == BOARD) { if (isdigit(c) != 0) { int move = c - '0'; file += move; if (file > 8) { std::println("Fatal: file was to big"); assert(false && "Malformed file"); exit(1); return; // malformed file } continue; } if (c == '/') { file = 0; rank--; if (rank < 0) { std::println("Fatal: rank was to big"); assert(false && "Malformed rank"); exit(1); return; // malformed rank } continue; }; if (toupper(c) == 'N') { bool color = isupper(c) != 0; g->PieceBitboards[color][KNIGHT] |= (1ULL << ((rank * 8) + file)); SetPiece((rank * 8) + file, KNIGHT, color, g); file++; continue; }; if (toupper(c) == 'R') { bool color = isupper(c) != 0; g->PieceBitboards[color][ROOK] |= (1ULL << ((rank * 8) + file)); SetPiece((rank * 8) + file, ROOK, color, g); file++; continue; } if (toupper(c) == 'Q') { bool color = isupper(c) != 0; g->PieceBitboards[color][QUEEN] |= (1ULL << ((rank * 8) + file)); SetPiece((rank * 8) + file, QUEEN, color, g); file++; continue; } if (toupper(c) == 'B') { bool color = isupper(c) != 0; g->PieceBitboards[color][BISHOP] |= (1ULL << ((rank * 8) + file)); SetPiece((rank * 8) + file, BISHOP, color, g); file++; continue; } if (toupper(c) == 'P') { bool color = isupper(c) != 0; g->PieceBitboards[color][PAWN] |= (1ULL << ((rank * 8) + file)); SetPiece((rank * 8) + file, PAWN, color, g); file++; continue; } if (toupper(c) == 'K') { bool color = isupper(c) != 0; g->PieceBitboards[color][KING] |= (1ULL << ((rank * 8) + file)); SetPiece((rank * 8) + file, KING, color, g); file++; continue; } } break; } g->enPassant = enpassant; g->WhitePieceBitboard = g->PieceBitboards[1][PAWN] | g->PieceBitboards[1][KNIGHT] | g->PieceBitboards[1][BISHOP] | g->PieceBitboards[1][ROOK] | g->PieceBitboards[1][QUEEN] | g->PieceBitboards[1][KING]; g->BlackPieceBitboard = g->PieceBitboards[0][PAWN] | g->PieceBitboards[0][KNIGHT] | g->PieceBitboards[0][BISHOP] | g->PieceBitboards[0][ROOK] | g->PieceBitboards[0][QUEEN] | g->PieceBitboards[0][KING]; g->PieceBitboard = g->WhitePieceBitboard | g->BlackPieceBitboard; int whiteKingCount = __builtin_popcountll(g->PieceBitboards[true][KING]); int blackKingCount = __builtin_popcountll(g->PieceBitboards[false][KING]); if (whiteKingCount != 1) { std::cerr << "ERROR: expected exactly one white king\n"; exit(1); } if (blackKingCount != 1) { std::cerr << "ERROR: expected exactly one black king\n"; exit(1); } }