Generate random chess position: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 568: Line 568:
type ChessBoard = [(Square, Pos)]
type ChessBoard = [(Square, Pos)]


data PieceRank = King | Queen | Rook | Bishop | Knight | Pawn
data PieceRank = King | Queen | Rook | Bishop | Knight | Pawn
deriving (Enum, Bounded, Show, Eq, Ord)
deriving (Enum, Bounded, Show, Eq, Ord)
data PieceColor = Black | White
data PieceColor = Black | White
deriving (Enum, Bounded, Show, Eq, Ord)
deriving (Enum, Bounded, Show, Eq, Ord)


data Square = ChessPiece PieceRank PieceColor | EmptySquare
data Square = ChessPiece PieceRank PieceColor | EmptySquare
deriving (Eq, Ord)
deriving (Eq, Ord)


Line 579: Line 579:


instance Show Square where
instance Show Square where
show (ChessPiece King Black) = "♚"
show (ChessPiece King Black) = "♚"
show (ChessPiece Queen Black) = "♛"
show (ChessPiece Queen Black) = "♛"
show (ChessPiece Rook Black) = "♜"
show (ChessPiece Rook Black) = "♜"
show (ChessPiece Bishop Black) = "♝"
show (ChessPiece Bishop Black) = "♝"
show (ChessPiece Knight Black) = "♞"
show (ChessPiece Knight Black) = "♞"
show (ChessPiece Pawn Black) = "♟"
show (ChessPiece Pawn Black) = "♟"
show (ChessPiece King White) = "♔"
show (ChessPiece King White) = "♔"
show (ChessPiece Queen White) = "♕"
show (ChessPiece Queen White) = "♕"
show (ChessPiece Rook White) = "♖"
show (ChessPiece Rook White) = "♖"
show (ChessPiece Bishop White) = "♗"
show (ChessPiece Bishop White) = "♗"
show (ChessPiece Knight White) = "♘"
show (ChessPiece Knight White) = "♘"
show (ChessPiece Pawn White) = "♙"
show (ChessPiece Pawn White) = "♙"
show EmptySquare = " "
show EmptySquare = " "


instance Random PieceRank where
instance Random PieceRank where
randomR (a, b) g =
randomR (a, b) g = case randomR (fromEnum a, fromEnum b) g of
case randomR (fromEnum a, fromEnum b) g of
(x, g'') -> (toEnum x, g'')
(x, g'') -> (toEnum x, g'')
random g = randomR (minBound, maxBound) g
random g = randomR (minBound, maxBound) g


instance Random PieceColor where
instance Random PieceColor where
randomR (a, b) g =
randomR (a, b) g = case randomR (fromEnum a, fromEnum b) g of
case randomR (fromEnum a, fromEnum b) g of
(x, g'') -> (toEnum x, g'')
(x, g'') -> (toEnum x, g'')
random g = randomR (minBound, maxBound) g
random g = randomR (minBound, maxBound) g

fullBoard :: PieceCount
fullBoard :: PieceCount
fullBoard =
fullBoard =
[ (ChessPiece King Black, 1)
[ (ChessPiece King Black , 1)
, (ChessPiece Queen Black, 1)
, (ChessPiece Queen Black , 1)
, (ChessPiece Rook Black, 2)
, (ChessPiece Rook Black , 2)
, (ChessPiece Bishop Black, 2)
, (ChessPiece Bishop Black, 2)
, (ChessPiece Knight Black, 2)
, (ChessPiece Knight Black, 2)
, (ChessPiece Pawn Black, 8)
, (ChessPiece Pawn Black , 8)
, (ChessPiece King White, 1)
, (ChessPiece King White , 1)
, (ChessPiece Queen White, 1)
, (ChessPiece Queen White , 1)
, (ChessPiece Rook White, 2)
, (ChessPiece Rook White , 2)
, (ChessPiece Bishop White, 2)
, (ChessPiece Bishop White, 2)
, (ChessPiece Knight White, 2)
, (ChessPiece Knight White, 2)
, (ChessPiece Pawn White, 8)
, (ChessPiece Pawn White , 8)
, (EmptySquare, 32)
, (EmptySquare , 32)
]
]


emptyBoard :: ChessBoard
emptyBoard :: ChessBoard
emptyBoard = [(EmptySquare, (x,y)) | x <-['a'..'h'], y <- [1..8]]
emptyBoard = [ (EmptySquare, (x, y)) | x <- ['a' .. 'h'], y <- [1 .. 8] ]


replaceSquareByPos :: (Square, Pos) -> ChessBoard -> ChessBoard
replaceSquareByPos :: (Square, Pos) -> ChessBoard -> ChessBoard
replaceSquareByPos (s, p) = map (\t@(s'', p'') -> if p == p'' then (s, p) else t)
replaceSquareByPos e@(s, p) = map (\x -> if p == snd x then e else x)


isPosOccupied :: Pos -> ChessBoard -> Bool
isPosOccupied :: Pos -> ChessBoard -> Bool
isPosOccupied p = occupied . found
isPosOccupied p = occupied . find (\x -> p == snd x)
where
where found = find (\(_, p'') -> p == p'')
occupied (Just (EmptySquare, _)) = False
occupied (Just (EmptySquare, _)) = False
occupied _ = True
occupied _ = True


isAdjacent :: Pos -> Pos -> Bool
isAdjacent :: Pos -> Pos -> Bool
Line 638: Line 636:
let upOrDown = (pred y == y'' || succ y == y'')
let upOrDown = (pred y == y'' || succ y == y'')
leftOrRight = (pred x == x'' || succ x == x'')
leftOrRight = (pred x == x'' || succ x == x'')
in (x'' == x && upOrDown) ||
in (x'' == x && upOrDown)
(pred x == x'' && upOrDown) ||
|| (pred x == x'' && upOrDown)
(succ x == x'' && upOrDown) ||
|| (succ x == x'' && upOrDown)
(leftOrRight && y == y'')
|| (leftOrRight && y == y'')


fen :: Square -> String
fen :: Square -> String
fen (ChessPiece King Black) = "k"
fen (ChessPiece King Black) = "k"
fen (ChessPiece Queen Black) = "q"
fen (ChessPiece Queen Black) = "q"
fen (ChessPiece Rook Black) = "r"
fen (ChessPiece Rook Black) = "r"
fen (ChessPiece Bishop Black) = "b"
fen (ChessPiece Bishop Black) = "b"
fen (ChessPiece Knight Black) = "n"
fen (ChessPiece Knight Black) = "n"
fen (ChessPiece Pawn Black) = "p"
fen (ChessPiece Pawn Black) = "p"
fen (ChessPiece King White) = "K"
fen (ChessPiece King White) = "K"
fen (ChessPiece Queen White) = "Q"
fen (ChessPiece Queen White) = "Q"
fen (ChessPiece Rook White) = "R"
fen (ChessPiece Rook White) = "R"
fen (ChessPiece Bishop White) = "B"
fen (ChessPiece Bishop White) = "B"
fen (ChessPiece Knight White) = "N"
fen (ChessPiece Knight White) = "N"
fen (ChessPiece Pawn White) = "P"
fen (ChessPiece Pawn White) = "P"


boardSort :: (Square, Pos) -> (Square, Pos) -> Ordering
boardSort :: (Square, Pos) -> (Square, Pos) -> Ordering
boardSort (_, (x, y)) (_, (x'', y''))
boardSort (_, (x, y)) (_, (x'', y'')) | y < y'' = GT
| y < y'' = GT
| y > y'' = LT
| y > y'' = LT
| y == y'' = compare x x''
| y == y'' = compare x x''


toFen :: ChessBoard -> String
toFen :: ChessBoard -> String
toFen [] = " w - - 0 1" <> []
toFen [] = " w - - 0 1" <> []
toFen b = scanRow (map fst $ take 8 b) 0
toFen b = scanRow (map fst $ take 8 b) 0
where
where scanRow [] 0 = nextRow
scanRow [] n = show n <> nextRow
scanRow [] 0 = nextRow
scanRow ((EmptySquare): xs) n = scanRow xs (succ n)
scanRow [] n = show n <> nextRow
scanRow (x:xs) 0 = nextPiece x xs
scanRow ((EmptySquare) : xs) n = scanRow xs (succ n)
scanRow (x:xs) n = show n <> nextPiece x xs
scanRow (x : xs) 0 = nextPiece x xs
scanRow (x : xs) n = show n <> nextPiece x xs


nextRow = "/" <> toFen (drop 8 b)
nextRow = "/" <> toFen (drop 8 b)
nextPiece x xs = fen x <> scanRow xs 0
nextPiece x xs = fen x <> scanRow xs 0


-- impure functions
-- impure functions


randomPos :: ChessBoard -> IO Pos
randomPos :: ChessBoard -> IO Pos
randomPos b = pos >>= \p -> if isPosOccupied p b
randomPos b = pos >>= \p -> if isPosOccupied p b then randomPos b else pos
where
then randomPos b
pos = (,) <$> chr <*> num
else pos
num = getStdRandom $ randomR (1, 8)
where pos = (,) <$> chr <*> num
num = getStdRandom $ randomR (1,8)
chr = getStdRandom $ randomR ('a', 'h')
chr = getStdRandom $ randomR ('a','h')


randomPiece :: IO Square
randomPiece :: IO Square
randomPiece = ChessPiece <$> rank <*> color
randomPiece = ChessPiece <$> rank <*> color
where
where rank = getStdRandom random
color = getStdRandom random
rank = getStdRandom random
color = getStdRandom random


