Generate random chess position: Difference between revisions

m (→‎{{header|PicoLisp}}: update PicoLisp)
 
(90 intermediate revisions by 28 users not shown)
Line 1:
{{draft task}}
 
;Task:
The purpose of this task is to generate a random chess position in [[wp:FEN|FEN format]]. The position does not have to be realistic or even balanced, but it must comply to the following rules:
Generate a random chess position in [[wp:Forsyth–Edwards Notation|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 &nbsp; ''en passant'' &nbsp; (the FEN should thus end in <tt>w - - 0 1</tt>).
 
* 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 <tt>w - - 0 1</tt>).
 
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>
 
=={{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}}==
{{trans|Java}}
<syntaxhighlight lang="c">#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;
}</syntaxhighlight>
 
{{out}}
Sample position:
<pre>
. . . Q . . b .
. . . . . . . .
R . . b . . r .
. . . . q . . K
. . . . P . . .
. B k P . . . .
. n . . . . . .
. . . N . . . .
3Q2b1/8/R2b2r1/4q2K/4P3/1BkP4/1n6/3N4/ w - - 0 1
</pre>
 
=={{header|C++}}==
 
<lang cpp>
<syntaxhighlight lang="cpp">
#include <ctime>
#include <iostream>
Line 89 ⟶ 419:
return 0;
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 113 ⟶ 443:
P..q...n
</pre>
 
=={{header|Crystal}}==
{{trans|Ruby}}
<syntaxhighlight lang="ruby">def hasNK(board, a, b)
(-1..1).each do |g|
(-1..1).each do |f|
aa = a + f; bb = b + g
if (0..7).includes?(aa) && (0..7).includes?(bb)
p = board[aa + 8 * bb]
return true if p == "K" || p == "k"
end
end
end
return false
end
 
def generateBoard(board, pieces)
pieces.each_char do |p|
while true
a = rand(8); b = rand(8)
next if ( (b == 0 || b == 7) && (p == "P" || p == "p") ) ||
( (p == "k" || p == "K") && hasNK(board, a, b) )
break if board[a + b * 8] == '.'
end
board[a + b * 8] = p
end
end
 
pieces = "ppppppppkqrrbbnnPPPPPPPPKQRRBBNN"
11.times do
e = pieces.size - 1
while e > 0
p = rand(e); t = pieces[e]
#pieces[e] = pieces[p]; pieces[p] = t; e -= 1 # in Ruby
pieces = pieces.sub(e, pieces[p]) # in Crystal because
pieces = pieces.sub(p, t); e -= 1 # strings immutable
end
end
 
# 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("") }</syntaxhighlight>
{{out}}<pre>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....
</pre>
 
=={{header|Factor}}==
<syntaxhighlight lang="factor">USING: combinators.short-circuit grouping io kernel math
math.parser math.ranges math.vectors prettyprint random
sequences sets splitting.monotonic strings ;
IN: rosetta-code.random-chess-position
 
<PRIVATE
 
CONSTANT: pieces "RNBQBNRPPPPPPPPrnbqbnrpppppppp"
CONSTANT: empty CHAR: .
 
