{-
	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@]

	* Defines configurable options related to the evaluation of the game at any instance.

	* N.B.: /evaluation/ is distinct from /search/:
		evaluation => how one assesses the fitness of candidate moves;
		search => the order in which one evaluates candidates before selecting on the basis of their fitness.
-}

module BishBosh.Input.EvaluationOptions(
-- * Types
-- ** Type-synonyms
	IncrementalEvaluation,
--	PieceSquareTablePair,
	Reader,
-- ** Data-types
	EvaluationOptions(
--		MkEvaluationOptions,
		getRankValues,
		getMaximumTotalRankValue,
		getCriteriaWeights,
		getIncrementalEvaluation,
--		getMaybePieceSquareTablePair,
		getMaybePieceSquareByCoordinatesByRank
	),
-- * Constants
	tag,
--	incrementalEvaluationTag,
--	pieceSquareTablesTag,
--	pieceSquareTableEndGameTag,
-- * Functions
--	fromPieceSquareTablePair,
-- ** Constructor
	mkEvaluationOptions
) where

import			BishBosh.Data.Bool()
import			Control.Arrow((***))
import qualified	BishBosh.Cartesian.Coordinates				as Cartesian.Coordinates
import qualified	BishBosh.Component.PieceSquareByCoordinatesByRank	as Component.PieceSquareByCoordinatesByRank
import qualified	BishBosh.Data.Exception					as Data.Exception
import qualified	BishBosh.Input.CriteriaWeights				as Input.CriteriaWeights
import qualified	BishBosh.Input.PieceSquareTable				as Input.PieceSquareTable
import qualified	BishBosh.Input.RankValues				as Input.RankValues
import qualified	BishBosh.Property.ShowFloat				as Property.ShowFloat
import qualified	BishBosh.Text.ShowList					as Text.ShowList
import qualified	BishBosh.Type.Mass					as Type.Mass
import qualified	Control.DeepSeq
import qualified	Control.Exception
import qualified	Control.Monad.Reader
import qualified	Data.Default
import qualified	Data.Foldable
import qualified	Data.Maybe
import qualified	Text.XML.HXT.Arrow.Pickle				as HXT

-- | Used to qualify XML.
tag :: String
tag :: String
tag	= String
"evaluationOptions"

-- | Used to qualify XML.
incrementalEvaluationTag :: String
incrementalEvaluationTag :: String
incrementalEvaluationTag	= String
"incrementalEvaluation"

-- | Used to qualify XML.
pieceSquareTablesTag :: String
pieceSquareTablesTag :: String
pieceSquareTablesTag	= String -> ShowS
showString String
Input.PieceSquareTable.tag String
"s"

-- | Used to qualify XML.
pieceSquareTableEndGameTag :: String
pieceSquareTableEndGameTag :: String
pieceSquareTableEndGameTag	= String -> ShowS
showString String
Input.PieceSquareTable.tag String
"EndGame"

-- | Whether to generate position-hashes incrementally from the hash of the position prior to the last move.
type IncrementalEvaluation	= Bool

-- | A pair of piece-square tables representing the opening & end-games respectively.
type PieceSquareTablePair pieceSquareValue	= (Input.PieceSquareTable.PieceSquareTable pieceSquareValue, Input.PieceSquareTable.PieceSquareTable pieceSquareValue)

