------------------------------------------------------------------------
-- |
-- Module      :  Math.Geometry.HexGridInternal
-- Copyright   :  (c) Amy de Buitléir 2012-2019
-- License     :  BSD-style
-- Maintainer  :  amy@nualeargais.ie
-- Stability   :  experimental
-- Portability :  portable
--
-- A module containing private @HexGrid@ internals. Most developers 
-- should use @HexGrid@ instead. This module is subject to change 
-- without notice.
--
------------------------------------------------------------------------
{-# LANGUAGE TypeFamilies, FlexibleContexts, DeriveGeneric #-}

module Math.Geometry.Grid.HexagonalInternal where

import Prelude hiding (null)
import Data.Function (on)
import Data.List (groupBy, sortBy)
import Data.Ord (comparing)
import GHC.Generics (Generic)
import Math.Geometry.GridInternal

data HexDirection = West | Northwest | Northeast | East | Southeast | 
                      Southwest deriving (Int -> HexDirection -> ShowS
[HexDirection] -> ShowS
HexDirection -> String
(Int -> HexDirection -> ShowS)
-> (HexDirection -> String)
-> ([HexDirection] -> ShowS)
-> Show HexDirection
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HexDirection] -> ShowS
$cshowList :: [HexDirection] -> ShowS
show :: HexDirection -> String
$cshow :: HexDirection -> String
showsPrec :: Int -> HexDirection -> ShowS
$cshowsPrec :: Int -> HexDirection -> ShowS
Show, HexDirection -> HexDirection -> Bool
(HexDirection -> HexDirection -> Bool)
-> (HexDirection -> HexDirection -> Bool) -> Eq HexDirection
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: HexDirection -> HexDirection -> Bool
$c/= :: HexDirection -> HexDirection -> Bool
== :: HexDirection -> HexDirection -> Bool
$c== :: HexDirection -> HexDirection -> Bool
Eq, (forall x. HexDirection -> Rep HexDirection x)
-> (forall x. Rep HexDirection x -> HexDirection)
-> Generic HexDirection
forall x. Rep HexDirection x -> HexDirection
forall x. HexDirection -> Rep HexDirection x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep HexDirection x -> HexDirection
$cfrom :: forall x. HexDirection -> Rep HexDirection x
Generic)

-- | An unbounded grid with hexagonal tiles
--   The grid and its indexing scheme are illustrated in the user guide,
--   available at <https://github.com/mhwombat/grid/wiki>.
data UnboundedHexGrid = UnboundedHexGrid deriving (Int -> UnboundedHexGrid -> ShowS
[UnboundedHexGrid] -> ShowS
UnboundedHexGrid -> String
(Int -> UnboundedHexGrid -> ShowS)
-> (UnboundedHexGrid -> String)
-> ([UnboundedHexGrid] -> ShowS)
-> Show UnboundedHexGrid
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UnboundedHexGrid] -> ShowS
$cshowList :: [UnboundedHexGrid] -> ShowS
show :: UnboundedHexGrid -> String
$cshow :: UnboundedHexGrid -> String
showsPrec :: Int -> UnboundedHexGrid -> ShowS
$cshowsPrec :: Int -> UnboundedHexGrid -> ShowS
Show, UnboundedHexGrid -> UnboundedHexGrid -> Bool
(UnboundedHexGrid -> UnboundedHexGrid -> Bool)
-> (UnboundedHexGrid -> UnboundedHexGrid -> Bool)
-> Eq UnboundedHexGrid
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: UnboundedHexGrid -> UnboundedHexGrid -> Bool
$c/= :: UnboundedHexGrid -> UnboundedHexGrid -> Bool
== :: UnboundedHexGrid -> UnboundedHexGrid -> Bool
$c== :: UnboundedHexGrid -> UnboundedHexGrid -> Bool
Eq, (forall x. UnboundedHexGrid -> Rep UnboundedHexGrid x)
-> (forall x. Rep UnboundedHexGrid x -> UnboundedHexGrid)
-> Generic UnboundedHexGrid
forall x. Rep UnboundedHexGrid x -> UnboundedHexGrid
forall x. UnboundedHexGrid -> Rep UnboundedHexGrid x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep UnboundedHexGrid x -> UnboundedHexGrid
$cfrom :: forall x. UnboundedHexGrid -> Rep UnboundedHexGrid x
Generic)

