diff --git a/lib/chess/moves/rook.ex b/lib/chess/moves/rook.ex index 09e60fb..58e764e 100644 --- a/lib/chess/moves/rook.ex +++ b/lib/chess/moves/rook.ex @@ -8,23 +8,54 @@ defmodule Chess.Moves.Rook do moves_west(board, {file, rank}) end - defp moves_north(_board, {_file, 7}), do: [] defp moves_north(board, {file, rank}) do - [{file, rank + 1} | moves_north(board, {file, rank + 1})] + board["#{file},#{rank}"] + |> Map.get("colour") + |> _moves(board, {file, rank}, {0, +1}) end - defp moves_south(_board, {_file, 0}), do: [] defp moves_south(board, {file, rank}) do - [{file, rank - 1} | moves_south(board, {file, rank - 1})] + board["#{file},#{rank}"] + |> Map.get("colour") + |> _moves(board, {file, rank}, {0, -1}) end - defp moves_east(_board, {7, _rank}), do: [] defp moves_east(board, {file, rank}) do - [{file + 1, rank} | moves_east(board, {file + 1, rank})] + board["#{file},#{rank}"] + |> Map.get("colour") + |> _moves(board, {file, rank}, {+1, 0}) end - defp moves_west(_board, {0, _rank}), do: [] defp moves_west(board, {file, rank}) do - [{file - 1, rank} | moves_west(board, {file - 1, rank})] + board["#{file},#{rank}"] + |> Map.get("colour") + |> _moves(board, {file, rank}, {-1, 0}) + end + + defp _moves(_colour, _board, {0, _rank}, {-1, _}), do: [] + defp _moves(_colour, _board, {_file, 0}, {_, -1}), do: [] + defp _moves(_colour, _board, {7, _rank}, {1, _}), do: [] + defp _moves(_colour, _board, {_file, 7}, {_, 1}), do: [] + defp _moves(colour, board, {file, rank}, {fv, rv}) do + next_square = {file + fv, rank + rv} + cond do + can_take_piece?(colour, board, next_square) -> + [next_square] + obstruction?(board, next_square) -> + [] + true -> + [next_square | _moves(colour, board, next_square, {fv, rv})] + end + end + + defp can_take_piece?(colour, board, {file, rank}) do + piece = board["#{file},#{rank}"] + + piece && piece["colour"] != colour + end + + defp obstruction?(board, {file, rank}) do + board + |> Map.has_key?("#{file},#{rank}") end end diff --git a/test/chess/moves/rook_test.exs b/test/chess/moves/rook_test.exs index b10a9cf..952629a 100644 --- a/test/chess/moves/rook_test.exs +++ b/test/chess/moves/rook_test.exs @@ -25,6 +25,34 @@ defmodule Chess.Moves.RookTest do assert Enum.sort(moves) == expected_moves end + test "rook is obstructed by another piece of the same colour" do + board = %{ + "0,0" => %{"type" => "rook", "colour" => "white"}, + "0,5" => %{"type" => "king", "colour" => "white"}, + } + moves = Moves.available(board, {0, 0}) + + expected_moves = Enum.sort([ + {0, 1}, {0, 2}, {0, 3}, {0, 4}, + {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0}, + ]) + assert Enum.sort(moves) == expected_moves + end + + test "rook can take a piece of the opposite colour" do + board = %{ + "0,0" => %{"type" => "rook", "colour" => "white"}, + "0,5" => %{"type" => "knight", "colour" => "black"}, + } + moves = Moves.available(board, {0, 0}) + + expected_moves = Enum.sort([ + {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, + {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0}, + ]) + assert Enum.sort(moves) == expected_moves + end + def board do Chess.Board.default end