-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboard.rb
153 lines (127 loc) · 3.5 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
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
# frozen_string_literal: true
require_relative 'pieces'
class Board
attr_reader :rows
def initialize
@rows = Array.new(8) { Array.new (8) { NullPiece.instance } }
@rows.each_with_index do |row, row_idx|
if [1, 6].include?(row_idx)
row.map!.with_index do |_square, col_idx|
add_piece(:pawn, [row_idx, col_idx])
end
elsif [0, 7].include?(row_idx)
row.map!.with_index do |square, col_idx|
square = [row_idx, col_idx]
if [0, 7].include?(col_idx)
add_piece(:rook, square)
elsif [1, 6].include?(col_idx)
add_piece(:knight, square)
elsif [2, 5].include?(col_idx)
add_piece(:bishop, square)
elsif col_idx == 3
add_piece(:queen, square)
elsif col_idx == 4
add_piece(:king, square)
end
end
end
end
end
def [](pos)
return nil unless valid_pos?(pos)
row, col = pos
rows[row][col]
end
def []=(pos, val)
return nil unless valid_pos?(pos)
row, col = pos
rows[row][col] = val
end
def valid_pos?(pos)
pos.all? { |coord| coord.between?(0, 7) }
end
def add_piece(color = nil, piece, pos)
if color.nil?
color = :white if [0, 1].include?(pos[0])
color = :black if [6, 7].include?(pos[0])
end
if piece == :rook
Rook.new(color, pos, self)
elsif piece == :pawn
Pawn.new(color, pos, self)
elsif piece == :knight
Knight.new(color, pos, self)
elsif piece == :queen
Queen.new(color, pos, self)
elsif piece == :bishop
Bishop.new(color, pos, self)
elsif piece == :king
King.new(color, pos, self)
end
end
def move_piece(turn_color, start_pos, end_pos)
piece = self[start_pos]
raise 'Start position is empty.' if piece.class == NullPiece
if piece.color != turn_color
raise 'You must move your own piece.'
elsif !piece.moves.include?(end_pos)
raise 'Piece does not move like that.'
elsif !piece.valid_moves.include?(end_pos)
raise 'You cannot move into / remain in check.'
end
move_piece!(start_pos, end_pos)
end
def move_piece!(start_pos, end_pos)
self[end_pos] = self[start_pos]
self[end_pos].pos = end_pos
self[start_pos] = NullPiece.instance
end
def in_check?(color)
king_pos = find_king(color)
pieces.each do |piece|
next unless piece.class != NullPiece && piece.color != color
return true if piece.moves.any? { |move| move == king_pos }
end
false
end
def find_king(color)
pieces(color).each do |piece|
return piece.pos if piece.class == King
end
nil
end
def checkmate?(color)
return false unless in_check?(color)
pieces.none? do |piece|
next if piece.class == NullPiece || piece.color != color
piece.valid_moves.any?
end
end
def dup
duped_board = Board.new
(0..7).each do |i|
(0..7).each do |j|
if self[[i, j]].class == NullPiece
duped_board[[i, j]] = NullPiece.instance
else
piece = self[[i, j]]
duped_board[[i, j]] = duped_board.add_piece(piece.color, piece.class.to_s.downcase.to_sym, [i, j])
end
end
end
duped_board
end
def pieces(color = nil)
all_pieces = []
(0..7).each do |i|
(0..7).each do |j|
if color.nil?
all_pieces << self[[i, j]]
else
all_pieces << self[[i, j]] if self[[i, j]].color == color
end
end
end
all_pieces
end
end