instance Grid UnboundedHexGrid where
  type Index UnboundedHexGrid = (Int, Int)
  type Direction UnboundedHexGrid = HexDirection
  indices :: UnboundedHexGrid -> [Index UnboundedHexGrid]
indices UnboundedHexGrid
_ = [Index UnboundedHexGrid]
forall a. HasCallStack => a
undefined
  neighbours :: UnboundedHexGrid
-> Index UnboundedHexGrid -> [Index UnboundedHexGrid]
neighbours UnboundedHexGrid
_ (x,y) = 
    [(Int
xInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1,Int
y), (Int
xInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1,Int
yInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1), (Int
x,Int
yInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1), (Int
xInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1,Int
y), (Int
xInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1,Int
yInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1), (Int
x,Int
yInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)]
  distance :: UnboundedHexGrid
-> Index UnboundedHexGrid -> Index UnboundedHexGrid -> Int
distance UnboundedHexGrid
_ (x1, y1) (x2, y2) = 
    [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int -> Int
forall a. Num a => a -> a
abs (Int
x2Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
x1), Int -> Int
forall a. Num a => a -> a
abs (Int
y2Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
y1), Int -> Int
forall a. Num a => a -> a
abs(Int
z2Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
z1)]
    where z1 :: Int
z1 = -Int
x1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
y1
          z2 :: Int
z2 = -Int
x2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
y2
  directionTo :: UnboundedHexGrid
-> Index UnboundedHexGrid
-> Index UnboundedHexGrid
-> [Direction UnboundedHexGrid]
directionTo UnboundedHexGrid
_ (x1, y1) (x2, y2) = [HexDirection] -> [HexDirection]
f1 ([HexDirection] -> [HexDirection])
-> ([HexDirection] -> [HexDirection])
-> [HexDirection]
-> [HexDirection]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [HexDirection] -> [HexDirection]
f2 ([HexDirection] -> [HexDirection])
-> ([HexDirection] -> [HexDirection])
-> [HexDirection]
-> [HexDirection]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [HexDirection] -> [HexDirection]
f3 ([HexDirection] -> [HexDirection])
-> ([HexDirection] -> [HexDirection])
-> [HexDirection]
-> [HexDirection]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [HexDirection] -> [HexDirection]
f4 ([HexDirection] -> [HexDirection])
-> ([HexDirection] -> [HexDirection])
-> [HexDirection]
-> [HexDirection]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [HexDirection] -> [HexDirection]
f5 ([HexDirection] -> [HexDirection])
-> ([HexDirection] -> [HexDirection])
-> [HexDirection]
-> [HexDirection]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [HexDirection] -> [HexDirection]
f6 ([HexDirection] -> [HexDirection])
-> [HexDirection] -> [HexDirection]
forall a b. (a -> b) -> a -> b
$ []
    where f1 :: [HexDirection] -> [HexDirection]
f1 [HexDirection]
ds =  if Int
dx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
&& Int
dz Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 then HexDirection
WestHexDirection -> [HexDirection] -> [HexDirection]
forall a. a -> [a] -> [a]
:[HexDirection]
ds else [HexDirection]
ds
          f2 :: [HexDirection] -> [HexDirection]
f2 [HexDirection]
ds =  if Int
dx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
&& Int
dy Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 then HexDirection
NorthwestHexDirection -> [HexDirection] -> [HexDirection]
forall a. a -> [a] -> [a]
:[HexDirection]
ds else [HexDirection]
ds
          f3 :: [HexDirection] -> [HexDirection]
f3 [HexDirection]
ds =  if Int
dy Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Int
dz Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 then HexDirection
NortheastHexDirection -> [HexDirection] -> [HexDirection]
forall a. a -> [a] -> [a]
:[HexDirection]
ds else [HexDirection]
ds
          f4 :: [HexDirection] -> [HexDirection]
f4 [HexDirection]
ds =  if Int
dx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Int
dz Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 then HexDirection
EastHexDirection -> [HexDirection] -> [HexDirection]
forall a. a -> [a] -> [a]
:[HexDirection]
ds else [HexDirection]
ds
          f5 :: [HexDirection] -> [HexDirection]
