Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
4
Task/Generate-Chess960-starting-position/00-META.yaml
Normal file
4
Task/Generate-Chess960-starting-position/00-META.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
category:
|
||||
- Chess960
|
||||
from: http://rosettacode.org/wiki/Generate_Chess960_starting_position
|
||||
16
Task/Generate-Chess960-starting-position/00-TASK.txt
Normal file
16
Task/Generate-Chess960-starting-position/00-TASK.txt
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
'''[[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:
|
||||
|
||||
* as in the standard chess game, all eight white pawns must be placed on the second rank.
|
||||
* White pieces must stand on the first rank as in the standard game, in random column order but with the two following constraints:
|
||||
** the bishops must be placed on opposite color squares (i.e. they must be an odd number of spaces apart or there must be an even number of spaces between them)
|
||||
** the King must be between two rooks (with any number of other pieces between them all)
|
||||
* Black pawns and pieces must be placed respectively on the seventh and eighth ranks, mirroring the white pawns and pieces, just as in the standard game. (That is, their positions are not independently randomized.)
|
||||
|
||||
<br>
|
||||
With those constraints there are '''960''' possible starting positions, thus the name of the variant.
|
||||
|
||||
|
||||
;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 with [[wp:Chess symbols in Unicode|Chess symbols in Unicode: ♔♕♖♗♘]] or with the letters '''K'''ing '''Q'''ueen '''R'''ook '''B'''ishop k'''N'''ight.
|
||||
<br><br>
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
F random960()
|
||||
V start = [‘R’, ‘K’, ‘R’]
|
||||
|
||||
L(piece) [‘Q’, ‘N’, ‘N’]
|
||||
start.insert(random:(start.len + 1), piece)
|
||||
|
||||
V bishpos = random:(start.len + 1)
|
||||
start.insert(bishpos, Char(‘B’))
|
||||
start.insert(random:(bishpos + 1), Char(‘B’))
|
||||
R start
|
||||
|
||||
print(random960())
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
⍝ 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
|
||||
∇
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
; 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
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
Loop, 5
|
||||
Out .= Chess960() "`n"
|
||||
MsgBox, % RTrim(Out, "`n")
|
||||
|
||||
Chess960() {
|
||||
P := {}
|
||||
P[K := Rand(2, 7)] := Chr(0x2654) ; King
|
||||
P[Rand(1, K - 1)] := Chr(0x2656) ; Rook 1
|
||||
P[Rand(K + 1, 8)] := Chr(0x2656) ; Rook 2
|
||||
Loop, 8
|
||||
Remaining .= P[A_Index] ? "" : A_Index "`n"
|
||||
Sort, Remaining, Random N
|
||||
P[Bishop1 := SubStr(Remaining, 1, 1)] := Chr(0x2657) ; Bishop 1
|
||||
Remaining := SubStr(Remaining, 3)
|
||||
Loop, Parse, Remaining, `n
|
||||
if (Mod(Bishop1 - A_LoopField, 2))
|
||||
Odd .= A_LoopField "`n"
|
||||
else
|
||||
Even .= A_LoopField "`n"
|
||||
X := StrSplit(Odd Even, "`n")
|
||||
P[X.1] := Chr(0x2657) ; Bishop 2
|
||||
P[X.2] := Chr(0x2655) ; Queen
|
||||
P[X.3] := Chr(0x2658) ; Knight 1
|
||||
P[X.4] := Chr(0x2658) ; Knight 2
|
||||
for Key, Val in P
|
||||
Out .= Val
|
||||
return Out
|
||||
}
|
||||
|
||||
Rand(Min, Max) {
|
||||
Random, n, Min, Max
|
||||
return n
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#.#.#.#.065*0#v_1-\>>?1v
|
||||
v,":".:%*8"x"$<^!:\*2<+<
|
||||
>48*,:4%2*1#v+#02#\3#g<<
|
||||
v"B"*2%4:/4p<vg0:+1<\-1<
|
||||
>\0p4/:6%0:0g>68*`#^_\:|
|
||||
v"RKRNN"p11/6$p0\ "Q" \<
|
||||
>"NRNKRRNNKRNRKNRRNKNR"v
|
||||
v"NRNKRNRKNRNRKRNRNNKR"<
|
||||
>"RKRNN"11g:!#v_\$\$\$\v
|
||||
v _v#!`*86:g0:<^!:-1$\$<
|
||||
>$\>,1+ :7`#@_^> v960v <
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
void placeRandomly(char* p, char c)
|
||||
{
|
||||
int loc = rand() % 8;
|
||||
if (!p[loc])
|
||||
p[loc] = c;
|
||||
else
|
||||
placeRandomly(p, c); // try again
|
||||
}
|
||||
int placeFirst(char* p, char c, int loc = 0)
|
||||
{
|
||||
while (p[loc]) ++loc;
|
||||
p[loc] = c;
|
||||
return loc;
|
||||
}
|
||||
|
||||
string startPos()
|
||||
{
|
||||
char p[8]; memset( p, 0, 8 );
|
||||
|
||||
// bishops on opposite color
|
||||
p[2 * (rand() % 4)] = 'B';
|
||||
p[2 * (rand() % 4) + 1] = 'B';
|
||||
|
||||
// queen knight knight, anywhere
|
||||
for (char c : "QNN")
|
||||
placeRandomly(p, c);
|
||||
|
||||
// rook king rook, in that order
|
||||
placeFirst(p, 'R', placeFirst(p, 'K', placeFirst(p, 'R')));
|
||||
|
||||
return string(p, 8);
|
||||
}
|
||||
} // leave local
|
||||
|
||||
namespace chess960
|
||||
{
|
||||
void generate( int c )
|
||||
{
|
||||
for( int x = 0; x < c; x++ )
|
||||
cout << startPos() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
srand( time( NULL ) );
|
||||
chess960::generate( 10 );
|
||||
cout << "\n\n";
|
||||
return system( "pause" );
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
#include<stdlib.h>
|
||||
#include<locale.h>
|
||||
#include<wchar.h>
|
||||
#include<stdio.h>
|
||||
#include<time.h>
|
||||
|
||||
char rank[9];
|
||||
|
||||
int pos[8];
|
||||
|
||||
void swap(int i,int j){
|
||||
int temp = pos[i];
|
||||
pos[i] = pos[j];
|
||||
pos[j] = temp;
|
||||
}
|
||||
|
||||
void generateFirstRank(){
|
||||
int kPos,qPos,bPos1,bPos2,rPos1,rPos2,nPos1,nPos2,i;
|
||||
|
||||
for(i=0;i<8;i++){
|
||||
rank[i] = 'e';
|
||||
pos[i] = i;
|
||||
}
|
||||
|
||||
do{
|
||||
kPos = rand()%8;
|
||||
rPos1 = rand()%8;
|
||||
rPos2 = rand()%8;
|
||||
}while((rPos1-kPos<=0 && rPos2-kPos<=0)||(rPos1-kPos>=0 && rPos2-kPos>=0)||(rPos1==rPos2 || kPos==rPos1 || kPos==rPos2));
|
||||
|
||||
rank[pos[rPos1]] = 'R';
|
||||
rank[pos[kPos]] = 'K';
|
||||
rank[pos[rPos2]] = 'R';
|
||||
|
||||
swap(rPos1,7);
|
||||
swap(rPos2,6);
|
||||
swap(kPos,5);
|
||||
|
||||
do{
|
||||
bPos1 = rand()%5;
|
||||
bPos2 = rand()%5;
|
||||
}while(((pos[bPos1]-pos[bPos2])%2==0)||(bPos1==bPos2));
|
||||
|
||||
rank[pos[bPos1]] = 'B';
|
||||
rank[pos[bPos2]] = 'B';
|
||||
|
||||
swap(bPos1,4);
|
||||
swap(bPos2,3);
|
||||
|
||||
do{
|
||||
qPos = rand()%3;
|
||||
nPos1 = rand()%3;
|
||||
}while(qPos==nPos1);
|
||||
|
||||
rank[pos[qPos]] = 'Q';
|
||||
rank[pos[nPos1]] = 'N';
|
||||
|
||||
for(i=0;i<8;i++)
|
||||
if(rank[i]=='e'){
|
||||
rank[i] = 'N';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void printRank(){
|
||||
int i;
|
||||
|
||||
#ifdef _WIN32
|
||||
printf("%s\n",rank);
|
||||
#else
|
||||
{
|
||||
setlocale(LC_ALL,"");
|
||||
printf("\n");
|
||||
for(i=0;i<8;i++){
|
||||
if(rank[i]=='K')
|
||||
printf("%lc",(wint_t)9812);
|
||||
else if(rank[i]=='Q')
|
||||
printf("%lc",(wint_t)9813);
|
||||
else if(rank[i]=='R')
|
||||
printf("%lc",(wint_t)9814);
|
||||
else if(rank[i]=='B')
|
||||
printf("%lc",(wint_t)9815);
|
||||
if(rank[i]=='N')
|
||||
printf("%lc",(wint_t)9816);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
|
||||
srand((unsigned)time(NULL));
|
||||
|
||||
for(i=0;i<9;i++){
|
||||
generateFirstRank();
|
||||
printRank();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
(ns c960.core
|
||||
(:gen-class)
|
||||
(:require [clojure.string :as s]))
|
||||
|
||||
;; legal starting rank - unicode chars for rook, knight, bishop, queen, king, bishop, knight, rook
|
||||
(def starting-rank [\♖ \♘ \♗ \♕ \♔ \♗ \♘ \♖])
|
||||
|
||||
(defn bishops-legal?
|
||||
"True if Bishops are odd number of indicies apart"
|
||||
[rank]
|
||||
(odd? (apply - (cons 0 (sort > (keep-indexed #(when (= \♗ %2) %1) rank))))))
|
||||
|
||||
(defn king-legal?
|
||||
"True if the king is between two rooks"
|
||||
[rank]
|
||||
(let [king-&-rooks (filter #{\♔ \♖} rank)]
|
||||
(and
|
||||
(= 3 (count king-&-rooks))
|
||||
(= \u2654 (second king-&-rooks)))))
|
||||
|
||||
|
||||
(defn c960
|
||||
"Return a legal rank for c960 chess"
|
||||
([] (c960 1))
|
||||
([n]
|
||||
(->> #(shuffle starting-rank)
|
||||
repeatedly
|
||||
(filter #(and (king-legal? %) (bishops-legal? %)))
|
||||
(take n)
|
||||
(map #(s/join ", " %)))))
|
||||
|
||||
|
||||
(c960)
|
||||
;; => "♗, ♖, ♔, ♕, ♘, ♘, ♖, ♗"
|
||||
(c960)
|
||||
;; => "♖, ♕, ♘, ♔, ♗, ♗, ♘, ♖"
|
||||
(c960 4)
|
||||
;; => ("♘, ♖, ♔, ♘, ♗, ♗, ♖, ♕" "♗, ♖, ♔, ♘, ♘, ♕, ♖, ♗" "♘, ♕, ♗, ♖, ♔, ♗, ♘, ♖" "♖, ♔, ♘, ♘, ♕, ♖, ♗, ♗")
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
(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))
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
void main() {
|
||||
import std.stdio, std.range, std.algorithm, std.string, permutations2;
|
||||
|
||||
const pieces = "KQRrBbNN";
|
||||
alias I = indexOf;
|
||||
auto starts = pieces.dup.permutations.filter!(p =>
|
||||
I(p, 'B') % 2 != I(p, 'b') % 2 && // Bishop constraint.
|
||||
// King constraint.
|
||||
((I(p, 'r') < I(p, 'K') && I(p, 'K') < I(p, 'R')) ||
|
||||
(I(p, 'R') < I(p, 'K') && I(p, 'K') < I(p, 'r'))))
|
||||
.map!toUpper.array.sort().uniq;
|
||||
writeln(starts.walkLength, "\n", starts.front);
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
void main() {
|
||||
import std.stdio, std.regex, std.range, std.algorithm, permutations2;
|
||||
|
||||
immutable pieces = "KQRRBBNN";
|
||||
immutable bish = r"B(|..|....|......)B";
|
||||
immutable king = r"R.*K.*R";
|
||||
auto starts3 = permutations(pieces.dup)
|
||||
.filter!(p => p.match(bish) && p.match(king))
|
||||
.array.sort().uniq;
|
||||
writeln(starts3.walkLength, "\n", starts3.front);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
void main() {
|
||||
import std.stdio, std.random, std.array, std.range;
|
||||
|
||||
// Subsequent order unchanged by insertions.
|
||||
auto start = "RKR".dup;
|
||||
foreach (immutable piece; "QNN")
|
||||
start.insertInPlace(uniform(0, start.length), piece);
|
||||
|
||||
immutable bishpos = uniform(0, start.length);
|
||||
start.insertInPlace(bishpos, 'B');
|
||||
start.insertInPlace(iota(bishpos % 2, start.length, 2)[uniform(0,$)], 'B');
|
||||
start.writeln;
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
(define-values (K Q R B N) (iota 5))
|
||||
(define *pos* (list R N B Q K B N R)) ;; standard starter
|
||||
|
||||
;; check opposite color bishops, and King between rooks
|
||||
(define (legal-pos p)
|
||||
(and
|
||||
(> (list-index K p) (list-index R p))
|
||||
(> (list-index K (reverse p)) (list-index R (reverse p)))
|
||||
(even? (+ (list-index B p) (list-index B (reverse p))))))
|
||||
|
||||
;; random shuffle current position until a legal one is found
|
||||
(define (c960)
|
||||
(set! *pos* (shuffle *pos*))
|
||||
(if (legal-pos *pos*)
|
||||
(map unicode-piece *pos*) (c960)))
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
defmodule Chess960 do
|
||||
@pieces ~w(♔ ♕ ♘ ♘ ♗ ♗ ♖ ♖) # ~w(K Q N N B B R R)
|
||||
@regexes [~r/♗(..)*♗/, ~r/♖.*♔.*♖/] # [~r/B(..)*B/, ~r/R.*K.*R/]
|
||||
|
||||
def shuffle do
|
||||
row = Enum.shuffle(@pieces) |> Enum.join
|
||||
if Enum.all?(@regexes, &Regex.match?(&1, row)), do: row, else: shuffle
|
||||
end
|
||||
end
|
||||
|
||||
Enum.each(1..5, fn _ -> IO.puts Chess960.shuffle end)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
defmodule Chess960 do
|
||||
def construct do
|
||||
row = Enum.reduce(~w[♕ ♘ ♘], ~w[♖ ♔ ♖], fn piece,acc ->
|
||||
List.insert_at(acc, :rand.uniform(length(acc)+1)-1, piece)
|
||||
end)
|
||||
[Enum.random([0, 2, 4, 6]), Enum.random([1, 3, 5, 7])]
|
||||
|> Enum.sort
|
||||
|> Enum.reduce(row, fn pos,acc -> List.insert_at(acc, pos, "♗") end)
|
||||
|> Enum.join
|
||||
end
|
||||
end
|
||||
|
||||
Enum.each(1..5, fn _ -> IO.puts Chess960.construct end)
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
defmodule Chess960 do
|
||||
@krn ~w(NNRKR NRNKR NRKNR NRKRN RNNKR RNKNR RNKRN RKNNR RKNRN RKRNN)
|
||||
|
||||
def start_position, do: start_position(:rand.uniform(960)-1)
|
||||
|
||||
def start_position(id) do
|
||||
pos = List.duplicate(nil, 8)
|
||||
q = div(id, 4)
|
||||
r = rem(id, 4)
|
||||
pos = List.replace_at(pos, r * 2 + 1, "B")
|
||||
q = div(q, 4)
|
||||
r = rem(q, 4)
|
||||
pos = List.replace_at(pos, r * 2, "B")
|
||||
q = div(q, 6)
|
||||
r = rem(q, 6)
|
||||
i = Enum.reject(0..7, &Enum.at(pos,&1)) |> Enum.at(r)
|
||||
pos = List.replace_at(pos, i, "Q")
|
||||
krn = Enum.at(@krn, q) |> String.codepoints
|
||||
Enum.reject(0..7, &Enum.at(pos,&1))
|
||||
|> Enum.zip(krn)
|
||||
|> Enum.reduce(pos, fn {i,x},acc -> List.replace_at(acc,i,x) end)
|
||||
|> Enum.join
|
||||
end
|
||||
end
|
||||
|
||||
IO.puts "Generate Start Position from ID number"
|
||||
Enum.each([0,518,959], fn id ->
|
||||
:io.format "~3w : ~s~n", [id, Chess960.start_position(id)]
|
||||
end)
|
||||
IO.puts "\nGenerate random Start Position"
|
||||
Enum.each(1..5, fn _ -> IO.puts Chess960.start_position end)
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
USING: io kernel math random sequences ;
|
||||
IN: rosetta-code.chess960
|
||||
|
||||
: empty ( seq -- n ) 32 swap indices random ; ! return a random empty index (i.e. equal to 32) of seq
|
||||
: next ( seq -- n ) 32 swap index ; ! return the leftmost empty index of seq
|
||||
: place ( seq elt n -- seq' ) rot [ set-nth ] keep ; ! set nth member of seq to elt, keeping seq on the stack
|
||||
|
||||
: white-bishop ( -- elt n ) CHAR: ♗ 4 random 2 * ;
|
||||
: black-bishop ( -- elt n ) white-bishop 1 + ;
|
||||
: queen ( seq -- seq elt n ) CHAR: ♕ over empty ;
|
||||
: knight ( seq -- seq elt n ) CHAR: ♘ over empty ;
|
||||
: rook ( seq -- seq elt n ) CHAR: ♖ over next ;
|
||||
: king ( seq -- seq elt n ) CHAR: ♔ over next ;
|
||||
|
||||
: chess960 ( -- str )
|
||||
" " clone
|
||||
black-bishop place
|
||||
white-bishop place
|
||||
queen place
|
||||
knight place
|
||||
knight place
|
||||
rook place
|
||||
king place
|
||||
rook place ;
|
||||
|
||||
: chess960-demo ( -- ) 5 [ chess960 print ] times ;
|
||||
|
||||
MAIN: chess960-demo
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
USING: chess960 prettyprint ;
|
||||
|
||||
chess960-position .
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
\ make starting position for Chess960, constructive
|
||||
|
||||
\ 0 1 2 3 4 5 6 7 8 9
|
||||
create krn S" NNRKRNRNKRNRKNRNRKRNRNNKRRNKNRRNKRNRKNNRRKNRNRKRNN" mem,
|
||||
|
||||
create pieces 8 allot
|
||||
|
||||
: chess960 ( n -- )
|
||||
pieces 8 erase
|
||||
4 /mod swap 2* 1+ pieces + 'B swap c!
|
||||
4 /mod swap 2* pieces + 'B swap c!
|
||||
6 /mod swap pieces swap bounds begin dup c@ if swap 1+ swap then 2dup > while 1+ repeat drop 'Q swap c!
|
||||
5 * krn + pieces 8 bounds do i c@ 0= if dup c@ i c! 1+ then loop drop
|
||||
cr pieces 8 type ;
|
||||
|
||||
0 chess960 \ BBQNNRKR ok
|
||||
518 chess960 \ RNBQKBNR ok
|
||||
959 chess960 \ RKRNNQBB ok
|
||||
|
||||
960 choose chess960 \ random position
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
program chess960
|
||||
implicit none
|
||||
|
||||
integer, pointer :: a,b,c,d,e,f,g,h
|
||||
integer, target :: p(8)
|
||||
a => p(1)
|
||||
b => p(2)
|
||||
c => p(3)
|
||||
d => p(4)
|
||||
e => p(5)
|
||||
f => p(6)
|
||||
g => p(7)
|
||||
h => p(8)
|
||||
|
||||
king: do a=2,7 ! King on an internal square
|
||||
r1: do b=1,a-1 ! R1 left of the King
|
||||
r2: do c=a+1,8 ! R2 right of the King
|
||||
b1: do d=1,7,2 ! B1 on an odd square
|
||||
if (skip_pos(d,4)) cycle
|
||||
b2: do e=2,8,2 ! B2 on an even square
|
||||
if (skip_pos(e,5)) cycle
|
||||
queen: do f=1,8 ! Queen anywhere else
|
||||
if (skip_pos(f,6)) cycle
|
||||
n1: do g=1,7 ! First knight
|
||||
if (skip_pos(g,7)) cycle
|
||||
n2: do h=g+1,8 ! Second knight (indistinguishable from first)
|
||||
if (skip_pos(h,8)) cycle
|
||||
if (sum(p) /= 36) stop 'Loop error' ! Sanity check
|
||||
call write_position
|
||||
end do n2
|
||||
end do n1
|
||||
end do queen
|
||||
end do b2
|
||||
end do b1
|
||||
end do r2
|
||||
end do r1
|
||||
end do king
|
||||
|
||||
contains
|
||||
|
||||
logical function skip_pos(i, n)
|
||||
integer, intent(in) :: i, n
|
||||
skip_pos = any(p(1:n-1) == i)
|
||||
end function skip_pos
|
||||
|
||||
subroutine write_position
|
||||
integer :: i, j
|
||||
character(len=15) :: position = ' '
|
||||
character(len=1), parameter :: names(8) = ['K','R','R','B','B','Q','N','N']
|
||||
do i=1,8
|
||||
j = 2*p(i)-1
|
||||
position(j:j) = names(i)
|
||||
end do
|
||||
write(*,'(a)') position
|
||||
end subroutine write_position
|
||||
|
||||
end program chess960
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
type symbols struct{ k, q, r, b, n rune }
|
||||
|
||||
var A = symbols{'K', 'Q', 'R', 'B', 'N'}
|
||||
var W = symbols{'♔', '♕', '♖', '♗', '♘'}
|
||||
var B = symbols{'♚', '♛', '♜', '♝', '♞'}
|
||||
|
||||
var krn = []string{
|
||||
"nnrkr", "nrnkr", "nrknr", "nrkrn",
|
||||
"rnnkr", "rnknr", "rnkrn",
|
||||
"rknnr", "rknrn",
|
||||
"rkrnn"}
|
||||
|
||||
func (sym symbols) chess960(id int) string {
|
||||
var pos [8]rune
|
||||
q, r := id/4, id%4
|
||||
pos[r*2+1] = sym.b
|
||||
q, r = q/4, q%4
|
||||
pos[r*2] = sym.b
|
||||
q, r = q/6, q%6
|
||||
for i := 0; ; i++ {
|
||||
if pos[i] != 0 {
|
||||
continue
|
||||
}
|
||||
if r == 0 {
|
||||
pos[i] = sym.q
|
||||
break
|
||||
}
|
||||
r--
|
||||
}
|
||||
i := 0
|
||||
for _, f := range krn[q] {
|
||||
for pos[i] != 0 {
|
||||
i++
|
||||
}
|
||||
switch f {
|
||||
case 'k':
|
||||
pos[i] = sym.k
|
||||
case 'r':
|
||||
pos[i] = sym.r
|
||||
case 'n':
|
||||
pos[i] = sym.n
|
||||
}
|
||||
}
|
||||
return string(pos[:])
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(" ID Start position")
|
||||
for _, id := range []int{0, 518, 959} {
|
||||
fmt.Printf("%3d %s\n", id, A.chess960(id))
|
||||
}
|
||||
fmt.Println("\nRandom")
|
||||
for i := 0; i < 5; i++ {
|
||||
fmt.Println(W.chess960(rand.Intn(960)))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import Data.List
|
||||
import qualified Data.Set as Set
|
||||
|
||||
data Piece = K | Q | R | B | N deriving (Eq, Ord, Show)
|
||||
|
||||
isChess960 :: [Piece] -> Bool
|
||||
isChess960 rank =
|
||||
(odd . sum $ findIndices (== B) rank) && king > rookA && king < rookB
|
||||
where
|
||||
Just king = findIndex (== K) rank
|
||||
[rookA, rookB] = findIndices (== R) rank
|
||||
|
||||
main :: IO ()
|
||||
main = mapM_ (putStrLn . concatMap show) . Set.toList . Set.fromList
|
||||
. filter isChess960 $ permutations [R,N,B,Q,K,B,N,R]
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
row0=: u: 9812+2}.5|i.10
|
||||
king=: u:9812
|
||||
rook=: u:9814
|
||||
bish=: u:9815
|
||||
pos=: I.@e.
|
||||
bishok=: 1=2+/ .| pos&bish
|
||||
rookok=: pos&rook -: (<./,>./)@pos&(rook,king)
|
||||
ok=: bishok*rookok
|
||||
perm=: A.&i.~ !
|
||||
valid=: (#~ ok"1) ~.row0{"1~perm 8
|
||||
gen=: valid {~ ? bind 960
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
gen''
|
||||
♘♗♖♔♗♕♖♘
|
||||
gen''
|
||||
♗♘♘♗♖♔♖♕
|
||||
gen''
|
||||
♖♗♔♘♘♕♗♖
|
||||
gen''
|
||||
♖♔♕♗♗♘♖♘
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class Chess960{
|
||||
private static List<Character> pieces = Arrays.asList('R','B','N','Q','K','N','B','R');
|
||||
|
||||
public static List<Character> generateFirstRank(){
|
||||
do{
|
||||
Collections.shuffle(pieces);
|
||||
}while(!check(pieces.toString().replaceAll("[^\\p{Upper}]", ""))); //List.toString adds some human stuff, remove that
|
||||
|
||||
return pieces;
|
||||
}
|
||||
|
||||
private static boolean check(String rank){
|
||||
if(!rank.matches(".*R.*K.*R.*")) return false; //king between rooks
|
||||
if(!rank.matches(".*B(..|....|......|)B.*")) return false; //all possible ways bishops can be placed
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void main(String[] args){
|
||||
for(int i = 0; i < 10; i++){
|
||||
System.out.println(generateFirstRank());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
function ch960startPos() {
|
||||
var rank = new Array(8),
|
||||
// randomizer (our die)
|
||||
d = function(num) { return Math.floor(Math.random() * ++num) },
|
||||
emptySquares = function() {
|
||||
var arr = [];
|
||||
for (var i = 0; i < 8; i++) if (rank[i] == undefined) arr.push(i);
|
||||
return arr;
|
||||
};
|
||||
// place one bishop on any black square
|
||||
rank[d(2) * 2] = "♗";
|
||||
// place the other bishop on any white square
|
||||
rank[d(2) * 2 + 1] = "♗";
|
||||
// place the queen on any empty square
|
||||
rank[emptySquares()[d(5)]] = "♕";
|
||||
// place one knight on any empty square
|
||||
rank[emptySquares()[d(4)]] = "♘";
|
||||
// place the other knight on any empty square
|
||||
rank[emptySquares()[d(3)]] = "♘";
|
||||
// place the rooks and the king on the squares left, king in the middle
|
||||
for (var x = 1; x <= 3; x++) rank[emptySquares()[0]] = x==2 ? "♔" : "♖";
|
||||
return rank;
|
||||
}
|
||||
|
||||
// testing (10 times)
|
||||
for (var x = 1; x <= 10; x++) console.log(ch960startPos().join(" | "));
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
### 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))
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
function generateposition()
|
||||
# Placeholder knights
|
||||
rank = ['♘', '♘', '♘', '♘', '♘', '♘', '♘', '♘']
|
||||
lrank = length(rank)
|
||||
|
||||
# Check if a space is available
|
||||
isfree(x::Int) = rank[x] == '♘'
|
||||
|
||||
# Place the King
|
||||
rank[indking = rand(2:lrank-1)] = '♔'
|
||||
|
||||
# Place rooks
|
||||
rank[indrook = rand(filter(isfree, 1:lrank))] = '♖'
|
||||
if indrook > indking
|
||||
rank[rand(filter(isfree, 1:indking-1))] = '♖'
|
||||
else
|
||||
rank[rand(filter(isfree, indking+1:lrank))] = '♖'
|
||||
end
|
||||
|
||||
# Place bishops
|
||||
rank[indbish = rand(filter(isfree, 1:8))] = '♗'
|
||||
pbish = filter(iseven(indbish) ? isodd : iseven, 1:lrank)
|
||||
rank[rand(filter(isfree, pbish))] = '♗'
|
||||
|
||||
# Place queen
|
||||
rank[rand(filter(isfree, 1:lrank))] = '♕'
|
||||
return rank
|
||||
end
|
||||
|
||||
@show generateposition()
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
object Chess960 : Iterable<String> {
|
||||
override fun iterator() = patterns.iterator()
|
||||
|
||||
private operator fun invoke(b: String, e: String) {
|
||||
if (e.length <= 1) {
|
||||
val s = b + e
|
||||
if (s.is_valid()) patterns += s
|
||||
} else {
|
||||
for (i in 0 until e.length) {
|
||||
invoke(b + e[i], e.substring(0, i) + e.substring(i + 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.is_valid(): Boolean {
|
||||
val k = indexOf('K')
|
||||
return indexOf('R') < k && k < lastIndexOf('R') &&
|
||||
indexOf('B') % 2 != lastIndexOf('B') % 2
|
||||
}
|
||||
|
||||
private val patterns = sortedSetOf<String>()
|
||||
|
||||
init {
|
||||
invoke("", "KQRRNNBB")
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
Chess960.forEachIndexed { i, s -> println("$i: $s") }
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
-- Insert 'str' into 't' at a random position from 'left' to 'right'
|
||||
function randomInsert (t, str, left, right)
|
||||
local pos
|
||||
repeat pos = math.random(left, right) until not t[pos]
|
||||
t[pos] = str
|
||||
return pos
|
||||
end
|
||||
|
||||
-- Generate a random Chess960 start position for white major pieces
|
||||
function chess960 ()
|
||||
local t, b1, b2 = {}
|
||||
local kingPos = randomInsert(t, "K", 2, 7)
|
||||
randomInsert(t, "R", 1, kingPos - 1)
|
||||
randomInsert(t, "R", kingPos + 1, 8)
|
||||
b1 = randomInsert(t, "B", 1, 8)
|
||||
b2 = randomInsert(t, "B", 1, 8)
|
||||
while (b2 - b1) % 2 == 0 do
|
||||
t[b2] = false
|
||||
b2 = randomInsert(t, "B", 1, 8)
|
||||
end
|
||||
randomInsert(t, "Q", 1, 8)
|
||||
randomInsert(t, "N", 1, 8)
|
||||
randomInsert(t, "N", 1, 8)
|
||||
return t
|
||||
end
|
||||
|
||||
-- Main procedure
|
||||
math.randomseed(os.time())
|
||||
print(table.concat(chess960()))
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
Print[StringJoin[
|
||||
RandomChoice[
|
||||
Select[Union[
|
||||
Permutations[{"\[WhiteKing]", "\[WhiteQueen]", "\[WhiteRook]",
|
||||
"\[WhiteRook]", "\[WhiteBishop]", "\[WhiteBishop]",
|
||||
"\[WhiteKnight]", "\[WhiteKnight]"}]],
|
||||
MatchQ[#, {___, "\[WhiteRook]", ___, "\[WhiteKing]", ___,
|
||||
"\[WhiteRook]", ___}] &&
|
||||
OddQ[Subtract @@ Flatten[Position[#, "\[WhiteBishop]"]]] &]]]];
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// placeholder knights
|
||||
rank = ["♘"] * 8
|
||||
|
||||
// function to get a random free space from a to b, inclusive
|
||||
randFree = function(a, b)
|
||||
free = []
|
||||
for i in range(a, b)
|
||||
if rank[i] == "♘" then free.push i
|
||||
end for
|
||||
return free[rnd * free.len]
|
||||
end function
|
||||
|
||||
// place the king
|
||||
kingIdx = randFree(1, 6)
|
||||
rank[kingIdx] = "♔"
|
||||
|
||||
// place rooks
|
||||
rank[randFree(0, kingIdx - 1)] = "♖"
|
||||
rank[randFree(kingIdx + 1, 7)] = "♖"
|
||||
|
||||
// place bishops
|
||||
bishIdx = randFree(0, 7)
|
||||
rank[bishIdx] = "♗"
|
||||
while true
|
||||
i = randFree(0, 7)
|
||||
if i % 2 != bishIdx % 2 then break
|
||||
end while
|
||||
rank[i] = "♗"
|
||||
|
||||
// place queen
|
||||
rank[randFree(0, 7)] = "♕"
|
||||
|
||||
print join(rank, " ")
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
import random, strutils
|
||||
|
||||
type
|
||||
|
||||
# Chess pieces on first row.
|
||||
Pieces {.pure.} = enum
|
||||
King = "♔",
|
||||
Queen = "♕",
|
||||
Rook1 = "♖",
|
||||
Rook2 = "♖",
|
||||
Bishop1 = "♗",
|
||||
Bishop2 = "♗",
|
||||
Knight1 = "♘",
|
||||
Knight2 = "♘"
|
||||
|
||||
# Position counted from 0.
|
||||
Position = range[0..7]
|
||||
|
||||
# Position of pieces.
|
||||
Positions = array[Pieces, Position]
|
||||
|
||||
|
||||
func pop[T](s: var set[T]): T =
|
||||
## Remove and return the first element of a set.
|
||||
for val in s:
|
||||
result = val
|
||||
break
|
||||
s.excl(result)
|
||||
|
||||
|
||||
proc choose[T](s: var set[T]): T =
|
||||
## Choose randomly a value from a set and remove it from the set.
|
||||
result = sample(s)
|
||||
s.excl(result)
|
||||
|
||||
|
||||
proc positions(): Positions =
|
||||
## Return a randomly chosen list of piece positions for the first row.
|
||||
|
||||
var pos = {Position.low..Position.high}
|
||||
|
||||
# Set bishops.
|
||||
result[Bishop1] = sample([0, 2, 4, 6]) # Black squares.
|
||||
result[Bishop2] = sample([1, 3, 5, 7]) # White squares.
|
||||
pos = pos - {result[Bishop1], result[Bishop2]}
|
||||
|
||||
# Set queen.
|
||||
result[Queen] = pos.choose()
|
||||
|
||||
# Set knights.
|
||||
result[Knight1] = pos.choose()
|
||||
result[Knight2] = pos.choose()
|
||||
|
||||
# In the remaining three pieces, the king must be between the two rooks.
|
||||
result[Rook1] = pos.pop()
|
||||
result[King] = pos.pop()
|
||||
result[Rook2] = pos.pop()
|
||||
|
||||
|
||||
#———————————————————————————————————————————————————————————————————————————————————————————————————
|
||||
|
||||
randomize()
|
||||
|
||||
for _ in 1..10:
|
||||
var row: array[8, string]
|
||||
let pos = positions()
|
||||
for piece in Pieces:
|
||||
row[pos[piece]] = $piece
|
||||
echo row.join(" ")
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
class Chess960 {
|
||||
function : Main(args : String[]) ~ Nil {
|
||||
Generate(10);
|
||||
}
|
||||
|
||||
function : Generate(c : Int) ~ Nil {
|
||||
for(x := 0; x < c; x += 1;) {
|
||||
StartPos()->PrintLine();
|
||||
};
|
||||
}
|
||||
|
||||
function : StartPos() ~ String {
|
||||
p := Char->New[8];
|
||||
|
||||
# bishops
|
||||
b1 : Int; b2 : Int;
|
||||
while(true) {
|
||||
b1 := GetPosition(); b2 := GetPosition();
|
||||
|
||||
b1c := b1 and 1; b2c := b2 and 1;
|
||||
c := b1c = 0 & b2c <> 0;
|
||||
if(c) {
|
||||
break;
|
||||
};
|
||||
};
|
||||
p[b1] := 0x2657; p[b2] := 0x2657;
|
||||
|
||||
# queen, knight, knight
|
||||
q := false;
|
||||
for(x := 0; x < 3; x += 1;) {
|
||||
do {
|
||||
b1 := GetPosition();
|
||||
} while( p[b1] <> '\0');
|
||||
|
||||
if(<>q) {
|
||||
p[b1] := 0x2655; q := true;
|
||||
}
|
||||
else {
|
||||
p[b1] := 0x2658;
|
||||
};
|
||||
};
|
||||
|
||||
# rook king rook
|
||||
q := false;
|
||||
for(x := 0; x < 3; x += 1;) {
|
||||
a := 0;
|
||||
while(a < 8) {
|
||||
if(p[a] = '\0') {
|
||||
break;
|
||||
};
|
||||
a += 1;
|
||||
};
|
||||
|
||||
if(<>q) {
|
||||
p[a] := 0x2656; q := true;
|
||||
}
|
||||
else {
|
||||
p[a] := 0x2654; q := false;
|
||||
};
|
||||
};
|
||||
|
||||
s := "";
|
||||
for(x := 0; x < 8; x += 1;) { s->Append(p[x]); };
|
||||
return s;
|
||||
}
|
||||
|
||||
function : GetPosition() ~ Int {
|
||||
return (Float->Random() * 1000)->As(Int) % 8;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
chess960() =
|
||||
{
|
||||
my (C = vector(8), i, j, r);
|
||||
|
||||
C[random(4) * 2 + 1] = C[random(4) * 2 + 2] = "B";
|
||||
for (i = 1, 3, while (C[r = random(8) + 1],); C[r] = Vec("NNQ")[i]);
|
||||
for (i = 1, 8, if (!C[i], C[i] = Vec("RKR")[j++]));
|
||||
C
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
sub rnd($) { int(rand(shift)) }
|
||||
|
||||
sub empties { grep !$_[0][$_], 0 .. 7 }
|
||||
|
||||
sub chess960 {
|
||||
my @s = (undef) x 8;
|
||||
@s[2*rnd(4), 1 + 2*rnd(4)] = qw/B B/;
|
||||
|
||||
for (qw/Q N N/) {
|
||||
my @idx = empties \@s;
|
||||
$s[$idx[rnd(@idx)]] = $_;
|
||||
}
|
||||
|
||||
@s[empties \@s] = qw/R K R/;
|
||||
@s
|
||||
}
|
||||
print "@{[chess960]}\n" for 0 .. 10;
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
<span style="color: #000080;font-style:italic;">-- sequence s = permute(rand(factorial(8),"RNBQKBNR")</span>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<span style="color: #000080;font-style:italic;">-- if getd_index(s,d)=0 then
|
||||
-- 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>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</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: #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>
|
||||
<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>
|
||||
<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>
|
||||
<!--
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
(load "@lib/simul.l")
|
||||
|
||||
(seed (in "/dev/urandom" (rd 8)))
|
||||
|
||||
(loop
|
||||
(match
|
||||
'(@A B @B B @C)
|
||||
(shuffle '(Q B B N N 0 0 0)) )
|
||||
(NIL (bit? 1 (length @B))) )
|
||||
|
||||
(let Rkr '(R K R)
|
||||
(for I (append @A '(B) @B '(B) @C)
|
||||
(prin (if (=0 I) (pop 'Rkr) I)) )
|
||||
(prinl) )
|
||||
|
||||
(bye)
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
function Get-RandomChess960Start
|
||||
{
|
||||
$Starts = @()
|
||||
|
||||
ForEach ( $Q in 0..3 ) {
|
||||
ForEach ( $N1 in 0..4 ) {
|
||||
ForEach ( $N2 in ($N1+1)..5 ) {
|
||||
ForEach ( $B1 in 0..3 ) {
|
||||
ForEach ( $B2 in 0..3 ) {
|
||||
$BB = $B1 * 2 + ( $B1 -lt $B2 )
|
||||
$BW = $B2 * 2
|
||||
$Start = [System.Collections.ArrayList]( '♖', '♔', '♖' )
|
||||
$Start.Insert( $Q , '♕' )
|
||||
$Start.Insert( $N1, '♘' )
|
||||
$Start.Insert( $N2, '♘' )
|
||||
$Start.Insert( $BB, '♗' )
|
||||
$Start.Insert( $BW, '♗' )
|
||||
$Starts += ,$Start
|
||||
}}}}}
|
||||
|
||||
$Index = Get-Random 960
|
||||
$StartString = $Starts[$Index] -join ''
|
||||
return $StartString
|
||||
}
|
||||
|
||||
Get-RandomChess960Start
|
||||
Get-RandomChess960Start
|
||||
Get-RandomChess960Start
|
||||
Get-RandomChess960Start
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
>>> from itertools import permutations
|
||||
>>> pieces = 'KQRrBbNN'
|
||||
>>> starts = {''.join(p).upper() for p in permutations(pieces)
|
||||
if p.index('B') % 2 != p.index('b') % 2 # Bishop constraint
|
||||
and ( p.index('r') < p.index('K') < p.index('R') # King constraint
|
||||
or p.index('R') < p.index('K') < p.index('r') ) }
|
||||
>>> len(starts)
|
||||
960
|
||||
>>> starts.pop()
|
||||
'QNBRNKRB'
|
||||
>>>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
>>> import re
|
||||
>>> pieces = 'KQRRBBNN'
|
||||
>>> bish = re.compile(r'B(|..|....|......)B').search
|
||||
>>> king = re.compile(r'R.*K.*R').search
|
||||
>>> starts3 = {p for p in (''.join(q) for q in permutations(pieces))
|
||||
if bish(p) and king(p)}
|
||||
>>> len(starts3)
|
||||
960
|
||||
>>> starts3.pop()
|
||||
'QRNKBNRB'
|
||||
>>>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
from random import choice
|
||||
|
||||
def random960():
|
||||
start = ['R', 'K', 'R'] # Subsequent order unchanged by insertions.
|
||||
#
|
||||
for piece in ['Q', 'N', 'N']:
|
||||
start.insert(choice(range(len(start)+1)), piece)
|
||||
#
|
||||
bishpos = choice(range(len(start)+1))
|
||||
start.insert(bishpos, 'B')
|
||||
start.insert(choice(range(bishpos + 1, len(start) + 1, 2)), 'B')
|
||||
return start
|
||||
return ''.join(start).upper()
|
||||
|
||||
print(random960())
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
from random import choice
|
||||
|
||||
def generate960():
|
||||
start = ('R', 'K', 'R') # Subsequent order unchanged by insertions.
|
||||
|
||||
# Insert QNN in all combinations of places
|
||||
starts = {start}
|
||||
for piece in ['Q', 'N', 'N']:
|
||||
starts2 = set()
|
||||
for s in starts:
|
||||
for pos in range(len(s)+1):
|
||||
s2 = list(s)
|
||||
s2.insert(pos, piece)
|
||||
starts2.add(tuple(s2))
|
||||
starts = starts2
|
||||
|
||||
# For each of the previous starting positions insert the bishops in their 16 positions
|
||||
starts2 = set()
|
||||
for s in starts:
|
||||
for bishpos in range(len(s)+1):
|
||||
s2 = list(s)
|
||||
s2.insert(bishpos, 'B')
|
||||
for bishpos2 in range(bishpos+1, len(s)+2, 2):
|
||||
s3 = s2[::]
|
||||
s3.insert(bishpos2, 'B')
|
||||
starts2.add(tuple(s3))
|
||||
|
||||
return list(starts2)
|
||||
|
||||
gen = generate960()
|
||||
print(''.join(choice(gen)))
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
pieces <- c("R","B","N","Q","K","N","B","R")
|
||||
|
||||
generateFirstRank <- function() {
|
||||
attempt <- paste0(sample(pieces), collapse = "")
|
||||
while (!check_position(attempt)) {
|
||||
attempt <- paste0(sample(pieces), collapse = "")
|
||||
}
|
||||
return(attempt)
|
||||
}
|
||||
|
||||
check_position <- function(position) {
|
||||
if (regexpr('.*R.*K.*R.*', position) == -1) return(FALSE)
|
||||
if (regexpr('.*B(..|....|......|)B.*', position) == -1) return(FALSE)
|
||||
TRUE
|
||||
}
|
||||
|
||||
convert_to_unicode <- function(s) {
|
||||
s <- sub("K","\u2654", s)
|
||||
s <- sub("Q","\u2655", s)
|
||||
s <- gsub("R","\u2656", s)
|
||||
s <- gsub("B","\u2657", s)
|
||||
s <- gsub("N","\u2658", s)
|
||||
}
|
||||
|
||||
cat(convert_to_unicode(generateFirstRank()), "\n")
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*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.*/
|
||||
@.=. /*define the first rank as being empty.*/
|
||||
r1=random(1,6) /*generate the first rook: rank 1. */
|
||||
@.r1='R' /*place the first rook on rank1. */
|
||||
do until r2\==r1 & r2\==r1-1 & r2\==r1+1
|
||||
r2=random(1,8) /*find placement for the 2nd rook. */
|
||||
end /*forever*/
|
||||
@.r2='r' /*place the second rook on rank 1. */
|
||||
k=random(min(r1, r2)+1, max(r1, r2)-1) /*find a random position for the king. */
|
||||
@.k='K' /*place king between the two rooks. */
|
||||
do _=0 ; b1=random(1,8); if @.b1\==. then iterate; c=b1//2
|
||||
do forever; b2=random(1,8) /* c=color of bishop ►──┘ */
|
||||
if @.b2\==. | b2==b1 | b2//2==c then iterate /*is a bad position?*/
|
||||
leave _ /*found position for the 2 clergy*/
|
||||
end /*forever*/ /* [↑] find a place for the 1st bishop*/
|
||||
end /* _ */ /* [↑] " " " " " 2nd " */
|
||||
@.b1='B' /*place the 1st bishop on rank 1. */
|
||||
@.b2='b' /* " " 2nd " " " " */
|
||||
/*place the two knights on rank 1. */
|
||||
do until @._='N'; _=random(1,8); if @._\==. then iterate; @._='N'; end
|
||||
do until @.!='n'; !=random(1,8); if @.!\==. then iterate; @.!='n'; end
|
||||
_= /*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. */
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*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.*/
|
||||
x.=0; #=0; rg='random generations: ' /*initialize game placeholder; # games.*/
|
||||
/*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*/
|
||||
do t=1 /* [↓] display every 1,000 generations*/ /*▒*/
|
||||
if t//1000==0 then say right(t,9) rg # " unique starting positions." /*▒*/
|
||||
@.=. /*define the first rank as being empty.*/ /*▒*/
|
||||
r1=random(1,6) /*generate the first rook: rank 1. */ /*▒*/
|
||||
@.r1='R' /*place the first rook on rank1. */ /*▒*/
|
||||
do until r2\==r1 & r2\==r1-1 & r2\==r1+1 /*▒*/
|
||||
r2=random(1,8) /*find placement for the 2nd rook. */ /*▒*/
|
||||
end /*forever*/ /*▒*/
|
||||
@.r2='r' /*place the second rook on rank 1. */ /*▒*/
|
||||
k=random(min(r1, r2)+1, max(r1, r2)-1) /*find a random position for the king. */ /*▒*/
|
||||
@.k='K' /*place king between the two rooks. */ /*▒*/
|
||||
do _=0 ; b1=random(1,8); if @.b1\==. then iterate; c=b1//2 /*▒*/
|
||||
do forever; b2=random(1,8) /* c=color of bishop ►──┘ */ /*▒*/
|
||||
if @.b2\==. | b2==b1 | b2//2==c then iterate /*is a bad position?*/ /*▒*/
|
||||
leave _ /*found position for the 2 clergy*/ /*▒*/
|
||||
end /*forever*/ /* [↑] find a place for the 1st bishop*/ /*▒*/
|
||||
end /* _ */ /* [↑] " " " " " 2nd " */ /*▒*/
|
||||
@.b1='B' /*place the 1st bishop on rank 1. */ /*▒*/
|
||||
@.b2='b' /* " " 2nd " " " " */ /*▒*/
|
||||
/*place the two knights on rank 1. */ /*▒*/
|
||||
do until @._='N'; _=random(1,8); if @._\==. then iterate; @._='N'; end /*▒*/
|
||||
do until @.!='n'; !=random(1,8); if @.!\==. then iterate; @.!='n'; end /*▒*/
|
||||
_= /*only the queen is left to be placed. */ /*▒*/
|
||||
do i=1 for 8; _=_ || @.i; end /*construct the output: first rank only*/ /*▒*/
|
||||
upper _ /*uppercase all the chess pieces. */ /*▒*/
|
||||
if x._ then iterate /*This position found before? Skip it.*/ /*▒*/
|
||||
x._=1 /*define this position as being found. */ /*▒*/
|
||||
#=#+1 /*bump the # of unique positions found,*/ /*▒*/
|
||||
if #==960 then leave /*▒*/
|
||||
end /*t ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*/
|
||||
|
||||
say # 'unique starting positions found after ' t "generations."
|
||||
/*stick a fork in it, we're all done. */ /**/
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*---------------------------------------------------------------
|
||||
* Compute the 960 possible solutions
|
||||
* There must be at least one field between the rooks
|
||||
* The king is positioned on any field between the rooks
|
||||
* The queen is placed on any unoccupied field
|
||||
* bishops are placed so that they are on different colored fields
|
||||
* what remains are the kNights...
|
||||
*--------------------------------------------------------------*/
|
||||
cnt.=0
|
||||
Call time 'R'
|
||||
Do r1=1 To 6
|
||||
Do r2=r1+1 To 8
|
||||
Do kk=r1+1 To r2-1
|
||||
poss=space(translate('12345678',' ',r1||kk||r2),0)
|
||||
Call rest
|
||||
End
|
||||
|
||||
End
|
||||
End
|
||||
say cnt.1 'solutions'
|
||||
Say time('E')
|
||||
Exit
|
||||
|
||||
rest:
|
||||
Do i=1 To 5
|
||||
q=substr(poss,i,1)
|
||||
br=space(translate(poss,' ',q),0)
|
||||
Do b1i=1 To 3
|
||||
Do b2i=b1i+1 To 4
|
||||
Call finish
|
||||
End
|
||||
End
|
||||
End
|
||||
Return
|
||||
|
||||
finish:
|
||||
b1=substr(br,b1i,1)
|
||||
b2=substr(br,b2i,1)
|
||||
If (b1+b2)//2>0 Then
|
||||
Call out
|
||||
Return
|
||||
|
||||
out:
|
||||
pos.='N'
|
||||
pos.r1='R'
|
||||
pos.r2='R'
|
||||
pos.kk='K'
|
||||
pos.q='Q'
|
||||
pos.b1='B'
|
||||
pos.b2='B'
|
||||
ol=''
|
||||
Do k=1 To 8
|
||||
ol=ol||pos.k
|
||||
End
|
||||
cnt.1=cnt.1+1
|
||||
If cnt.1<4 |,
|
||||
cnt.1>957 Then
|
||||
Say format(cnt.1,3) poss r1 kk r2 ol
|
||||
If cnt.1=4 Then
|
||||
Say ' ...'
|
||||
Return
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#lang racket
|
||||
(define white (match-lambda ['P #\♙] ['R #\♖] ['B #\♗] ['N #\♘] ['Q #\♕] ['K #\♔]))
|
||||
(define black (match-lambda ['P #\♟] ['R #\♜] ['B #\♝] ['N #\♞] ['Q #\♛] ['K #\♚]))
|
||||
|
||||
(define (piece->unicode piece colour)
|
||||
(match colour ('w white) ('b black)) piece)
|
||||
|
||||
(define (find/set!-random-slot vec val k (f values))
|
||||
(define r (f (random k)))
|
||||
(cond
|
||||
[(vector-ref vec r)
|
||||
(find/set!-random-slot vec val k f)]
|
||||
[else
|
||||
(vector-set! vec r val)
|
||||
r]))
|
||||
|
||||
(define (chess960-start-position)
|
||||
(define v (make-vector 8 #f))
|
||||
;; Kings and Rooks
|
||||
(let ((k (find/set!-random-slot v (white 'K) 6 add1)))
|
||||
(find/set!-random-slot v (white 'R) k)
|
||||
(find/set!-random-slot v (white 'R) (- 7 k) (curry + k 1)))
|
||||
;; Bishops -- so far only three squares allocated, so there is at least one of each colour left
|
||||
(find/set!-random-slot v (white 'B) 4 (curry * 2))
|
||||
(find/set!-random-slot v (white 'B) 4 (compose add1 (curry * 2)))
|
||||
;; Everyone else
|
||||
(find/set!-random-slot v (white 'Q) 8)
|
||||
(find/set!-random-slot v (white 'N) 8)
|
||||
(find/set!-random-slot v (white 'N) 8)
|
||||
(list->string (vector->list v)))
|
||||
|
||||
(chess960-start-position)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
repeat until m/ '♗' [..]* '♗' / { $_ = < ♖ ♖ ♖ ♕ ♗ ♗ ♘ ♘ >.pick(*).join }
|
||||
s:2nd['♖'] = '♔';
|
||||
say .comb;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
sub chess960 {
|
||||
.subst(:nth(2), /'♜'/, '♚') given
|
||||
first rx/ '♝' [..]* '♝' /,
|
||||
< ♛ ♜ ♜ ♜ ♝ ♝ ♞ ♞ >.pick(*).join xx *;
|
||||
}
|
||||
|
||||
say chess960;
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
constant chess960 =
|
||||
< ♛ ♜ ♜ ♜ ♝ ♝ ♞ ♞ >.permutations».join.unique.grep( / '♝' [..]* '♝' / )».subst(:nth(2), /'♜'/, '♚');
|
||||
|
||||
.say for chess960;
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
constant chess960 = gather for 0..3 -> $q {
|
||||
(my @q = <♜ ♚ ♜>).splice($q, 0, '♛');
|
||||
for 0 .. @q -> $n1 {
|
||||
(my @n1 = @q).splice($n1, 0, '♞');
|
||||
for $n1 ^.. @n1 -> $n2 {
|
||||
(my @n2 = @n1).splice($n2, 0, '♞');
|
||||
for 0 .. @n2 -> $b1 {
|
||||
(my @b1 = @n2).splice($b1, 0, '♝');
|
||||
for $b1+1, $b1+3 ...^ * > @b1 -> $b2 {
|
||||
(my @b2 = @b1).splice($b2, 0, '♝');
|
||||
take @b2.join;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK { note "done compiling" }
|
||||
note +chess960;
|
||||
say chess960.pick;
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
subset Pos960 of Int where { $_ ~~ ^960 };
|
||||
sub chess960(Pos960 $position = (^960).pick) {
|
||||
|
||||
# We remember the remainder used to place first bishop in order to place the
|
||||
# second
|
||||
my $b1;
|
||||
|
||||
# And likewise remember the chosen combination for knights between those
|
||||
# placements
|
||||
my @n;
|
||||
|
||||
# Piece symbols and positioning rules in order. Start with the position
|
||||
# number. At each step, divide by the divisor; the quotient becomes the
|
||||
# dividend for the next step. Feed the remainder into the specified code block
|
||||
# to get a space number N, then place the piece in the Nth empty space left in
|
||||
# the array.
|
||||
my @rules = (
|
||||
#divisor, mapping function, piece
|
||||
( 4, { $b1 = $_; 2 * $_ + 1 }, '♝' ),
|
||||
( 4, { 2 * $_ - ($_ > $b1 ?? 1 !! 0) }, '♝' ),
|
||||
( 6, { $_ }, '♛' ),
|
||||
(10, { @n = combinations(5,2)[$_]; @n[0] }, '♞' ),
|
||||
( 1, { @n[1]-1 }, '♞' ),
|
||||
( 1, { 0 }, '♜' ),
|
||||
( 1, { 0 }, '♚' ),
|
||||
( 1, { 0 }, '♜' )
|
||||
|
||||
);
|
||||
|
||||
# Initial array, using '-' to represent empty spaces
|
||||
my @array = «-» xx 8;
|
||||
|
||||
# Working value that starts as the position number but is divided by the
|
||||
# divisor at each placement step.
|
||||
my $p = $position;
|
||||
|
||||
# Loop over the placement rules
|
||||
for @rules -> ($divisor, $block, $piece) {
|
||||
|
||||
# get remainder when divided by divisor
|
||||
(my $remainder, $p) = $p.polymod($divisor);
|
||||
|
||||
# apply mapping function
|
||||
my $space = $block($remainder);
|
||||
|
||||
# find index of the $space'th element of the array that's still empty
|
||||
my $index = @array.kv.grep(-> $i,$v { $v eq '-' })[$space][0];
|
||||
|
||||
# and place the piece
|
||||
@array[$index] = $piece;
|
||||
}
|
||||
return @array;
|
||||
}
|
||||
|
||||
# demo code
|
||||
say chess960(518); #standard optning position
|
||||
say chess960; # (it happened to pick #300)
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
pieces = %i(♔ ♕ ♘ ♘ ♗ ♗ ♖ ♖)
|
||||
regexes = [/♗(..)*♗/, /♖.*♔.*♖/]
|
||||
row = pieces.shuffle.join until regexes.all?{|re| re.match(row)}
|
||||
puts row
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
KRN = %w(NNRKR NRNKR NRKNR NRKRN RNNKR RNKNR RNKRN RKNNR RKNRN RKRNN)
|
||||
|
||||
def chess960(id=rand(960))
|
||||
pos = Array.new(8)
|
||||
q, r = id.divmod(4)
|
||||
pos[r * 2 + 1] = "B"
|
||||
q, r = q.divmod(4)
|
||||
pos[r * 2] = "B"
|
||||
q, r = q.divmod(6)
|
||||
pos[pos.each_index.reject{|i| pos[i]}[r]] = "Q"
|
||||
krn = KRN[q].each_char
|
||||
pos.each_index {|i| pos[i] ||= krn.next}
|
||||
pos.join
|
||||
end
|
||||
|
||||
puts "Generate Start Position from id number"
|
||||
[0,518,959].each do |id|
|
||||
puts "%3d : %s" % [id, chess960(id)]
|
||||
end
|
||||
|
||||
puts "\nGenerate random Start Position"
|
||||
5.times {puts chess960}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
use std::collections::BTreeSet;
|
||||
|
||||
struct Chess960 ( BTreeSet<String> );
|
||||
|
||||
impl Chess960 {
|
||||
fn invoke(&mut self, b: &str, e: &str) {
|
||||
if e.len() <= 1 {
|
||||
let s = b.to_string() + e;
|
||||
if Chess960::is_valid(&s) { self.0.insert(s); }
|
||||
} else {
|
||||
for (i, c) in e.char_indices() {
|
||||
let mut b = b.to_string();
|
||||
b.push(c);
|
||||
let mut e = e.to_string();
|
||||
e.remove(i);
|
||||
self.invoke(&b, &e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_valid(s: &str) -> bool {
|
||||
let k = s.find('K').unwrap();
|
||||
k > s.find('R').unwrap() && k < s.rfind('R').unwrap() && s.find('B').unwrap() % 2 != s.rfind('B').unwrap() % 2
|
||||
}
|
||||
}
|
||||
|
||||
// Program entry point.
|
||||
fn main() {
|
||||
let mut chess960 = Chess960(BTreeSet::new());
|
||||
chess960.invoke("", "KQRRNNBB");
|
||||
|
||||
for (i, p) in chess960.0.iter().enumerate() {
|
||||
println!("{}: {}", i, p);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// 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());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import scala.annotation.tailrec
|
||||
|
||||
object Chess960 extends App {
|
||||
|
||||
private val pieces = List('♖', '♗', '♘', '♕', '♔', '♘', '♗', '♖')
|
||||
|
||||
@tailrec
|
||||
private def generateFirstRank(pieces: List[Char]): List[Char] = {
|
||||
def check(rank: String) =
|
||||
rank.matches(".*♖.*♔.*♖.*") && rank.matches(".*♗(..|....|......|)♗.*")
|
||||
|
||||
val p = scala.util.Random.shuffle(pieces)
|
||||
if (check(p.toString.replaceAll("[^\\p{Upper}]", "")))
|
||||
generateFirstRank(pieces)
|
||||
else p
|
||||
}
|
||||
|
||||
loop(10)
|
||||
|
||||
@tailrec
|
||||
private def loop(n: Int): Unit = {
|
||||
println(generateFirstRank(pieces))
|
||||
if (n <= 0) () else loop(n - 1)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
object Chess960 extends App {
|
||||
private def apply(b: String, e: String) {
|
||||
if (e.length <= 1) {
|
||||
val s = b + e
|
||||
if (is_valid(s)) patterns += s
|
||||
} else
|
||||
for (i <- 0 until e.length)
|
||||
apply(b + e(i), e.substring(0, i) + e.substring(i + 1))
|
||||
}
|
||||
|
||||
private def is_valid(s: String) = {
|
||||
val k = s.indexOf('K')
|
||||
if (k < s.indexOf('R')) false
|
||||
else k < s.lastIndexOf('R') && s.indexOf('B') % 2 != s.lastIndexOf('B') % 2
|
||||
}
|
||||
|
||||
private val patterns = scala.collection.mutable.SortedSet[String]()
|
||||
|
||||
apply("", "KQRRNNBB")
|
||||
for ((s, i) <- patterns.zipWithIndex) println(s"$i: $s")
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
(import (scheme base) (scheme write)
|
||||
(srfi 1) ; list library
|
||||
(srfi 27)) ; random numbers
|
||||
|
||||
(random-source-randomize! default-random-source)
|
||||
|
||||
;; Random integer in [start, end)
|
||||
(define (random-between start end)
|
||||
(let ((len (- end start 1)))
|
||||
(if (< len 2)
|
||||
start
|
||||
(+ start (random-integer len)))))
|
||||
|
||||
;; Random item in list
|
||||
(define (random-pick lst)
|
||||
(if (= 1 (length lst))
|
||||
(car lst)
|
||||
(list-ref lst (random-integer (length lst)))))
|
||||
|
||||
;; Construct a random piece placement for Chess960
|
||||
(define (random-piece-positions)
|
||||
(define (free-indices positions) ; return list of empty slot indices
|
||||
(let loop ((i 0)
|
||||
(free '()))
|
||||
(if (= 8 i)
|
||||
free
|
||||
(loop (+ 1 i)
|
||||
(if (string=? "." (vector-ref positions i))
|
||||
(cons i free)
|
||||
free)))))
|
||||
;
|
||||
(define (place-king+rooks positions)
|
||||
(let ((king-posn (random-between 1 8)))
|
||||
(vector-set! positions king-posn "K")
|
||||
; left-rook is between left-edge and king
|
||||
(vector-set! positions (random-between 0 king-posn) "R")
|
||||
; right-rook is between right-edge and king
|
||||
(vector-set! positions (random-between (+ 1 king-posn) 8) "R")))
|
||||
;
|
||||
(define (place-bishops positions)
|
||||
(let-values (((evens odds) (partition even? (free-indices positions))))
|
||||
(vector-set! positions (random-pick evens) "B")
|
||||
(vector-set! positions (random-pick odds) "B")))
|
||||
;
|
||||
(let ((positions (make-vector 8 ".")))
|
||||
(place-king+rooks positions)
|
||||
(place-bishops positions)
|
||||
;; place the queen in a random remaining slot
|
||||
(vector-set! positions (random-pick (free-indices positions)) "Q")
|
||||
;; place the two knights in the remaining slots
|
||||
(for-each (lambda (idx) (vector-set! positions idx "N"))
|
||||
(free-indices positions))
|
||||
|
||||
positions))
|
||||
|
||||
(display "First rank: ") (display (random-piece-positions)) (newline)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
$ include "seed7_05.s7i";
|
||||
|
||||
const proc: main is func
|
||||
local
|
||||
var string: start is "RKR";
|
||||
var char: piece is ' ';
|
||||
var integer: pos is 0;
|
||||
begin
|
||||
for piece range "QNN" do
|
||||
pos := rand(1, succ(length(start)));
|
||||
start := start[.. pred(pos)] & str(piece) & start[pos ..];
|
||||
end for;
|
||||
pos := rand(1, succ(length(start)));
|
||||
start := start[.. pred(pos)] & "B" & start[pos ..];
|
||||
pos := succ(pos) + 2 * rand(0, (length(start) - pos) div 2);
|
||||
start := start[.. pred(pos)] & "B" & start[pos ..];
|
||||
writeln(start);
|
||||
end func;
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
func is_valid_960 (backrank) {
|
||||
var king = backrank.index('♚')
|
||||
var (rook1, rook2) = backrank.indices_of('♜')...
|
||||
king.is_between(rook1, rook2) || return false
|
||||
var (bishop1, bishop2) = backrank.indices_of('♝')...
|
||||
bishop1+bishop2 -> is_odd
|
||||
}
|
||||
|
||||
func random_960_position(pieces = <♛ ♚ ♜ ♜ ♝ ♝ ♞ ♞>) {
|
||||
pieces.shuffle.permutations {|*a|
|
||||
return a if is_valid_960(a)
|
||||
}
|
||||
}
|
||||
|
||||
say random_960_position().join(' ')
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
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()!)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package require struct::list
|
||||
|
||||
proc chess960 {} {
|
||||
while true {
|
||||
set pos [join [struct::list shuffle {N N B B R R Q K}] ""]
|
||||
if {[regexp {R.*K.*R} $pos] && [regexp {B(..)*B} $pos]} {
|
||||
return $pos
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# A simple renderer
|
||||
proc chessRender {position} {
|
||||
string map {P ♙ N ♘ B ♗ R ♖ Q ♕ K ♔} $position
|
||||
}
|
||||
|
||||
# Output multiple times just to show scope of positions
|
||||
foreach - {1 2 3 4 5} {puts [chessRender [chess960]]}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
import "random" for Random
|
||||
import "/dynamic" for Tuple
|
||||
import "/fmt" for Fmt
|
||||
|
||||
var Symbols = Tuple.create("Symbols", ["k", "q", "r", "b", "n"])
|
||||
|
||||
var A = Symbols.new("K", "Q", "R", "B", "N")
|
||||
var W = Symbols.new("♔", "♕", "♖", "♗", "♘")
|
||||
var B = Symbols.new("♚", "♛", "♜", "♝", "♞")
|
||||
|
||||
var krn = [
|
||||
"nnrkr", "nrnkr", "nrknr", "nrkrn",
|
||||
"rnnkr", "rnknr", "rnkrn",
|
||||
"rknnr", "rknrn",
|
||||
"rkrnn"
|
||||
]
|
||||
|
||||
var NUL = "\0"
|
||||
|
||||
var chess960 = Fn.new { |sym, id|
|
||||
var pos = List.filled(8, NUL)
|
||||
var q = (id/4).floor
|
||||
var r = id % 4
|
||||
pos[r*2+1]= sym.b
|
||||
var t = q
|
||||
q = (q/4).floor
|
||||
r = t % 4
|
||||
pos[r*2] = sym.b
|
||||
t = q
|
||||
q = (q/6).floor
|
||||
r = t % 6
|
||||
var i = 0
|
||||
while (true) {
|
||||
if (pos[i] == NUL) {
|
||||
if (r == 0) {
|
||||
pos[i] = sym.q
|
||||
break
|
||||
}
|
||||
r = r - 1
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
i = 0
|
||||
for (f in krn[q]) {
|
||||
while (pos[i] != NUL) i = i + 1
|
||||
pos[i] = (f == "k") ? sym.k :
|
||||
(f == "r") ? sym.r :
|
||||
(f == "n") ? sym.n : pos[i]
|
||||
}
|
||||
return pos.join(" ")
|
||||
}
|
||||
|
||||
System.print(" ID Start position")
|
||||
for (id in [0, 518, 959]) Fmt.print("$3d $s", id, chess960.call(A, id))
|
||||
System.print("\nRandom")
|
||||
var rand = Random.new()
|
||||
for (i in 0..4) System.print(chess960.call(W, rand.int(960)))
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
char Col;
|
||||
|
||||
func ColNum(Start, Piece); \Return column number of Piece
|
||||
int Start, Piece, I;
|
||||
[for I:= Start to 7 do
|
||||
if Col(I) = Piece then return I;
|
||||
return -1;
|
||||
];
|
||||
|
||||
proc Shuffle; \Randomly rearrange pieces in columns
|
||||
int I, J, T;
|
||||
[for I:= 8-1 downto 1 do
|
||||
[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);
|
||||
];
|
||||
]
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
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$
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
const pieces="KQRrBbNN";
|
||||
starts:=pieces:Utils.Helpers.permuteW(_).filter(fcn(p){
|
||||
I:=p.index;
|
||||
I("B") % 2 != I("b") % 2 and // Bishop constraint.
|
||||
// King constraint.
|
||||
((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(_);
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
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() }
|
||||
Loading…
Add table
Add a link
Reference in a new issue