-- | Defines the options related to the automatic selection of /move/s.
data EvaluationOptions pieceSquareValue	= MkEvaluationOptions {
	EvaluationOptions pieceSquareValue -> RankValues
getRankValues				:: Input.RankValues.RankValues,				-- ^ The static value associated with each /piece/'s /rank/.
	EvaluationOptions pieceSquareValue -> RankValue
getMaximumTotalRankValue		:: Type.Mass.RankValue,					-- ^ Used to normalise the total value of pieces. Derived from 'getRankValues'.
	EvaluationOptions pieceSquareValue -> CriteriaWeights
getCriteriaWeights			:: Input.CriteriaWeights.CriteriaWeights,		-- ^ The weights applied to each of the heterogeneous criterion-values used to select a /move/.
	EvaluationOptions pieceSquareValue -> IncrementalEvaluation
getIncrementalEvaluation		:: IncrementalEvaluation,				-- ^ Whether to generate position-hashes & evaluate the piece-square value, from the previous value or from scratch.
	EvaluationOptions pieceSquareValue
-> Maybe (PieceSquareTablePair pieceSquareValue)
getMaybePieceSquareTablePair		:: Maybe (PieceSquareTablePair pieceSquareValue),	-- ^ A optional pair of piece-square tables representing the opening & end-games respectively.
	EvaluationOptions pieceSquareValue
-> Maybe (PieceSquareByCoordinatesByRank pieceSquareValue)
getMaybePieceSquareByCoordinatesByRank	:: Maybe (
		Component.PieceSquareByCoordinatesByRank.PieceSquareByCoordinatesByRank pieceSquareValue
	)												-- ^ The optional value for each rank of /piece/, when occupying each coordinate, at each phase of the game.
} deriving (EvaluationOptions pieceSquareValue
-> EvaluationOptions pieceSquareValue -> IncrementalEvaluation
(EvaluationOptions pieceSquareValue
 -> EvaluationOptions pieceSquareValue -> IncrementalEvaluation)
-> (EvaluationOptions pieceSquareValue
    -> EvaluationOptions pieceSquareValue -> IncrementalEvaluation)
-> Eq (EvaluationOptions pieceSquareValue)
forall pieceSquareValue.
Eq pieceSquareValue =>
EvaluationOptions pieceSquareValue
-> EvaluationOptions pieceSquareValue -> IncrementalEvaluation
forall a.
(a -> a -> IncrementalEvaluation)
-> (a -> a -> IncrementalEvaluation) -> Eq a
/= :: EvaluationOptions pieceSquareValue
-> EvaluationOptions pieceSquareValue -> IncrementalEvaluation
$c/= :: forall pieceSquareValue.
Eq pieceSquareValue =>
EvaluationOptions pieceSquareValue
-> EvaluationOptions pieceSquareValue -> IncrementalEvaluation
== :: EvaluationOptions pieceSquareValue
-> EvaluationOptions pieceSquareValue -> IncrementalEvaluation
$c== :: forall pieceSquareValue.
Eq pieceSquareValue =>
EvaluationOptions pieceSquareValue
-> EvaluationOptions pieceSquareValue -> IncrementalEvaluation
Eq, Int -> EvaluationOptions pieceSquareValue -> ShowS
[EvaluationOptions pieceSquareValue] -> ShowS
EvaluationOptions pieceSquareValue -> String
(Int -> EvaluationOptions pieceSquareValue -> ShowS)
-> (EvaluationOptions pieceSquareValue -> String)
-> ([EvaluationOptions pieceSquareValue] -> ShowS)
-> Show (EvaluationOptions pieceSquareValue)
forall pieceSquareValue.
Show pieceSquareValue =>
Int -> EvaluationOptions pieceSquareValue -> ShowS
forall pieceSquareValue.
Show pieceSquareValue =>
[EvaluationOptions pieceSquareValue] -> ShowS
forall pieceSquareValue.
Show pieceSquareValue =>
EvaluationOptions pieceSquareValue -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [EvaluationOptions pieceSquareValue] -> ShowS
$cshowList :: forall pieceSquareValue.
Show pieceSquareValue =>
[EvaluationOptions pieceSquareValue] -> ShowS
show :: EvaluationOptions pieceSquareValue -> String
$cshow :: forall pieceSquareValue.
Show pieceSquareValue =>
EvaluationOptions pieceSquareValue -> String
showsPrec :: Int -> EvaluationOptions pieceSquareValue -> ShowS
$cshowsPrec :: forall pieceSquareValue.
Show pieceSquareValue =>
Int -> EvaluationOptions pieceSquareValue -> ShowS
Show)

instance Control.DeepSeq.NFData pieceSquareValue => Control.DeepSeq.NFData (EvaluationOptions pieceSquareValue) where
	rnf :: EvaluationOptions pieceSquareValue -> ()
rnf MkEvaluationOptions {
--		getRankValues				= rankValues,
		getMaximumTotalRankValue :: forall pieceSquareValue.
EvaluationOptions pieceSquareValue -> RankValue
getMaximumTotalRankValue		= RankValue
maximumTotalValue,
		getCriteriaWeights :: forall pieceSquareValue.
EvaluationOptions pieceSquareValue -> CriteriaWeights
getCriteriaWeights			= CriteriaWeights
criteriaWeights,
		getIncrementalEvaluation :: forall pieceSquareValue.
EvaluationOptions pieceSquareValue -> IncrementalEvaluation
getIncrementalEvaluation		= IncrementalEvaluation
incrementalEvaluation,
--		getMaybePieceSquareTablePair		= maybePieceSquareTablePair,
		getMaybePieceSquareByCoordinatesByRank :: forall pieceSquareValue.
EvaluationOptions pieceSquareValue
-> Maybe (PieceSquareByCoordinatesByRank pieceSquareValue)
getMaybePieceSquareByCoordinatesByRank	= Maybe (PieceSquareByCoordinatesByRank pieceSquareValue)
maybePieceSquareByCoordinatesByRank
	} = (RankValue, CriteriaWeights, IncrementalEvaluation,
 Maybe (PieceSquareByCoordinatesByRank pieceSquareValue))
-> ()
forall a. NFData a => a -> ()
Control.DeepSeq.rnf (RankValue
maximumTotalValue, CriteriaWeights
criteriaWeights, IncrementalEvaluation
incrementalEvaluation, Maybe (PieceSquareByCoordinatesByRank pieceSquareValue)
maybePieceSquareByCoordinatesByRank)

instance (Real pieceSquareValue, Show pieceSquareValue) => Property.ShowFloat.ShowFloat (EvaluationOptions pieceSquareValue) where
	showsFloat :: (RankValue -> ShowS) -> EvaluationOptions pieceSquareValue -> ShowS
