-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathboard.rb
More file actions
158 lines (135 loc) · 3.65 KB
/
board.rb
File metadata and controls
158 lines (135 loc) · 3.65 KB
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
require_relative 'pieces/pieces'
class Board
attr_accessor :grid
def initialize
@null = Nullpiece.instance
@grid = Array.new(8) {Array.new(8, @null)}
populate_board
end
def [](pos)
x, y = pos
self.grid[x][y]
end
def []=(pos, val)
x, y = pos
self.grid[x][y] = val
end
def empty?(pos)
self[pos].empty?
end
def move_piece(start_pos, end_pos)
raise "no piece at starting position" if self[start_pos].empty?
raise "can't move into check" if self[start_pos].move_into_check?(end_pos)
raise "invalid move" unless self[start_pos].valid_moves.include?(end_pos)
raise "invalid end position" unless valid_pos?(end_pos) || self[start_pos].color != self[end_pos].color
self[start_pos], self[end_pos] = self[end_pos], self[start_pos]
self[end_pos].pos, self[start_pos].pos = end_pos, start_pos
capture_piece(start_pos)
end
def capture_piece(pos)
self[pos] = @null
end
def valid_pos?(pos)
return true if pos[0].between?(0, 7) && pos[1].between?(0, 7) && self[pos].empty?
end
def add_piece(piece, pos)
self[pos] = piece
end
def checkmate?(color)
own_pieces = pieces.select {|piece| piece.color == color}
own_pieces.all?{|piece| piece.valid_moves.empty?} && in_check?(color)
end
def in_check?(color)
king_pos = find_king(color)
opposing_pieces = pieces.select do |piece|
color == :white ? piece.color == :black : piece.color == :white
end
opposing_pieces.any?{|piece| piece.moves.include?(king_pos)}
end
def find_king(color)
self.grid.each_with_index do |row, i|
row.each_with_index do |piece, j|
return [i, j] if piece.class == King && piece.color == color
end
end
end
def pieces
all_pieces = []
self.grid.each_with_index do |row, i|
row.each_with_index do |piece, j|
all_pieces << piece unless empty?([i,j])
end
end
all_pieces
end
def dup
duped_board = Board.new
duped_board.grid = Array.new(8) {Array.new(8, @null)}
self.grid.each_with_index do |row, i|
row.each_with_index do |piece, j|
unless piece.empty?
duped_board.add_piece(piece.class.new(piece.color, duped_board, [i, j]), [i, j])
end
end
end
duped_board
end
def move_piece!(start_pos, end_pos)
self[start_pos], self[end_pos] = self[end_pos], self[start_pos]
self[end_pos].pos, self[start_pos].pos = end_pos, start_pos
capture_piece(start_pos)
end
private
def populate_rooks
[0, 7].each do |i|
color = i == 0 ? :black : :white
[0, 7].each do |j|
add_piece(Rook.new(color, self, [i, j]), [i, j])
end
end
end
def populate_bishops
[0, 7].each do |i|
color = i == 0 ? :black : :white
[2, 5].each do |j|
add_piece(Bishop.new(color, self, [i, j]), [i, j])
end
end
end
def populate_queens
[0, 7].each do |i|
color = i == 0 ? :black : :white
add_piece(Queen.new(color, self, [i, 3]), [i, 3])
end
end
def populate_knights
[0, 7].each do |i|
color = i == 0 ? :black : :white
[1, 6].each do |j|
add_piece(Knight.new(color, self, [i, j]), [i, j])
end
end
end
def populate_kings
[0, 7].each do |i|
color = i == 0 ? :black : :white
add_piece(King.new(color, self, [i, 4]), [i, 4])
end
end
def populate_pawns
[1, 6].each do |i|
color = i == 1 ? :black : :white
(0..7).each do |j|
add_piece(Pawn.new(color, self, [i, j]), [i, j])
end
end
end
def populate_board
populate_rooks
populate_bishops
populate_queens
populate_knights
populate_kings
populate_pawns
end
end