f5 [HexDirection]
ds =  if Int
dx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Int
dy Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 then HexDirection
SoutheastHexDirection -> [HexDirection] -> [HexDirection]
forall a. a -> [a] -> [a]
:[HexDirection]
ds else [HexDirection]
ds
          f6 :: [HexDirection] -> [HexDirection]
f6 [HexDirection]
ds =  if Int
dy Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
&& Int
dz Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 then HexDirection
SouthwestHexDirection -> [HexDirection] -> [HexDirection]
forall a. a -> [a] -> [a]
:[HexDirection]
ds else [HexDirection]
ds
          dx :: Int
dx = Int
x2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
x1
          dy :: Int
dy = Int
y2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
y1
          z1 :: Int
z1 = -Int
x1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
y1
          z2 :: Int
z2 = -Int
x2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
y2
          dz :: Int
dz = Int
z2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
z1
  contains :: UnboundedHexGrid -> Index UnboundedHexGrid -> Bool
contains UnboundedHexGrid
_ Index UnboundedHexGrid
_ = Bool
True
  null :: UnboundedHexGrid -> Bool
null UnboundedHexGrid
_ = Bool
False
  nonNull :: UnboundedHexGrid -> Bool
nonNull UnboundedHexGrid
_ = Bool
True

--
-- Hexagonal grids with hexagonal tiles
--

-- | A hexagonal grid with hexagonal tiles
--   The grid and its indexing scheme are illustrated in the user guide,
--   available at <https://github.com/mhwombat/grid/wiki>.
data HexHexGrid = HexHexGrid Int [(Int, Int)] deriving (HexHexGrid -> HexHexGrid -> Bool
(HexHexGrid -> HexHexGrid -> Bool)
-> (HexHexGrid -> HexHexGrid -> Bool) -> Eq HexHexGrid
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: HexHexGrid -> HexHexGrid -> Bool
$c/= :: HexHexGrid -> HexHexGrid -> Bool
== :: HexHexGrid -> HexHexGrid -> Bool
$c== :: HexHexGrid -> HexHexGrid -> Bool
Eq, (forall x. HexHexGrid -> Rep HexHexGrid x)
-> (forall x. Rep HexHexGrid x -> HexHexGrid) -> Generic HexHexGrid
forall x. Rep HexHexGrid x -> HexHexGrid
forall x. HexHexGrid -> Rep HexHexGrid x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep HexHexGrid x -> HexHexGrid
$cfrom :: forall x. HexHexGrid -> Rep HexHexGrid x
Generic)

instance Show HexHexGrid where show :: HexHexGrid -> String
show (HexHexGrid Int
s [(Int, Int)]
_) = String
"hexHexGrid " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
s

instance Grid HexHexGrid where
  type Index HexHexGrid = (Int, Int)
  type Direction HexHexGrid = HexDirection
  indices :: HexHexGrid -> [Index HexHexGrid]
indices (HexHexGrid Int
_ [(Int, Int)]
xs) = [(Int, Int)]
[Index HexHexGrid]
xs
  neighbours :: HexHexGrid -> Index HexHexGrid -> [Index HexHexGrid]
neighbours = UnboundedHexGrid
-> HexHexGrid -> Index HexHexGrid -> [Index HexHexGrid]
forall u g.
(Eq (Index u), Grid g, Grid u, Index g ~ Index u) =>
u -> g -> Index g -> [Index g]
neighboursBasedOn UnboundedHexGrid
UnboundedHexGrid
  distance :: HexHexGrid -> Index HexHexGrid -> Index HexHexGrid -> Int
distance = UnboundedHexGrid
-> HexHexGrid -> Index HexHexGrid -> Index HexHexGrid -> Int
forall g u.
(Eq (Index g), Grid g, Grid u, Index g ~ Index u) =>
u -> g -> Index g -> Index g -> Int
distanceBasedOn UnboundedHexGrid
UnboundedHexGrid
  directionTo :: HexHexGrid
-> Index HexHexGrid -> Index HexHexGrid -> [Direction HexHexGrid]
directionTo = UnboundedHexGrid
-> HexHexGrid
-> Index HexHexGrid
-> Index HexHexGrid
-> [Direction HexHexGrid]
forall g u.
(Eq (Index g), Eq (Direction g), Grid g, Grid u, Index g ~ Index u,
 Direction g ~ Direction u) =>
