diff --git a/lib/cartographer.ex b/lib/cartographer.ex index 0fdd926..93db43d 100644 --- a/lib/cartographer.ex +++ b/lib/cartographer.ex @@ -1,7 +1,7 @@ defmodule Cartographer do alias Cartographer.Board - defdelegate new_board(height, width), to: Board + defdelegate new_board(height, width, wrap), to: Board defdelegate height(board), to: Board diff --git a/lib/cartographer/board.ex b/lib/cartographer/board.ex index 3a374a9..0cbadd4 100644 --- a/lib/cartographer/board.ex +++ b/lib/cartographer/board.ex @@ -2,13 +2,18 @@ defmodule Cartographer.Board do defstruct( tiles: %{}, height: nil, - width: nil + width: nil, + wrap: false ) - def new_board(height, width) do + def new_board(height, width, :wrap), do: _new_board(height, width, true) + def new_board(height, width, :no_wrap), do: _new_board(height, width, false) + + defp _new_board(height, width, wrap) do %__MODULE__{ height: height, width: width, + wrap: wrap, } end @@ -16,6 +21,15 @@ defmodule Cartographer.Board do x >= 0 and x < width and y >= 0 and y < height end + def teleport(%__MODULE__{:height => height, :width => width}, x, y) do + {_teleport(x, width), _teleport(y, height)} + end + + defp _teleport(n, range) when n >= range, do: rem(n, range) + defp _teleport(n, range) when rem(n, range) == 0, do: 0 + defp _teleport(n, range) when n < 0, do: range + rem(n, range) + defp _teleport(n, _range), do: n + def coordinate_range(center_x, center_y, range) do for x <- (center_x - range)..(center_x + range), y <- (center_y - range)..(center_y + range), do: {x, y} end @@ -29,12 +43,18 @@ defmodule Cartographer.Board do Map.get(board.tiles, {x, y}) end - def get(board, center_x, center_y, range) do + def get(board = %{wrap: false}, center_x, center_y, range) do coordinate_range(center_x, center_y, range) |> Enum.filter(fn({x, y}) -> in_bounds(board, x, y) end) |> Enum.reduce(%{}, &(Map.put(&2, &1, Map.get(board.tiles, &1)))) end + def get(board = %{wrap: true}, center_x, center_y, range) do + coordinate_range(center_x, center_y, range) + |> Enum.map(fn({x, y}) -> teleport(board, x, y) end) + |> Enum.reduce(%{}, &(Map.put(&2, &1, Map.get(board.tiles, &1)))) + end + def set(board, x, y, data) do in_bounds(board, x, y) |> _set(board, x, y, data) @@ -50,10 +70,17 @@ defmodule Cartographer.Board do defp _set(_not_in_bounds, board, _x, _y, _data), do: board - def neighbors(board, center_x, center_y) do + def neighbors(board = %{wrap: false}, center_x, center_y) do coordinate_range(center_x, center_y, 1) |> List.delete({center_x, center_y}) |> Enum.filter(fn({x, y}) -> in_bounds(board, x, y) end) |> Enum.reduce(%{}, &(Map.put(&2, &1, Map.get(board.tiles, &1)))) end + + def neighbors(board = %{wrap: true}, center_x, center_y) do + coordinate_range(center_x, center_y, 1) + |> List.delete({center_x, center_y}) + |> Enum.map(fn({x, y}) -> teleport(board, x, y) end) + |> Enum.reduce(%{}, &(Map.put(&2, &1, Map.get(board.tiles, &1)))) + end end