showsFloat RankValue -> ShowS
fromDouble MkEvaluationOptions {
		getRankValues :: forall pieceSquareValue.
EvaluationOptions pieceSquareValue -> RankValues
getRankValues				= RankValues
rankValues,
--		getMaximumTotalRankValue		= maximumTotalValue,
		getCriteriaWeights :: forall pieceSquareValue.
EvaluationOptions pieceSquareValue -> CriteriaWeights
getCriteriaWeights			= CriteriaWeights
criteriaWeights,
		getIncrementalEvaluation :: forall pieceSquareValue.
EvaluationOptions pieceSquareValue -> IncrementalEvaluation
getIncrementalEvaluation		= IncrementalEvaluation
incrementalEvaluation,
		getMaybePieceSquareTablePair :: forall pieceSquareValue.
EvaluationOptions pieceSquareValue
-> Maybe (PieceSquareTablePair pieceSquareValue)
getMaybePieceSquareTablePair		= Maybe (PieceSquareTablePair pieceSquareValue)
maybePieceSquareTablePair
--		getMaybePieceSquareByCoordinatesByRank	= maybePieceSquareByCoordinatesByRank
	} = [(String, ShowS)] -> ShowS
Text.ShowList.showsAssociationList' ([(String, ShowS)] -> ShowS) -> [(String, ShowS)] -> ShowS
forall a b. (a -> b) -> a -> b
$ [
		(
			String
Input.RankValues.tag,		(RankValue -> ShowS) -> RankValues -> ShowS
forall a. ShowFloat a => (RankValue -> ShowS) -> a -> ShowS
Property.ShowFloat.showsFloat RankValue -> ShowS
fromDouble RankValues
rankValues
		), (
			String
incrementalEvaluationTag,	IncrementalEvaluation -> ShowS
forall a. Show a => a -> ShowS
shows IncrementalEvaluation
incrementalEvaluation
		), (
			String
Input.CriteriaWeights.tag,	(RankValue -> ShowS) -> CriteriaWeights -> ShowS
forall a. ShowFloat a => (RankValue -> ShowS) -> a -> ShowS
Property.ShowFloat.showsFloat RankValue -> ShowS
fromDouble CriteriaWeights
criteriaWeights
		)
	 ] [(String, ShowS)] -> [(String, ShowS)] -> [(String, ShowS)]
forall a. [a] -> [a] -> [a]
++ [(String, ShowS)]
-> (PieceSquareTablePair pieceSquareValue -> [(String, ShowS)])
-> Maybe (PieceSquareTablePair pieceSquareValue)
-> [(String, ShowS)]
forall b a. b -> (a -> b) -> Maybe a -> b
Data.Maybe.maybe [] (
		\(PieceSquareTable pieceSquareValue
t, PieceSquareTable pieceSquareValue
t')	-> [
			(
				String
Input.PieceSquareTable.tag,
				(RankValue -> ShowS) -> PieceSquareTable pieceSquareValue -> ShowS
forall a. ShowFloat a => (RankValue -> ShowS) -> a -> ShowS
Property.ShowFloat.showsFloat RankValue -> ShowS
fromDouble PieceSquareTable pieceSquareValue
t
			), (
				String
pieceSquareTableEndGameTag,
				(RankValue -> ShowS) -> PieceSquareTable pieceSquareValue -> ShowS
forall a. ShowFloat a => (RankValue -> ShowS) -> a -> ShowS
Property.ShowFloat.showsFloat RankValue -> ShowS
fromDouble PieceSquareTable pieceSquareValue
t'
			)
		]
	 ) Maybe (PieceSquareTablePair pieceSquareValue)
maybePieceSquareTablePair

instance Data.Default.Default (EvaluationOptions pieceSquareValue) where
	def :: EvaluationOptions pieceSquareValue
def = MkEvaluationOptions :: forall pieceSquareValue.
RankValues
-> RankValue
-> CriteriaWeights
-> IncrementalEvaluation
-> Maybe (PieceSquareTablePair pieceSquareValue)
-> Maybe (PieceSquareByCoordinatesByRank pieceSquareValue)
-> EvaluationOptions pieceSquareValue
MkEvaluationOptions {
		getRankValues :: RankValues
getRankValues				= RankValues
rankValues,
		getMaximumTotalRankValue :: RankValue
getMaximumTotalRankValue		= RankValues -> RankValue
Input.RankValues.calculateMaximumTotalValue RankValues
rankValues,
		getCriteriaWeights :: CriteriaWeights
getCriteriaWeights			= CriteriaWeights
forall a. Default a => a
Data.Default.def,
		getIncrementalEvaluation :: IncrementalEvaluation
getIncrementalEvaluation		= IncrementalEvaluation
True,
		getMaybePieceSquareTablePair :: Maybe (PieceSquareTablePair pieceSquareValue)
getMaybePieceSquareTablePair		= Maybe (PieceSquareTablePair pieceSquareValue)
forall a. Maybe a
Nothing,
		getMaybePieceSquareByCoordinatesByRank :: Maybe (PieceSquareByCoordinatesByRank pieceSquareValue)
getMaybePieceSquareByCoordinatesByRank	= Maybe (PieceSquareByCoordinatesByRank pieceSquareValue)
forall a. Maybe a
Nothing
	} where
		rankValues :: RankValues