u -> g -> Index g -> Index g -> [Direction g]
directionToBasedOn UnboundedHexGrid
UnboundedHexGrid
  contains :: HexHexGrid -> Index HexHexGrid -> Bool
contains HexHexGrid
g (x,y) = -Int
Size HexHexGrid
s Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
x Bool -> Bool -> Bool
&& Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
Size HexHexGrid
s Bool -> Bool -> Bool
&& Bool
check
    where s :: Size HexHexGrid
s = HexHexGrid -> Size HexHexGrid
forall g. FiniteGrid g => g -> Size g
size HexHexGrid
g
          check :: Bool
check = if Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0
                    then -Int
Size HexHexGrid
sInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
y Bool -> Bool -> Bool
&& Int
y Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
Size HexHexGrid
s
                    else -Int
Size HexHexGrid
s Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
y Bool -> Bool -> Bool
&& Int
y Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
Size HexHexGrid
sInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
x

instance FiniteGrid HexHexGrid where
  type Size HexHexGrid = Int
  size :: HexHexGrid -> Size HexHexGrid
size (HexHexGrid Int
s [(Int, Int)]
_) = Int
Size HexHexGrid
s
  maxPossibleDistance :: HexHexGrid -> Int
maxPossibleDistance g :: HexHexGrid
g@(HexHexGrid Int
s [(Int, Int)]
_) = HexHexGrid -> Index HexHexGrid -> Index HexHexGrid -> Int
forall g. Grid g => g -> Index g -> Index g -> Int
distance HexHexGrid
g (-Int
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1,Int
0) (Int
sInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1,Int
0)

instance BoundedGrid HexHexGrid where
  tileSideCount :: HexHexGrid -> Int
tileSideCount HexHexGrid
_ = Int
6
  boundary :: HexHexGrid -> [Index HexHexGrid]
boundary HexHexGrid
g = 
    [(Int, Int)]
north [(Int, Int)] -> [(Int, Int)] -> [(Int, Int)]
forall a. [a] -> [a] -> [a]
++ [(Int, Int)]
northeast [(Int, Int)] -> [(Int, Int)] -> [(Int, Int)]
forall a. [a] -> [a] -> [a]
++ [(Int, Int)]
southeast [(Int, Int)] -> [(Int, Int)] -> [(Int, Int)]
forall a. [a] -> [a] -> [a]
++ [(Int, Int)]
south [(Int, Int)] -> [(Int, Int)] -> [(Int, Int)]
forall a. [a] -> [a] -> [a]
++ [(Int, Int)]
southwest [(Int, Int)] -> [(Int, Int)] -> [(Int, Int)]
forall a. [a] -> [a] -> [a]
++ [(Int, Int)]
northwest
    where s :: Size HexHexGrid
s = HexHexGrid -> Size HexHexGrid
forall g. FiniteGrid g => g -> Size g
size HexHexGrid
g
          north :: [(Int, Int)]
north = [(Int
k,Int
Size HexHexGrid
sInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) | Int
k <- [-Int
Size HexHexGrid
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1,-Int
Size HexHexGrid
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2..Int
0]]
          northeast :: [(Int, Int)]
northeast = [(Int
k,Int
Size HexHexGrid
sInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
k) | Int
k <- [Int
1,Int
2..Int
Size HexHexGrid
sInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]]
          southeast :: [(Int, Int)]
southeast = [(Int
Size HexHexGrid
sInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1,Int
k) | Int
k <- [-Int
1,-Int
2..(-Int
Size HexHexGrid
s)Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1]]
          south :: [(Int, Int)]
south = [(Int
k,(-Int
Size HexHexGrid
s)Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) | Int
k <- [Int
Size HexHexGrid
sInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2,Int
Size HexHexGrid
sInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
3..Int
0]]
          southwest :: [(Int, Int)]
southwest = [(Int
k,(-Int
Size HexHexGrid
s)Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
k) | Int
k <- [-Int
1,-Int
2..(-Int
Size HexHexGrid
s)Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1]]
          northwest :: [(Int, Int)]
northwest = [(-Int
Size HexHexGrid
sInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1,Int
k) | Int
k <- [Int
1,Int
2..Int
Size HexHexGrid
sInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2]]
  centre :: HexHexGrid -> [Index HexHexGrid]
