-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpiece.rb
More file actions
executable file
·157 lines (124 loc) · 3.15 KB
/
piece.rb
File metadata and controls
executable file
·157 lines (124 loc) · 3.15 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
require_relative 'board'
require_relative 'chess_errors'
class Piece
include ChessErrors
attr_reader :board, :color, :pos
attr_accessor :first_move
def initialize(board = Board.new, color = :white, pos = [0, 0])
@color = color
@pos = pos
@board = board
@board[pos] = self
@first_move = true
end
def moves
end
def update_pos(new_pos)
self.pos = new_pos
end
def on_board?(pos)
pos[0].between?(0,7) && pos[1].between?(0,7)
end
def move_into_check?(pos)
test_board = self.board.dup
test_board[self.pos] = nil
test_board[pos] = self.class.new(test_board, self.color, pos )
test_board.in_check?(self.color)
end
def valid_moves
moves.select do |move|
legal?(move)
end.reject do |move|
move_into_check?(move)
end
end
def legal?(new_pos)
test_board = self.board.dup
begin
test_board.raise_move_errors(self.pos, new_pos, self.color)
rescue ArgumentError
return false
end
true
end
protected
attr_writer :pos
end
class SlidingPiece < Piece
def moves
some_moves = []
self.class.move_dirs.each do |delta|
y, x = delta[0] + self.pos[0], delta[1] + self.pos[1]
next unless on_board?([y, x])
some_moves << [y,x]
blocked = false
until blocked == true
blocked = true
break unless self.board[some_moves.last].nil?
y, x = delta[0] + some_moves.last[0], delta[1] + some_moves.last[1]
break unless on_board?([y, x])
some_moves << [y,x]
blocked = false
end
end
some_moves
end
end
class SteppingPiece < Piece
def moves
self.class.deltas.map do |delta|
y, x = delta[0] + self.pos[0], delta[1] + self.pos[1]
[y,x] if on_board?([y, x])
end.compact
end
end
class Knight < SteppingPiece
def self.deltas
[[1, 2], [1, -2], [-1, 2], [-1, -2],
[2, 1], [2, -1], [-2, 1], [-2, -1]]
end
end
class King < SteppingPiece
def self.deltas
[[1, 0], [-1, 0], [0, 1], [0, -1],
[1, 1], [-1, 1], [1, -1], [-1, -1]]
end
end
class Bishop < SlidingPiece
def self.move_dirs
[ [1, 1], [1, -1], [-1, 1], [-1, -1] ]
end
end
class Rook < SlidingPiece
def self.move_dirs
[ [0, 1], [1, 0], [0, -1], [-1, 0] ]
end
end
class Queen < SlidingPiece
def self.move_dirs
[ [0, 1], [1, 0], [0, -1], [-1, 0],
[1, 1], [1, -1], [-1, 1], [-1, -1] ]
end
end
class Pawn < Piece
COLOR_DIR = { :black => 1, :white => -1 }
attr_reader :delta
def initialize(board = Board.new, color = :white, pos = [0, 0])
super(board, color, pos)
@delta = COLOR_DIR[self.color]
end
def moves # still kind of ugly
moves = []
y, x = self.pos[0] + delta, self.pos[1]
moves << [y, x] if on_board?([y, x])
moves << [y + delta, x] if on_board?([y + delta, x]) && self.first_move
straight_moves = moves.select { |move| board[move].nil? }
diag_moves = [ [y, x - 1], [y, x + 1] ]
diag_moves.select! { |pos| on_board?(pos) && !self.board[pos].nil? }
diag_moves.reject! { |pos| board[pos].nil? }
straight_moves + diag_moves
end
def at_end?
self.color == :white ? self.pos[0] == 0 : self.pos[0] == 7
end
end