Generate random chess position

Revision as of 10:15, 28 December 2017 by PureFox (talk | contribs) (Added Kotlin)

The purpose of this task is to generate a random chess position in FEN format. The position does not have to be realistic or even balanced, but it must comply to the following rules:

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

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


C++

<lang cpp>

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

class chessBoard { public:

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

private:

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

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

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

} </lang>

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


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

J

Implementation:

<lang J>getlayout=:3 :0

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

)

randboard=:3 :0

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

)

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

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

)

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

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

)

randfen=:b2fen@randboard</lang>

Example use:

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

  randfen

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

  randfen

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

  randfen

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

  randfen

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

  randfen

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

Java

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

public class Fen {

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

}</lang>

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

Kotlin

Translation of: Java

<lang scala>// version 1.2.0

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

val rand = Random()

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

const val NUL = '\u0000'

fun createFen(): String {

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

}

fun placeKings() {

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

}

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

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

}

fun toFen(): String {

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

}

fun main(args: Array<String>) {

   println(createFen())

}</lang>

Sample output:

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

Perl 6

<lang perl6>sub pick-FEN {

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

my @pieces =

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

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

PicoLisp

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

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

(de pieceset ()

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

(de neib (A)

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

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

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

(loop

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

(setq *FEN

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

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

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

Python

Translation of: Ruby

<lang python> from sys import stdout import random


pieces = ["p","p","p","p","p","p","p","p","k","q","r","r","b","b","n","n",

         "P","P","P","P","P","P","P","P","K","Q","R","R","B","B","N","N"]


def check_king(brd, c, r):

   for j in range(-1, 1):
       for i in range(-1, 1):
           cc = c + i
           rr = r + j
           if -1 < cc < 8 and -1 < rr < 8:
               pc = brd[cc + rr * 8]
               if pc == "k" or pc == "K":
                   return 1
   return 0


def generate_board():

   for i in range(17):
       n = len(pieces) - 1
       while n > 0:
           pt = random.randrange(n)
           tp = pieces[n]
           pieces[n] = pieces[pt]
           pieces[pt] = tp
           n -= 1
   board = [0 for i in range(64)]
   while len(pieces) > 1:
       pc = pieces[0]
       pieces.pop(0)
       while 1:
           c = random.randrange(8)
           r = random.randrange(8)
           if ((r == 0 or r == 7) and (pc == "P" or pc == "p")) or ((pc == "k" or pc == "K") and 1 == check_king( board, c, r)):
               continue
           if board[c + r * 8] == 0:
               break
       board[c + r * 8] = pc
   return board


def start():

   brd = generate_board()
   e = 0
   for j in range(8):
       for i in range(8):
           if brd[i + j * 8] == 0:
               e += 1
           else:
               if e > 0:
                   stdout.write("{0}".format(e))
                   e = 0
               stdout.write(brd[i + j * 8])
       if e > 0:
           stdout.write("{0}".format(e))
           e = 0
       if j < 7:
           stdout.write("/")
   stdout.write(" w - - 0 1\n")
   for j in range (8):
       for i in range (8):
           if brd[i + j * 8] == 0:
               stdout.write(".")
           else:
               stdout.write(brd[i + j * 8])
       print()


  1. entry point

start() </lang>

Output:

1N6/N1PrQpPp/p1p4P/1p1r1q2/1pn1bBp1/PP5P/1bKP1k1p/3RnB1R w - - 0 1 .N...... N.PrQpPp p.p....P .p.r.q.. .pn.bBp. PP.....P .bKP.k.p ...RnB.R

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 chessboard specified is negative, then the number of pieces for each side will be random.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ruby

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

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

end def generateBoard( board, pieces )

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

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

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

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

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

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

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

end </lang>

Output:

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

zkl

Translation of: perl6

<lang zkl>fcn pickFEN{

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

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

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

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

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

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

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

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

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

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

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

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