placeKings :: ChessBoard -> IO ChessBoard
placeKings :: ChessBoard -> IO ChessBoard
placeKings b = do
placeKings b = do
p1 <- randomPos b
p1 <- randomPos b
p2 <- randomPos b
p2 <- randomPos b
if p1 `isAdjacent` p2 || p1 == p2
if p1 `isAdjacent` p2 || p1 == p2
then placeKings b
then placeKings b
else
else pure
pure (replaceSquareByPos ((ChessPiece King White), p1) $
( replaceSquareByPos ((ChessPiece King White), p1)
replaceSquareByPos ((ChessPiece King Black), p2) b)
$ replaceSquareByPos ((ChessPiece King Black), p2) b
)


placePawns :: ChessBoard -> IO ChessBoard
placePawns :: ChessBoard -> IO ChessBoard
placePawns b = num >>= go b
placePawns b = num >>= go b
where
where go :: ChessBoard -> Int -> IO ChessBoard
go :: ChessBoard -> Int -> IO ChessBoard
go b'' 0 = pure b''
go b'' n = do
go b'' 0 = pure b''
go b'' n = do
pos <- randomPos b''
pawn@(ChessPiece _ color) <- randomPawn
pos <- randomPos b''
pawn@(ChessPiece _ color) <- randomPawn
if promoted color == snd pos || isPosOccupied pos b''
|| enpassant color == snd pos || firstPos color == snd pos
if promoted color == snd pos
then go b'' n
|| isPosOccupied pos b''
else
|| enpassant color == snd pos
go (replaceSquareByPos (pawn, pos) b'') (pred n)
|| firstPos color == snd pos
promoted White = 8
then go b'' n
else go (replaceSquareByPos (pawn, pos) b'') (pred n)
promoted Black = 1
enpassant White = 5
promoted White = 8
enpassant Black = 4
promoted Black = 1
firstPos White = 1
enpassant White = 5
firstPos Black = 8
enpassant Black = 4
firstPos White = 1
firstPos Black = 8


num = getStdRandom (randomR (1,16))
num = getStdRandom (randomR (1, 16))


randomPawn = ChessPiece Pawn <$> rColor
randomPawn = ChessPiece Pawn <$> rColor where rColor = getStdRandom (random)
where rColor = getStdRandom (random)


placeRemaining :: ChessBoard -> IO ChessBoard
placeRemaining :: ChessBoard -> IO ChessBoard
placeRemaining b = do
placeRemaining b = do
n <- num (sum $ map snd remaining)
n <- num (sum $ map snd remaining)
putStrLn $ "Placing " <> show n <>
putStrLn $ "Placing " <> show n
" more random positions after placing 2 kings and "
<> " more random positions after placing 2 kings and "
<> (show $ totalPawns b) <> " pawns. "
<> (show $ totalPawns b) <> " pawns. "
go remaining b n
go remaining b n
where
where remaining :: [(Square, Int)]
remaining :: [(Square, Int)]
remaining =
filter (\case
remaining = filter
(\case
((ChessPiece King _), _) -> False
((ChessPiece Pawn _), _) -> False
((ChessPiece King _), _) -> False
(EmptySquare, _) -> False
((ChessPiece Pawn _), _) -> False
_ -> True) fullBoard
(EmptySquare , _) -> False
_ -> True
)
fullBoard


num mx = getStdRandom $ randomR (5, mx)
num mx = getStdRandom $ randomR (5, mx)


totalPawns = length . filter (\case ((ChessPiece Pawn _), _) -> True
totalPawns = length . filter
(\case ((ChessPiece Pawn _), _) -> True
_ -> False)
_ -> False
)


go :: [(Square, Int)] -> ChessBoard -> Int -> IO ChessBoard
go :: [(Square, Int)] -> ChessBoard -> Int -> IO ChessBoard
go _ b'' 0 = pure b''
go _ b'' 0 = pure b''
go permitted b'' n = do
go permitted b'' n = do
position <- randomPos b''
position <- randomPos b''
piece <- randomPiece
piece <- randomPiece
if (not $ isPermitted piece) || isPosOccupied position b''
if (not $ isPermitted piece) || isPosOccupied position b''
then go permitted b'' n
then go permitted b'' n
else
else go (consume piece permitted)
go (consume piece permitted) (replaceSquareByPos (piece, position) b'') (pred n)
(replaceSquareByPos (piece, position) b'')
(pred n)


where
where isPermitted p = case find (\x -> fst x == p) permitted of
isPermitted p = case find (\x -> fst x == p) permitted of
Just (_, count) -> count > 0
Just (_, count) -> count > 0
Nothing -> False
Nothing -> False
consume p'' = map (\(p, c) -> if p == p'' then (p, pred c) else (p, c))
consume p'' = map (\(p, c) -> if p == p'' then (p, pred c) else (p, c))


draw :: ChessBoard -> IO ()
draw :: ChessBoard -> IO ()
Line 763: Line 770:
showXAxis
showXAxis
line
line
mapM_ (\b@(p, (x,y)) ->
mapM_
(\b@(p, (x, y)) -> case x of
case x of 'h' -> putStr (" | " <> show p <> " | " <> show y <> "\n") >> line
'a' -> putStr (show y <> " | " <> show p)
'h' -> putStr (" | " <> show p <> " | " <> show y <> "\n") >> line
_ -> putStr (" | " <> show p)
'a' -> putStr (show y <> " | " <> show p)
)
_ -> putStr (" | " <> show p)
)
sorted
sorted
showXAxis
showXAxis
Line 774: Line 782:
-- mapM_ print $ sortBy (comparing fst) $ filter (\(s, _) -> s /= EmptySquare) b
-- mapM_ print $ sortBy (comparing fst) $ filter (\(s, _) -> s /= EmptySquare) b


where
where sorted = sortBy boardSort b
sorted = sortBy boardSort b
line = putStrLn (" " <> (replicate 33 '-'))
line = putStrLn (" " <> (replicate 33 '-'))
showXAxis = do
showXAxis = do
putStr " "
putStr " "
mapM_ (\(_, (x, _)) -> putStr $ " " <> [x]) (take 8 sorted)
mapM_ (\(_, (x, _)) -> putStr $ " " <> [x]) (take 8 sorted)
putStrLn ""
putStrLn ""


main :: IO ()
main :: IO ()
main = placeKings emptyBoard >>= placePawns >>= placeRemaining >>= draw</lang>
main =
placeKings emptyBoard >>=
placePawns >>=
placeRemaining >>=
draw</lang>
{{out}}
{{out}}
Run 1
Run 1

Revision as of 13:15, 16 April 2020

Task
Generate random chess position
You are encouraged to solve this task according to the task description, using any language you may know.

The purpose of this task is to 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 is 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.

C

Translation of: Java

<lang c>#include <stdio.h>

  1. include <math.h>
  2. include <string.h>
  3. include <stdlib.h>
  4. include <time.h>
  1. define TRUE 1
  2. define FALSE 0

typedef int bool;

char grid[8][8];

void placeKings() {

   int r1, r2, c1, c2;
   for (;;) {
       r1 = rand() % 8;
       c1 = rand() % 8;
       r2 = rand() % 8;
       c2 = rand() % 8;
       if (r1 != r2 && abs(r1 - r2) > 1 && abs(c1 - c2) > 1) {
           grid[r1][c1] = 'K';
           grid[r2][c2] = 'k';
           return;
       }
   }

}

void placePieces(const char *pieces, bool isPawn) {

   int n, r, c;
   int numToPlace = rand() % strlen(pieces);
   for (n = 0; n < numToPlace; ++n) {
       do {
           r = rand() % 8;
           c = rand() % 8;
       }
       while (grid[r][c] != 0 || (isPawn && (r == 7 || r == 0)));
       grid[r][c] = pieces[n];
   }

}

void toFen() {

   char fen[80], ch;
   int r, c, countEmpty = 0, index = 0;
   for (r = 0; r < 8; ++r) {
       for (c = 0; c < 8; ++c) {
           ch = grid[r][c];
           printf("%2c ", ch == 0 ? '.' : ch);
           if (ch == 0) {
               countEmpty++;
           }
           else {
               if (countEmpty > 0) {
                   fen[index++] = countEmpty + 48;
                   countEmpty = 0;               
               }
               fen[index++] = ch;
           }
       }
       if (countEmpty > 0) {
           fen[index++] = countEmpty + 48;
           countEmpty = 0;
       }
       fen[index++]= '/';
       printf("\n");
   }
   strcpy(fen + index, " w - - 0 1");
   printf("%s\n", fen);

}

char *createFen() {

   placeKings();
   placePieces("PPPPPPPP", TRUE);
   placePieces("pppppppp", TRUE);
   placePieces("RNBQBNR", FALSE);
   placePieces("rnbqbnr", FALSE);
   toFen();

}

int main() {

   srand(time(NULL));
   createFen();
   return 0;

}</lang>

Output:

Sample position:

 .  .  .  Q  .  .  b  . 
 .  .  .  .  .  .  .  . 
 R  .  .  b  .  .  r  . 
 .  .  .  .  q  .  .  K 
 .  .  .  .  P  .  .  . 
 .  B  k  P  .  .  .  . 
 .  n  .  .  .  .  .  . 
 .  .  .  N  .  .  .  . 
3Q2b1/8/R2b2r1/4q2K/4P3/1BkP4/1n6/3N4/ w - - 0 1

C++

<lang cpp>

  1. include <ctime>
  2. include <iostream>
  3. include <string>
  4. include <algorithm>

class chessBoard { public:

   void generateRNDBoard( int brds ) {
       int a, b, i; char c;
       for( int cc = 0; cc < brds; cc++ ) {
           memset( brd, 0, 64 );
           std::string pieces = "PPPPPPPPNNBBRRQKppppppppnnbbrrqk";
           random_shuffle( pieces.begin(), pieces.end() );
           while( pieces.length() ) {
               i = rand() % pieces.length(); c = pieces.at( i );
               while( true ) {
                   a = rand() % 8; b = rand() % 8;
                   if( brd[a][b] == 0 ) {
                       if( c == 'P' && !b || c == 'p' && b == 7 || 
                         ( ( c == 'K' || c == 'k' ) && search( c == 'k' ? 'K' : 'k', a, b ) ) ) continue;
                       break;
                   }
               }
               brd[a][b] = c;
               pieces = pieces.substr( 0, i ) + pieces.substr( i + 1 );
           }
           print();
       }
   }

private:

