Source

puzzle_nodes / 13 / lib / board.rb

# Chess Validator - Board
# =======================
#
# Part of my solution to PuzzleNode #13.
# Replication of a chess board.

#<pre>
#    a  b  c  d  e  f  g  h
# 8 bR bN bB bQ bK bB bN bR 8
# 7 bP bP bP bP bP bP bP bP 7
# 6 -- -- -- -- -- -- -- -- 6
# 5 -- -- -- -- -- -- -- -- 5
# 4 -- -- -- -- -- -- -- -- 4
# 3 -- -- -- -- -- -- -- -- 3
# 2 wP wP wP wP wP wP wP wP 2
# 1 wR wN wB wQ wK wB wN wR 1
#    a  b  c  d  e  f  g  h
#</pre>

# We will represent the board as a single array of length 64 beginning with 0
# at a8 and continuing with 63 at h1. Each row and column can then be found by
# taking the index divided by 8 and the index modulo 8. For example 8 - (40 /
# 8) = 3 so 40 is in row 3. The column of 40 is found by taking 40 mod 8 = 0 so
# 40 is in column a.

#<pre>
#      a  b  c  d  e  f  g  h
# 8 | 00 01 02 03 04 05 06 07 | 8
# 7 | 08 09 10 11 12 13 14 15 | 7
# 6 | 16 17 18 19 20 21 22 23 | 6
# 5 | 24 25 26 27 28 29 30 31 | 5
# 4 | 32 33 34 35 36 37 38 39 | 4
# 3 | 40 41 42 43 44 45 46 47 | 3
# 2 | 48 49 50 51 52 53 54 55 | 2
# 1 | 56 57 58 59 60 61 62 63 | 1
#      a  b  c  d  e  f  g  h
#</pre>
class Board
  BOARD_LETTERS ={ 'a' => 0, 'b' => 1, 'c' => 2, 'd' => 3, 'e' => 4, 'f' => 5,
                   'g' => 6, 'h' => 7 }

  def initialize input_string
    @board_matrix = input_string.split
  end

  def [] index
    @board_matrix[index]
  end

  def algebraic? symbol
   symbol.length == 2 and
     %w[a b c d e f g h].include? symbol[0] and
     (1..8).include? symbol[1].to_i
  end

  # a move is valid when:
  # 1. [x] There is a piece at the first square
  # 2. [ ] The last square is a valid destination for the piece.
  # 3. [ ] There is a clear path to the destination.
  # 4. [ ] The destination is empty or has a capturable piece.
  def valid_move? move
    return false if empty? move.first
    true
  end

  def empty? place
    send(place) == '--'
  end

  def index_from_algebraic symbol
    (8 - symbol[1].to_i) * 8 + BOARD_LETTERS[symbol[0]]
  end

  def method_missing symbol, *args, &block
    if algebraic? symbol
      @board_matrix[index_from_algebraic symbol]
    else
      super symbol, *args, &block
    end
  end
end