Generate Chess960 starting position: Difference between revisions

m
 
(36 intermediate revisions by 19 users not shown)
Line 1:
{{task}} [[Category:Chess960]]
'''[[wp:Chess960|Chess960]]''' is a variant of chess created by world champion [[wp:Bobby Fischer|Bobby Fischer]]. Unlike other variants of the game, Chess960 does not require a different material, but instead relies on a random initial position, with a few constraints:
 
Line 13:
 
;Task:
The purpose of this task is to write a program that can randomly generate any one of the 960 Chess960 initial positions. You will show the result as the first rank displayed withusing either the [[wp:Chess symbols in Unicode|Chesschess symbols in Unicode: (♔♕♖♗♘)]] or with, the letters '''K'''ing '''Q'''ueen '''R'''ook '''B'''ishop k'''N'''ight, or the corresponding letters in a language other than English.
<br><br>
 
Line 19:
{{trans|Python: Correct by construction}}
 
<langsyntaxhighlight lang="11l">F random960()
V start = [‘R’, ‘K’, ‘R’]
 
Line 30:
R start
 
print(random960())</langsyntaxhighlight>
 
{{out}}
Line 36:
[Q, B, N, R, K, B, N, R]
</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE MAX_NUMBERS="200"
DEFINE MAX_LEN="20"
DEFINE MAX_FACTORS="5"
DEFINE PTR="CARD"
 
PROC PrintResult(BYTE max,n BYTE ARRAY factors PTR ARRAY texts)
BYTE i,j,t
BYTE ARRAY values(MAX_FACTORS)
 
FOR j=0 TO n-1
DO
values(j)=1
OD
 
FOR i=1 TO max
DO
t=0
FOR j=0 TO n-1
DO
IF values(j)=0 THEN
t=1 Print(texts(j))
FI
values(j)==+1
IF values(j)=factors(j) THEN
values(j)=0
FI
OD
IF t=0 THEN PrintB(i) FI
Put(32)
OD
RETURN
 
BYTE FUNC Find(CHAR ARRAY s CHAR c BYTE POINTER err)
BYTE i
 
FOR i=1 TO s(0)
DO
IF s(i)=c THEN
err^=0 RETURN (i)
FI
OD
err^=1
RETURN (0)
 
PROC Main()
BYTE max,i,n,pos,err
BYTE ARRAY factors(MAX_FACTORS)
PTR ARRAY texts(MAX_FACTORS)
CHAR ARRAY
s(100),tmp(100),
t0(MAX_LEN),t1(MAX_LEN),t2(MAX_LEN),
t3(MAX_LEN),t4(MAX_LEN)
texts(0)=t0 texts(1)=t1 texts(2)=t2
texts(3)=t3 texts(4)=t4
 
DO
PrintF("Max number (1-%B): ",MAX_NUMBERS)
max=InputB()
UNTIL max>=1 AND max<=MAX_NUMBERS
OD
 
n=0
DO
PrintF("Number of rules (1-%B): ",MAX_FACTORS)
n=InputB()
UNTIL n>=1 AND n<=MAX_FACTORS
OD
 
FOR i=0 TO n-1
DO
DO
PrintF("Rule #%B (number space text):",i+1)
InputS(s)
pos=Find(s,' ,@err)
IF pos=1 OR pos=s(0) THEN
err=1
FI
IF err=0 THEN
SCopyS(tmp,s,1,pos-1)
factors(i)=ValB(tmp)
IF factors(i)<2 THEN
err=1
FI
SCopyS(texts(i),s,pos+1,s(0))
FI
UNTIL err=0
OD
OD
 
PutE()
PrintResult(max,n,factors,texts)
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Generate_Chess960_starting_position_.png Screenshot from Atari 8-bit computer]
<pre>
NBBQRNKR
NRKBRQBN
BNRBKRNQ
QBRKRNBN
RBKNRQBN
BNNBRKQR
NQNBRKBR
BRNKRBQN
NRKRQNBB
RNQBKRBN
</pre>
 