centre HexHexGrid
_ = [(Int
0,Int
0)]

-- | @'hexHexGrid' s@ returns a grid of hexagonal shape, with
--   sides of length @s@, using hexagonal tiles. If @s@ is nonnegative, the 
--   resulting grid will have @3*s*(s-1) + 1@ tiles. Otherwise, the resulting 
--   grid will be null and the list of indices will be null.
hexHexGrid :: Int -> HexHexGrid
hexHexGrid :: Int -> HexHexGrid
hexHexGrid Int
r = Int -> [(Int, Int)] -> HexHexGrid
HexHexGrid Int
r [(Int
x, Int
y) | Int
x <- [-Int
rInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1..Int
rInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1], Int
y <- Int -> [Int]
f Int
x]
  where f :: Int -> [Int]
f Int
x = if Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 then [Int
1Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
rInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
x .. Int
rInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1] else [Int
1Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
r .. Int
rInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
x]

--
-- Parallelogrammatical grids with hexagonal tiles
--

-- | A parallelogramatical grid with hexagonal tiles
--   The grid and its indexing scheme are illustrated in the user guide,
--   available at <https://github.com/mhwombat/grid/wiki>.
data ParaHexGrid = ParaHexGrid (Int, Int) [(Int, Int)]
  deriving (ParaHexGrid -> ParaHexGrid -> Bool
(ParaHexGrid -> ParaHexGrid -> Bool)
-> (ParaHexGrid -> ParaHexGrid -> Bool) -> Eq ParaHexGrid
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ParaHexGrid -> ParaHexGrid -> Bool
$c/= :: ParaHexGrid -> ParaHexGrid -> Bool
== :: ParaHexGrid -> ParaHexGrid -> Bool
$c== :: ParaHexGrid -> ParaHexGrid -> Bool
Eq, (forall x. ParaHexGrid -> Rep ParaHexGrid x)
-> (forall x. Rep ParaHexGrid x -> ParaHexGrid)
-> Generic ParaHexGrid
forall x. Rep ParaHexGrid x -> ParaHexGrid
forall x. ParaHexGrid -> Rep ParaHexGrid x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ParaHexGrid x -> ParaHexGrid
$cfrom :: forall x. ParaHexGrid -> Rep ParaHexGrid x
Generic)

instance Show ParaHexGrid where 
  show :: ParaHexGrid -> String
show (ParaHexGrid (Int
r,Int
c) [(Int, Int)]
_) = String
"paraHexGrid " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
r String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
c

instance Grid ParaHexGrid where
  type Index ParaHexGrid = (Int, Int)
  type Direction ParaHexGrid = HexDirection
  indices :: ParaHexGrid -> [Index ParaHexGrid]
indices (ParaHexGrid (Int, Int)
_ [(Int, Int)]
xs) = [(Int, Int)]
[Index ParaHexGrid]
xs
  neighbours :: ParaHexGrid -> Index ParaHexGrid -> [Index ParaHexGrid]
neighbours = UnboundedHexGrid
-> ParaHexGrid -> Index ParaHexGrid -> [Index ParaHexGrid]
forall u g.
(Eq (Index u), Grid g, Grid u, Index g ~ Index u) =>
u -> g -> Index g -> [Index g]
neighboursBasedOn UnboundedHexGrid
UnboundedHexGrid
  distance :: ParaHexGrid -> Index ParaHexGrid -> Index ParaHexGrid -> Int
distance = UnboundedHexGrid
-> ParaHexGrid -> Index ParaHexGrid -> Index ParaHexGrid -> Int
forall g u.
(Eq (Index g), Grid g, Grid u, Index g ~ Index u) =>
u -> g -> Index g -> Index g -> Int
distanceBasedOn UnboundedHexGrid
UnboundedHexGrid
  directionTo :: ParaHexGrid
-> Index ParaHexGrid
-> Index ParaHexGrid
-> [Direction ParaHexGrid]
directionTo = UnboundedHexGrid
-> ParaHexGrid
-> Index ParaHexGrid
-> Index ParaHexGrid
-> [Direction ParaHexGrid]
forall g u.
(Eq (Index g), Eq (Direction g), Grid g, Grid u, Index g ~ Index u,
 Direction g ~ Direction u) =>
