Chess Buddy is a ruby implementation of Chess. It allows the user(s) to play Human vs. Human or Human vs. Computer. Users can also watch a Computer vs. Computer game play out.
You must have Ruby installed in order to play this game. Once you have Ruby installed:
- Download the zip file by clicking here
- Open the zip file. You should see a folder called
chess-buddy-master
- Open Terminal, and navigate to the chess-buddy-master directory. It should be in the
Downloads
directory.
- (If you'd like, you can optionally move the folder elsewhere before completing Step 3)
- Type the command
bundle install
and press enter. This will ensure that you have thecolorize
gem installed. Colorize is used to color the pieces, the board, and the cursor. - Type the command
ruby chess.rb
and press enter to play the game.
To read more about rules of Chess and much more, check out Wikipedia.
Note: It may be helpful to zoom in, in order to see the pieces more clearly. To do this, press Command-+ (the command key and the plus/equals key) as many times as desired.
To use Chess Buddy:
- Click enter when you see the welcome message.
- Type either H or C to indicate that Player 1 will be either a human or computer player.
- If you choose human, you will be prompted to enter your name.
- Repeat the same for Player 2.
- The game always begins with "white", represented in this game by red pieces.
- The yellow cursor begins on square e4. You can move it around the board using the arrow keys.
- When you are ready to select a piece to move, click either space bar or enter.
- Once you select a piece, Chess Buddy will show you all valid moves for that piece by highlighting them in blue.
- Navigate to the square where you'd like to move your piece, and press enter again.
- If you attempt to make an invalid move, Chess Buddy will show you an error message and ask you to try again.
- Chess Buddy currently supports Pawn Promotion, but not Castling.
Chess Buddy features a custom Computer Player AI. Chess Buddy categorizes all valid moves on several dimensions:
- In Check: Does the move put the opponent in check?
- Safe vs. At Risk: Does the move put given piece in a position where the opponent could immediately capture it on the next turn?
- Capture: Does the move capture a piece?
- Valuable Capture: Does the move capture a piece with value greater than or equal to the value of the capturing piece?
One interesting challenge was determining whether or not a move left a piece at risk. Here is code from the Piece
class. In order to determine whether a piece is at risk, the entire board (and all of its pieces) must first be duplicated. Only then can the speculative moves be made. Once a move is made on the dup_board
, the code checks if any of the opponent_pieces
are able to move to the piece's new position (to_pos
).
def puts_self_at_risk?(to_pos)
opponent_color = (color == :white ? :black : :white)
dup_board = board.dup
dup_board.move!(pos, to_pos)
opponent_pieces = dup_board.rows.flatten.select { |piece| piece.color == opponent_color }
opponent_pieces.each do |opponent_piece|
opponent_piece.valid_moves_that_could_capture.each do |move|
return true if move == to_pos
end
end
false
end
Chess Buddy's AI then chooses a move for the Computer Player in the following order of preference:
- Safe and Valuable Capture
- Safe and In Check
- Valuable Capture
- Safe and Capture
- Safe
- In Check
- Capture
- None of the above
Each player has six types of pieces on the board: Rook (2), Knight (2), Bishop (2), Queen (1), King (1), and Pawn (8). While each piece has unique constraints on its movement, these constraints have a lot in common. Rooks can slide horizontally or vertically until they meet another piece, while Bishops can slide diagonally. Queens can slide in all 8 of these directions. Chess Buddy captures (!) these similar movement patterns in a SlidingPiece class, from which all three pieces inherit.
# pieces/sliding_piece.rb
HORIZ_VERT_MOVES = { up: [-1, 0], down: [1, 0], left: [0, -1], right: [0, 1] }
DIAGONAL_MOVES = { up_left: [-1, -1], down_left: [1, -1], up_right: [-1, 1], down_right: [1, 1] }
def moves
possible_moves = []
if move_dirs[:horiz_and_vert_allowed]
HORIZ_VERT_MOVES.each { | _, (dx, dy) | possible_moves += eval_moves(dx, dy) }
end
if move_dirs[:diagonal_allowed]
DIAGONAL_MOVES.each { | _, (dx, dy) | possible_moves += eval_moves(dx, dy) }
end
possible_moves
end
Rook
s, Bishop
s, and Queen
s share the moves
method above, which returns an array of all possible_moves
a given piece can make. It does this by iterating through all of the directions in which each piece is allowed to move and moving the piece as far as possible in each directions.
The differences in movement rules can be found in the hash returned by each piece's move_dirs
method. Here is the move_dirs
method for the Rook.
# pieces/rook.rb
def move_dirs
{ horiz_and_vert_allowed: true, diagonal_allowed: false }
end
This example shows the fastest possible game of Chess (two moves by each side).
Features that could be added to future versions of Chess Buddy include:
- Saving/Loading Games
- Stronger AI that recognizes all pieces that are at risk before making any move