rankValues	= RankValues
forall a. Default a => a
Data.Default.def

instance (
	Fractional	pieceSquareValue,
	Ord		pieceSquareValue,
	Real		pieceSquareValue,
	Show		pieceSquareValue
 ) => HXT.XmlPickler (EvaluationOptions pieceSquareValue) where
	xpickle :: PU (EvaluationOptions pieceSquareValue)
xpickle	= EvaluationOptions pieceSquareValue
-> PU (EvaluationOptions pieceSquareValue)
-> PU (EvaluationOptions pieceSquareValue)
forall a. Eq a => a -> PU a -> PU a
HXT.xpDefault EvaluationOptions pieceSquareValue
def (PU (EvaluationOptions pieceSquareValue)
 -> PU (EvaluationOptions pieceSquareValue))
-> (PU (PieceSquareTablePair pieceSquareValue)
    -> PU (EvaluationOptions pieceSquareValue))
-> PU (PieceSquareTablePair pieceSquareValue)
-> PU (EvaluationOptions pieceSquareValue)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String
-> PU (EvaluationOptions pieceSquareValue)
-> PU (EvaluationOptions pieceSquareValue)
forall a. String -> PU a -> PU a
HXT.xpElem String
tag (PU (EvaluationOptions pieceSquareValue)
 -> PU (EvaluationOptions pieceSquareValue))
-> (PU (PieceSquareTablePair pieceSquareValue)
    -> PU (EvaluationOptions pieceSquareValue))
-> PU (PieceSquareTablePair pieceSquareValue)
-> PU (EvaluationOptions pieceSquareValue)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((RankValues, CriteriaWeights, IncrementalEvaluation,
  Maybe (PieceSquareTablePair pieceSquareValue))
 -> EvaluationOptions pieceSquareValue,
 EvaluationOptions pieceSquareValue
 -> (RankValues, CriteriaWeights, IncrementalEvaluation,
     Maybe (PieceSquareTablePair pieceSquareValue)))
-> PU
     (RankValues, CriteriaWeights, IncrementalEvaluation,
      Maybe (PieceSquareTablePair pieceSquareValue))
-> PU (EvaluationOptions pieceSquareValue)
forall a b. (a -> b, b -> a) -> PU a -> PU b
HXT.xpWrap (
		\(RankValues
a, CriteriaWeights
b, IncrementalEvaluation
c, Maybe (PieceSquareTablePair pieceSquareValue)
d) -> RankValues
-> CriteriaWeights
-> IncrementalEvaluation
-> Maybe (PieceSquareTablePair pieceSquareValue)
-> EvaluationOptions pieceSquareValue
forall pieceSquareValue.
Fractional pieceSquareValue =>
RankValues
-> CriteriaWeights
-> IncrementalEvaluation
-> Maybe (PieceSquareTablePair pieceSquareValue)
-> EvaluationOptions pieceSquareValue
mkEvaluationOptions RankValues
a CriteriaWeights
b IncrementalEvaluation
c Maybe (PieceSquareTablePair pieceSquareValue)
d,	-- Construct.
		\MkEvaluationOptions {
			getRankValues :: forall pieceSquareValue.
EvaluationOptions pieceSquareValue -> RankValues
getRankValues				= RankValues
rankValues,
--			getMaximumTotalRankValue		= maximumTotalRankValue,
			getCriteriaWeights :: forall pieceSquareValue.
EvaluationOptions pieceSquareValue -> CriteriaWeights
getCriteriaWeights			= CriteriaWeights
criteriaWeights,
			getIncrementalEvaluation :: forall pieceSquareValue.
EvaluationOptions pieceSquareValue -> IncrementalEvaluation
getIncrementalEvaluation		= IncrementalEvaluation
incrementalEvaluation,
			getMaybePieceSquareTablePair :: forall pieceSquareValue.
EvaluationOptions pieceSquareValue
-> Maybe (PieceSquareTablePair pieceSquareValue)
getMaybePieceSquareTablePair		= Maybe (PieceSquareTablePair pieceSquareValue)
maybePieceSquareTablePair
--			getMaybePieceSquareByCoordinatesByRank	= maybePieceSquareByCoordinatesByRank
		} -> (
			RankValues
rankValues,
			CriteriaWeights
criteriaWeights,
			IncrementalEvaluation
incrementalEvaluation,
			Maybe (PieceSquareTablePair pieceSquareValue)
maybePieceSquareTablePair
		) -- Deconstruct.
	 ) (PU
   (RankValues, CriteriaWeights, IncrementalEvaluation,
    Maybe (PieceSquareTablePair pieceSquareValue))
 -> PU (EvaluationOptions pieceSquareValue))