: <empty-board> ( -- seq ) 64 [ empty ] "" replicate-as ;
: empty-index ( seq -- n ) empty swap indices random ;
: place ( seq elt n -- seq' ) rot [ set-nth ] keep ;
 
! return a list of indices that are adjacent to n
: adj ( n -- seq )
[ 1 - ] [ 1 + ] bi [a,b] { 8 8 8 } [ v- ] 2keep dupd v+
append append ;
 
: rand-non-adjacent ( m -- n ) 64 <iota> swap adj diff random ;
 
: place-kings ( seq -- seq' )
CHAR: K over empty-index [ place ] keep [ CHAR: k ] dip
rand-non-adjacent place ;
 
: non-pawn ( seq elt -- seq' ) over empty-index place ;
 
! prevent placing of pawns in ranks 1 and 8
: pawn ( seq elt -- seq' )
over empty swap indices
[ { [ 7 > ] [ 56 < ] } 1&& ] filter random place ;
 
: place-piece ( seq -- seq' )
pieces random dup "Pp" member? [ pawn ] [ non-pawn ] if ;
 
PRIVATE>
 
 
: position ( -- seq )
<empty-board> place-kings 30 random [ place-piece ] times ;
 
: position. ( seq -- )
[ 1string ] { } map-as 8 group simple-table. ;
 
: position>fen ( seq -- seq' )
8 group [
[ = ] monotonic-split
[ dup first empty = [ length number>string ] when ]
map concat
] map "/" join "/ w - - 0 1" append ;
 
: random-chess-position-demo ( -- )
position [ position. ] [ position>fen print ] bi ;
 
MAIN: random-chess-position-demo</syntaxhighlight>
{{out}}
<pre>
. . . . . . . .
. p . . . . . .
. . . Q R . . .
. . . . . . k .
. P . . b . . .
. . P . . . K .
. . . . . . b .
. . . . . . r .
8/1p6/3QR3/6k1/1P2b3/2P3K1/6b1/6r1/ w - - 0 1
</pre>
 
=={{header|FreeBASIC}}==
{{trans|Yabasic}}
<syntaxhighlight lang="freebasic">
Dim Shared As Byte grid(8, 8), r, c
 
Sub placeKings()
Dim As Byte r1, r2, c1, c2
Do
r1 = Int(Rnd*8)
c1 = Int(Rnd*8)
r2 = Int(Rnd*8)
c2 = Int(Rnd*8)
If (r1 <> r2 And Abs(r1 - r2) > 1 And Abs(c1 - c2) > 1) Then
grid(r1, c1) = Asc("K")
grid(r2, c2) = Asc("k")
Return
End If
Loop
End Sub
 
Sub placePieces(pieces As String, isPawn As Byte)
Dim numToPlace As Byte = Int(Rnd*(Len(pieces)))
For n As Byte = 0 To numToPlace-1
Do
r = Int(Rnd*8)
c = Int(Rnd*8)
Loop Until(Not(grid(r, c) Or (isPawn And (r = 7 Or r = 0))))
grid(r, c) = Asc(Mid(pieces, n, 1))
Next n
End Sub
 
Sub toFen()
Dim As Byte ch, countEmpty = 0
Dim As String fen
For r = 0 To 8-1
For c = 0 To 8-1
ch = grid(r, c)
If ch <> 0 Then
Print " " & Chr(ch);
Else
Print " .";
End If
If ch = 0 Then
countEmpty += 1
Else
If countEmpty > 0 Then
fen += Chr(countEmpty + 48)
countEmpty = 0
End If
fen += Chr(ch)
End If
Next c
If countEmpty > 0 Then
fen += Chr(countEmpty + 48)
countEmpty = 0
End If
fen += "/"
Print
Next r
fen += " w - - 0 1"
Print fen
End Sub
 
Randomize Timer
placeKings()
placePieces("PPPPPPPP", True)
placePieces("pppppppp", True)
placePieces("RNBQBNR", False)
placePieces("rnbqbnr", False)
toFen()
Sleep
</syntaxhighlight>
{{out}}
<pre>
. . . . . . . .
. . . . . . 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
</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>
 
=={{header|Go}}==
{{trans|Java}}
<syntaxhighlight lang="go">package main
 
import (
"fmt"
"math/rand"
"strconv"
"strings"
"time"
)
 
var grid [8][8]byte
 
func abs(i int) int {
if i >= 0 {
return i
} else {
return -i
}
}
 
func createFen() string {
placeKings()
placePieces("PPPPPPPP", true)
placePieces("pppppppp", true)
placePieces("RNBQBNR", false)
placePieces("rnbqbnr", false)
return toFen()
}
 
func placeKings() {
for {
r1 := rand.Intn(8)
c1 := rand.Intn(8)
r2 := rand.Intn(8)
c2 := rand.Intn(8)
if r1 != r2 && abs(r1-r2) > 1 && abs(c1-c2) > 1 {
grid[r1][c1] = 'K'
grid[r2][c2] = 'k'
return
}
}
}
 
func placePieces(pieces string, isPawn bool) {
numToPlace := rand.Intn(len(pieces))
for n := 0; n < numToPlace; n++ {
var r, c int
for {
r = rand.Intn(8)
c = rand.Intn(8)
if grid[r][c] == '\000' && !(isPawn && (r == 7 || r == 0)) {
break
}
}
grid[r][c] = pieces[n]
}
}
 
func toFen() string {
var fen strings.Builder
countEmpty := 0
for r := 0; r < 8; r++ {
for c := 0; c < 8; c++ {
ch := grid[r][c]
if ch == '\000' {
ch = '.'
}
fmt.Printf("%2c ", ch)
if ch == '.' {
countEmpty++
} else {
if countEmpty > 0 {
fen.WriteString(strconv.Itoa(countEmpty))
countEmpty = 0
}
fen.WriteByte(ch)
}
}
if countEmpty > 0 {
fen.WriteString(strconv.Itoa(countEmpty))
countEmpty = 0
}
fen.WriteString("/")
fmt.Println()
}
fen.WriteString(" w - - 0 1")
return fen.String()
}
 
func main() {
rand.Seed(time.Now().UnixNano())
fmt.Println(createFen())
}</syntaxhighlight>
 
{{out}}
Sample position:
<pre>
. q . . . . . .
. . . p . . . K
. . . . . . . b
. r . b . . . .
. . . k . . . .
. . . . . . p .
. . . . . . . .
. n n . . . . .
1q6/3p3K/7b/1r1b4/3k4/6p1/8/1nn5/ w - - 0 1
</pre>
=={{header|Haskell}}==
Module RandomChess
<syntaxhighlight lang="haskell">{-# 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)</syntaxhighlight>
 
Module Main
<syntaxhighlight lang="haskell">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</syntaxhighlight>
{{out}}
Run 1
<pre> 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</pre>
Run 2
<pre> 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</pre>
etc...
 
=={{header|J}}==
Line 118 ⟶ 1,222:
Implementation:
 
<langsyntaxhighlight Jlang="j">getlayout=:3 :0
whilst. NB. first two positions are non-adjacent kings
(0{pos) e. (1{pos)+(,-)1 7 8 9
Line 150 ⟶ 1,254:
)
 
randfen=:b2fen@randboard</langsyntaxhighlight>
 
Example use:
 
<langsyntaxhighlight Jlang="j"> randfen''
q6J/1pb1p1p1/1Jq2k2/4p1Pp/1pP5/1K2Bp2/5p2/1P4P1 w - - 0 1
randfen''
Line 166 ⟶ 1,270:
randfen''
b1Q1Bb1J/j1N1PpK1/PpB1P1Pp/2pp2PN/3nnk2/3J4/P6P/1N2Qb1J w - - 0 1
</syntaxhighlight>
</lang>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import static java.lang.Math.abs;
import java.util.Random;
 
Line 245 ⟶ 1,349:
return fen.append(" w - - 0 1").toString();
}
}</langsyntaxhighlight>
<pre>(lol, the black king is in check, it couldn't possibly be white's turn)
. . . . . B . .
Line 257 ⟶ 1,361:
5B2/P1P5/2k1R3/p1Pp4/7Q/P7/1N2rNP1/6BK/ w - - 0 1</pre>
 
=={{header|Perl 6JavaScript}}==
<syntaxhighlight lang="javascript">
<lang perl6>sub pick-FEN {
Array.prototype.shuffle = function() {
# First we chose how many pieces to place
for (let i = this.length - 1; i > 0; i--) {
my $n = (2..32).pick;
let j = Math.floor(Math.random() * (i + 1));
[this[i], this[j]] = [this[j], this[i]];
}
}
 
function randomFEN() {
# Then we pick $n squares
my @n = (^64).pick($n);
 
let board = [];
# We try to find suitable king positions on non-adjacent squares.
for (let x = 0; x < 8; x++) board.push('. . . . . . . .'.split(' '));
# 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);
 
function getRandPos() {
# We make a list of pieces we can pick (apart from the kings)
return [Math.floor(Math.random() * 8), Math.floor(Math.random() * 8)];
my @pieces = <p P n N b B r R q Q>;
}
 
function isOccupied(pos) {
# We make a list of two king symbols to pick randomly a black or white king
return board[pos[0]][pos[1]] != '.';
my @k = <K k>.pick(*);
}
 
function isAdjacent(pos1, pos2) {
return (gather for ^64 -> $sq {
if (pos1[0] == pos2[0] if|| $sqpos1[0] == @kings.anypos2[0]-1 {|| takepos1[0] @k.shift== }pos2[0]+1)
if (pos1[1] == pos2[1] || pos1[1] == pos2[1]-1 || pos1[1] == pos2[1]+1)
elsif $sq == @n.any {
return true;
my $row = 7 - $sq div 8;
return takefalse;
}
$row == 7 ?? @pieces.grep(none('P')).pick !!
 
$row == 0 ?? @pieces.grep(none('p')).pick !!
// place kings
@pieces.pick;
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|jq}}==
'''Adapted from [[#Wren|Wren]]'''
 
'''Works with jq, the C implementation of jq'''
 
'''Works with gojq, the Go implementation of jq'''
 
The program presented here, like others on this page, does not ensure
that white and black are not in check.
 
Since jq does not include a PRN generator, an external source of entropy such as /dev/urandom is assumed.
A suitable invocation of jq would be along the lines of:
<pre>
< /dev/urandom tr -cd '0-9' | fold -w 1 | jq -nr chess.jq
</pre>
<syntaxhighlight lang="jq">
### Pseuo-random numbers
 
# Output: a prn in range(0;$n) where $n is `.`
def prn:
if . == 1 then 0
else . as $n
| ([1, (($n-1)|tostring|length)]|max) as $w
| [limit($w; inputs)] | join("") | tonumber
| if . < $n then . else ($n | prn) end
end;
 
def sample:
if length == 0 # e.g. null or []
then null
else .[length|prn]
end;
 
def randFloat:
(1000|prn) / 1000;
 
### Chess
 
def isEmpty: . == "." or . == "•";
 
def grid:
[range(0;4) | (".","•") ] as $black
| [range(0;4) | ("•", ".")] as $white
| [range(0;4) | ($black, $white)] ;
 
# input: {grid}
def placeKings:
.done = false
| until(.done;
[8 | prn, prn, prn, prn] as [$r1, $c1, $r2, $c2]
| if $r1 != $r2 and (($r1 - $r2)|length) > 1 and (($c1 - $c2)|length) > 1
then .grid[$r1][$c1] = "K"
| .grid[$r2][$c2] = "k"
| .done = true
else .
end )
| del(.done);
 
# input: {grid}
def placePieces($pieces; $isPawn):
($pieces|length|prn) as $numToPlace
| .n = -1
| until(.n == $numToPlace;
.n += 1
| .done = false
| until(.done;
.r = (8 | prn)
| .c = (8 | prn)
| if (.grid[.r][.c] | isEmpty) and (($isPawn and (.r == 7 or .r == 0))|not)
then .done = true
else .
end )
| .grid[.r][.c] = $pieces[.n:.n+1] ) ;
 
def toFen:
{ grid,
fen: "",
countEmpty: 0 }
| reduce range (0;8) as $r (.;
reduce range(0;8) as $c (.;
.grid[$r][$c] as $ch
| .emit += " \($ch) "
| if ($ch | isEmpty)
then .countEmpty += 1
else
if .countEmpty > 0
then .fen += (.countEmpty|tostring)
| .countEmpty = 0
end
| .fen += $ch
end )
| if .countEmpty > 0
then .fen += (.countEmpty|tostring)
| .countEmpty = 0
end
| .fen += "/"
| .emit += "\n" )
| .emit,
.fen + " w - - 0 1" ;
 
def createFen:
{grid: grid}
| placeKings
| placePieces("PPPPPPPP"; true)
| placePieces("pppppppp"; true)
| placePieces("RNBQBNR"; false)
| placePieces("rnbqbnr"; false)
| toFen;
 
createFen
</syntaxhighlight>
{{output}}
<pre>
. • . • b R . •
• p q . • . • p
. K P • . p . •
• . • . • . P p
. P . • . P . •
• b n . • . • .
p p . k . p r p
• . • . • . • .
 
4bR2/1pq4p/1KP2p2/6Pp/1P3P2/1bn5/pp1k1prp/8/ w - - 0 1
</pre>
 
=={{header|Julia}}==
{{trans|Kotlin}}
 
'''Module''':
<syntaxhighlight lang="julia">module Chess
 
using Printf
 
struct King end
struct Pawn end
 
function placepieces!(grid, ::King)
axis = axes(grid, 1)
while true
r1, c1, r2, c2 = rand(axis, 4)
if r1 != r2 && abs(r1 - r2) > 1 && abs(c1 - c2) > 1
grid[r1, c1] = '♚'
grid[r2, c2] = '♔'
return grid
end
end
end
 
function placepieces!(grid, ch)
axis = axes(grid, 1)
while true
r, c = rand(axis, 2)
if grid[r, c] == ' '
grid[r, c] = ch
return grid
end
end
end
 
function placepieces!(grid, ch, ::Pawn)
axis = axes(grid, 1)
while true
r, c = rand(axis, 2)
if grid[r, c] == ' ' && r ∉ extrema(axis)
grid[r, c] = ch
return grid
end
end
end
 
function randposition!(grid)
placepieces!(grid, King())
foreach("♙♙♙♙♙♙♙♙♙♟♟♟♟♟♟♟♟") do ch
placepieces!(grid, ch, Pawn())
end
foreach("♖♘♗♕♗♘♖♜♞♝♛♝♞♜") do ch
placepieces!(grid, ch)
end
return grid
end
 
printgrid(grid) = println(join((join(grid[r, :], ' ') for r in 1:size(grid, 1)), '\n'))
 
end # module Chess</syntaxhighlight>
 
'''Main''':
<syntaxhighlight lang="julia">grid = fill(' ', 8, 8)
Chess.randposition!(grid)
Chess.printgrid(grid)</syntaxhighlight>
 
{{out}}
<pre> ♕ ♞ ♗
♖ ♙ ♔ ♙ ♖ ♜ ♙
♟ ♙ ♙ ♜
♘ ♝ ♙ ♙ ♟
♙ ♚ ♝ ♟
♟ ♟ ♗ ♟
♙ ♞ ♟ ♟
♘ ♛</pre>
 
=={{header|Kotlin}}==
{{trans|Java}}
<syntaxhighlight 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
}
}
else { take 'ø' }
}).rotor(8)».join».subst(/ø+/,{ .chars }, :g).join('/') ~ ' w - - 0 1';
}
 
fun placePieces(pieces: String, isPawn: Boolean) {
say pick-FEN();</lang>
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())
}</syntaxhighlight>
 
Sample output:
<pre>
. . . . . . . .
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
</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>q2n1n22N5/1Qpk3Q1P3P2/1r3bP1p1P3P1/1b1b45q2/2pRBR28/4P1bN5k1K/2R3K11p3p2/N1r2rPB8 w - - 0 1</pre>
 
=={{header|Nim}}==
{{trans|Kotlin}}
<syntaxhighlight lang="nim">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()</syntaxhighlight>
 
{{out}}
<pre> . . . . . . . .
. . . . ♟ . . .
♟ . . . ♟ . . .
. . . . . ♙ ♟ .
. ♙ . . . ♚ . .
. ♙ . . . . ♗ ♘
. ♟ . . ♙ . . .
. . . ♔ . . . . </pre>
 
=={{header|Perl}}==
{{trans|Raku}}
<syntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
use utf8;
use List::AllUtils <shuffle any natatime>;
 
sub pick1 { return @_[rand @_] }
 
sub gen_FEN {
my $n = 1 + int rand 31;
my @n = (shuffle(0 .. 63))[1 .. $n];
 
my @kings;
 
KINGS: {
for my $a (@n) {
for my $b (@n) {
next unless $a != $b && abs(int($a/8) - int($b/8)) > 1 || abs($a%8 - $b%8) > 1;
@kings = ($a, $b);
last KINGS;
}
die 'No good place for kings!';
}
}
 
my ($row, @pp);
my @pieces = <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();</syntaxhighlight>
{{out}}
<pre>p5Nq/1nn5/3N2bp/PRBkQr2/1QB1Pn2/Q5pK/1NRb2rN/p1R2r1N w - - 0 1</pre>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<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>
<span style="color: #004080;">string</span> <span style="color: #000000;">board</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">fen</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</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;">64</span> <span style="color: #008080;">by</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">empty</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<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>
<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>
<span style="color: #000000;">empty</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">empty</span> <span style="color: #008080;">then</span>
<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>
<span style="color: #000000;">empty</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">empty</span> <span style="color: #008080;">then</span>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">" w - - 0 1"</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">p15</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"pppppppprrnnbbq"</span>
<span style="color: #000080;font-style:italic;">-- promote 0..8 pawns</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: #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>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<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>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<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>
<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>
<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>
<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>
<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>
<span style="color: #004080;">integer</span> <span style="color: #000000;">lp</span>
<span style="color: #008080;">procedure</span> <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;">"%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>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<span style="color: #008080;">else</span>
<span style="color: #000080;font-style:italic;">-- check no pawn will be on a promotion square,
-- and (above spec) no pawn has gone backwards:</span>
<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>
<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>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<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
<code>if not find('P',board[1..8]) and not find('p',board[57..64]) then exit end if</code><br>
{{out}}
with show_bad_boards set to true
<pre>
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
</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(load "@lib/simul.l")
(seed (in "/dev/urandom" (rd 8)))
(de pieceN (P)
Line 379 ⟶ 2,151:
(gt0 C)
(link C) ) ) ) ) ) ) )
(println (pack (glue "/" *FEN) " w - - 0 1"))</langsyntaxhighlight>
{{out}}
<pre>
Line 392 ⟶ 2,164:
"3n3B/1p1BQ1B1/B2P2Br/p6p/r1PpBrrk/3B1P2/3r2K1/6r1 w - - 0 1"
</pre>
 
