|
1 |
| -# encoding: utf-8 |
2 |
| - |
3 |
| -def vector_sum(vectors) |
4 |
| - result = [0,0] |
5 |
| - vectors.each do |vec| |
6 |
| - result[0] += vec[0] |
7 |
| - result[1] += vec[1] |
8 |
| - end |
9 |
| - result |
10 |
| -end |
11 |
| - |
12 |
| -class Piece |
13 |
| - attr_reader :color |
14 |
| - attr_accessor :pos |
15 |
| - # row, col |
16 |
| - DELTAS = { nw: [-1, -1], n: [-1, 0], ne: [-1, 1], |
17 |
| - w: [0, -1], e: [0, 1], |
18 |
| - sw: [1, -1], s: [1, 0], se: [1, 1] } |
19 |
| - |
20 |
| - def initialize(pos, board, color) |
21 |
| - @pos = pos |
22 |
| - @board = board |
23 |
| - @color = color |
24 |
| - end |
25 |
| - |
26 |
| - def move_within_boundaries?(pos) |
27 |
| - row, col = pos |
28 |
| - row.between?(0, @board.height - 1) && col.between?(0, @board.width - 1) |
29 |
| - end |
30 |
| - |
31 |
| - def valid_moves |
32 |
| - moves.select { |move| valid_move?(move) } |
33 |
| - end |
34 |
| - |
35 |
| - def valid_move?(target) |
36 |
| - duped_board = @board.dup |
37 |
| - duped_board.move!(@pos, target) |
38 |
| - !duped_board.in_check?(self.color) |
39 |
| - end |
40 |
| -end |
41 |
| - |
42 |
| -class SlidingPiece < Piece |
43 |
| - def moves |
44 |
| - moves = [] |
45 |
| - move_dirs.each do |dir| |
46 |
| - current_pos = @pos |
47 |
| - loop do |
48 |
| - next_move = vector_sum([current_pos, dir]) |
49 |
| - break unless move_within_boundaries?(next_move) |
50 |
| - break if !@board[next_move].nil? && @board[next_move].color == self.color |
51 |
| - moves << next_move |
52 |
| - break unless @board[next_move].nil? #change .empty? to whatever call |
53 |
| - |
54 |
| - current_pos = next_move |
55 |
| - end |
56 |
| - end |
57 |
| - |
58 |
| - moves |
59 |
| - end |
60 |
| -end |
61 |
| - |
62 |
| -class SteppingPiece < Piece |
63 |
| - def moves |
64 |
| - moves = [] |
65 |
| - move_dirs.each do |dir| |
66 |
| - next_move = vector_sum([pos, dir]) |
67 |
| - next unless move_within_boundaries?(next_move) |
68 |
| - next if !@board[next_move].nil? && @board[next_move].color == self.color |
69 |
| - moves << next_move |
70 |
| - end |
71 |
| - |
72 |
| - moves |
73 |
| - end |
74 |
| -end |
75 |
| - |
76 |
| -class Pawn < Piece |
77 |
| - def move_dirs |
78 |
| - case @color |
79 |
| - when :w |
80 |
| - [DELTAS[:n], DELTAS[:ne], DELTAS[:nw]] |
81 |
| - when :b |
82 |
| - [DELTAS[:s], DELTAS[:se], DELTAS[:sw]] |
83 |
| - end |
84 |
| - end |
85 |
| - |
86 |
| - def moves |
87 |
| - moves = [] |
88 |
| - dirs = move_dirs |
89 |
| - |
90 |
| - advance = vector_sum([@pos, dirs[0]]) |
91 |
| - if @board[advance].nil? |
92 |
| - moves << advance |
93 |
| - unless moved? |
94 |
| - advance = vector_sum([advance, dirs[0]]) |
95 |
| - moves << advance if @board[advance].nil? |
96 |
| - end |
97 |
| - end |
98 |
| - |
99 |
| - 2.times do |i| |
100 |
| - advance = vector_sum([@pos, dirs[i + 1]]) |
101 |
| - unless @board[advance].nil? || @board[advance].color == self.color |
102 |
| - moves << advance |
103 |
| - end |
104 |
| - end |
105 |
| - |
106 |
| - moves.select { |move| move_within_boundaries?(move) } |
107 |
| - end |
108 |
| - |
109 |
| - def to_s |
110 |
| - @color == :b ? "\u{265f}" : "\u{2659}" |
111 |
| - end |
112 |
| - |
113 |
| - def moved? |
114 |
| - case @color |
115 |
| - when :w |
116 |
| - @pos.first != @board.height - 2 |
117 |
| - when :b |
118 |
| - @pos.first != 1 |
119 |
| - end |
120 |
| - end |
121 |
| - |
122 |
| -end |
123 |
| - |
124 |
| -class Bishop < SlidingPiece |
125 |
| - def move_dirs |
126 |
| - [DELTAS[:nw], DELTAS[:ne], DELTAS[:sw], DELTAS[:se]] |
127 |
| - end |
128 |
| - |
129 |
| - def to_s |
130 |
| - @color == :b ? "\u{265d}" : "\u{2657}" |
131 |
| - end |
132 |
| -end |
133 |
| - |
134 |
| -class Rook < SlidingPiece |
135 |
| - def move_dirs |
136 |
| - [DELTAS[:n], DELTAS[:e], DELTAS[:s], DELTAS[:w]] |
137 |
| - end |
138 |
| - |
139 |
| - def to_s |
140 |
| - @color == :b ? "\u{265c}" : "\u{2656}" |
141 |
| - end |
142 |
| -end |
143 |
| - |
144 |
| -class Queen < SlidingPiece |
145 |
| - def move_dirs |
146 |
| - DELTAS.values |
147 |
| - end |
148 |
| - |
149 |
| - def to_s |
150 |
| - @color == :b ? "\u{265b}" : "\u{2655}" |
151 |
| - end |
152 |
| -end |
153 |
| - |
154 |
| -class Knight < SteppingPiece |
155 |
| - def move_dirs |
156 |
| - [ |
157 |
| - [DELTAS[:n]] * 2 + [DELTAS[:e]], |
158 |
| - [DELTAS[:n]] * 2 + [DELTAS[:w]], |
159 |
| - [DELTAS[:s]] * 2 + [DELTAS[:e]], |
160 |
| - [DELTAS[:s]] * 2 + [DELTAS[:w]], |
161 |
| - [DELTAS[:e]] * 2 + [DELTAS[:n]], |
162 |
| - [DELTAS[:w]] * 2 + [DELTAS[:n]], |
163 |
| - [DELTAS[:e]] * 2 + [DELTAS[:s]], |
164 |
| - [DELTAS[:w]] * 2 + [DELTAS[:s]], |
165 |
| - ].map { |vec| vector_sum(vec) } |
166 |
| - end |
167 |
| - |
168 |
| - def to_s |
169 |
| - @color == :b ? "\u{265e}" : "\u{2658}" |
170 |
| - end |
171 |
| -end |
172 |
| - |
173 |
| -class King < SteppingPiece |
174 |
| - def move_dirs |
175 |
| - DELTAS.values |
176 |
| - end |
177 |
| - |
178 |
| - def to_s |
179 |
| - @color == :b ? "\u{265a}" : "\u{2654}" |
180 |
| - end |
181 |
| -end |
182 |
| - |
183 |
| -class Board |
184 |
| - def initialize |
185 |
| - @board = Array.new(8) { Array.new(8) } |
186 |
| - place_pieces |
187 |
| - end |
188 |
| - |
189 |
| - def height |
190 |
| - @board.count |
191 |
| - end |
192 |
| - |
193 |
| - def width |
194 |
| - @board[0].count |
195 |
| - end |
196 |
| - |
197 |
| - def [](pos) |
198 |
| - row, col = pos |
199 |
| - @board[row][col] |
200 |
| - end |
201 |
| - |
202 |
| - def []=(pos, value) |
203 |
| - row, col = pos |
204 |
| - @board[row][col] = value |
205 |
| - end |
206 |
| - |
207 |
| - def place_pieces |
208 |
| - place_piece_row(0, :b) |
209 |
| - place_pawn_row(1, :b) |
210 |
| - place_pawn_row(6, :w) |
211 |
| - place_piece_row(7, :w) |
212 |
| - end |
213 |
| - |
214 |
| - def place_pawn_row(row, color) |
215 |
| - @board[row].each_with_index do |spot, i| |
216 |
| - @board[row][i] = Pawn.new([row, i], self, color) |
217 |
| - end |
218 |
| - |
219 |
| - nil |
220 |
| - end |
221 |
| - |
222 |
| - def place_piece_row(row, color) |
223 |
| - starting_row = [Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook] |
224 |
| - @board[row].each_with_index do |spot, i| |
225 |
| - @board[row][i] = starting_row[i].new([row, i], self, color) |
226 |
| - end |
227 |
| - |
228 |
| - nil |
229 |
| - end |
230 |
| - |
231 |
| - def display |
232 |
| - puts '' |
233 |
| - puts ' ' + ('a'..'h').to_a.join(' ') |
234 |
| - @board.each_with_index do |row, index| |
235 |
| - print " #{8 - index} " |
236 |
| - row.each do |piece| |
237 |
| - print (piece.nil? ? ' ' : piece.to_s) + ' ' |
238 |
| - end |
239 |
| - print "#{8 - index}" |
240 |
| - puts |
241 |
| - end |
242 |
| - puts ' ' + ('a'..'h').to_a.join(' ') |
243 |
| - puts ' ' |
244 |
| - |
245 |
| - nil |
246 |
| - end |
247 |
| - |
248 |
| - def find_king(color) |
249 |
| - @board.flatten.each do |piece| |
250 |
| - if piece.class == King && piece.color == color |
251 |
| - return piece.pos |
252 |
| - end |
253 |
| - end |
254 |
| - |
255 |
| - nil |
256 |
| - end |
257 |
| - |
258 |
| - def in_check?(color) |
259 |
| - king_pos = find_king(color) |
260 |
| - @board.flatten.compact.each do |piece| |
261 |
| - next if piece.color == color |
262 |
| - return true if piece.moves.include?(king_pos) |
263 |
| - end |
264 |
| - |
265 |
| - false |
266 |
| - end |
267 |
| - |
268 |
| - def move!(start, end_pos) |
269 |
| - piece = self[start] |
270 |
| - # changes piece.pos to end_pos |
271 |
| - piece.pos = end_pos |
272 |
| - |
273 |
| - # changes Board positions |
274 |
| - self[start], self[end_pos] = nil, piece |
275 |
| - |
276 |
| - nil |
277 |
| - end |
278 |
| - |
279 |
| - def move(start, end_pos) |
280 |
| - # finds piece at start position |
281 |
| - piece = self[start] |
282 |
| - if piece.nil? |
283 |
| - raise "No piece at start position." |
284 |
| - end |
285 |
| - |
286 |
| - # checks piece.moves for end_pos |
287 |
| - unless piece.moves.include?(end_pos) |
288 |
| - raise "Can't move to that position." |
289 |
| - end |
290 |
| - |
291 |
| - unless piece.valid_moves.include?(end_pos) |
292 |
| - raise "Move will leave you in check." |
293 |
| - end |
294 |
| - |
295 |
| - piece.pos = end_pos |
296 |
| - self[start], self[end_pos] = nil, piece |
297 |
| - |
298 |
| - nil |
299 |
| - end |
300 |
| - |
301 |
| - def checkmate?(color) |
302 |
| - pieces = @board.flatten.compact.select { |piece| piece.color == color } |
303 |
| - pieces.all? { |piece| piece.valid_moves.empty? } |
304 |
| - end |
305 |
| - |
306 |
| - def dup |
307 |
| - duped_board = Board.new #Array.new(8) { Array.new(8) } |
308 |
| - @board.each_with_index do |row, row_index| |
309 |
| - row.each_with_index do |piece, col_index| |
310 |
| - pos = [row_index, col_index] |
311 |
| - if piece.nil? |
312 |
| - duped_board[pos] = nil |
313 |
| - else |
314 |
| - duped_board[pos] = piece.class.new(pos, duped_board, piece.color) |
315 |
| - end |
316 |
| - end |
317 |
| - end |
318 |
| - |
319 |
| - duped_board |
320 |
| - end |
321 |
| - |
322 |
| -end |
| 1 | +require_relative 'chess_board' |
| 2 | +require_relative 'human_player' |
323 | 3 |
|
324 | 4 | class Game
|
325 | 5 | def initialize(white, black)
|
@@ -379,22 +59,6 @@ def make_move(color, start, target)
|
379 | 59 |
|
380 | 60 | end
|
381 | 61 |
|
382 |
| -class HumanPlayer |
383 |
| - def play_turn |
384 |
| - print "Input start, target positions: " |
385 |
| - move_string = gets.chomp |
386 |
| - start, target = move_string.scan(/\D\d/) |
387 |
| - |
388 |
| - [parse(start), parse(target)] |
389 |
| - end |
390 |
| - |
391 |
| - def parse(pos_string) |
392 |
| - letters, numbers = ('a'..'h').to_a, (1..8).to_a.reverse |
393 |
| - |
394 |
| - [numbers.index(pos_string[1].to_i), letters.index(pos_string[0])] |
395 |
| - end |
396 |
| -end |
397 |
| - |
398 | 62 | if __FILE__ == $PROGRAM_NAME
|
399 | 63 | player1 = HumanPlayer.new
|
400 | 64 | player2 = HumanPlayer.new
|
|
0 commit comments