Learning Elixir - Year One

With Elixir formatter this is better:

defmodule Example do
  @illegal_moves %{
    "Bd3" => ~w[a5 b5 c5 d3 d4 d5 e5 f5 g5 h5 Nd2 Ba3 Bb2 Bc2 Be3 Bf4 Bf5 Bg5 Bg6 Bh6]
  }
end

as that your list would not be expanded in so many lines …

Shorter:

"(" <> Enum.join(possible_line, " ") <> ") "

Optionally:

illegal_moves_map["Bd3"]

You may use pattern matching for this like:

    Enum.map(moves_list, fn
      [_one, w1 | _rest] = possible_line when w1 in ~w[e4 d4] ->
        remove_illegal_second_moves_after(possible_line, w1)

      possible_line ->
        "(" <> Enum.join(possible_line, " ") <> ") "
    end)

Much better:

        fn moves_list ->
          [move_numbering, moves_list, blacks_moves_list]
          |> Enum.zip()
          |> Enum.flat_map(&Tuple.to_list/1)
        end

scrub_moves_list/1 always returns list, so second Enum.reject/2 is not needed.

Also you can write &is_nil/1.

Finally having "(" <> Enum.join(possible_line, " ") <> ") " multiple times we may want to create a helper function for that.