-> (PU (PieceSquareTablePair pieceSquareValue)
    -> PU
         (RankValues, CriteriaWeights, IncrementalEvaluation,
          Maybe (PieceSquareTablePair pieceSquareValue)))
-> PU (PieceSquareTablePair pieceSquareValue)
-> PU (EvaluationOptions pieceSquareValue)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PU RankValues
-> PU CriteriaWeights
-> PU IncrementalEvaluation
-> PU (Maybe (PieceSquareTablePair pieceSquareValue))
-> PU
     (RankValues, CriteriaWeights, IncrementalEvaluation,
      Maybe (PieceSquareTablePair pieceSquareValue))
forall a b c d. PU a -> PU b -> PU c -> PU d -> PU (a, b, c, d)
HXT.xp4Tuple PU RankValues
forall a. XmlPickler a => PU a
HXT.xpickle {-RankValues-} PU CriteriaWeights
forall a. XmlPickler a => PU a
HXT.xpickle {-CriteriaWeights-} (
		EvaluationOptions pieceSquareValue -> IncrementalEvaluation
forall pieceSquareValue.
EvaluationOptions pieceSquareValue -> IncrementalEvaluation
getIncrementalEvaluation EvaluationOptions pieceSquareValue
def IncrementalEvaluation
-> PU IncrementalEvaluation -> PU IncrementalEvaluation
forall a. Eq a => a -> PU a -> PU a
`HXT.xpDefault` String -> PU IncrementalEvaluation -> PU IncrementalEvaluation
forall a. String -> PU a -> PU a
HXT.xpAttr String
incrementalEvaluationTag PU IncrementalEvaluation
forall a. XmlPickler a => PU a
HXT.xpickle {-Bool-}
	 ) (PU (Maybe (PieceSquareTablePair pieceSquareValue))
 -> PU
      (RankValues, CriteriaWeights, IncrementalEvaluation,
       Maybe (PieceSquareTablePair pieceSquareValue)))
-> (PU (PieceSquareTablePair pieceSquareValue)
    -> PU (Maybe (PieceSquareTablePair pieceSquareValue)))
-> PU (PieceSquareTablePair pieceSquareValue)
-> PU
     (RankValues, CriteriaWeights, IncrementalEvaluation,
      Maybe (PieceSquareTablePair pieceSquareValue))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PU (PieceSquareTablePair pieceSquareValue)
-> PU (Maybe (PieceSquareTablePair pieceSquareValue))
forall a. PU a -> PU (Maybe a)
HXT.xpOption (PU (PieceSquareTablePair pieceSquareValue)
 -> PU (Maybe (PieceSquareTablePair pieceSquareValue)))
-> (PU (PieceSquareTablePair pieceSquareValue)
    -> PU (PieceSquareTablePair pieceSquareValue))
-> PU (PieceSquareTablePair pieceSquareValue)
-> PU (Maybe (PieceSquareTablePair pieceSquareValue))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String
-> PU (PieceSquareTablePair pieceSquareValue)
-> PU (PieceSquareTablePair pieceSquareValue)
forall a. String -> PU a -> PU a
HXT.xpElem String
pieceSquareTablesTag (PU (PieceSquareTablePair pieceSquareValue)
 -> PU (EvaluationOptions pieceSquareValue))
-> PU (PieceSquareTablePair pieceSquareValue)
-> PU (EvaluationOptions pieceSquareValue)
forall a b. (a -> b) -> a -> b
$ String
-> PU (PieceSquareTable pieceSquareValue)
-> PU (PieceSquareTable pieceSquareValue)
forall a. String -> PU a -> PU a
HXT.xpElem String
Input.PieceSquareTable.tag PU (PieceSquareTable pieceSquareValue)
forall a. XmlPickler a => PU a
HXT.xpickle PU (PieceSquareTable pieceSquareValue)
-> PU (PieceSquareTable pieceSquareValue)
-> PU (PieceSquareTablePair pieceSquareValue)
forall a b. PU a -> PU b -> PU (a, b)
`HXT.xpPair` String
-> PU (PieceSquareTable pieceSquareValue)
-> PU (PieceSquareTable pieceSquareValue)
forall a. String -> PU a -> PU a
HXT.xpElem String
pieceSquareTableEndGameTag PU (PieceSquareTable pieceSquareValue)
forall a. XmlPickler a => PU a
HXT.xpickle where
		def :: EvaluationOptions pieceSquareValue
def	= EvaluationOptions pieceSquareValue
forall a. Default a => a
Data.Default.def

-- | Convert a /PieceSquareTablePair/ to a single linearly interpolated array.
fromPieceSquareTablePair :: Fractional pieceSquareValue => PieceSquareTablePair pieceSquareValue -> Component.PieceSquareByCoordinatesByRank.PieceSquareByCoordinatesByRank pieceSquareValue
fromPieceSquareTablePair :: PieceSquareTablePair pieceSquareValue
-> PieceSquareByCoordinatesByRank pieceSquareValue
fromPieceSquareTablePair PieceSquareTablePair pieceSquareValue
pieceSquareTablePair	= (Rank
 -> EitherPieceSquareValueByNPiecesByCoordinates pieceSquareValue)
