Generate random chess position: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added Wren)
(→‎ZX Spectrum Basic: transposed board labels)
(22 intermediate revisions by 12 users not shown)
Line 17: Line 17:
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.
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.
<br><br>
<br><br>

=={{header|11l}}==
{{trans|Python}}

<syntaxhighlight lang="11l">V board = [[‘ ’] * 8] * 8
V piece_list = [‘R’, ‘N’, ‘B’, ‘Q’, ‘P’]

F place_kings(&brd)
L
V (rank_white, file_white, rank_black, file_black) = (random:(0 .. 7), random:(0 .. 7), random:(0 .. 7), random:(0 .. 7))
V diff_list = [abs(rank_white - rank_black), abs(file_white - file_black)]
I sum(diff_list) > 2 | Set(diff_list) == Set([0, 2])
(brd[rank_white][file_white], brd[rank_black][file_black]) = (Char(‘K’), Char(‘k’))
L.break

F pawn_on_promotion_square(pc, pr)
I pc == ‘P’ & pr == 0
R 1B
E I pc == ‘p’ & pr == 7
R 1B
R 0B

F populate_board(&brd, wp, bp)
L(x) 2
Int piece_amount
[Char] pieces
I x == 0
piece_amount = wp
pieces = :piece_list
E
piece_amount = bp
pieces = :piece_list.map(s -> s.lowercase())
L piece_amount != 0
V (piece_rank, piece_file) = (random:(0 .. 7), random:(0 .. 7))
V piece = random:choice(pieces)
I brd[piece_rank][piece_file] == ‘ ’ & pawn_on_promotion_square(piece, piece_rank) == 0B
brd[piece_rank][piece_file] = piece
piece_amount--

F fen_from_board(brd)
V fen = ‘’
L(x) brd
V n = 0
L(y) x
I y == ‘ ’
n++
E
I n != 0
fen ‘’= String(n)
fen ‘’= y
n = 0
I n != 0
fen ‘’= String(n)
fen ‘’= I fen.count(‘/’) < 7 {‘/’} E ‘’
fen ‘’= " w - - 0 1\n"
R fen

V (piece_amount_white, piece_amount_black) = (random:(0 .. 15), random:(0 .. 15))
place_kings(&board)
populate_board(&board, piece_amount_white, piece_amount_black)
print(fen_from_board(board))
L(x) board
print(‘[’x.map(c -> ‘'’c‘'’).join(‘, ’)‘]’)</syntaxhighlight>

{{out}}
<pre>
8/8/p7/4n3/3K4/2BbN1k1/4Q3/4R3 w - - 0 1