   bool search( char c, int a, int b ) {
       for( int y = -1; y < 2; y++ ) {
           for( int x = -1; x < 2; x++ ) {
               if( !x && !y ) continue;
               if( a + x > -1 && a + x < 8 && b + y >-1 && b + y < 8 ) {
                   if( brd[a + x][b + y] == c ) return true;
               }
           }
       }
       return false;
   }
   void print() {
       int e = 0;
       for( int y = 0; y < 8; y++ ) {
           for( int x = 0; x < 8; x++ ) {
               if( brd[x][y] == 0 ) e++;
               else {
                   if( e > 0 ) { std::cout << e; e = 0; }
                   std::cout << brd[x][y];
               }
           }
           if( e > 0 ) { std::cout << e; e = 0; } 
           if( y < 7 ) std::cout << "/";
       }
       std::cout << " w - - 0 1\n\n";
       for( int y = 0; y < 8; y++ ) {
           for( int x = 0; x < 8; x++ ) {
               if( brd[x][y] == 0 ) std::cout << ".";
               else std::cout << brd[x][y];
           }
           std::cout << "\n";
       }
       std::cout << "\n\n";
   }
   char brd[8][8];

}; int main( int argc, char* argv[] ) {

   srand( ( unsigned )time( 0 ) );
   chessBoard c;
   c.generateRNDBoard( 2 );
   return 0;

} </lang>

Output:
1R6/2bnQP1K/br1N1BP1/nPkp1P2/2p1P1P1/4Ppqp/p1r1ppp1/1PNR3B w - - 0 1
.R......
..bnQP.K
br.N.BP.
nPkp.P..
..p.P.P.
....Ppqp
p.r.ppp.
.PNR...B


1n1k2bp/1PppQpb1/N1p4p/1B2P1K1/1RB2P2/pPR1Np2/P1r1rP1P/P2q3n w - - 0 1
.n.k..bp
.PppQpb.
N.p....p
.B..P.K.
.RB..P..
pPR.Np..
P.r.rP.P
P..q...n

Crystal

Translation of: Ruby

<lang ruby>def hasNK(board, a, b)

   (-1..1).each do |g|
       (-1..1).each do |f|
           aa = a + f; bb = b + g
           if (0..7).includes?(aa) && (0..7).includes?(bb)
               p = board[aa + 8 * bb]
               return true if p == "K" || p == "k"
           end 
       end
   end
   return false

end

def generateBoard(board, pieces)

   pieces.each_char do |p|
       while true
           a = rand(8); b = rand(8)
           next  if ( (b == 0 || b == 7) && (p == "P" || p == "p") ) || 
              ( (p == "k" || p == "K") && hasNK(board, a, b) )
           break if board[a + b * 8] == '.'
       end
       board[a + b * 8] = p
   end

end

pieces = "ppppppppkqrrbbnnPPPPPPPPKQRRBBNN" 11.times do

   e = pieces.size - 1
   while e > 0
       p = rand(e); t = pieces[e]
       #pieces[e] = pieces[p]; pieces[p] = t; e -= 1 # in Ruby
       pieces = pieces.sub(e, pieces[p])             # in Crystal because
       pieces = pieces.sub(p, t); e -= 1             # strings immutable
   end

end

  1. No 'nil' for Crystal arrays; use '.' for blank value

board = Array.new(64, '.'); generateBoard(board, pieces) puts e = 0 8.times do |j| row_j = j * 8

   8.times do |i| 
       board[row_j + i ] == '.' ? (e += 1) :
           ( (print(e); e = 0) if e > 0
           print board[row_j + i] )
   end
   (print(e); e = 0) if e > 0
   print("/") if j < 7

end

print(" w - - 0 1\n") 8.times do |j| row_j = j * 8

 8.times { |i| board[row_j + i] == '.' ? print(".") : print(board[row_j + i]) }
 puts

end

  1. Simpler for same output

8.times{ |row| puts board[row*8..row*8 + 7].join("") }</lang>

Output:
1n1P3p/1p1k2Pp/1ppPPprn/2rP4/KNRQ2b1/2Bp1PP1/3qPBN1/2Rp4 w - - 0 1

.n.P...p .p.k..Pp .ppPPprn ..rP.... KNRQ..b. ..Bp.PP. ...qPBN. ..Rp....

Factor

<lang factor>USING: combinators.short-circuit grouping io kernel math math.parser math.ranges math.vectors prettyprint random sequences sets splitting.monotonic strings ; IN: rosetta-code.random-chess-position

<PRIVATE

CONSTANT: pieces "RNBQBNRPPPPPPPPrnbqbnrpppppppp" CONSTANT: empty CHAR: .