=={{header|Python}}==
<syntaxhighlight lang="python">
import random
 
board = [[" " for x in range(8)] for y in range(8)]
piece_list = ["R", "N", "B", "Q", "P"]
 
 
def place_kings(brd):
while True:
rank_white, file_white, rank_black, file_black = random.randint(0,7), random.randint(0,7), random.randint(0,7), random.randint(0,7)
diff_list = [abs(rank_white - rank_black), abs(file_white - file_black)]
if sum(diff_list) > 2 or set(diff_list) == set([0, 2]):
brd[rank_white][file_white], brd[rank_black][file_black] = "K", "k"
break
 
def populate_board(brd, wp, bp):
for x in range(2):
if x == 0:
piece_amount = wp
pieces = piece_list
else:
piece_amount = bp
pieces = [s.lower() for s in piece_list]
while piece_amount != 0:
piece_rank, piece_file = random.randint(0, 7), random.randint(0, 7)
piece = random.choice(pieces)
if brd[piece_rank][piece_file] == " " and pawn_on_promotion_square(piece, piece_rank) == False:
brd[piece_rank][piece_file] = piece
piece_amount -= 1
 
def fen_from_board(brd):
fen = ""
for x in brd:
n = 0
for y in x:
if y == " ":
n += 1
else:
if n != 0:
fen += str(n)
fen += y
n = 0
if n != 0:
fen += str(n)
fen += "/" if fen.count("/") < 7 else ""
fen += " w - - 0 1\n"
return fen
 
