ruby-chess 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +4 -0
- data/bin/ruby-chess.rb +39 -0
- data/lib/bishop.rb +43 -0
- data/lib/board.rb +78 -0
- data/lib/chess.rb +11 -0
- data/lib/game.rb +81 -0
- data/lib/king.rb +107 -0
- data/lib/knight.rb +45 -0
- data/lib/moves.rb +37 -0
- data/lib/pawn.rb +111 -0
- data/lib/piece.rb +74 -0
- data/lib/queen.rb +43 -0
- data/lib/rook.rb +56 -0
- data/lib/space.rb +52 -0
- data/rakefile +7 -0
- data/test/bishop_test.rb +63 -0
- data/test/castle_test.rb +81 -0
- data/test/game_test.rb +68 -0
- data/test/king_test.rb +61 -0
- data/test/knight_test.rb +45 -0
- data/test/pawn_test.rb +119 -0
- data/test/queen_test.rb +103 -0
- data/test/rook_test.rb +41 -0
- metadata +68 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1452333c430641f1e9a88d3fc161f93088a77711
|
4
|
+
data.tar.gz: fc97265dbdb0b88f318f62f3154b29f9d26cd770
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 298dd4574960b152a2492067d73b066663494f14efe1654f44a2871a1379e6e5edf8fe83c28924dfd53809419810ebaf24f12e4ecf9619e8c0a9812717a708db
|
7
|
+
data.tar.gz: d17700fb66c60e0e9e95bfe97cfd98a4465075395bfaf85b7fa4d9bf94d4a99da58184a414a1259c2e4ddf8de2fb490f440da9d827d625ef3be4452d4cc1bfaa
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 John Hager
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
data/bin/ruby-chess.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/chess'
|
4
|
+
|
5
|
+
game = Game.new
|
6
|
+
|
7
|
+
def game.prompt_for_turn
|
8
|
+
puts "Resign or enter piece coordinates then move coordinate."
|
9
|
+
print "Format: x,y:a,b for move (e.g. 3,1:3,3): "
|
10
|
+
ans = gets.chomp.downcase.gsub(/\s/, '')
|
11
|
+
|
12
|
+
if ans =~ /res/
|
13
|
+
self.resign
|
14
|
+
sleep(3)
|
15
|
+
nil
|
16
|
+
else
|
17
|
+
ans.split(':').map do |point|
|
18
|
+
point.split(',').map {|i| i.to_i}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
system "clear"
|
24
|
+
game.show
|
25
|
+
|
26
|
+
until game.over?
|
27
|
+
begin
|
28
|
+
puts "#{game.turn.to_s.capitalize}'s turn"
|
29
|
+
ans = game.prompt_for_turn
|
30
|
+
game.play(*ans) if ans
|
31
|
+
|
32
|
+
system "clear"
|
33
|
+
game.show
|
34
|
+
rescue Game::IllegalMove
|
35
|
+
next
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
system "clear"
|
data/lib/bishop.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Bishop
|
2
|
+
|
3
|
+
extend self
|
4
|
+
include Moves
|
5
|
+
|
6
|
+
def illegal(board,x,y)
|
7
|
+
possible_moves = []
|
8
|
+
|
9
|
+
7.times do |coord|
|
10
|
+
possible_moves += Board.board_safe(
|
11
|
+
diagonal(coord)
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
if not(possible_moves.any? {|move| move == [x,y]})
|
16
|
+
raise Game::IllegalMove, "#{x},#{y} is not a possible move"
|
17
|
+
elsif board.at(x,y).friend_of?(self)
|
18
|
+
raise Game::IllegalMove, "#{x},#{y} is occupied by a friend"
|
19
|
+
elsif jumped?(board,x,y)
|
20
|
+
raise Game::IllegalMove, "Bishops cannot jump"
|
21
|
+
else
|
22
|
+
:legal_move
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class WhiteBishop < WhitePiece
|
28
|
+
|
29
|
+
include Bishop
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"WB"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class BlackBishop < BlackPiece
|
37
|
+
|
38
|
+
include Bishop
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
"BB"
|
42
|
+
end
|
43
|
+
end
|
data/lib/board.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
class Board
|
2
|
+
|
3
|
+
BackRow = { white: 7, black: 0 }
|
4
|
+
|
5
|
+
attr_accessor :board, :en_passent
|
6
|
+
def initialize(flag = false)
|
7
|
+
@board = []
|
8
|
+
8.times do |y|
|
9
|
+
row = []
|
10
|
+
8.times {|x| row << EmptySpace.new(x,y)}
|
11
|
+
@board << row
|
12
|
+
end
|
13
|
+
|
14
|
+
unless flag
|
15
|
+
pieces = []
|
16
|
+
8.times do |x|
|
17
|
+
pieces << BlackPawn.new(x,6) << WhitePawn.new(x,1)
|
18
|
+
end
|
19
|
+
|
20
|
+
[0,7].each do |x|
|
21
|
+
pieces << BlackRook.new(x,7) << WhitePawn.new(x,0)
|
22
|
+
end
|
23
|
+
|
24
|
+
[1,6].each do |x|
|
25
|
+
pieces << BlackKnight.new(x,7) << WhiteKnight.new(x,0)
|
26
|
+
end
|
27
|
+
|
28
|
+
[2,5].each do |x|
|
29
|
+
pieces << BlackBishop.new(x,7) << WhiteBishop.new(x,0)
|
30
|
+
end
|
31
|
+
|
32
|
+
pieces << BlackQueen.new(4,7) << WhiteQueen.new(3,0)
|
33
|
+
pieces << BlackKing.new(3,7) << WhiteKing.new(4,0)
|
34
|
+
|
35
|
+
pieces.each {|piece| place(piece)}
|
36
|
+
end
|
37
|
+
|
38
|
+
@en_passent = NullSpace.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def place(piece)
|
42
|
+
piece.place_on(self)
|
43
|
+
end
|
44
|
+
|
45
|
+
def remove(piece)
|
46
|
+
piece.remove_from(self)
|
47
|
+
end
|
48
|
+
|
49
|
+
def at(x,y)
|
50
|
+
board[y][x]
|
51
|
+
end
|
52
|
+
|
53
|
+
def enemies(piece)
|
54
|
+
board.flatten.select {|other| other.enemy_of?(piece)}
|
55
|
+
end
|
56
|
+
|
57
|
+
def move(piece, x, y)
|
58
|
+
piece.move(self, x, y)
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.board_safe(points)
|
62
|
+
points.select do |point|
|
63
|
+
not(point.any? {|cord| cord < 0 or cord > 7})
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_s
|
68
|
+
out = "\s\s"
|
69
|
+
out << (0..7).to_a.join(' ') << "\n"
|
70
|
+
|
71
|
+
@board.each_with_index do |row, i|
|
72
|
+
out << "#{i} " << (row.collect{|pc| pc.to_s}).join('') << "\n"
|
73
|
+
end
|
74
|
+
|
75
|
+
out
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
data/lib/chess.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require_relative 'board'
|
2
|
+
require_relative 'space'
|
3
|
+
require_relative 'moves'
|
4
|
+
require_relative 'piece'
|
5
|
+
require_relative 'pawn'
|
6
|
+
require_relative 'rook'
|
7
|
+
require_relative 'knight'
|
8
|
+
require_relative 'bishop'
|
9
|
+
require_relative 'queen'
|
10
|
+
require_relative 'king'
|
11
|
+
require_relative 'game'
|
data/lib/game.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
class Game
|
2
|
+
|
3
|
+
attr_reader :turn
|
4
|
+
def initialize
|
5
|
+
@board = Board.new
|
6
|
+
@kings = {white: @board.at(4,0), black: @board.at(3,7)}
|
7
|
+
@moves = []
|
8
|
+
@turn = :white
|
9
|
+
@over = false
|
10
|
+
end
|
11
|
+
|
12
|
+
def show
|
13
|
+
puts @board
|
14
|
+
end
|
15
|
+
|
16
|
+
def over?
|
17
|
+
@over
|
18
|
+
end
|
19
|
+
|
20
|
+
def at(x,y)
|
21
|
+
@board.at(x,y)
|
22
|
+
end
|
23
|
+
|
24
|
+
def undo
|
25
|
+
move = @moves.pop
|
26
|
+
piece = at(*move[:piece][:point_a])
|
27
|
+
new_piece = piece.class.new(*move[:piece][:point_b])
|
28
|
+
capture = move[:capture]
|
29
|
+
|
30
|
+
@board.remove(piece)
|
31
|
+
@board.place(new_piece)
|
32
|
+
@board.place(capture)
|
33
|
+
|
34
|
+
switch_turn
|
35
|
+
end
|
36
|
+
|
37
|
+
def play(point_a, point_b)
|
38
|
+
raise Game::IllegalMove, "Game over" if @over
|
39
|
+
|
40
|
+
piece, at_destination = at(*point_a), at(*point_b)
|
41
|
+
|
42
|
+
unless piece.color == @turn
|
43
|
+
raise Game::IllegalMove,
|
44
|
+
"It is #{@turn.to_s.capitalize}'s turn"
|
45
|
+
end
|
46
|
+
|
47
|
+
@board.move(piece, *point_b)
|
48
|
+
@moves << {
|
49
|
+
piece: {
|
50
|
+
point_a: point_a,
|
51
|
+
point_b: point_b,
|
52
|
+
},
|
53
|
+
capture: at_destination,
|
54
|
+
}
|
55
|
+
|
56
|
+
if @kings[@turn].checked?(@board)
|
57
|
+
undo
|
58
|
+
raise Game::IllegalMove, "#{@turn}'s king is in check!"
|
59
|
+
end
|
60
|
+
|
61
|
+
switch_turn
|
62
|
+
end
|
63
|
+
|
64
|
+
def resign
|
65
|
+
@over = true
|
66
|
+
print "#{@turn.to_s.capitalize} resigns, "
|
67
|
+
switch_turn
|
68
|
+
puts "#{@turn.to_s.capitalize} wins!"
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
def switch_turn
|
73
|
+
@turn = @turn == :white ? :black : :white
|
74
|
+
end
|
75
|
+
|
76
|
+
public
|
77
|
+
class IllegalMove < Exception
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
data/lib/king.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
module King
|
2
|
+
|
3
|
+
extend self
|
4
|
+
include Moves
|
5
|
+
|
6
|
+
def illegal(board,x,y)
|
7
|
+
x_diff = x-@x
|
8
|
+
possible_moves = []
|
9
|
+
|
10
|
+
possible_moves += Board.board_safe(
|
11
|
+
diagonal(1) + horizontal(1) + vertical(1)
|
12
|
+
)
|
13
|
+
|
14
|
+
if @start #castling
|
15
|
+
possible_moves += [
|
16
|
+
[@x-(2 * @direction), @y], [@x+(2 * @direction), @y]
|
17
|
+
]
|
18
|
+
end
|
19
|
+
|
20
|
+
if not(possible_moves.any? {|move| move == [x,y]})
|
21
|
+
raise Game::IllegalMove, "#{x},#{y} is not a possible move"
|
22
|
+
elsif board.at(x,y).friend_of?(self)
|
23
|
+
raise Game::IllegalMove, "#{x},#{y} is occupied by a friend"
|
24
|
+
elsif jumped?(board,x,y)
|
25
|
+
raise Game::IllegalMove, "Kings can't jump"
|
26
|
+
elsif checked?(board,x,y,x_diff)
|
27
|
+
raise Game::IllegalMove, "King can't move into check"
|
28
|
+
else
|
29
|
+
castle(board,x,y,x_diff) if (x_diff).abs > 1
|
30
|
+
:legal_move
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def castle(board,x,y,x_diff)
|
35
|
+
direction = x_diff/x_diff.abs
|
36
|
+
|
37
|
+
# get rook, raise illegal move unless start, else move the rook
|
38
|
+
if direction > 0 # right
|
39
|
+
rook = board.at(7,y)
|
40
|
+
rook_x = x-1
|
41
|
+
else # left
|
42
|
+
rook = board.at(0,y)
|
43
|
+
rook_x = x+1
|
44
|
+
end
|
45
|
+
|
46
|
+
if rook.is_a?(Rook) && rook.friend_of?(self) && rook.start
|
47
|
+
board.move(rook,rook_x,y)
|
48
|
+
else
|
49
|
+
raise Game::IllegalMove, "King cannot castle this way, now"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def checked?(board,x = @x, y = @y, x_diff = 0)
|
54
|
+
enemies = board.enemies(self)
|
55
|
+
spaces = [[x,y]]
|
56
|
+
|
57
|
+
if x_diff.abs > 1 #castling
|
58
|
+
spaces << [x - 1*(x_diff/x_diff.abs), y]
|
59
|
+
end
|
60
|
+
|
61
|
+
enemies.each do |enemy|
|
62
|
+
spaces.each do |space|
|
63
|
+
begin
|
64
|
+
enemy.illegal(board,*space)
|
65
|
+
return true
|
66
|
+
rescue Game::IllegalMove
|
67
|
+
:not_checked
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
return false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class WhiteKing < WhitePiece
|
77
|
+
|
78
|
+
include King
|
79
|
+
|
80
|
+
attr_reader :start
|
81
|
+
def initialize(x,y)
|
82
|
+
super
|
83
|
+
@start = true
|
84
|
+
@direction = 1
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_s
|
88
|
+
"W!"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class BlackKing < BlackPiece
|
93
|
+
|
94
|
+
include King
|
95
|
+
|
96
|
+
attr_reader :start
|
97
|
+
def initialize(x,y)
|
98
|
+
super
|
99
|
+
@start = true
|
100
|
+
@direction = -1
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_s
|
104
|
+
"B!"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
data/lib/knight.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Knight
|
2
|
+
|
3
|
+
extend self
|
4
|
+
include Moves
|
5
|
+
|
6
|
+
def illegal(board,x,y)
|
7
|
+
possible_moves = [
|
8
|
+
[@x+2, @y-1],
|
9
|
+
[@x+2, @y+1],
|
10
|
+
[@x-2, @y+1],
|
11
|
+
[@x-2, @y-1],
|
12
|
+
[@x+1, @y-2],
|
13
|
+
[@x-1, @y-2],
|
14
|
+
[@x+1, @y+2],
|
15
|
+
[@x-1, @y+2],
|
16
|
+
]
|
17
|
+
|
18
|
+
if not(possible_moves.any? {|move| move == [x,y]})
|
19
|
+
raise Game::IllegalMove, "#{x},#{y} is not a possible move"
|
20
|
+
elsif board.at(x,y).friend_of?(self)
|
21
|
+
raise Game::IllegalMove, "#{x},#{y} is occupied by a friend"
|
22
|
+
else
|
23
|
+
:legal_move
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class WhiteKnight < WhitePiece
|
29
|
+
|
30
|
+
include Knight
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
"WK"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class BlackKnight < BlackPiece
|
38
|
+
|
39
|
+
include Knight
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
"BK"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
data/lib/moves.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Moves
|
2
|
+
|
3
|
+
def move(board,x,y)
|
4
|
+
illegal(board,x,y)
|
5
|
+
|
6
|
+
remove_from(board)
|
7
|
+
@x,@y = x,y
|
8
|
+
place_on(board)
|
9
|
+
|
10
|
+
@start &&= false
|
11
|
+
end
|
12
|
+
|
13
|
+
def diagonal(coord)
|
14
|
+
[
|
15
|
+
[@x-coord, @y-coord],
|
16
|
+
[@x+coord, @y-coord],
|
17
|
+
[@x-coord, @y+coord],
|
18
|
+
[@x+coord, @y+coord],
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
def horizontal(coord)
|
23
|
+
[
|
24
|
+
[@x-coord, @y],
|
25
|
+
[@x+coord, @y],
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
def vertical(coord)
|
30
|
+
[
|
31
|
+
[@x, @y-coord],
|
32
|
+
[@x, @y+coord],
|
33
|
+
]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
data/lib/pawn.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
module Pawn
|
2
|
+
|
3
|
+
extend self
|
4
|
+
|
5
|
+
attr_reader :direction
|
6
|
+
|
7
|
+
# attempt to move the piece to x,y on the board
|
8
|
+
def move(board,x,y)
|
9
|
+
# check if it is an illegal move (raises Game::IllegalMove if it is)
|
10
|
+
illegal(board, x, y)
|
11
|
+
|
12
|
+
# make start false if it not already false
|
13
|
+
!@start || @start = false
|
14
|
+
|
15
|
+
# remove the piece from it's original position
|
16
|
+
board.remove(self)
|
17
|
+
|
18
|
+
# save the piece if it can be taken by en passent
|
19
|
+
board.en_passent = (@y-y).abs == 2 ? self : NullSpace.new
|
20
|
+
|
21
|
+
# update the coordinates
|
22
|
+
@x, @y = x, y
|
23
|
+
|
24
|
+
# replace with queen if on back row
|
25
|
+
if @y == Board::BackRow[color]
|
26
|
+
board.place(@queen.new(@x,@y))
|
27
|
+
else
|
28
|
+
# or place on board
|
29
|
+
place_on(board)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def illegal(board,x,y)
|
34
|
+
possible_moves = [
|
35
|
+
[@x, @y+(1 * @direction)],
|
36
|
+
]
|
37
|
+
possible_moves << [@x, @y+(2 * @direction)] if @start
|
38
|
+
possible_moves = Board.board_safe(possible_moves)
|
39
|
+
|
40
|
+
possible_attack_moves = Board.board_safe([
|
41
|
+
[@x-1, @y+(1 * @direction)],
|
42
|
+
[@x+1, @y+(1 * @direction)]
|
43
|
+
])
|
44
|
+
|
45
|
+
en_passent = board.en_passent
|
46
|
+
en_passent_coord = en_passent.to_coord
|
47
|
+
en_passent_coord[1] &&= en_passent_coord[1] - en_passent.direction
|
48
|
+
|
49
|
+
if board.at(x,y).friend_of?(self)
|
50
|
+
error = "Your piece is blocking your path"
|
51
|
+
elsif board.at(x,y).enemy_of?(self)
|
52
|
+
unless possible_attack_moves.find {|move| move == [x,y]}
|
53
|
+
error = "Cannot move this way!"
|
54
|
+
end
|
55
|
+
elsif en_passent_coord == [x,y]
|
56
|
+
unless possible_attack_moves.find {|move| move == [x,y]}
|
57
|
+
error = "Cannot move this way!"
|
58
|
+
else
|
59
|
+
en_passent.remove_from(board)
|
60
|
+
end
|
61
|
+
else
|
62
|
+
unless possible_moves.find {|move| move == [x,y]}
|
63
|
+
error = "Cannot move here!"
|
64
|
+
else
|
65
|
+
if jumped?(board,x,y)
|
66
|
+
raise Game::IllegalMove, "Pawns cannot jump!"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
raise Game::IllegalMove, error if error
|
72
|
+
end
|
73
|
+
|
74
|
+
def jumped?(board,x,y)
|
75
|
+
return false unless (@y-y).abs == 2
|
76
|
+
!board.at(x,y-@direction).empty?
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class WhitePawn < WhitePiece
|
81
|
+
|
82
|
+
include Pawn
|
83
|
+
|
84
|
+
def initialize(x,y)
|
85
|
+
super
|
86
|
+
@start = true
|
87
|
+
@direction = 1
|
88
|
+
@queen = WhiteQueen
|
89
|
+
end
|
90
|
+
|
91
|
+
def to_s
|
92
|
+
"WP"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class BlackPawn < BlackPiece
|
97
|
+
|
98
|
+
include Pawn
|
99
|
+
|
100
|
+
def initialize(x,y)
|
101
|
+
super
|
102
|
+
@start = true
|
103
|
+
@direction = -1
|
104
|
+
@queen = BlackQueen
|
105
|
+
end
|
106
|
+
|
107
|
+
def to_s
|
108
|
+
"BP"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
data/lib/piece.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
class Piece < EmptySpace
|
2
|
+
|
3
|
+
private
|
4
|
+
def jumped?(board,x,y)
|
5
|
+
start, new = self.to_coord, [x,y]
|
6
|
+
|
7
|
+
# find all the spaces ([x,y]) between start and new
|
8
|
+
x_diff = (start.first - new.first)
|
9
|
+
y_diff = (start.last - new.last)
|
10
|
+
|
11
|
+
moves_between = []
|
12
|
+
|
13
|
+
if x_diff == 0 # vertical movement
|
14
|
+
multiplyer = y_diff / y_diff.abs
|
15
|
+
|
16
|
+
((y_diff.abs)-1).times do |aug|
|
17
|
+
aug = (aug + 1) * multiplyer
|
18
|
+
moves_between << [x, y + aug]
|
19
|
+
end
|
20
|
+
|
21
|
+
elsif y_diff == 0 # horizontal movement
|
22
|
+
multiplyer = x_diff / x_diff.abs
|
23
|
+
|
24
|
+
((x_diff.abs)-1).times do |aug|
|
25
|
+
aug = (aug + 1) * multiplyer
|
26
|
+
moves_between << [x + aug, y]
|
27
|
+
end
|
28
|
+
else # diagonal movement
|
29
|
+
y_multiplyer = y_diff / y_diff.abs
|
30
|
+
x_multiplyer = x_diff / x_diff.abs
|
31
|
+
|
32
|
+
((x_diff.abs)-1).times do |aug|
|
33
|
+
y_aug = (aug + 1) * y_multiplyer
|
34
|
+
x_aug = (aug + 1) * x_multiplyer
|
35
|
+
moves_between << [x + x_aug, y + y_aug]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
moves_between.any? {|coord| !board.at(*coord).empty?}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class BlackPiece < Piece
|
44
|
+
|
45
|
+
def initialize(x,y)
|
46
|
+
super
|
47
|
+
@color = :black
|
48
|
+
end
|
49
|
+
|
50
|
+
def enemy_of?(piece)
|
51
|
+
piece.color == :white
|
52
|
+
end
|
53
|
+
|
54
|
+
def friend_of?(piece)
|
55
|
+
piece.color == color
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class WhitePiece < Piece
|
60
|
+
|
61
|
+
def initialize(x,y)
|
62
|
+
super
|
63
|
+
@color = :white
|
64
|
+
end
|
65
|
+
|
66
|
+
def enemy_of?(piece)
|
67
|
+
piece.color == :black
|
68
|
+
end
|
69
|
+
|
70
|
+
def friend_of?(piece)
|
71
|
+
piece.color == color
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
data/lib/queen.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Queen
|
2
|
+
|
3
|
+
extend self
|
4
|
+
include Moves
|
5
|
+
|
6
|
+
def illegal(board,x,y)
|
7
|
+
possible_moves = []
|
8
|
+
|
9
|
+
7.times do |coord|
|
10
|
+
possible_moves += Board.board_safe(
|
11
|
+
diagonal(coord) + horizontal(coord) + vertical(coord)
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
if not(possible_moves.any? {|move| move == [x,y]})
|
16
|
+
raise Game::IllegalMove, "#{x},#{y} is not a possible move"
|
17
|
+
elsif board.at(x,y).friend_of?(self)
|
18
|
+
raise Game::IllegalMove, "#{x},#{y} is occupied by a friend"
|
19
|
+
elsif jumped?(board,x,y)
|
20
|
+
raise Game::IllegalMove, "Queens cannot jump"
|
21
|
+
else
|
22
|
+
:legal_move
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class WhiteQueen < WhitePiece
|
28
|
+
|
29
|
+
include Queen
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"WQ"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class BlackQueen < BlackPiece
|
37
|
+
|
38
|
+
include Queen
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
"BQ"
|
42
|
+
end
|
43
|
+
end
|