William James wrote:
> 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:
> >
> > 	* 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.
>
> which = ( ARGV.first || rand(960) + 1 ).to_i
> count = 0
>
> (1..6).each{|k|
>   (0...k).each{|r1|
>     (k+1..7).each{|r2|
>       ((0..7).to_a - [k,r1,r2]).each{|q|
>         used = [k,r1,r2,q]
>         ((0..7).select{|i| i % 2 == 0} - used).each{|b1|
>           ((0..7).select{|i| i % 2 == 1} - used).each{|b2|
>             count += 1
>             if which == count
>               puts "Position #{ count }"
>               s = 'N' * 8
>               [k,q,r1,r2,b1,b2].zip(%w(K Q R R B B)).each{|i,p|
>                 s[i] = p }
>               puts s.downcase,'p'*8,('.'*8+"\n")*4,'P'*8,s
>             end   } } } } } }

# Using  Scharnagl's numbering.

if "all" == ARGV.first
  range = (1..960)
else
  n = ARGV.first
  n = n && Integer( n ) || rand(960) + 1
  range = (n..n)
end

def empty( ary )
  ary.select{|x| x.class==Fixnum}
end

range.each{|which|
  num = which % 960
  row = Array.new(8){|i| i}
  num, bishop = num.divmod( 4 )
  row[ bishop*2 + 1 ] = "B"
  num, bishop = num.divmod( 4 )
  row[ bishop*2 ] = "B"
  num, queen = num.divmod( 6 )
  row[ empty( row )[queen] ] = "Q"
  avail = empty( row )
  while num / (avail.size - 1 ) > 0
    avail.shift
    num -= avail.size
  end
  row[ avail.first ] = "N"
  avail.shift
  row[ avail[ num % avail.size ] ] = "N"
  empty( row ).zip( %w(R K R) ).each{|i,piece| row[i] = piece}
  puts "\nPosition #{ which }"
  s = row.join
  puts s.downcase,'p'*8,('.'*8+"\n")*4,'P'*8,s
}