[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
['p', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', 'n', ' ', ' ', ' ']
[' ', ' ', ' ', 'K', ' ', ' ', ' ', ' ']
[' ', ' ', 'B', 'b', 'N', ' ', 'k', ' ']
[' ', ' ', ' ', ' ', 'Q', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', 'R', ' ', ' ', ' ']
</pre>

=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE BOARDSIZE="64"
DEFINE EMPTY="'."

BYTE FUNC AbsDist(BYTE a,b)
IF a>b THEN RETURN (a-b) FI
RETURN (b-a)

BYTE FUNC GetPiece(BYTE ARRAY board BYTE x,y)
RETURN (board(x+y*8))

PROC PutPiece(BYTE ARRAY board BYTE x,y,piece)
board(x+y*8)=piece
RETURN

PROC PrintBoard(BYTE ARRAY board)
BYTE i,j,c

FOR j=0 TO 7
DO
FOR i=0 TO 7
DO
c=GetPiece(board,i,j)
Put(c)
OD
PutE()
OD
RETURN

PROC Append(CHAR ARRAY s CHAR c)
s(0)==+1
s(s(0))=c
RETURN

PROC ExportToFen(BYTE ARRAY board CHAR ARRAY fen)
CHAR ARRAY s=" w - - 0 1"
INT x,y
BYTE count,p

fen(0)=0
FOR y=0 TO 7
DO
x=0
WHILE x<8
DO
count=0
WHILE x<8 AND GetPiece(board,x,y)=EMPTY
DO
x==+1 count==+1
OD
IF count>0 THEN
Append(fen,'0+count)
ELSE
p=GetPiece(board,x,y)
Append(fen,p)
x==+1
FI
OD
IF y<7 THEN
Append(fen,'/)
FI
OD

FOR x=1 TO s(0)
DO
Append(fen,s(x))
OD
RETURN

PROC PutKings(BYTE ARRAY board)
BYTE x1,y1,x2,y2
DO
x1=Rand(8) y1=Rand(8)
x2=Rand(8) y2=Rand(8)
IF AbsDist(x1,x2)>1 AND AbsDist(y1,y2)>1 THEN
PutPiece(board,x1,y1,'K)
PutPiece(board,x2,y2,'k)
RETURN
FI
OD
RETURN

PROC PutPieces(BYTE ARRAY board CHAR ARRAY pieces)
BYTE i,x,y,p

FOR i=1 TO pieces(0)
DO
p=pieces(i)
DO
x=Rand(8)
IF p='P OR p='p THEN
y=Rand(6)+1
ELSE
y=Rand(8)
FI
UNTIL GetPiece(board,x,y)=EMPTY
OD
PutPiece(board,x,y,p)
OD
RETURN

PROC Generate(BYTE ARRAY board CHAR ARRAY pieces)
SetBlock(board,BOARDSIZE,EMPTY)
PutKings(board)
PutPieces(board,pieces)
RETURN

PROC Test(CHAR ARRAY pieces)
BYTE ARRAY board(BOARDSIZE)
CHAR ARRAY fen(256)

Generate(board,pieces)
PrintBoard(board)
ExportToFen(board,fen)
PrintE(fen) PutE()
RETURN

PROC Main()
Test("PPPPPPPPBBNNQRRppppppppbbnnqrr")
Test("PPBNQRppbnqr")
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Generate_random_chess_position.png Screenshot from Atari 8-bit computer]
<pre>
.Q...R..
nnp.P.Pq
pPpP.B.k
...prNp.
P.p.B.P.
.K.pb.pP
.P...NRb
..r.....
1Q3R2/nnp1P1Pq/pPpP1B1k/3prNp1/P1p1B1P1/1K1pb1pP/1P3NRb/2r5 w - - 0 1

........
....n.bp
k...p...
...B....
r.PP....
q..K...R
.....Q.N
........
8/4n1bp/k3p3/3B4/r1PP4/q2K3R/5Q1N/8 w - - 0 1
</pre>


=={{header|C}}==
=={{header|C}}==
{{trans|Java}}
{{trans|Java}}
<lang c>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>
#include <math.h>
#include <math.h>
#include <string.h>
#include <string.h>
Line 103: Line 325:
createFen();
createFen();
return 0;
return 0;
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 121: Line 343:
=={{header|C++}}==
=={{header|C++}}==


<lang cpp>
<syntaxhighlight lang="cpp">
#include <ctime>
#include <ctime>
#include <iostream>
#include <iostream>
Line 197: Line 419:
return 0;
return 0;
}
}
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 224: Line 446:
=={{header|Crystal}}==
=={{header|Crystal}}==
{{trans|Ruby}}
{{trans|Ruby}}
<lang ruby>def hasNK(board, a, b)
<syntaxhighlight lang="ruby">def hasNK(board, a, b)
(-1..1).each do |g|
(-1..1).each do |g|
(-1..1).each do |f|
(-1..1).each do |f|
Line 281: Line 503:


# Simpler for same output
# Simpler for same output
8.times{ |row| puts board[row*8..row*8 + 7].join("") }</lang>
8.times{ |row| puts board[row*8..row*8 + 7].join("") }</syntaxhighlight>
{{out}}<pre>1n1P3p/1p1k2Pp/1ppPPprn/2rP4/KNRQ2b1/2Bp1PP1/3qPBN1/2Rp4 w - - 0 1
{{out}}<pre>1n1P3p/1p1k2Pp/1ppPPprn/2rP4/KNRQ2b1/2Bp1PP1/3qPBN1/2Rp4 w - - 0 1
.n.P...p
.n.P...p
Line 294: Line 516:


=={{header|Factor}}==
=={{header|Factor}}==
<lang factor>USING: combinators.short-circuit grouping io kernel math
<syntaxhighlight lang="factor">USING: combinators.short-circuit grouping io kernel math
math.parser math.ranges math.vectors prettyprint random
math.parser math.ranges math.vectors prettyprint random
sequences sets splitting.monotonic strings ;
sequences sets splitting.monotonic strings ;
Line 348: Line 570:
position [ position. ] [ position>fen print ] bi ;
position [ position. ] [ position>fen print ] bi ;


MAIN: random-chess-position-demo</lang>
MAIN: random-chess-position-demo</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 364: Line 586:
=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==
{{trans|Yabasic}}
{{trans|Yabasic}}
<lang freebasic>
<syntaxhighlight lang="freebasic">
Dim Shared As Byte grid(8, 8), r, c
Dim Shared As Byte grid(8, 8), r, c


Line 436: Line 658:
toFen()
toFen()
Sleep
Sleep
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 448: Line 670:
. . . N . B n .
. . . N . B n .
8/6p1/2kP4/5b2/p1p2pK1/1Q2p1r1/1q6/3N1Bn1/ w - - 0 1
8/6p1/2kP4/5b2/p1p2pK1/1Q2p1r1/1q6/3N1Bn1/ w - - 0 1
</pre>




=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">begin globals
short grid(8, 8) // 1-8
end globals


local fn PlaceKings
short r1, r2, c1, c2
while (YES)
r1 = rnd(8)
c1 = rnd(8)
r2 = rnd(8)
c2 = rnd(8)
if ( abs( r1 - r2 ) > 1 or abs( c1 - c2) > 1 )
grid(r1, c1) = asc("K")
grid(r2, c2) = asc("k")
exit fn
end if
wend
end fn


local fn PlacePieces( pieces$ as Str255, isPawn as BOOL )
short n, r, c, numToPlace
numToPlace = rnd( len$(pieces$) )
for n = 1 to numToPlace
do
r = rnd(8)
c = rnd(8)
if isPawn == YES and mid$( pieces$, n, 1 ) == "p" and r = 8 then exit fn
if isPawn == YES and mid$( pieces$, n, 1 ) == "P" and r = 1 then exit fn
until not( ( grid(r, c) != 0 ) or ( isPawn and ( r == 8 or r == 1 ) ) )
grid(r, c) = asc( mid$( pieces$, n, 1 ) )
next
end fn


local fn ToFen
Str255 fen$
short ch, r, c, countEmpty = 0
CFStringRef pieceStr
for r = 1 to 8
for c = 1 to 8
ch = grid(r, c)
select (ch)
case 107 : pieceStr = @" ♚" // Black King
case 75 : pieceStr = @" ♔" // White King
case 112 : pieceStr = @" ♟" // Black Pawn
case 80 : pieceStr = @" ♙" // White Pawn
case 114 : pieceStr = @" ♜" // Black Rook
case 82 : pieceStr = @" ♖" // White Rook
case 110 : pieceStr = @" ♞" // Black Knight
case 78 : pieceStr = @" ♘" // White Knight
case 98 : pieceStr = @" ♝" // Black Bishop
case 66 : pieceStr = @" ♗" // White Bishop
case 113 : pieceStr = @" ♛" // Black Queen
case 81 : pieceStr = @" ♕" // White Queen
end select
if ( ch )
print pieceStr,
else
print @" .",
end if
if ( ch == 0 )
countEmpty++
else
if ( countEmpty > 0 )
fen$ = fen$ + chr$(countEmpty + 48)
countEmpty = 0
end if
fen$ = fen$ + chr$(ch)
end if
next
if ( countEmpty > 0 )
fen$ = fen$ + chr$(countEmpty + 48)
countEmpty = 0
end if
fen$ = fen$ + "/"
print
next
fen$ = fen$ + " w - - 0 1"
fen$ = mid$( fen$, 8, len$(fen$) )
print
text @"Menlo", 14, fn ColorText, fn ColorClear, NSTextAlignmentLeft, 10
print fen$
end fn

local fn CreateFen
fn PlaceKings
fn PlacePieces( "PPPPPPPP", YES )
fn PlacePieces( "pppppppp", YES )
fn PlacePieces( "RNBQBNR", NO )
fn PlacePieces( "rnbqbnr", NO )
fn ToFen
end fn


randomize

window 1, @"Random Chess Position", ( 0, 0, 700, 400 )

text @"Menlo", 32, fn ColorText, fn ColorClear, NSTextAlignmentLeft, 10

fn CreateFen

HandleEvents</syntaxhighlight>
{{output}}
<pre style="font-size: 32px">
♘ . . . . . ♛ .
♞ . . ♟ . . ♙ .
♔ ♙ . . . . . .
. . ♝ . ♝ . . ♟
. . ♙ . ♜ . ♙ .
♙ . ♞ . . ♗ . ♙
♚ ♙ ♖ . . . . ♜
. . . . . . . .
</pre>
<pre style="font-size: 18px">
N5q1/n2p2P1/KP6/2b1b2p/2P1r1P1/P1n2B1P/kPR4r/8/ w - - 0 1
</pre>
</pre>


=={{header|Go}}==
=={{header|Go}}==
{{trans|Java}}
{{trans|Java}}
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 544: Line 902:
rand.Seed(time.Now().UnixNano())
rand.Seed(time.Now().UnixNano())
fmt.Println(createFen())
fmt.Println(createFen())
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 561: Line 919:
=={{header|Haskell}}==
=={{header|Haskell}}==
Module RandomChess
Module RandomChess
<lang haskell>{-# LANGUAGE LambdaCase, TupleSections #-}
<syntaxhighlight lang="haskell">{-# LANGUAGE LambdaCase, TupleSections #-}


module RandomChess
module RandomChess
Line 781: Line 1,139:


getBoard :: State BoardState ChessBoard
getBoard :: State BoardState ChessBoard
getBoard = gets (sortBy boardSort . board)</lang>
getBoard = gets (sortBy boardSort . board)</syntaxhighlight>


Module Main
Module Main
<lang haskell>module Main where
<syntaxhighlight lang="haskell">module Main where


import Control.Monad.State (evalState)
import Control.Monad.State (evalState)
Line 812: Line 1,170:
main = BoardState emptyBoard <$> newStdGen >>= draw . evalState buildBoard
main = BoardState emptyBoard <$> newStdGen >>= draw . evalState buildBoard
where
where
buildBoard = placeKings >> placePawns >> placeRemaining >> getBoard</lang>
buildBoard = placeKings >> placePawns >> placeRemaining >> getBoard</syntaxhighlight>
{{out}}
{{out}}
Run 1
Run 1
Line 864: Line 1,222:
Implementation:
Implementation:


<lang J>getlayout=:3 :0
<syntaxhighlight lang="j">getlayout=:3 :0
whilst. NB. first two positions are non-adjacent kings
whilst. NB. first two positions are non-adjacent kings
(0{pos) e. (1{pos)+(,-)1 7 8 9
(0{pos) e. (1{pos)+(,-)1 7 8 9
Line 896: Line 1,254:
)
)


randfen=:b2fen@randboard</lang>
randfen=:b2fen@randboard</syntaxhighlight>


Example use:
Example use:


<lang J> randfen''
<syntaxhighlight lang="j"> randfen''
q6J/1pb1p1p1/1Jq2k2/4p1Pp/1pP5/1K2Bp2/5p2/1P4P1 w - - 0 1
q6J/1pb1p1p1/1Jq2k2/4p1Pp/1pP5/1K2Bp2/5p2/1P4P1 w - - 0 1
randfen''
randfen''
Line 912: Line 1,270:
randfen''
randfen''
b1Q1Bb1J/j1N1PpK1/PpB1P1Pp/2pp2PN/3nnk2/3J4/P6P/1N2Qb1J w - - 0 1
b1Q1Bb1J/j1N1PpK1/PpB1P1Pp/2pp2PN/3nnk2/3J4/P6P/1N2Qb1J w - - 0 1
</syntaxhighlight>
</lang>


=={{header|Java}}==
=={{header|Java}}==
<lang java>import static java.lang.Math.abs;
<syntaxhighlight lang="java">import static java.lang.Math.abs;
import java.util.Random;
import java.util.Random;


Line 991: Line 1,349:
return fen.append(" w - - 0 1").toString();
return fen.append(" w - - 0 1").toString();
}
}
}</lang>
}</syntaxhighlight>
<pre>(lol, the black king is in check, it couldn't possibly be white's turn)
<pre>(lol, the black king is in check, it couldn't possibly be white's turn)
. . . . . B . .
. . . . . B . .
Line 1,002: Line 1,360:
. . . . . . B K
. . . . . . B K
5B2/P1P5/2k1R3/p1Pp4/7Q/P7/1N2rNP1/6BK/ w - - 0 1</pre>
5B2/P1P5/2k1R3/p1Pp4/7Q/P7/1N2rNP1/6BK/ w - - 0 1</pre>

=={{header|JavaScript}}==
<syntaxhighlight lang="javascript">
Array.prototype.shuffle = function() {
for (let i = this.length - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1));
[this[i], this[j]] = [this[j], this[i]];
}
}

function randomFEN() {

let board = [];
for (let x = 0; x < 8; x++) board.push('. . . . . . . .'.split(' '));

function getRandPos() {
return [Math.floor(Math.random() * 8), Math.floor(Math.random() * 8)];
}

function isOccupied(pos) {
return board[pos[0]][pos[1]] != '.';
}

function isAdjacent(pos1, pos2) {
if (pos1[0] == pos2[0] || pos1[0] == pos2[0]-1 || pos1[0] == pos2[0]+1)
if (pos1[1] == pos2[1] || pos1[1] == pos2[1]-1 || pos1[1] == pos2[1]+1)
return true;
return false;
}

// place kings
let wk, bk;
do { wk = getRandPos(); bk = getRandPos(); }
while (isAdjacent(wk, bk));
board[wk[0]][wk[1]] = 'K';
board[bk[0]][bk[1]] = 'k';

// get peaces
let peaces = [];
let names = 'PRNBQ';
function pick() {
for (x = 1; x < Math.floor(Math.random() * 32); x++)
peaces.push(names[Math.floor(Math.random() * names.length)]);
}
pick();
names = names.toLowerCase();
pick();
peaces.shuffle();

// place peaces
while (peaces.length > 0) {
let p = peaces.shift(), pos;
// paws: cannot be placed in bottom or top row
if (p == 'p' || p == 'P')
do { pos = getRandPos() }
while (isOccupied(pos) || pos[0] == 0 || pos[0] == 7);
// everything else
else do { pos = getRandPos(); } while (isOccupied(pos));
board[pos[0]][pos[1]] = p;
}

// write FEN
let fen = [];
for (x = 0; x < board.length; x++) {
let str ='', buf = 0;
for (let y = 0; y < board[x].length; y++)
if (board[x][y] == '.') buf++;
else {
if (buf > 0) { str += buf; buf = 0; }
str += board[x][y];
}
if (buf > 0) str += buf;
fen.push(str);
}
fen = fen.join('/') + ' w - - 0 1';
console.table(board); // for demonstrating purpose
return fen;
}

// example
console.log(randomFEN());
</syntaxhighlight>
{{out}}
<pre>
X 0 1 2 3 4 5 6 7
0 . . . . Q . . .
1 . . . . Q . . .
2 . . . p . . . .
3 . . . . . . . R
4 . r r R . . . .
5 . . P . . . . .
6 . . . . . k . .
7 . . R . . . . K
4Q3/4Q3/3p4/7R/1rrR4/2P5/5k2/2R4K w - - 0 1
</pre>


=={{header|Julia}}==
=={{header|Julia}}==
Line 1,007: Line 1,460:


'''Module''':
'''Module''':
<lang julia>module Chess
<syntaxhighlight lang="julia">module Chess


using Printf
using Printf
Line 1,061: Line 1,514:
printgrid(grid) = println(join((join(grid[r, :], ' ') for r in 1:size(grid, 1)), '\n'))
printgrid(grid) = println(join((join(grid[r, :], ' ') for r in 1:size(grid, 1)), '\n'))


end # module Chess</lang>
end # module Chess</syntaxhighlight>


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


{{out}}
{{out}}
Line 1,080: Line 1,533:
=={{header|Kotlin}}==
=={{header|Kotlin}}==
{{trans|Java}}
{{trans|Java}}
<lang scala>// version 1.2.0
<syntaxhighlight lang="scala">// version 1.2.0


import java.util.Random
import java.util.Random
Line 1,158: Line 1,611:
fun main(args: Array<String>) {
fun main(args: Array<String>) {
println(createFen())
println(createFen())
}</lang>
}</syntaxhighlight>


Sample output:
Sample output:
Line 1,172: Line 1,625:
8/K7/1Pp1b1PP/1pP3P1/1p1q1pPP/3k3b/3np3/2r5/ w - - 0 1
8/K7/1Pp1b1PP/1pP3P1/1p1q1pPP/3k3b/3np3/2r5/ w - - 0 1
</pre>
</pre>

=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">g = ConstantArray["", {8, 8}];
While[Norm@First@Differences[r = RandomChoice[Tuples[Range[8], 2], 2]] <= Sqrt[2], Null];
g = ReplacePart[g, {r[[1]] -> "K", r[[2]] -> "k"}];
avail = Position[g, "", {2}];
n = RandomInteger[{2, 14}];
rls = Thread[RandomSample[avail, n] -> RandomChoice[Characters@"NBRQnbrq", n]];
g = ReplacePart[g, rls];
avail = RandomSample[DeleteCases[Position[g, "", {2}], {8, _}], RandomInteger[{2, 8}]];
g = ReplacePart[g, Thread[avail -> "P"]];
avail = RandomSample[DeleteCases[Position[g, "", {2}], {1, _}], RandomInteger[{2, 8}]];
g = ReplacePart[g, Thread[avail -> "p"]];
g //= Map[Split];
g = g /. (x : {"" ..}) :> ToString[Length[x]];
g //= Map[StringJoin@*Flatten];
g = StringRiffle[Reverse[g], "/"];
g = g <> " w - - 0 1";
g</syntaxhighlight>
{{out}}
<pre>2N5/1P3P2/p1P3P1/5q2/8/5k1K/1p3p2/8 w - - 0 1</pre>


=={{header|Nim}}==
=={{header|Nim}}==
{{trans|Kotlin}}
{{trans|Kotlin}}
<lang Nim>import random
<syntaxhighlight lang="nim">import random


type
type
Line 1,279: Line 1,753:


randomize()
randomize()
echo createFen()</lang>
echo createFen()</syntaxhighlight>


{{out}}
{{out}}
Line 1,293: Line 1,767:
=={{header|Perl}}==
=={{header|Perl}}==
{{trans|Raku}}
{{trans|Raku}}
<lang perl>use strict;
<syntaxhighlight lang="perl">use strict;
use warnings;
use warnings;
use feature 'say';
use feature 'say';
Line 1,347: Line 1,821:
}
}


