J
James Edward Gray II
I don't want to spoil all the fun, in case anyone is still attempting
this quiz, but here's my solution to four of the seven variations:
#!/usr/local/bin/ruby -w
# blackhole_chess
#
# Created by James Edward Gray II on 2005-06-20.
# Copyright 2005 Gray Productions. All rights reserved.
require "chess"
# An enhanced chess board for playing Blackhole Chess.
class BlackholeChess < Chess::Board
#
# A general purpose test to see if a _test_ square is between
_start_ and
# _finish_ squares, on a rank, file or diagonal.
#
def self.between?( start, finish, test )
test_rank, test_file = test[1, 1].to_i, test[0]
start_rank, start_file = start[1, 1].to_i, start[0]
finish_rank, finish_file = finish[1, 1].to_i, finish[0]
( test_rank == start_rank and test_rank == finish_rank and
test_file >= [start_file, finish_file].min and
test_file <= [start_file, finish_file].max ) or
( test_file == start_file and test_file == finish_file and
test_rank >= [start_rank, finish_rank].min and
test_rank <= [start_rank, finish_rank].max ) or
( (start_file - finish_file).abs == (start_rank -
finish_rank).abs and
(start_file - test_file).abs == (start_rank -
test_rank).abs and
(test_file - finish_file).abs == (test_rank -
finish_rank).abs and
test_file >= [start_file, finish_file].min and
test_file <= [start_file, finish_file].max and
test_rank >= [start_rank, finish_rank].min and
test_rank <= [start_rank, finish_rank].max )
end
# End the game if a King goes missing.
def in_checkmate?( who = @turn )
if find { |(s, pc)| pc and pc.color == who and pc.is_a?
Chess::King }
super
else
true
end
end
# Eliminate any piece moving through the blackholes.
def move( from_square, to_square, promote_to = nil )
if self.class.between?(from_square, to_square, "d5") or
self.class.between?(from_square, to_square, "f5")
@squares[from_square] = nil
next_turn
else
super
end
self
end
# Board display with two added blackholes.
def to_s( )
super.sub( /^(5\s+\|(?:[^|]+\|){3})[^|]+\|([^|]+\|)[^|]+\|/,
"\\1 * |\\2 * |" )
end
end
board = BlackholeChess.new
# insert my chess inteface code (see Summary) here, with a minor
addition to spot
# a king that falls into a blackhole
__END__
#!/usr/local/bin/ruby -w
# fairy_chess
#
# Created by James Edward Gray II on 2005-06-20.
# Copyright 2005 Gray Productions. All rights reserved.
require "chess"
#
# The container for the behavior of a chess fairy. Fairies are
simply treated
# as both a Queen and a Knight.
#
class Fairy < Chess::Queen
#
# Returns all the capturing moves for a Fairy on the provided
_board_
# at the provided _square_ of the provided _color_.
#
def self.captures( board, square, color )
captures = Chess::Queen.captures(board, square, color)
captures += Chess::Knight.captures(board, square, color)
captures.sort
end
#
# Returns all the non-capturing moves for a Fairy on the provided
# _board_ at the provided _square_ of the provided _color_.
#
def self.moves( board, square, color )
moves = Chess::Queen.moves(board, square, color)
moves += Chess::Knight.moves(board, square, color)
moves.sort
end
end
# Make the Chess::King aware of the Fairy.
class FairyAwareKing < Chess::King
# Enhance in_check? to spot special Fairy moves.
def self.in_check?( bd, sq, col )
return true if Chess::Knight.captures(bd, sq, col).any? do |
name|
bd[name].is_a?(Fairy)
end
Chess::King.in_check?( bd, sq, col )
end
# Make this piece show up as a normal King.
def to_s( )
if @color == :white then "K" else "k" end
end
end
# An enhanced chess board for playing Fairy Chess.
class FairyChess < Chess::Board
# Setup a normal board, then replace the queens with fairies.
def setup( )
super
@squares["d1"] = Fairy.new(self, "d1", :white)
@squares["d8"] = Fairy.new(self, "d8", :black)
@squares["e1"] = FairyAwareKing.new(self, "e1", :white)
@squares["e8"] = FairyAwareKing.new(self, "e8", :black)
end
end
board = FairyChess.new
# insert my chess inteface code (see Summary) here
__END__
#!/usr/local/bin/ruby -w
# fibonacci_chess
#
# Created by James Edward Gray II on 2005-06-20.
# Copyright 2005 Gray Productions. All rights reserved.
require "chess"
# An enhanced chess board for playing Fibonacci Chess.
class FibonacciBoard < Chess::Board
# Setup chess board and initialize move count sequence.
def initialize( )
super
@fib1 = nil
@fib2 = nil
@Count = 1
end
# Advance turn, as players complete moves in the Fibonacci
sequence.
def next_turn( )
if @fib1.nil?
@fib1 = 1
elsif @fib2.nil?
@fib2 = 2
next_turn if in_check?(@turn == :white ? :black : :white)
elsif @count.zero? or in_check?(@turn
== :white ? :black : :white)
@fib1, @fib2 = @fib2, @fib1 + @fib2
@Count = @fib2 - 1
else
@Count -= 1
return
end
super
end
# Return a String description of the moves remaining.
def moves_remaining( )
if @fib1.nil? or @fib2.nil? or @count.zero?
"last move"
else
"#{@count + 1} moves"
end
end
end
board = FibonacciBoard.new
# insert my chess inteface code (see Summary) here
__END__
#!/usr/local/bin/ruby -w
# gun_chess
#
# Created by James Edward Gray II on 2005-06-20.
# Copyright 2005 Gray Productions. All rights reserved.
require "chess"
# An enhanced chess board for playing Gun Chess.
class GunChess < Chess::Board
# Returns a numerical count of all the pieces on the board.
def count_pieces( )
find_all { |(square, piece)| piece }.size
end
# Make standard chess moves, save that capturing pieces do not
move.
def move( from_square, to_square, promote_to = nil )
old_count = count_pieces
super # normal chess move
if count_pieces < old_count # if it was a capture...
move(to_square, from_square) # move the piece back
next_turn # fix the extra turn change
end
self
end
end
board = GunChess.new
# insert my chess inteface code (see Summary) here, with a minor
addition to
# promote pawns on moves only, never captures
__END__
You can download the complete files here:
http://rubyquiz.com/ruby_quiz_chess.zip
I was surprised that this wasn't harder. I didn't tailor my library
to the variations and I chose random variations to solve. I expected
the library would need enhancements for some, but that didn't seem to
be the case, at least for these four variations.
James Edward Gray II
this quiz, but here's my solution to four of the seven variations:
#!/usr/local/bin/ruby -w
# blackhole_chess
#
# Created by James Edward Gray II on 2005-06-20.
# Copyright 2005 Gray Productions. All rights reserved.
require "chess"
# An enhanced chess board for playing Blackhole Chess.
class BlackholeChess < Chess::Board
#
# A general purpose test to see if a _test_ square is between
_start_ and
# _finish_ squares, on a rank, file or diagonal.
#
def self.between?( start, finish, test )
test_rank, test_file = test[1, 1].to_i, test[0]
start_rank, start_file = start[1, 1].to_i, start[0]
finish_rank, finish_file = finish[1, 1].to_i, finish[0]
( test_rank == start_rank and test_rank == finish_rank and
test_file >= [start_file, finish_file].min and
test_file <= [start_file, finish_file].max ) or
( test_file == start_file and test_file == finish_file and
test_rank >= [start_rank, finish_rank].min and
test_rank <= [start_rank, finish_rank].max ) or
( (start_file - finish_file).abs == (start_rank -
finish_rank).abs and
(start_file - test_file).abs == (start_rank -
test_rank).abs and
(test_file - finish_file).abs == (test_rank -
finish_rank).abs and
test_file >= [start_file, finish_file].min and
test_file <= [start_file, finish_file].max and
test_rank >= [start_rank, finish_rank].min and
test_rank <= [start_rank, finish_rank].max )
end
# End the game if a King goes missing.
def in_checkmate?( who = @turn )
if find { |(s, pc)| pc and pc.color == who and pc.is_a?
Chess::King }
super
else
true
end
end
# Eliminate any piece moving through the blackholes.
def move( from_square, to_square, promote_to = nil )
if self.class.between?(from_square, to_square, "d5") or
self.class.between?(from_square, to_square, "f5")
@squares[from_square] = nil
next_turn
else
super
end
self
end
# Board display with two added blackholes.
def to_s( )
super.sub( /^(5\s+\|(?:[^|]+\|){3})[^|]+\|([^|]+\|)[^|]+\|/,
"\\1 * |\\2 * |" )
end
end
board = BlackholeChess.new
# insert my chess inteface code (see Summary) here, with a minor
addition to spot
# a king that falls into a blackhole
__END__
#!/usr/local/bin/ruby -w
# fairy_chess
#
# Created by James Edward Gray II on 2005-06-20.
# Copyright 2005 Gray Productions. All rights reserved.
require "chess"
#
# The container for the behavior of a chess fairy. Fairies are
simply treated
# as both a Queen and a Knight.
#
class Fairy < Chess::Queen
#
# Returns all the capturing moves for a Fairy on the provided
_board_
# at the provided _square_ of the provided _color_.
#
def self.captures( board, square, color )
captures = Chess::Queen.captures(board, square, color)
captures += Chess::Knight.captures(board, square, color)
captures.sort
end
#
# Returns all the non-capturing moves for a Fairy on the provided
# _board_ at the provided _square_ of the provided _color_.
#
def self.moves( board, square, color )
moves = Chess::Queen.moves(board, square, color)
moves += Chess::Knight.moves(board, square, color)
moves.sort
end
end
# Make the Chess::King aware of the Fairy.
class FairyAwareKing < Chess::King
# Enhance in_check? to spot special Fairy moves.
def self.in_check?( bd, sq, col )
return true if Chess::Knight.captures(bd, sq, col).any? do |
name|
bd[name].is_a?(Fairy)
end
Chess::King.in_check?( bd, sq, col )
end
# Make this piece show up as a normal King.
def to_s( )
if @color == :white then "K" else "k" end
end
end
# An enhanced chess board for playing Fairy Chess.
class FairyChess < Chess::Board
# Setup a normal board, then replace the queens with fairies.
def setup( )
super
@squares["d1"] = Fairy.new(self, "d1", :white)
@squares["d8"] = Fairy.new(self, "d8", :black)
@squares["e1"] = FairyAwareKing.new(self, "e1", :white)
@squares["e8"] = FairyAwareKing.new(self, "e8", :black)
end
end
board = FairyChess.new
# insert my chess inteface code (see Summary) here
__END__
#!/usr/local/bin/ruby -w
# fibonacci_chess
#
# Created by James Edward Gray II on 2005-06-20.
# Copyright 2005 Gray Productions. All rights reserved.
require "chess"
# An enhanced chess board for playing Fibonacci Chess.
class FibonacciBoard < Chess::Board
# Setup chess board and initialize move count sequence.
def initialize( )
super
@fib1 = nil
@fib2 = nil
@Count = 1
end
# Advance turn, as players complete moves in the Fibonacci
sequence.
def next_turn( )
if @fib1.nil?
@fib1 = 1
elsif @fib2.nil?
@fib2 = 2
next_turn if in_check?(@turn == :white ? :black : :white)
elsif @count.zero? or in_check?(@turn
== :white ? :black : :white)
@fib1, @fib2 = @fib2, @fib1 + @fib2
@Count = @fib2 - 1
else
@Count -= 1
return
end
super
end
# Return a String description of the moves remaining.
def moves_remaining( )
if @fib1.nil? or @fib2.nil? or @count.zero?
"last move"
else
"#{@count + 1} moves"
end
end
end
board = FibonacciBoard.new
# insert my chess inteface code (see Summary) here
__END__
#!/usr/local/bin/ruby -w
# gun_chess
#
# Created by James Edward Gray II on 2005-06-20.
# Copyright 2005 Gray Productions. All rights reserved.
require "chess"
# An enhanced chess board for playing Gun Chess.
class GunChess < Chess::Board
# Returns a numerical count of all the pieces on the board.
def count_pieces( )
find_all { |(square, piece)| piece }.size
end
# Make standard chess moves, save that capturing pieces do not
move.
def move( from_square, to_square, promote_to = nil )
old_count = count_pieces
super # normal chess move
if count_pieces < old_count # if it was a capture...
move(to_square, from_square) # move the piece back
next_turn # fix the extra turn change
end
self
end
end
board = GunChess.new
# insert my chess inteface code (see Summary) here, with a minor
addition to
# promote pawns on moves only, never captures
__END__
You can download the complete files here:
http://rubyquiz.com/ruby_quiz_chess.zip
I was surprised that this wasn't harder. I didn't tailor my library
to the variations and I chose random variations to solve. I expected
the library would need enhancements for some, but that didn't seem to
be the case, at least for these four variations.
James Edward Gray II