-> PieceSquareByCoordinatesByRank pieceSquareValue
forall pieceSquareValue.
(Rank
 -> EitherPieceSquareValueByNPiecesByCoordinates pieceSquareValue)
-> PieceSquareByCoordinatesByRank pieceSquareValue
Component.PieceSquareByCoordinatesByRank.mkPieceSquareByCoordinatesByRank ((Rank
  -> EitherPieceSquareValueByNPiecesByCoordinates pieceSquareValue)
 -> PieceSquareByCoordinatesByRank pieceSquareValue)
-> (Rank
    -> EitherPieceSquareValueByNPiecesByCoordinates pieceSquareValue)
-> PieceSquareByCoordinatesByRank pieceSquareValue
forall a b. (a -> b) -> a -> b
$ \Rank
rank -> (
	\(Array Coordinates pieceSquareValue
openingGamePieceSquareValuesByCoordinates, Maybe (Array Coordinates pieceSquareValue)
maybeEndGamePieceSquareValuesByCoordinates) -> EitherPieceSquareValueByNPiecesByCoordinates pieceSquareValue
-> (Array Coordinates pieceSquareValue
    -> EitherPieceSquareValueByNPiecesByCoordinates pieceSquareValue)
-> Maybe (Array Coordinates pieceSquareValue)
-> EitherPieceSquareValueByNPiecesByCoordinates pieceSquareValue
forall b a. b -> (a -> b) -> Maybe a -> b
Data.Maybe.maybe (
		Array Coordinates pieceSquareValue
-> EitherPieceSquareValueByNPiecesByCoordinates pieceSquareValue
forall a b. a -> Either a b
Left Array Coordinates pieceSquareValue
openingGamePieceSquareValuesByCoordinates
	) (
		Array Coordinates (PieceSquareValueByNPieces pieceSquareValue)
-> EitherPieceSquareValueByNPiecesByCoordinates pieceSquareValue
forall a b. b -> Either a b
Right (Array Coordinates (PieceSquareValueByNPieces pieceSquareValue)
 -> EitherPieceSquareValueByNPiecesByCoordinates pieceSquareValue)
-> (Array Coordinates pieceSquareValue
    -> Array Coordinates (PieceSquareValueByNPieces pieceSquareValue))
-> Array Coordinates pieceSquareValue
-> EitherPieceSquareValueByNPiecesByCoordinates pieceSquareValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [PieceSquareValueByNPieces pieceSquareValue]
-> Array Coordinates (PieceSquareValueByNPieces pieceSquareValue)
forall (a :: * -> * -> *) e. IArray a e => [e] -> a Coordinates e
Cartesian.Coordinates.listArrayByCoordinates ([PieceSquareValueByNPieces pieceSquareValue]
 -> Array Coordinates (PieceSquareValueByNPieces pieceSquareValue))
-> (Array Coordinates pieceSquareValue
    -> [PieceSquareValueByNPieces pieceSquareValue])
-> Array Coordinates pieceSquareValue
-> Array Coordinates (PieceSquareValueByNPieces pieceSquareValue)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (pieceSquareValue
 -> pieceSquareValue -> PieceSquareValueByNPieces pieceSquareValue)
-> [pieceSquareValue]
-> [pieceSquareValue]
-> [PieceSquareValueByNPieces pieceSquareValue]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith pieceSquareValue
-> pieceSquareValue -> PieceSquareValueByNPieces pieceSquareValue
forall pieceSquareValue.
Fractional pieceSquareValue =>
pieceSquareValue
-> pieceSquareValue -> PieceSquareValueByNPieces pieceSquareValue
Component.PieceSquareByCoordinatesByRank.interpolatePieceSquareValues (
			Array Coordinates pieceSquareValue -> [pieceSquareValue]
forall (t :: * -> *) a. Foldable t => t a -> [a]
Data.Foldable.toList Array Coordinates pieceSquareValue
openingGamePieceSquareValuesByCoordinates
		) ([pieceSquareValue]
 -> [PieceSquareValueByNPieces pieceSquareValue])
-> (Array Coordinates pieceSquareValue -> [pieceSquareValue])
-> Array Coordinates pieceSquareValue
-> [PieceSquareValueByNPieces pieceSquareValue]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array Coordinates pieceSquareValue -> [pieceSquareValue]
forall (t :: * -> *) a. Foldable t => t a -> [a]
Data.Foldable.toList
	) Maybe (Array Coordinates pieceSquareValue)
maybeEndGamePieceSquareValuesByCoordinates
 ) ((Array Coordinates pieceSquareValue,
  Maybe (Array Coordinates pieceSquareValue))
 -> EitherPieceSquareValueByNPiecesByCoordinates pieceSquareValue)
-> (Array Coordinates pieceSquareValue,
    Maybe (Array Coordinates pieceSquareValue))
