On Oct 27, 2007, at 12:20 PM, Helder Ribeiro wrote:

> Does anyone know if there's a sort of library for the game Checkers in
> Ruby? Something that would, at least:
>
> 1. given a board state and a player, tell me what the legal moves are;
> 2. given a board state and a move, tell me if it's legal;
> 3. given a board state, tell me if it's a draw or a win (and who won).
>
> Also, if there isn't a library (very likely), a complete game that's
> open source, from which I could extract that, would be good enough.

I decided to see what I could put together for you request quickly.   
Unfortunately, I'm now out of time as I'm about to walk out the door  
for a concert.

This doesn't yet handle jumps and it doesn't determine win, lose, or  
draw conditions.  Hopefully it's enough to get you started though:

#!/usr/bin/env ruby -wKU

require "enumerator"

module Checkers
   class Piece
     def initialize(color, king = false)
       @color = color
       @king  = king
     end

     attr_reader :color

     def king_me!
       @king = true
     end

     def king?
       @king
     end

     def to_s
       str = @color.to_s[0, 1]
       @king ? str.upcase : str
     end
   end

   class Board
     MOVES = {
        1 => [ 5,  6],          2 => [ 6,  7],          3 => [ 7,  8],
        4 => [ 8],              5 => [ 1,  9],          6 => [ 1,   
2,  9, 10],
        7 => [ 2,  3, 10, 11],  8 => [ 3,  4, 11, 12],  9 => [ 5,  6,  
13, 14],
       10 => [ 6,  7, 14, 15], 11 => [ 7,  8, 15, 16], 12 => [ 8, 16],
       13 => [ 9, 17],         14 => [ 9, 10, 17, 18], 15 => [10, 11,  
18, 19],
       16 => [11, 12, 19, 20], 17 => [13, 14, 21, 22], 18 => [14, 15,  
22, 23],
       19 => [15, 16, 23, 24], 20 => [16, 24],         21 => [17, 25],
       22 => [17, 18, 25, 26], 23 => [18, 19, 26, 27], 24 => [19, 20,  
27, 28],
       25 => [21, 22, 29, 30], 26 => [22, 23, 30, 31], 27 => [23, 24,  
31, 32],
       28 => [24, 32],         29 => [25],             30 => [25, 26],
       31 => [26, 27],         32 => [27, 28]
     }

     def initialize
       @squares = Array.new(12) { Piece.new(:black) } +
                  Array.new(8)                        +
                  Array.new(12) { Piece.new(:red) }
       @turn    = :black
     end

     def [](square_number)
       @squares[square_number - 1]
     end

     def moves(color = @turn)
       @squares.enum_with_index.inject([]) do |moves, (piece, i)|
         next moves unless piece and piece.color == color
         possible = MOVES[i + 1]
         unless piece.king?
           illegal = piece.color == :black ? :< : :>
           possible.reject! { |n| n.send(illegal, i + 1) }
         end
          
moves                                                              +
         possible.select { |to| self[to].nil? }.map { |m| "#{i + 1}-# 
{m}" }
       end
     end

     def legal?(move, color = @turn)
       moves(color).include? move
     end

     def to_s
       leading_black = false
       border        = "+---+---" * 4 + "+\n"
       @squares.enum_with_index.enum_slice(4).inject("") do |str, row|
         leading_black = !leading_black
         pattern       = (leading_black ? "|###|%-3s" : "|%-3s|###")  
* 4 + "|\n"
         str                                                           +
         border                                                        +
         pattern             % [*row.map { |square| square.first }]    +
         pattern.delete("-") % [*row.map { |square| square.last + 1 }]
       end + border
     end
   end
end

__END__

James Edward Gray II