<empty-board> ( -- seq ) 64 [ empty ] "" replicate-as ;
empty-index ( seq -- n ) empty swap indices random ;
place ( seq elt n -- seq' ) rot [ set-nth ] keep ;

! return a list of indices that are adjacent to n

adj ( n -- seq )
   [ 1 - ] [ 1 + ] bi [a,b] { 8 8 8 } [ v- ] 2keep dupd v+
   append append ;
rand-non-adjacent ( m -- n ) 64 <iota> swap adj diff random ;
place-kings ( seq -- seq' )
   CHAR: K over empty-index [ place ] keep [ CHAR: k ] dip
   rand-non-adjacent place ;
non-pawn ( seq elt -- seq' ) over empty-index place ;

! prevent placing of pawns in ranks 1 and 8

pawn ( seq elt -- seq' )
   over empty swap indices
   [ { [ 7 > ] [ 56 < ] } 1&& ] filter random place ;
place-piece ( seq -- seq' )
   pieces random dup "Pp" member? [ pawn ] [ non-pawn ] if ;

PRIVATE>


position ( -- seq )
   <empty-board> place-kings 30 random [ place-piece ] times ;
position. ( seq -- )
   [ 1string ] { } map-as 8 group simple-table. ;
position>fen ( seq -- seq' )
   8 group [
       [ = ] monotonic-split
       [ dup first empty = [ length number>string ] when ]
       map concat
   ] map "/" join "/ w - - 0 1" append ;
random-chess-position-demo ( -- )
   position [ position. ] [ position>fen print ] bi ;

MAIN: random-chess-position-demo</lang>

Output:
. . . . . . . .
. p . . . . . .
. . . Q R . . .
. . . . . . k .
. P . . b . . .
. . P . . . K .
. . . . . . b .
. . . . . . r .
8/1p6/3QR3/6k1/1P2b3/2P3K1/6b1/6r1/ w - - 0 1

FreeBASIC

Translation of: Yabasic

<lang freebasic> Dim Shared As Byte grid(8, 8), r, c

Sub placeKings()

   Dim As Byte r1, r2, c1, c2
   
   Do
       r1 = Int(Rnd*8)
       c1 = Int(Rnd*8)
       r2 = Int(Rnd*8)
       c2 = Int(Rnd*8)
       If (r1 <> r2 And Abs(r1 - r2) > 1 And Abs(c1 - c2) > 1) Then
           grid(r1, c1) = Asc("K")
           grid(r2, c2) = Asc("k")
           Return
       End If
   Loop

End Sub

Sub placePieces(pieces As String, isPawn As Byte)

   Dim numToPlace As Byte = Int(Rnd*(Len(pieces)))
   
   For n As Byte = 0 To numToPlace-1
       Do
           r = Int(Rnd*8)
           c = Int(Rnd*8)
       Loop Until(Not(grid(r, c) Or (isPawn And (r = 7 Or r = 0))))
       grid(r, c) = Asc(Mid(pieces, n, 1))
   Next n

End Sub

Sub toFen()

   Dim As Byte ch, countEmpty = 0
   Dim As String fen
   
   For r = 0 To 8-1
       For c = 0 To 8-1
           ch = grid(r, c)
           If ch <> 0 Then 
               Print " " & Chr(ch);
           Else 
               Print " .";
           End If
           If ch = 0 Then
               countEmpty += 1
           Else
               If countEmpty > 0 Then
                   fen += Chr(countEmpty + 48)
                   countEmpty = 0
               End If
               fen += Chr(ch)
           End If
       Next c
       If countEmpty > 0 Then
           fen += Chr(countEmpty + 48)
           countEmpty = 0
       End If
       fen += "/"
       Print
   Next r
   fen += " w - - 0 1"
   Print fen

End Sub

Randomize Timer placeKings() placePieces("PPPPPPPP", True) placePieces("pppppppp", True) placePieces("RNBQBNR", False) placePieces("rnbqbnr", False) toFen() Sleep </lang>

Output:
 . . . . . . . .
 . . . . . . p .
 . . k P . . . .
 . . . . . b . .
 p . p . . p K .
 . Q . . p . r .
 . q . . . . . .
 . . . N . B n .
8/6p1/2kP4/5b2/p1p2pK1/1Q2p1r1/1q6/3N1Bn1/ w - - 0 1

Go

Translation of: Java

<lang go>package main

import (

   "fmt"
   "math/rand"
   "strconv"
   "strings"
   "time"

)

var grid [8][8]byte

func abs(i int) int {

   if i >= 0 {
       return i
   } else {
       return -i
   }

}

func createFen() string {

   placeKings()
   placePieces("PPPPPPPP", true)
   placePieces("pppppppp", true)
   placePieces("RNBQBNR", false)
   placePieces("rnbqbnr", false)
   return toFen()

}

func placeKings() {

   for {
       r1 := rand.Intn(8)
       c1 := rand.Intn(8)
       r2 := rand.Intn(8)
       c2 := rand.Intn(8)
       if r1 != r2 && abs(r1-r2) > 1 && abs(c1-c2) > 1 {
           grid[r1][c1] = 'K'
           grid[r2][c2] = 'k'
           return
       }
   }

}

func placePieces(pieces string, isPawn bool) {

   numToPlace := rand.Intn(len(pieces))
   for n := 0; n < numToPlace; n++ {
       var r, c int
       for {
           r = rand.Intn(8)
           c = rand.Intn(8)
           if grid[r][c] == '\000' && !(isPawn && (r == 7 || r == 0)) {
               break
           }
       }
       grid[r][c] = pieces[n]
   }

}

func toFen() string {

   var fen strings.Builder
   countEmpty := 0
   for r := 0; r < 8; r++ {
       for c := 0; c < 8; c++ {
           ch := grid[r][c]
           if ch == '\000' {
               ch = '.'
           }
           fmt.Printf("%2c ", ch)
           if ch == '.' {
               countEmpty++
           } else {
               if countEmpty > 0 {
                   fen.WriteString(strconv.Itoa(countEmpty))
                   countEmpty = 0
               }
               fen.WriteByte(ch)
           }
       }
       if countEmpty > 0 {
           fen.WriteString(strconv.Itoa(countEmpty))
           countEmpty = 0
       }
       fen.WriteString("/")
       fmt.Println()
   }
   fen.WriteString(" w - - 0 1")
   return fen.String()

}

func main() {

   rand.Seed(time.Now().UnixNano())
   fmt.Println(createFen())

}</lang>

Output:

Sample position:

 .  q  .  .  .  .  .  . 
 .  .  .  p  .  .  .  K 
 .  .  .  .  .  .  .  b 
 .  r  .  b  .  .  .  . 
 .  .  .  k  .  .  .  . 
 .  .  .  .  .  .  p  . 
 .  .  .  .  .  .  .  . 
 .  n  n  .  .  .  .  .
1q6/3p3K/7b/1r1b4/3k4/6p1/8/1nn5/ w - - 0 1 

Haskell

Uses System.Random library: https://hackage.haskell.org/package/random-1.1/docs/System-Random.html

caveat: I'm learning the language and as such my approach may is not be the simplest way to do this.

<lang haskell>{-# LANGUAGE LambdaCase #-}

import System.Random (getStdRandom, randomR, Random, random) import Data.List (find, sortBy) import Data.Ord (comparing)

type Pos = (Char, Int)

type ChessBoard = [(Square, Pos)]

data PieceRank = King | Queen | Rook | Bishop | Knight | Pawn

 deriving (Enum, Bounded, Show, Eq, Ord)

data PieceColor = Black | White

 deriving (Enum, Bounded, Show, Eq, Ord)

data Square = ChessPiece PieceRank PieceColor | EmptySquare

 deriving (Eq, Ord)

type PieceCount = [(Square, Int)]

instance Show Square where

 show (ChessPiece King   Black) = "♚"
 show (ChessPiece Queen  Black) = "♛"
 show (ChessPiece Rook   Black) = "♜"
 show (ChessPiece Bishop Black) = "♝"
 show (ChessPiece Knight Black) = "♞"
 show (ChessPiece Pawn   Black) = "♟"
 show (ChessPiece King   White) = "♔"
 show (ChessPiece Queen  White) = "♕"
 show (ChessPiece Rook   White) = "♖"
 show (ChessPiece Bishop White) = "♗"
 show (ChessPiece Knight White) = "♘"
 show (ChessPiece Pawn   White) = "♙"
 show EmptySquare               = " "

instance Random PieceRank where

 randomR (a, b) g = case randomR (fromEnum a, fromEnum b) g of
   (x, g) -> (toEnum x, g)
 random g = randomR (minBound, maxBound) g

instance Random PieceColor where

 randomR (a, b) g = case randomR (fromEnum a, fromEnum b) g of
   (x, g) -> (toEnum x, g)
 random g = randomR (minBound, maxBound) g

fullBoard :: PieceCount fullBoard =

 [ (ChessPiece King Black  , 1)
 , (ChessPiece Queen Black , 1)
 , (ChessPiece Rook Black  , 2)
 , (ChessPiece Bishop Black, 2)
 , (ChessPiece Knight Black, 2)
 , (ChessPiece Pawn Black  , 8)
 , (ChessPiece King White  , 1)
 , (ChessPiece Queen White , 1)
 , (ChessPiece Rook White  , 2)
 , (ChessPiece Bishop White, 2)
 , (ChessPiece Knight White, 2)
 , (ChessPiece Pawn White  , 8)
 , (EmptySquare            , 32)
 ]

emptyBoard :: ChessBoard emptyBoard = [ (EmptySquare, (x, y)) | x <- ['a' .. 'h'], y <- [1 .. 8] ]

replaceSquareByPos :: (Square, Pos) -> ChessBoard -> ChessBoard replaceSquareByPos e@(s, p) = map (\x -> if p == snd x then e else x)

isPosOccupied :: Pos -> ChessBoard -> Bool isPosOccupied p = occupied . find (\x -> p == snd x)

where
 occupied (Just (EmptySquare, _)) = False
 occupied _                       = True

isAdjacent :: Pos -> Pos -> Bool isAdjacent (x, y) (x, y) =

 let upOrDown    = (pred y == y || succ y == y)
     leftOrRight = (pred x == x || succ x == x)
 in  (x == x && upOrDown)
       || (pred x == x && upOrDown)
       || (succ x == x && upOrDown)
       || (leftOrRight && y == y)

fen :: Square -> String fen (ChessPiece King Black) = "k" fen (ChessPiece Queen Black) = "q" fen (ChessPiece Rook Black) = "r" fen (ChessPiece Bishop Black) = "b" fen (ChessPiece Knight Black) = "n" fen (ChessPiece Pawn Black) = "p" fen (ChessPiece King White) = "K" fen (ChessPiece Queen White) = "Q" fen (ChessPiece Rook White) = "R" fen (ChessPiece Bishop White) = "B" fen (ChessPiece Knight White) = "N" fen (ChessPiece Pawn White) = "P"

boardSort :: (Square, Pos) -> (Square, Pos) -> Ordering boardSort (_, (x, y)) (_, (x, y)) | y < y = GT

                                     | y > y  = LT
                                     | y == y = compare x x

toFen :: ChessBoard -> String toFen [] = " w - - 0 1" <> [] toFen b = scanRow (map fst $ take 8 b) 0

where
 scanRow []                   0 = nextRow
 scanRow []                   n = show n <> nextRow
 scanRow ((EmptySquare) : xs) n = scanRow xs (succ n)
 scanRow (x             : xs) 0 = nextPiece x xs
 scanRow (x             : xs) n = show n <> nextPiece x xs
 nextRow = "/" <> toFen (drop 8 b)
 nextPiece x xs = fen x <> scanRow xs 0

-- impure functions

randomPos :: ChessBoard -> IO Pos randomPos b = pos >>= \p -> if isPosOccupied p b then randomPos b else pos

where
 pos = (,) <$> chr <*> num
 num = getStdRandom $ randomR (1, 8)
 chr = getStdRandom $ randomR ('a', 'h')

randomPiece :: IO Square randomPiece = ChessPiece <$> rank <*> color

where
 rank  = getStdRandom random
 color = getStdRandom random

placeKings :: ChessBoard -> IO ChessBoard placeKings b = do

 p1 <- randomPos b
 p2 <- randomPos b
 if p1 `isAdjacent` p2 || p1 == p2
   then placeKings b
   else pure
     ( replaceSquareByPos ((ChessPiece King White), p1)
     $ replaceSquareByPos ((ChessPiece King Black), p2) b
     )

placePawns :: ChessBoard -> IO ChessBoard placePawns b = num >>= go b

where
 go :: ChessBoard -> Int -> IO ChessBoard
 go b 0 = pure b
 go b n = do
   pos                       <- randomPos b
   pawn@(ChessPiece _ color) <- randomPawn
   if promoted color == snd pos
        || isPosOccupied pos b
        || enpassant color == snd pos
        || firstPos color == snd pos
     then go b n
     else go (replaceSquareByPos (pawn, pos) b) (pred n)
 promoted White = 8
 promoted Black = 1
 enpassant White = 5
 enpassant Black = 4
 firstPos White = 1
 firstPos Black = 8
 num        = getStdRandom (randomR (1, 16))
 randomPawn = ChessPiece Pawn <$> rColor where rColor = getStdRandom (random)

placeRemaining :: ChessBoard -> IO ChessBoard placeRemaining b = do

 n <- num (sum $ map snd remaining)
 putStrLn $  "Placing " <> show n
   <> " more random positions after placing 2 kings and "
   <> (show $ totalPawns b) <> " pawns. "
 go remaining b n
where
 remaining :: [(Square, Int)]
 remaining = filter
   (\case
     ((ChessPiece King _), _) -> False
     ((ChessPiece Pawn _), _) -> False
     (EmptySquare        , _) -> False
     _                        -> True
   )
   fullBoard
 num mx = getStdRandom $ randomR (5, mx)
 totalPawns = length . filter
   (\case ((ChessPiece Pawn _), _) -> True
          _                        -> False
   )
 go :: [(Square, Int)] -> ChessBoard -> Int -> IO ChessBoard
 go _         b 0 = pure b
 go permitted b n = do
   position <- randomPos b
   piece    <- randomPiece
   if (not $ isPermitted piece) || isPosOccupied position b
     then go permitted b n
     else go (consume piece permitted)
             (replaceSquareByPos (piece, position) b)
             (pred n)
  where
   isPermitted p = case find (\x -> fst x == p) permitted of
     Just (_, count) -> count > 0
     Nothing         -> False
   consume p = map (\(p, c) -> if p == p then (p, pred c) else (p, c))

draw :: ChessBoard -> IO () draw b = do

 showXAxis
 line
 mapM_
   (\b@(p, (x, y)) -> case x of
     'h' -> putStr (" | " <> show p <> " | " <> show y <> "\n") >> line
     'a' -> putStr (show y <> " | " <> show p)
     _   -> putStr (" | " <> show p)
   )
   sorted
 showXAxis
 putStrLn ""
 putStrLn $ toFen sorted
 -- mapM_ print $ sortBy (comparing fst) $ filter (\(s, _) -> s /= EmptySquare) b
where
 sorted    = sortBy boardSort b
 line      = putStrLn ("  " <> (replicate 33 '-'))
 showXAxis = do
   putStr " "
   mapM_ (\(_, (x, _)) -> putStr $ "   " <> [x]) (take 8 sorted)
   putStrLn ""

main :: IO () main = placeKings emptyBoard >>= placePawns >>= placeRemaining >>= draw</lang>

Output:

Run 1

Placing 8 more random positions after placing 2 kings and 11 pawns. 
    a   b   c   d   e   f   g   h
  ---------------------------------
8 |   |   |   | ♗ |   | ♚ |   |   | 8
  ---------------------------------
7 | ♙ |   |   |   |   | ♟ | ♟ | ♗ | 7
  ---------------------------------
6 |   |   |   |   |   |   | ♟ | ♟ | 6
  ---------------------------------
5 |   |   | ♟ |   | ♟ |   |   |   | 5
  ---------------------------------
4 |   |   |   |   | ♔ |   |   |   | 4
  ---------------------------------
3 |   | ♙ | ♟ |   |   | ♝ | ♖ |   | 3
  ---------------------------------
2 | ♜ |   | ♟ | ♟ |   | ♕ |   |   | 2
  ---------------------------------
1 |   |   |   | ♝ |   | ♘ |   |   | 1
  ---------------------------------
    a   b   c   d   e   f   g   h

3B1k2/P4ppB/6pp/2p1p3/4K3/1Pp2bR1/r1pp1Q2/3b1N2/ w - - 0 1

Run 2

Placing 9 more random positions after placing 2 kings and 2 pawns. 
    a   b   c   d   e   f   g   h
  ---------------------------------
8 |   | ♖ |   |   |   |   |   |   | 8
  ---------------------------------
7 | ♔ | ♙ |   |   |   |   | ♚ |   | 7
  ---------------------------------
6 |   |   |   |   | ♞ |   |   |   | 6
  ---------------------------------
5 |   |   |   |   |   | ♜ |   |   | 5
  ---------------------------------
4 |   | ♗ |   |   |   |   |   |   | 4
  ---------------------------------
3 |   |   | ♙ |   |   |   |   | ♘ | 3
  ---------------------------------
2 |   |   | ♕ |   |   | ♞ |   |   | 2
  ---------------------------------
1 |   | ♛ |   |   | ♝ |   |   |   | 1
  ---------------------------------
    a   b   c   d   e   f   g   h

1R6/KP4k1/4n3/5r2/1B6/2P4N/2Q2n2/1q2b3/ w - - 0 1

etc...

J

Implementation:

<lang J>getlayout=:3 :0

 whilst. NB. first two positions are non-adjacent kings
   (0{pos) e. (1{pos)+(,-)1 7 8 9
 do.
   pos=: y?64
 end.

)

randboard=:3 :0

 n=: ?30  NB. number of non-king pieces on board
 layout=: getlayout 2+n   NB. where they go
 white=: 0 1,?n#2         NB. which ones are white?
 pawns=: 0 0,?n#2             NB. where are the pawns?
 pawns=: pawns * 1- white*layout e.56+i.8
 pawns=: pawns * 1-(1-white)*layout e.i.8
 ptyp=: 'pkqbjnPKQBJN'{~(6*white)+1 1,(1-2}.pawns)*2+?n#4
 8 8$ptyp layout}64#'.'

)

NB. fen compress a line fen1=:3 :0

 for_n.8-i.8 do.
   y=. y rplc (#&'.';":) n
 end.

)

NB. translate 8x8 board to fen notation NB. (just the task specific crippled fen) b2fen=:3 :0

 (}.;|.<@(('/',fen1)"1) y),' w - - 0 1'

)

randfen=:b2fen@randboard</lang>

Example use:

<lang J> randfen q6J/1pb1p1p1/1Jq2k2/4p1Pp/1pP5/1K2Bp2/5p2/1P4P1 w - - 0 1

  randfen

1Q3Q2/1Kn5/1PP5/2P5/2kNq1J1/7J/1P6/8 w - - 0 1

  randfen

8/8/7K/8/8/8/k7/8 w - - 0 1

  randfen

p4n2/1Q6/8/8/8/p4k1K/8/P5Qn w - - 0 1

  randfen

bk1q3J/8/1N4K1/N3P3/3BQ3/j1P3P1/7P/5jq1 w - - 0 1

  randfen

b1Q1Bb1J/j1N1PpK1/PpB1P1Pp/2pp2PN/3nnk2/3J4/P6P/1N2Qb1J w - - 0 1 </lang>

Java

<lang java>import static java.lang.Math.abs; import java.util.Random;

public class Fen {

   static Random rand = new Random();
   public static void main(String[] args) {
       System.out.println(createFen());
   }
   static String createFen() {
       char[][] grid = new char[8][8];
       placeKings(grid);
       placePieces(grid, "PPPPPPPP", true);
       placePieces(grid, "pppppppp", true);
       placePieces(grid, "RNBQBNR", false);
       placePieces(grid, "rnbqbnr", false);
       return toFen(grid);
   }
   static void placeKings(char[][] grid) {
       int r1, c1, r2, c2;
       while (true) {
           r1 = rand.nextInt(8);
           c1 = rand.nextInt(8);
           r2 = rand.nextInt(8);
           c2 = rand.nextInt(8);
           if (r1 != r2 && abs(r1 - r2) > 1 && abs(c1 - c2) > 1)
               break;
       }
       grid[r1][c1] = 'K';
       grid[r2][c2] = 'k';
   }
   static void placePieces(char[][] grid, String pieces, boolean isPawn) {
       int numToPlace = rand.nextInt(pieces.length());
       for (int n = 0; n < numToPlace; n++) {
           int r, c;
           do {
               r = rand.nextInt(8);
               c = rand.nextInt(8);
           } while (grid[r][c] != 0 || (isPawn && (r == 7 || r == 0)));
           grid[r][c] = pieces.charAt(n);
       }
   }
   static String toFen(char[][] grid) {
       StringBuilder fen = new StringBuilder();
       int countEmpty = 0;
       for (int r = 0; r < 8; r++) {
           for (int c = 0; c < 8; c++) {
               char ch = grid[r][c];
               System.out.printf("%2c ", ch == 0 ? '.' : ch);
               if (ch == 0) {
                   countEmpty++;
               } else {
                   if (countEmpty > 0) {
                       fen.append(countEmpty);
                       countEmpty = 0;
                   }
                   fen.append(ch);
               }
           }
           if (countEmpty > 0) {
               fen.append(countEmpty);
               countEmpty = 0;
           }
           fen.append("/");
           System.out.println();
       }
       return fen.append(" w - - 0 1").toString();
   }

}</lang>

(lol, the black king is in check, it couldn't possibly be white's turn)
 .  .  .  .  .  B  .  . 
 P  .  P  .  .  .  .  . 
 .  .  k  .  R  .  .  . 
 p  .  P  p  .  .  .  . 
 .  .  .  .  .  .  .  Q 
 P  .  .  .  .  .  .  . 
 .  N  .  .  r  N  P  . 
 .  .  .  .  .  .  B  K 
5B2/P1P5/2k1R3/p1Pp4/7Q/P7/1N2rNP1/6BK/ w - - 0 1

Julia

Translation of: Kotlin

Module: <lang julia>module Chess

using Printf

struct King end struct Pawn end

function placepieces!(grid, ::King)

   axis = axes(grid, 1)
   while true
       r1, c1, r2, c2 = rand(axis, 4)
       if r1 != r2 && abs(r1 - r2) > 1 && abs(c1 - c2) > 1
           grid[r1, c1] = '♚'
           grid[r2, c2] = '♔'
           return grid
       end
   end

end

function placepieces!(grid, ch)

   axis = axes(grid, 1)
   while true
       r, c = rand(axis, 2)
       if grid[r, c] == ' '
           grid[r, c] = ch
           return grid
       end
   end

end

function placepieces!(grid, ch, ::Pawn)

   axis = axes(grid, 1)
   while true
       r, c = rand(axis, 2)
       if grid[r, c] == ' ' && r ∉ extrema(axis)
           grid[r, c] = ch
           return grid
       end
   end

end

function randposition!(grid)

   placepieces!(grid, King())
   foreach("♙♙♙♙♙♙♙♙♙♟♟♟♟♟♟♟♟") do ch
       placepieces!(grid, ch, Pawn())
   end
   foreach("♖♘♗♕♗♘♖♜♞♝♛♝♞♜") do ch
       placepieces!(grid, ch)
   end
   return grid

end

printgrid(grid) = println(join((join(grid[r, :], ' ') for r in 1:size(grid, 1)), '\n'))

end # module Chess</lang>

Main: <lang julia>grid = fill(' ', 8, 8) Chess.randposition!(grid) Chess.printgrid(grid)</lang>

Output:
    ♕     ♞ ♗
♖ ♙ ♔ ♙ ♖ ♜   ♙
      ♟   ♙ ♙ ♜
♘ ♝ ♙ ♙ ♟
  ♙     ♚   ♝ ♟
    ♟ ♟     ♗ ♟
♙     ♞   ♟   ♟
        ♘   ♛

Kotlin

Translation of: Java

<lang scala>// version 1.2.0

import java.util.Random import kotlin.math.abs

val rand = Random()

val grid = List(8) { CharArray(8) }

const val NUL = '\u0000'

fun createFen(): String {

   placeKings()
   placePieces("PPPPPPPP", true)
   placePieces("pppppppp", true)
   placePieces("RNBQBNR", false)
   placePieces("rnbqbnr", false)
   return toFen()

}

fun placeKings() {

   while (true) {
       val r1 = rand.nextInt(8)
       val c1 = rand.nextInt(8)
       val r2 = rand.nextInt(8)
       val c2 = rand.nextInt(8)
       if (r1 != r2 && abs(r1 - r2) > 1 && abs(c1 - c2) > 1) {
           grid[r1][c1] = 'K'
           grid[r2][c2] = 'k'
           return
       }
   }

}

fun placePieces(pieces: String, isPawn: Boolean) {

   val numToPlace = rand.nextInt(pieces.length)
   for (n in 0 until numToPlace) {
       var r: Int
       var c: Int
       do {
           r = rand.nextInt(8)
           c = rand.nextInt(8)
       }
       while (grid[r][c] != NUL || (isPawn && (r == 7 || r == 0)))
       grid[r][c] = pieces[n]
   }

}

fun toFen(): String {

   val fen = StringBuilder()
   var countEmpty = 0
   for (r in 0..7) {
       for (c in 0..7) {
           val ch = grid[r][c]
           print ("%2c ".format(if (ch == NUL) '.' else ch))
           if (ch == NUL) {
               countEmpty++
           }
           else {
               if (countEmpty > 0) {
                   fen.append(countEmpty)
                   countEmpty = 0
               }
               fen.append(ch)
           }
       }
       if (countEmpty > 0) {
           fen.append(countEmpty)
           countEmpty = 0
       }
       fen.append("/")
       println()
   }
   return fen.append(" w - - 0 1").toString()

}

fun main(args: Array<String>) {

   println(createFen())

}</lang>

Sample output:

 .  .  .  .  .  .  .  . 
 K  .  .  .  .  .  .  . 
 .  P  p  .  b  .  P  P 
 .  p  P  .  .  .  P  . 
 .  p  .  q  .  p  P  P 
 .  .  .  k  .  .  .  b 
 .  .  .  n  p  .  .  . 
 .  .  r  .  .  .  .  .
8/K7/1Pp1b1PP/1pP3P1/1p1q1pPP/3k3b/3np3/2r5/ w - - 0 1 

Perl

Translation of: Raku

<lang perl>use strict; use warnings; use feature 'say'; use utf8; use List::AllUtils <shuffle any natatime>;

sub pick1 { return @_[rand @_] }

sub gen_FEN {

   my $n = 1 + int rand 31;
   my @n = (shuffle(0 .. 63))[1 .. $n];
   my @kings;
 KINGS: {
   for my $a (@n) {
       for my $b (@n) {
           next unless $a != $b && abs(int($a/8) - int($b/8)) > 1 || abs($a%8 - $b%8) > 1;
           @kings = ($a, $b);
           last KINGS;
       }
       die 'No good place for kings!';
   }
   }
   my ($row, @pp);

my @pieces =

; my @k = rand() < .5 ? <K k> : <k K>; for my $sq (0 .. 63) { if (any { $_ == $sq } @kings) { push @pp, shift @k; } elsif (any { $_ == $sq } @n) { $row = 7 - int $sq / 8; push @pp, $row == 0 ? pick1(grep { $_ ne 'P' } @pieces)  : $row == 7 ? pick1(grep { $_ ne 'P' } @pieces)  : pick1(@pieces); } else { push @pp, 'ø'; } } my @qq; my $iter = natatime 8, @pp; while (my $row = join , $iter->()) { $row =~ s/((ø)\2*)/length($1)/eg; push @qq, $row; } return join('/', @qq) . ' w - - 0 1'; } say gen_FEN();</lang>

Output:
p5Nq/1nn5/3N2bp/PRBkQr2/1QB1Pn2/Q5pK/1NRb2rN/p1R2r1N w - - 0 1

Phix

<lang Phix>constant show_bad_boards = false

string board

function fen()

   string res = ""
   for i=1 to 64 by 8 do
       integer empty = 0
       for j=i to i+7 do
           if board[j]='.' then
               empty += 1
           else
               if empty then
                   res &= empty+'0'
                   empty = 0
               end if
               res &= board[j]
           end if
       end for
       if empty then
           res &= empty+'0'
       end if
       if i<57 then res &= '/' end if
   end for
   res &= " w - - 0 1"
   return res

end function

function p15()

   string res = "pppppppprrnnbbq"
   -- promote 0..8 pawns
   for i=1 to rand(9)-1 do
       res[i] = res[rand(7)+8]
   end for
   res = shuffle(res)
   return res

end function

function kings_adjacent(sequence p12)

   integer {p1,p2} = sq_sub(p12,1),
           row_diff = abs(floor(p1/8)-floor(p2/8)),
           col_diff = abs(mod(p1,8)-mod(p2,8))
   return row_diff<=1 and col_diff<=1

end function

integer lp procedure show_board()

   printf(1,"%d pieces\n%s",{lp,join_by(board,1,8,"")})

end procedure

while true do

   string pieces = "Kk"&                        -- kings
                   upper(p15())[1..rand(16)-1]& -- white
                   lower(p15())[1..rand(16)-1]  -- black
   lp = length(pieces)
   sequence p = tagset(64)
   p = shuffle(p)
   board = repeat('.',64)
   for i=1 to lp do board[p[i]] = pieces[i] end for
   if kings_adjacent(p[1..2]) then
       if show_bad_boards then show_board() end if
       puts(1,"kings adjacent - reshuffle\n\n")
   else
       -- check no pawn will be on a promotion square,
       -- and (above spec) no pawn has gone backwards:
       if find('p',lower(board[1..8]&board[57..64]))=0 then exit end if
       if show_bad_boards then show_board() end if
       puts(1,"pawn on rank 1/8 - reshuffle\n\n")
   end if

end while show_board() printf(1,"\n%s\n",{fen()})</lang> To allow pawns that have "moved backwards", replace the inner test with if not find('P',board[1..8]) and not find('p',board[57..64]) then exit end if

Output:

with show_bad_boards set to true

28 pieces
nR..rprR
kp....Rp
BQ..B.B.
b..B...b
.Kq.B.b.
....r.n.
ppN..r..
.P......
pawn on rank 1/8 - reshuffle

28 pieces
pnp...K.
.q.....k
b.P....p
P..P..bp
pPN.P.P.
.BP..rRN
QR....bN
....n...
kings adjacent - reshuffle

10 pieces
......K.
b......q
...nn...
.....k..
........
..Q..n..
..b..r..
........

6K1/b6q/3nn3/5k2/8/2Q2n2/2b2r2/8 w - - 0 1

PicoLisp

<lang PicoLisp>(load "@lib/simul.l") (seed (in "/dev/urandom" (rd 8))) (de pieceN (P)

  (case P
     ("p" 8)
     ("q" 1)
     (T 2) ) )

(de pieceset ()

  (let C 0
     (make
        (for P (conc (cons "p") (shuffle '("r" "n" "b" "q")))
           (let (X (pieceN P)  N (rand 0 (+ X C)))
              (do N
                 (link P) )
              (if (= P "p")
                 (and
                    (> X N)
                    (inc 'C (- X N)) )
                 (and
                    (> N X)
                    (dec 'C (- N X)) ) ) ) ) ) ) )

(de neib (A)

  (let
     (X (/ (dec A) 8)
        Y (% (dec A) 8) )
     (filter
        '((N)
           (and
              (<= 1 N 64)
              (<=
                 (abs (- (/ (dec N) 8) X))
                 1 )
              (<=
                 (abs (- (% (dec N) 8) Y))
                 1 ) ) )
        (mapcar
           '((B) (+ B A))
           (-9 -8 -7 -1 1 7 8 9) ) ) ) )

(setq *B (need 64 ".")) (setq *P (conc (pieceset) (mapcar uppc (pieceset)) (cons "K"))) (for P *P

  (loop
     (T
        (=
           "."
           (car
              (setq @@
                 (nth
                    *B
                    (apply
                       rand
                       (if (or (= "p" P) (= "P" P))
                          (9 56)
                          (1 64) ) ) ) ) ) )
        (set @@ P) ) ) )

(loop

  (T
     (and
        (=
           "."
           (car
              (setq @@ (nth *B (setq @@@ (rand 1 64)))) ) )
        (fully
           '((N) (<> "K" (get *B N)))
           (neib @@@) ) )
     (set @@ "k") ) )

(setq *FEN

  (make
     (while *B
        (let (C 0  Lst (cut 8 '*B))
           (prinl Lst)
           (link
              (make
                 (for L Lst
                    (if (= L ".")
                       (inc 'C)
                       (and
                          (gt0 C)
                          (link (swap 'C 0)) )
                       (link L) ) )
                 (and
                    (gt0 C)
                    (link C) ) ) ) ) ) ) )

(println (pack (glue "/" *FEN) " w - - 0 1"))</lang>

Output:
...n...B
.p.BQ.B.
B..P..Br
p......p
r.PpBrrk
...B.P..
...r..K.
......r.
"3n3B/1p1BQ1B1/B2P2Br/p6p/r1PpBrrk/3B1P2/3r2K1/6r1 w - - 0 1"

Python

<lang python> import random

board = [[" " for x in range(8)] for y in range(8)] piece_list = ["R", "N", "B", "Q", "P"]


def place_kings(brd): while True: rank_white, file_white, rank_black, file_black = random.randint(0,7), random.randint(0,7), random.randint(0,7), random.randint(0,7) diff_list = [abs(rank_white - rank_black), abs(file_white - file_black)] if sum(diff_list) > 2 or set(diff_list) == set([0, 2]): brd[rank_white][file_white], brd[rank_black][file_black] = "K", "k" break

def populate_board(brd, wp, bp): for x in range(2): if x == 0: piece_amount = wp pieces = piece_list else: piece_amount = bp pieces = [s.lower() for s in piece_list] while piece_amount != 0: piece_rank, piece_file = random.randint(0, 7), random.randint(0, 7) piece = random.choice(pieces) if brd[piece_rank][piece_file] == " " and pawn_on_promotion_square(piece, piece_rank) == False: brd[piece_rank][piece_file] = piece piece_amount -= 1

def fen_from_board(brd): fen = "" for x in brd: n = 0 for y in x: if y == " ": n += 1 else: if n != 0: fen += str(n) fen += y n = 0 if n != 0: fen += str(n) fen += "/" if fen.count("/") < 7 else "" fen += " w - - 0 1\n" return fen

def pawn_on_promotion_square(pc, pr): if pc == "P" and pr == 0: return True elif pc == "p" and pr == 7: return True return False


def start(): piece_amount_white, piece_amount_black = random.randint(0, 15), random.randint(0, 15) place_kings(board) populate_board(board, piece_amount_white, piece_amount_black) print(fen_from_board(board)) for x in board: print(x)

  1. entry point

start() </lang>

Output:

1p5k/1B4P1/1KN4R/nR3Nrb/Q1NrnpP1/7R/3PP3/1P5P w - - 0 1

[' ', 'p', ' ', ' ', ' ', ' ', ' ', 'k'] [' ', 'B', ' ', ' ', ' ', ' ', 'P', ' '] [' ', 'K', 'N', ' ', ' ', ' ', ' ', 'R'] ['n', 'R', ' ', ' ', ' ', 'N', 'r', 'b'] ['Q', ' ', 'N', 'r', 'n', 'p', 'P', ' '] [' ', ' ', ' ', ' ', ' ', ' ', ' ', 'R'] [' ', ' ', ' ', 'P', 'P', ' ', ' ', ' '] [' ', 'P', ' ', ' ', ' ', ' ', ' ', 'P']

Raku

(formerly Perl 6) <lang perl6>sub pick-FEN {

   # First we chose how many pieces to place
   my $n = (2..32).pick;
   # Then we pick $n squares
   my @n = (^64).pick($n);
   # We try to find suitable king positions on non-adjacent squares.
   # If we could not find any, we return recursively
   return pick-FEN() unless
   my @kings[2] = first -> [$a, $b] {
       $a !== $b && abs($a div 8 - $b div 8) | abs($a mod 8 - $b mod 8) > 1
   }, (@n X @n);
   # We make a list of pieces we can pick (apart from the kings)

my @pieces =

; # We make a list of two king symbols to pick randomly a black or white king my @k = <K k>.pick(*); return (gather for ^64 -> $sq { if $sq == @kings.any { take @k.shift } elsif $sq == @n.any { my $row = 7 - $sq div 8; take $row == 7 ?? @pieces.grep(none('P')).pick !! $row == 0 ?? @pieces.grep(none('p')).pick !! @pieces.pick; } else { take 'ø' } }).rotor(8)».join».subst(/ø+/,{ .chars }, :g).join('/') ~ ' w - - 0 1'; } say pick-FEN();</lang>

Output:
q2n1n2/1Qpk3Q/1r3bP1/1b1b4/2pRBR2/4P1bN/2R3K1/N1r2rPB w - - 0 1

REXX

This REXX version normally generates balanced number of pieces   (both sides have an equal number of total pieces,
but not necessarily of the same kind).

If the number of chessboards specified is negative, then the number of chess pieces for each side will be random.

This version also allows any number of chessboards to be displayed. <lang rexx>/*REXX program generates a chess position (random pieces & positions) in a FEN format.*/ parse arg seed CBs . /*obtain optional arguments from the CL*/ if datatype(seed,'W') then call random ,,seed /*SEED given for RANDOM repeatability? */ if CBs== | CBs=="," then CBs=1 /*CBs: number of generated ChessBoards*/

                                                /* [↓]  maybe display any # of boards. */
     do boards=1  for abs(CBs)                  /* [↓]  maybe display separator & title*/
     if sign(CBs)\==CBs  then do;   say;   say center(' board' boards" ", 79, '▒');   end
     @.=.;  !.=.                                /*initialize the chessboard to be empty*/
                 do p=1  for random(2, 32)      /*generate a random number of chessmen.*/
                 if p<3  then call piece 'k'    /*a   king   of each color.            */
                         else call piece substr('bnpqr', random(1, 5), 1)
                 end  /*p*/                     /* [↑]  place a piece on the chessboard*/
     call cb                                    /*display the ChessBoard  and  its FEN.*/
     end          /*boards*/                    /* [↑]  CB ≡  ─    ─                   */

exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ cb: fen=; do r=8 for 8 by -1; $= /*the board rank (so far).*/

            do f=8  for 8  by -1; $=$ || @.r.f;  end /*f*/  /*append the board file.   */
          say $                                             /*display the board rank.  */
            do e=8  for 8  by -1; $=changestr(copies(.,e),$,e); end  /*e*/   /*.≡filler*/
          fen=fen || $ || left('/', r\==1)                  /*append / if not 1st rank.*/
          end   /*r*/                                       /* [↑]  append $ str to FEN*/
   say                                                      /*display a blank sep. line*/
   say 'FEN='fen   "w - - 0 1"                              /*Forsyth─Edwards Notation.*/
   return                                                   /* [↑]  display chessboard.*/

/*──────────────────────────────────────────────────────────────────────────────────────*/ piece: parse arg x; if p//2 then upper x; arg ux /*use white if odd P.*/

      if CBs<0 & p>2  then if random(1)  then upper x           /*CBs>0?  Use balanced.*/
                                                                /*[↓]  # isn't changed.*/
        do #=0  by 0;  r=random(1, 8);   f=random(1, 8)         /*random rank and file.*/
        if @.r.f\==.   then iterate                             /*is position occupied?*/
        if (x=='p' & r==1) | (x=='P' & r==8)  then iterate      /*any promoting pawn?  */
                                                                /*[↑]  skip these pawns*/
        if ux=='K'  then do    rr=r-1 for 3                     /*[↓]  neighbor ≡ king?*/
                            do ff=f-1 for 3;  if !.rr.ff=='K'  then iterate #   /*king?*/
                            end   /*rr*/                        /*[↑]  neighbor ≡ king?*/
                         end      /*ff*/                        /*[↑]  we're all done. */
        @.r.f= x                                                /*put random piece.    */
        !.r.f=ux;  return                                       /* "     "     "  upper*/
        end   /*#*/                                             /*#: isn't incremented.*/</lang>

Some older REXXes don't have a   changestr   BIF,   so one is included here:   ───►   CHANGESTR.REX.

output   showing five chess positions (starting with a specific position by seeding the   random   BIF with   96),
specifying the arguments (for Regina REXX under Windows):   96   5

▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ board 1 ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
........
........
....K...
........
....k...
........
........
........

FEN=8/8/4K3/8/4k3/8/8/8 w - - 0 1

▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ board 2 ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
...Q..r.
r.kbn...
...pqn.p
..N.N.qQ
p....N.n
..N.....
...NB...
.R.Q.KBP

FEN=3Q2r1/r1kbn3/3pqn1p/2N1N1qQ/p4N1n/2N5/3NB3/1R1Q1KBP w - - 0 1

▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ board 3 ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
.....B.n
N...p.p.
.q..n...
.K..R...
.BP...P.
q....k..
........
R.N..n..

FEN=5B1n/N3p1p1/1q2n3/1K2R3/1BP3P1/q4k2/8/R1N2n2 w - - 0 1

▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ board 4 ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
......K.
pN..q...
...qN...
....n...
.....Q..
........
....k...
P.r....B

FEN=6K1/pN2q3/3qN3/4n3/5Q2/8/4k3/P1r4B w - - 0 1

▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ board 5 ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
qnqN...N
...B...N
n....P.Q
PP..b.Rn
KqB.....
pB.knp..
q.n.qB..
.......N

FEN=qnqN3N/3B3N/n4P1Q/PP2b1Rn/KqB5/pB1knp2/q1n1qB2/7N w - - 0 1

Ruby

<lang ruby> def hasNK( board, a, b )

   for g in -1 .. 1
       for f in -1 .. 1
           aa = a + f; bb = b + g
           if aa.between?( 0, 7 ) && bb.between?( 0, 7 )
               p = board[aa + 8 * bb]
               if p == "K" || p == "k"; return true; end
           end 
       end
   end
   return false

end def generateBoard( board, pieces )

   while( pieces.length > 1 )
       p = pieces[pieces.length - 1]
       pieces = pieces[0...-1]
       while( true )
           a = rand( 8 ); b = rand( 8 )
           if ( ( b == 0 || b == 7 ) && ( p == "P" || p == "p" ) ) || 
              ( ( p == "k" || p == "K" ) && hasNK( board, a, b ) ); next; end  
           if board[a + b * 8] == nil; break;end
       end
       board[a + b * 8] = p
   end

end pieces = "ppppppppkqrrbbnnPPPPPPPPKQRRBBNN" for i in 0 .. 10

   e = pieces.length - 1
   while e > 0
       p = rand( e ); t = pieces[e]; 
       pieces[e] = pieces[p]; pieces[p] = t; e -= 1
   end

end board = Array.new( 64 ); generateBoard( board, pieces ) puts e = 0 for j in 0 .. 7

   for i in 0 .. 7 
       if board[i + 8 * j] == nil; e += 1
       else 
           if e > 0; print( e ); e = 0; end
           print( board[i + 8 * j] )
       end
   end
   if e > 0; print( e ); e = 0; end
   if j < 7; print( "/" ); end

end print( " w - - 0 1\n" ) for j in 0 .. 7

   for i in 0 .. 7 
       if board[i + j * 8] == nil; print( "." )
       else print( board[i + j * 8] ); end
   end
   puts

end </lang>

Output:

1bN1RK2/1Pp1pQbP/p2PpP2/8/1pkNP3/P1r1Pp1p/Bn1RPp1r/3qB3 w - - 0 1 .bN.RK.. .Pp.pQbP p..PpP.. ........ .pkNP... P.r.Pp.p Bn.RPp.r ...qB...

Rust

<lang Rust>use std::fmt::Write;

use rand::{Rng, distributions::{Distribution, Standard}};

const EMPTY: u8 = b'.';

  1. [derive(Clone, Debug)]

struct Board {

   grid: [[u8; 8]; 8],

}

impl Distribution<Board> for Standard {

   fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Board {
       let mut board = Board::empty();
       board.place_kings(rng);
       board.place_pieces(rng, b"PPPPPPPP", true);
       board.place_pieces(rng, b"pppppppp", true);
       board.place_pieces(rng, b"RNBQBNR", false);
       board.place_pieces(rng, b"rnbqbnr", false);
       board
   }

}

impl Board {

   fn empty() -> Self {
       Board { grid: [[EMPTY; 8]; 8] }
   }
   
   fn fen(&self) -> String {
       let mut fen = String::new();
       let mut count_empty = 0;
       for row in &self.grid {
           for &ch in row {
               print!("{} ", ch as char);
               if ch == EMPTY {
                   count_empty += 1;
               } else {
                   if count_empty > 0 {
                       write!(fen, "{}", count_empty).unwrap();
                       count_empty = 0;
                   }
                   fen.push(ch as char);
               }
           }
           if count_empty > 0 {
               write!(fen, "{}", count_empty).unwrap();
               count_empty = 0;
           }
           fen.push('/');
           println!();
       }
       fen.push_str(" w - - 0 1");
       fen
   }
   fn place_kings<R: Rng + ?Sized>(&mut self, rng: &mut R) {
       loop {
           let r1: i8 = rng.gen_range(0, 8);
           let c1: i8 = rng.gen_range(0, 8);
           let r2: i8 = rng.gen_range(0, 8);
           let c2: i8 = rng.gen_range(0, 8);
           if r1 != r2 && (r1 - r2).abs() > 1 && (c1 - c2).abs() > 1 {
               self.grid[r1 as usize][c1 as usize] = b'K';
               self.grid[r2 as usize][c2 as usize] = b'k';
               return;
           }
       }
   }
   fn place_pieces<R: Rng + ?Sized>(&mut self, rng: &mut R, pieces: &[u8], is_pawn: bool) {
       let num_to_place = rng.gen_range(0, pieces.len());
       for &piece in pieces.iter().take(num_to_place) {
           let mut r = rng.gen_range(0, 8);
           let mut c = rng.gen_range(0, 8);
           while self.grid[r][c] != EMPTY || (is_pawn && (r == 7 || r == 0)) {
               r = rng.gen_range(0, 8);
               c = rng.gen_range(0, 8);
           }
           self.grid[r][c] = piece;
       }
   }

}

fn main() {

   let b: Board = rand::random();
   println!("{}", b.fen());

}</lang>

Output:
b . . . . . . . 
. R P . . . . . 
n . . P . . . k 
p . . . P r . . 
P p . b . . . n 
. . P . . . . . 
K . . . . . . . 
. . . q . . . . 
b7/1RP5/n2P3k/p3Pr2/Pp1b3n/2P5/K7/3q4/ w - - 0 1

Scala

Output:

Best seen running in your browser Scastie (remote JVM).

<lang Scala>import scala.math.abs import scala.util.Random

object RandomFen extends App {

 val rand = new Random
 private def createFen = {
   val grid = Array.ofDim[Char](8, 8)
   def placeKings(grid: Array[Array[Char]]): Unit = {
     var r1, c1, r2, c2 = 0
     do {
       r1 = rand.nextInt(8)
       c1 = rand.nextInt(8)
       r2 = rand.nextInt(8)
       c2 = rand.nextInt(8)
     } while (r1 == r2 || abs(r1 - r2) <= 1 || abs(c1 - c2) <= 1)
     grid(r1)(c1) = 'K'
     grid(r2)(c2) = 'k'
   }
   def placePieces(grid: Array[Array[Char]],
                   pieces: String,
                   isPawn: Boolean): Unit = {
     val numToPlace = rand.nextInt(pieces.length)
     for (n <- 0 until numToPlace) {
       var r, c = 0
       do {
         r = rand.nextInt(8)
         c = rand.nextInt(8)
       } while (grid(r)(c) != 0 || (isPawn && (r == 7 || r == 0)))
       grid(r)(c) = pieces(n)
     }
   }
   def toFen(grid: Array[Array[Char]]) = {
     val fen = new StringBuilder
     var countEmpty = 0
     for (r <- grid.indices) {
       for (c <- grid.indices) {
         val ch = grid(r)(c)
         print(f"${if (ch == 0) '.' else ch}%2c ")
         if (ch == 0) countEmpty += 1
         else {
           if (countEmpty > 0) {
             fen.append(countEmpty)
             countEmpty = 0
           }
           fen.append(ch)
         }
       }
       if (countEmpty > 0) {
         fen.append(countEmpty)
         countEmpty = 0
       }
       fen.append("/")
       println()
     }
     fen.append(" w - - 0 1").toString
   }
   placeKings(grid)
   placePieces(grid, "PPPPPPPP", isPawn = true)
   placePieces(grid, "pppppppp", isPawn = true)
   placePieces(grid, "RNBQBNR", isPawn = false)
   placePieces(grid, "rnbqbnr", isPawn = false)
   toFen(grid)
 }
 println(createFen)

}</lang>

Yabasic

Translation of: C

<lang Yabasic>dim grid(8, 8)

sub placeKings()

   local r1, r2, c1, c2
   
   do
       r1 = int(ran(8))
       c1 = int(ran(8))
       r2 = int(ran(8))
       c2 = int(ran(8))
       if (r1 <> r2 and abs(r1 - r2) > 1 and abs(c1 - c2) > 1) then
           grid(r1, c1) = asc("K")
           grid(r2, c2) = asc("k")
           return
       end if
   loop

end sub

sub placePieces(pieces$, isPawn)

   local n, r, c, numToPlace
   
   numToPlace = int(ran(len(pieces$)))
   for n = 0 to numToPlace-1
       repeat
           r = int(ran(8))
           c = int(ran(8))
       until(not(grid(r, c) or (isPawn and (r = 7 or r = 0))))
       grid(r, c) = asc(mid$(pieces$, n, 1))
   next

end sub

sub toFen()

   local fen$, ch, r, c, countEmpty
   
   for r = 0 to 8-1
       for c = 0 to 8-1
           ch = grid(r, c)
           if ch then print chr$(ch); else print "."; end if
           if not ch then
               countEmpty = countEmpty + 1
           else
               if countEmpty then
                   fen$ = fen$ + chr$(countEmpty + 48)
                   countEmpty = 0
               end if
               fen$ = fen$ + chr$(ch)
           end if
       next
       if countEmpty then
           fen$ = fen$ + chr$(countEmpty + 48)
           countEmpty = 0
       end if
       fen$ = fen$ + "/"
       print
   next
   fen$ = fen$ + " w - - 0 1"
   print fen$

end sub

sub createFen()

   placeKings()
   placePieces("PPPPPPPP", TRUE)
   placePieces("pppppppp", TRUE)
   placePieces("RNBQBNR", FALSE)
   placePieces("rnbqbnr", FALSE)
   toFen()

end sub

createFen() </lang>

zkl

Translation of: Raku

<lang zkl>fcn pickFEN{

  # First we chose how many pieces to place: 2 to 32
  n := (0).random(2,33);

  # Then we pick $n squares: first n of shuffle (0,1,2,3...63)
  n = [0..63].walk().shuffle()[0,n]; 

  # We try to find suitable king positions on non-adjacent squares.
  # If we could not find any, we return recursively
  kings := Walker.cproduct(n,n).filter1(fcn([(a,b)]){  // Cartesian product
     a!=b and (a/8 - b/8).abs() or (a%8 - b%8).abs()>1
  }); # (a,b) on success, False on fail
  if(not kings) return(pickFEN());    // tail recursion

  # We make a list of pieces we can pick (apart from the kings)
  pieces,pnp,pnP := "p P n N b B r R q Q".split(" "), pieces-"p", pieces-"P";

  # We make a list of two king symbols to pick randomly a black or white king
  k := "K k".split(" ").shuffle();

  [0..63].apply('wrap(sq){  # look at each square
     if(kings.holds(sq)) k.pop();
     else if(n.holds(sq)){
        row,n,n2 := 7 - sq/8, (0).random(pieces.len()), (0).random(pnp.len());

if( row == 7) pnP[n2] // no white pawn in the promotion square else if(row == 0) pnp[n2] // no black pawn in the promotion square else pieces[n] // otherwise, any ole random piece

     }
     else "#"  // empty square
  })
  .pump(List,T(Void.Read,7),"".append,subst)  // chunkize into groups of 8 chars (1 row)
  .concat("/") + " w - - 0 1"

} fcn subst(str){ // replace "#" with count of #s

  re :=RegExp("#+");
  while(re.search(str,1)){ n,m:=re.matched[0]; str=String(str[0,n],m,str[n+m,*]) }
  str

}</lang> <lang zkl>do(5){ pickFEN().println() }</lang>

Output:
b3rQBr/n2b1Q1q/1R6/1BQRQ2n/RnB2r2/q3b1nQ/1BqB1bBQ/2q1Q3 w - - 0 1
b7/5qqB/qb3B2/8/3b4/Q1n3r1/3B2Q1/n6r w - - 0 1
r2R3N/Q1n5/1N6/1N1R1RBB/8/Rn1b1r2/3QbNN1/2n3rQ w - - 0 1
5b2/1R6/r4b1q/3Q4/8/8/8/5b2 w - - 0 1
8/1BQ5/8/1q6/1q6/3B1Rq1/5b2/3N3R w - - 0 1