-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathboard.rb
More file actions
executable file
·125 lines (99 loc) · 3.23 KB
/
board.rb
File metadata and controls
executable file
·125 lines (99 loc) · 3.23 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
class Board
attr_reader :black_sq, :board
def initialize(setup = true)
@board = Array.new(8) { Array.new(8) }
@black_sq = "\u25A0"
board_setup if setup
end
def [](pos)
x, y = pos
@board[x][y]
end
def []=(pos, piece)
x, y = pos
@board[x][y] = piece
end
def dup
dup_board = Board.new(false)
dup_board.board.each_with_index do |row, x|
row.each_index do |y|
piece = self[[x, y]]
dup_board[[x, y]] = piece.class.new(dup_board, [x, y], piece.color) unless piece.nil?
end
end
dup_board
end
def checkmate?(color)
in_check?(color) && pieces_array(color).all? { |p| p.valid_moves.empty? }
end
def in_check?(color)
opp_color = (color == :white ? :black : :white)
all_moves = []
pieces_array(opp_color).each { |piece| all_moves += piece.moves }
all_moves.any? { |pos| self[pos].class == King && self[pos].color == color }
end
def move(start_pos, end_pos, color)
piece = self[start_pos]
raise StartPositionEmpty.new 'Your starting position is empty.' if piece.nil?
raise InvalidMove.new "That's not your piece!" unless piece.color == color
raise InvalidMove.new "Piece can't move there." unless piece.moves.include?(end_pos)
raise InvalidMove.new 'That move puts you in check.' if piece.move_into_check?(end_pos)
move!(start_pos, end_pos)
end
def move!(start_pos, end_pos)
self[start_pos], self[end_pos] = nil, self[start_pos]
self[end_pos].pos = end_pos
end
def pieces_array(color)
@board.flatten.compact.select { |piece| piece.color == color }
end
def display(player_color)
system('clear')
row_labels, col_labels, temp_board = format_layout(player_color)
output = format_board(row_labels, col_labels, temp_board)
puts output
end
private
def format_layout(player_color)
white_move = (player_color == :white)
row_nums = (white_move ? [*'1'..'8'].reverse : [*'1'..'8'])
col_letters = (white_move ? [*'a'..'h'] : [*'a'..'h'].reverse)
temp_board = (white_move ? @board.reverse.map(&:reverse) : @board)
[row_nums, col_letters, temp_board]
end
def format_board(row_labels, col_labels, board)
output = ""
board.each_with_index do |row, x|
output += row_labels[x]
row.each_with_index do |item, y|
output += (item.nil? ? ' ' : (item.icon + ' ')).colorize(background: sq_color(x, y))
end
output += "\n"
end
output += ' '.white + col_labels.join(' ')
end
def board_setup
setup_pawns
setup_back_rows
end
def setup_pawns
8.times do |col|
[1, 6].each do |row|
piece_color = (row <= 1 ? :white : :black)
Pawn.new(self, [row, col], piece_color)
end
end
end
def setup_back_rows
[[0, :white], [7, :black]].each do |(x, color)|
pieces = [Rook, Knight, Bishop, King, Queen, Bishop, Knight, Rook]
pieces.each_with_index do |klass, y|
pos = x, y
klass.new(self, pos, color)
end
end
end
def sq_color(idx1, idx2)
(idx1.even? && idx2.even?) || (idx1.odd? && idx2.odd?) ? :light_green : :green
end
end