# \[QUIZ\] Chess960 (#106)

**URL:** <https://rubytalk.org/t/quiz-chess960-106/33761>\
**Category:** ruby-talk\
**Created:** [15 December 2006 13:50 UTC](https://rubytalk.org/t/quiz-chess960-106/33761 "2006-12-15T13:50:58Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [15 December 2006 13:50 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/1 "2006-12-15T13:50:58Z")

</div>

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until  
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

[http://www.rubyquiz.com/](http://www.rubyquiz.com/)

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone  
on Ruby Talk follow the discussion. Please reply to the original quiz message,  
if you can.

> **···**
>
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
> 
> by Kieran Wild
> 
> Chess960, is a chess variant produced by Grandmaster Bobby Fischer by  
> formalizing the rules of Shuffle Chess. Its goal was to create a chess variant  
> in which chess creativity and talent would be more important than memorization  
> and analysis of opening moves. His approach was to create a randomized initial  
> chess position, which would thus make memorizing chess opening move sequences  
> far less helpful. The initial position is set up in a special way and there are  
> 960 such positions, thus the name Chess960.
> 
> The starting position for Chess960 must meet certain rules. White pawns are  
> placed on the second rank as in chess. All remaining white pieces are placed  
> randomly on the first rank, but with the following restrictions:
> 
> &nbsp;&nbsp;\* The king is placed somewhere between the two rooks.  
> &nbsp;&nbsp;\* The bishops are placed on opposite-colored squares.
> 
> The black pieces are placed equal-and-opposite to the white pieces. For example,  
> if the white king is placed on b1, then the black king is placed on b8. Note  
> that the king never starts on file a or h, because there would be no room for a  
> rook
> 
> Can I suggest a nice little ruby program to generates all 960 possible starting  
> positions and outputs a random one on request.
> 
> Output could be as follows.
> 
> &nbsp;&nbsp;Starting Position 432:  
> &nbsp;&nbsp;  
> &nbsp;&nbsp;White  
> &nbsp;&nbsp;  
> &nbsp;&nbsp;a1 b1 c1 d1 e1 f1 g1 h1  
> &nbsp;&nbsp;N B B R K R Q N  
> &nbsp;&nbsp;  
> &nbsp;&nbsp;Black  
> &nbsp;&nbsp;  
> &nbsp;&nbsp;a8 b8 c8 d8 e8 f8 g8 h8  
> &nbsp;&nbsp;N B B R K R Q N
> 
> Or some better output.

---

<div class="post-metadata">

**Author:** ![Daniel\_Martin](https://avatars.discourse-cdn.com/v4/letter/d/dc4da7/32.png) [@Daniel\_Martin](https://rubytalk.org/u/Daniel_Martin)\
**Post date:** [15 December 2006 19:25 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/2 "2006-12-15T19:25:05Z")

</div>

Ruby Quiz \<james@grayproductions.net\> writes:

> Output could be as follows.
> 
> &nbsp;&nbsp;Starting Position 432:  
> &nbsp;&nbsp;  
> &nbsp;&nbsp;White  
> &nbsp;&nbsp;  
> &nbsp;&nbsp;a1 b1 c1 d1 e1 f1 g1 h1  
> &nbsp;&nbsp;N B B R K R Q N  
> &nbsp;&nbsp;  
> &nbsp;&nbsp;Black  
> &nbsp;&nbsp;  
> &nbsp;&nbsp;a8 b8 c8 d8 e8 f8 g8 h8  
> &nbsp;&nbsp;N B B R K R Q N
> 
> Or some better output.

Let me suggest that another potential output format is an html page  
that when viewed in a browser looks like the opening format. I happen  
to think that the chess boards shown on  
&nbsp;&nbsp;[PmWiki | Cookbook / ChessMarkup](http://www.pmwiki.org/wiki/Cookbook/ChessMarkup)  
look particularly nice, and shouldn't be too hard to duplicate.  
(they're done as 8x8 tables, with the colors of the squares done by  
CSS and the pieces being .png images with transparency) Presumably  
some enterprising person could then churn out a Rails page that showed  
a given starting position.

There's also this basic ascii art method: (black is the lowercase  
letters)

nbbrkrqn  
pppppppp  
........  
........  
........  
........  
PPPPPPPP  
NBBRKRQN

(It's traditional to show the place where white starts at the bottom,  
and to number the rows upwards - that is, row "8" is at the top of the  
diagram)

Then there's a FEN string inside PGN notation:

[Event "Starting Position 432"]  
[SetUp "1"]  
[FEN "nbbrkrqn/pppppppp/8/8/8/8/PPPPPPPP/NBBRKRQN w KQkq - 0 1"]

The advantage of that format is that you can feed it right into  
X-Board, WinBoard, or any other chess program that accepts PGN  
notation, and it'll start play from that setup. (More on what that  
FEN string means at  
[Forsyth–Edwards Notation - Wikipedia](http://en.wikipedia.org/wiki/Forsyth-Edwards_Notation) )

> **···**
>
> --  
> s=%q( Daniel Martin -- martin@snowplow.org  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "s=%q(#{s})",s.map{|i|i}[1] )  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "s=%q(#{s})",s.map{|i|i}[1]

---

<div class="post-metadata">

**Author:** ![Daniel\_Finnie1](https://avatars.discourse-cdn.com/v4/letter/d/4af34b/32.png) [@Daniel\_Finnie1](https://rubytalk.org/u/Daniel_Finnie1)\
**Post date:** [16 December 2006 03:25 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/3 "2006-12-16T03:25:36Z")

</div>

Is that the real starting position 432? Or was that just a made up number?

[ImageShack - Best place for all of your image hosting and image sharing needs](http://img308.imageshack.us/img308/9290/positions400479up0.jpg) Gives BBRNNQKR as number 432 as does my program.

Also, is the range of the numbers 0-956 or 1-960? I've seen things saying that both are acceptable with no definitive answer.

Thanks,  
Dan

Ruby Quiz wrote:

> **···**
>
> > &nbsp;&nbsp;Starting Position 432:  
> > &nbsp;&nbsp;  
> > &nbsp;&nbsp;White  
> > &nbsp;&nbsp;  
> > &nbsp;&nbsp;a1 b1 c1 d1 e1 f1 g1 h1  
> > &nbsp;&nbsp;N B B R K R Q N  
> > &nbsp;&nbsp;  
> > &nbsp;&nbsp;Black  
> > &nbsp;&nbsp;  
> > &nbsp;&nbsp;a8 b8 c8 d8 e8 f8 g8 h8  
> > &nbsp;&nbsp;N B B R K R Q N

---

<div class="post-metadata">

**Author:** ![Chunyun\_Zhao](https://avatars.discourse-cdn.com/v4/letter/c/3da27b/32.png) [@Chunyun\_Zhao](https://rubytalk.org/u/Chunyun_Zhao)\
**Post date:** [17 December 2006 14:08 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/4 "2006-12-17T14:08:23Z")

</div>

Attached is my solution.

-Chunyun

Sample output:

Generated 960 starting positions.

Starting position 93:

[chess960.rb](https://rubytalk.org/uploads/short-url/gm6sNZ1pfZV5iJDD4iLlrZg1M7z.rb) (2.19 KB)

> **···**
>
> > +++++++++++++++++++++++++++++++|  
> > b | n | r | b | k | q | r | n |  
> > +++++++++++++++++++++++++++++++|  
> > p | p | p | p | p | p | p | p |  
> > +++++++++++++++++++++++++++++++|  
> > &nbsp;&nbsp;\> \> \> \> \> \> \> \>  
> > +++++++++++++++++++++++++++++++|  
> > &nbsp;&nbsp;\> \> \> \> \> \> \> \>  
> > +++++++++++++++++++++++++++++++|  
> > &nbsp;&nbsp;\> \> \> \> \> \> \> \>  
> > +++++++++++++++++++++++++++++++|  
> > &nbsp;&nbsp;\> \> \> \> \> \> \> \>  
> > +++++++++++++++++++++++++++++++|  
> > P | P | P | P | P | P | P | P |  
> > +++++++++++++++++++++++++++++++|  
> > B | N | R | B | K | Q | R | N |  
> > +++++++++++++++++++++++++++++++|
> 
> On 12/15/06, Ruby Quiz \<james@grayproductions.net\> wrote:
> 
> > The three rules of Ruby Quiz:
> > 
> > 1. Please do not post any solutions or spoiler discussion for this quiz  
> > until  
> > 48 hours have passed from the time on this message.
> > 
> > 2. Support Ruby Quiz by submitting ideas as often as you can:
> > 
> > [http://www.rubyquiz.com/](http://www.rubyquiz.com/)
> > 
> > 3. Enjoy!
> > 
> > Suggestion: A [QUIZ] in the subject of emails about the problem helps  
> > everyone  
> > on Ruby Talk follow the discussion. Please reply to the original quiz  
> > message,  
> > if you can.
> > 
> > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
> > 
> > by Kieran Wild
> > 
> > Chess960, is a chess variant produced by Grandmaster Bobby Fischer by  
> > formalizing the rules of Shuffle Chess. Its goal was to create a chess  
> > variant  
> > in which chess creativity and talent would be more important than  
> > memorization  
> > and analysis of opening moves. His approach was to create a randomized  
> > initial  
> > chess position, which would thus make memorizing chess opening move  
> > sequences  
> > far less helpful. The initial position is set up in a special way and  
> > there are  
> > 960 such positions, thus the name Chess960.
> > 
> > The starting position for Chess960 must meet certain rules. White pawns  
> > are  
> > placed on the second rank as in chess. All remaining white pieces are  
> > placed  
> > randomly on the first rank, but with the following restrictions:
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* The king is placed somewhere between the two rooks.  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* The bishops are placed on opposite-colored squares.
> > 
> > The black pieces are placed equal-and-opposite to the white pieces. For  
> > example,  
> > if the white king is placed on b1, then the black king is placed on b8.  
> > Note  
> > that the king never starts on file a or h, because there would be no room  
> > for a  
> > rook
> > 
> > Can I suggest a nice little ruby program to generates all 960 possible  
> > starting  
> > positions and outputs a random one on request.
> > 
> > Output could be as follows.
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Starting Position 432:
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;White
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a1 b1 c1 d1 e1 f1 g1 h1  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N B B R K R Q N
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Black
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a8 b8 c8 d8 e8 f8 g8 h8  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N B B R K R Q N
> > 
> > Or some better output.

---

<div class="post-metadata">

**Author:** ![W\_James](https://avatars.discourse-cdn.com/v4/letter/w/e274bd/32.png) [@W\_James](https://rubytalk.org/u/W_James)\
**Post date:** [17 December 2006 17:25 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/5 "2006-12-17T17:25:08Z")

</div>

Ruby Quiz wrote:

> by Kieran Wild
> 
> Chess960, is a chess variant produced by Grandmaster Bobby Fischer by  
> formalizing the rules of Shuffle Chess. Its goal was to create a chess variant  
> in which chess creativity and talent would be more important than memorization  
> and analysis of opening moves. His approach was to create a randomized initial  
> chess position, which would thus make memorizing chess opening move sequences  
> far less helpful. The initial position is set up in a special way and there are  
> 960 such positions, thus the name Chess960.
> 
> The starting position for Chess960 must meet certain rules. White pawns are  
> placed on the second rank as in chess. All remaining white pieces are placed  
> randomly on the first rank, but with the following restrictions:
> 
> &nbsp;&nbsp;\* The king is placed somewhere between the two rooks.  
> &nbsp;&nbsp;\* The bishops are placed on opposite-colored squares.
> 
> The black pieces are placed equal-and-opposite to the white pieces. For example,  
> if the white king is placed on b1, then the black king is placed on b8. Note  
> that the king never starts on file a or h, because there would be no room for a  
> rook
> 
> Can I suggest a nice little ruby program to generates all 960 possible starting  
> positions and outputs a random one on request.

which = ( ARGV.first || rand(960) + 1 ).to\_i  
count = 0

(1..6).each{|k|  
&nbsp;&nbsp;(0...k).each{|r1|  
&nbsp;&nbsp;&nbsp;&nbsp;(k+1..7).each{|r2|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((0..7).to\_a - [k,r1,r2]).each{|q|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;used = [k,r1,r2,q]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((0..7).select{|i| i % 2 == 0} - used).each{|b1|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((0..7).select{|i| i % 2 == 1} - used).each{|b2|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count += 1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if which == count  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Position #{ count }"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s = 'N' \* 8  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[k,q,r1,r2,b1,b2].zip(%w(K Q R R B B)).each{|i,p|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s[i] = p }  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts s.downcase,'p'\*8,('.'\*8+"\n")\*4,'P'\*8,s  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end } } } } } }

---

<div class="post-metadata">

**Author:** ![Forum](https://avatars.discourse-cdn.com/v4/letter/f/43a26b/32.png) [@Forum](https://rubytalk.org/u/Forum)\
**Post date:** [17 December 2006 17:50 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/6 "2006-12-17T17:50:58Z")

</div>

Here is my solution to #106 I thaught I'll make a more readable amb based  
soluytion but I did not succeed so far :(, maybe I'll come up with it before  
not too long.

> **···**
>
> -----------------------------------------  
> #!/usr/bin/ruby  
> class Chess960  
> &nbsp;&nbsp;&nbsp;&nbsp;class ::Range  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class \<\< self  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def free= args  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@@free = args  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def each\_free  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;each do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\>ele\>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next unless @@free.include? ele  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@@free.delete ele  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield ele  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@@free.unshift ele  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end #def each\_free  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;N = 8  
> &nbsp;&nbsp;&nbsp;&nbsp;def initialize  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@solutions = []  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Range.free = [\*1..N]  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;generate  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;def [] sol\_nb  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@solutions[sol\_nb]  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;private  
> &nbsp;&nbsp;&nbsp;&nbsp;def init  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol="Q " \* N  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;def generate  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1..N-1).each\_free do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\>@b1|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(@b1.succ..N).each\_free do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\>@b2|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next if @b1 & 1 == @b2 & 1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1..N-2).each\_free do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\>@r1|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(@r1.succ..N-1).each\_free do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\>@k|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(@k.succ..N).each\_free do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\>@r2|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1..N-1).each\_free do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\>@n1|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(@n1.succ..N).each\_free do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\>@n2|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;save\_solution  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end #(@k.succ..N).each\_free do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end #(1..N-2).each\_free do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;def save\_solution  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol[2\*(@b1-1)]= ?B  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol[2\*(@b2-1)]= ?B  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol[2\*(@r1-1)]= ?R  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol[2\*(@r2-1)]= ?R  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol[2\*(@n1-1)]= ?N  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol[2\*(@n2-1)]= ?N  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol[2\*(@k-1)] = ?K
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@solutions \<\< @sol  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> end
> 
> c = Chess960.new  
> puts %\<enter a number to show a specific solution (0 based) or  
> enter r for a random solution or  
> enter q to go back to work\>  
> until (n = gets.strip) =~ /^q/i  
> &nbsp;&nbsp;&nbsp;&nbsp;i = n.to\_i  
> &nbsp;&nbsp;&nbsp;&nbsp;i = rand(960) if n =~ /^r/i  
> &nbsp;&nbsp;&nbsp;&nbsp;puts "Solution #{i}"  
> &nbsp;&nbsp;&nbsp;&nbsp;puts c[i]  
> end  
> -----------------------------------------
> 
> Cheers  
> Robert  
> --  
> "The real romance is out ahead and yet to come. The computer revolution  
> hasn't started yet. Don't be misled by the enormous flow of money into bad  
> defacto standards for unsophisticated buyers using poor adaptations of  
> incomplete ideas."
> 
> - Alan Kay

---

<div class="post-metadata">

**Author:** ![Forum](https://avatars.discourse-cdn.com/v4/letter/f/43a26b/32.png) [@Forum](https://rubytalk.org/u/Forum)\
**Post date:** [17 December 2006 19:28 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/7 "2006-12-17T19:28:23Z")

</div>

Here goes my second solution, looks a little bit better, using Jim Weirich's  
Amb class

> **···**
>
> ------------------------------------------------------------------  
> #!/usr/bin/ruby  
> # This solution uses a cut down version of Jim Weirich's Amb class  
> # submitted to Ruby Quiz # 70. Hope that's ok?  
> #  
> # The purpose of this solution is to show how #generate becomes more  
> readable  
> # and there is a fix of the "place 2 Knights instead of 1 Queen" error.  
> class Amb  
> &nbsp;&nbsp;class ExhaustedError \< RuntimeError; end
> 
> &nbsp;&nbsp;def initialize  
> &nbsp;&nbsp;&nbsp;&nbsp;@fail = proc { fail ExhaustedError, "amb tree exhausted" }  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def choose(\*choices)  
> &nbsp;&nbsp;&nbsp;&nbsp;prev\_fail = @fail  
> &nbsp;&nbsp;&nbsp;&nbsp;callcc { |sk|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;choices.each { |choice|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;callcc { |fk|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@fail = proc {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@fail = prev\_fail  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fk.call(:fail)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sk.call(choice)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@fail.call  
> &nbsp;&nbsp;&nbsp;&nbsp;}  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def assert(cond)  
> &nbsp;&nbsp;&nbsp;&nbsp;choose unless cond  
> &nbsp;&nbsp;end  
> end
> 
> class Chess960  
> &nbsp;&nbsp;&nbsp;&nbsp;N = 8  
> &nbsp;&nbsp;&nbsp;&nbsp;Queen = ?Q  
> &nbsp;&nbsp;&nbsp;&nbsp;King = ?K  
> &nbsp;&nbsp;&nbsp;&nbsp;Rook = ?R  
> &nbsp;&nbsp;&nbsp;&nbsp;Bishop = ?B  
> &nbsp;&nbsp;&nbsp;&nbsp;def initialize  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@amb = Amb.new  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@solutions = []  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;generate  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise RuntimeError, "Illegal Number of solutions #{@solutions.length}"  
> unless  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@solutions.length == 960  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;def [] sol\_nb  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@solutions[sol\_nb]  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;private  
> &nbsp;&nbsp;&nbsp;&nbsp;def init  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol="N " \* N  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;def generate  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@b1 = @amb.choose( \*1..N-1 )  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@b2 = @amb.choose( \*@b1.succ..N )  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@amb.assert @b1 & 1 != @b2 & 1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@r1 = @amb.choose( \*1..N-2 )  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@k = @amb.choose( \*@r1.succ..N-1 )  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@r2 = @amb.choose( \*@k.succ..N )  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@q = @amb.choose( \*1..N )  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# This late check makes the whole thing more readable  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# we can easily afford the additional computations  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@amb.assert [@b1,@b2,@r1,@k,@r2,@q].uniq.length == 6  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;save\_solution  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rescue Amb::ExhaustedError  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;def save\_solution  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol[2\*(@b1-1)]= Bishop  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol[2\*(@b2-1)]= Bishop  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol[2\*(@r1-1)]= Rook  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol[2\*(@r2-1)]= Rook  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol[2\*(@q-1)]= Queen  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@sol[2\*(@k-1)] = King  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@solutions \<\< @sol  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@amb.choose  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> end
> 
> c = Chess960.new  
> puts %\<enter a number to show a specific solution (0 based) or  
> enter r for a random solution or  
> enter q to go back to work\>  
> until (n = gets.strip) =~ /^q/i  
> &nbsp;&nbsp;&nbsp;&nbsp;i = n.to\_i  
> &nbsp;&nbsp;&nbsp;&nbsp;i = rand(960) if n =~ /^r/i  
> &nbsp;&nbsp;&nbsp;&nbsp;puts "Solution #{i}"  
> &nbsp;&nbsp;&nbsp;&nbsp;puts c[i]  
> end
> 
> ------------------------------------------------------------------  
> Cheers  
> Robert  
> --  
> "The real romance is out ahead and yet to come. The computer revolution  
> hasn't started yet. Don't be misled by the enormous flow of money into bad  
> defacto standards for unsophisticated buyers using poor adaptations of  
> incomplete ideas."
> 
> - Alan Kay

---

<div class="post-metadata">

**Author:** ![Jamie\_Macey](https://avatars.discourse-cdn.com/v4/letter/j/9dc877/32.png) [@Jamie\_Macey](https://rubytalk.org/u/Jamie_Macey)\
**Post date:** [18 December 2006 00:17 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/8 "2006-12-18T00:17:22Z")

</div>

I just did up a random generator using the die-rolling method  
mentioned on Wikipedia. As such, it's not deterministic, so my boards  
can't be referenced by number.

After my Chess360 class is a Camping app to host it - my current code  
is live at [http://tracefunc.com:3301/](http://tracefunc.com:3301/) - the images were shamelessly stolen from  
[PmWiki | Cookbook / ChessMarkup](http://www.pmwiki.org/wiki/Cookbook/ChessMarkup), and the whole thing  
(code plus images) can be downloaded from  
[Index - set\_trace\_func](http://tracefunc.com/chess960.zip) - I'd've attached it but ruby-talk  
rejected it as too large a message.

- Jamie

class Chess960  
&nbsp;&nbsp;attr\_reader :board\_id, :board

&nbsp;&nbsp;def initialize  
&nbsp;&nbsp;&nbsp;&nbsp;@board = generate\_board(bodlaender\_line)  
&nbsp;&nbsp;end

&nbsp;&nbsp;def generate\_board(white)  
&nbsp;&nbsp;&nbsp;&nbsp;# Black's starting line is mirror of white's  
&nbsp;&nbsp;&nbsp;&nbsp;black = white.map{|piece| piece.downcase}

&nbsp;&nbsp;&nbsp;&nbsp;# middle of board is always the same  
&nbsp;&nbsp;&nbsp;&nbsp;middle = [  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%w(p p p p p p p p),  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%w(\_ \_ \_ \_ \_ \_ \_ \_),  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%w(P P P P P P P P)  
&nbsp;&nbsp;&nbsp;&nbsp;]

&nbsp;&nbsp;&nbsp;&nbsp;# add back rows  
&nbsp;&nbsp;&nbsp;&nbsp;[black] + middle + [white]  
&nbsp;&nbsp;end

&nbsp;&nbsp;def bodlaender\_line  
&nbsp;&nbsp;&nbsp;&nbsp;free = (0...8).to\_a  
&nbsp;&nbsp;&nbsp;&nbsp;white =

&nbsp;&nbsp;&nbsp;&nbsp;dark\_bishop = rand(4) \* 2  
&nbsp;&nbsp;&nbsp;&nbsp;light\_bishop = rand(4) \* 2 + 1  
&nbsp;&nbsp;&nbsp;&nbsp;white[dark\_bishop] = 'B'  
&nbsp;&nbsp;&nbsp;&nbsp;white[light\_bishop] = 'B'  
&nbsp;&nbsp;&nbsp;&nbsp;free.delete(dark\_bishop)  
&nbsp;&nbsp;&nbsp;&nbsp;free.delete(light\_bishop)

&nbsp;&nbsp;&nbsp;&nbsp;queen = rand(6)  
&nbsp;&nbsp;&nbsp;&nbsp;white[free[queen]] = 'Q'  
&nbsp;&nbsp;&nbsp;&nbsp;free.delete\_at(queen)

&nbsp;&nbsp;&nbsp;&nbsp;knight1 = rand(5)  
&nbsp;&nbsp;&nbsp;&nbsp;white[free[knight1]] = 'N'  
&nbsp;&nbsp;&nbsp;&nbsp;free.delete\_at(knight1)  
&nbsp;&nbsp;&nbsp;&nbsp;knight2 = rand(4)  
&nbsp;&nbsp;&nbsp;&nbsp;white[free[knight2]] = 'N'  
&nbsp;&nbsp;&nbsp;&nbsp;free.delete\_at(knight2)

&nbsp;&nbsp;&nbsp;&nbsp;white[free[0]] = 'R'  
&nbsp;&nbsp;&nbsp;&nbsp;white[free[1]] = 'K'  
&nbsp;&nbsp;&nbsp;&nbsp;white[free[2]] = 'R'  
&nbsp;&nbsp;&nbsp;&nbsp;white  
&nbsp;&nbsp;end  
end

> **···**
>
> On 12/15/06, Ruby Quiz \<james@grayproductions.net\> wrote:
> 
> > by Kieran Wild
> > 
> > Chess960, is a chess variant produced by Grandmaster Bobby Fischer by  
> > formalizing the rules of Shuffle Chess. Its goal was to create a chess variant  
> > in which chess creativity and talent would be more important than memorization  
> > and analysis of opening moves. His approach was to create a randomized initial  
> > chess position, which would thus make memorizing chess opening move sequences  
> > far less helpful. The initial position is set up in a special way and there are  
> > 960 such positions, thus the name Chess960.
> > 
> > The starting position for Chess960 must meet certain rules. White pawns are  
> > placed on the second rank as in chess. All remaining white pieces are placed  
> > randomly on the first rank, but with the following restrictions:
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* The king is placed somewhere between the two rooks.  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* The bishops are placed on opposite-colored squares.
> > 
> > The black pieces are placed equal-and-opposite to the white pieces. For example,  
> > if the white king is placed on b1, then the black king is placed on b8. Note  
> > that the king never starts on file a or h, because there would be no room for a  
> > rook
> > 
> > Can I suggest a nice little ruby program to generates all 960 possible starting  
> > positions and outputs a random one on request.
> 
> ###########
> 
> require 'rubygems'  
> require 'camping'  
> require 'chess960'
> 
> Camping.goes :Chess
> 
> module Chess::Controllers  
> &nbsp;&nbsp;# main page  
> &nbsp;&nbsp;class Index \< R '/'  
> &nbsp;&nbsp;&nbsp;&nbsp;def get  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@chess = Chess960.new  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;render :index  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;# image passthrough  
> &nbsp;&nbsp;class Images \< R '/images/(.+)'  
> &nbsp;&nbsp;&nbsp;&nbsp;MIME\_TYPES = {'.png' =\> 'image/png'}  
> &nbsp;&nbsp;&nbsp;&nbsp;PATH = \_\_FILE\_\_[/(.\*)\//, 1]
> 
> &nbsp;&nbsp;&nbsp;&nbsp;def get(path)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@headers['Content-Type'] = MIME\_TYPES[path[/\.\w+$/, 0]] || "text/plain"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unless path =~ /\.\./ # sample test to prevent directory traversal attacks  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@headers['X-Sendfile'] = "#{PATH}/images/#{path}"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"404 - Invalid path"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end  
> end
> 
> module Chess::Views  
> &nbsp;&nbsp;def layout  
> &nbsp;&nbsp;&nbsp;&nbsp;html do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;body do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;style :type =\> 'text/css' do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"#chess { border-collapse: collapse;  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;float: left; margin-right: 2em; } " +  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".dark { background-color: #888; } " +  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".light { background-color: #ddd; } " +  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".thin { width: 50em; } "  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self \<\< yield  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def index  
> &nbsp;&nbsp;&nbsp;&nbsp;c = 0  
> &nbsp;&nbsp;&nbsp;&nbsp;table.chess! do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@chess.board.each do |row|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c = 1 - c  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tr do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;row.each do |tile|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c = 1 - c  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;td :class =\> c==0 ? 'light' : 'dark' do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;img :src =\> "images/#{tile}.png"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;h1 "Chess 960"  
> &nbsp;&nbsp;&nbsp;&nbsp;div.thin do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text "\<p\>Randomly created board, using the #{a 'Bodlaendar', :href =\>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"[Fischer random chess - Wikipedia](http://en.wikipedia.org/wiki/Chess960#Determining_a_starting_position&quot;%5C)}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method for generating piece order.\</p\>"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p "Result was #{@chess.board.last.join(", ")}."  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end  
> end

---

<div class="post-metadata">

**Author:** ![Eric\_I2](https://avatars.discourse-cdn.com/v4/letter/e/22d042/32.png) [@Eric\_I2](https://rubytalk.org/u/Eric_I2)\
**Post date:** [18 December 2006 06:45 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/9 "2006-12-18T06:45:08Z")

</div>

Here's my solution. I hadn't realized that there was an official  
numbering scheme to the Chess960 starting positions. So my program  
uses an ad hoc numbering scheme.

The program uses a simple recursive descent technique. Seen positions  
(full and parital) are memorizeed so as not to revisit them again. All  
possible board positions are generated and placed in an array, and the  
number chosen is used as an index into this array.

Eric

> **···**
>
> ----  
> Considering Ruby Training? Visit [http://learnruby.com](http://learnruby.com) .
> 
> ----------------------------------------
> 
> # Returns true if a layout or partial layout is legal, false if it  
> # isn't. Makes sure the bishops are on different colors and the king  
> # is between the rooks.  
> def good?(layout)  
> &nbsp;&nbsp;bishop1 = layout.index(:b)  
> &nbsp;&nbsp;bishop2 = layout.rindex(:b)  
> &nbsp;&nbsp;return false if bishop1 != bishop2 && bishop1 % 2 == bishop2 % 2
> 
> &nbsp;&nbsp;rook1 = layout.index(:r)  
> &nbsp;&nbsp;rook2 = layout.rindex(:r)  
> &nbsp;&nbsp;king = layout.index(:k)  
> &nbsp;&nbsp;!(rook1 != rook2 && (king.nil? || king \< rook1 || king \> rook2))  
> end
> 
> # Generates all possible layouts. pieces contains all the remaining  
> # pieces to be placed. layout is the layout so far. layout\_set are  
> # the completed layouts that have so far been generated. layouts\_seen  
> # are the full and partial layouts that have already been seen, to  
> # avoid duplicate efforts.  
> def generate(pieces, layout, layout\_set, seen\_layouts)  
> &nbsp;&nbsp;if pieces.empty? : layout\_set \<\< layout.dup # complete layout  
> &nbsp;&nbsp;elsif seen\_layouts[layout] : return # layout already seen  
> &nbsp;&nbsp;else # partial layout; do  
> next square  
> &nbsp;&nbsp;&nbsp;&nbsp;seen\_layouts[layout.dup] = true  
> &nbsp;&nbsp;&nbsp;&nbsp;pieces.each\_index do |i|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;layout.push(pieces.delete\_at(i))  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;generate(pieces, layout, layout\_set, seen\_layouts) if  
> good?(layout)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pieces.insert(i, layout.pop)  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end  
> end
> 
> # Generates a string that describes a given layout.  
> def display(layout)  
> &nbsp;&nbsp;[["White", 1], ["Black", 8]].map do |color, rank|  
> &nbsp;&nbsp;&nbsp;&nbsp;color \<\< "\n" \<\<  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;('a'..'h').map { |file| file + rank.to\_s }.join(" ") \<\< "\n" \<\<  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;layout.map{|sym| sym.to\_s.upcase}.join(" ") \<\< "\n"  
> &nbsp;&nbsp;end.join("\n")  
> end
> 
> layouts = []
> 
> generate([:r, :n, :b, :q, :k, :b, :n, :r], [], layouts, {})
> 
> if ARGV.size \> 1  
> &nbsp;&nbsp;$stderr.puts "Usage: #{$0} [layout-index]"  
> &nbsp;&nbsp;exit 1  
> elsif ARGV.size == 1  
> &nbsp;&nbsp;layout\_index = ARGV[0].to\_i  
> &nbsp;&nbsp;if layout\_index \< 1 || layout\_index \> layouts.size  
> &nbsp;&nbsp;&nbsp;&nbsp;$stderr.puts "Error: layout-index must be from 1 to  
> #{layouts.size}."  
> &nbsp;&nbsp;&nbsp;&nbsp;exit 2  
> &nbsp;&nbsp;end  
> else  
> &nbsp;&nbsp;layout\_index = rand(layouts.size) + 1  
> end
> 
> puts "Layout ##{layout\_index}:\n\n"  
> puts display(layouts[layout\_index - 1])

---

<div class="post-metadata">

**Author:** ![Dave\_Burt2](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/dave_burt2/32/2036_2.png) [@Dave\_Burt2](https://rubytalk.org/u/Dave_Burt2)\
**Post date:** [18 December 2006 11:00 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/10 "2006-12-18T11:00:06Z")

</div>

D:\Docs\ruby\>ruby chess960.rb  
[Event "Starting Position 787"]  
[SetUp "1"]  
[FEN "bbrnkrqn/pppppppp/8/8/8/8/PPPPPPPP/BBRNKRQN w KQkq - 0 1"]

&nbsp;&nbsp;&nbsp;&nbsp;a b c d e f g h

> **···**
>
> +-----------------+  
> 8 | b b r n k r q n | 8  
> 7 | p p p p p p p p | 7  
> 6 | . . . . . . . . | 6  
> 5 | . . . . . . . . | 5  
> 4 | . . . . . . . . | 4  
> 3 | . . . . . . . . | 3  
> 2 | P P P P P P P P | 2  
> 1 | B B R N K R Q N | 1  
> &nbsp;&nbsp;+-----------------+  
> &nbsp;&nbsp;&nbsp;&nbsp;a b c d e f g h
> 
> D:\Docs\ruby\>cat chess960.rb  
> class Array  
> &nbsp;&nbsp;def permute  
> &nbsp;&nbsp;&nbsp;&nbsp;if empty?  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[]  
> &nbsp;&nbsp;&nbsp;&nbsp;elsif size == 1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[self]  
> &nbsp;&nbsp;&nbsp;&nbsp;else  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;heads = uniq  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret = []  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;heads.each do |head|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tails = dup  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tails.delete\_at index(head)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret.concat tails.permute.map {|tail| [head, \*tail] }  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end  
> end
> 
> module Chess960
> 
> &nbsp;&nbsp;def all  
> &nbsp;&nbsp;&nbsp;&nbsp;\_all.dup  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def random  
> &nbsp;&nbsp;&nbsp;&nbsp;\_all[rand(960)].dup  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def ascii\_board\_showing(n)  
> &nbsp;&nbsp;&nbsp;&nbsp;top\_row = \_all[n].join(' ')  
> &nbsp;&nbsp;&nbsp;&nbsp;bottom\_row = top\_row.upcase  
> &nbsp;&nbsp;&nbsp;&nbsp;\<\<-END  
> &nbsp;&nbsp;&nbsp;&nbsp;a b c d e f g h  
> &nbsp;&nbsp;+-----------------+  
> 8 | #{ top\_row } | 8  
> 7 | p p p p p p p p | 7  
> 6 | | 6  
> 5 | | 5  
> 4 | | 4  
> 3 | | 3  
> 2 | P P P P P P P P | 2  
> 1 | #{ bottom\_row } | 1  
> &nbsp;&nbsp;+-----------------+  
> &nbsp;&nbsp;&nbsp;&nbsp;a b c d e f g h  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def fen\_notation\_for(n)  
> &nbsp;&nbsp;&nbsp;&nbsp;"#{all[n]}/pppppppp/8/8/8/8/PPPPPPPP/#{all[n].join.upcase} w KQkq - 0 1"  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def pgn\_notation\_for(n)  
> &nbsp;&nbsp;&nbsp;&nbsp;\<\<-END  
> [Event "Starting Position #{n}"]  
> [SetUp "1"]  
> [FEN "#{fen\_notation\_for(n)}"]  
> &nbsp;&nbsp;&nbsp;&nbsp;END  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;private
> 
> &nbsp;&nbsp;&nbsp;&nbsp;def \_all  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@all ||= %w[r n b q k b n r].permute.select {|x| valid\_position?(x) }  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;def valid\_position?(array)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# array.sort == %w [b b k n n q r r] &&  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(array.index("b") + array.rindex("b")) % 2 == 1 &&  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array.grep(/[rk]/) == %w[r k r]  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;extend self  
> end
> 
> if $0 == \_\_FILE\_\_
> 
> &nbsp;&nbsp;n = rand(960)  
> &nbsp;&nbsp;puts Chess960.pgn\_notation\_for(n)  
> &nbsp;&nbsp;puts  
> &nbsp;&nbsp;puts Chess960.ascii\_board\_showing(n)  
> end

---

<div class="post-metadata">

**Author:** ![Morton\_Goldberg](https://avatars.discourse-cdn.com/v4/letter/m/7ea924/32.png) [@Morton\_Goldberg](https://rubytalk.org/u/Morton_Goldberg)\
**Post date:** [18 December 2006 13:11 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/11 "2006-12-18T13:11:50Z")

</div>

Here is my solution. Run with no argument, it generates a random initial position. Run with an argument in the range 1..960, it provides the initial position for the specified game. It uses Scharnagl's method which is quite easy to implement in Ruby.

Here is what it produces when given 519 as its argument:

Initial position 519  
rnbqkbnr  
pppppppp  
........  
PPPPPPPP  
RNBQKBNR

Regards, Morton

\<code\>  
#! /usr/bin/env ruby -w

> **···**
>
> #  
> # Ruby Quiz 106 -- Chess960 Starting Positions  
> # Implementation uses Scharnagl's tables. See  
> # [http://en.wikipedia.org/wiki/Chess960\_starting\_position](http://en.wikipedia.org/wiki/Chess960_starting_position)
> 
> class Chess960  
> &nbsp;&nbsp;&nbsp;&nbsp;BISHOP\_TABLE = [  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"BB------", #0  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"B--B----", #1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"B----B--", #2  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"B------B", #3  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"-BB-----", #4  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"--BB----", #5  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"--B--B--", #6  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"--B----B", #7  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"-B--B---", #8  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"---BB---", #9  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"----BB--", #10  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"----B--B", #11  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"-B----B-", #12  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"---B--B-", #13  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"-----BB-", #14  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"------BB" #15  
> &nbsp;&nbsp;&nbsp;&nbsp;]
> 
> &nbsp;&nbsp;&nbsp;&nbsp;N5N\_TABLE = [  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"NN---", #0  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"N-N--", #1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"N--N-", #2  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"N---N", #3  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"-NN--", #4  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"-N-N-", #5  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"-N--N", #6  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"--NN-", #7  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"--N-N", #8  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"---NN" #9  
> &nbsp;&nbsp;&nbsp;&nbsp;]
> 
> &nbsp;&nbsp;&nbsp;&nbsp;def initialize(number)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q, @bishop\_index = (number - 1).divmod 16  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@knight\_index, @queen\_index = q.divmod 6  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@white\_pieces = BISHOP\_TABLE[@bishop\_index].split('')  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@white\_pieces[nth\_dash(@queen\_index)] = 'Q'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;knights = N5N\_TABLE[@knight\_index]  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m = knights.index('N')  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n = knights.index('N', m + 1)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m, n = nth\_dash(m), nth\_dash(n)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@white\_pieces[m] = 'N'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@white\_pieces[n] = 'N'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@white\_pieces[@white\_pieces.index('-')] = 'R'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@white\_pieces[@white\_pieces.index('-')] = 'K'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@white\_pieces[@white\_pieces.index('-')] = 'R'  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;def nth\_dash(n)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dashes = []  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@white\_pieces.each\_with\_index { |ch, i| dashes \<\< i if ch == '-' }  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dashes[n]  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;def inspect  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@white\_pieces.join  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;def to\_s  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;white\_pieces = @white\_pieces.join + "\n"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;white\_pawns = 'P' \* 8 + "\n"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;black\_pieces = white\_pieces.downcase  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;black\_pawns = 'p' \* 8 + "\n"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;empty = ('.' \* 8 + "\n") \* 4  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;black\_pieces + black\_pawns + empty + white\_pawns + white\_pieces  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> end
> 
> if \_\_FILE\_\_ == $0  
> &nbsp;&nbsp;&nbsp;&nbsp;begin  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ARGV.empty? then n = 1 + rand(960)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n = ARGV.first.to\_i  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise StandardError unless (1..960).include?(n)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Initial position #{n}"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print Chess960.new(n).to\_s  
> &nbsp;&nbsp;&nbsp;&nbsp;rescue StandardError  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Usage: #{$PROGRAM\_NAME} [\<integer\>]"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "where \<integer\> is in 1..960"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Omitting \<integer\> produces a random initial position"  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> end  
> \</code\>

---

<div class="post-metadata">

**Author:** ![Rob\_Biedenharn1](https://avatars.discourse-cdn.com/v4/letter/r/57b2e6/32.png) [@Rob\_Biedenharn1](https://rubytalk.org/u/Rob_Biedenharn1)\
**Post date:** [18 December 2006 13:27 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/12 "2006-12-18T13:27:57Z")

</div>

I found the Wikipedia article that described the Chess960\_Enumbering\_Scheme and used its direct derivation of the placement from the number. The relevant portion of the article is mixed in as comments in the code below.

-Rob

Rob Biedenharn [http://agileconsultingllc.com](http://agileconsultingllc.com)  
[Rob@AgileConsultingLLC.com](mailto:Rob@AgileConsultingLLC.com)

#!/usr/bin/env ruby -w

> **···**
>
> #  
> # Solution by: Rob Biedenharn  
> #  
> # From: [james@grayproductions.net](mailto:james@grayproductions.net)  
> # Subject: [QUIZ] Chess960 (#106)  
> # Date: December 15, 2006 8:50:58 AM EST  
> # To: [ruby-talk@ruby-lang.org](mailto:ruby-talk@ruby-lang.org)  
> #  
> # by Kieran Wild  
> #  
> # Chess960, is a chess variant produced by Grandmaster Bobby Fischer by  
> # formalizing the rules of Shuffle Chess. Its goal was to create a chess  
> # variant in which chess creativity and talent would be more important than  
> # memorization and analysis of opening moves. His approach was to create a  
> # randomized initial chess position, which would thus make memorizing chess  
> # opening move sequences far less helpful. The initial position is set up in a  
> # special way and there are 960 such positions, thus the name Chess960.  
> #  
> # The starting position for Chess960 must meet certain rules. White pawns are  
> # placed on the second rank as in chess. All remaining white pieces are placed  
> # randomly on the first rank, but with the following restrictions:  
> #  
> # \* The king is placed somewhere between the two rooks.  
> # \* The bishops are placed on opposite-colored squares.  
> #  
> # The black pieces are placed equal-and-opposite to the white pieces. For  
> # example, if the white king is placed on b1, then the black king is placed on  
> # b8. Note that the king never starts on file a or h, because there would be  
> # no room for a rook  
> #  
> # Can I suggest a nice little ruby program to generates all 960 possible  
> # starting positions and outputs a random one on request.  
> # ----------------------------------------------------------------------------  
> # From wikipedia:  
> # [http://en.wikipedia.org/wiki/Chess960\_starting\_position](http://en.wikipedia.org/wiki/Chess960_starting_position)  
> #  
> # [http://en.wikipedia.org/wiki/Chess960\_Enumbering\_Scheme](http://en.wikipedia.org/wiki/Chess960_Enumbering_Scheme)  
> #  
> # Direct Derivation  
> #  
> # The accurate sequence of White's Chess960 starting array could be derived  
> # from its number as follows:  
> #  
> debug=ENV['DEBUG']  
> puts "ARGV: #{ARGV.join(', ')}" if debug
> 
> starting\_position = ARGV.empty? ? rand(960) : ARGV[0].to\_i  
> string = '-' \* 8  
> # a) Divide the number by 960, determine the remainder (0 ... 959) and use  
> # that number thereafter.  
> temp = starting\_position % 960
> 
> puts "starting\_position #{starting\_position}" if debug  
> puts "a) #{string}" if debug
> 
> # b) Divide the number by 4, determine the remainder (0 ... 3) and  
> # correspondingly place a Bishop upon the matching bright square (b, d, f, h).  
> temp,lb = temp.divmod 4  
> string[2\*lb+1]='B'
> 
> puts "b) #{lb} #{string} #{temp}" if debug
> 
> # c) Divide the number by 4, determine the remainder (0 ... 3) and  
> # correspondingly place a Bishop upon the matching dark square (a, c, e, g).  
> temp,db = temp.divmod 4  
> string[2\*db]='B'
> 
> puts "c) #{db} #{string} #{temp}" if debug
> 
> # d) Divide the number by 6, determine the remainder (0 ... 5) und  
> # correspondingly place the Queen upon the matching of the six free squares.  
> n,q = temp.divmod 6  
> print "d) #{q} " if debug  
> string.gsub!(/-/) { |p| p='Q' if q.zero?; q -= 1; p }  
> puts "#{string} #{n}" if debug
> 
> # e) Now only one digit (0 ... 9) is left on hand; place the both Knights upon  
> # the remaining five free squares according to following scheme:  
> #  
> # Digit Knights' Positioning  
> # 0 N N - - -  
> # 1 N - N - -  
> # 2 N - - N -  
> # 3 N - - - N  
> # 4 - N N - -  
> # 5 - N - N -  
> # 6 - N - - N  
> # 7 - - N N -  
> # 8 - - N - N  
> # 9 - - - N N
> 
> require 'enumerator'  
> class Integer  
> &nbsp;&nbsp;&nbsp;def comb(r=1)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if self \< r or r \< 1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elsif r == 1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.upto(self-1) { |x| yield [x] }  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(0...self).each\_cons(1) do |i|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(self-1).comb(r-1) do |j|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next if j.last + i.last \>= self-1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bump=i.last+1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield(i + j.map! { |e| e+bump })  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;end  
> end
> 
> print "e) #{n} " if debug  
> 5.comb(2) do |c|  
> # puts "comb: #{c.join(' ')}" if debug  
> &nbsp;&nbsp;&nbsp;if n.zero?  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c.reverse.each do |q|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string.gsub!(/-/) { |p| p='N' if q.zero?; q -= 1; p }  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break  
> &nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;n -= 1  
> end
> 
> puts "#{string}" if debug
> 
> # f) The now still remaining three free squares will be filled in the  
> # following sequence: Rook, King, Rook.  
> puts "f)" if debug  
> %w[R K R].each do |p|  
> &nbsp;&nbsp;&nbsp;string[string.index('-')] = p  
> &nbsp;&nbsp;&nbsp;puts " #{string}" if debug  
> end
> 
> fen = "#{string.downcase}/#{'p'\*8}/8/8/8/8/#{'P'\*8}/#{string} w KQkq - 0 1"
> 
> puts %{[Event "Starting Position #{starting\_position}"]}  
> puts %{[SetUp "1"]}  
> puts %{[FEN "#{fen}"]}
> 
> \_\_END\_\_

---

<div class="post-metadata">

**Author:** ![Eric\_I2](https://avatars.discourse-cdn.com/v4/letter/e/22d042/32.png) [@Eric\_I2](https://rubytalk.org/u/Eric_I2)\
**Post date:** [18 December 2006 18:05 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/13 "2006-12-18T18:05:07Z")

</div>

I decided to make a second submission that uses the official board  
position numbering scheme as described on Wikipedia.

Eric

> **···**
>
> ----  
> Interested in Ruby Training? See [http://learnruby.com](http://learnruby.com) .
> 
> ----------------------------------------
> 
> # Generates a string that describes a given layout.  
> def display(layout)  
> &nbsp;&nbsp;[["White", 1], ["Black", 8]].map do |color, rank|  
> &nbsp;&nbsp;&nbsp;&nbsp;color \<\< "\n" \<\<  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;('a'..'h').map { |file| file + rank.to\_s }.join(" ") \<\< "\n" \<\<  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;layout.map{|sym| sym.to\_s.upcase}.join(" ") \<\< "\n"  
> &nbsp;&nbsp;end.join("\n")  
> end
> 
> # Places the given piece in an empty cell of positions indexed by  
> # index.  
> def place\_in\_empty(positions, index, piece)  
> &nbsp;&nbsp;positions[(0..7).to\_a.select { |i| positions[i].nil? }[index]] =  
> piece  
> end
> 
> index = (ARGV[0] || rand(960)).to\_i  
> index %= 960
> 
> positions = Array.new(8)
> 
> positions[(index % 4) \* 2 + 1] = :b  
> index /= 4
> 
> positions[(index % 4) \* 2] = :b  
> index /= 4
> 
> place\_in\_empty(positions, index % 6, :q)  
> index /= 6
> 
> [[0, 1], [0, 2], [0, 3], [0, 4], [1, 2],  
> [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]][index].reverse.each do |i|  
> &nbsp;&nbsp;place\_in\_empty(positions, i, :n)  
> end
> 
> place\_in\_empty(positions, 0, :r)  
> place\_in\_empty(positions, 0, :k)  
> place\_in\_empty(positions, 0, :r)
> 
> puts display(positions)

---

<div class="post-metadata">

**Author:** ![Daniel\_Finnie1](https://avatars.discourse-cdn.com/v4/letter/d/4af34b/32.png) [@Daniel\_Finnie1](https://rubytalk.org/u/Daniel_Finnie1)\
**Post date:** [19 December 2006 03:27 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/14 "2006-12-19T03:27:42Z")

</div>

This is my solution. It makes use of my ArrayValue class which was discussed on the list previously. It calculate the placement of pieces for a certain number without first calculating the placement of the pieces for all numbers lower than it by using the following algorithm (found at [http://frcec.tripod.com/fischerrandomchessstartingpositions/\](http://frcec.tripod.com/fischerrandomchessstartingpositions/%5C)):  
1. id % 4 \* 2 = light square bishop (counting left to right  
2. (id / 4) % 4 \* 2 + 1 = dark square bishop ^ starting at 0)  
3. (id / 4 / 6) % 6 = queen, number of vacant squares from the left  
4. (id / 4 / 6) = KeRN code of the other pieces (see the website for more. The KeRN codes do have a pattern but I hard coded it).

First, an explaination of the ArrayValue class. The code is below:  
daniel@daniel-desktop:~$ cat arrayvalue.rb  
class ArrayValue  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;instance\_methods.each do |m|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;undef\_method(m) unless m =~ /^\_\*(method\_missing|send|id)\_\*$/  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def initialize(origArray, origIndex)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@origArray, @origIndex = origArray, origIndex  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def set(newObj)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@origArray[@origIndex] = newObj  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def get  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@origArray[@origIndex]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def method\_missing(method, \*args)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get.send(method, \*args)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rescue  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;define\_method(:'= ') {|other| set(other)}  
end

class Array  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def to\_av()  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret =   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;each\_index {|x| ret \<\< ArrayValue.new(self, x) }  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
end

So, an ArrayValue stores the array and index it originally came from and it can edit/get those values. Otherwise, an ArrayValue inherits all of the methods of the value it represents because of the method\_missing definition. One thing missing from the ArrayValue class is what to do if CRD (CRUD minus the U) operations are performed on the original array. Because of this, I recommend never actually storing an ArrayValue but creating them again every time you need one.

Also, the array class is edited to provide a to\_av method, which returns an array of ArrayValues. This is the only recommended way of creating ArrayValues.

Note that Logan Capaldo wrote something with the same concept but that uses some tricks with arrays and overriding = so that calling ArrayValue#Set is not necessary, you just go ArrayOfArrayValues[0]=Something and it changes the original array.

Some uses of ArrayValue:  
daniel@daniel-desktop:~$ irb -r arrayvalue.rb  
irb(main):001:0\> ary = [1, 2, 3, "a", :b]  
=\> [1, 2, 3, "a", :b]  
irb(main):002:0\> ary.to\_av[4].set("c")  
=\> "c"  
irb(main):003:0\> ary  
=\> [1, 2, 3, "a", "c"]  
irb(main):005:0\> ary.to\_av.select{|x| x.kind\_of?(Numeric)}.each{|x| x.set(42)}  
=\> [42, 42, 42]  
irb(main):006:0\> ary  
=\> [42, 42, 42, "a", "c"]  
irb(main):013:0\> ary = ["Skip me!", nil, nil, nil, 43]  
=\> ["Skip me!", nil, nil, nil, 43]  
irb(main):014:0\> ary.to\_av.select{|x| x.nil?}[1].set("The 2nd nil")  
=\> "The 2nd nil"  
irb(main):015:0\> ary  
=\> ["Skip me!", nil, "The 2nd nil", nil, 43]

Now to the real code:  
daniel@daniel-desktop:~$ cat chess960short.rb  
#! /usr/bin/ruby  
require 'arrayvalue.rb'

KeRN = \<\<-END.split("\n").collect{|x| x.split(" ")}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N N R K R  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N R N K R  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N R K N R  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N R K R N  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;R N N K R  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;R N K N R  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;R N K R N  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;R K N N R  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;R K N R N  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;R K R N N  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END

id = ARGV[0].to\_i % 960  
out = Array.new(8)  
1.downto(0) {|x| out[id % 4 \*2 + x] = "B"; id /= 4 }  
out.to\_av.select{|x| x.nil?}[id % 6].set("Q"); id /= 6  
KeRN[id].each{ |currentPiece| out.to\_av.select{|x| x.nil?}.first.set(currentPiece) }

Another, commented and not written for brevity version will be posted shortly.

Ruby Quiz wrote:

[arrayvalue.rb](https://rubytalk.org/uploads/short-url/wX2j575R7NrdAuD3YwxvIwUV9ZL.rb) (1.58 KB)

[chess960short.rb](https://rubytalk.org/uploads/short-url/cnrICTYezx68or3culN9wMK9DI6.rb) (459 Bytes)

> **···**
>
> > The three rules of Ruby Quiz:
> > 
> > 1. Please do not post any solutions or spoiler discussion for this quiz until  
> > 48 hours have passed from the time on this message.
> > 
> > 2. Support Ruby Quiz by submitting ideas as often as you can:
> > 
> > [http://www.rubyquiz.com/](http://www.rubyquiz.com/)
> > 
> > 3. Enjoy!
> > 
> > Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone  
> > on Ruby Talk follow the discussion. Please reply to the original quiz message,  
> > if you can.
> > 
> > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
> > 
> > by Kieran Wild
> > 
> > Chess960, is a chess variant produced by Grandmaster Bobby Fischer by  
> > formalizing the rules of Shuffle Chess. Its goal was to create a chess variant  
> > in which chess creativity and talent would be more important than memorization  
> > and analysis of opening moves. His approach was to create a randomized initial  
> > chess position, which would thus make memorizing chess opening move sequences  
> > far less helpful. The initial position is set up in a special way and there are  
> > 960 such positions, thus the name Chess960.
> > 
> > The starting position for Chess960 must meet certain rules. White pawns are  
> > placed on the second rank as in chess. All remaining white pieces are placed  
> > randomly on the first rank, but with the following restrictions:
> > 
> > &nbsp;&nbsp;\* The king is placed somewhere between the two rooks.  
> > &nbsp;&nbsp;\* The bishops are placed on opposite-colored squares.
> > 
> > The black pieces are placed equal-and-opposite to the white pieces. For example,  
> > if the white king is placed on b1, then the black king is placed on b8. Note  
> > that the king never starts on file a or h, because there would be no room for a  
> > rook
> > 
> > Can I suggest a nice little ruby program to generates all 960 possible starting  
> > positions and outputs a random one on request.
> > 
> > Output could be as follows.
> > 
> > &nbsp;&nbsp;Starting Position 432:  
> > &nbsp;&nbsp;  
> > &nbsp;&nbsp;White  
> > &nbsp;&nbsp;  
> > &nbsp;&nbsp;a1 b1 c1 d1 e1 f1 g1 h1  
> > &nbsp;&nbsp;N B B R K R Q N  
> > &nbsp;&nbsp;  
> > &nbsp;&nbsp;Black  
> > &nbsp;&nbsp;  
> > &nbsp;&nbsp;a8 b8 c8 d8 e8 f8 g8 h8  
> > &nbsp;&nbsp;N B B R K R Q N
> > 
> > Or some better output.

---

<div class="post-metadata">

**Author:** ![Daniel\_Finnie1](https://avatars.discourse-cdn.com/v4/letter/d/4af34b/32.png) [@Daniel\_Finnie1](https://rubytalk.org/u/Daniel_Finnie1)\
**Post date:** [19 December 2006 03:31 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/15 "2006-12-19T03:31:58Z")

</div>

This is the full version of the quiz that I wrote first. It uses the ArrayValues class which is described in my previous email. I think it is adequately documented as it is, especially because the algorithm and main logic parts are described in the previous email. Run with no options to get the usage. One thing to say, though is that the facets bracket method is basically this:  
class String  
&nbsp;&nbsp;def bracket(wrapper)  
&nbsp;&nbsp;&nbsp;wrapper + self + wrapper  
&nbsp;&nbsp;end  
end

It is actually more complex, there is a second argument you can pass in.

daniel@daniel-desktop:~$ cat chess960.rb  
#! /usr/bin/ruby -w  
require 'arrayvalue.rb'  
require 'rubygems'  
require 'facet/string/bracket'

# Represents a row ("rank") on a chess board  
class ChessRow \< Array  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def initialize  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;replace(Array.new(8))  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Sets the specified vacant square to the specified piece, with nthVacant starting at 0.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def setVacantSquare(nthVacantSquare, piece)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to\_av.select{|x| x.nil?}[nthVacantSquare].set(piece)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def to\_s  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;collect{|x| x.bracket(" ")}.join("|").bracket("|")  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
end

class Chess960Row \< ChessRow  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeRN = \<\<-END.split("\n").collect{|x| x.split(" ")}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N N R K R  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N R N K R  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N R K N R  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N R K R N  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;R N N K R  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;R N K N R  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;R N K R N  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;R K N N R  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;R K N R N  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;R K R N N  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def setFromNum(id)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Set the bishops, light first then dark.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.downto(0) do |x|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self[(id % 4)\*2 + x] = "B"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id /= 4  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Set the queen  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setVacantSquare(id % 6, "Q")  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id /= 6

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Set everything else using KeRN codes.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeRN[id].each do |currentPiece|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setVacantSquare(0, currentPiece)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
end

Pawns = ChessRow.new.fill("p").to\_s  
EmptyRows = [ChessRow.new.fill {|i| i % 2 == 0? " " : "#" }.to\_s,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ChessRow.new.fill {|i| i % 2 == 1? " " : "#" }.to\_s]  
Spacer = "+---" \* (Pawns.to\_s.length / 4) + "+"

def parseInput(input)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case input  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when nil  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "Usage:",  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"\tchess960 all - Print all the possible Chess960 lineups",  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"\tchess960 rnd - Print a random Chess960 lineup",  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"\tchess960 ID - Print ID Chess960 lineup"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when /all/  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.upto(959) {|x| parseInput(x) }  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when /(ra?nd)/  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parseInput(rand(960).to\_i)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else # is a number  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input = input.to\_i % 960 # Change 960 into 0.  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mainRow = Chess960Row.new.setFromNum(input).to\_s  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[input.to\_s + ": ",  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mainRow.downcase,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Pawns.downcase,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EmptyRows \* 2,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Pawns.upcase,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mainRow.upcase].  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;flatten.each{|x| puts x, Spacer}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
end  
parseInput(ARGV[0])

Ruby Quiz wrote:

[chess960.rb](https://rubytalk.org/uploads/short-url/qSTKOTygYWXqCy28773vq89ori5.rb) (1.81 KB)

[arrayvalue.rb](https://rubytalk.org/uploads/short-url/wX2j575R7NrdAuD3YwxvIwUV9ZL.rb) (1.58 KB)

> **···**
>
> > The three rules of Ruby Quiz:
> > 
> > 1. Please do not post any solutions or spoiler discussion for this quiz until  
> > 48 hours have passed from the time on this message.
> > 
> > 2. Support Ruby Quiz by submitting ideas as often as you can:
> > 
> > [http://www.rubyquiz.com/](http://www.rubyquiz.com/)
> > 
> > 3. Enjoy!
> > 
> > Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone  
> > on Ruby Talk follow the discussion. Please reply to the original quiz message,  
> > if you can.
> > 
> > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
> > 
> > by Kieran Wild
> > 
> > Chess960, is a chess variant produced by Grandmaster Bobby Fischer by  
> > formalizing the rules of Shuffle Chess. Its goal was to create a chess variant  
> > in which chess creativity and talent would be more important than memorization  
> > and analysis of opening moves. His approach was to create a randomized initial  
> > chess position, which would thus make memorizing chess opening move sequences  
> > far less helpful. The initial position is set up in a special way and there are  
> > 960 such positions, thus the name Chess960.
> > 
> > The starting position for Chess960 must meet certain rules. White pawns are  
> > placed on the second rank as in chess. All remaining white pieces are placed  
> > randomly on the first rank, but with the following restrictions:
> > 
> > &nbsp;&nbsp;\* The king is placed somewhere between the two rooks.  
> > &nbsp;&nbsp;\* The bishops are placed on opposite-colored squares.
> > 
> > The black pieces are placed equal-and-opposite to the white pieces. For example,  
> > if the white king is placed on b1, then the black king is placed on b8. Note  
> > that the king never starts on file a or h, because there would be no room for a  
> > rook
> > 
> > Can I suggest a nice little ruby program to generates all 960 possible starting  
> > positions and outputs a random one on request.
> > 
> > Output could be as follows.
> > 
> > &nbsp;&nbsp;Starting Position 432:  
> > &nbsp;&nbsp;  
> > &nbsp;&nbsp;White  
> > &nbsp;&nbsp;  
> > &nbsp;&nbsp;a1 b1 c1 d1 e1 f1 g1 h1  
> > &nbsp;&nbsp;N B B R K R Q N  
> > &nbsp;&nbsp;  
> > &nbsp;&nbsp;Black  
> > &nbsp;&nbsp;  
> > &nbsp;&nbsp;a8 b8 c8 d8 e8 f8 g8 h8  
> > &nbsp;&nbsp;N B B R K R Q N
> > 
> > Or some better output.

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [15 December 2006 19:34 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/16 "2006-12-15T19:34:45Z")

</div>

Or with a touch more window dressing:

> **···**
>
> On Dec 15, 2006, at 1:25 PM, Daniel Martin wrote:
> 
> > There's also this basic ascii art method: (black is the lowercase  
> > letters)
> > 
> > nbbrkrqn  
> > pppppppp  
> > ........  
> > PPPPPPPP  
> > NBBRKRQN
> 
> +---+---+---+---+---+---+---+---+
> 
> > n | b | b | r | k | r | q | n |
> 
> +---+---+---+---+---+---+---+---+
> 
> > p | p | p | p | p | p | p | p |
> 
> +---+---+---+---+---+---+---+---+
> 
> > &nbsp;&nbsp;\> . | | . | | . | | . |
> 
> +---+---+---+---+---+---+---+---+
> 
> > . | | . | | . | | . | |
> 
> +---+---+---+---+---+---+---+---+
> 
> > &nbsp;&nbsp;\> . | | . | | . | | . |
> 
> +---+---+---+---+---+---+---+---+
> 
> > . | | . | | . | | . | |
> 
> +---+---+---+---+---+---+---+---+
> 
> > P | P | P | P | P | P | P | P |
> 
> +---+---+---+---+---+---+---+---+
> 
> > N | B | B | R | K | R | Q | N |
> 
> +---+---+---+---+---+---+---+---+
> 
> James Edward Gray II

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [16 December 2006 05:07 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/17 "2006-12-16T05:07:45Z")

</div>

Ask Ruby.

James Edward Gray II

> **···**
>
> On Dec 15, 2006, at 9:25 PM, Daniel Finnie wrote:
> 
> > Also, is the range of the numbers 0-956 or 1-960? I've seen things saying that both are acceptable with no definitive answer.

---

<div class="post-metadata">

**Author:** ![Jamie\_Macey](https://avatars.discourse-cdn.com/v4/letter/j/9dc877/32.png) [@Jamie\_Macey](https://rubytalk.org/u/Jamie_Macey)\
**Post date:** [16 December 2006 22:23 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/18 "2006-12-16T22:23:05Z")

</div>

I haven't bothered generating the full table, I'm just randomly  
generating the layouts. I thought the app was a bit too lightweight  
for Rails, but I stole the images from pmwiki.org and set up a camping  
app here: [http://www.tracefunc.com:3301/](http://www.tracefunc.com:3301/) - just refresh for a  
different layout.

If I can find more time this weekend, I'll see about doing the table  
lookup and adding that info to the page.

- Jamie

> **···**
>
> On 12/15/06, Daniel Martin \<martin@snowplow.org\> wrote:
> 
> > Ruby Quiz \<james@grayproductions.net\> writes:
> > 
> > \> Output could be as follows.  
> > \>  
> > \> Starting Position 432:  
> > \>  
> > \> White  
> > \>  
> > \> a1 b1 c1 d1 e1 f1 g1 h1  
> > \> N B B R K R Q N  
> > \>  
> > \> Black  
> > \>  
> > \> a8 b8 c8 d8 e8 f8 g8 h8  
> > \> N B B R K R Q N  
> > \>  
> > \> Or some better output.
> > 
> > Let me suggest that another potential output format is an html page  
> > that when viewed in a browser looks like the opening format. I happen  
> > to think that the chess boards shown on  
> > &nbsp;&nbsp;[PmWiki | Cookbook / ChessMarkup](http://www.pmwiki.org/wiki/Cookbook/ChessMarkup)  
> > look particularly nice, and shouldn't be too hard to duplicate.  
> > (they're done as 8x8 tables, with the colors of the squares done by  
> > CSS and the pieces being .png images with transparency) Presumably  
> > some enterprising person could then churn out a Rails page that showed  
> > a given starting position.

---

<div class="post-metadata">

**Author:** ![Mushfeq\_Khan](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Mushfeq\_Khan](https://rubytalk.org/u/Mushfeq_Khan)\
**Post date:** [17 December 2006 18:28 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/19 "2006-12-17T18:28:45Z")

</div>

This is not a very elegant or concise or even efficient solution. I tried  
finding the weirdest solution I could think of. The idea is to reduce (or in  
this case, enlarge 🙂 the problem to the exact-cover problem. So I  
formalized 6 constraints that need to be satisfied by a solution:

1) all the pieces need to be placed  
2) all the columns need to be occupied  
3) the left rook must appear to the left of the king and the right rook to  
the right  
4) the left bishop must appear to the left of the right one  
5) the left knight must appear to the left of the right knight  
6) each color must be occupied by exactly one bishop

The program constructs rows of a DLX matrix (if you don't know this  
algorithm, it's described here: [http://en.wikipedia.org/wiki/Dancing\_Links](http://en.wikipedia.org/wiki/Dancing_Links)).  
It then uses a DLX solver that I wrote to find legal combinations of piece  
placements. The enumeration order is not the same as the one on the internet  
but is deterministic.

The file 'dlx.rb' contains the DLX solver.

Mushfeq.

[chess960.rb](https://rubytalk.org/uploads/short-url/1r0W5IWmk3GHmbC2EDWlBjcP4w.rb) (3.73 KB)

[dlx.rb](https://rubytalk.org/uploads/short-url/3fAxPebGFagg9rNAXGRPoawBrPh.rb) (3.46 KB)

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [17 December 2006 23:25 UTC](https://rubytalk.org/t/quiz-chess960-106/33761/20 "2006-12-17T23:25:25Z")

</div>

I decided to try it with Amb too. It's slow but works:

#!/usr/bin/env ruby -w

require "amb"

setup = Amb.new  
count = 0  
seen = Hash.new  
begin  
&nbsp;&nbsp;&nbsp;squares = Array.new(8) { setup.choose(\*%w[r n b q k b n r]) }

&nbsp;&nbsp;&nbsp;%w[r n b].each do |piece|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setup.assert(squares.select { |s| s == piece }.size == 2)  
&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;%w[k q].each do |piece|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setup.assert(squares.select { |s| s == piece }.size == 1)  
&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;king = squares.index("k")  
&nbsp;&nbsp;&nbsp;setup.assert(squares.index("r") \< king)  
&nbsp;&nbsp;&nbsp;setup.assert(squares.rindex("r") \> king)  
&nbsp;&nbsp;&nbsp;setup.assert((squares.index("b") + squares.rindex("b")) % 2 == 1)  
&nbsp;&nbsp;&nbsp;board = squares.join(' ')  
&nbsp;&nbsp;&nbsp;setup.assert(seen[board].nil?)

&nbsp;&nbsp;&nbsp;puts "#{count += 1}: #{board}"

&nbsp;&nbsp;&nbsp;seen[board] = true  
&nbsp;&nbsp;&nbsp;setup.failure  
rescue  
&nbsp;&nbsp;&nbsp;# do nothing, we're done  
end

\_\_END\_\_

James Edward Gray II

> **···**
>
> On Dec 17, 2006, at 1:28 PM, Robert Dober wrote:
> 
> > Here goes my second solution, looks a little bit better, using Jim Weirich's Amb class

[Next page](https://rubytalk.org/t/quiz-chess960-106/33761.md?page=2)