u -> g -> Index g -> Index g -> [Direction g]
directionToBasedOn UnboundedHexGrid
UnboundedHexGrid
  contains :: ParaHexGrid -> Index ParaHexGrid -> Bool
contains ParaHexGrid
g (x,y) = Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
x Bool -> Bool -> Bool
&& Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
c Bool -> Bool -> Bool
&& Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
y Bool -> Bool -> Bool
&& Int
y Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
r
    where (Int
r,Int
c) = ParaHexGrid -> Size ParaHexGrid
forall g. FiniteGrid g => g -> Size g
size ParaHexGrid
g

instance FiniteGrid ParaHexGrid where
  type Size ParaHexGrid = (Int, Int)
  size :: ParaHexGrid -> Size ParaHexGrid
size (ParaHexGrid (Int, Int)
s [(Int, Int)]
_) = (Int, Int)
Size ParaHexGrid
s
  maxPossibleDistance :: ParaHexGrid -> Int
maxPossibleDistance g :: ParaHexGrid
g@(ParaHexGrid (Int
r,Int
c) [(Int, Int)]
_) = 
    ParaHexGrid -> Index ParaHexGrid -> Index ParaHexGrid -> Int
forall g. Grid g => g -> Index g -> Index g -> Int
distance ParaHexGrid
g (Int
0,Int
0) (Int
cInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1,Int
rInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)

instance BoundedGrid ParaHexGrid where
  tileSideCount :: ParaHexGrid -> Int
tileSideCount ParaHexGrid
_ = Int
6
  boundary :: ParaHexGrid -> [Index ParaHexGrid]
boundary ParaHexGrid
g = (Int, Int) -> [(Int, Int)]
forall r c.
(Enum r, Enum c, Num r, Num c, Ord r, Ord c) =>
(r, c) -> [(c, r)]
cartesianIndices ((Int, Int) -> [(Int, Int)])
-> (ParaHexGrid -> (Int, Int)) -> ParaHexGrid -> [(Int, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParaHexGrid -> (Int, Int)
forall g. FiniteGrid g => g -> Size g
size (ParaHexGrid -> [(Int, Int)]) -> ParaHexGrid -> [(Int, Int)]
forall a b. (a -> b) -> a -> b
$ ParaHexGrid
g
  centre :: ParaHexGrid -> [Index ParaHexGrid]
centre ParaHexGrid
g | [[((Int, Int), Int)]] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[((Int, Int), Int)]]
xs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1  = (((Int, Int), Int) -> (Int, Int))
-> [((Int, Int), Int)] -> [(Int, Int)]
forall a b. (a -> b) -> [a] -> [b]
map ((Int, Int), Int) -> (Int, Int)
forall a b. (a, b) -> a
fst ([((Int, Int), Int)] -> [(Int, Int)])
-> ([[((Int, Int), Int)]] -> [((Int, Int), Int)])
-> [[((Int, Int), Int)]]
-> [(Int, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[((Int, Int), Int)]] -> [((Int, Int), Int)]
forall a. [a] -> a
head ([[((Int, Int), Int)]] -> [(Int, Int)])
-> [[((Int, Int), Int)]] -> [(Int, Int)]
forall a b. (a -> b) -> a -> b
$ [[((Int, Int), Int)]]
xs
           | [[((Int, Int), Int)]] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[((Int, Int), Int)]]
xs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2  = (((Int, Int), Int) -> (Int, Int))
-> [((Int, Int), Int)] -> [(Int, Int)]
forall a b. (a -> b) -> [a] -> [b]
map ((Int, Int), Int) -> (Int, Int)
forall a b. (a, b) -> a
fst ([((Int, Int), Int)] -> [(Int, Int)])
-> ([[((Int, Int), Int)]] -> [((Int, Int), Int)])
-> [[((Int, Int), Int)]]
-> [(Int, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[((Int, Int), Int)]] -> [((Int, Int), Int)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[((Int, Int), Int)]] -> [(Int, Int)])
-> [[((Int, Int), Int)]] -> [(Int, Int)]
forall a b. (a -> b) -> a -> b
$ [[((Int, Int), Int)]]
xs
           | [[((Int, Int), Int)]] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[((Int, Int), Int)]]
