packages feed

bishbosh-0.1.3.0: src-lib/BishBosh/Direction/Diagonal.hs

{-
	Copyright (C) 2021 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 directional components of a diagonal line.
-}

module BishBosh.Direction.Diagonal(
-- * Types
-- ** Data-types
	Diagonal()
) where

import			Control.Arrow((***))
import qualified	BishBosh.Direction.Horizontal		as Direction.Horizontal
import qualified	BishBosh.Direction.Vertical		as Direction.Vertical
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	Control.DeepSeq
import qualified	Data.List.Extra

-- | Directions at 45 degress to all edges of the board; those in which a Bishop can move.
data Diagonal	= MkDiagonal {
	getVertical	:: Direction.Vertical.Vertical,		-- ^ The vertical component of the diagonal.
	getHorizontal	:: Direction.Horizontal.Horizontal	-- ^ The horizontal component of the diagonal.
} deriving (Eq, Ord)

instance Control.DeepSeq.NFData Diagonal where
	rnf MkDiagonal {
		getVertical	= _,
		getHorizontal	= _
	} = ()

instance Enum Diagonal where
	fromEnum MkDiagonal {
		getVertical	= v,
		getHorizontal	= h
	} = fromIntegral Direction.Vertical.nVerticals * fromEnum v + fromEnum h

	toEnum i	= uncurry MkDiagonal . (toEnum *** toEnum) $! i `divMod` fromIntegral Direction.Vertical.nVerticals

instance Show Diagonal where
	showsPrec precedence MkDiagonal {
		getVertical	= v,
		getHorizontal	= h
	} = showsPrec precedence v . showsPrec precedence h

instance Read Diagonal where
	readsPrec precedence s	= case readsPrec precedence $ Data.List.Extra.trimStart s of
		[(vertical, s')]	-> case readsPrec precedence s' of
			[(horizontal, s'')]	-> [
				(
					MkDiagonal {
						getVertical	= vertical,
						getHorizontal	= horizontal
					},
					s''
				) -- Pair.
			 ] -- Singleton.
			_			-> []	-- No parse.
		_			-> []	-- No parse.

instance Property.FixedMembership.FixedMembership Diagonal where
	members	= map MkDiagonal Property.FixedMembership.members {-vertical-} <*> Property.FixedMembership.members {-horizontal-}

instance Property.Opposable.Opposable Diagonal where
	getOpposite MkDiagonal {
		getVertical	= v,
		getHorizontal	= h
	} = MkDiagonal {
		getVertical	= Property.Opposable.getOpposite v,
		getHorizontal	= Property.Opposable.getOpposite h
	}

instance Property.Orientated.Orientated Diagonal where
	isParallel	= const False
	isDiagonal	= const True
	isStraight	= const True

instance Property.Reflectable.ReflectableOnX Diagonal where
	reflectOnX diagonal@MkDiagonal {
		getVertical	= v
	} = diagonal {
		getVertical	= Property.Reflectable.reflectOnX v
	}

instance Property.Reflectable.ReflectableOnY Diagonal where
	reflectOnY diagonal@MkDiagonal {
		getHorizontal	= h
	} = diagonal {
		getHorizontal	= Property.Reflectable.reflectOnY h
	}