Task
 
Generate a random chess position in FEN format.

The position does not have to be realistic or even balanced,  but it must comply to the following rules:

 there is one and only one king of each color  (one black king and one white king);
 the kings must not be placed on adjacent squares;
 there can not be any pawn in the promotion square  (no white pawn in the eighth rank, and no black pawn in the first rank);
 including the kings, up to 32 pieces of either color can be placed. 
 There is no requirement for material balance between sides. 
 The picking of pieces does not have to comply to a regular chess set --- there can be five knights, twenty rooks, whatever ... as long as the total number of pieces do not exceed thirty-two. 
 it is white's turn.
 It's assumed that both sides have lost castling rights and that there is no possibility for   en passant   (the FEN should thus end in w - - 0 1).


No requirement is made regarding the probability distribution of your method, but your program should be able to span a reasonably representative sample of all possible positions. For instance, programs that would always generate positions with say five pieces on the board, or with kings on a corner, would not be considered truly random.




 
place_kings <- function(brd){
  ###
  #  Function that puts the two kings on the board
  #  and makes sure that they are not adjacent
  ###
  while (TRUE) {
    # generate positions for white and black kings
    rank_white <- sample(1:8, 1) ; file_white <- sample(1:8, 1)
    rank_black <- sample(1:8, 1) ; file_black <- sample(1:8, 1)
    # compute the differences between ranks and files
    diff_vec <- c(abs(rank_white - rank_black), abs(file_white - file_black))
    # if the two kings are not adjacent, place them on the board
    if (sum(diff_vec) > 2 | setequal(diff_vec, c(0,2))) {
      brd[rank_white, file_white] <- "K"
      brd[rank_black, file_black] <- "k"
      break
    }
  }
  return(brd)
}
 
pawn_on_extreme_ranks <- function(pc, pr){
  ###
  #  Function that checks whether a pawn is on the first or eight rank
  #  (such a situation is not possible in chess)
  ### 
  if (pc %in% c("P","p") & pr %in% c(1,8))
    return(TRUE)
  else
    return(FALSE)
}
 
populate_board <- function(brd, wp, bp){
  ###
  #  Function that puts pieces on the board making sure that they
  #  are not on the same squares, and verifying for pawn_on_extreme_ranks
  ###
  # initialization
  piece_list <- c("P", "N", "B", "R", "Q")
  for (color in c("white", "black")){
    # iterate for white (first) and black (after) pieces
    if (color == "white"){
      n_pieces = wp
      pieces = piece_list
    }
    else {
      n_pieces = bp
      pieces = tolower(piece_list)
    }
    # place pieces one by one until we have them
    while (n_pieces != 0){
      piece_rank <- sample(1:8, 1) ; piece_file <- sample(1:8, 1)
      piece <- sample(pieces, 1)
      # check if square is empty and it is not a pawn on an extreme rank
      if (brd[piece_rank, piece_file] == " " & !pawn_on_extreme_ranks(piece, piece_rank)){
        brd[piece_rank, piece_file] <- piece
        n_pieces <- n_pieces - 1
      }
    }
  }
  return(brd)
}
 
fen_from_board <- function(brd){
  ###
  #  Function that prints out the FEN of a given input board
  ###
  # create vector of positions by row
  fen <- apply(brd, 1, function(x) {
    r <- rle(x) 
    paste(ifelse(r$values == " ", r$lengths, r$values), collapse = "")
    })
  # paste them together with separator '/' and add the final string
  fen <- paste(paste(fen, collapse = "/"), "w - - 0 1")
  return(fen)
}
 
generate_fen <- function(){
  ###
  #  This function calls all the functions above and generates
  #  the board representation along with its FEN
  ###
  # initialization
  board <- matrix(" ", nrow = 8, ncol = 8)
  # generate random amount of white and black pieces (kings excluded)
  n_pieces_white <- sample(0:31, 1) ; n_pieces_black <- sample(0:31, 1)
  # place kings on board
  board <- place_kings(board)
  # put other pieces on board
  board <- populate_board(board, wp = n_pieces_white, bp = n_pieces_black)
  # print board and FEN
  print(board)
  cat("\n")
  cat(fen_from_board(board))
}
 
generate_fen()
 