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.




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