       end)
 
     if any_errors? do
-      {:error, :invalid_coord}
+      {:error, :badarg}
     else
       parsed_coords
       |> Keyword.values

  @doc """
  Places a bomb on each of the board squares at the given coordinates.

  Returns `:ok` on success, or `{:error, :invalid_coord}` on failure.
  """
  @spec place_bombs(pid, [coord]) :: :ok | {:error, :invalid_coord}
  def place_bombs(pid, coords) do
    parsed_coords = coords |> Enum.map(&parse_coord(pid, &1))

    any_errors? =
      Enum.any?(parsed_coords, fn coord ->

      |> String.rstrip
      |> String.to_integer
    catch
      :error, :badarg -> {:error, :badarg}
    else
      row -> parse_coord({row, letter})
    end
  end

  def parse_coord({row, letter}) when is_integer(row) and is_binary(letter) do
    col = letter_to_col(letter)
    case col do
      :error ->
        {:error, :badarg}
      _ ->
        parse_coord({row, col})
    end
  end

  def parse_coord({row, col}) when is_integer(row) and is_integer(col) do
    if Enum.all?([row, col], &(&1 >= 0)) do
      {:ok, {row, col}}
    else
      {:error, :badarg}
    end
  end

  def parse_coord(_coord), do: {:error, :badarg}

  @spec letter_to_col(String.t) :: pos_integer | :error
  defp letter_to_col(string) when byte_size(string) === 1 do
    normalized = String.downcase(string)
    [char] = normalized |> to_char_list

    char - ?a + 1
  end
  defp letter_to_col(_), do: :error

  @doc """
  Validates if the given coordinate points to a square on the board.
  """
  @spec valid_square?(pid, coord) :: boolean
  def valid_square?(pid, coord) do
    result =
      with {:ok, coord} <- parse_coord(coord),
           grid = get(pid).grid,
        do: Grid.valid_coord?(grid, coord)

    case result do
      {:error, _} -> false
      _ -> result
    end
  end

  # Reveal all the squares on a `board` for debugging.
  @doc false