-> EitherPieceSquareValueByNPiecesByCoordinates pieceSquareValue
forall a b. (a -> b) -> a -> b
$ (
	 Maybe (Array Coordinates pieceSquareValue)
-> Array Coordinates pieceSquareValue
forall a. HasCallStack => Maybe a -> a
Data.Maybe.fromJust {-values for the openingGame must be specified-} (Maybe (Array Coordinates pieceSquareValue)
 -> Array Coordinates pieceSquareValue)
-> (PieceSquareTable pieceSquareValue
    -> Maybe (Array Coordinates pieceSquareValue))
-> PieceSquareTable pieceSquareValue
-> Array Coordinates pieceSquareValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rank
-> PieceSquareTable pieceSquareValue
-> Maybe (Array Coordinates pieceSquareValue)
forall pieceSquareValue.
Rank
-> PieceSquareTable pieceSquareValue
-> Maybe (ArrayByCoordinates pieceSquareValue)
Input.PieceSquareTable.dereference Rank
rank (PieceSquareTable pieceSquareValue
 -> Array Coordinates pieceSquareValue)
-> (PieceSquareTable pieceSquareValue
    -> Maybe (Array Coordinates pieceSquareValue))
-> PieceSquareTablePair pieceSquareValue
-> (Array Coordinates pieceSquareValue,
    Maybe (Array Coordinates pieceSquareValue))
forall (a :: * -> * -> *) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
*** Rank
-> PieceSquareTable pieceSquareValue
-> Maybe (Array Coordinates pieceSquareValue)
forall pieceSquareValue.
Rank
-> PieceSquareTable pieceSquareValue
-> Maybe (ArrayByCoordinates pieceSquareValue)
Input.PieceSquareTable.dereference Rank
rank
 ) PieceSquareTablePair pieceSquareValue
pieceSquareTablePair

-- | Smart constructor.
mkEvaluationOptions
	:: Fractional pieceSquareValue
	=> Input.RankValues.RankValues				-- ^ The static value associated with each /piece/'s /rank/.
	-> Input.CriteriaWeights.CriteriaWeights		-- ^ The weights applied to the values of the criteria used to select a /move/.
	-> IncrementalEvaluation
	-> Maybe (PieceSquareTablePair pieceSquareValue)	-- ^ The value to each type of piece, of each square, during normal play & the end-game.
	-> EvaluationOptions pieceSquareValue
mkEvaluationOptions :: RankValues
-> CriteriaWeights
-> IncrementalEvaluation
-> Maybe (PieceSquareTablePair pieceSquareValue)
-> EvaluationOptions pieceSquareValue
mkEvaluationOptions RankValues
rankValues CriteriaWeights
criteriaWeights IncrementalEvaluation
incrementalEvaluation Maybe (PieceSquareTablePair pieceSquareValue)
maybePieceSquareTablePair
	| Just (PieceSquareTable pieceSquareValue
pieceSquareTable, PieceSquareTable pieceSquareValue
_)	<- Maybe (PieceSquareTablePair pieceSquareValue)
maybePieceSquareTablePair
	, let undefinedRanks :: Set Rank
undefinedRanks	= PieceSquareTable pieceSquareValue -> Set Rank
forall pieceSquareValue.
PieceSquareTable pieceSquareValue -> Set Rank
Input.PieceSquareTable.findUndefinedRanks PieceSquareTable pieceSquareValue
pieceSquareTable
	, IncrementalEvaluation -> IncrementalEvaluation
not (IncrementalEvaluation -> IncrementalEvaluation)
-> IncrementalEvaluation -> IncrementalEvaluation
forall a b. (a -> b) -> a -> b
$ Set Rank -> IncrementalEvaluation
forall (t :: * -> *) a. Foldable t => t a -> IncrementalEvaluation
Data.Foldable.null Set Rank
undefinedRanks
	= Exception -> EvaluationOptions pieceSquareValue
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> EvaluationOptions pieceSquareValue)
-> (String -> Exception)
-> String
-> EvaluationOptions pieceSquareValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Exception
Data.Exception.mkInsufficientData (String -> Exception) -> ShowS -> String -> Exception
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"BishBosh.Input.EvaluationOptions.mkEvaluationOptions:\tranks" ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
Text.ShowList.showsAssociation (String -> EvaluationOptions pieceSquareValue)
-> String -> EvaluationOptions pieceSquareValue
forall a b. (a -> b) -> a -> b
$ [Rank] -> ShowS
forall a. Show a => a -> ShowS
shows (Set Rank -> [Rank]
forall (t :: * -> *) a. Foldable t => t a -> [a]
Data.Foldable.toList Set Rank
undefinedRanks) String
" are undefined."
	| CriteriaWeights -> CriterionWeight
Input.CriteriaWeights.getWeightOfPieceSquareValue CriteriaWeights
criteriaWeights CriterionWeight -> CriterionWeight -> IncrementalEvaluation
forall a. Eq a => a -> a -> IncrementalEvaluation
/= CriterionWeight
forall a. Bounded a => a
minBound
	, Maybe (PieceSquareTablePair pieceSquareValue)