say gen_FEN();</lang>
say gen_FEN();</syntaxhighlight>
{{out}}
{{out}}
<pre>p5Nq/1nn5/3N2bp/PRBkQr2/1QB1Pn2/Q5pK/1NRb2rN/p1R2r1N w - - 0 1</pre>
<pre>p5Nq/1nn5/3N2bp/PRBkQr2/1QB1Pn2/Q5pK/1NRb2rN/p1R2r1N w - - 0 1</pre>


=={{header|Phix}}==
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>constant show_bad_boards = false
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>

<span style="color: #008080;">constant</span> <span style="color: #000000;">show_bad_boards</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
string board

<span style="color: #004080;">string</span> <span style="color: #000000;">board</span>
function fen()
string res = ""
<span style="color: #008080;">function</span> <span style="color: #000000;">fen</span><span style="color: #0000FF;">()</span>
for i=1 to 64 by 8 do
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
integer empty = 0
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">64</span> <span style="color: #008080;">by</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span>
for j=i to i+7 do
<span style="color: #004080;">integer</span> <span style="color: #000000;">empty</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
if board[j]='.' then
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">i</span> <span style="color: #008080;">to</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">7</span> <span style="color: #008080;">do</span>
empty += 1
<span style="color: #008080;">if</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'.'</span> <span style="color: #008080;">then</span>
else
<span style="color: #000000;">empty</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
if empty then
res &= empty+'0'
<span style="color: #008080;">else</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">empty</span> <span style="color: #008080;">then</span>
empty = 0
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">empty</span><span style="color: #0000FF;">+</span><span style="color: #008000;">'0'</span>
end if
<span style="color: #000000;">empty</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
res &= board[j]
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if empty then
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
res &= empty+'0'
<span style="color: #008080;">if</span> <span style="color: #000000;">empty</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">empty</span><span style="color: #0000FF;">+</span><span style="color: #008000;">'0'</span>
if i<57 then res &= '/' end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;"><</span><span style="color: #000000;">57</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">'/'</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
res &= " w - - 0 1"
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return res
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">" w - - 0 1"</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function p15()
string res = "pppppppprrnnbbq"
<span style="color: #008080;">function</span> <span style="color: #000000;">p15</span><span style="color: #0000FF;">()</span>
-- promote 0..8 pawns
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"pppppppprrnnbbq"</span>
for i=1 to rand(9)-1 do
<span style="color: #000080;font-style:italic;">-- promote 0..8 pawns</span>
res[i] = res[rand(7)+8]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">7</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">8</span><span style="color: #0000FF;">]</span>
res = shuffle(res)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return res
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">shuffle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function kings_adjacent(sequence p12)
integer {p1,p2} = sq_sub(p12,1),
<span style="color: #008080;">function</span> <span style="color: #000000;">kings_adjacent</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">p12</span><span style="color: #0000FF;">)</span>
row_diff = abs(floor(p1/8)-floor(p2/8)),
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span>
col_diff = abs(mod(p1,8)-mod(p2,8))
<span style="color: #000000;">row_diff</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)-</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p2</span><span style="color: #0000FF;">/</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)),</span>
return row_diff<=1 and col_diff<=1
<span style="color: #000000;">col_diff</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)-</span><span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">))</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">row_diff</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">col_diff</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
integer lp
procedure show_board()
<span style="color: #004080;">integer</span> <span style="color: #000000;">lp</span>
printf(1,"%d pieces\n%s",{lp,join_by(board,1,8,"")})
<span style="color: #008080;">procedure</span> <span style="color: #000000;">show_board</span><span style="color: #0000FF;">()</span>
end procedure
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d pieces\n%s"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">lp</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join_by</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)})</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
while true do
string pieces = "Kk"& -- kings
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
upper(p15())[1..rand(16)-1]& -- white
<span style="color: #004080;">string</span> <span style="color: #000000;">pieces</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"Kk"</span><span style="color: #0000FF;">&</span> <span style="color: #000080;font-style:italic;">-- kings</span>
lower(p15())[1..rand(16)-1] -- black
<span style="color: #7060A8;">upper</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p15</span><span style="color: #0000FF;">())[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">16</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]&</span> <span style="color: #000080;font-style:italic;">-- white</span>
lp = length(pieces)
<span style="color: #7060A8;">lower</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p15</span><span style="color: #0000FF;">())[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">16</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">-- black</span>
sequence p = tagset(64)
<span style="color: #000000;">lp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pieces</span><span style="color: #0000FF;">)</span>
p = shuffle(p)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">64</span><span style="color: #0000FF;">)</span>
board = repeat('.',64)
<span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">shuffle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
for i=1 to lp do board[p[i]] = pieces[i] end for
<span style="color: #000000;">board</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">64</span><span style="color: #0000FF;">)</span>

<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">lp</span> <span style="color: #008080;">do</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pieces</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
if kings_adjacent(p[1..2]) then
if show_bad_boards then show_board() end if
<span style="color: #008080;">if</span> <span style="color: #000000;">kings_adjacent</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
puts(1,"kings adjacent - reshuffle\n\n")
<span style="color: #008080;">if</span> <span style="color: #000000;">show_bad_boards</span> <span style="color: #008080;">then</span> <span style="color: #000000;">show_board</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
else
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"kings adjacent - reshuffle\n\n"</span><span style="color: #0000FF;">)</span>
-- check no pawn will be on a promotion square,
<span style="color: #008080;">else</span>
-- and (above spec) no pawn has gone backwards:
<span style="color: #000080;font-style:italic;">-- check no pawn will be on a promotion square,
if find('p',lower(board[1..8]&board[57..64]))=0 then exit end if
-- and (above spec) no pawn has gone backwards:</span>
if show_bad_boards then show_board() end if
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'p'</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">lower</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">8</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">57</span><span style="color: #0000FF;">..</span><span style="color: #000000;">64</span><span style="color: #0000FF;">]))=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
puts(1,"pawn on rank 1/8 - reshuffle\n\n")
<span style="color: #008080;">if</span> <span style="color: #000000;">show_bad_boards</span> <span style="color: #008080;">then</span> <span style="color: #000000;">show_board</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"pawn on rank 1/8 - reshuffle\n\n"</span><span style="color: #0000FF;">)</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
show_board()
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
printf(1,"\n%s\n",{fen()})</lang>
<span style="color: #000000;">show_board</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">fen</span><span style="color: #0000FF;">()})</span>
<!--</syntaxhighlight>-->
To allow pawns that have "moved backwards", replace the inner test with
To allow pawns that have "moved backwards", replace the inner test with
<code>if not find('P',board[1..8]) and not find('p',board[57..64]) then exit end if</code><br>
<code>if not find('P',board[1..8]) and not find('p',board[57..64]) then exit end if</code><br>
Line 1,466: Line 1,943:


=={{header|PicoLisp}}==
=={{header|PicoLisp}}==
<lang PicoLisp>(load "@lib/simul.l")
<syntaxhighlight lang="picolisp">(load "@lib/simul.l")
(seed (in "/dev/urandom" (rd 8)))
(seed (in "/dev/urandom" (rd 8)))
(de pieceN (P)
(de pieceN (P)
Line 1,549: Line 2,026:
(gt0 C)
(gt0 C)
(link C) ) ) ) ) ) ) )
(link C) ) ) ) ) ) ) )
(println (pack (glue "/" *FEN) " w - - 0 1"))</lang>
(println (pack (glue "/" *FEN) " w - - 0 1"))</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,564: Line 2,041:


=={{header|Python}}==
=={{header|Python}}==
<lang python>
<syntaxhighlight lang="python">
import random
import random


