-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboard.rb
118 lines (96 loc) · 3.1 KB
/
board.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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
110
111
112
113
114
115
116
117
118
require 'singleton'
require 'byebug'
require_relative "Pieces/piece.rb"
require_relative "Pieces/pawn.rb"
require_relative "Pieces/bishop.rb"
require_relative "Pieces/queen.rb"
require_relative "Pieces/rook.rb"
require_relative "Pieces/king.rb"
require_relative "Pieces/knight.rb"
require_relative "Pieces/nullpiece.rb"
class Board
attr_reader :rows
LAYOUT = [Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook ]
def initialize(empty_board = false)
@rows = Array.new(8) { Array.new(8, Nullpiece.instance) }
set_pieces unless empty_board
end
def move_piece(color, start_pos, end_pos)
target_piece = self[start_pos]
raise ArgumentError.new("There is no piece at this start position.") if target_piece.empty?
raise ArgumentError.new("You may only move #{color == :white ? "white" : "black"} pieces on your turn.") if target_piece.color != color
raise ArgumentError.new("The #{target_piece.symbol} cannot move to square #{end_pos.first} #{end_pos.last}") unless target_piece.valid_moves.include?(end_pos)
move_piece!(start_pos, end_pos)
end
def add_piece(piece, pos)
raise "Square already occupied" unless empty?(pos)
self[pos] = piece
end
def [](pos)
row, col = pos
@rows[row][col]
end
def []=(pos, value)
row, col = pos
@rows[row][col] = value
end
def valid_pos?(pos)
pos.min >= 0 && pos.max < 8
end
def empty?(pos)
self[pos].empty?
end
def find_king(color)
king = pieces.find { | piece| piece.is_a?(King) && piece.color == color }
king.pos
end
def pieces
@rows.flatten.reject(&:empty?)
end
def dup
duped_board = Board.new(true)
rows.each do |row|
row.each do |original_piece|
next if original_piece.empty?
dup_class = original_piece.class
dup_class.new(original_piece.color, original_piece.pos, duped_board)
end
end
duped_board
end
def in_check?(color)
king_pos = find_king(color)
pieces.reject { |piece| piece.color == color }.any? do |opponent_piece|
opponent_piece.moves.include?(king_pos)
end
end
def checkmate?(color)
in_check?(color) && pieces.select{ |p| p.color == color }.all? do |player_piece|
player_piece.valid_moves.empty?
end
end
def move_piece!(start_pos, end_pos)
target_piece = self[start_pos]
raise ArgumentError.new("This is not a valid move for this piece.") unless target_piece.moves.include?(end_pos)
self[start_pos] = Nullpiece.instance
self[end_pos] = target_piece
target_piece.pos = end_pos
end
private
def fill_back_row(row)
color = row == 0 ? :black : :white
LAYOUT.each_with_index { |piece, col| piece.new(color, [row, col], self) }
end
def fill_pawn_row(row)
color = row == 1 ? :black : :white
8.times { |col| Pawn.new(color, [row, col], self)}
end
def set_pieces
[0,7].each do |row|
fill_back_row(row)
end
[1,6].each do |row|
fill_pawn_row(row)
end
end
end