xs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
3  = (((Int, Int), Int) -> (Int, Int))
-> [((Int, Int), Int)] -> [(Int, Int)]
forall a b. (a -> b) -> [a] -> [b]
map ((Int, Int), Int) -> (Int, Int)
forall a b. (a, b) -> a
fst ([((Int, Int), Int)] -> [(Int, Int)])
-> ([[((Int, Int), Int)]] -> [((Int, Int), Int)])
-> [[((Int, Int), Int)]]
-> [(Int, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[((Int, Int), Int)]] -> [((Int, Int), Int)]
forall a. [a] -> a
head ([[((Int, Int), Int)]] -> [((Int, Int), Int)])
-> ([[((Int, Int), Int)]] -> [[((Int, Int), Int)]])
-> [[((Int, Int), Int)]]
-> [((Int, Int), Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [[((Int, Int), Int)]] -> [[((Int, Int), Int)]]
forall a. Int -> [a] -> [a]
drop Int
1 ([[((Int, Int), Int)]] -> [(Int, Int)])
-> [[((Int, Int), Int)]] -> [(Int, Int)]
forall a b. (a -> b) -> a -> b
$ [[((Int, Int), Int)]]
xs
           | Bool
otherwise      = String -> [(Int, Int)]
forall a. HasCallStack => String -> a
error String
"logic error"
    where xs :: [[((Int, Int), Int)]]
xs = (((Int, Int), Int) -> ((Int, Int), Int) -> Bool)
-> [((Int, Int), Int)] -> [[((Int, Int), Int)]]
forall a. (a -> a -> Bool) -> [a] -> [[a]]
groupBy (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Int -> Int -> Bool)
-> (((Int, Int), Int) -> Int)
-> ((Int, Int), Int)
-> ((Int, Int), Int)
-> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` ((Int, Int), Int) -> Int
forall a b. (a, b) -> b
snd) ([((Int, Int), Int)] -> [[((Int, Int), Int)]])
-> (ParaHexGrid -> [((Int, Int), Int)])
-> ParaHexGrid
-> [[((Int, Int), Int)]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (((Int, Int), Int) -> ((Int, Int), Int) -> Ordering)
-> [((Int, Int), Int)] -> [((Int, Int), Int)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ((((Int, Int), Int) -> Int)
-> ((Int, Int), Int) -> ((Int, Int), Int) -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing ((Int, Int), Int) -> Int
forall a b. (a, b) -> b
snd)
                 ([((Int, Int), Int)] -> [((Int, Int), Int)])
-> (ParaHexGrid -> [((Int, Int), Int)])
-> ParaHexGrid
-> [((Int, Int), Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, Int) -> ((Int, Int), Int))
-> [(Int, Int)] -> [((Int, Int), Int)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Int, Int)
a -> ((Int, Int)
a,(Int, Int) -> Int
forall a b. (a, b) -> a
fst (Int, Int)
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int, Int) -> Int
forall a b. (a, b) -> b
snd (Int, Int)
a))
                 ([(Int, Int)] -> [((Int, Int), Int)])
-> (ParaHexGrid -> [(Int, Int)])
-> ParaHexGrid
-> [((Int, Int), Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Int) -> [(Int, Int)]
cartesianCentre ((Int, Int) -> [(Int, Int)])
-> (ParaHexGrid -> (Int, Int)) -> ParaHexGrid -> [(Int, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParaHexGrid -> (Int, Int)
forall g. FiniteGrid g => g -> Size g
size (ParaHexGrid -> [[((Int, Int), Int)]])
-> ParaHexGrid -> [[((Int, Int), Int)]]
forall a b. (a -> b) -> a -> b
$ ParaHexGrid
g

-- | @'paraHexGrid' r c@ returns a grid in the shape of a 
--   parallelogram with @r@ rows and @c@ columns, using hexagonal tiles. If 
--   @r@ and @c@ are both nonnegative, the resulting grid will have @r*c@ tiles.
--   Otherwise, the resulting grid will be null and the list of indices will 
--   be null.
paraHexGrid :: Int -> Int -> ParaHexGrid
paraHexGrid :: Int -> Int -> ParaHexGrid
paraHexGrid Int
r Int
c = 
  (Int, Int) -> [(Int, Int)] -> ParaHexGrid
ParaHexGrid (Int
r,Int
c) [(Int
x, Int
y) | Int
x <- [Int
0..Int
cInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1], Int
y <- [Int
0..Int
rInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]]