{-# LANGUAGE CPP #-}
module BishBosh.Cartesian.Coordinates(
Coordinates(
getX,
getY
),
ArrayByCoordinates,
#ifdef USE_UNBOXED_ARRAYS
UArrayByCoordinates,
#endif
tag,
topLeft,
bottomRight,
nSquares,
extrapolate,
applyAlongDirectionsFrom,
interpolate,
getLogicalColourOfSquare,
kingsStartingCoordinates,
rooksStartingCoordinates,
measureDistance,
translate,
maybeTranslate,
translateX,
maybeTranslateX,
translateY,
maybeTranslateY,
getAdjacents,
advance,
retreat,
maybeRetreat,
mkCoordinates,
mkMaybeCoordinates,
mkRelativeCoordinates,
listArrayByCoordinates,
arrayByCoordinates,
isPawnsFirstRank,
isEnPassantRank,
areSquaresIsochromatic
) where
import Control.Arrow((&&&), (***))
import Data.Array.IArray((!))
import qualified BishBosh.Cartesian.Abscissa as Cartesian.Abscissa
import qualified BishBosh.Cartesian.Ordinate as Cartesian.Ordinate
import qualified BishBosh.Colour.LogicalColour as Colour.LogicalColour
import qualified BishBosh.Colour.LogicalColourOfSquare as Colour.LogicalColourOfSquare
import qualified BishBosh.Direction.Direction as Direction.Direction
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 BishBosh.Type.Count as Type.Count
import qualified BishBosh.Type.Length as Type.Length
import qualified Control.Arrow
import qualified Control.DeepSeq
import qualified Control.Exception
import qualified Data.Array.IArray
import qualified Data.Foldable
import qualified Data.List
import qualified Data.Map as Map
import qualified Data.Maybe
#ifdef USE_PARALLEL
import qualified Control.Parallel.Strategies
#endif
#ifdef USE_UNBOXED_ARRAYS
import qualified Data.Array.Unboxed
#endif
tag :: String
tag :: String
tag = String
"coordinates"
data Coordinates = MkCoordinates {
Coordinates -> X
getX :: ! Type.Length.X,
Coordinates -> X
getY :: ! Type.Length.Y
} deriving Coordinates -> Coordinates -> Bool
(Coordinates -> Coordinates -> Bool)
-> (Coordinates -> Coordinates -> Bool) -> Eq Coordinates
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Coordinates -> Coordinates -> Bool
$c/= :: Coordinates -> Coordinates -> Bool
== :: Coordinates -> Coordinates -> Bool
$c== :: Coordinates -> Coordinates -> Bool
Eq
instance Bounded Coordinates where
minBound :: Coordinates
minBound = MkCoordinates :: X -> X -> Coordinates
MkCoordinates {
getX :: X
getX = X
Cartesian.Abscissa.xMin,
getY :: X
getY = X
Cartesian.Ordinate.yMin
}
maxBound :: Coordinates
maxBound = MkCoordinates :: X -> X -> Coordinates
MkCoordinates {
getX :: X
getX = X
Cartesian.Abscissa.xMax,
getY :: X
getY = X
Cartesian.Ordinate.yMax
}
instance Control.DeepSeq.NFData Coordinates where
rnf :: Coordinates -> ()
rnf MkCoordinates { getX :: Coordinates -> X
getX = X
x, getY :: Coordinates -> X
getY = X
y } = (X, X) -> ()
forall a. NFData a => a -> ()
Control.DeepSeq.rnf (X
x, X
y)
instance Data.Array.IArray.Ix Coordinates where
range :: (Coordinates, Coordinates) -> [Coordinates]
range (Coordinates
lower, Coordinates
upper) = Bool -> [Coordinates] -> [Coordinates]
forall a. (?callStack::CallStack) => Bool -> a -> a
Control.Exception.assert (Coordinates
lower Coordinates -> Coordinates -> Bool
forall a. Eq a => a -> a -> Bool
== Coordinates
forall a. Bounded a => a
minBound Bool -> Bool -> Bool
&& Coordinates
upper Coordinates -> Coordinates -> Bool
forall a. Eq a => a -> a -> Bool
== Coordinates
forall a. Bounded a => a
maxBound) [Coordinates]
forall a. FixedMembership a => [a]
Property.FixedMembership.members
inRange :: (Coordinates, Coordinates) -> Coordinates -> Bool
inRange (Coordinates
lower, Coordinates
upper) Coordinates
coordinates = Bool -> Bool -> Bool
forall a. (?callStack::CallStack) => Bool -> a -> a
Control.Exception.assert (Coordinates
coordinates Coordinates -> Coordinates -> Bool
forall a. Ord a => a -> a -> Bool
>= Coordinates
lower Bool -> Bool -> Bool
&& Coordinates
coordinates Coordinates -> Coordinates -> Bool
forall a. Ord a => a -> a -> Bool
<= Coordinates
upper) Bool
True
index :: (Coordinates, Coordinates) -> Coordinates -> X
index (Coordinates
lower, Coordinates
upper) = Bool -> X -> X
forall a. (?callStack::CallStack) => Bool -> a -> a
Control.Exception.assert (Coordinates
lower Coordinates -> Coordinates -> Bool
forall a. Eq a => a -> a -> Bool
== Coordinates
forall a. Bounded a => a
minBound Bool -> Bool -> Bool
&& Coordinates
upper Coordinates -> Coordinates -> Bool
forall a. Eq a => a -> a -> Bool
== Coordinates
forall a. Bounded a => a
maxBound) (X -> X) -> (Coordinates -> X) -> Coordinates -> X
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Coordinates -> X
forall a. Enum a => a -> X
fromEnum
instance Enum Coordinates where
toEnum :: X -> Coordinates
toEnum = (
\(X
y, X
x) -> MkCoordinates :: X -> X -> Coordinates
MkCoordinates {
getX :: X
getX = X -> X
Cartesian.Abscissa.fromIx X
x,
getY :: X
getY = X -> X
Cartesian.Ordinate.fromIx X
y
}
) ((X, X) -> Coordinates) -> (X -> (X, X)) -> X -> Coordinates
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (X -> X -> (X, X)
forall a. Integral a => a -> a -> (a, a)
`divMod` X -> X
forall a b. (Integral a, Num b) => a -> b
fromIntegral X
Cartesian.Abscissa.xLength)
fromEnum :: Coordinates -> X
fromEnum MkCoordinates {
getX :: Coordinates -> X
getX = X
x,
getY :: Coordinates -> X
getY = X
y
} = X -> X
forall a b. (Integral a, Num b) => a -> b
fromIntegral X
Cartesian.Abscissa.xLength X -> X -> X
forall a. Num a => a -> a -> a
* X -> X
Cartesian.Ordinate.toIx X
y X -> X -> X
forall a. Num a => a -> a -> a
+ X -> X
Cartesian.Abscissa.toIx X
x
instance Ord Coordinates where
MkCoordinates { getX :: Coordinates -> X
getX = X
x, getY :: Coordinates -> X
getY = X
y } compare :: Coordinates -> Coordinates -> Ordering
`compare` MkCoordinates { getX :: Coordinates -> X
getX = X
x', getY :: Coordinates -> X
getY = X
y' } = (X
y, X
x) (X, X) -> (X, X) -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` (X
y', X
x')
instance Show Coordinates where
showsPrec :: X -> Coordinates -> ShowS
showsPrec X
precedence MkCoordinates { getX :: Coordinates -> X
getX = X
x, getY :: Coordinates -> X
getY = X
y } = X -> (X, X) -> ShowS
forall a. Show a => X -> a -> ShowS
showsPrec X
precedence (X
x, X
y)
instance Read Coordinates where
readsPrec :: X -> ReadS Coordinates
readsPrec X
precedence String
s = [
(Coordinates
coordinates, String
remainder) |
(Just Coordinates
coordinates, String
remainder) <- ((X, X) -> Maybe Coordinates)
-> ((X, X), String) -> (Maybe Coordinates, String)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
Control.Arrow.first ((X -> X -> Maybe Coordinates) -> (X, X) -> Maybe Coordinates
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry X -> X -> Maybe Coordinates
mkMaybeCoordinates) (((X, X), String) -> (Maybe Coordinates, String))
-> [((X, X), String)] -> [(Maybe Coordinates, String)]
forall a b. (a -> b) -> [a] -> [b]
`map` X -> ReadS (X, X)
forall a. Read a => X -> ReadS a
readsPrec X
precedence String
s
]
instance Property.Opposable.Opposable Coordinates where
getOpposite :: Coordinates -> Coordinates
getOpposite MkCoordinates {
getX :: Coordinates -> X
getX = X
x,
getY :: Coordinates -> X
getY = X
y
} = MkCoordinates :: X -> X -> Coordinates
MkCoordinates {
getX :: X
getX = X -> X
Cartesian.Abscissa.reflect X
x,
getY :: X
getY = X -> X
Cartesian.Ordinate.reflect X
y
}
instance Property.Reflectable.ReflectableOnX Coordinates where
reflectOnX :: Coordinates -> Coordinates
reflectOnX coordinates :: Coordinates
coordinates@MkCoordinates { getY :: Coordinates -> X
getY = X
y } = Coordinates
coordinates { getY :: X
getY = X -> X
Cartesian.Ordinate.reflect X
y }
instance Property.Reflectable.ReflectableOnY Coordinates where
reflectOnY :: Coordinates -> Coordinates
reflectOnY coordinates :: Coordinates
coordinates@MkCoordinates { getX :: Coordinates -> X
getX = X
x } = Coordinates
coordinates { getX :: X
getX = X -> X
Cartesian.Abscissa.reflect X
x }
instance Property.Rotatable.Rotatable Coordinates where
rotate90 :: Coordinates -> Coordinates
rotate90 MkCoordinates {
getX :: Coordinates -> X
getX = X
x,
getY :: Coordinates -> X
getY = X
y
} = MkCoordinates :: X -> X -> Coordinates
MkCoordinates {
getX :: X
getX = X -> X
forall a b. (Integral a, Num b) => a -> b
fromIntegral (X -> X) -> X -> X
forall a b. (a -> b) -> a -> b
$! X -> X
Cartesian.Ordinate.reflect X
y,
getY :: X
getY = X -> X
forall a b. (Integral a, Num b) => a -> b
fromIntegral X
x
}
rotate180 :: Coordinates -> Coordinates
rotate180 = Coordinates -> Coordinates
forall a. Opposable a => a -> a
Property.Opposable.getOpposite
rotate270 :: Coordinates -> Coordinates
rotate270 MkCoordinates {
getX :: Coordinates -> X
getX = X
x,
getY :: Coordinates -> X
getY = X
y
} = MkCoordinates :: X -> X -> Coordinates
MkCoordinates {
getX :: X
getX = X -> X
forall a b. (Integral a, Num b) => a -> b
fromIntegral X
y,
getY :: X
getY = X -> X
forall a b. (Integral a, Num b) => a -> b
fromIntegral (X -> X) -> X -> X
forall a b. (a -> b) -> a -> b
$! X -> X
Cartesian.Abscissa.reflect X
x
}
topLeft :: Coordinates
topLeft :: Coordinates
topLeft = MkCoordinates :: X -> X -> Coordinates
MkCoordinates {
getX :: X
getX = X
Cartesian.Abscissa.xMin,
getY :: X
getY = X
Cartesian.Ordinate.yMax
}
bottomRight :: Coordinates
bottomRight :: Coordinates
bottomRight = MkCoordinates :: X -> X -> Coordinates
MkCoordinates {
getX :: X
getX = X
Cartesian.Abscissa.xMax,
getY :: X
getY = X
Cartesian.Ordinate.yMin
}
nSquares :: Type.Count.NCoordinates
nSquares :: X
nSquares = X -> X
forall a b. (Integral a, Num b) => a -> b
fromIntegral X
Cartesian.Abscissa.xLength X -> X -> X
forall a. Num a => a -> a -> a
* X -> X
forall a b. (Integral a, Num b) => a -> b
fromIntegral X
Cartesian.Ordinate.yLength
instance Property.FixedMembership.FixedMembership Coordinates where
members :: [Coordinates]
members = [
MkCoordinates :: X -> X -> Coordinates
MkCoordinates {
getX :: X
getX = X
x,
getY :: X
getY = X
y
} |
X
y <- [X]
Cartesian.Ordinate.yRange,
X
x <- [X]
Cartesian.Abscissa.xRange
]
inBounds
:: Type.Length.X
-> Type.Length.Y
-> Bool
inBounds :: X -> X -> Bool
inBounds X
x X
y = X -> Bool
Cartesian.Abscissa.inBounds X
x Bool -> Bool -> Bool
&& X -> Bool
Cartesian.Ordinate.inBounds X
y
mkCoordinates
:: Type.Length.X
-> Type.Length.Y
-> Coordinates
mkCoordinates :: X -> X -> Coordinates
mkCoordinates X
x X
y = Bool -> Coordinates -> Coordinates
forall a. (?callStack::CallStack) => Bool -> a -> a
Control.Exception.assert (X -> X -> Bool
inBounds X
x X
y) (Coordinates -> Coordinates) -> Coordinates -> Coordinates
forall a b. (a -> b) -> a -> b
$ X -> X -> Coordinates
MkCoordinates X
x X
y
mkMaybeCoordinates
:: Type.Length.X
-> Type.Length.Y
-> Maybe Coordinates
mkMaybeCoordinates :: X -> X -> Maybe Coordinates
mkMaybeCoordinates X
x X
y
| X -> X -> Bool
inBounds X
x X
y = Coordinates -> Maybe Coordinates
forall a. a -> Maybe a
Just MkCoordinates :: X -> X -> Coordinates
MkCoordinates { getX :: X
getX = X
x, getY :: X
getY = X
y }
| Bool
otherwise = Maybe Coordinates
forall a. Maybe a
Nothing
type Transformation = Coordinates -> Coordinates
translate :: ((Type.Length.X, Type.Length.Y) -> (Type.Length.X, Type.Length.Y)) -> Transformation
translate :: ((X, X) -> (X, X)) -> Coordinates -> Coordinates
translate (X, X) -> (X, X)
transformation MkCoordinates {
getX :: Coordinates -> X
getX = X
x,
getY :: Coordinates -> X
getY = X
y
} = (X -> X -> Coordinates) -> (X, X) -> Coordinates
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry X -> X -> Coordinates
mkCoordinates ((X, X) -> Coordinates) -> (X, X) -> Coordinates
forall a b. (a -> b) -> a -> b
$ (X, X) -> (X, X)
transformation (X
x, X
y)
maybeTranslate :: ((Type.Length.X, Type.Length.Y) -> (Type.Length.X, Type.Length.Y)) -> Coordinates -> Maybe Coordinates
maybeTranslate :: ((X, X) -> (X, X)) -> Coordinates -> Maybe Coordinates
maybeTranslate (X, X) -> (X, X)
transformation MkCoordinates {
getX :: Coordinates -> X
getX = X
x,
getY :: Coordinates -> X
getY = X
y
} = (X -> X -> Maybe Coordinates) -> (X, X) -> Maybe Coordinates
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry X -> X -> Maybe Coordinates
mkMaybeCoordinates ((X, X) -> Maybe Coordinates) -> (X, X) -> Maybe Coordinates
forall a b. (a -> b) -> a -> b
$ (X, X) -> (X, X)
transformation (X
x, X
y)
translateX :: (Type.Length.X -> Type.Length.X) -> Transformation
translateX :: (X -> X) -> Coordinates -> Coordinates
translateX X -> X
transformation coordinates :: Coordinates
coordinates@MkCoordinates { getX :: Coordinates -> X
getX = X
x } = Coordinates
coordinates { getX :: X
getX = (X -> X) -> X -> X
Cartesian.Abscissa.translate X -> X
transformation X
x }
maybeTranslateX
:: (Type.Length.X -> Type.Length.X)
-> Coordinates
-> Maybe Coordinates
maybeTranslateX :: (X -> X) -> Coordinates -> Maybe Coordinates
maybeTranslateX X -> X
transformation coordinates :: Coordinates
coordinates@MkCoordinates { getX :: Coordinates -> X
getX = X
x } = (\X
x' -> Coordinates
coordinates { getX :: X
getX = X
x' }) (X -> Coordinates) -> Maybe X -> Maybe Coordinates
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (X -> X) -> X -> Maybe X
Cartesian.Abscissa.maybeTranslate X -> X
transformation X
x
translateY :: (Type.Length.Y -> Type.Length.Y) -> Transformation
translateY :: (X -> X) -> Coordinates -> Coordinates
translateY X -> X
transformation coordinates :: Coordinates
coordinates@MkCoordinates { getY :: Coordinates -> X
getY = X
y } = Coordinates
coordinates { getY :: X
getY = (X -> X) -> X -> X
Cartesian.Ordinate.translate X -> X
transformation X
y }
maybeTranslateY
:: (Type.Length.Y -> Type.Length.Y)
-> Coordinates
-> Maybe Coordinates
maybeTranslateY :: (X -> X) -> Coordinates -> Maybe Coordinates
maybeTranslateY X -> X
transformation coordinates :: Coordinates
coordinates@MkCoordinates { getY :: Coordinates -> X
getY = X
y } = (\X
y' -> Coordinates
coordinates { getY :: X
getY = X
y' }) (X -> Coordinates) -> Maybe X -> Maybe Coordinates
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (X -> X) -> X -> Maybe X
Cartesian.Ordinate.maybeTranslate X -> X
transformation X
y
mkRelativeCoordinates :: ((Type.Length.X, Type.Length.Y) -> (Type.Length.X, Type.Length.Y)) -> Coordinates
mkRelativeCoordinates :: ((X, X) -> (X, X)) -> Coordinates
mkRelativeCoordinates = (((X, X) -> (X, X)) -> Coordinates -> Coordinates
`translate` Coordinates
forall a. Bounded a => a
minBound)
advance
:: Colour.LogicalColour.LogicalColour
-> Transformation
advance :: LogicalColour -> Coordinates -> Coordinates
advance LogicalColour
logicalColour = (X -> X) -> Coordinates -> Coordinates
translateY ((X -> X) -> Coordinates -> Coordinates)
-> (X -> X) -> Coordinates -> Coordinates
forall a b. (a -> b) -> a -> b
$ if LogicalColour -> Bool
Colour.LogicalColour.isBlack LogicalColour
logicalColour
then X -> X
forall a. Enum a => a -> a
pred
else X -> X
forall a. Enum a => a -> a
succ
maybeAdvance
:: Colour.LogicalColour.LogicalColour
-> Coordinates
-> Maybe Coordinates
maybeAdvance :: LogicalColour -> Coordinates -> Maybe Coordinates
maybeAdvance LogicalColour
logicalColour = (X -> X) -> Coordinates -> Maybe Coordinates
maybeTranslateY ((X -> X) -> Coordinates -> Maybe Coordinates)
-> (X -> X) -> Coordinates -> Maybe Coordinates
forall a b. (a -> b) -> a -> b
$ if LogicalColour -> Bool
Colour.LogicalColour.isBlack LogicalColour
logicalColour
then X -> X
forall a. Enum a => a -> a
pred
else X -> X
forall a. Enum a => a -> a
succ
retreat
:: Colour.LogicalColour.LogicalColour
-> Transformation
retreat :: LogicalColour -> Coordinates -> Coordinates
retreat = LogicalColour -> Coordinates -> Coordinates
advance (LogicalColour -> Coordinates -> Coordinates)
-> (LogicalColour -> LogicalColour)
-> LogicalColour
-> Coordinates
-> Coordinates
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LogicalColour -> LogicalColour
forall a. Opposable a => a -> a
Property.Opposable.getOpposite
maybeRetreat
:: Colour.LogicalColour.LogicalColour
-> Coordinates
-> Maybe Coordinates
maybeRetreat :: LogicalColour -> Coordinates -> Maybe Coordinates
maybeRetreat = LogicalColour -> Coordinates -> Maybe Coordinates
maybeAdvance (LogicalColour -> Coordinates -> Maybe Coordinates)
-> (LogicalColour -> LogicalColour)
-> LogicalColour
-> Coordinates
-> Maybe Coordinates
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LogicalColour -> LogicalColour
forall a. Opposable a => a -> a
Property.Opposable.getOpposite
getAdjacents :: Coordinates -> [Coordinates]
getAdjacents :: Coordinates -> [Coordinates]
getAdjacents coordinates :: Coordinates
coordinates@MkCoordinates { getX :: Coordinates -> X
getX = X
x } = (X -> Coordinates) -> [X] -> [Coordinates]
forall a b. (a -> b) -> [a] -> [b]
map (\X
x' -> Coordinates
coordinates { getX :: X
getX = X
x' }) ([X] -> [Coordinates]) -> [X] -> [Coordinates]
forall a b. (a -> b) -> a -> b
$ X -> [X]
Cartesian.Abscissa.getAdjacents X
x
extrapolate'
:: Coordinates
-> Direction.Direction.Direction
-> [Coordinates]
MkCoordinates {
getX :: Coordinates -> X
getX = X
x,
getY :: Coordinates -> X
getY = X
y
} Direction
direction = ([X] -> [X] -> [Coordinates]) -> ([X], [X]) -> [Coordinates]
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ((X -> X -> Coordinates) -> [X] -> [X] -> [Coordinates]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith X -> X -> Coordinates
MkCoordinates) (([X], [X]) -> [Coordinates]) -> ([X], [X]) -> [Coordinates]
forall a b. (a -> b) -> a -> b
$ if Direction -> Bool
forall a. Orientated a => a -> Bool
Property.Orientated.isParallel Direction
direction
then if Direction -> Bool
forall a. Orientated a => a -> Bool
Property.Orientated.isVertical Direction
direction
then ([X], [X])
doVertical
else ([X], [X])
doHorizontal
else ([X], [X])
doDiagonal
where
xIncreasing, xDecreasing :: [Type.Length.X]
xIncreasing :: [X]
xIncreasing = [X -> X
forall a. Enum a => a -> a
succ X
x .. X
Cartesian.Abscissa.xMax]
xDecreasing :: [X]
xDecreasing = let startX :: X
startX = X -> X
forall a. Enum a => a -> a
pred X
x in X
startX X -> [X] -> [X]
`seq` [X
startX, X -> X
forall a. Enum a => a -> a
pred X
startX .. X
Cartesian.Abscissa.xMin]
yIncreasing, yDecreasing :: [Type.Length.Y]
yIncreasing :: [X]
yIncreasing = [X -> X
forall a. Enum a => a -> a
succ X
y .. X
Cartesian.Ordinate.yMax]
yDecreasing :: [X]
yDecreasing = let startY :: X
startY = X -> X
forall a. Enum a => a -> a
pred X
y in X
startY X -> [X] -> [X]
`seq` [X
startY, X -> X
forall a. Enum a => a -> a
pred X
startY .. X
Cartesian.Ordinate.yMin]
doVertical, doHorizontal, doDiagonal :: ([Type.Length.X], [Type.Length.Y])
doVertical :: ([X], [X])
doVertical = (
X -> [X]
forall a. a -> [a]
repeat X
x,
if Direction
direction Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Direction.Direction.s then [X]
yDecreasing else [X]
yIncreasing
)
doHorizontal :: ([X], [X])
doHorizontal = (
if Direction
direction Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Direction.Direction.w then [X]
xDecreasing else [X]
xIncreasing,
X -> [X]
forall a. a -> [a]
repeat X
y
)
doDiagonal :: ([X], [X])
doDiagonal
| Direction
direction Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Direction.Direction.sw = ([X]
xDecreasing, [X]
yDecreasing)
| Direction
direction Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Direction.Direction.se = ([X]
xIncreasing, [X]
yDecreasing)
| Direction
direction Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Direction.Direction.nw = ([X]
xDecreasing, [X]
yIncreasing)
| Bool
otherwise = ([X]
xIncreasing, [X]
yIncreasing)
extrapolate
:: Coordinates
-> Direction.Direction.Direction
-> [Coordinates]
Coordinates
coordinates Direction
direction = ArrayByCoordinates (ArrayByDirection [Coordinates])
extrapolationsByDirectionByCoordinates ArrayByCoordinates (ArrayByDirection [Coordinates])
-> Coordinates -> ArrayByDirection [Coordinates]
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
! Coordinates
coordinates ArrayByDirection [Coordinates] -> Direction -> [Coordinates]
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
! Direction
direction
extrapolationsByDirectionByCoordinates :: ArrayByCoordinates (Direction.Direction.ArrayByDirection [Coordinates])
= [ArrayByDirection [Coordinates]]
-> ArrayByCoordinates (ArrayByDirection [Coordinates])
forall (a :: * -> * -> *) e. IArray a e => [e] -> a Coordinates e
listArrayByCoordinates
#ifdef USE_PARALLEL
([ArrayByDirection [Coordinates]]
-> ArrayByCoordinates (ArrayByDirection [Coordinates]))
-> ([ArrayByDirection [Coordinates]]
-> [ArrayByDirection [Coordinates]])
-> [ArrayByDirection [Coordinates]]
-> ArrayByCoordinates (ArrayByDirection [Coordinates])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Strategy [ArrayByDirection [Coordinates]]
-> [ArrayByDirection [Coordinates]]
-> [ArrayByDirection [Coordinates]]
forall a. Strategy a -> a -> a
Control.Parallel.Strategies.withStrategy (Strategy (ArrayByDirection [Coordinates])
-> Strategy [ArrayByDirection [Coordinates]]
forall a. Strategy a -> Strategy [a]
Control.Parallel.Strategies.parList Strategy (ArrayByDirection [Coordinates])
forall a. NFData a => Strategy a
Control.Parallel.Strategies.rdeepseq)
#endif
([ArrayByDirection [Coordinates]]
-> ArrayByCoordinates (ArrayByDirection [Coordinates]))
-> [ArrayByDirection [Coordinates]]
-> ArrayByCoordinates (ArrayByDirection [Coordinates])
forall a b. (a -> b) -> a -> b
$ (Coordinates -> ArrayByDirection [Coordinates])
-> [Coordinates] -> [ArrayByDirection [Coordinates]]
forall a b. (a -> b) -> [a] -> [b]
map (
\Coordinates
coordinates -> [[Coordinates]] -> ArrayByDirection [Coordinates]
forall (a :: * -> * -> *) e. IArray a e => [e] -> a Direction e
Direction.Direction.listArrayByDirection ([[Coordinates]] -> ArrayByDirection [Coordinates])
-> [[Coordinates]] -> ArrayByDirection [Coordinates]
forall a b. (a -> b) -> a -> b
$ Coordinates -> Direction -> [Coordinates]
extrapolate' Coordinates
coordinates (Direction -> [Coordinates]) -> [Direction] -> [[Coordinates]]
forall a b. (a -> b) -> [a] -> [b]
`map` [Direction]
forall a. FixedMembership a => [a]
Property.FixedMembership.members
) [Coordinates]
forall a. FixedMembership a => [a]
Property.FixedMembership.members
applyAlongDirectionsFrom
:: ([Coordinates] -> [a])
-> Coordinates
-> Maybe [Direction.Direction.Direction]
-> [a]
applyAlongDirectionsFrom :: ([Coordinates] -> [a]) -> Coordinates -> Maybe [Direction] -> [a]
applyAlongDirectionsFrom [Coordinates] -> [a]
f Coordinates
from = [a] -> ([Direction] -> [a]) -> Maybe [Direction] -> [a]
forall b a. b -> (a -> b) -> Maybe a -> b
Data.Maybe.maybe (
([Coordinates] -> [a]) -> ArrayByDirection [Coordinates] -> [a]
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
Data.Foldable.foldMap [Coordinates] -> [a]
f (ArrayByDirection [Coordinates] -> [a])
-> ArrayByDirection [Coordinates] -> [a]
forall a b. (a -> b) -> a -> b
$ ArrayByCoordinates (ArrayByDirection [Coordinates])
extrapolationsByDirectionByCoordinates ArrayByCoordinates (ArrayByDirection [Coordinates])
-> Coordinates -> ArrayByDirection [Coordinates]
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
! Coordinates
from
) (
(Direction -> [a]) -> [Direction] -> [a]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ((Direction -> [a]) -> [Direction] -> [a])
-> (Direction -> [a]) -> [Direction] -> [a]
forall a b. (a -> b) -> a -> b
$ [Coordinates] -> [a]
f ([Coordinates] -> [a])
-> (Direction -> [Coordinates]) -> Direction -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ArrayByCoordinates (ArrayByDirection [Coordinates])
extrapolationsByDirectionByCoordinates ArrayByCoordinates (ArrayByDirection [Coordinates])
-> Coordinates -> ArrayByDirection [Coordinates]
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
! Coordinates
from ArrayByDirection [Coordinates] -> Direction -> [Coordinates]
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
!)
)
interpolationsByDestinationBySource :: ArrayByCoordinates (Map.Map Coordinates [Coordinates])
interpolationsByDestinationBySource :: ArrayByCoordinates (Map Coordinates [Coordinates])
interpolationsByDestinationBySource = (ArrayByDirection [Coordinates] -> Map Coordinates [Coordinates])
-> ArrayByCoordinates (ArrayByDirection [Coordinates])
-> ArrayByCoordinates (Map Coordinates [Coordinates])
forall (a :: * -> * -> *) e' e i.
(IArray a e', IArray a e, Ix i) =>
(e' -> e) -> a i e' -> a i e
Data.Array.IArray.amap (
[(Coordinates, [Coordinates])] -> Map Coordinates [Coordinates]
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(Coordinates, [Coordinates])] -> Map Coordinates [Coordinates])
-> (ArrayByDirection [Coordinates]
-> [(Coordinates, [Coordinates])])
-> ArrayByDirection [Coordinates]
-> Map Coordinates [Coordinates]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Coordinates] -> (Coordinates, [Coordinates]))
-> [[Coordinates]] -> [(Coordinates, [Coordinates])]
forall a b. (a -> b) -> [a] -> [b]
map (
[Coordinates] -> Coordinates
forall a. [a] -> a
last ([Coordinates] -> Coordinates)
-> ([Coordinates] -> [Coordinates])
-> [Coordinates]
-> (Coordinates, [Coordinates])
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& [Coordinates] -> [Coordinates]
forall a. a -> a
id
) ([[Coordinates]] -> [(Coordinates, [Coordinates])])
-> (ArrayByDirection [Coordinates] -> [[Coordinates]])
-> ArrayByDirection [Coordinates]
-> [(Coordinates, [Coordinates])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Coordinates] -> [[Coordinates]])
-> [[Coordinates]] -> [[Coordinates]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (
[[Coordinates]] -> [[Coordinates]]
forall a. [a] -> [a]
tail ([[Coordinates]] -> [[Coordinates]])
-> ([Coordinates] -> [[Coordinates]])
-> [Coordinates]
-> [[Coordinates]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Coordinates] -> [[Coordinates]]
forall a. [a] -> [[a]]
Data.List.inits
) ([[Coordinates]] -> [[Coordinates]])
-> (ArrayByDirection [Coordinates] -> [[Coordinates]])
-> ArrayByDirection [Coordinates]
-> [[Coordinates]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ArrayByDirection [Coordinates] -> [[Coordinates]]
forall (t :: * -> *) a. Foldable t => t a -> [a]
Data.Foldable.toList
) ArrayByCoordinates (ArrayByDirection [Coordinates])
extrapolationsByDirectionByCoordinates
interpolate :: Coordinates -> Coordinates -> [Coordinates]
interpolate :: Coordinates -> Coordinates -> [Coordinates]
interpolate Coordinates
coordinatesSource Coordinates
coordinatesDestination = ArrayByCoordinates (Map Coordinates [Coordinates])
interpolationsByDestinationBySource ArrayByCoordinates (Map Coordinates [Coordinates])
-> Coordinates -> Map Coordinates [Coordinates]
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
! Coordinates
coordinatesSource Map Coordinates [Coordinates] -> Coordinates -> [Coordinates]
forall k a. Ord k => Map k a -> k -> a
Map.! Coordinates
coordinatesDestination
measureDistance
:: Coordinates
-> Coordinates
-> (Type.Length.X, Type.Length.Y)
measureDistance :: Coordinates -> Coordinates -> (X, X)
measureDistance MkCoordinates {
getX :: Coordinates -> X
getX = X
x,
getY :: Coordinates -> X
getY = X
y
} MkCoordinates {
getX :: Coordinates -> X
getX = X
x',
getY :: Coordinates -> X
getY = X
y'
} = (X
x' X -> X -> X
forall a. Num a => a -> a -> a
- X
x, X
y' X -> X -> X
forall a. Num a => a -> a -> a
- X
y)
getLogicalColourOfSquare :: Coordinates -> Colour.LogicalColourOfSquare.LogicalColourOfSquare
getLogicalColourOfSquare :: Coordinates -> LogicalColourOfSquare
getLogicalColourOfSquare Coordinates
coordinates
| (Bool -> Bool -> Bool) -> (Bool, Bool) -> Bool
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
(==) ((Bool, Bool) -> Bool)
-> ((X, X) -> (Bool, Bool)) -> (X, X) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (
X -> Bool
forall a. Integral a => a -> Bool
even (X -> Bool) -> (X -> Bool) -> (X, X) -> (Bool, Bool)
forall (a :: * -> * -> *) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
*** X -> Bool
forall a. Integral a => a -> Bool
even
) ((X, X) -> Bool) -> (X, X) -> Bool
forall a b. (a -> b) -> a -> b
$ Coordinates -> Coordinates -> (X, X)
measureDistance Coordinates
forall a. Bounded a => a
minBound Coordinates
coordinates = LogicalColourOfSquare
Colour.LogicalColourOfSquare.black
| Bool
otherwise = LogicalColourOfSquare
Colour.LogicalColourOfSquare.white
areSquaresIsochromatic :: [Coordinates] -> Bool
areSquaresIsochromatic :: [Coordinates] -> Bool
areSquaresIsochromatic = (Bool -> Bool -> Bool) -> (Bool, Bool) -> Bool
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Bool -> Bool -> Bool
(||) ((Bool, Bool) -> Bool)
-> ([Coordinates] -> (Bool, Bool)) -> [Coordinates] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((LogicalColourOfSquare -> Bool) -> [LogicalColourOfSquare] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (LogicalColourOfSquare -> LogicalColourOfSquare -> Bool
forall a. Eq a => a -> a -> Bool
== LogicalColourOfSquare
forall a. Bounded a => a
minBound) ([LogicalColourOfSquare] -> Bool)
-> ([LogicalColourOfSquare] -> Bool)
-> [LogicalColourOfSquare]
-> (Bool, Bool)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& (LogicalColourOfSquare -> Bool) -> [LogicalColourOfSquare] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (LogicalColourOfSquare -> LogicalColourOfSquare -> Bool
forall a. Eq a => a -> a -> Bool
== LogicalColourOfSquare
forall a. Bounded a => a
maxBound)) ([LogicalColourOfSquare] -> (Bool, Bool))
-> ([Coordinates] -> [LogicalColourOfSquare])
-> [Coordinates]
-> (Bool, Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Coordinates -> LogicalColourOfSquare)
-> [Coordinates] -> [LogicalColourOfSquare]
forall a b. (a -> b) -> [a] -> [b]
map Coordinates -> LogicalColourOfSquare
getLogicalColourOfSquare
kingsStartingCoordinates :: Colour.LogicalColour.LogicalColour -> Coordinates
kingsStartingCoordinates :: LogicalColour -> Coordinates
kingsStartingCoordinates LogicalColour
logicalColour = MkCoordinates :: X -> X -> Coordinates
MkCoordinates {
getX :: X
getX = X
Cartesian.Abscissa.kingsFile,
getY :: X
getY = LogicalColour -> X
Cartesian.Ordinate.firstRank LogicalColour
logicalColour
}
rooksStartingCoordinates :: Colour.LogicalColour.LogicalColour -> [Coordinates]
rooksStartingCoordinates :: LogicalColour -> [Coordinates]
rooksStartingCoordinates LogicalColour
Colour.LogicalColour.Black = [Coordinates
topLeft, Coordinates
forall a. Bounded a => a
maxBound]
rooksStartingCoordinates LogicalColour
_ = [Coordinates
forall a. Bounded a => a
minBound, Coordinates
bottomRight]
isPawnsFirstRank :: Coordinates -> Colour.LogicalColour.LogicalColour -> Bool
isPawnsFirstRank :: Coordinates -> LogicalColour -> Bool
isPawnsFirstRank MkCoordinates { getY :: Coordinates -> X
getY = X
y } = (X -> X -> Bool
forall a. Eq a => a -> a -> Bool
== X
y) (X -> Bool) -> (LogicalColour -> X) -> LogicalColour -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LogicalColour -> X
Cartesian.Ordinate.pawnsFirstRank
isEnPassantRank :: Coordinates -> Colour.LogicalColour.LogicalColour -> Bool
isEnPassantRank :: Coordinates -> LogicalColour -> Bool
isEnPassantRank MkCoordinates { getY :: Coordinates -> X
getY = X
y } = (X -> X -> Bool
forall a. Eq a => a -> a -> Bool
== X
y) (X -> Bool) -> (LogicalColour -> X) -> LogicalColour -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LogicalColour -> X
Cartesian.Ordinate.enPassantRank
type ArrayByCoordinates = Data.Array.IArray.Array Coordinates
#ifdef USE_UNBOXED_ARRAYS
type UArrayByCoordinates = Data.Array.Unboxed.UArray Coordinates
#endif
listArrayByCoordinates :: Data.Array.IArray.IArray a e => [e] -> a Coordinates e
listArrayByCoordinates :: [e] -> a Coordinates e
listArrayByCoordinates = (Coordinates, Coordinates) -> [e] -> a Coordinates e
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
(i, i) -> [e] -> a i e
Data.Array.IArray.listArray (Coordinates
forall a. Bounded a => a
minBound, Coordinates
forall a. Bounded a => a
maxBound)
arrayByCoordinates :: Data.Array.IArray.IArray a e => [(Coordinates, e)] -> a Coordinates e
arrayByCoordinates :: [(Coordinates, e)] -> a Coordinates e
arrayByCoordinates = (Coordinates, Coordinates) -> [(Coordinates, e)] -> a Coordinates e
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
(i, i) -> [(i, e)] -> a i e
Data.Array.IArray.array (Coordinates
forall a. Bounded a => a
minBound, Coordinates
forall a. Bounded a => a
maxBound)