-> IncrementalEvaluation
forall a. Maybe a -> IncrementalEvaluation
Data.Maybe.isNothing Maybe (PieceSquareTablePair pieceSquareValue)
maybePieceSquareTablePair
	= Exception -> EvaluationOptions pieceSquareValue
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> EvaluationOptions pieceSquareValue)
-> (String -> Exception)
-> String
-> EvaluationOptions pieceSquareValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Exception
Data.Exception.mkIncompatibleData (String -> Exception) -> ShowS -> String -> Exception
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"BishBosh.Input.EvaluationOptions.mkEvaluationOptions:\tweight of " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
forall a. Show a => a -> ShowS
shows String
Input.CriteriaWeights.weightOfPieceSquareValueTag ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" is defined but " (String -> EvaluationOptions pieceSquareValue)
-> String -> EvaluationOptions pieceSquareValue
forall a b. (a -> b) -> a -> b
$ String -> ShowS
forall a. Show a => a -> ShowS
shows String
Input.PieceSquareTable.tag String
" isn't."
	| RankValue
maximumTotalRankValue RankValue -> RankValue -> IncrementalEvaluation
forall a. Eq a => a -> a -> IncrementalEvaluation
== RankValue
0 IncrementalEvaluation
-> IncrementalEvaluation -> IncrementalEvaluation
&& CriteriaWeights -> CriterionWeight
Input.CriteriaWeights.getWeightOfMaterial CriteriaWeights
criteriaWeights CriterionWeight -> CriterionWeight -> IncrementalEvaluation
forall a. Eq a => a -> a -> IncrementalEvaluation
/= CriterionWeight
0	= Exception -> EvaluationOptions pieceSquareValue
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> EvaluationOptions pieceSquareValue)
-> (String -> Exception)
-> String
-> EvaluationOptions pieceSquareValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Exception
Data.Exception.mkIncompatibleData (String -> Exception) -> ShowS -> String -> Exception
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"BishBosh.Input.EvaluationOptions.mkEvaluationOptions:\tweight of " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
forall a. Show a => a -> ShowS
shows String
Input.CriteriaWeights.weightOfMaterialTag ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" is non-zero, but the maximum total rank-value is " (String -> EvaluationOptions pieceSquareValue)
-> String -> EvaluationOptions pieceSquareValue
forall a b. (a -> b) -> a -> b
$ RankValues -> ShowS
forall a. Show a => a -> ShowS
shows RankValues
rankValues String
"."
	| IncrementalEvaluation
otherwise		= MkEvaluationOptions :: forall pieceSquareValue.
RankValues
-> RankValue
-> CriteriaWeights
-> IncrementalEvaluation
-> Maybe (PieceSquareTablePair pieceSquareValue)
-> Maybe (PieceSquareByCoordinatesByRank pieceSquareValue)
-> EvaluationOptions pieceSquareValue
MkEvaluationOptions {
		getRankValues :: RankValues
getRankValues				= RankValues
rankValues,
		getMaximumTotalRankValue :: RankValue
getMaximumTotalRankValue		= RankValue
maximumTotalRankValue,
		getCriteriaWeights :: CriteriaWeights
getCriteriaWeights			= CriteriaWeights
criteriaWeights,
		getIncrementalEvaluation :: IncrementalEvaluation
getIncrementalEvaluation		= IncrementalEvaluation
incrementalEvaluation,
		getMaybePieceSquareTablePair :: Maybe (PieceSquareTablePair pieceSquareValue)
getMaybePieceSquareTablePair		= Maybe (PieceSquareTablePair pieceSquareValue)
maybePieceSquareTablePair,
		getMaybePieceSquareByCoordinatesByRank :: Maybe (PieceSquareByCoordinatesByRank pieceSquareValue)
getMaybePieceSquareByCoordinatesByRank	= PieceSquareTablePair pieceSquareValue
-> PieceSquareByCoordinatesByRank pieceSquareValue
forall pieceSquareValue.
Fractional pieceSquareValue =>
PieceSquareTablePair pieceSquareValue
-> PieceSquareByCoordinatesByRank pieceSquareValue
fromPieceSquareTablePair (PieceSquareTablePair pieceSquareValue
 -> PieceSquareByCoordinatesByRank pieceSquareValue)
-> Maybe (PieceSquareTablePair pieceSquareValue)
-> Maybe (PieceSquareByCoordinatesByRank pieceSquareValue)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` Maybe (PieceSquareTablePair pieceSquareValue)
maybePieceSquareTablePair	-- Infer.
	} where
		maximumTotalRankValue :: RankValue
maximumTotalRankValue	= RankValues -> RankValue
Input.RankValues.calculateMaximumTotalValue RankValues
rankValues

-- | Self-documentation.
type Reader pieceSquareValue	= Control.Monad.Reader.Reader (EvaluationOptions pieceSquareValue)