#include #include #include "SchachHoernchen/types.h" #include "SchachHoernchen/utils.h" #include "SchachHoernchen/Board.h" //' Convert a legal FEN string to a 3D binary (integer with 0-1 entries) array // [[Rcpp::export(rng = false)]] Rcpp::IntegerVector fen2int(const std::vector& boards) { // Initialize empty chess board as a 3D binary tensor Rcpp::IntegerVector bitboards(8 * 8 * 12 * (int)boards.size()); // Set dimension and dimension names (required this way since `Rcpp::Dimension` // does _not_ support 4D arrays) auto dims = Rcpp::IntegerVector({ 8, 8, 12, (int)boards.size() }); bitboards.attr("dim") = dims; bitboards.attr("dimnames") = Rcpp::List::create( Rcpp::Named("rank") = Rcpp::CharacterVector::create( "8", "7", "6", "5", "4", "3", "2", "1" ), Rcpp::Named("file") = Rcpp::CharacterVector::create( "a", "b", "c", "d", "e", "f", "g", "h" ), Rcpp::Named("piece") = Rcpp::CharacterVector::create( "P", "N", "B", "R", "Q", "K", // White Pieces (Upper Case) "p", "n", "b", "r", "q", "k" // Black Pieces (Lower Case) ), R_NilValue ); // Index to color/piece mapping (more robust) enum piece colorLoopup[2] = { white, black }; enum piece pieceLookup[6] = { pawn, knight, bishop, rook, queen, king }; // Set for every piece the corresponding pit positions, note the // "transposition" of the indexing from SchachHoernchen's binary indexing // scheme to the 3D array indexing of ranks/files. for (int i = 0; i < boards.size(); ++i) { const Board& pos = boards[i]; for (int color = 0; color < 2; ++color) { for (int piece = 0; piece < 6; ++piece) { int slice = 6 * color + piece; u64 bb = pos.bb(colorLoopup[color]) & pos.bb(pieceLookup[piece]); for (; bb; bb &= bb - 1) { // Get BitBoard index int index = bitScanLS(bb); // Transpose to align with printing as a Chess Board index = ((index & 7) << 3) | ((index & 56) >> 3); // Flip black to move positions to whites point of view index ^= pos.isWhiteTurn() ? 0 : 7; bitboards[768 * i + 64 * slice + index] = 1; } } } } return bitboards; }