def pawn_on_promotion_square(pc, pr):
if pc == "P" and pr == 0:
return True
elif pc == "p" and pr == 7:
return True
return False
 
 
def start():
piece_amount_white, piece_amount_black = random.randint(0, 15), random.randint(0, 15)
place_kings(board)
populate_board(board, piece_amount_white, piece_amount_black)
print(fen_from_board(board))
for x in board:
print(x)
 
#entry point
start()
</syntaxhighlight>
{{out}}<pre>
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']
</pre>
 
=={{header|R}}==
<syntaxhighlight lang="rsplus">
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()
</syntaxhighlight>
{{out}}
[,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
 
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" line>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();</syntaxhighlight>
{{out}}
<pre>q2n1n2/1Qpk3Q/1r3bP1/1b1b4/2pRBR2/4P1bN/2R3K1/N1r2rPB w - - 0 1</pre>
 
=={{header|REXX}}==
 
This REXX version normally generates balanced number of pieces &nbsp; (both sides have an equal number of total pieces,
<br>but not necessarily of the same kind).
 
If the number of chessboardchessboards 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 &nbsp; (the default is to only display one chessboard).
<langsyntaxhighlight 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? */
Line 407 ⟶ 2,414:
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. */
Line 416 ⟶ 2,423:
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. */
end /*f*/
say $ /*display the board rank. */
do e=8 for 8 by -1; $= changestr( copies(., e), $, e); end /*e*/ . /*filler.≡filler*/
fen=fen || $ || left('/', r\==1) end /*append / if not 1st rank.e*/
end /*r*/ fen= fen || $ || left('/', r\==1) /*append [↑]/ if append $ strnot to1st FENrank.*/
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?*/
Line 437 ⟶ 2,446:
end /*rr*/ /*[↑] neighbor ≡ king?*/
end /*ff*/ /*[↑] we're all done. */
@.r.f= x x /*put random piece. */
!.r.f= ux; return /* " " " upper*/
end /*#*/ /*#: isn't incremented.*/</langsyntaxhighlight>
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'''),
Line 504 ⟶ 2,513:
FEN=qnqN3N/3B3N/n4P1Q/PP2b1Rn/KqB5/pB1knp2/q1n1qB2/7N w - - 0 1
</pre>
 
=={{header|Ruby}}==
<syntaxhighlight 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
</syntaxhighlight>
{{out}}<pre>
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...
</pre>
 
=={{header|Rust}}==
<syntaxhighlight lang="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());
}</syntaxhighlight>
 
{{out}}
<pre>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</pre>
 
=={{header|Scala}}==
{{Out}}Best seen running in your browser [https://scastie.scala-lang.org/zdG9NQ4YSaShFRU7AS31GA Scastie (remote JVM)].
<syntaxhighlight lang="scala">import scala.math.abs
import scala.util.Random
 
object RandomFen extends App {
val rand = new Random
 
private def createFen = {
val grid = Array.ofDim[Char](8, 8)
 
def placeKings(grid: Array[Array[Char]]): Unit = {
var r1, c1, r2, c2 = 0
do {
r1 = rand.nextInt(8)
c1 = rand.nextInt(8)
r2 = rand.nextInt(8)
c2 = rand.nextInt(8)
} while (r1 == r2 || abs(r1 - r2) <= 1 || abs(c1 - c2) <= 1)
grid(r1)(c1) = 'K'
grid(r2)(c2) = 'k'
}
 
def placePieces(grid: Array[Array[Char]],
pieces: String,
isPawn: Boolean): Unit = {
val numToPlace = rand.nextInt(pieces.length)
 
for (n <- 0 until numToPlace) {
var r, c = 0
do {
r = rand.nextInt(8)
c = rand.nextInt(8)
} while (grid(r)(c) != 0 || (isPawn && (r == 7 || r == 0)))
grid(r)(c) = pieces(n)
}
}
 
def toFen(grid: Array[Array[Char]]) = {
val fen = new StringBuilder
var countEmpty = 0
for (r <- grid.indices) {
for (c <- grid.indices) {
val ch = grid(r)(c)
print(f"${if (ch == 0) '.' else ch}%2c ")
if (ch == 0) countEmpty += 1
else {
if (countEmpty > 0) {
fen.append(countEmpty)
countEmpty = 0
}
fen.append(ch)
}
}
if (countEmpty > 0) {
fen.append(countEmpty)
countEmpty = 0
}
fen.append("/")
println()
}
fen.append(" w - - 0 1").toString
}
 
placeKings(grid)
placePieces(grid, "PPPPPPPP", isPawn = true)
placePieces(grid, "pppppppp", isPawn = true)
placePieces(grid, "RNBQBNR", isPawn = false)
placePieces(grid, "rnbqbnr", isPawn = false)
toFen(grid)
}
 
println(createFen)
 
}</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}}==
{{trans|Kotlin}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">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())</syntaxhighlight>
 
{{out}}
Sample position:
<pre>
. . . 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
</pre>
 
=={{header|Yabasic}}==
{{trans|C}}
<syntaxhighlight lang="yabasic">dim grid(8, 8)
sub placeKings()
local r1, r2, c1, c2
do
r1 = int(ran(8))
c1 = int(ran(8))
r2 = int(ran(8))
c2 = int(ran(8))
if (r1 <> r2 and abs(r1 - r2) > 1 and abs(c1 - c2) > 1) then
grid(r1, c1) = asc("K")
grid(r2, c2) = asc("k")
return
end if
loop
end sub
sub placePieces(pieces$, isPawn)
local n, r, c, numToPlace
numToPlace = int(ran(len(pieces$)))
for n = 0 to numToPlace-1
repeat
r = int(ran(8))
c = int(ran(8))
until(not(grid(r, c) or (isPawn and (r = 7 or r = 0))))
grid(r, c) = asc(mid$(pieces$, n, 1))
next
end sub
sub toFen()
local fen$, ch, r, c, countEmpty
for r = 0 to 8-1
for c = 0 to 8-1
ch = grid(r, c)
if ch then print chr$(ch); else print "."; end if
if not ch then
countEmpty = countEmpty + 1
else
if countEmpty then
fen$ = fen$ + chr$(countEmpty + 48)
countEmpty = 0
end if
fen$ = fen$ + chr$(ch)
end if
next
if countEmpty then
fen$ = fen$ + chr$(countEmpty + 48)
countEmpty = 0
end if
fen$ = fen$ + "/"
print
next
fen$ = fen$ + " w - - 0 1"
print fen$
end sub
sub createFen()
placeKings()
placePieces("PPPPPPPP", TRUE)
placePieces("pppppppp", TRUE)
placePieces("RNBQBNR", FALSE)
placePieces("rnbqbnr", FALSE)
toFen()
end sub
createFen()
</syntaxhighlight>
 
=={{header|zkl}}==
{{trans|perl6Raku}}
<langsyntaxhighlight lang="zkl">fcn pickFEN{
# First we chose how many pieces to place: 2 to 32
n := (0).random(2,33);
Line 544 ⟶ 3,051:
while(re.search(str,1)){ n,m:=re.matched[0]; str=String(str[0,n],m,str[n+m,*]) }
str
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">do(5){ pickFEN().println() }</langsyntaxhighlight>
{{out}}
<pre>
Line 552 ⟶ 3,059:
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</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>
2,442

edits