Programming Chess: Moving a Rook in Ruby

I’d like to make a Tic Tac Chec program, so to begin, I wanted to be able to move a rook around the board.

The Setup

To better understand the mechanics of the program, I decided to make a command line program in Ruby. I put each Class into a separate file, then used require_relative to include them into an app.rb file. I also required the PrettyPrint class to beautify my output.

There is a Game class, which initializes with @player1, @player2, @board, and sets the first turn to be played by Player 1. During their turn, Player 1 chooses which piece to move based on its x-y coordinates. Then the player chooses where to move the piece based on a list of possible moves. Next, it’s the other player’s turn to move a piece.

I created an 8x8 board with 4 rooks on it, two belonging to each player. It started like this:

1
2
3
4
5
6
7
8
9
 coordinates x/y: 0    1    2        3    4    5        6    7
             0  [nil, nil, nil,     nil, nil, nil,     nil, nil],
             1  [nil, nil, nil,     nil, nil, nil,     nil, nil],
             2  [nil, nil, P1-Rook, nil, nil, nil,     nil, nil],
             3  [nil, nil, nil,     nil, nil, nil,     nil, nil],
             4  [nil, nil, P1-Rook, nil, nil, P2-Rook, nil, nil],
             5  [nil, nil, nil,     nil, nil, nil,     nil, nil],
             6  [nil, nil, nil,     nil, nil, nil,     nil, nil],
             7  [nil, nil, P2-Rook, nil, nil, nil,     nil, nil]

Finding the Rook’s Available Moves

Upon selecting a piece, the player receives a list of x-y coordinates where that piece can move. I defined the method available moves in the Rook class.

1
2
3
4
5
6
7
8
9
class Rook < Piece
  def available_moves x, y
    horz_left x, y
    horz_right x, y
    vert_up x, y
    vert_down x, y
    moves
  end
end

The method returns a list of moves after checking each direction for open squares. Based on the rook’s position, these “by direction” methods find whether there is a piece obstructing the rook’s path or else adds that x-y coordinate to a list of moves. See below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Rook < Piece
  def horz_right x, y
    ((x+1)..7).each do |x_pos|
      square_or_piece = self.player.choose(x_pos,y)
      return if add_by_x_pos(square_or_piece, x_pos, y) == "stop"
    end
  end

  def add_by_x_pos square_piece, x_pos, y
    if square_piece.nil?
      moves << [x_pos, y]
    else
      add_taking(x_pos, y) if square_piece.player != self.player
      return "stop"
    end
  end

  def add_taking x, y
    taking_moves << [x, y]
    moves        << [x, y]
  end
end

The first method checks all squares to the right of the rook until it finds a square with a piece in it. Then, the second method determines whether the rook can move there based on whether this piece belongs to current player. If it’s an enemy piece, the third method adds that square to both the move list and the taking_moves list.

Once a piece is found in the Rook’s path, the second method terminates itself with a return "stop" that then stops the first method. This way, only spots that need to be checked are looked at.

Takeaways and Future Improvements

As I was coding this, I also wrote the logic to switch turns between players. While my initial focus was getting rooks to move properly, it was necessary to associate rooks with players if I wanted to determine if a rook could move into another piece’s square. Therefore I ended up building the game class despite not intending to do so immediately.

Luckily, I already had a good idea of how to design the chess app in general. Rather than just starting anywhere, having a sense of how the entire program is designed proved to be invaluable.

In the future, I will add the logic for more pieces and create a way to recognize when the game is finished. Stay tuned!