bishbosh-0.1.2.0: src-lib/BishBosh/Cartesian/Abscissa.hs
{-
Copyright (C) 2018 Dr. Alistair Ward
This file is part of BishBosh.
BishBosh is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
BishBosh is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with BishBosh. If not, see <http://www.gnu.org/licenses/>.
-}
{- |
[@AUTHOR@] Dr. Alistair Ward
[@DESCRIPTION@]
* Describes the /x/-axis by which the /board/ is indexed.
* AKA the /file/ of a piece.
* N.B. this coordinate-system is for internal use only, and doesn't attempt to replicate any standard chess-notation.
-}
module BishBosh.Cartesian.Abscissa(
-- * Constants
xLength,
xMin,
xMax,
xBounds,
xRange,
bishopsFiles,
kingsFile,
-- adjacents,
-- * Functions
toIx,
fromIx,
reflect,
translate,
maybeTranslate,
getAdjacents,
-- getAdjacents',
-- ** Constructors
listArrayByAbscissa,
-- ** Predicates
inBounds
) where
import Data.Array.IArray((!))
import qualified BishBosh.Type.Length as Type.Length
import qualified Control.Exception
import qualified Data.Array.IArray
-- | The constant length of the /x/-axis.
xLength :: Type.Length.X
xLength = 8
-- | The constant bounds of abscissae.
xBounds :: (Type.Length.X, Type.Length.X)
xMin, xMax :: Type.Length.X
xBounds@(xMin, xMax) = (0, xMin + pred {-fence-post-} xLength)
-- | The constant list of all abscissae.
xRange :: [Type.Length.X]
xRange = uncurry enumFromTo xBounds
-- | The conventional starting /file/s for the @Bishops@ of either /logical colour/.
bishopsFiles :: [Type.Length.X]
bishopsFiles = map fromIx [2, 5]
-- | The conventional starting /file/ for the @King@ of either /logical colour/.
kingsFile :: Type.Length.X
kingsFile = fromIx 4
-- | Convert to an array-index.
toIx :: Type.Length.X -> Int
{-# INLINE toIx #-}
toIx = fromIntegral . subtract xMin
-- | Convert from an array-index.
fromIx :: Int -> Type.Length.X
{-# INLINE fromIx #-}
fromIx = (+ xMin) . fromIntegral
-- | Reflects about the mid-point of the axis.
reflect :: Type.Length.X -> Type.Length.X
reflect = (
+ (2 * xMin + pred xLength)
) . negate
-- | Predicate.
inBounds :: Type.Length.X -> Bool
{-# INLINE inBounds #-}
inBounds x = x >= xMin && x <= xMax
-- | Translate the specified ordinate.
translate :: (Type.Length.X -> Type.Length.X) -> Type.Length.X -> Type.Length.X
translate transformation = (\x -> Control.Exception.assert (inBounds x) x) . transformation
-- | Where legal, translate the specified abscissa.
maybeTranslate :: (Type.Length.X -> Type.Length.X) -> Type.Length.X -> Maybe Type.Length.X
maybeTranslate transformation = (
\x -> if inBounds x
then Just x
else Nothing
) . transformation
-- | Get the abscissae immediately left & right.
getAdjacents' :: Type.Length.X -> [Type.Length.X]
getAdjacents' x
| x == xMin = [succ xMin]
| x == xMax = [pred xMax]
| otherwise = [pred x, succ x]
-- | The constant abscissae either side of each value.
adjacents :: Data.Array.IArray.Array Type.Length.X [Type.Length.X]
adjacents = listArrayByAbscissa $ map getAdjacents' xRange
-- | Get the abscissae immediately left & right.
getAdjacents :: Type.Length.X -> [Type.Length.X]
getAdjacents = (adjacents !)
-- | Array-constructor.
listArrayByAbscissa :: Data.Array.IArray.IArray a e => [e] -> a Type.Length.X e
listArrayByAbscissa = Data.Array.IArray.listArray xBounds