Line 1,630: Line 2,107:
#entry point
#entry point
start()
start()
</syntaxhighlight>
</lang>
{{out}}<pre>
{{out}}<pre>
1p5k/1B4P1/1KN4R/nR3Nrb/Q1NrnpP1/7R/3PP3/1P5P w - - 0 1
1p5k/1B4P1/1KN4R/nR3Nrb/Q1NrnpP1/7R/3PP3/1P5P w - - 0 1
Line 1,645: Line 2,122:


=={{header|R}}==
=={{header|R}}==
<lang rsplus>
<syntaxhighlight lang="rsplus">
place_kings <- function(brd){
place_kings <- function(brd){
###
###
Line 1,743: Line 2,220:


generate_fen()
generate_fen()
</syntaxhighlight>
</lang>
{{out}}
{{out}}
Line 1,760: Line 2,237:
=={{header|Raku}}==
=={{header|Raku}}==
(formerly Perl 6)
(formerly Perl 6)
<lang perl6>sub pick-FEN {
<syntaxhighlight lang="raku" line>sub pick-FEN {
# First we chose how many pieces to place
# First we chose how many pieces to place
my $n = (2..32).pick;
my $n = (2..32).pick;
Line 1,793: Line 2,270:
}
}


say pick-FEN();</lang>
say pick-FEN();</syntaxhighlight>
{{out}}
{{out}}
<pre>q2n1n2/1Qpk3Q/1r3bP1/1b1b4/2pRBR2/4P1bN/2R3K1/N1r2rPB w - - 0 1</pre>
<pre>q2n1n2/1Qpk3Q/1r3bP1/1b1b4/2pRBR2/4P1bN/2R3K1/N1r2rPB w - - 0 1</pre>
Line 1,804: Line 2,281:
If the number of chessboards specified is negative, then the number of chess pieces for each side will be random.
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.
This version also allows any number of chessboards to be displayed &nbsp; (the default is to only display one chessboard).
<lang rexx>/*REXX program generates a chess position (random pieces & positions) in a FEN format.*/
<syntaxhighlight 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*/
parse arg seed CBs . /*obtain optional arguments from the CL*/
if datatype(seed,'W') then call random ,,seed /*SEED given for RANDOM repeatability? */
if datatype(seed,'W') then call random ,,seed /*SEED given for RANDOM repeatability? */
Line 1,846: Line 2,323:
@.r.f= x /*put random piece. */
@.r.f= x /*put random piece. */
!.r.f= ux; return /* " " " upper*/
!.r.f= ux; return /* " " " upper*/
end /*#*/ /*#: isn't incremented.*/</lang>
end /*#*/ /*#: isn't incremented.*/</syntaxhighlight>
Some older REXXes don't have a &nbsp; '''changestr''' &nbsp; BIF, &nbsp; so one is included here: &nbsp; ───► &nbsp; [[CHANGESTR.REX]]. <br><br>
Some older REXXes don't have a &nbsp; '''changestr''' &nbsp; BIF, &nbsp; so one is included here: &nbsp; ───► &nbsp; [[CHANGESTR.REX]]. <br><br>
'''output''' &nbsp; showing five chess positions (starting with a specific position by seeding the &nbsp; '''random''' &nbsp; BIF with &nbsp; '''96'''),
'''output''' &nbsp; showing five chess positions (starting with a specific position by seeding the &nbsp; '''random''' &nbsp; BIF with &nbsp; '''96'''),
Line 1,913: Line 2,390:


=={{header|Ruby}}==
=={{header|Ruby}}==
<lang ruby>
<syntaxhighlight lang="ruby">
def hasNK( board, a, b )
def hasNK( board, a, b )
for g in -1 .. 1
for g in -1 .. 1
Line 1,969: Line 2,446:
puts
puts
end
end
</syntaxhighlight>
</lang>
{{out}}<pre>
{{out}}<pre>
1bN1RK2/1Pp1pQbP/p2PpP2/8/1pkNP3/P1r1Pp1p/Bn1RPp1r/3qB3 w - - 0 1
1bN1RK2/1Pp1pQbP/p2PpP2/8/1pkNP3/P1r1Pp1p/Bn1RPp1r/3qB3 w - - 0 1
Line 1,983: Line 2,460:


=={{header|Rust}}==
=={{header|Rust}}==
<lang Rust>use std::fmt::Write;
<syntaxhighlight lang="rust">use std::fmt::Write;


use rand::{Rng, distributions::{Distribution, Standard}};
use rand::{Rng, distributions::{Distribution, Standard}};
Line 2,069: Line 2,546:
let b: Board = rand::random();
let b: Board = rand::random();
println!("{}", b.fen());
println!("{}", b.fen());
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 2,084: Line 2,561:
=={{header|Scala}}==
=={{header|Scala}}==
{{Out}}Best seen running in your browser [https://scastie.scala-lang.org/zdG9NQ4YSaShFRU7AS31GA Scastie (remote JVM)].
{{Out}}Best seen running in your browser [https://scastie.scala-lang.org/zdG9NQ4YSaShFRU7AS31GA Scastie (remote JVM)].
<lang Scala>import scala.math.abs
<syntaxhighlight lang="scala">import scala.math.abs
import scala.util.Random
import scala.util.Random


Line 2,156: Line 2,633:
println(createFen)
println(createFen)


}</lang>
}</syntaxhighlight>

=={{header|Typescript}}==
{{trans|Java}}
<syntaxhighlight lang="typescript">
class Fen {

public createFen() {
let grid: string[][];

grid = [];

for (let r = 0; r < 8; r++) {
grid[r] = [];
for (let c = 0; c < 8; c++) {
grid[r][c] = "0";
}
}

this.placeKings(grid);
this.placePieces(grid, "PPPPPPPP", true);
this.placePieces(grid, "pppppppp", true);
this.placePieces(grid, "RNBQBNR", false);
this.placePieces(grid, "rnbqbnr", false);
return this.toFen(grid);
}

private placeKings(grid: string[][]): void {
let r1, c1, r2, c2: number;
while (true) {
r1 = Math.floor(Math.random() * 8);
c1 = Math.floor(Math.random() * 8);
r2 = Math.floor(Math.random() * 8);
c2 = Math.floor(Math.random() * 8);
if (r1 != r2 && Math.abs(r1 - r2) > 1 && Math.abs(c1 - c2) > 1) {
break;
}
}
grid[r1][c1] = "K";
grid[r2][c2] = "k";
}

private placePieces(grid: string[][], pieces: string, isPawn: boolean): void {
let numToPlace: number = Math.floor(Math.random() * pieces.length);
for (let n = 0; n < numToPlace; n++) {
let r, c: number;
do {
r = Math.floor(Math.random() * 8);
c = Math.floor(Math.random() * 8);
} while (grid[r][c] != "0" || (isPawn && (r == 7 || r == 0)));

grid[r][c] = pieces.charAt(n);
}
}

private toFen(grid: string[][]): string {
let result: string = "";
let countEmpty: number = 0;
for (let r = 0; r < 8; r++) {
for (let c = 0; c < 8; c++) {
let char: string = grid[r][c];
if (char == "0") {
countEmpty++;
} else {
if (countEmpty > 0) {
result += countEmpty;
countEmpty = 0;
}
result += char;
}
}
if (countEmpty > 0) {
result += countEmpty;
countEmpty = 0;
}
result += "/";
}
return result += " w - - 0 1";
}

}

let fen: Fen = new Fen();
console.log(fen.createFen());
</syntaxhighlight>
{{out}}
<pre>
5B2/2KbN3/pr6/pp6/5P2/5k2/1Rp5/1nQ5/ w - - 0 1
</pre>


=={{header|Wren}}==
=={{header|Wren}}==
{{trans|Kotlin}}
{{trans|Kotlin}}
{{libheader|Wren-fmt}}
{{libheader|Wren-fmt}}
<lang ecmascript>import "random" for Random
<syntaxhighlight lang="wren">import "random" for Random
import "/fmt" for Fmt
import "./fmt" for Fmt


var rand = Random.new()
var rand = Random.new()
Line 2,233: Line 2,798:
}
}


System.print(createFen.call())</lang>
System.print(createFen.call())</syntaxhighlight>


{{out}}
{{out}}
Line 2,251: Line 2,816:
=={{header|Yabasic}}==
=={{header|Yabasic}}==
{{trans|C}}
{{trans|C}}
<lang Yabasic>dim grid(8, 8)
<syntaxhighlight lang="yabasic">dim grid(8, 8)
sub placeKings()
sub placeKings()
Line 2,320: Line 2,885:
createFen()
createFen()
</syntaxhighlight>
</lang>


=={{header|zkl}}==
=={{header|zkl}}==
{{trans|Raku}}
{{trans|Raku}}
<lang zkl>fcn pickFEN{
<syntaxhighlight lang="zkl">fcn pickFEN{
# First we chose how many pieces to place: 2 to 32
# First we chose how many pieces to place: 2 to 32
n := (0).random(2,33);
n := (0).random(2,33);
Line 2,361: Line 2,926:
while(re.search(str,1)){ n,m:=re.matched[0]; str=String(str[0,n],m,str[n+m,*]) }
while(re.search(str,1)){ n,m:=re.matched[0]; str=String(str[0,n],m,str[n+m,*]) }
str
str
}</lang>
}</syntaxhighlight>
<lang zkl>do(5){ pickFEN().println() }</lang>
<syntaxhighlight lang="zkl">do(5){ pickFEN().println() }</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 2,370: Line 2,935:
5b2/1R6/r4b1q/3Q4/8/8/8/5b2 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</pre>
8/1BQ5/8/1q6/1q6/3B1Rq1/5b2/3N3R w - - 0 1</pre>

=={{header|ZX Spectrum Basic}}==
A few traps to prevent positions with the wrong number of pieces (not required by the task description but it's worth the effort if we want to use this in a modular way later).

<syntaxhighlight lang="zxbasic">
1 DEF FN r(v)=INT (RND*v)+1: REM we'll be using this a lot here for setup, although in real chess it should barely be used at all...

10 GO SUB 9400: REM modularity is pretty much vital in making Sinclair BASIC legible
20 GO SUB 9100
30 GO SUB 9200
40 GO SUB 8800
50 GO TO 9500

8799 REM Material assignment
8800 LET b=FN r(16)-1: REM give black and white a random number of additional pieces each
8810 LET w=FN r(16)-1
8820 FOR x=1 TO b
8830 LET p=LEN b$
8840 LET k=FN r(p)
8850 LET r=FN r(8): REM defined functions can have the same name as variables
8860 LET f=FN r(8)
8870 IF d$(r,f)<>" " THEN GO TO 8840: REM piece already there
8880 IF b$(k)="p" AND (r=1 OR r=8) THEN GO TO 8840: REM pawn on 1st or 8th rank trapping
8890 LET d$(r,f)=b$(k)
8900 IF k=p THEN LET b$=b$(1 TO k-1): GO TO 8920
8910 LET b$=b$( TO k-1)+b$(k+1 TO )
8920 NEXT x
8930 FOR x=1 TO w: REM now doing for white what we just did for black, could be tidied
8940 LET p=LEN w$
8950 LET k=FN r(p)
8960 LET r=FN r(8)
8970 LET f=FN r(8)
8980 IF d$(r,f)<>" " THEN GO TO 8950
8990 IF w$(k)="P" AND (r=1 OR r=8) THEN GO TO 8950
9000 LET d$(r,f)=w$(k)
9010 IF k=p THEN LET w$=w$(1 TO k-1): GO TO 9030
9020 LET w$=w$( TO k-1)+w$(k+1 TO )
9030 NEXT x
9040 RETURN

9099 REM Kings
9100 LET rw=FN r(8)
9110 LET fw=FN r(8)
9120 LET d$(rw,fw)="K"
9130 LET rb=FN r(8)
9140 LET fb=FN r(8)
9150 LET rd=ABS (rw-rb): REM find distance between kings
9160 LET fd=ABS (fd-fb)
9170 IF rd<2 AND fd<2 THEN GO TO 9130
9180 LET d$(rb,fb)="k"
9190 RETURN

9199 REM Promotions
9200 FOR b=1 TO 8
9210 LET v=FN r(30): REM 30% chance of promoting each pawn
9220 IF v=1 THEN LET b$(7+b)="q": GO TO 9260
9230 IF v<3 THEN LET b$(7+b)="r": GO TO 9260
9240 IF v<7 THEN LET b$(7+b)="n": GO TO 9260
9250 IF v<10 THEN LET b$(7+b)="b"
9260 NEXT b
9270 FOR w=1 TO 8
9280 LET v=FN r(30)
9290 IF v=1 THEN LET w$(7+w)="Q": GO TO 9330
9300 IF v<3 THEN LET w$(7+w)="R": GO TO 9330
9310 IF v<7 THEN LET w$(7+w)="N": GO TO 9330
9320 IF v<10 THEN LET w$(7+w)="B"
9330 NEXT b
9340 RETURN

9399 REM Setup
9400 LET b$="qrrnnbbpppppppp": REM we'll set the kings specifically later
9410 LET w$="QRRNNBBPPPPPPPP"
9420 DIM d$(8,8): REM string arrays are autofilled with spaces; this defines the board area
9430 LET f$=""
9440 LET g$=""
9450 RETURN

9499 REM Board
9500 FOR x=1 TO 8
9510 PRINT 9-x;: REM rank number
9520 FOR y=1 TO 8
9530 PRINT INVERSE (((x+y)/2)<>INT ((x+y)/2));d$(x,y);: REM evaluates to 1, a black square, if rank number + file number, read from the top left, is odd; the bottom right square is 8 + 8 = 16 = even = white, conforming to "white to the right" standards
9540 LET f$=f$+d$(x,y): REM building the FEN
9550 NEXT y
9560 PRINT ': REM newline
9570 LET f$=f$+"/"
9580 NEXT x
9590 PRINT " abcdefgh"''
9600 LET k=LEN f$: REM f$ now contains the full string of the board, but we need to count the spaces into numbers
9610 LET t=0: REM counter variable
9620 FOR x=1 TO k
9630 LET t$=f$(x)
9640 IF t$<>" " AND t=0 THEN GO TO 9670: REM not empty and not currently running through blank spaces
9650 IF t$=" " THEN LET t=t+1: GO TO 9670: REM number of blanks in this batch so far
9660 LET f$(x-1)=STR$ t: LET t=0: REM not empty, so a blank space sequence must have ended; insert the counter into the string (STR$ turns the numeric value into its string representation)
9670 NEXT x
9680 FOR x=1 TO k: REM now strip the spaces out
9690 IF f$(x)<>" " THEN LET g$=g$+f$(x)
9700 NEXT x
9710 LET g$=g$( TO LEN g$-1)+" w - - 0 1": REM knock off the final /
9720 PRINT g$</syntaxhighlight>

{{out}}
Inverted squares aren't shown here.
<pre>
8..b.....
7N.....R.
6.Q.P..PB
5....R...
4P..R.Nk.
3PRP.....
2K..P....
1........
abcdefgh

2B5/N5R1/1Q1P2PB/4R3/P2R1Nk1/PRP
5/K2P4/8 w - - 0 1

0 OK, 9720:1
</pre>

Revision as of 22:30, 21 February 2024

Task
Generate random chess position
You are encouraged to solve this task according to the task description, using any language you may know.
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.

11l

Translation of: Python
V board = [[‘ ’] * 8] * 8
V piece_list = [‘R’, ‘N’, ‘B’, ‘Q’, ‘P’]

F place_kings(&brd)
   L
      V (rank_white, file_white, rank_black, file_black) = (random:(0 .. 7), random:(0 .. 7), random:(0 .. 7), random:(0 .. 7))
      V diff_list = [abs(rank_white - rank_black), abs(file_white - file_black)]
      I sum(diff_list) > 2 | Set(diff_list) == Set([0, 2])
         (brd[rank_white][file_white], brd[rank_black][file_black]) = (Char(‘K’), Char(‘k’))
         L.break

F pawn_on_promotion_square(pc, pr)
   I pc == ‘P’ & pr == 0
      R 1B
   E I pc == ‘p’ & pr == 7
      R 1B
   R 0B

F populate_board(&brd, wp, bp)
   L(x) 2
      Int piece_amount
      [Char] pieces
      I x == 0
         piece_amount = wp
         pieces = :piece_list
      E
         piece_amount = bp
         pieces = :piece_list.map(s -> s.lowercase())
      L piece_amount != 0
         V (piece_rank, piece_file) = (random:(0 .. 7), random:(0 .. 7))
         V piece = random:choice(pieces)
         I brd[piece_rank][piece_file] == ‘ ’ & pawn_on_promotion_square(piece, piece_rank) == 0B
            brd[piece_rank][piece_file] = piece
            piece_amount--

F fen_from_board(brd)
   V fen = ‘’
   L(x) brd
      V n = 0
      L(y) x
         I y == ‘ ’
            n++
         E
            I n != 0
               fen ‘’= String(n)
            fen ‘’= y
            n = 0
      I n != 0
         fen ‘’= String(n)
      fen ‘’= I fen.count(‘/’) < 7 {‘/’} E ‘’
   fen ‘’= " w - - 0 1\n"
   R fen

V (piece_amount_white, piece_amount_black) = (random:(0 .. 15), random:(0 .. 15))
place_kings(&board)
populate_board(&board, piece_amount_white, piece_amount_black)
print(fen_from_board(board))
L(x) board
   print(‘[’x.map(c -> ‘'’c‘'’).join(‘, ’)‘]’)
Output:
8/8/p7/4n3/3K4/2BbN1k1/4Q3/4R3 w - - 0 1

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

Action!

DEFINE BOARDSIZE="64"
DEFINE EMPTY="'."

BYTE FUNC AbsDist(BYTE a,b)
  IF a>b THEN RETURN (a-b) FI
RETURN (b-a)

BYTE FUNC GetPiece(BYTE ARRAY board BYTE x,y)
RETURN (board(x+y*8))

PROC PutPiece(BYTE ARRAY board BYTE x,y,piece)
  board(x+y*8)=piece
RETURN

PROC PrintBoard(BYTE ARRAY board)
  BYTE i,j,c

  FOR j=0 TO 7
  DO
    FOR i=0 TO 7
    DO
      c=GetPiece(board,i,j)
      Put(c)
    OD
    PutE()
  OD
RETURN

PROC Append(CHAR ARRAY s CHAR c)
  s(0)==+1
  s(s(0))=c
RETURN

PROC ExportToFen(BYTE ARRAY board CHAR ARRAY fen)
  CHAR ARRAY s=" w - - 0 1"
  INT x,y
  BYTE count,p

  fen(0)=0
  FOR y=0 TO 7
  DO
    x=0
    WHILE x<8
    DO
      count=0
      WHILE x<8 AND GetPiece(board,x,y)=EMPTY
      DO
        x==+1 count==+1
      OD
      IF count>0 THEN
        Append(fen,'0+count)
      ELSE
        p=GetPiece(board,x,y)
        Append(fen,p)
        x==+1
      FI
    OD
    IF y<7 THEN
      Append(fen,'/)
    FI
  OD

  FOR x=1 TO s(0)
  DO
    Append(fen,s(x))
  OD
RETURN

PROC PutKings(BYTE ARRAY board)
  BYTE x1,y1,x2,y2
  DO
    x1=Rand(8) y1=Rand(8)
    x2=Rand(8) y2=Rand(8)
    IF AbsDist(x1,x2)>1 AND AbsDist(y1,y2)>1 THEN
      PutPiece(board,x1,y1,'K)
      PutPiece(board,x2,y2,'k)
      RETURN
    FI
  OD
RETURN

PROC PutPieces(BYTE ARRAY board CHAR ARRAY pieces)
  BYTE i,x,y,p

  FOR i=1 TO pieces(0)
  DO
    p=pieces(i)
    DO
      x=Rand(8)
      IF p='P OR p='p THEN
        y=Rand(6)+1
      ELSE
        y=Rand(8)
      FI
    UNTIL GetPiece(board,x,y)=EMPTY
    OD
    PutPiece(board,x,y,p)
  OD
RETURN

PROC Generate(BYTE ARRAY board CHAR ARRAY pieces)
  SetBlock(board,BOARDSIZE,EMPTY)
  PutKings(board)
  PutPieces(board,pieces)
RETURN

PROC Test(CHAR ARRAY pieces)
  BYTE ARRAY board(BOARDSIZE)
  CHAR ARRAY fen(256)

  Generate(board,pieces)
  PrintBoard(board)
  ExportToFen(board,fen)
  PrintE(fen) PutE()
RETURN

PROC Main()
  Test("PPPPPPPPBBNNQRRppppppppbbnnqrr")
  Test("PPBNQRppbnqr")
RETURN
Output:

Screenshot from Atari 8-bit computer

.Q...R..
nnp.P.Pq
pPpP.B.k
...prNp.
P.p.B.P.
.K.pb.pP
.P...NRb
..r.....
1Q3R2/nnp1P1Pq/pPpP1B1k/3prNp1/P1p1B1P1/1K1pb1pP/1P3NRb/2r5 w - - 0 1

........
....n.bp
k...p...
...B....
r.PP....
q..K...R
.....Q.N
........
8/4n1bp/k3p3/3B4/r1PP4/q2K3R/5Q1N/8 w - - 0 1

C

Translation of: Java
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#define TRUE 1
#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;
}
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++

#include <ctime>
#include <iostream>
#include <string>
#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;
}
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
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

# 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

# Simpler for same output
8.times{ |row| puts board[row*8..row*8 + 7].join("") }
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

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
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
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
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



FutureBasic

begin globals
short grid(8, 8)  // 1-8
end globals


local fn PlaceKings
  short r1, r2, c1, c2
  
  while (YES)
    r1 = rnd(8)
    c1 = rnd(8)
    r2 = rnd(8)
    c2 = rnd(8)
    if ( abs( r1 - r2 ) > 1 or abs( c1 - c2) > 1 )
      grid(r1, c1) = asc("K")
      grid(r2, c2) = asc("k")
      exit fn
    end if
  wend
end fn


local fn  PlacePieces( pieces$ as Str255, isPawn as BOOL )
  short n, r, c, numToPlace
  
  numToPlace = rnd( len$(pieces$) )
  for n = 1 to numToPlace
    do
      r = rnd(8)
      c = rnd(8)
      if isPawn == YES and mid$( pieces$, n, 1 ) == "p" and r = 8 then exit fn
      if isPawn == YES and mid$( pieces$, n, 1 ) == "P" and r = 1 then exit fn
    until not( ( grid(r, c) != 0 ) or ( isPawn and ( r == 8 or r == 1 ) ) )
    grid(r, c) = asc( mid$( pieces$, n, 1 ) )
  next
end fn


local fn ToFen
  Str255      fen$
  short        ch, r, c, countEmpty = 0
  CFStringRef pieceStr
  
  for r = 1 to 8
    for c = 1 to 8
      ch = grid(r, c)
      
      select (ch)
        
        case 107 : pieceStr = @" ♚" // Black King
        case  75 : pieceStr = @" ♔" // White King
          
        case 112 : pieceStr = @" ♟" // Black Pawn
        case  80 : pieceStr = @" ♙" // White Pawn
          
        case 114 : pieceStr = @" ♜" // Black Rook
        case  82 : pieceStr = @" ♖" // White Rook
          
        case 110 : pieceStr = @" ♞" // Black Knight
        case  78 : pieceStr = @" ♘" // White Knight
          
        case  98 : pieceStr = @" ♝" // Black Bishop
        case  66 : pieceStr = @" ♗" // White Bishop
          
        case 113 : pieceStr = @" ♛" // Black Queen
        case  81 : pieceStr = @" ♕" // White Queen
          
      end select
      
      if ( ch   )
        print pieceStr,
      else
        print @" .",
      end if
      if ( ch == 0 )
        countEmpty++
      else
        if ( countEmpty > 0 )
          fen$ = fen$ + chr$(countEmpty + 48)
          countEmpty = 0
        end if
        fen$ = fen$ + chr$(ch)
      end if
    next
    if ( countEmpty > 0 )
      fen$ = fen$ + chr$(countEmpty + 48)
      countEmpty = 0
    end if
    fen$ = fen$ + "/"
    print
  next
  fen$ = fen$ + " w - - 0 1"
  fen$ = mid$( fen$, 8, len$(fen$) )
  print
  text @"Menlo", 14, fn ColorText, fn ColorClear, NSTextAlignmentLeft, 10
  print fen$
end fn

local fn CreateFen
  fn PlaceKings
  fn PlacePieces( "PPPPPPPP", YES )
  fn PlacePieces( "pppppppp", YES )
  fn PlacePieces( "RNBQBNR",   NO )
  fn PlacePieces( "rnbqbnr",   NO )
  fn ToFen
end fn


randomize

window 1, @"Random Chess Position", ( 0, 0, 700, 400 )

text @"Menlo", 32, fn ColorText, fn ColorClear, NSTextAlignmentLeft, 10

fn CreateFen

HandleEvents
Output:
 ♘  .  .  .  .  .  ♛  . 
 ♞  .  .  ♟  .  .  ♙  . 
 ♔  ♙  .  .  .  .  .  . 
 .  .  ♝  .  ♝  .  .  ♟ 
 .  .  ♙  .  ♜  .  ♙  . 
 ♙  .  ♞  .  .  ♗  .  ♙ 
 ♚  ♙  ♖  .  .  .  .  ♜ 
 .  .  .  .  .  .  .  . 
N5q1/n2p2P1/KP6/2b1b2p/2P1r1P1/P1n2B1P/kPR4r/8/ w - - 0 1

Go

Translation of: Java
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())
}
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

Module RandomChess

{-# LANGUAGE LambdaCase, TupleSections #-}

module RandomChess
( placeKings
, placePawns
, placeRemaining
, emptyBoard
, toFen
, ChessBoard
, Square (..)
, BoardState (..)
, getBoard
)
where

import Control.Monad.State (State, get, gets, put)
import Data.List (find, sortBy)
import System.Random (Random, RandomGen, StdGen, random, randomR)

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)]

data BoardState = BoardState { board :: ChessBoard , generator :: StdGen }

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 = randomR (minBound, maxBound)

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

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 = fmap (EmptySquare,) . (,) <$> ['a'..'h'] <*> [1..8]

replaceSquareByPos :: (Square, Pos) -> ChessBoard -> ChessBoard
replaceSquareByPos e@(_, p) = fmap (\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 (x1, y1) (x2, y2) =
  let upOrDown    = (pred y1 == y2 || succ y1 == y2)
      leftOrRight = (pred x1 == x2 || succ x1 == x2)
  in  (x2 == x1 && upOrDown)
        || (pred x1 == x2 && upOrDown)
        || (succ x1 == x2 && upOrDown)
        || (leftOrRight && y1 == y2)

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 (_, (x1, y1)) (_, (x2, y2)) | y1 < y2  = GT
                                      | y1 > y2  = LT
                                      | y1 == y2 = compare x1 x2

toFen :: ChessBoard -> String
toFen [] = " w - - 0 1" <> []
toFen b = scanRow (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

-- State functions
withStateGen :: (StdGen -> (a, StdGen)) -> State BoardState a
withStateGen f = do
  currentState <- get
  let gen1 = generator currentState
  let (x, gen2) = f gen1
  put (currentState {generator = gen2})
  pure x

randomPos :: State BoardState Pos
randomPos = do
  boardState <- gets board
  chr <- withStateGen (randomR ('a', 'h'))
  num <- withStateGen (randomR (1, 8))
  let pos = (chr, num)
  if isPosOccupied pos boardState then
    randomPos
  else
    pure pos

randomPiece :: State BoardState Square
randomPiece = ChessPiece <$> withStateGen random <*> withStateGen random

placeKings :: State BoardState ()
placeKings = do
  currentState <- get
  p1 <- randomPos
  p2 <- randomPos
  if p1 `isAdjacent` p2 || p1 == p2
    then placeKings
    else do
      let updatedBoard = replaceSquareByPos (ChessPiece King White, p1) $
            replaceSquareByPos (ChessPiece King Black, p2) (board currentState)
      put currentState { board = updatedBoard }

placePawns :: State BoardState ()
placePawns = withStateGen (randomR (1, 16)) >>= go
  where
    go :: Int -> State BoardState ()
    go 0 = pure ()
    go n = do
      currentState <- get
      pos <- randomPos
      color <- withStateGen random
      let pawn = ChessPiece Pawn color
      let currentBoard = board currentState
      if promoted color == snd pos || isPosOccupied pos currentBoard ||
                           enpassant color == snd pos || firstPos color == snd pos
        then go n
        else do
          put currentState { board = replaceSquareByPos (pawn, pos) currentBoard }
          go $ pred n
    promoted White = 8
    promoted Black = 1
    enpassant White = 5
    enpassant Black = 4
    firstPos White = 1
    firstPos Black = 8

placeRemaining :: State BoardState ()
placeRemaining =
  withStateGen (randomR (5, sum $ fmap snd remaining)) >>= go remaining
  where
    remaining = filter (\case
                         (ChessPiece King _, _) -> False
                         (ChessPiece Pawn _, _) -> False
                         (EmptySquare, _) -> False
                         _ -> True)
                        fullBoard

    go :: PieceCount -> Int -> State BoardState ()
    go _ 0 = pure ()
    go remaining n = do
      currentState <- get
      let currentBoard = board currentState
      position <- randomPos
      piece <- randomPiece
      if not (isPermitted piece) || isPosOccupied position currentBoard
        then go remaining n
        else do
          let updatedBoard = replaceSquareByPos (piece, position) currentBoard
          put currentState { board = updatedBoard }
          go (consume piece remaining) (pred n)
      where
        isPermitted p =
          case find ((==p) . fst) remaining of
            Just (_, count) -> count > 0
            Nothing         -> False
        consume p'' = fmap (\(p, c) -> if p == p'' then (p, pred c) else (p, c))

getBoard :: State BoardState ChessBoard
getBoard = gets (sortBy boardSort . board)

Module Main

module Main where

import Control.Monad.State (evalState)
import RandomChess (ChessBoard, emptyBoard, placeKings, getBoard,
                    placePawns, placeRemaining, toFen, BoardState (..))
import System.Random (newStdGen)

draw :: ChessBoard -> IO ()
draw b = do
  showXAxis >> drawLine
  mapM_ (\b@(p, (x,y)) ->
          case x of 'h' -> putStr (" | " <> show p <> " | " <> show y <> "\n") >> drawLine
                    'a' -> putStr (show y <> " | " <> show p)
                    _   -> putStr (" | " <> show p)
        )
    b
  showXAxis >> putStrLn "" >> putStrLn (toFen b)

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

main :: IO ()
main = BoardState emptyBoard <$> newStdGen >>= draw . evalState buildBoard
  where
    buildBoard = placeKings >> placePawns >> placeRemaining >> getBoard
Output:

Run 1

    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

2rN2n1/PppKPP1P/3q4/N6p/2P2BP1/pQrp1Bk1/n3P1Pp/2R5/ w - - 0 1

Run 2

    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

4k3/pKP5/p1rp4/2p5/8/1p2P2q/4p2N/RR2b3/ w - - 0 1

etc...

J

Implementation:

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

Example use:

   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

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();
    }
}
(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

JavaScript

Array.prototype.shuffle = function() {
  for (let i = this.length - 1; i > 0; i--) {
    let j = Math.floor(Math.random() * (i + 1));
    [this[i], this[j]] = [this[j], this[i]];
  }
}

function randomFEN() {

  let board = [];
  for (let x = 0; x < 8; x++) board.push('. . . . . . . .'.split(' '));

  function getRandPos() {
    return [Math.floor(Math.random() * 8), Math.floor(Math.random() * 8)];
  }

  function isOccupied(pos) {
    return board[pos[0]][pos[1]] != '.';
  }

  function isAdjacent(pos1, pos2) {
    if (pos1[0] == pos2[0] || pos1[0] == pos2[0]-1 || pos1[0] == pos2[0]+1)
    if (pos1[1] == pos2[1] || pos1[1] == pos2[1]-1 || pos1[1] == pos2[1]+1)
      return true;
    return false;
  }

  // place kings
  let wk, bk;
  do { wk = getRandPos(); bk = getRandPos(); }
  while (isAdjacent(wk, bk));
  board[wk[0]][wk[1]] = 'K';
  board[bk[0]][bk[1]] = 'k';

  // get peaces
  let peaces = [];
  let names = 'PRNBQ';
  function pick() {
    for (x = 1; x < Math.floor(Math.random() * 32); x++)
      peaces.push(names[Math.floor(Math.random() * names.length)]);
  }
  pick();
  names = names.toLowerCase();
  pick();
  peaces.shuffle();

  // place peaces
  while (peaces.length > 0) {
    let p = peaces.shift(), pos;
    // paws: cannot be placed in bottom or top row
    if (p == 'p' || p == 'P')
      do { pos = getRandPos() }
      while (isOccupied(pos) || pos[0] == 0 || pos[0] == 7);
    // everything else
    else do { pos = getRandPos(); } while (isOccupied(pos));
    board[pos[0]][pos[1]] = p;
  }

  // write FEN
  let fen = [];
  for (x = 0; x < board.length; x++) {
    let str ='', buf = 0;
    for (let y = 0; y < board[x].length; y++)
      if (board[x][y] == '.') buf++;
      else {
        if (buf > 0) { str += buf; buf = 0; }
        str += board[x][y];
      }
    if (buf > 0) str += buf;
    fen.push(str);
  }
  fen = fen.join('/') + ' w - - 0 1';
  console.table(board); // for demonstrating purpose
  return fen;
}

// example
console.log(randomFEN());
Output:
X  0  1  2  3  4  5  6  7
0  .  .  .  .  Q  .  .  .
1  .  .  .  .  Q  .  .  .
2  .  .  .  p  .  .  .  .
3  .  .  .  .  .  .  .  R
4  .  r  r  R  .  .  .  .
5  .  .  P  .  .  .  .  .
6  .  .  .  .  .  k  .  .
7  .  .  R  .  .  .  .  K
4Q3/4Q3/3p4/7R/1rrR4/2P5/5k2/2R4K w - - 0 1

Julia

Translation of: Kotlin

Module:

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

Main:

grid = fill(' ', 8, 8)
Chess.randposition!(grid)
Chess.printgrid(grid)
Output:
    ♕     ♞ ♗
♖ ♙ ♔ ♙ ♖ ♜   ♙
      ♟   ♙ ♙ ♜
♘ ♝ ♙ ♙ ♟
  ♙     ♚   ♝ ♟
    ♟ ♟     ♗ ♟
♙     ♞   ♟   ♟
        ♘   ♛

Kotlin

Translation of: Java
// 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())
}

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 

Mathematica/Wolfram Language

g = ConstantArray["", {8, 8}];
While[Norm@First@Differences[r = RandomChoice[Tuples[Range[8], 2], 2]] <= Sqrt[2], Null];
g = ReplacePart[g, {r[[1]] -> "K", r[[2]] -> "k"}];
avail = Position[g, "", {2}];
n = RandomInteger[{2, 14}];
rls = Thread[RandomSample[avail, n] -> RandomChoice[Characters@"NBRQnbrq", n]];
g = ReplacePart[g, rls];
avail = RandomSample[DeleteCases[Position[g, "", {2}], {8, _}], RandomInteger[{2, 8}]];
g = ReplacePart[g, Thread[avail -> "P"]];
avail = RandomSample[DeleteCases[Position[g, "", {2}], {1, _}], RandomInteger[{2, 8}]];
g = ReplacePart[g, Thread[avail -> "p"]];
g //= Map[Split];
g = g /. (x : {"" ..}) :> ToString[Length[x]];
g //= Map[StringJoin@*Flatten];
g = StringRiffle[Reverse[g], "/"];
g = g <> " w - - 0 1";
g
Output:
2N5/1P3P2/p1P3P1/5q2/8/5k1K/1p3p2/8 w - - 0 1

Nim

Translation of: Kotlin
import random

type

  Piece {.pure.} = enum
    None
    WhiteBishop = ('B', "♗")
    WhiteKing = ('K', "♔")
    WhiteKnight = ('N', "♘")
    WhitePawn = ('P', "♙")
    WhiteQueen = ('Q', "♕")
    WhiteRook = ('R', "♖")
    BlackBishop = ('b', "♝")
    BlackKing = ('k', "♚")
    BlackKnight = ('n', "♞")
    BlackPawn = ('p', "♟")
    BlackQueen = ('q', "♛")
    BlackRook = ('r', "♜")

  Color {.pure.} = enum White, Black

  Grid = array[8, array[8, Piece]]

const
  # White pieces except king and pawns.
  WhitePieces = [WhiteQueen, WhiteRook, WhiteRook, WhiteBishop,
                 WhiteBishop, WhiteKnight, WhiteKnight]

  # Black pieces except king and pawns.
  BlackPieces = [BlackQueen, BlackRook, BlackRook, BlackBishop,
                 BlackBishop, BlackKnight, BlackKnight]

proc placeKings(grid: var Grid) =
  while true:
    let r1 = rand(7)
    let c1 = rand(7)
    let r2 = rand(7)
    let c2 = rand(7)
    if r1 != r2 and abs(r1 - r2) > 1 and abs(c1 - c2) > 1:
      grid[r1][c1] = WhiteKing
      grid[r2][c2] = BlackKing
      break

proc placePawns(grid: var Grid; color: Color) =
  let piece = if color == White: WhitePawn else: BlackPawn
  let numToPlace = rand(8)
  for n in 0..<numToPlace:
    var r, c: int
    while true:
      r = rand(7)
      c = rand(7)
      if grid[r][c] == None and r notin {0, 7}: break
    grid[r][c] = piece


proc placePieces(grid: var Grid; color: Color) =
  var pieces = if color == White: WhitePieces else: BlackPieces
  pieces.shuffle()
  let numToPlace = rand(7)
  for n in 0..<numToPlace:
    var r, c: int
    while true:
      r = rand(7)
      c = rand(7)
      if grid[r][c] == None: break
    grid[r][c] = pieces[n]


proc toFen(grid: Grid): string =
  var countEmpty = 0
  for r in 0..7:
    for c in 0..7:
      let piece = grid[r][c]
      if piece == None:
        stdout.write " . "
        inc countEmpty
      else:
        stdout.write ' ' & $piece & ' '
        if countEmpty > 0:
          result.add $countEmpty
          countEmpty = 0
        result.add chr(ord(piece))

    if countEmpty > 0:
      result.add $countEmpty
      countEmpty = 0

    result.add '/'
    echo ""

  result.add " w - - 0 1"


proc createFen(): string =
  var grid: Grid
  grid.placeKings()
  grid.placePawns(White)
  grid.placePawns(Black)
  grid.placePieces(White)
  grid.placePieces(Black)
  result = grid.toFen()


randomize()
echo createFen()
Output:
 .  .  .  .  .  .  .  . 
 .  .  .  .  ♟  .  .  . 
 ♟  .  .  .  ♟  .  .  . 
 .  .  .  .  .  ♙  ♟  . 
 .  ♙  .  .  .  ♚  .  . 
 .  ♙  .  .  .  .  ♗  ♘ 
 .  ♟  .  .  ♙  .  .  . 
 .  .  .  ♔  .  .  .  . 

Perl

Translation of: Raku
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 = <p P n N b B r R q Q>;
    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();
Output:
p5Nq/1nn5/3N2bp/PRBkQr2/1QB1Pn2/Q5pK/1NRb2rN/p1R2r1N w - - 0 1

Phix

with javascript_semantics
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()})

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

(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"))
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

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)

#entry point
start()
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']

R

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()
Output:
        [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
   [1,] " "  " "  "n"  " "  " "  "r"  " "  " " 
   [2,] " "  " "  " "  " "  " "  "B"  " "  " " 
   [3,] " "  " "  " "  " "  "k"  "p"  " "  " " 
   [4,] " "  "r"  " "  "q"  " "  " "  "b"  " " 
   [5,] " "  " "  " "  "r"  "n"  " "  "r"  " " 
   [6,] " "  " "  " "  "Q"  "b"  "r"  " "  "K" 
   [7,] " "  "n"  " "  " "  " "  "b"  "p"  " " 
   [8,] " "  " "  " "  " "  " "  " "  " "  " " 
   2n2r2/5B2/4kp2/1r1q2b1/3rn1r1/3Qbr1K/1n3bp1/8 w - - 0 1

Raku

(formerly Perl 6)

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 = <p P n N b B r R q Q>;

    # 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();
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   (the default is to only display one chessboard).

/*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          /*append the board file.   */
             end   /*f*/
           say $                                             /*display the board rank.  */
             do e=8  for 8  by -1;  $= changestr( copies(., e),  $, e)    /* . ≡ filler.*/
             end   /*e*/
           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.*/

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

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
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

use std::fmt::Write;

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

const EMPTY: u8 = b'.';

#[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());
}
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).

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)

}

Typescript

Translation of: Java
class Fen {

    public createFen() {
        let grid: string[][];

        grid = [];

        for (let r = 0; r < 8; r++) {
            grid[r] = [];
            for (let c = 0; c < 8; c++) {
                grid[r][c] = "0";
            }
        }

        this.placeKings(grid);
        this.placePieces(grid, "PPPPPPPP", true);
        this.placePieces(grid, "pppppppp", true);
        this.placePieces(grid, "RNBQBNR", false);
        this.placePieces(grid, "rnbqbnr", false);
        return this.toFen(grid);
    }

    private placeKings(grid: string[][]): void {
        let r1, c1, r2, c2: number;
        while (true) {
            r1 = Math.floor(Math.random() * 8);
            c1 = Math.floor(Math.random() * 8);
            r2 = Math.floor(Math.random() * 8);
            c2 = Math.floor(Math.random() * 8);
            if (r1 != r2 && Math.abs(r1 - r2) > 1 && Math.abs(c1 - c2) > 1) {
                break;
            }
        }
        grid[r1][c1] = "K";
        grid[r2][c2] = "k";
    }

    private placePieces(grid: string[][], pieces: string, isPawn: boolean): void {
        let numToPlace: number = Math.floor(Math.random() * pieces.length);
        for (let n = 0; n < numToPlace; n++) {
            let r, c: number;
            do {
                r = Math.floor(Math.random() * 8);
                c = Math.floor(Math.random() * 8);
            } while (grid[r][c] != "0" || (isPawn && (r == 7 || r == 0)));

            grid[r][c] = pieces.charAt(n);
        }
    }

    private toFen(grid: string[][]): string {
        let result: string = "";
        let countEmpty: number = 0;
        for (let r = 0; r < 8; r++) {
            for (let c = 0; c < 8; c++) {
                let char: string = grid[r][c];
                if (char == "0") {
                    countEmpty++;
                } else {
                    if (countEmpty > 0) {
                        result += countEmpty;
                        countEmpty = 0;
                    }
                    result += char;
                }
            }
            if (countEmpty > 0) {
                result += countEmpty;
                countEmpty = 0;
            }
            result += "/";
        }
        return result += " w - - 0 1";
    }

}

let fen: Fen = new Fen();
console.log(fen.createFen());
Output:
5B2/2KbN3/pr6/pp6/5P2/5k2/1Rp5/1nQ5/ w - - 0 1

Wren

Translation of: Kotlin
Library: Wren-fmt
import "random" for Random
import "./fmt" for Fmt

var rand = Random.new()

var grid = List.filled(8, null)
for (i in 0..7) grid[i] = List.filled(9, ".")

var placeKings = Fn.new {
    while (true) {
        var r1 = rand.int(8)
        var c1 = rand.int(8)
        var r2 = rand.int(8)
        var c2 = rand.int(8)
        if (r1 != r2 && (r1 - r2).abs > 1 && (c1 - c2).abs > 1) {
            grid[r1][c1] = "K"
            grid[r2][c2] = "k"
            return
        }
    }
}

var placePieces = Fn.new { |pieces, isPawn|
    var numToPlace = rand.int(pieces.count)
    for (n in 0...numToPlace) {
        var r
        var c
        while (true) {
            r = rand.int(8)
            c = rand.int(8)
            if (grid[r][c] == "." && !(isPawn && (r == 7 || r == 0))) break
        }
        grid[r][c] = pieces[n]
    }
}

var toFen = Fn.new {
    var fen = ""
    var countEmpty = 0
    for (r in 0..7) {
        for (c in 0..7) {
            var ch = grid[r][c]
            Fmt.write("$2s ", ch)
            if (ch == ".") {
                countEmpty = countEmpty + 1
            } else {
                if (countEmpty > 0) {
                    fen = fen + countEmpty.toString
                    countEmpty = 0
                }
                fen = fen + ch
            }
        }
        if (countEmpty > 0) {
            fen = fen + countEmpty.toString
            countEmpty = 0
        }
        fen = fen + "/"
        System.print()
    }
    return fen + " w - - 0 1"
}

var createFen = Fn.new {
    placeKings.call()
    placePieces.call("PPPPPPPP", true)
    placePieces.call("pppppppp", true)
    placePieces.call("RNBQBNR", false)
    placePieces.call("rnbqbnr", false)
    return toFen.call()
}

System.print(createFen.call())
Output:

Sample position:

 .  .  .  N  .  Q  R  . 
 .  .  .  .  .  r  p  . 
 K  .  .  .  p  .  P  . 
 .  .  .  .  .  .  .  . 
 .  .  p  .  .  .  k  . 
 p  .  .  .  .  .  .  . 
 .  .  p  .  .  .  P  B 
 .  .  .  .  .  .  .  . 
3N1QR1/5rp1/K3p1P1/8/2p3k1/p7/2p3PB/8/ w - - 0 1

Yabasic

Translation of: C
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()

zkl

Translation of: Raku
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
}
do(5){ pickFEN().println() }
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

ZX Spectrum Basic

A few traps to prevent positions with the wrong number of pieces (not required by the task description but it's worth the effort if we want to use this in a modular way later).

1 DEF FN r(v)=INT (RND*v)+1: REM we'll be using this a lot here for setup, although in real chess it should barely be used at all...

10 GO SUB 9400: REM modularity is pretty much vital in making Sinclair BASIC legible
20 GO SUB 9100
30 GO SUB 9200
40 GO SUB 8800
50 GO TO 9500

8799 REM Material assignment
8800 LET b=FN r(16)-1: REM give black and white a random number of additional pieces each
8810 LET w=FN r(16)-1
8820 FOR x=1 TO b
8830 LET p=LEN b$
8840 LET k=FN r(p)
8850 LET r=FN r(8): REM defined functions can have the same name as variables
8860 LET f=FN r(8)
8870 IF d$(r,f)<>" " THEN GO TO 8840: REM piece already there
8880 IF b$(k)="p" AND (r=1 OR r=8) THEN GO TO 8840: REM pawn on 1st or 8th rank trapping
8890 LET d$(r,f)=b$(k)
8900 IF k=p THEN LET b$=b$(1 TO k-1): GO TO 8920
8910 LET b$=b$( TO k-1)+b$(k+1 TO )
8920 NEXT x
8930 FOR x=1 TO w: REM now doing for white what we just did for black, could be tidied
8940 LET p=LEN w$
8950 LET k=FN r(p)
8960 LET r=FN r(8)
8970 LET f=FN r(8)
8980 IF d$(r,f)<>" " THEN GO TO 8950
8990 IF w$(k)="P" AND (r=1 OR r=8) THEN GO TO 8950
9000 LET d$(r,f)=w$(k)
9010 IF k=p THEN LET w$=w$(1 TO k-1): GO TO 9030
9020 LET w$=w$( TO k-1)+w$(k+1 TO )
9030 NEXT x
9040 RETURN

9099 REM Kings
9100 LET rw=FN r(8)
9110 LET fw=FN r(8)
9120 LET d$(rw,fw)="K"
9130 LET rb=FN r(8)
9140 LET fb=FN r(8)
9150 LET rd=ABS (rw-rb): REM find distance between kings
9160 LET fd=ABS (fd-fb)
9170 IF rd<2 AND fd<2 THEN GO TO 9130
9180 LET d$(rb,fb)="k"
9190 RETURN

9199 REM Promotions
9200 FOR b=1 TO 8
9210 LET v=FN r(30): REM 30% chance of promoting each pawn
9220 IF v=1 THEN LET b$(7+b)="q": GO TO 9260
9230 IF v<3 THEN LET b$(7+b)="r": GO TO 9260
9240 IF v<7 THEN LET b$(7+b)="n": GO TO 9260
9250 IF v<10 THEN LET b$(7+b)="b"
9260 NEXT b
9270 FOR w=1 TO 8
9280 LET v=FN r(30)
9290 IF v=1 THEN LET w$(7+w)="Q": GO TO 9330
9300 IF v<3 THEN LET w$(7+w)="R": GO TO 9330
9310 IF v<7 THEN LET w$(7+w)="N": GO TO 9330
9320 IF v<10 THEN LET w$(7+w)="B"
9330 NEXT b
9340 RETURN

9399 REM Setup
9400 LET b$="qrrnnbbpppppppp": REM we'll set the kings specifically later
9410 LET w$="QRRNNBBPPPPPPPP"
9420 DIM d$(8,8): REM string arrays are autofilled with spaces; this defines the board area
9430 LET f$=""
9440 LET g$=""
9450 RETURN

9499 REM Board
9500 FOR x=1 TO 8
9510 PRINT 9-x;: REM rank number
9520 FOR y=1 TO 8
9530 PRINT INVERSE (((x+y)/2)<>INT ((x+y)/2));d$(x,y);: REM evaluates to 1, a black square, if rank number + file number, read from the top left, is odd; the bottom right square is 8 + 8 = 16 = even = white, conforming to "white to the right" standards
9540 LET f$=f$+d$(x,y): REM building the FEN
9550 NEXT y
9560 PRINT ': REM newline
9570 LET f$=f$+"/"
9580 NEXT x
9590 PRINT " abcdefgh"''
9600 LET k=LEN f$: REM f$ now contains the full string of the board, but we need to count the spaces into numbers
9610 LET t=0: REM counter variable
9620 FOR x=1 TO k
9630 LET t$=f$(x)
9640 IF t$<>" " AND t=0 THEN GO TO 9670: REM not empty and not currently running through blank spaces
9650 IF t$=" " THEN LET t=t+1: GO TO 9670: REM number of blanks in this batch so far
9660 LET f$(x-1)=STR$ t: LET t=0: REM not empty, so a blank space sequence must have ended; insert the counter into the string (STR$ turns the numeric value into its string representation)
9670 NEXT x
9680 FOR x=1 TO k: REM now strip the spaces out
9690 IF f$(x)<>" " THEN LET g$=g$+f$(x)
9700 NEXT x
9710 LET g$=g$( TO LEN g$-1)+" w - - 0 1": REM knock off the final /
9720 PRINT g$
Output:

Inverted squares aren't shown here.

8..b.....
7N.....R.
6.Q.P..PB
5....R...
4P..R.Nk.
3PRP.....
2K..P....
1........
 abcdefgh

2B5/N5R1/1Q1P2PB/4R3/P2R1Nk1/PRP
5/K2P4/8 w - - 0 1

0 OK, 9720:1