Para los demás, hay una función simple en el motor Stockfish, que valida una cadena FEN.
bool Position::is_valid_fen(const std::string &fen) {
std::istringstream iss(fen);
std::string board, side, castleRights, ep;
if (!iss) return false;
iss >> board;
if (!iss) return false;
iss >> side;
if (!iss) {
castleRights = "-";
ep = "-";
} else {
iss >> castleRights;
if (iss)
iss >> ep;
else
ep = "-";
}
// Let's check that all components of the supposed FEN are OK.
if (side != "w" && side != "b") return false;
if (castleRights != "-" && castleRights != "K" && castleRights != "Kk"
&& castleRights != "Kkq" && castleRights != "Kq" && castleRights !="KQ"
&& castleRights != "KQk" && castleRights != "KQq" && castleRights != "KQkq"
&& castleRights != "k" && castleRights != "q" && castleRights != "kq"
&& castleRights != "Q" && castleRights != "Qk" && castleRights != "Qq"
&& castleRights != "Qkq")
return false;
if (ep != "-") {
if (ep.length() != 2) return false;
if (!(ep[0] >= 'a' && ep[0] <= 'h')) return false;
if (!((side == "w" && ep[1] == '6') || (side == "b" && ep[1] == '3')))
return false;
}
// The tricky part: The board.
// Seven slashes?
if (std::count(board.begin(), board.end(), '/') != 7) return false;
// Only legal characters?
for (int i = 0; i < board.length(); i++)
if (!(board[i] == '/' || (board[i] >= '1' && board[i] <= '8')
|| piece_type_is_ok(piece_type_from_char(board[i]))))
return false;
// Exactly one king per side?
if (std::count(board.begin(), board.end(), 'K') != 1) return false;
if (std::count(board.begin(), board.end(), 'k') != 1) return false;
// Other piece counts reasonable?
size_t wp = std::count(board.begin(), board.end(), 'P'),
bp = std::count(board.begin(), board.end(), 'p'),
wn = std::count(board.begin(), board.end(), 'N'),
bn = std::count(board.begin(), board.end(), 'n'),
wb = std::count(board.begin(), board.end(), 'B'),
bb = std::count(board.begin(), board.end(), 'b'),
wr = std::count(board.begin(), board.end(), 'R'),
br = std::count(board.begin(), board.end(), 'r'),
wq = std::count(board.begin(), board.end(), 'Q'),
bq = std::count(board.begin(), board.end(), 'q');
if (wp > 8 || bp > 8 || wn > 10 || bn > 10 || wb > 10 || bb > 10
|| wr > 10 || br > 10 || wq > 9 || bq > 10
|| wp + wn + wb + wr + wq > 15 || bp + bn + bb + br + bq > 15)
return false;
// OK, looks close enough to a legal position. Let's try to parse
// the FEN and see!
Position p;
p.from_fen(board + " " + side + " " + castleRights + " " + ep);
return p.is_ok(true);
}