module BishBosh.Cartesian.Ordinate(
yOrigin,
yLength,
yMin,
yMax,
yRange,
centre,
firstRank,
lastRank,
pawnsFirstRank,
enPassantRank,
reflect,
translate,
maybeTranslate,
inBounds
) where
import qualified BishBosh.Attribute.LogicalColour as Attribute.LogicalColour
import qualified BishBosh.Cartesian.Abscissa as Cartesian.Abscissa
import qualified BishBosh.Property.Opposable as Property.Opposable
import qualified BishBosh.Types as T
import qualified Control.Exception
yOrigin :: Int
yOrigin = Cartesian.Abscissa.xOrigin
yLength :: T.Distance
yLength = Cartesian.Abscissa.xLength
yMin :: Enum y => y
yMin = toEnum yOrigin
yMax :: Enum y => y
yMax = toEnum $ yOrigin + fromIntegral (pred yLength)
yBounds :: Enum y => (y, y)
yBounds = (yMin, yMax)
yRange :: Enum y => [y]
yRange = uncurry enumFromTo yBounds
centre :: Fractional centre => centre
centre = fromIntegral (uncurry (+) yBounds :: T.Y) / 2
firstRank :: Enum y => Attribute.LogicalColour.LogicalColour -> y
firstRank Attribute.LogicalColour.Black = yMax
firstRank _ = yMin
lastRank :: Enum y => Attribute.LogicalColour.LogicalColour -> y
lastRank = firstRank . Property.Opposable.getOpposite
pawnsFirstRank :: Enum y => Attribute.LogicalColour.LogicalColour -> y
pawnsFirstRank Attribute.LogicalColour.Black = pred yMax
pawnsFirstRank _ = succ yMin
enPassantRank :: Enum y => Attribute.LogicalColour.LogicalColour -> y
enPassantRank Attribute.LogicalColour.Black = toEnum $ yOrigin + 3
enPassantRank _ = toEnum $ yOrigin + 4
reflect :: Enum y => y -> y
reflect = toEnum . (
+ (2 * yOrigin + fromIntegral (pred yLength))
) . negate . fromEnum
inBounds :: (Enum y, Ord y) => y -> Bool
inBounds y = y >= yMin && y <= yMax
translate :: (Enum y, Ord y) => (y -> y) -> y -> y
translate transformation = (\y -> Control.Exception.assert (inBounds y) y) . transformation
maybeTranslate :: (Enum y, Ord y) => (y -> y) -> y -> Maybe y
maybeTranslate transformation = (
\y -> if inBounds y
then Just y
else Nothing
) . transformation