Current section
Files
Jump to
Current section
Files
lib/hexgrid.ex
defmodule Hextille.HexGrid do
require Integer
alias Hextille.Offset
alias Hextille.Cube
@moduledoc """
Module for creating HexGrids
"""
@doc ~S"""
Returns a MapSet containing grid of `row` rows and `col` columns of
hexagon tiles in Cube coordinates.
Top left corner of the grid is at %Cube{q: 0, r: 0, s: 0}, unless offset is shifted.
"""
def create(rows, columns, offset_col \\ 0, offset_row \\ 0) do
create_grid(MapSet.new, rows, columns, offset_col, offset_row)
end
@doc ~S"""
Finds the columns and rows representing boundaries of a MapSet.
iex> a = HexGrid.create(4, 4, -2, -2)
iex> b = HexGrid.create(4, 4, -3, -5)
iex> HexGrid.boundaries(a)
%{max_col: 2, max_row: 2, min_col: -2, min_row: -2}
iex> HexGrid.boundaries(b)
%{max_col: 1, max_row: -1, min_col: -3, min_row: -5}
"""
def boundaries(%MapSet{} = mapset) do
%{:min_col => mapset |> min_col,
:max_col => mapset |> max_col,
:min_row => mapset |> min_row,
:max_row => mapset |> max_row}
end
defp min_col(%MapSet{} = mapset), do: Enum.min_by(cube_to_offset_mapset(mapset), fn(x) -> x.col end).col
defp max_col(%MapSet{} = mapset), do: Enum.max_by(cube_to_offset_mapset(mapset), fn(x) -> x.col end).col
defp min_row(%MapSet{} = mapset), do: Enum.min_by(cube_to_offset_mapset(mapset), fn(x) -> x.row end).row
defp max_row(%MapSet{} = mapset), do: Enum.max_by(cube_to_offset_mapset(mapset), fn(x) -> x.row end).row
@doc ~S"""
Checks if hexagon has any neighbour in direction at MapSet
iex> h = HexGrid.create(4, 4, -2, -2)
iex> HexGrid.has_neighbour(h, %Cube{q: 1, r: -2, s: 1}, :east)
true
iex> HexGrid.has_neighbour(h, %Cube{q: 1, r: -2, s: 1}, :north_east)
false
"""
def has_neighbour(%MapSet{} = mapset, %Cube{} = h, direction) do
mapset
|> MapSet.member?(Cube.neighbour(h, direction))
end
@doc ~S"""
Checks if hexagon has any neighbours in MapSet
iex> h = HexGrid.create(4, 4, -2, -2)
iex> HexGrid.has_neighbour(h, %Cube{q: 1, r: -2, s: 1})
%{east: true, north_east: false, north_west: false, south_east: true,
south_west: true, west: true}
"""
def has_neighbour(%MapSet{} = mapset, %Cube{} = h) do
%{:north_east => has_neighbour(mapset, h, :north_east),
:east => has_neighbour(mapset, h, :east),
:south_east => has_neighbour(mapset, h, :south_east),
:south_west => has_neighbour(mapset, h, :south_west),
:west => has_neighbour(mapset, h, :west),
:north_west => has_neighbour(mapset, h, :north_west)}
end
defp create_grid(mapset, rows, _columns, _offset_col, _offset_row) when rows < 0 do
mapset
end
defp create_grid(mapset, rows, columns, offset_col, offset_row) do
mapset = create_row(mapset, rows, columns, offset_col, offset_row)
create_grid(mapset, rows - 1, columns, offset_col, offset_row)
end
defp create_row(mapset, _rows, columns, _offset_col, _offset_row) when columns < 0 do
mapset
end
defp create_row(mapset, rows, columns, offset_col, offset_row) do
hexagon = Offset.roffset_to_cube(%Offset{
col: columns + offset_col, row: rows + offset_row})
mapset
|> MapSet.put(hexagon)
|> create_row(rows, columns - 1, offset_col, offset_row)
end
defp cube_to_offset_mapset(%MapSet{} = mapset) do
Enum.map(mapset, fn(h) -> Offset.roffset_from_cube(h) end)
end
end