defmodule Cartographer.Board do defstruct( tiles: %{}, height: nil, width: nil ) def new_board(height, width) do %__MODULE__{ height: height, width: width, } end def in_bounds(%__MODULE__{:height => height, :width => width}, x, y) do x >= 0 and x < width and y >= 0 and y < height end 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 def height(board), do: board.height def width(board), do: board.width def get(board), do: board def get(board, x, y) do Map.get(board.tiles, {x, y}) end def get(board, 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 set(board, x, y, data) do in_bounds(board, x, y) |> _set(board, x, y, data) end defp _set(_in_bounds = true, board, x, y, data) do tiles = board.tiles |> Map.put({x, y}, data) board |> Map.put(:tiles, tiles) end defp _set(_not_in_bounds, board, _x, _y, _data), do: board def neighbors(board, 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 end