-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpiece.rb
executable file
·137 lines (112 loc) · 2.63 KB
/
piece.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
require_relative 'sliding'
require_relative 'stepping'
require 'byebug'
class Piece
attr_reader :color, :color_option, :board
attr_accessor :pos
CARDINALS = [[-1, 0], [1, 0], [0, -1], [0, 1]]
DIAGONALS = [[-1, -1], [-1, 1], [1, 1], [1, -1]]
def initialize(color, board, pos)
@color = color
@enemy_color = (@color == :white ? :black : :white)
@board = board
@pos = pos
@board[@pos] = self
@color_option = (@color == :white ? :green : :light_blue)
end
def inspect
to_s
end
def move_into_check?(test_pos)
test_board = @board.deep_dup
test_board.move(@pos, test_pos)
test_board.in_check?(color)
end
end
class Knight < Piece
include Stepping
DELTAS = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, -1], [2, 1]]
def to_s
" ♞ "
end
def move_dirs
DELTAS
end
end
class King < Piece
include Stepping
def to_s
" ♚ "
end
def move_dirs
CARDINALS + DIAGONALS
end
end
class Bishop < Piece
include Sliding
def move_dirs
DIAGONALS
end
def to_s
" ♝ "
end
end
class Rook < Piece
include Sliding
def move_dirs
CARDINALS
end
def to_s
" ♜ "
end
end
class Queen < Piece
include Sliding
def move_dirs
CARDINALS + DIAGONALS
end
def to_s
" ♛ "
end
end
class Pawn < Piece
include Stepping
PASSANT = { left: -1, right: 1 }
attr_accessor :passant
def to_s
" ♟ "
end
def passant_set
@passant = pawn_left? || pawn_right?
end
def pawn_left?
left = [@pos[0], @pos[1] - 1]
@board.pieces(@enemy_color).any? { |piece| piece.is_a?(Pawn) && piece.pos == left }
end
def pawn_right?
right = [@pos[0], @pos[1] + 1]
@board.pieces(@enemy_color).any? { |piece| piece.is_a?(Pawn) && piece.pos == right }
end
def passant_adjacent
left = [@pos[0], @pos[1] - 1]
right = [@pos[0], @pos[1] + 1]
return :left if pawn_left? && @board[left].passant
return :right if pawn_right? && @board[right].passant
nil
end
def move_dirs
deltas = []
starting_rank = (color == :white ? 6 : 1)
direction = (color == :white ? -1 : 1)
deltas << [direction * 2, 0] if @pos[0] == starting_rank
one_step_forward = [@pos[0] + direction, @pos[1]]
deltas << [direction, 0] unless @board.pieces.any? { |piece| piece.pos == one_step_forward }
[[direction, -1], [direction, 1]].each do |delta|
d_x, d_y = delta
test_pos = [@pos[0] + d_x, @pos[1] + d_y]
deltas << delta if @board.pieces(@enemy_color).any? { |piece| piece.pos == test_pos }
end
deltas << [direction, PASSANT[passant_adjacent]] unless passant_adjacent.nil?
deltas
end
end