Class: Board

Inherits:
Object
  • Object
show all
Defined in:
lib/bangkok/board.rb

Instance Method Summary collapse

Constructor Details

#initialize(listener) ⇒ Board

Returns a new instance of Board.



6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/bangkok/board.rb', line 6

def initialize(listener)
  @listener = listener
  @pieces = []
  [:R, :N, :B, :Q, :K, :B, :N, :R].each_with_index { | sym, file |
    @pieces << Piece.create(self, listener, :white, sym, Square.at(file, 0))
    @pieces << Piece.create(self, listener, :black, sym, Square.at(file, 7))
  }
  8.times { | file |
    @pieces << Piece.create(self, listener, :white, :P, Square.at(file, 1))
    @pieces << Piece.create(self, listener, :black, :P, Square.at(file, 6))
  }
end

Instance Method Details

#apply(move) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/bangkok/board.rb', line 19

def apply(move)
  if move.castle?
    apply_castle(move)
  else
    piece = find_piece(move)
    other_piece = at(move.square) unless move.castle?
    piece.move_to(move.square)
    if other_piece              # capture
      unless move.capture?
        raise "error: piece found at target (#{other_piece}) but move" +
          " #{move} is not a capture"
      end
      @listener.capture(piece, other_piece)
      remove_from_board(other_piece)
    end

    if move.pawn_promotion?
      raise "error: trying to promote a non-pawn" unless piece.piece == :P

      @listener.pawn_to_queen(piece)
      color = piece.color
      remove_from_board(piece) # will also trigger the listener
      @pieces << Piece.create(self, color, :Q, move.square)
    end
  end
end

#apply_castle(move) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/bangkok/board.rb', line 46

def apply_castle(move)
  new_king_file = nil
  new_rook_file = nil
  king = @pieces.detect { | p | p.piece == :K && p.color == move.color }
  rook = nil

  if move.queenside_castle?
    new_king_file = king.square.square.file - 2
    rook = @pieces.detect { | p |
      p.piece == :R && p.color == move.color && p.square.file == 0
    }
    new_rook_file = rook.square.file + 3
  else # kingside castle
    new_king_file = king.square.file + 2
    rook = @pieces.detect { | p |
      p.piece == :R && p.color == move.color && p.square.file == 7
    }
    new_rook_file = rook.square.file - 2
  end

  king.move_to(Square.at(new_king_file, king.square.rank))
  rook.move_to(Square.at(new_rook_file, rook.square.rank))
end

#at(square) ⇒ Object



79
80
81
# File 'lib/bangkok/board.rb', line 79

def at(square)
  return @pieces.detect { | p | p.square == square }
end

#empty_at?(square) ⇒ Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/bangkok/board.rb', line 75

def empty_at?(square)
  return at(square).nil?
end

#find_piece(move) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/bangkok/board.rb', line 83

def find_piece(move)
  candidates = @pieces.find_all { | p | p.could_perform_move(move) }
  case candidates.length
  when 0
    raise "error: no pieces found for move #{move}"
  when 1
    return candidates[0]
  else                        # Disambiguate using move's orig. rank or file
    if move.from_rank_or_file.rank.nil? # file is non-nil
      candidates = candidates.find_all { | p |
        p.square.file == move.from_rank_or_file.file
      }
    else
      candidates = candidates.find_all { | p |
        p.square.rank == move.from_rank_or_file.rank
      }
    end
    case candidates.length
    when 0
      raise "error: disambiguation found no pieces for #{move}"
    when 1
      return candidates[0]
    else
      raise "error: too many pieces match #{move}"
    end
  end
end

#remove_from_board(piece) ⇒ Object



70
71
72
73
# File 'lib/bangkok/board.rb', line 70

def remove_from_board(piece)
  @pieces.delete(piece)
  piece.move_off_board()
end