module BishBosh.Direction.Direction(
ArrayByDirection,
Direction(),
parallels,
s,
n,
w,
e,
diagonals,
sw,
se,
nw,
ne,
opposites,
attackDirectionsForPawn,
listArrayByDirection,
areAligned
) where
import Control.Arrow((&&&), (|||), (+++))
import qualified BishBosh.Colour.LogicalColour as Colour.LogicalColour
import qualified BishBosh.Direction.Diagonal as Direction.Diagonal
import qualified BishBosh.Direction.Parallel as Direction.Parallel
import qualified BishBosh.Property.FixedMembership as Property.FixedMembership
import qualified BishBosh.Property.Opposable as Property.Opposable
import qualified BishBosh.Property.Orientated as Property.Orientated
import qualified BishBosh.Property.Reflectable as Property.Reflectable
import qualified BishBosh.Property.Rotatable as Property.Rotatable
import qualified Control.DeepSeq
import qualified Data.Array.IArray
import qualified Data.List.Extra
newtype Direction = MkDirection (Either Direction.Parallel.Parallel Direction.Diagonal.Diagonal) deriving (Direction -> Direction -> Bool
(Direction -> Direction -> Bool)
-> (Direction -> Direction -> Bool) -> Eq Direction
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Direction -> Direction -> Bool
$c/= :: Direction -> Direction -> Bool
== :: Direction -> Direction -> Bool
$c== :: Direction -> Direction -> Bool
Eq, Eq Direction
Eq Direction
-> (Direction -> Direction -> Ordering)
-> (Direction -> Direction -> Bool)
-> (Direction -> Direction -> Bool)
-> (Direction -> Direction -> Bool)
-> (Direction -> Direction -> Bool)
-> (Direction -> Direction -> Direction)
-> (Direction -> Direction -> Direction)
-> Ord Direction
Direction -> Direction -> Bool
Direction -> Direction -> Ordering
Direction -> Direction -> Direction
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Direction -> Direction -> Direction
$cmin :: Direction -> Direction -> Direction
max :: Direction -> Direction -> Direction
$cmax :: Direction -> Direction -> Direction
>= :: Direction -> Direction -> Bool
$c>= :: Direction -> Direction -> Bool
> :: Direction -> Direction -> Bool
$c> :: Direction -> Direction -> Bool
<= :: Direction -> Direction -> Bool
$c<= :: Direction -> Direction -> Bool
< :: Direction -> Direction -> Bool
$c< :: Direction -> Direction -> Bool
compare :: Direction -> Direction -> Ordering
$ccompare :: Direction -> Direction -> Ordering
$cp1Ord :: Eq Direction
Ord)
instance Control.DeepSeq.NFData Direction where
rnf :: Direction -> ()
rnf (MkDirection Either Parallel Diagonal
d) = Parallel -> ()
forall a. NFData a => a -> ()
Control.DeepSeq.rnf (Parallel -> ())
-> (Diagonal -> ()) -> Either Parallel Diagonal -> ()
forall (a :: * -> * -> *) b d c.
ArrowChoice a =>
a b d -> a c d -> a (Either b c) d
||| Diagonal -> ()
forall a. NFData a => a -> ()
Control.DeepSeq.rnf (Either Parallel Diagonal -> ()) -> Either Parallel Diagonal -> ()
forall a b. (a -> b) -> a -> b
$ Either Parallel Diagonal
d
instance Show Direction where
showsPrec :: Int -> Direction -> ShowS
showsPrec Int
precedence (MkDirection Either Parallel Diagonal
d) = Int -> Parallel -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
precedence (Parallel -> ShowS)
-> (Diagonal -> ShowS) -> Either Parallel Diagonal -> ShowS
forall (a :: * -> * -> *) b d c.
ArrowChoice a =>
a b d -> a c d -> a (Either b c) d
||| Int -> Diagonal -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
precedence (Either Parallel Diagonal -> ShowS)
-> Either Parallel Diagonal -> ShowS
forall a b. (a -> b) -> a -> b
$ Either Parallel Diagonal
d
instance Read Direction where
readsPrec :: Int -> ReadS Direction
readsPrec Int
precedence String
string = let
s' :: String
s' = ShowS
Data.List.Extra.trimStart String
string
in case Int -> ReadS Diagonal
forall a. Read a => Int -> ReadS a
readsPrec Int
precedence String
s' of
[(Diagonal
diagonal, String
s'')] -> [(Either Parallel Diagonal -> Direction
MkDirection (Either Parallel Diagonal -> Direction)
-> Either Parallel Diagonal -> Direction
forall a b. (a -> b) -> a -> b
$ Diagonal -> Either Parallel Diagonal
forall a b. b -> Either a b
Right Diagonal
diagonal, String
s'')]
[(Diagonal, String)]
_ -> case Int -> ReadS Parallel
forall a. Read a => Int -> ReadS a
readsPrec Int
precedence String
s' of
[(Parallel
parallel, String
s'')] -> [(Either Parallel Diagonal -> Direction
MkDirection (Either Parallel Diagonal -> Direction)
-> Either Parallel Diagonal -> Direction
forall a b. (a -> b) -> a -> b
$ Parallel -> Either Parallel Diagonal
forall a b. a -> Either a b
Left Parallel
parallel, String
s'')]
[(Parallel, String)]
_ -> []
instance Property.Opposable.Opposable Direction where
getOpposite :: Direction -> Direction
getOpposite (MkDirection Either Parallel Diagonal
d) = Either Parallel Diagonal -> Direction
MkDirection (Either Parallel Diagonal -> Direction)
-> Either Parallel Diagonal -> Direction
forall a b. (a -> b) -> a -> b
$ (Parallel -> Parallel
forall a. Opposable a => a -> a
Property.Opposable.getOpposite (Parallel -> Parallel)
-> (Diagonal -> Diagonal)
-> Either Parallel Diagonal
-> Either Parallel Diagonal
forall (a :: * -> * -> *) b c b' c'.
ArrowChoice a =>
a b c -> a b' c' -> a (Either b b') (Either c c')
+++ Diagonal -> Diagonal
forall a. Opposable a => a -> a
Property.Opposable.getOpposite) Either Parallel Diagonal
d
instance Property.Orientated.Orientated Direction where
isVertical :: Direction -> Bool
isVertical (MkDirection (Left Parallel
p)) = Parallel -> Bool
forall a. Orientated a => a -> Bool
Property.Orientated.isVertical Parallel
p
isVertical Direction
_ = Bool
False
isHorizontal :: Direction -> Bool
isHorizontal (MkDirection (Left Parallel
p)) = Parallel -> Bool
forall a. Orientated a => a -> Bool
Property.Orientated.isHorizontal Parallel
p
isHorizontal Direction
_ = Bool
False
isParallel :: Direction -> Bool
isParallel (MkDirection (Left Parallel
_)) = Bool
True
isParallel Direction
_ = Bool
False
isDiagonal :: Direction -> Bool
isDiagonal (MkDirection (Right Diagonal
_)) = Bool
True
isDiagonal Direction
_ = Bool
False
isStraight :: Direction -> Bool
isStraight = Bool -> Direction -> Bool
forall a b. a -> b -> a
const Bool
True
instance Property.Reflectable.ReflectableOnX Direction where
reflectOnX :: Direction -> Direction
reflectOnX (MkDirection Either Parallel Diagonal
d) = Either Parallel Diagonal -> Direction
MkDirection (Either Parallel Diagonal -> Direction)
-> Either Parallel Diagonal -> Direction
forall a b. (a -> b) -> a -> b
$ (Parallel -> Parallel
forall a. ReflectableOnX a => a -> a
Property.Reflectable.reflectOnX (Parallel -> Parallel)
-> (Diagonal -> Diagonal)
-> Either Parallel Diagonal
-> Either Parallel Diagonal
forall (a :: * -> * -> *) b c b' c'.
ArrowChoice a =>
a b c -> a b' c' -> a (Either b b') (Either c c')
+++ Diagonal -> Diagonal
forall a. ReflectableOnX a => a -> a
Property.Reflectable.reflectOnX) Either Parallel Diagonal
d
instance Property.Reflectable.ReflectableOnY Direction where
reflectOnY :: Direction -> Direction
reflectOnY (MkDirection Either Parallel Diagonal
d) = Either Parallel Diagonal -> Direction
MkDirection (Either Parallel Diagonal -> Direction)
-> Either Parallel Diagonal -> Direction
forall a b. (a -> b) -> a -> b
$ (Parallel -> Parallel
forall a. ReflectableOnY a => a -> a
Property.Reflectable.reflectOnY (Parallel -> Parallel)
-> (Diagonal -> Diagonal)
-> Either Parallel Diagonal
-> Either Parallel Diagonal
forall (a :: * -> * -> *) b c b' c'.
ArrowChoice a =>
a b c -> a b' c' -> a (Either b b') (Either c c')
+++ Diagonal -> Diagonal
forall a. ReflectableOnY a => a -> a
Property.Reflectable.reflectOnY) Either Parallel Diagonal
d
instance Property.Rotatable.Rotatable Direction where
rotate90 :: Direction -> Direction
rotate90 Direction
direction
| Direction -> Bool
forall a. Orientated a => a -> Bool
Property.Orientated.isParallel Direction
direction = Direction
rotateParallel
| Bool
otherwise = Direction
rotateDiagonal
where
rotateParallel :: Direction
rotateParallel
| Direction -> Bool
forall a. Orientated a => a -> Bool
Property.Orientated.isVertical Direction
direction = Direction
rotateVertical
| Bool
otherwise = Direction
rotateHorizontal
where
rotateVertical :: Direction
rotateVertical
| Direction
direction Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
s = Direction
e
| Bool
otherwise = Direction
w
rotateHorizontal :: Direction
rotateHorizontal
| Direction
direction Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
w = Direction
s
| Bool
otherwise = Direction
n
rotateDiagonal :: Direction
rotateDiagonal
| Direction
direction Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
sw = Direction
se
| Direction
direction Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
se = Direction
ne
| Direction
direction Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
nw = Direction
sw
| Bool
otherwise = Direction
nw
rotate180 :: Direction -> Direction
rotate180 = Direction -> Direction
forall a. Opposable a => a -> a
Property.Opposable.getOpposite
instance Property.FixedMembership.FixedMembership Direction where
members :: [Direction]
members = [Direction]
parallels [Direction] -> [Direction] -> [Direction]
forall a. [a] -> [a] -> [a]
++ [Direction]
diagonals
instance Bounded Direction where
minBound :: Direction
minBound = [Direction] -> Direction
forall a. [a] -> a
head [Direction]
forall a. FixedMembership a => [a]
Property.FixedMembership.members
maxBound :: Direction
maxBound = [Direction] -> Direction
forall a. [a] -> a
last [Direction]
forall a. FixedMembership a => [a]
Property.FixedMembership.members
instance Data.Array.IArray.Ix Direction where
range :: (Direction, Direction) -> [Direction]
range (Direction, Direction)
_ = [Direction]
forall a. FixedMembership a => [a]
Property.FixedMembership.members
inRange :: (Direction, Direction) -> Direction -> Bool
inRange (Direction, Direction)
_ Direction
_ = Bool
True
index :: (Direction, Direction) -> Direction -> Int
index (Direction, Direction)
_ (MkDirection Either Parallel Diagonal
d) = Parallel -> Int
forall a. Enum a => a -> Int
fromEnum (Parallel -> Int)
-> (Diagonal -> Int) -> Either Parallel Diagonal -> Int
forall (a :: * -> * -> *) b d c.
ArrowChoice a =>
a b d -> a c d -> a (Either b c) d
||| (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Direction.Parallel.nParallels) (Int -> Int) -> (Diagonal -> Int) -> Diagonal -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Diagonal -> Int
forall a. Enum a => a -> Int
fromEnum (Either Parallel Diagonal -> Int)
-> Either Parallel Diagonal -> Int
forall a b. (a -> b) -> a -> b
$ Either Parallel Diagonal
d
parallels :: [Direction]
s, n, w, e :: Direction
parallels :: [Direction]
parallels@[Direction
s, Direction
n, Direction
w, Direction
e] = (Parallel -> Direction) -> [Parallel] -> [Direction]
forall a b. (a -> b) -> [a] -> [b]
map (Either Parallel Diagonal -> Direction
MkDirection (Either Parallel Diagonal -> Direction)
-> (Parallel -> Either Parallel Diagonal) -> Parallel -> Direction
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parallel -> Either Parallel Diagonal
forall a b. a -> Either a b
Left) [Parallel]
forall a. FixedMembership a => [a]
Property.FixedMembership.members
diagonals :: [Direction]
sw, se, nw, ne :: Direction
diagonals :: [Direction]
diagonals@[Direction
sw, Direction
se, Direction
nw, Direction
ne] = (Diagonal -> Direction) -> [Diagonal] -> [Direction]
forall a b. (a -> b) -> [a] -> [b]
map (Either Parallel Diagonal -> Direction
MkDirection (Either Parallel Diagonal -> Direction)
-> (Diagonal -> Either Parallel Diagonal) -> Diagonal -> Direction
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Diagonal -> Either Parallel Diagonal
forall a b. b -> Either a b
Right) [Diagonal]
forall a. FixedMembership a => [a]
Property.FixedMembership.members
opposites :: [(Direction, Direction)]
opposites :: [(Direction, Direction)]
opposites = (Direction -> (Direction, Direction))
-> [Direction] -> [(Direction, Direction)]
forall a b. (a -> b) -> [a] -> [b]
map (Direction -> Direction
forall a. a -> a
id (Direction -> Direction)
-> (Direction -> Direction) -> Direction -> (Direction, Direction)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& Direction -> Direction
forall a. Opposable a => a -> a
Property.Opposable.getOpposite) [Direction
n, Direction
ne, Direction
e, Direction
se]
attackDirectionsForPawn :: Colour.LogicalColour.LogicalColour -> [Direction]
attackDirectionsForPawn :: LogicalColour -> [Direction]
attackDirectionsForPawn LogicalColour
Colour.LogicalColour.Black = [Direction
sw, Direction
se]
attackDirectionsForPawn LogicalColour
_ = [Direction
nw, Direction
ne]
areAligned :: Direction -> Direction -> Bool
areAligned :: Direction -> Direction -> Bool
areAligned Direction
l = (Bool -> Bool -> Bool) -> (Bool, Bool) -> Bool
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Bool -> Bool -> Bool
(||) ((Bool, Bool) -> Bool)
-> (Direction -> (Bool, Bool)) -> Direction -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
l) (Direction -> Bool)
-> (Direction -> Bool) -> Direction -> (Bool, Bool)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& (Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
l) (Direction -> Bool)
-> (Direction -> Direction) -> Direction -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Direction -> Direction
forall a. Opposable a => a -> a
Property.Opposable.getOpposite)
type ArrayByDirection = Data.Array.IArray.Array Direction
listArrayByDirection :: Data.Array.IArray.IArray a e => [e] -> a Direction e
listArrayByDirection :: [e] -> a Direction e
listArrayByDirection = (Direction, Direction) -> [e] -> a Direction e
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
(i, i) -> [e] -> a i e
Data.Array.IArray.listArray (Direction
forall a. Bounded a => a
minBound, Direction
forall a. Bounded a => a
maxBound)