=={{header|APL}}==
This function accepts a SP-ID and generates the corresponding position; to generate a random one, just pass in roll 960 (<tt>?960</tt>). (It's written for index origin 1, but reduces the passed-in SP-ID modulo 960 so that works without having to subtract 1 from the roll result.)
{{works with|Dyalog APL}}
{{works with|GNU APL}}
 
<syntaxhighlight lang="apl">⍝ Utility functions
divmod ← {(⌊⍺÷⍵),⍵|⍺}
indices ← {(⍺∊⍵)/⍳⍴⍺}
∇result ← place placement; array; index; piece; result
(array piece index) ← placement
array[(array indices '-')[index]] ← piece
result ← array
∇result ← chess960 spid; array; n; b1; b2; n1; n2; q
spid ← 960 | spid
array ← 8/'-'
(n b1) ← spid divmod 4
array[2+2×b1] ← 'B'
(n b2) ← n divmod 4
array[1+2×b2] ← 'B'
(n q) ← n divmod 6
array ← place array 'Q' (1+q)
n1 ← 1⍳⍨n<4 7 9 10
array ← place array 'N' n1
n2 ← (1 2 3 4 2 3 4 3 4 4)[n+1]
array ← place array 'N' n2
array ← place array 'R' 1
array ← place array 'K' 1
array ← place array 'R' 1
result ← spid, array
∇</syntaxhighlight>
 
{{Out}}
<pre> chess960 518
518 RNBQKBNR
chess960 ?960
377 NRKBBRNQ
chess960 ?960
487 QRBNKNRB</pre>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="arturo">; Using Edward Collins' single-die method
; http://www.edcollins.com/chess/fischer-random.htm
 
chess960: function [][
result: array.of: 8 ø
vacant: @0..7 ; open squares available to put pieces
result\[remove 'vacant <= 2 * random 0 3]: 'bishop ; place on random black square
result\[remove 'vacant <= 1 + 2 * random 0 3]: 'bishop ; place on random white square
loop ['queen 'knight 'knight] 'piece [
result\[remove 'vacant <= sample vacant]: piece ; place on random open square
]
result\[vacant\0]: 'rook ; place king between rooks on remaining open squares
result\[vacant\1]: 'king
result\[vacant\2]: 'rook
result
]
 
do.times:5 -> print chess960</syntaxhighlight>
 
{{out}}
 
<pre>bishop knight rook queen king knight rook bishop
knight rook queen bishop bishop king knight rook
rook bishop bishop knight knight king rook queen
bishop knight rook queen king knight rook bishop
rook king knight knight bishop queen rook bishop</pre>
 
=={{header|AutoHotkey}}==
{{works with|AutoHotkey 1.1}}
<langsyntaxhighlight AutoHotkeylang="autohotkey">Loop, 5
Out .= Chess960() "`n"
MsgBox, % RTrim(Out, "`n")
Line 71 ⟶ 249:
Random, n, Min, Max
return n
}</langsyntaxhighlight>
{{Output}}
<big><big><pre>♕♘♖♗♗♘♔♖
Line 78 ⟶ 256:
♗♗♘♖♔♕♘♖
♘♗♖♔♗♘♕♖</pre></big></big>
 
=={{header|BASIC}}==
==={{header|BASIC256}}===
{{trans|Yabasic}}
<syntaxhighlight lang="basic256">for i = 1 to 10
inicio$ = "RKR"
pieza$ = "QNN"
 
for n = 1 to length(pieza$)
posic = int(rand*(length(inicio$) + 1)) + 1
inicio$ = left(inicio$, posic-1) + mid(pieza$, n, 1) + right(inicio$, length(inicio$) - posic + 1)
next n
posic = int(rand*(length(inicio$) + 1)) + 1
inicio$ = left(inicio$, posic-1) + "B" + right(inicio$, length(inicio$) - posic + 1)
posic += 1 + 2 * int(int(rand*(length(inicio$) - posic)) / 2)
inicio$ = left(inicio$, posic-1) + "B" + right(inicio$, length(inicio$) - posic + 1)
print inicio$
next i
end</syntaxhighlight>
 
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
<syntaxhighlight lang="bbcbasic"> VDU 23, 22, 240; 360; 8, 16, 16, 136
*FONT Arial, 20
FOR I% = 1 TO 10
Rank1$ = "202"
FOR Piece = 1 TO 3
P% = RND(LENRank1$ + 1)
Rank1$ = LEFT$(Rank1$, P% - 1) + MID$("144", Piece, 1) + MID$(Rank1$, P%)
NEXT
P% = RND(7)
Rank1$ = LEFT$(Rank1$, P% - 1) + "3" + MID$(Rank1$, P%)
IF P% > 5 P% += 1 ELSE P% += RND(4 - (P% >> 1)) * 2 - 1
Rank1$ = LEFT$(Rank1$, P% - 1) + "3" + MID$(Rank1$, P%)
FOR Piece = 1 TO 8
VDU &E2, &99, &94 + VALMID$(Rank1$, Piece, 1)
NEXT
PRINT
NEXT</syntaxhighlight>
{{out}}
<pre>♘ ♖ ♗ ♔ ♖ ♘ ♕ ♗
♘ ♖ ♔ ♘ ♕ ♖ ♗ ♗
♕ ♗ ♖ ♔ ♗ ♘ ♖ ♘
♖ ♘ ♔ ♗ ♖ ♕ ♗ ♘
♖ ♗ ♗ ♘ ♔ ♖ ♘ ♕
♘ ♖ ♗ ♗ ♕ ♔ ♘ ♖
♖ ♔ ♕ ♘ ♗ ♘ ♖ ♗
♘ ♘ ♖ ♔ ♖ ♗ ♗ ♕
♖ ♕ ♔ ♘ ♗ ♗ ♖ ♘
♖ ♕ ♔ ♘ ♘ ♗ ♗ ♖</pre>
 
==={{header|Commodore BASIC}}===
{{works with|Commodore BASIC|3.5,7.0}}
Besides the admittedly-trivial use of <tt>DO</tt>/<tt>LOOP</tt>, this implementation also exploits the BASIC 3.5+ ability to use <tt>MID$</tt> as an lvalue.
<syntaxhighlight lang="basic">100 REM CHESS 960
110 PRINT "SPID (-1 FOR RANDOM):";
120 OPEN 1,0:INPUT#1, SP$:CLOSE 1
130 SP=VAL(SP$)
140 IF SP<0 THEN SP=INT(RND(.)*960)
150 PRINT
160 DO WHILE SP>959: SP=SP-960: LOOP
170 AR$="--------"
180 P=SP
190 N=P AND 3:P=INT(P/4)
200 MID$(AR$,2*N+2,1)="B"
210 N=P AND 3:P=INT(P/4)
220 MID$(AR$,2*N+1,1)="B"
230 N=P-6*INT(P/6):P=INT(P/6)
240 P$="Q":GOSUB 420
250 N=P-10*INT(P/10):P=INT(P/10)
260 FOR N1=0 TO 3
270 : FOR N2=N1+1 TO 4
280 : IF N<>0 THEN 340
290 : P$="N":N=N1:GOSUB 420
300 : P$="N":N=N2-1:GOSUB 420
310 : N1=3
320 : N2=4
340 : N=N-1
350 : NEXT N2
360 NEXT N1
370 P$="R":N=0:GOSUB 420
380 P$="K":N=0:GOSUB 420
390 P$="R":N=0:GOSUB 420
400 PRINT STR$(SP);":";AR$
410 END
420 FOR I=1 TO LEN(AR$)
430 : IF MID$(AR$,I,1)<>"-" THEN 510
440 : IF N<>0 THEN 480
450 : MID$(AR$,I,1)=P$
460 : I=LEN(AR$)
470 : GOTO 510
480 : N=N-1
510 NEXT I
520 RETURN
</syntaxhighlight>
 
Here's a version that doesn't use the advanced features:
{{works with|Commodore BASIC|2.0}}
 
<syntaxhighlight lang="basic">100 REM CHESS 960
110 PRINT "SPID (-1 FOR RANDOM):";
120 OPEN 1,0:INPUT#1, SP$:CLOSE 1
130 SP=VAL(SP$)
140 IF SP<0 THEN SP=INT(RND(.)*960)
150 PRINT
160 IF SP>959 THEN SP=SP-960: GOTO 160
170 AR$="--------"
180 P=SP
190 N=P AND 3:P=INT(P/4)
200 AR$=LEFT$(AR$,2*N+1)+"B"+MID$(AR$,2*N+3)
210 N=P AND 3:P=INT(P/4)
220 AR$=LEFT$(AR$,2*N)+"B"+MID$(AR$,2*N+2)
230 N=P-6*INT(P/6):P=INT(P/6)
240 P$="Q":GOSUB 420
250 N=P-10*INT(P/10):P=INT(P/10)
260 FOR N1=0 TO 3
270 : FOR N2=N1+1 TO 4
280 : IF N<>0 THEN 340
290 : P$="N":N=N1:GOSUB 420
300 : P$="N":N=N2-1:GOSUB 420
310 : N1=3
320 : N2=4
340 : N=N-1
350 : NEXT N2
360 NEXT N1
370 P$="R":N=0:GOSUB 420
380 P$="K":N=0:GOSUB 420
390 P$="R":N=0:GOSUB 420
400 PRINT STR$(SP);":";AR$
410 END
420 FOR I=1 TO LEN(AR$)
430 : IF MID$(AR$,I,1)<>"-" THEN 510
440 : IF N<>0 THEN 480
450 : AR$=LEFT$(AR$,I-1)+P$+MID$(AR$,I+1)
460 : I=LEN(AR$)
470 : GOTO 510
480 : N=N-1
510 NEXT I
520 RETURN</syntaxhighlight>
 
{{Out}}
The output is the same for both versions:
<pre>
READY.
RUN
SPID (-1 FOR RANDOM):518
518:RNBQKBNR
 
READY.
RUN
SPID (-1 FOR RANDOM):-1
926:RKRQNBBN
 
READY.</pre>
 
==={{header|FreeBASIC}}===
{{trans|Yabasic}}
<syntaxhighlight lang="freebasic">
Randomize Timer
For i As Byte = 1 To 10
Dim As String inicio = "RKR", pieza = "QNN"
Dim As Byte posic
For n As Byte = 1 To Len(pieza)
posic = Int(Rnd*(Len(inicio) + 1)) + 1
inicio = Left(inicio, posic-1) + _
Mid(pieza, n, 1) +_
Right(inicio, Len(inicio) - posic + 1)
Next n
posic = Int(Rnd*(Len(inicio) + 1)) + 1
inicio = Left(inicio, posic-1) + "B" + Right(inicio, Len(inicio) - posic + 1)
posic = posic + 1 + 2 * Int(Int(Rnd*(Len(inicio) - posic)) / 2)
inicio = Left(inicio, posic-1) + "B" + Right(inicio, Len(inicio) - posic + 1)
Print inicio
Next i
</syntaxhighlight>
 
==={{header|QBasic}}===
{{trans|Yabasic}}
<syntaxhighlight lang="qbasic">RANDOMIZE TIMER
 
FOR i = 1 TO 10
inicio$ = "RKR"
pieza$ = "QNN"
'Dim posic
FOR n = 1 TO LEN(pieza$)
posic = INT(RND * (LEN(inicio$) + 1)) + 1
inicio$ = LEFT$(inicio$, posic - 1) + MID$(pieza$, n, 1) + RIGHT$(inicio$, LEN(inicio$) - posic + 1)
NEXT n
posic = INT(RND * (LEN(inicio$) + 1)) + 1
inicio$ = LEFT$(inicio$, posic - 1) + "B" + RIGHT$(inicio$, LEN(inicio$) - posic + 1)
posic = posic + 1 + 2 * INT(INT(RND * (LEN(inicio$) - posic)) / 2)
inicio$ = LEFT$(inicio$, posic - 1) + "B" + RIGHT$(inicio$, LEN(inicio$) - posic + 1)
PRINT inicio$
NEXT i
END</syntaxhighlight>
 
==={{header|Yabasic}}===
{{trans|Seed7}}
<syntaxhighlight lang="yabasic">start$ = "RKR"
piece$ = "QNN"
 
for piece = 1 to len(piece$)
pos = int(ran(len(start$) + 1)) + 1
start$ = left$(start$, pos-1) + mid$(piece$, piece, 1) + right$(start$, len(start$) - pos + 1)
next
pos = int(ran(len(start$) + 1)) + 1
start$ = left$(start$, pos-1) + "B" + right$(start$, len(start$) - pos + 1)
pos = pos + 1 + 2 * int(int(ran(len(start$) - pos)) / 2)
start$ = left$(start$, pos-1) + "B" + right$(start$, len(start$) - pos + 1)
print start$
</syntaxhighlight>
 
=={{header|Befunge}}==
Similar to the [[Generate_Chess960_starting_position#Ruby:_Generate_from_SP-ID|Ruby SP-ID solution]], this generates the start position for a random number in the [[wp:Chess960 numbering scheme|Chess960 numbering scheme]].
<langsyntaxhighlight lang="befunge">#.#.#.#.065*0#v_1-\>>?1v
v,":".:%*8"x"$<^!:\*2<+<
>48*,:4%2*1#v+#02#\3#g<<
Line 91 ⟶ 482:
>"RKRNN"11g:!#v_\$\$\$\v
v _v#!`*86:g0:<^!:-1$\$<
>$\>,1+ :7`#@_^> v960v <</langsyntaxhighlight>
{{out}}
<pre>856 : RBKNBRNQ</pre>
Line 97 ⟶ 488:
=={{header|C}}==
As noted in the C implementation for the [[Sparkline in unicode]] task, unicode output is reliable only on Linux/Unix systems. This implementation thus has compiler directives to check whether the underlying system is Windows or Linux, if Windows, only letters are printed, otherwise Unicode output is displayed. 9 rows are displayed.
<langsyntaxhighlight Clang="c">#include<stdlib.h>
#include<locale.h>
#include<wchar.h>
Line 199 ⟶ 590:
return 0;
}
</syntaxhighlight>
</lang>
Output on Linux :
<pre>♗♗♖♕♘♘♔♖
Line 220 ⟶ 611:
RNKBNRBQ
QNRBBNKR</pre>
 
 
=={{header|C#}}==
{{trans|Go}}
<syntaxhighlight lang="C#">
using System;
 
class Program
{
struct Symbols
{
public char K, Q, R, B, N;
 
public Symbols(char k, char q, char r, char b, char n)
{
K = k; Q = q; R = r; B = b; N = n;
}
}
 
private static Symbols A = new Symbols('K', 'Q', 'R', 'B', 'N');
private static Symbols W = new Symbols('♔', '♕', '♖', '♗', '♘');
private static Symbols B = new Symbols('♚', '♛', '♜', '♝', '♞');
 
private static string[] krn = new string[]
{
"nnrkr", "nrnkr", "nrknr", "nrkrn",
"rnnkr", "rnknr", "rnkrn",
"rknnr", "rknrn",
"rkrnn"
};
 
private static string Chess960(Symbols sym, int id)
{
char[] pos = new char[8];
int q = id / 4, r = id % 4;
pos[r * 2 + 1] = sym.B;
r = q % 4; q /= 4;
pos[r * 2] = sym.B;
r = q % 6; q /= 6;
int placementIndex = 0; // Adjusted variable name to prevent conflict
for (int i = 0; ; i++)
{
if (pos[i] != '\0') continue;
if (r == 0)
{
pos[i] = sym.Q;
break;
}
r--;
}
while (pos[placementIndex] != '\0') placementIndex++; // Adjusted loop to prevent conflict
foreach (char f in krn[q])
{
while (pos[placementIndex] != '\0') placementIndex++;
switch (f)
{
case 'k':
pos[placementIndex] = sym.K;
break;
case 'r':
pos[placementIndex] = sym.R;
break;
case 'n':
pos[placementIndex] = sym.N;
break;
}
}
return new string(pos);
}
 
static void Main(string[] args)
{
Console.WriteLine(" ID Start position");
foreach (int id in new int[] { 0, 518, 959 })
{
Console.WriteLine($"{id,3} {Chess960(A, id)}");
}
Console.WriteLine("\nRandom");
Random rand = new Random();
for (int i = 0; i < 5; i++)
{
Console.WriteLine(Chess960(W, rand.Next(960)));
}
}
}
</syntaxhighlight>
{{out}}
<pre>
ID Start position
0 BBQNNRKR
518 RNBQKBNR
959 RKRNNQBB
 
Random
♘♕♖♔♗♖♘♗
♗♗♖♘♔♖♕♘
♖♕♘♔♖♗♗♘
♘♖♗♔♘♗♖♕
♖♘♕♗♔♘♗♖
 
</pre>
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <string>
#include <time.h>
Line 279 ⟶ 771:
return system( "pause" );
}
</syntaxhighlight>
</lang>
{{out}}
<pre>NQBRNBKR
Line 293 ⟶ 785:
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">(ns c960.core
(:gen-class)
(:require [clojure.string :as s]))
Line 330 ⟶ 822:
;; => "♖, ♕, ♘, ♔, ♗, ♗, ♘, ♖"
(c960 4)
;; => ("♘, ♖, ♔, ♘, ♗, ♗, ♖, ♕" "♗, ♖, ♔, ♘, ♘, ♕, ♖, ♗" "♘, ♕, ♗, ♖, ♔, ♗, ♘, ♖" "♖, ♔, ♘, ♘, ♕, ♖, ♗, ♗")</langsyntaxhighlight>
 
=={{header|Common Lisp}}==
 
===Common Lisp: generate from SP-ID===
{{trans|Raku}}
<syntaxhighlight lang="lisp">(defun chess960-from-sp-id
(&optional (sp-id (random 360 (make-random-state t))))
(labels
((combinations (lst r)
(cond
((numberp lst)
(combinations (loop for i from 0 while (< i lst) collect i) r))
((= r 1)
(mapcar #'list lst))
(t
(loop for i in lst append
(let ((left (loop for j in lst if (< i j) collect j)))
(mapcar (lambda (c) (cons i c))
(combinations left (1- r))))))))
 
(enumerate (ary)
(loop for item across ary for index from 0
collect (list index item))))
 
(let*
((first-bishop -1)
(knight-combo '())
(placements (list
;divisor function to get position piece symbol
(list 4 (lambda (n) (setq first-bishop n)
(1+ (* 2 n))) '♝)
(list 4 (lambda (n) ( - (* 2 n) (if (> n first-bishop) 1 0))) '♝)
(list 6 #'identity '♛)
(list 10 (lambda (n)
(setq knight-combo (nth n (combinations 5 2)))
(car knight-combo)) '♞)
(list 1 (lambda (n) (1- (cadr knight-combo))) '♞)
(list 1 (lambda (n) 0) '♜)
(list 1 (lambda (n) 0) '♚)
(list 1 (lambda (n) 0) '♜)))
(p sp-id)
(ary (make-array 8 :initial-element '-)))
 
(loop for (divisor func piece) in placements doing
(let* ((n (mod p divisor))
(square (funcall func n)))
(setq p (floor p divisor))
(setq index
(car (nth square (remove-if-not (lambda (p) (eq (cadr p) '-))
(enumerate ary)))))
(setf (aref ary index) piece)))
 
(list sp-id ary))))
 
;; demo
 
(format t "~a~%" (chess960-from-sp-id 518))
(format t "~a~%" (chess960-from-sp-id))</syntaxhighlight>
 
{{Out}}<pre>(518 #(♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜))
(246 #(♞ ♜ ♝ ♚ ♛ ♝ ♞ ♜))</pre>
 
=={{header|D}}==
Line 336 ⟶ 889:
 
===D: Indexing===
<langsyntaxhighlight lang="d">void main() {
import std.stdio, std.range, std.algorithm, std.string, permutations2;
 
Line 348 ⟶ 901:
.map!toUpper.array.sort().uniq;
writeln(starts.walkLength, "\n", starts.front);
}</langsyntaxhighlight>
{{out}}
<pre>960
Line 354 ⟶ 907:
 
===D: Regexp===
<langsyntaxhighlight lang="d">void main() {
import std.stdio, std.regex, std.range, std.algorithm, permutations2;
 
Line 364 ⟶ 917:
.array.sort().uniq;
writeln(starts3.walkLength, "\n", starts3.front);
}</langsyntaxhighlight>
The output is the same.
 
===D: Correct by construction===
<langsyntaxhighlight lang="d">void main() {
import std.stdio, std.random, std.array, std.range;
 
Line 380 ⟶ 933:
start.insertInPlace(iota(bishpos % 2, start.length, 2)[uniform(0,$)], 'B');
start.writeln;
}</langsyntaxhighlight>
{{out}}
<pre>QBNNBRKR</pre>
 
=={{header|EasyLang}}==
{{trans|Lua}}
<syntaxhighlight>
len t$[] 8
proc randins c$ l r . pos .
repeat
pos = randint (r - l + 1) + l - 1
until t$[pos] = ""
.
t$[pos] = c$
.
randins "K" 2 7 king
randins "R" 1 (king - 1) h
randins "R" (king + 1) 8 h
randins "B" 1 8 b1
repeat
randins "B" 1 8 b2
until (b2 - b1) mod 2 <> 0
t$[b2] = ""
.
randins "Q" 1 8 b1
randins "N" 1 8 b1
randins "N" 1 8 b1
print strjoin t$[]
</syntaxhighlight>
{{out}}
<pre>
RBBNQNKR
</pre>
 
=={{header|EchoLisp}}==
<langsyntaxhighlight lang="lisp">(define-values (K Q R B N) (iota 5))
(define *pos* (list R N B Q K B N R)) ;; standard starter
 
Line 400 ⟶ 983:
(if (legal-pos *pos*)
(map unicode-piece *pos*) (c960)))
</syntaxhighlight>
</lang>
{{out}}
<pre>(define (unicode-piece i) (unicode->string (+ 0x2654 i)))
Line 417 ⟶ 1,000:
{{works with|Elixir|1.1}}
===Elixir: shuffle pieces until all regexes match===
<langsyntaxhighlight lang="elixir">defmodule Chess960 do
@pieces ~w(♔ ♕ ♘ ♘ ♗ ♗ ♖ ♖) # ~w(K Q N N B B R R)
@regexes [~r/♗(..)*♗/, ~r/♖.*♔.*♖/] # [~r/B(..)*B/, ~r/R.*K.*R/]
Line 427 ⟶ 1,010:
end
 
Enum.each(1..5, fn _ -> IO.puts Chess960.shuffle end)</langsyntaxhighlight>
{{out}}
<pre>♘♗♘♖♗♔♕♖
Line 436 ⟶ 1,019:
 
===Elixir: Construct===
<langsyntaxhighlight lang="elixir">defmodule Chess960 do
def construct do
row = Enum.reduce(~w[♕ ♘ ♘], ~w[♖ ♔ ♖], fn piece,acc ->
Line 448 ⟶ 1,031:
end
 
Enum.each(1..5, fn _ -> IO.puts Chess960.construct end)</langsyntaxhighlight>
{{out}}
<pre>♖♔♗♘♖♕♘♗
Line 457 ⟶ 1,040:
 
===Elixir: Generate from SP-ID===
<langsyntaxhighlight lang="elixir">defmodule Chess960 do
@krn ~w(NNRKR NRNKR NRKNR NRKRN RNNKR RNKNR RNKRN RKNNR RKNRN RKRNN)
Line 487 ⟶ 1,070:
end)
IO.puts "\nGenerate random Start Position"
Enum.each(1..5, fn _ -> IO.puts Chess960.start_position end)</langsyntaxhighlight>
{{out}}
<pre>Generate Start Position from ID number
Line 504 ⟶ 1,087:
===Single die method===
Using the single die method: https://en.wikipedia.org/wiki/Chess960_starting_position#Single_die_method
<langsyntaxhighlight lang="factor">USING: io kernel math random sequences ;
IN: rosetta-code.chess960
 
Line 531 ⟶ 1,114:
: chess960-demo ( -- ) 5 [ chess960 print ] times ;
 
MAIN: chess960-demo</langsyntaxhighlight>
{{out}}
<pre>
Line 543 ⟶ 1,126:
===Built-in===
Factor comes with a chess960 position generator:
<langsyntaxhighlight lang="factor">USING: chess960 prettyprint ;
 
chess960-position .</langsyntaxhighlight>
{{out}}
<pre>
Line 553 ⟶ 1,136:
=={{header|Forth}}==
 
<langsyntaxhighlight lang="forth">\ make starting position for Chess960, constructive
 
\ 0 1 2 3 4 5 6 7 8 9
Line 572 ⟶ 1,155:
959 chess960 \ RKRNNQBB ok
 
960 choose chess960 \ random position</langsyntaxhighlight>
 
=={{header|Fortran}}==
This implementation simply iterates through all 960 positions.
<langsyntaxhighlight lang="fortran">program chess960
implicit none
Line 633 ⟶ 1,216:
end program chess960
</syntaxhighlight>
</lang>
{{out}}
The first ten positions:
Line 646 ⟶ 1,229:
R K R N B N Q B
R K R B Q N B N</pre>
 
=={{header|FreeBASIC}}==
{{trans|Yabasic}}
<lang freebasic>
Randomize Timer
For i As Byte = 1 To 10
Dim As String inicio = "RKR", pieza = "QNN"
Dim As Byte posic
For n As Byte = 1 To Len(pieza)
posic = Int(Rnd*(Len(inicio) + 1)) + 1
inicio = Left(inicio, posic-1) + _
Mid(pieza, n, 1) +_
Right(inicio, Len(inicio) - posic + 1)
Next n
posic = Int(Rnd*(Len(inicio) + 1)) + 1
inicio = Left(inicio, posic-1) + "B" + Right(inicio, Len(inicio) - posic + 1)
posic = posic + 1 + 2 * Int(Int(Rnd*(Len(inicio) - posic)) / 2)
inicio = Left(inicio, posic-1) + "B" + Right(inicio, Len(inicio) - posic + 1)
Print inicio
Next i
</lang>
 
=={{header|Go}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 733 ⟶ 1,294:
fmt.Println(W.chess960(rand.Intn(960)))
}
}</langsyntaxhighlight>
{{out}}
<pre> ID Start position
Line 748 ⟶ 1,309:
 
=={{header|Haskell}}==
<langsyntaxhighlight Haskelllang="haskell">import Data.List
import qualified Data.Set as Set
 
Line 762 ⟶ 1,323:
main :: IO ()
main = mapM_ (putStrLn . concatMap show) . Set.toList . Set.fromList
. filter isChess960 $ permutations [R,N,B,Q,K,B,N,R]</langsyntaxhighlight>
{{out}}
<pre>QRKRBBNN
Line 772 ⟶ 1,333:
 
=={{header|J}}==
BuildThe simplest J approach for this task is to initially build a table of the starting positions. thenThen, for the task, we pick one position from the table at random. There are 40320 distinct permutations of 8 items and 5040 distinct permutations of these chess pieces and (as the task name points out) only 960 permutations which also satisfy the constraints on bishop and rook position, so little memory is needed to generate the table. Also, since the table is built at "compile time", execution is fast (though "compilation" is reasonably fast also).
 
<langsyntaxhighlight Jlang="j">row0=: u: 9812+2}.5|i.10
king=: u:9812
rook=: u:9814
Line 784 ⟶ 1,345:
perm=: A.&i.~ !
valid=: (#~ ok"1) ~.row0{"1~perm 8
gen=: valid {~ ? bind 960</langsyntaxhighlight>
 
Example use:
 
<langsyntaxhighlight Jlang="j"> gen''
♘♗♖♔♗♕♖♘
gen''
Line 795 ⟶ 1,356:
♖♗♔♘♘♕♗♖
gen''
♖♔♕♗♗♘♖♘</langsyntaxhighlight>
 
=={{header|Java}}==
{{works with|Java|1.5+}}
Regex inspired by (original) [[#Python: Regexp|Python Regexp]], prints ten examples.
<langsyntaxhighlight lang="java5">import java.util.Arrays;
import java.util.Collections;
import java.util.List;
Line 826 ⟶ 1,387:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>[R, N, K, N, R, B, B, Q]
Line 841 ⟶ 1,402:
=={{header|JavaScript}}==
This conforms to Altendörfer's single die method[https://en.wikipedia.org/wiki/Chess960_starting_position#Single_die_method], though the die will give no "needless" numbers.
<langsyntaxhighlight javaScriptlang="javascript">function ch960startPos() {
var rank = new Array(8),
// randomizer (our die)
Line 866 ⟶ 1,427:
 
// testing (10 times)
for (var x = 1; x <= 10; x++) console.log(ch960startPos().join(" | "));</langsyntaxhighlight>
{{out}}
<p>The test-output (exemplary each):</p>
Line 879 ⟶ 1,440:
♗ | ♘ | ♖ | ♘ | ♕ | ♗ | ♔ | ♖<br/>
♘ | ♗ | ♖ | ♔ | ♗ | ♘ | ♖ | ♕<br/>
 
=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
{{works with|jq}}
'''Also works with gojq, the Go implementation of jq'''
 
'''Also works with fq, a Go implementation of a large subset of jq'''
 
<syntaxhighlight lang=jq>
### Utilities
# The glyphs in .
def chars: explode[] | [.] | implode;
 
# input: an array
# $keys : an array of strings
def objectify($keys):
with_entries(.key = $keys[.key]) ;
 
def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;
 
 
def Symbols: ["k", "q", "r", "b", "n"];
 
def A: ["K", "Q", "R", "B", "N"] | objectify(Symbols);
def W: ["♔", "♕", "♖", "♗", "♘"] | objectify(Symbols);
def B: ["♚", "♛", "♜", "♝", "♞"] | objectify(Symbols);
 
def krn: [
"nnrkr", "nrnkr", "nrknr", "nrkrn",
"rnnkr", "rnknr", "rnkrn",
"rknnr", "rknrn",
"rkrnn"
];
 
# $sym specifies the Symbols
# $id specifies the position
def chess960($sym):
. as $id
| { q: (($id/4)|floor),
r: ($id % 4)
}
| .pos[.r*2+1] = $sym.b
| .t = .q
| .q |= ((./4)|floor)
| .r = (.t % 4)
| .pos[.r*2] = $sym.b
| .t = .q
| .q |= ((./6)|floor)
| .r = .t % 6
| .i = 0
| .break = false
| until( .break;
if .pos[.i] == null
then if .r == 0
then .pos[.i] = $sym.q
| .break = true
else .r += -1
end
else .
end
| .i += 1 )
| .i = 0
| reduce (krn[.q]|chars) as $f (.;
# find next insertion point
until(.pos[.i] == null; .i += 1)
| if $f | IN("k", "r", "n")
then .pos[.i] = $sym[$f]
else .
end )
| .pos
| join(" ") ;
 
def display960($sym):
"\(lpad(3)) \(chess960($sym))";
" ID Start position",
( 0, 518, 959 | display960(A) ),
"\nPseudo-random starting positions:",
(699, 889, 757, 645, 754 | display960(W))
</syntaxhighlight>
{{output}}
<pre>
ID Start position
0 B B Q N N R K R
518 R N B Q K B N R
959 R K R N N Q B B
 
Pseudo-random starting positions:
699 ♖ ♕ ♔ ♘ ♗ ♘ ♖ ♗
889 ♖ ♕ ♔ ♗ ♗ ♖ ♘ ♘
757 ♖ ♔ ♗ ♗ ♘ ♘ ♖ ♕
645 ♖ ♘ ♗ ♗ ♔ ♖ ♕ ♘
754 ♗ ♖ ♔ ♘ ♘ ♗ ♖ ♕
</pre>
 
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
<langsyntaxhighlight lang="julia">function generateposition()
# Placeholder knights
rank = ['♘', '♘', '♘', '♘', '♘', '♘', '♘', '♘']
Line 911 ⟶ 1,567:
end
 
@show generateposition()</langsyntaxhighlight>
{{out}}
<pre>generateposition() = ['♘', '♗', '♗', '♖', '♕', '♔', '♘', '♖']</pre>
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">object Chess960 : Iterable<String> {
override fun iterator() = patterns.iterator()
 
Line 945 ⟶ 1,601:
fun main(args: Array<String>) {
Chess960.forEachIndexed { i, s -> println("$i: $s") }
}</langsyntaxhighlight>
{{Out}}
<pre>0: BBNNQRKR
Line 956 ⟶ 1,612:
 
=={{header|Lua}}==
<langsyntaxhighlight Lualang="lua">-- Insert 'str' into 't' at a random position from 'left' to 'right'
function randomInsert (t, str, left, right)
local pos
Line 984 ⟶ 1,640:
-- Main procedure
math.randomseed(os.time())
print(table.concat(chess960()))</langsyntaxhighlight>
{{out}}
<pre>NNRQBBKR</pre>
 
=={{header|M2000 Interpreter}}==
 
<syntaxhighlight lang="m2000 interpreter">
Module Chess960 {
function OneFrom960$ {
def q$="♕", h$="♘", t$="♖", b$="♗", k$="♔"
def integer b1, b2, t1, t2, k, q
buffer p as integer *8
return p, 0:=string$(h$, 8)
k=random(1, 6)
t1=random(0,k-1)
t2=random(k+1, 7)
used=list:=k, t1, t2
do : b1=random(0,7): until not exist(used, b1)
append used, b1
n=b1 mod 2
do : b2=random(0,7): until not exist(used, b2) and b2 mod 2 <> n
append used, b2
do : q=random(0,7): until not exist(used, q)
// place pawns to positions
return p, k:=k$, t1:=t$, t2:=t$, b1:=b$, b2:=b$, q:=q$
=Eval$(p)+{
} // append new line to every solution
}
document doc$
For i=0 to 7:doc$+=OneFrom960$(): next
clipboard doc$
report doc$
}
Chess960
</syntaxhighlight>
{{out}}
<pre>
♘♗♗♘♖♕♔♖
♗♕♖♘♘♔♖♗
♗♗♕♖♔♘♖♘
♘♖♕♗♗♔♖♘
♖♔♘♗♖♕♗♘
♖♔♖♗♘♘♗♕
♘♘♗♕♖♗♔♖
♖♔♕♘♘♗♗♖
</pre>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
{{Output?}}
Generates all possible initial conditions, filters for validity, and chooses a random element.
<langsyntaxhighlight Mathematicalang="mathematica">Print[StringJoin[
RandomChoice[
Select[Union[
Line 999 ⟶ 1,698:
MatchQ[#, {___, "\[WhiteRook]", ___, "\[WhiteKing]", ___,
"\[WhiteRook]", ___}] &&
OddQ[Subtract @@ Flatten[Position[#, "\[WhiteBishop]"]]] &]]]];</langsyntaxhighlight>
 
=={{header|MiniScript}}==
This version uses the Unicode piece characters. If running in [[Mini Micro]] — which supports Unicode but does not have these characters in its font — just replace the the piece characters with letters.
<langsyntaxhighlight MiniScriptlang="miniscript">// placeholder knights
rank = ["♘"] * 8
 
Line 1,035 ⟶ 1,734:
rank[randFree(0, 7)] = "♕"
 
print join(rank, " ")</langsyntaxhighlight>
{{out}}
<pre>♘ ♖ ♕ ♔ ♖ ♘ ♗ ♗</pre>
 
=={{header|Nim}}==
<langsyntaxhighlight Nimlang="nim">import random, strutils
 
type
Line 1,108 ⟶ 1,807:
for piece in Pieces:
row[pos[piece]] = $piece
echo row.join(" ")</langsyntaxhighlight>
 
{{out}}
Line 1,124 ⟶ 1,823:
=={{header|Objeck}}==
{{trans|C++}}
<langsyntaxhighlight lang="objeck">class Chess960 {
function : Main(args : String[]) ~ Nil {
Generate(10);
Line 1,193 ⟶ 1,892:
return (Float->Random() * 1000)->As(Int) % 8;
}
}</langsyntaxhighlight>
 
Output:
Line 1,208 ⟶ 1,907:
 
=={{header|PARI/GP}}==
<langsyntaxhighlight lang="parigp">chess960() =
{
my (C = vector(8), i, j, r);
Line 1,216 ⟶ 1,915:
for (i = 1, 8, if (!C[i], C[i] = Vec("RKR")[j++]));
C
}</langsyntaxhighlight>
 
Output:<pre>gp > for(i=1, 10, print(chess960()));
Line 1,246 ⟶ 1,945:
=={{header|Perl}}==
Directly generates a configuration by inserting pieces at random appropriate places. Each config has an equal chance of being produced.
<langsyntaxhighlight lang="perl">sub rnd($) { int(rand(shift)) }
 
sub empties { grep !$_[0][$_], 0 .. 7 }
Line 1,262 ⟶ 1,961:
@s
}
print "@{[chess960]}\n" for 0 .. 10;</langsyntaxhighlight>
{{out}}
<pre>R N B K R N Q B
Line 1,281 ⟶ 1,980:
For something faster, and truer to the task description, just use the commented out permute(rand(factorial(8) line,
and quit as soon as you find a valid one (but I wanted to check that I had found exactly 960).
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>sequence solutions = {}
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
--integer d = new_dict()
<span style="color: #004080;">sequence</span> <span style="color: #000000;">solutions</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
 
<span style="color: #000080;font-style:italic;">--integer d = new_dict()</span>
for i=1 to factorial(8) do
sequence s = permute(i,"RNBQKBNR")
<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;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
-- sequence s = permute(rand(factorial(8),"RNBQKBNR")
<span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">permute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"RNBQKBNR"</span><span style="color: #0000FF;">)</span>
integer b1 = find('B',s),
<span style="color: #000080;font-style:italic;">-- sequence s = permute(rand(factorial(8),"RNBQKBNR")</span>
b2 = find('B',s,b1+1)
<span style="color: #004080;">integer</span> <span style="color: #000000;">b1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'B'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">),</span>
if and_bits(b2-b1,1)=1 then
<span style="color: #000000;">b2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'B'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b1</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
integer k = find('K',s)
<span style="color: #008080;">if</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">b1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
integer r1 = find('R',s)
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'K'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
integer r2 = find('R',s,r1+1)
<span style="color: #004080;">integer</span> <span style="color: #000000;">r1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'R'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
if r1<k and k<r2 then
<span style="color: #004080;">integer</span> <span style="color: #000000;">r2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'R'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r1</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
if find(s,solutions)=0 then
<span style="color: #008080;">if</span> <span style="color: #000000;">r1</span><span style="color: #0000FF;"><</span><span style="color: #000000;">k</span> <span style="color: #008080;">and</span> <span style="color: #000000;">k</span><span style="color: #0000FF;"><</span><span style="color: #000000;">r2</span> <span style="color: #008080;">then</span>
-- if getd_index(s,d)=0 then
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
-- setd(s,0,d)
<span style="color: #000080;font-style:italic;">-- if getd_index(s,d)=0 then
solutions = append(solutions,s)
-- end if setd(s,0,d)</span>
<span style="color: #000000;">solutions</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
printf(1,"Found %d solutions\n",{length(solutions)})
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for i=1 to 5 do
<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;">"Found %d solutions\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">)})</span>
?solutions[rand(length(solutions))]
<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;">5</span> <span style="color: #008080;">do</span>
end for</lang>
<span style="color: #0000FF;">?</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">))]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>Found 960 solutions
Line 1,316 ⟶ 2,018:
=={{header|PicoLisp}}==
{{Output?}}
<langsyntaxhighlight PicoLisplang="picolisp">(load "@lib/simul.l")
 
(seed (in "/dev/urandom" (rd 8)))
Line 1,331 ⟶ 2,033:
(prinl) )
 
(bye)</langsyntaxhighlight>
 
=={{header|PowerShell}}==
{{works with|powershell|2}}
<langsyntaxhighlight PowerShelllang="powershell">function Get-RandomChess960Start
{
$Starts = @()
Line 1,364 ⟶ 2,066:
Get-RandomChess960Start
Get-RandomChess960Start
</syntaxhighlight>
</lang>
{{out}}
<pre>♘♕♖♔♖♘♗♗
Line 1,370 ⟶ 2,072:
♖♗♔♕♗♖♘♘
♘♖♔♖♕♗♗♘</pre>
 
=={{header|Prolog}}==
Uses <code lang="prolog">random_permutation/2</code> defined in SWI-Prolog.
 
<syntaxhighlight lang="prolog">
check(Row) :-
nth1(King, Row, ♔),
nth1(Rook1, Row, ♖),
nth1(Rook2, Row, ♖),
nth1(Bishop1, Row, ♗),
nth1(Bishop2, Row, ♗),
Rook1 < King, King < Rook2,
(Bishop1 + Bishop2) mod 2 =:= 1.
 
generate(Row) :-
random_permutation([♖,♘,♗,♕,♔,♗,♘,♖], Row),
check(Row) ; generate(Row).
</syntaxhighlight>
 
Example run:
<syntaxhighlight lang="prolog">
?- generate(X).
X = [♘, ♗, ♖, ♕, ♘, ♔, ♗, ♖] ;
X = [♘, ♗, ♖, ♕, ♘, ♔, ♗, ♖] ;
X = [♘, ♖, ♘, ♕, ♔, ♖, ♗, ♗] ;
X = [♘, ♖, ♘, ♕, ♔, ♖, ♗, ♗]
</syntaxhighlight>
 
=={{header|Python}}==
Line 1,375 ⟶ 2,104:
This uses indexing rather than regexps. Rooks and bishops are in upper and lower case to start with so they can be individually indexed to apply the constraints. This would lead to some duplication of start positions if not for the use of a set comprehension to uniquify the, (upper-cased), start positions.
 
<langsyntaxhighlight lang="python">>>> from itertools import permutations
>>> pieces = 'KQRrBbNN'
>>> starts = {''.join(p).upper() for p in permutations(pieces)
Line 1,385 ⟶ 2,114:
>>> starts.pop()
'QNBRNKRB'
>>></langsyntaxhighlight>
 
===Python: Regexp===
This uses regexps to filter permutations of the start position pieces rather than indexing.
<langsyntaxhighlight lang="python">>>> import re
>>> pieces = 'KQRRBBNN'
>>> bish = re.compile(r'B(|..|....|......)B').search
Line 1,399 ⟶ 2,128:
>>> starts3.pop()
'QRNKBNRB'
>>></langsyntaxhighlight>
 
===Python: Correct by construction===
Follows Perl algorithm of constructing one start position randomly, according to the rules.
(See talk page for tests).
<langsyntaxhighlight lang="python">from random import choice
 
def random960():
Line 1,418 ⟶ 2,147:
return ''.join(start).upper()
 
print(random960())</langsyntaxhighlight>
{{out}}
<pre>['N', 'R', 'K', 'N', 'B', 'Q', 'R', 'B']</pre>
 
===Python: Generate all positions then choose one randomly===
<langsyntaxhighlight lang="python">from random import choice
 
def generate960():
Line 1,453 ⟶ 2,182:
 
gen = generate960()
print(''.join(choice(gen)))</langsyntaxhighlight>
{{out}}
<pre>NRBQNKRB</pre>
 
=={{header|R}}==
<langsyntaxhighlight lang="rsplus">
pieces <- c("R","B","N","Q","K","N","B","R")
 
Line 1,484 ⟶ 2,213:
 
cat(convert_to_unicode(generateFirstRank()), "\n")
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,494 ⟶ 2,223:
Constructive:
 
<langsyntaxhighlight lang="racket">#lang racket
(define white (match-lambda ['P #\♙] ['R #\♖] ['B #\♗] ['N #\♘] ['Q #\♕] ['K #\♔]))
(define black (match-lambda ['P #\♟] ['R #\♜] ['B #\♝] ['N #\♞] ['Q #\♛] ['K #\♚]))
Line 1,525 ⟶ 2,254:
(list->string (vector->list v)))
 
(chess960-start-position)</langsyntaxhighlight>
{{out}}
<pre>"♖♘♗♕♔♗♘♖"</pre>
Line 1,536 ⟶ 2,265:
(formerly Perl 6)
First, using a list with three rooks and no king, we keep generating a random piece order until the two bishops are on opposite colors. Then we sneakily promote the second of the three rooks to a king.
<syntaxhighlight lang="raku" perl6line>repeat until m/ '♗' [..]* '♗' / { $_ = < ♖ ♖ ♖ ♕ ♗ ♗ ♘ ♘ >.pick(*).join }
s:2nd['♖'] = '♔';
say .comb;</langsyntaxhighlight>
{{out}}
<big><big><big><big><pre>♕ ♗ ♖ ♘ ♔ ♖ ♗ ♘</pre></big></big></big></big>
Here's a more "functional" solution that avoids side effects
<syntaxhighlight lang="raku" perl6line>sub chess960 {
.subst(:nth(2), /'♜'/, '♚') given
first rx/ '♝' [..]* '♝' /,
Line 1,548 ⟶ 2,277:
}
 
say chess960;</langsyntaxhighlight>
{{out}}
<big><big><big><big><pre>♛♝♜♚♝♞♞♜</pre></big></big></big></big>
Line 1,556 ⟶ 2,285:
but written in the form of a list comprehension rather than nested map and grep. (The list comprehension is actually faster currently.) Note that the constant is calculated at compile time, because, well, it's a constant. Just a big fancy one.
 
<syntaxhighlight lang="raku" perl6line>constant chess960 =
< ♛ ♜ ♜ ♜ ♝ ♝ ♞ ♞ >.permutations».join.unique.grep( / '♝' [..]* '♝' / )».subst(:nth(2), /'♜'/, '♚');
 
.say for chess960;</langsyntaxhighlight>
Here's a much faster way (about 30x) to generate all 960 variants by construction. No need to filter for uniqueness, since it produces exactly 960 entries.
<syntaxhighlight lang="raku" perl6line>constant chess960 = gather for 0..3 -> $q {
(my @q = <♜ ♚ ♜>).splice($q, 0, '♛');
for 0 .. @q -> $n1 {
Line 1,580 ⟶ 2,309:
CHECK { note "done compiling" }
note +chess960;
say chess960.pick;</langsyntaxhighlight>
{{out}}
<pre>done compiling
Line 1,588 ⟶ 2,317:
 
<big><big><big><big><pre>♛♝♜♚♝♞♞♜</pre></big></big></big></big>
=== FromRaku: StartingGenerate Positionfrom SP-ID Number (SPID) ===
There is a [https://en.wikipedia.org/wiki/Fischer_random_chess_numbering_scheme standard numbering scheme] for Chess960 positions, assigning each an index in the range 0..959. This function will generate the corresponding position from a given index number (or fall back to a random one if no index is specified, making it yet another solution to the general problem).
 
<syntaxhighlight lang="raku" perl6line>subset Pos960 of Int where { $_ ~~ ^960 };
sub chess960(Pos960 $position = (^960).pick) {
 
Line 1,647 ⟶ 2,376:
# demo code
say chess960(518); #standard optning position
say chess960; # (it happened to pick #300)</langsyntaxhighlight>
 
{{Out}}
Line 1,656 ⟶ 2,385:
Random starting position is correct by construction &nbsp; (both REXX entries).
===generates one random position===
<langsyntaxhighlight lang="rexx">/*REXX program generates a random starting position for the Chess960 game. */
parse arg seed . /*allow for (RANDOM BIF) repeatability.*/
if seed\=='' then call random ,,seed /*if SEED was specified, use the seed.*/
Line 1,681 ⟶ 2,410:
_= /*only the queen is left to be placed. */
do i=1 for 8; _=_ || @.i; end /*construct the output: first rank only*/
say translate(translate(_, 'q', .)) /*stick a fork in it, we're all done. */</langsyntaxhighlight>
'''output'''
<pre>NRQKBRNB</pre>
 
===generates all 960 positions randomly===
<langsyntaxhighlight lang="rexx">/*REXX program generates all random starting positions for the Chess960 game. */
parse arg seed . /*allow for (RANDOM BIF) repeatability.*/
if seed\=='' then call random ,,seed /*if SEED was specified, use the seed.*/
Line 1,723 ⟶ 2,452:
say # 'unique starting positions found after ' t "generations."
/*stick a fork in it, we're all done. */ /**/</langsyntaxhighlight>
'''output'''
<pre> 1000 random generations: 515 unique starting positions.
Line 1,741 ⟶ 2,470:
960 unique starting positions found after 14639 generations.</pre>
===version 3 COMPUTE all possibilities===
<langsyntaxhighlight lang="rexx">/*---------------------------------------------------------------
* Compute the 960 possible solutions
* There must be at least one field between the rooks
Line 1,801 ⟶ 2,530:
If cnt.1=4 Then
Say ' ...'
Return</langsyntaxhighlight>
{{out}}
<pre> 1 45678 1 2 3 RKRQBBNN
Line 1,811 ⟶ 2,540:
960 12345 6 7 8 NNBBQRKR
960 solutions</pre>
 
=={{header|RPL}}==
We use here the single die method, starting with a list of rooks that are gradually replaced by other pieces.
{{works with|HP|48G}}
≪ SWAP 1 ≪ 'R' SAME ≫ DOLIST 0 SWAP
1 OVER SIZE '''FOR''' j
DUP j GET ROT + SWAP
j 3 PICK PUT
'''NEXT'''
SWAP DROP SWAP POS
≫ '<span style="color:blue">ROOKPOS</span>' STO
≪ { } 1 8 '''START''' 'R' + '''NEXT'''
RAND 4 * FLOOR 2 * 1 + 'B' PUT
RAND 4 * CEIL 2 * 'B' PUT
DUP RAND 6 * CEIL <span style="color:blue">ROOKPOS</span> 'Q' PUT
DUP RAND 5 * CEIL <span style="color:blue">ROOKPOS</span> 'N' PUT
DUP RAND 4 * CEIL <span style="color:blue">ROOKPOS</span> 'N' PUT
DUP 2 <span style="color:blue">ROOKPOS</span> 'K' PUT
≫ '<span style="color:blue">→CH360</span>' STO
{{out}}
<pre>
3: { N Q R K B B R N }
2: { R K B B R Q N N }
1: { Q N R B K N B R }
</pre>
 
=={{header|Ruby}}==
===Ruby: shuffle pieces until all regexes match===
Translation of Tcl.
<langsyntaxhighlight lang="ruby">pieces = %i(♔ ♕ ♘ ♘ ♗ ♗ ♖ ♖)
regexes = [/♗(..)*♗/, /♖.*♔.*♖/]
row = pieces.shuffle.join until regexes.all?{|re| re.match(row)}
puts row</langsyntaxhighlight>
{{output}}
<big><big><big><big><pre>♕♖♗♘♔♖♘♗</pre></big></big></big></big>
Line 1,824 ⟶ 2,579:
===Ruby: Construct===
Uses the Perl idea of starting with [R,K,R] and inserting the rest:
<langsyntaxhighlight lang="ruby">row = [:♖, :♔, :♖]
[:♕, :♘, :♘].each{|piece| row.insert(rand(row.size+1), piece)}
[[0, 2, 4, 6].sample, [1, 3, 5, 7].sample].sort.each{|pos| row.insert(pos, :♗)}
 
puts row</langsyntaxhighlight>
{{output}}
<big><big><big><big><pre>♗♘♕♘♖♗♔♖</pre></big></big></big></big>
Line 1,834 ⟶ 2,589:
===Ruby: Generate from SP-ID===
'''[[wp:Chess960 numbering scheme|Chess960 numbering scheme]]'''
<langsyntaxhighlight lang="ruby">KRN = %w(NNRKR NRNKR NRKNR NRKRN RNNKR RNKNR RNKRN RKNNR RKNRN RKRNN)
 
def chess960(id=rand(960))
Line 1,855 ⟶ 2,610:
 
puts "\nGenerate random Start Position"
5.times {puts chess960}</langsyntaxhighlight>
{{out}}
<pre>Generate Start Position from id number
Line 1,872 ⟶ 2,627:
{{Output?}}
{{trans|Kotlin}}
<langsyntaxhighlight lang="rust">use std::collections::BTreeSet;
 
struct Chess960 ( BTreeSet<String> );
Line 1,906 ⟶ 2,661:
println!("{}: {}", i, p);
}
}</langsyntaxhighlight>
 
 
===Rust 1.57 nightly===
<syntaxhighlight lang="rust">
// Chess960: regex and unicode version, create 5 valid random positions.
 
use rand::{seq::SliceRandom, thread_rng};
use regex::Regex;
 
fn vec_to_string(v: Vec<&str>) -> String {
let mut is_string = String::new();
for ele in v {
is_string.push_str(ele)
}
is_string
}
fn is_rook_king_ok(str_to_check: Vec<&str>) -> bool {
Regex::new(r"(.*♖.*♔.*♖.*)")
.unwrap()
.is_match(vec_to_string(str_to_check.clone()).as_str())
}
fn is_two_bishops_ok(str_to_check: Vec<&str>) -> bool {
Regex::new(r"(.*♗.{0}♗.*|.*♗.{2}♗.*|.*♗.{4}♗.*|.*♗.{6}♗.*)")
.unwrap()
.is_match(vec_to_string(str_to_check.clone()).as_str())
}
fn create_rnd_candidate() -> [&'static str; 8] {
let mut rng = thread_rng();
let mut chaine = ["♖", "♘", "♗", "♔", "♕", "♗", "♘", "♖"];
 
loop {
chaine.shuffle(&mut rng);
if is_candidate_valide(chaine) {
break chaine;
}
}
}
fn is_candidate_valide(s: [&str; 8]) -> bool {
is_rook_king_ok(s.to_vec()) && is_two_bishops_ok(s.to_vec())
}
fn main() {
for _ in 0..5 {
println!("{:?}", create_rnd_candidate());
}
}</syntaxhighlight>
{{out}}
<pre>["♕", "♘", "♗", "♗", "♖", "♘", "♔", "♖"]
["♖", "♔", "♗", "♕", "♘", "♗", "♖", "♘"]
["♗", "♖", "♕", "♔", "♘", "♗", "♖", "♘"]
["♘", "♖", "♘", "♕", "♔", "♖", "♗", "♗"]
["♖", "♗", "♕", "♔", "♗", "♘", "♖", "♘"]</pre>
 
=={{header|Scala}}==
===Functional Programming, tail recursive, Unicode, RegEx===
<langsyntaxhighlight Scalalang="scala">import scala.annotation.tailrec
 
object Chess960 extends App {
Line 1,934 ⟶ 2,740:
if (n <= 0) () else loop(n - 1)
}
}</langsyntaxhighlight>
{{Out}}See it running in your browser by [https://scalafiddle.io/sf/AkvVAlG/0 ScalaFiddle (JavaScript, non JVM)] or by [https://scastie.scala-lang.org/qpKdhOc4SkuAbze8kgU6zQ Scastie (JVM)].
===Imperative Programming===
{{trans|Kotlin}}
<langsyntaxhighlight lang="scala">object Chess960 extends App {
private def apply(b: String, e: String) {
if (e.length <= 1) {
Line 1,958 ⟶ 2,764:
apply("", "KQRRNNBB")
for ((s, i) <- patterns.zipWithIndex) println(s"$i: $s")
}</langsyntaxhighlight>
 
=={{header|Scheme}}==
{{libheader|Scheme/SRFIs}}
 
<langsyntaxhighlight Schemelang="scheme">(import (scheme base) (scheme write)
(srfi 1) ; list library
(srfi 27)) ; random numbers
Line 2,019 ⟶ 2,825:
 
(display "First rank: ") (display (random-piece-positions)) (newline)
</syntaxhighlight>
</lang>
{{out}}
Ten sample runs:
Line 2,034 ⟶ 2,840:
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const proc: main is func
Line 2,051 ⟶ 2,857:
start := start[.. pred(pos)] & "B" & start[pos ..];
writeln(start);
end func;</langsyntaxhighlight>
{{out}}
<pre>NQBNRBKR</pre>
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">func is_valid_960 (backrank) {
var king = backrank.index('♚')
var (rook1, rook2) = backrank.indices_of('♜')...
Line 2,070 ⟶ 2,876:
}
 
say random_960_position().join(' ')</langsyntaxhighlight>
{{out}}
<pre>
♝ ♝ ♜ ♚ ♞ ♛ ♜ ♞
</pre>
 
=={{header|Swift}}==
 
<syntaxhighlight lang="swift">func isValid960Position(_ firstRank: String) -> Bool {
var rooksPlaced = 0
var bishopColor = -1
 
for (i, piece) in firstRank.enumerated() {
switch piece {
case "♚" where rooksPlaced != 1:
return false
case "♜":
rooksPlaced += 1
case "♝" where bishopColor == -1:
bishopColor = i & 1
case "♝" where bishopColor == i & 1:
return false
case _:
continue
}
}
 
return true
}
 
struct Chess960Counts {
var king = 0, queen = 0, rook = 0, bishop = 0, knight = 0
 
subscript(_ piece: String) -> Int {
get {
switch piece {
case "♚": return king
case "♛": return queen
case "♜": return rook
case "♝": return bishop
case "♞": return knight
case _: fatalError()
}
}
 
set {
switch piece {
case "♚": king = newValue
case "♛": queen = newValue
case "♜": rook = newValue
case "♝": bishop = newValue
case "♞": knight = newValue
case _: fatalError()
}
}
}
}
 
func get960Position() -> String {
var counts = Chess960Counts()
var bishopColor = -1 // 0 - white 1 - black
var output = ""
 
for i in 1...8 {
let validPieces = [
counts["♜"] == 1 && counts["♚"] == 0 ? "♚" : nil, // king
i == 1 || (counts["♛"] == 0) ? "♛" : nil, // queen
i == 1 || (counts["♜"] == 0 || counts["♜"] < 2 && counts["♚"] == 1) ? "♜" : nil, // rook
i == 1 || (counts["♝"] < 2 && bishopColor == -1 || bishopColor != i & 1) ? "♝" : nil, // bishop
i == 1 || (counts["♞"] < 2) ? "♞" : nil // knight
].lazy.compactMap({ $0 })
 
guard let chosenPiece = validPieces.randomElement() else {
// Need to swap last piece with a bishop
output.insert("♝", at: output.index(before: output.endIndex))
 
break
}
 
counts[chosenPiece] += 1
output += chosenPiece
 
if bishopColor == -1 && chosenPiece == "♝" {
bishopColor = i & 1
}
}
 
assert(isValid960Position(output), "invalid 960 position \(output)")
 
return output
}
 
var positions = Set<String>()
 
while positions.count != 960 {
positions.insert(get960Position())
}
 
print(positions.count, positions.randomElement()!)</syntaxhighlight>
 
{{out}}
 
<pre>960 ♞♛♜♞♚♝♝♜</pre>
 
=={{header|Tcl}}==
Using regular expressions to filter a random permutation.
{{tcllib|struct::list}}
<langsyntaxhighlight lang="tcl">package require struct::list
 
proc chess960 {} {
Line 2,096 ⟶ 3,000:
 
# Output multiple times just to show scope of positions
foreach - {1 2 3 4 5} {puts [chessRender [chess960]]}</langsyntaxhighlight>
{{out}}
<pre>♕♖♘♔♗♗♘♖
Line 2,103 ⟶ 3,007:
♘♕♗♖♔♖♘♗
♘♘♖♔♗♗♕♖</pre>
 
=={{header|UNIX Shell}}==
{{trans|raku}}
{{works with|bash}}
<syntaxhighlight lang=bash>declare -a pieces=(♖ ♖ ♖ ♕ ♗ ♗ ♘ ♘)
declare -i i pick index
declare -ai picking_history
declare attempt
 
until [[ "$attempt" =~ ♗(..)*♗ ]]
do
attempt=''
picking_history=()
for _ in {1..8}
do
while ((picking_history[pick=RANDOM%8]++))
do :
done
attempt+="${pieces[pick]}"
done
done
for i in {0..7}
do
if [[ "${attempt:i:1}" = ♖ ]] && ((index++))
then echo "${attempt:0:i}♔${attempt:i+1}"; break;
fi
done</syntaxhighlight>
 
=={{header|Wren}}==
Line 2,108 ⟶ 3,039:
{{libheader|Wren-dynamic}}
{{libheader|Wren-fmt}}
<langsyntaxhighlight ecmascriptlang="wren">import "random" for Random
import "./dynamic" for Tuple
import "./fmt" for Fmt
 
var Symbols = Tuple.create("Symbols", ["k", "q", "r", "b", "n"])
Line 2,164 ⟶ 3,095:
System.print("\nRandom")
var rand = Random.new()
for (i in 0..4) System.print(chess960.call(W, rand.int(960)))</langsyntaxhighlight>
 
{{out}}
Line 2,181 ⟶ 3,112:
</pre>
 
=={{header|YabasicXPL0}}==
<syntaxhighlight lang="xpl0">char Col;
{{trans|Seed7}}
<lang Yabasic>start$ = "RKR"
piece$ = "QNN"
 
func ColNum(Start, Piece); \Return column number of Piece
for piece = 1 to len(piece$)
int Start, Piece, I;
pos = int(ran(len(start$) + 1)) + 1
[for I:= Start to 7 do
start$ = left$(start$, pos-1) + mid$(piece$, piece, 1) + right$(start$, len(start$) - pos + 1)
if Col(I) = Piece then return I;
next
return -1;
pos = int(ran(len(start$) + 1)) + 1
];
start$ = left$(start$, pos-1) + "B" + right$(start$, len(start$) - pos + 1)
 
pos = pos + 1 + 2 * int(int(ran(len(start$) - pos)) / 2)
proc Shuffle; \Randomly rearrange pieces in columns
start$ = left$(start$, pos-1) + "B" + right$(start$, len(start$) - pos + 1)
int I, J, T;
print start$
[for I:= 8-1 downto 1 do
</lang>
[J:= Ran(I); \range [0..I-1] (Sattolo cycle)
T:= Col(I); Col(I):= Col(J); Col(J):= T;
];
];
 
int N, B1, B2, BOK, R1, R2, K, KOK;
[for N:= 1 to 5 do
[Col:= "RNBQKBNR ";
repeat Shuffle;
B1:= ColNum(0, ^B);
B2:= ColNum(B1+1, ^B);
BOK:= ((B1 xor B2) and 1) # 0;
R1:= ColNum(0, ^R);
R2:= ColNum(R1+1, ^R);
K:= ColNum(0, ^K);
KOK:= R1<K and K<R2;
until BOK and KOK;
Text(0, Col); CrLf(0);
];
]</syntaxhighlight>
 
{{out}}
<pre>
BNRBQKRN
RBKNNQBR
BQRBNKNR
NRBBQKNR
RNKNBQRB
</pre>
 
=={{header|zkl}}==
{{trans|D}}
<langsyntaxhighlight lang="zkl">const pieces="KQRrBbNN";
starts:=pieces:Utils.Helpers.permuteW(_).filter(fcn(p){
I:=p.index;
Line 2,206 ⟶ 3,164:
((I("r") < I("K") and I("K") < I("R")) or
(I("R") < I("K") and I("K") < I("r")))
}).pump(List,"concat","toUpper"):Utils.Helpers.listUnique(_);</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">N:=starts.len(); println(N);
glyphs:=Dictionary("K","\u2654", "Q","\u2655", "R","\u2656", "B","\u2657", "N","\u2658");
// pick some random starts and transform BBNRKQRN to glyphs
do(10){ starts[(0).random(N)].apply(glyphs.find).println() }</langsyntaxhighlight>
{{out}}
<pre>960
1,982

edits