support boards that wrap

This commit is contained in:
Gavin McDonald
2019-01-13 15:23:39 -05:00
parent 5e537d6895
commit 7548f52252
2 changed files with 32 additions and 5 deletions

View File

@@ -1,7 +1,7 @@
defmodule Cartographer do defmodule Cartographer do
alias Cartographer.Board alias Cartographer.Board
defdelegate new_board(height, width), to: Board defdelegate new_board(height, width, wrap), to: Board
defdelegate height(board), to: Board defdelegate height(board), to: Board

View File

@@ -2,13 +2,18 @@ defmodule Cartographer.Board do
defstruct( defstruct(
tiles: %{}, tiles: %{},
height: nil, 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__{ %__MODULE__{
height: height, height: height,
width: width, width: width,
wrap: wrap,
} }
end end
@@ -16,6 +21,15 @@ defmodule Cartographer.Board do
x >= 0 and x < width and y >= 0 and y < height x >= 0 and x < width and y >= 0 and y < height
end 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 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} for x <- (center_x - range)..(center_x + range), y <- (center_y - range)..(center_y + range), do: {x, y}
end end
@@ -29,12 +43,18 @@ defmodule Cartographer.Board do
Map.get(board.tiles, {x, y}) Map.get(board.tiles, {x, y})
end 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) coordinate_range(center_x, center_y, range)
|> Enum.filter(fn({x, y}) -> in_bounds(board, x, y) end) |> Enum.filter(fn({x, y}) -> in_bounds(board, x, y) end)
|> Enum.reduce(%{}, &(Map.put(&2, &1, Map.get(board.tiles, &1)))) |> Enum.reduce(%{}, &(Map.put(&2, &1, Map.get(board.tiles, &1))))
end 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 def set(board, x, y, data) do
in_bounds(board, x, y) in_bounds(board, x, y)
|> _set(board, x, y, data) |> _set(board, x, y, data)
@@ -50,10 +70,17 @@ defmodule Cartographer.Board do
defp _set(_not_in_bounds, board, _x, _y, _data), do: board 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) coordinate_range(center_x, center_y, 1)
|> List.delete({center_x, center_y}) |> List.delete({center_x, center_y})
|> Enum.filter(fn({x, y}) -> in_bounds(board, x, y) end) |> Enum.filter(fn({x, y}) -> in_bounds(board, x, y) end)
|> Enum.reduce(%{}, &(Map.put(&2, &1, Map.get(board.tiles, &1)))) |> Enum.reduce(%{}, &(Map.put(&2, &1, Map.get(board.tiles, &1))))
end 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 end