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

	* Constructs a tree in which each node contains,
	a zobrist-hash,
	a /quantifiedGame/ with one of the moves available to its parent node applied & evaluation of the fitness of the resulting position.

	* Each forest in the tree is sorted, before evaluation of its fitness is performed.

	* CAVEAT: promotions are insufficiently frequent to be treated specially when sorting.
-}

module BishBosh.Evaluation.PositionHashQuantifiedGameTree(
-- * Types
-- ** Type-synonyms
--	BarePositionHashQuantifiedGameTree,
	Forest,
-- ** Data-types
	NodeLabel(
--		MkNodeLabel,
		getPositionHash,
		getQuantifiedGame
	),
	PositionHashQuantifiedGameTree(
		MkPositionHashQuantifiedGameTree,
		deconstruct
	),
-- * Functions
	reduce,
	traceRoute,
	resign,
	traceMatchingMoves,
	promoteMatchingMoves,
	sortNonCaptureMoves,
-- ** Accessors
	getRootQuantifiedGame',
	getRootPositionHash,
	getRootQuantifiedGame,
-- ** Constructor
	fromBarePositionHashQuantifiedGameTree,
	mkPositionHashQuantifiedGameTree
-- ** Predicates
--	equalsLastMove
 ) where

import			Control.Arrow((&&&))
import qualified	BishBosh.Attribute.RankValues				as Attribute.RankValues
import qualified	BishBosh.Attribute.WeightedMeanAndCriterionValues	as Attribute.WeightedMeanAndCriterionValues
import qualified	BishBosh.Component.Move					as Component.Move
import qualified	BishBosh.Component.QualifiedMove			as Component.QualifiedMove
import qualified	BishBosh.Component.Turn					as Component.Turn
import qualified	BishBosh.Component.Zobrist				as Component.Zobrist
import qualified	BishBosh.Data.RoseTree					as Data.RoseTree
import qualified	BishBosh.Evaluation.Fitness				as Evaluation.Fitness
import qualified	BishBosh.Evaluation.QuantifiedGame			as Evaluation.QuantifiedGame
import qualified	BishBosh.Input.EvaluationOptions			as Input.EvaluationOptions
import qualified	BishBosh.Input.SearchOptions				as Input.SearchOptions
import qualified	BishBosh.Model.Game					as Model.Game
import qualified	BishBosh.Model.GameTree					as Model.GameTree
import qualified	BishBosh.Notation.MoveNotation				as Notation.MoveNotation
import qualified	BishBosh.Property.Null					as Property.Null
import qualified	BishBosh.Property.Tree					as Property.Tree
import qualified	BishBosh.Types						as T
import qualified	Control.Arrow
import qualified	Control.Monad.Reader
import qualified	Data.Array.IArray
import qualified	Data.Bits
import qualified	Data.Maybe
import qualified	Data.Tree

-- | Define a node in the tree to contain the hash of a /game/ & an evaluation of the fitness of that /game/.
data NodeLabel x y positionHash criterionValue weightedMean	= MkNodeLabel {
	NodeLabel x y positionHash criterionValue weightedMean
-> positionHash
getPositionHash		:: positionHash,	-- ^ The hash of the /game/ contained in 'getQuantifiedGame'.
	NodeLabel x y positionHash criterionValue weightedMean
-> QuantifiedGame x y criterionValue weightedMean
getQuantifiedGame	:: Evaluation.QuantifiedGame.QuantifiedGame x y criterionValue weightedMean
} deriving (NodeLabel x y positionHash criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean -> Bool
(NodeLabel x y positionHash criterionValue weightedMean
 -> NodeLabel x y positionHash criterionValue weightedMean -> Bool)
-> (NodeLabel x y positionHash criterionValue weightedMean
    -> NodeLabel x y positionHash criterionValue weightedMean -> Bool)
-> Eq (NodeLabel x y positionHash criterionValue weightedMean)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall x y positionHash criterionValue weightedMean.
(Enum x, Enum y, Ord x, Ord y, Eq positionHash, Eq weightedMean,
 Eq criterionValue) =>
NodeLabel x y positionHash criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean -> Bool
/= :: NodeLabel x y positionHash criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean -> Bool
$c/= :: forall x y positionHash criterionValue weightedMean.
(Enum x, Enum y, Ord x, Ord y, Eq positionHash, Eq weightedMean,
 Eq criterionValue) =>
NodeLabel x y positionHash criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean -> Bool
== :: NodeLabel x y positionHash criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean -> Bool
$c== :: forall x y positionHash criterionValue weightedMean.
(Enum x, Enum y, Ord x, Ord y, Eq positionHash, Eq weightedMean,
 Eq criterionValue) =>
NodeLabel x y positionHash criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean -> Bool
Eq, Int
-> NodeLabel x y positionHash criterionValue weightedMean -> ShowS
[NodeLabel x y positionHash criterionValue weightedMean] -> ShowS
NodeLabel x y positionHash criterionValue weightedMean -> String
(Int
 -> NodeLabel x y positionHash criterionValue weightedMean -> ShowS)
-> (NodeLabel x y positionHash criterionValue weightedMean
    -> String)
-> ([NodeLabel x y positionHash criterionValue weightedMean]
    -> ShowS)
-> Show (NodeLabel x y positionHash criterionValue weightedMean)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall x y positionHash criterionValue weightedMean.
(Enum x, Enum y, Ord x, Ord y, Show positionHash, Show x, Show y,
 Show weightedMean, Show criterionValue) =>
Int
-> NodeLabel x y positionHash criterionValue weightedMean -> ShowS
forall x y positionHash criterionValue weightedMean.
(Enum x, Enum y, Ord x, Ord y, Show positionHash, Show x, Show y,
 Show weightedMean, Show criterionValue) =>
[NodeLabel x y positionHash criterionValue weightedMean] -> ShowS
forall x y positionHash criterionValue weightedMean.
(Enum x, Enum y, Ord x, Ord y, Show positionHash, Show x, Show y,
 Show weightedMean, Show criterionValue) =>
NodeLabel x y positionHash criterionValue weightedMean -> String
showList :: [NodeLabel x y positionHash criterionValue weightedMean] -> ShowS
$cshowList :: forall x y positionHash criterionValue weightedMean.
(Enum x, Enum y, Ord x, Ord y, Show positionHash, Show x, Show y,
 Show weightedMean, Show criterionValue) =>
[NodeLabel x y positionHash criterionValue weightedMean] -> ShowS
show :: NodeLabel x y positionHash criterionValue weightedMean -> String
$cshow :: forall x y positionHash criterionValue weightedMean.
(Enum x, Enum y, Ord x, Ord y, Show positionHash, Show x, Show y,
 Show weightedMean, Show criterionValue) =>
NodeLabel x y positionHash criterionValue weightedMean -> String
showsPrec :: Int
-> NodeLabel x y positionHash criterionValue weightedMean -> ShowS
$cshowsPrec :: forall x y positionHash criterionValue weightedMean.
(Enum x, Enum y, Ord x, Ord y, Show positionHash, Show x, Show y,
 Show weightedMean, Show criterionValue) =>
Int
-> NodeLabel x y positionHash criterionValue weightedMean -> ShowS
Show)

instance (Enum x, Enum y, Real weightedMean) => Notation.MoveNotation.ShowNotationFloat (NodeLabel x y positionHash criterionValue weightedMean) where
	showsNotationFloat :: MoveNotation
-> (Double -> ShowS)
-> NodeLabel x y positionHash criterionValue weightedMean
-> ShowS
showsNotationFloat MoveNotation
moveNotation Double -> ShowS
showsDouble MkNodeLabel { getQuantifiedGame :: forall x y positionHash criterionValue weightedMean.
NodeLabel x y positionHash criterionValue weightedMean
-> QuantifiedGame x y criterionValue weightedMean
getQuantifiedGame = QuantifiedGame x y criterionValue weightedMean
quantifiedGame }	= MoveNotation -> Turn x y -> ShowS
forall a. ShowNotation a => MoveNotation -> a -> ShowS
Notation.MoveNotation.showsNotation MoveNotation
moveNotation (
		QuantifiedGame x y criterionValue weightedMean -> Turn x y
forall x y criterionValue weightedMean.
QuantifiedGame x y criterionValue weightedMean -> Turn x y
Evaluation.QuantifiedGame.getLastTurn QuantifiedGame x y criterionValue weightedMean
quantifiedGame
	 ) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"\t=> " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> ShowS
showsDouble (
		weightedMean -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac (weightedMean -> Double)
-> (WeightedMeanAndCriterionValues weightedMean criterionValue
    -> weightedMean)
-> WeightedMeanAndCriterionValues weightedMean criterionValue
-> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WeightedMeanAndCriterionValues weightedMean criterionValue
-> weightedMean
forall weightedMean criterionValue.
WeightedMeanAndCriterionValues weightedMean criterionValue
-> weightedMean
Attribute.WeightedMeanAndCriterionValues.getWeightedMean (WeightedMeanAndCriterionValues weightedMean criterionValue
 -> Double)
-> WeightedMeanAndCriterionValues weightedMean criterionValue
-> Double
forall a b. (a -> b) -> a -> b
$ QuantifiedGame x y criterionValue weightedMean
-> WeightedMeanAndCriterionValues weightedMean criterionValue
forall x y criterionValue weightedMean.
QuantifiedGame x y criterionValue weightedMean
-> WeightedMeanAndCriterionValues weightedMean criterionValue
Evaluation.QuantifiedGame.getWeightedMeanAndCriterionValues QuantifiedGame x y criterionValue weightedMean
quantifiedGame
	 )

instance Property.Null.Null (NodeLabel x y positionHash criterionValue weightedMean) where
	isNull :: NodeLabel x y positionHash criterionValue weightedMean -> Bool
isNull MkNodeLabel { getQuantifiedGame :: forall x y positionHash criterionValue weightedMean.
NodeLabel x y positionHash criterionValue weightedMean
-> QuantifiedGame x y criterionValue weightedMean
getQuantifiedGame = QuantifiedGame x y criterionValue weightedMean
quantifiedGame }	= QuantifiedGame x y criterionValue weightedMean -> Bool
forall a. Null a => a -> Bool
Property.Null.isNull QuantifiedGame x y criterionValue weightedMean
quantifiedGame

-- | Whether the last move of the /game/ in a node, matches a specified /move/.
equalsLastMove :: (Eq x, Eq y) => Component.Move.Move x y -> Data.RoseTree.IsMatch (NodeLabel x y positionHash criterionValue weightedMean)
equalsLastMove :: Move x y
-> IsMatch (NodeLabel x y positionHash criterionValue weightedMean)
equalsLastMove Move x y
move MkNodeLabel { getQuantifiedGame :: forall x y positionHash criterionValue weightedMean.
NodeLabel x y positionHash criterionValue weightedMean
-> QuantifiedGame x y criterionValue weightedMean
getQuantifiedGame = QuantifiedGame x y criterionValue weightedMean
quantifiedGame }	= (Move x y -> Move x y -> Bool
forall a. Eq a => a -> a -> Bool
== Move x y
move) (Move x y -> Bool) -> (Turn x y -> Move x y) -> Turn x y -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QualifiedMove x y -> Move x y
forall x y. QualifiedMove x y -> Move x y
Component.QualifiedMove.getMove (QualifiedMove x y -> Move x y)
-> (Turn x y -> QualifiedMove x y) -> Turn x y -> Move x y
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Turn x y -> QualifiedMove x y
forall x y. Turn x y -> QualifiedMove x y
Component.Turn.getQualifiedMove (Turn x y -> Bool) -> Turn x y -> Bool
forall a b. (a -> b) -> a -> b
$ QuantifiedGame x y criterionValue weightedMean -> Turn x y
forall x y criterionValue weightedMean.
QuantifiedGame x y criterionValue weightedMean -> Turn x y
Evaluation.QuantifiedGame.getLastTurn QuantifiedGame x y criterionValue weightedMean
quantifiedGame

-- | The tree resulting from each possible move-choice applied to a /game/, including a position-hash & an evaluation of the resulting fitness.
type BarePositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean	= Data.Tree.Tree (NodeLabel x y positionHash criterionValue weightedMean)

-- | Accessor.
getRootQuantifiedGame' :: BarePositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean -> Evaluation.QuantifiedGame.QuantifiedGame x y criterionValue weightedMean
getRootQuantifiedGame' :: BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> QuantifiedGame x y criterionValue weightedMean
getRootQuantifiedGame' Data.Tree.Node {
	rootLabel :: forall a. Tree a -> a
Data.Tree.rootLabel	= MkNodeLabel { getQuantifiedGame :: forall x y positionHash criterionValue weightedMean.
NodeLabel x y positionHash criterionValue weightedMean
-> QuantifiedGame x y criterionValue weightedMean
getQuantifiedGame = QuantifiedGame x y criterionValue weightedMean
quantifiedGame }
} = QuantifiedGame x y criterionValue weightedMean
quantifiedGame

-- | Wrap the bare tree.
newtype PositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean	= MkPositionHashQuantifiedGameTree {
	PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
deconstruct	:: BarePositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean
} deriving PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> Bool
(PositionHashQuantifiedGameTree
   x y positionHash criterionValue weightedMean
 -> PositionHashQuantifiedGameTree
      x y positionHash criterionValue weightedMean
 -> Bool)
-> (PositionHashQuantifiedGameTree
      x y positionHash criterionValue weightedMean
    -> PositionHashQuantifiedGameTree
         x y positionHash criterionValue weightedMean
    -> Bool)
-> Eq
     (PositionHashQuantifiedGameTree
        x y positionHash criterionValue weightedMean)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall x y positionHash criterionValue weightedMean.
(Enum x, Enum y, Ord x, Ord y, Eq positionHash, Eq weightedMean,
 Eq criterionValue) =>
PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> Bool
/= :: PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> Bool
$c/= :: forall x y positionHash criterionValue weightedMean.
(Enum x, Enum y, Ord x, Ord y, Eq positionHash, Eq weightedMean,
 Eq criterionValue) =>
PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> Bool
== :: PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> Bool
$c== :: forall x y positionHash criterionValue weightedMean.
(Enum x, Enum y, Ord x, Ord y, Eq positionHash, Eq weightedMean,
 Eq criterionValue) =>
PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> Bool
Eq

instance Property.Tree.Prunable (PositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean) where
	prune :: Int
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
prune Int
depth MkPositionHashQuantifiedGameTree { deconstruct :: forall x y positionHash criterionValue weightedMean.
PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
deconstruct = BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
barePositionHashQuantifiedGameTree }	= BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
forall x y positionHash criterionValue weightedMean.
BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
MkPositionHashQuantifiedGameTree (BarePositionHashQuantifiedGameTree
   x y positionHash criterionValue weightedMean
 -> PositionHashQuantifiedGameTree
      x y positionHash criterionValue weightedMean)
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
forall a b. (a -> b) -> a -> b
$ Int
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
forall tree. Prunable tree => Int -> tree -> tree
Property.Tree.prune Int
depth BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
barePositionHashQuantifiedGameTree

instance (
	Enum	x,
	Enum	y,
	Real	weightedMean
 ) => Notation.MoveNotation.ShowNotationFloat (PositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean) where
	showsNotationFloat :: MoveNotation
-> (Double -> ShowS)
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> ShowS
showsNotationFloat MoveNotation
moveNotation Double -> ShowS
showsDouble MkPositionHashQuantifiedGameTree { deconstruct :: forall x y positionHash criterionValue weightedMean.
PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
deconstruct = BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
barePositionHashQuantifiedGameTree } = String -> ShowS
showString (String -> ShowS) -> String -> ShowS
forall a b. (a -> b) -> a -> b
$ (
		if NodeLabel x y positionHash criterionValue weightedMean -> Bool
forall a. Null a => a -> Bool
Property.Null.isNull (NodeLabel x y positionHash criterionValue weightedMean -> Bool)
-> (BarePositionHashQuantifiedGameTree
      x y positionHash criterionValue weightedMean
    -> NodeLabel x y positionHash criterionValue weightedMean)
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean
forall a. Tree a -> a
Data.Tree.rootLabel (BarePositionHashQuantifiedGameTree
   x y positionHash criterionValue weightedMean
 -> Bool)
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> Bool
forall a b. (a -> b) -> a -> b
$ BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
barePositionHashQuantifiedGameTree
			then (NodeLabel x y positionHash criterionValue weightedMean -> String)
-> Forest (NodeLabel x y positionHash criterionValue weightedMean)
-> String
forall a. (a -> String) -> Forest a -> String
Data.RoseTree.drawForest NodeLabel x y positionHash criterionValue weightedMean -> String
forall a. ShowNotationFloat a => a -> String
toString (Forest (NodeLabel x y positionHash criterionValue weightedMean)
 -> String)
-> (BarePositionHashQuantifiedGameTree
      x y positionHash criterionValue weightedMean
    -> Forest (NodeLabel x y positionHash criterionValue weightedMean))
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> Forest (NodeLabel x y positionHash criterionValue weightedMean)
forall a. Tree a -> Forest a
Data.Tree.subForest
			else (NodeLabel x y positionHash criterionValue weightedMean -> String)
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> String
forall a. (a -> String) -> Tree a -> String
Data.RoseTree.drawTree NodeLabel x y positionHash criterionValue weightedMean -> String
forall a. ShowNotationFloat a => a -> String
toString
	 ) BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
barePositionHashQuantifiedGameTree where
		toString :: a -> String
toString a
nodeLabel	= MoveNotation -> (Double -> ShowS) -> a -> ShowS
forall a.
ShowNotationFloat a =>
MoveNotation -> (Double -> ShowS) -> a -> ShowS
Notation.MoveNotation.showsNotationFloat MoveNotation
moveNotation Double -> ShowS
showsDouble a
nodeLabel String
""

-- | Constructor.
fromBarePositionHashQuantifiedGameTree :: BarePositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean -> PositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean
fromBarePositionHashQuantifiedGameTree :: BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
fromBarePositionHashQuantifiedGameTree	= BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
forall x y positionHash criterionValue weightedMean.
BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
MkPositionHashQuantifiedGameTree

-- | Constructor.
mkPositionHashQuantifiedGameTree :: (
	Data.Array.IArray.Ix	x,
	Data.Bits.Bits		positionHash,
	Fractional		criterionValue,
	Fractional		pieceSquareValue,
	Fractional		rankValue,
	Fractional		weightedMean,
	Integral		x,
	Integral		y,
	Real			criterionValue,
	Real			criterionWeight,
	Real			pieceSquareValue,
	Real			rankValue,
	Show			x,
	Show			y
 )
	=> Input.EvaluationOptions.EvaluationOptions criterionWeight pieceSquareValue rankValue x y
	-> Input.SearchOptions.SearchOptions
	-> Component.Zobrist.Zobrist x y positionHash
	-> Model.GameTree.MoveFrequency x y
	-> Model.Game.Game x y	-- ^ The current state of the /game/.
	-> PositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean
{-# SPECIALISE mkPositionHashQuantifiedGameTree
	:: Input.EvaluationOptions.EvaluationOptions T.CriterionWeight T.PieceSquareValue T.RankValue T.X T.Y
	-> Input.SearchOptions.SearchOptions
	-> Component.Zobrist.Zobrist T.X T.Y T.PositionHash
	-> Model.GameTree.MoveFrequency T.X T.Y
	-> Model.Game.Game T.X T.Y
	-> PositionHashQuantifiedGameTree T.X T.Y T.PositionHash T.CriterionValue T.WeightedMean
 #-}
mkPositionHashQuantifiedGameTree :: EvaluationOptions criterionWeight pieceSquareValue rankValue x y
-> SearchOptions
-> Zobrist x y positionHash
-> MoveFrequency x y
-> Game x y
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
mkPositionHashQuantifiedGameTree EvaluationOptions criterionWeight pieceSquareValue rankValue x y
evaluationOptions SearchOptions
searchOptions Zobrist x y positionHash
zobrist MoveFrequency x y
moveFrequency Game x y
seedGame	= BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
forall x y positionHash criterionValue weightedMean.
BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
MkPositionHashQuantifiedGameTree (
	if EvaluationOptions criterionWeight pieceSquareValue rankValue x y
-> Bool
forall criterionWeight pieceSquareValue rankValue x y.
EvaluationOptions criterionWeight pieceSquareValue rankValue x y
-> Bool
Input.EvaluationOptions.getIncrementalEvaluation EvaluationOptions criterionWeight pieceSquareValue rankValue x y
evaluationOptions
		then let
			apexPositionHash :: positionHash
apexPositionHash	= Game x y -> Zobrist x y positionHash -> positionHash
forall positionHash (hashable :: * -> * -> *) x y.
(Bits positionHash, Hashable2D hashable x y) =>
hashable x y -> Zobrist x y positionHash -> positionHash
Component.Zobrist.hash2D Game x y
seedGame Zobrist x y positionHash
zobrist
		in Node :: forall a. a -> Forest a -> Tree a
Data.Tree.Node {
			rootLabel :: NodeLabel x y positionHash criterionValue weightedMean
Data.Tree.rootLabel	= positionHash
-> QuantifiedGame x y criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean
forall x y positionHash criterionValue weightedMean.
positionHash
-> QuantifiedGame x y criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean
MkNodeLabel positionHash
apexPositionHash (QuantifiedGame x y criterionValue weightedMean
 -> NodeLabel x y positionHash criterionValue weightedMean)
-> QuantifiedGame x y criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean
forall a b. (a -> b) -> a -> b
$ Reader
  (EvaluationOptions criterionWeight pieceSquareValue rankValue x y)
  (QuantifiedGame x y criterionValue weightedMean)
-> EvaluationOptions criterionWeight pieceSquareValue rankValue x y
-> QuantifiedGame x y criterionValue weightedMean
forall r a. Reader r a -> r -> a
Control.Monad.Reader.runReader (
				Maybe pieceSquareValue
-> Game x y
-> Reader
     (EvaluationOptions criterionWeight pieceSquareValue rankValue x y)
     (QuantifiedGame x y criterionValue weightedMean)
forall x y criterionValue pieceSquareValue rankValue weightedMean
       criterionWeight.
(Enum x, Enum y, Fractional criterionValue,
 Fractional pieceSquareValue, Fractional rankValue,
 Fractional weightedMean, Ord x, Ord y, Real criterionValue,
 Real criterionWeight, Real pieceSquareValue, Real rankValue,
 Show x, Show y) =>
Maybe pieceSquareValue
-> Game x y
-> Reader
     criterionWeight
     pieceSquareValue
     rankValue
     x
     y
     (QuantifiedGame x y criterionValue weightedMean)
Evaluation.QuantifiedGame.fromGame Maybe pieceSquareValue
forall a. Maybe a
Nothing Game x y
seedGame
			) EvaluationOptions criterionWeight pieceSquareValue rankValue x y
evaluationOptions,	-- Neither the previous positionHash nor the previous pieceSquareValue, are available to support incremental construction.
			subForest :: Forest (NodeLabel x y positionHash criterionValue weightedMean)
Data.Tree.subForest	= (Tree (Game x y)
 -> BarePositionHashQuantifiedGameTree
      x y positionHash criterionValue weightedMean)
-> [Tree (Game x y)]
-> Forest (NodeLabel x y positionHash criterionValue weightedMean)
forall a b. (a -> b) -> [a] -> [b]
map (
				(positionHash
 -> Game x y
 -> Tree (Game x y)
 -> BarePositionHashQuantifiedGameTree
      x y positionHash criterionValue weightedMean)
-> (PieceSquareArray x y pieceSquareValue
    -> positionHash
    -> Game x y
    -> Tree (Game x y)
    -> BarePositionHashQuantifiedGameTree
         x y positionHash criterionValue weightedMean)
-> Maybe (PieceSquareArray x y pieceSquareValue)
-> positionHash
-> Game x y
-> Tree (Game x y)
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
forall b a. b -> (a -> b) -> Maybe a -> b
Data.Maybe.maybe (
					let
						slave :: positionHash
-> Game x y
-> Tree (Game x y)
-> Tree (NodeLabel x y positionHash criterionValue weightedMean)
slave positionHash
positionHash Game x y
game Data.Tree.Node {
							rootLabel :: forall a. Tree a -> a
Data.Tree.rootLabel	= Game x y
game',
							subForest :: forall a. Tree a -> Forest a
Data.Tree.subForest	= [Tree (Game x y)]
gameForest'
						} = Node :: forall a. a -> Forest a -> Tree a
Data.Tree.Node {
							rootLabel :: NodeLabel x y positionHash criterionValue weightedMean
Data.Tree.rootLabel	= positionHash
-> QuantifiedGame x y criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean
forall x y positionHash criterionValue weightedMean.
positionHash
-> QuantifiedGame x y criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean
MkNodeLabel positionHash
positionHash' (QuantifiedGame x y criterionValue weightedMean
 -> NodeLabel x y positionHash criterionValue weightedMean)
-> QuantifiedGame x y criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean
forall a b. (a -> b) -> a -> b
$ Reader
  (EvaluationOptions criterionWeight pieceSquareValue rankValue x y)
  (QuantifiedGame x y criterionValue weightedMean)
-> EvaluationOptions criterionWeight pieceSquareValue rankValue x y
-> QuantifiedGame x y criterionValue weightedMean
forall r a. Reader r a -> r -> a
Control.Monad.Reader.runReader (
								Maybe pieceSquareValue
-> Game x y
-> Reader
     (EvaluationOptions criterionWeight pieceSquareValue rankValue x y)
     (QuantifiedGame x y criterionValue weightedMean)
forall x y criterionValue pieceSquareValue rankValue weightedMean
       criterionWeight.
(Enum x, Enum y, Fractional criterionValue,
 Fractional pieceSquareValue, Fractional rankValue,
 Fractional weightedMean, Ord x, Ord y, Real criterionValue,
 Real criterionWeight, Real pieceSquareValue, Real rankValue,
 Show x, Show y) =>
Maybe pieceSquareValue
-> Game x y
-> Reader
     criterionWeight
     pieceSquareValue
     rankValue
     x
     y
     (QuantifiedGame x y criterionValue weightedMean)
Evaluation.QuantifiedGame.fromGame Maybe pieceSquareValue
forall a. Maybe a
Nothing Game x y
game'
							) EvaluationOptions criterionWeight pieceSquareValue rankValue x y
evaluationOptions,
							subForest :: Forest (NodeLabel x y positionHash criterionValue weightedMean)
Data.Tree.subForest	= (Tree (Game x y)
 -> Tree (NodeLabel x y positionHash criterionValue weightedMean))
-> [Tree (Game x y)]
-> Forest (NodeLabel x y positionHash criterionValue weightedMean)
forall a b. (a -> b) -> [a] -> [b]
map (positionHash
-> Game x y
-> Tree (Game x y)
-> Tree (NodeLabel x y positionHash criterionValue weightedMean)
slave positionHash
positionHash' Game x y
game') [Tree (Game x y)]
gameForest'	-- Recurse.
						} where
							positionHash' :: positionHash
positionHash'	= Game x y
-> positionHash
-> Game x y
-> Zobrist x y positionHash
-> positionHash
forall x positionHash y.
(Ix x, Bits positionHash, Enum x, Enum y, Ord y) =>
Game x y
-> positionHash
-> Game x y
-> Zobrist x y positionHash
-> positionHash
Model.Game.incrementalHash Game x y
game positionHash
positionHash Game x y
game' Zobrist x y positionHash
zobrist
					in positionHash
-> Game x y
-> Tree (Game x y)
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
forall criterionValue weightedMean.
(Fractional criterionValue, Fractional weightedMean,
 Real criterionValue) =>
positionHash
-> Game x y
-> Tree (Game x y)
-> Tree (NodeLabel x y positionHash criterionValue weightedMean)
slave
				) (
					\PieceSquareArray x y pieceSquareValue
pieceSquareArray -> let
						slave :: pieceSquareValue
-> positionHash
-> Game x y
-> Tree (Game x y)
-> Tree (NodeLabel x y positionHash criterionValue weightedMean)
slave pieceSquareValue
pieceSquareValue positionHash
positionHash Game x y
game Data.Tree.Node {
							rootLabel :: forall a. Tree a -> a
Data.Tree.rootLabel	= Game x y
game',
							subForest :: forall a. Tree a -> Forest a
Data.Tree.subForest	= [Tree (Game x y)]
gameForest'
						} = Node :: forall a. a -> Forest a -> Tree a
Data.Tree.Node {
							rootLabel :: NodeLabel x y positionHash criterionValue weightedMean
Data.Tree.rootLabel	= positionHash
-> QuantifiedGame x y criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean
forall x y positionHash criterionValue weightedMean.
positionHash
-> QuantifiedGame x y criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean
MkNodeLabel positionHash
positionHash' (QuantifiedGame x y criterionValue weightedMean
 -> NodeLabel x y positionHash criterionValue weightedMean)
-> QuantifiedGame x y criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean
forall a b. (a -> b) -> a -> b
$ Reader
  (EvaluationOptions criterionWeight pieceSquareValue rankValue x y)
  (QuantifiedGame x y criterionValue weightedMean)
-> EvaluationOptions criterionWeight pieceSquareValue rankValue x y
-> QuantifiedGame x y criterionValue weightedMean
forall r a. Reader r a -> r -> a
Control.Monad.Reader.runReader (
								Maybe pieceSquareValue
-> Game x y
-> Reader
     (EvaluationOptions criterionWeight pieceSquareValue rankValue x y)
     (QuantifiedGame x y criterionValue weightedMean)
forall x y criterionValue pieceSquareValue rankValue weightedMean
       criterionWeight.
(Enum x, Enum y, Fractional criterionValue,
 Fractional pieceSquareValue, Fractional rankValue,
 Fractional weightedMean, Ord x, Ord y, Real criterionValue,
 Real criterionWeight, Real pieceSquareValue, Real rankValue,
 Show x, Show y) =>
Maybe pieceSquareValue
-> Game x y
-> Reader
     criterionWeight
     pieceSquareValue
     rankValue
     x
     y
     (QuantifiedGame x y criterionValue weightedMean)
Evaluation.QuantifiedGame.fromGame (pieceSquareValue -> Maybe pieceSquareValue
forall a. a -> Maybe a
Just pieceSquareValue
pieceSquareValue') Game x y
game'
							) EvaluationOptions criterionWeight pieceSquareValue rankValue x y
evaluationOptions,
							subForest :: Forest (NodeLabel x y positionHash criterionValue weightedMean)
Data.Tree.subForest	= (Tree (Game x y)
 -> Tree (NodeLabel x y positionHash criterionValue weightedMean))
-> [Tree (Game x y)]
-> Forest (NodeLabel x y positionHash criterionValue weightedMean)
forall a b. (a -> b) -> [a] -> [b]
map (pieceSquareValue
-> positionHash
-> Game x y
-> Tree (Game x y)
-> Tree (NodeLabel x y positionHash criterionValue weightedMean)
slave pieceSquareValue
pieceSquareValue' positionHash
positionHash' Game x y
game') [Tree (Game x y)]
gameForest'	-- Recurse.
						} where
							pieceSquareValue' :: pieceSquareValue
pieceSquareValue'	= pieceSquareValue
-> PieceSquareArray x y pieceSquareValue
-> Game x y
-> pieceSquareValue
forall x y pieceSquareValue.
(Enum x, Enum y, Num pieceSquareValue, Ord x, Ord y) =>
pieceSquareValue
-> PieceSquareArray x y pieceSquareValue
-> Game x y
-> pieceSquareValue
Evaluation.Fitness.measurePieceSquareValueIncrementally pieceSquareValue
pieceSquareValue PieceSquareArray x y pieceSquareValue
pieceSquareArray Game x y
game'
							positionHash' :: positionHash
positionHash'		= Game x y
-> positionHash
-> Game x y
-> Zobrist x y positionHash
-> positionHash
forall x positionHash y.
(Ix x, Bits positionHash, Enum x, Enum y, Ord y) =>
Game x y
-> positionHash
-> Game x y
-> Zobrist x y positionHash
-> positionHash
Model.Game.incrementalHash Game x y
game positionHash
positionHash Game x y
game' Zobrist x y positionHash
zobrist
					in pieceSquareValue
-> positionHash
-> Game x y
-> Tree (Game x y)
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
forall criterionValue weightedMean.
(Fractional criterionValue, Fractional weightedMean,
 Real criterionValue) =>
pieceSquareValue
-> positionHash
-> Game x y
-> Tree (Game x y)
-> Tree (NodeLabel x y positionHash criterionValue weightedMean)
slave (pieceSquareValue
 -> positionHash
 -> Game x y
 -> Tree (Game x y)
 -> BarePositionHashQuantifiedGameTree
      x y positionHash criterionValue weightedMean)
-> pieceSquareValue
-> positionHash
-> Game x y
-> Tree (Game x y)
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
forall a b. (a -> b) -> a -> b
$ PieceSquareArray x y pieceSquareValue
-> Game x y -> pieceSquareValue
forall x y pieceSquareValue.
(Enum x, Enum y, Num pieceSquareValue, Ord x, Ord y) =>
PieceSquareArray x y pieceSquareValue
-> Game x y -> pieceSquareValue
Evaluation.Fitness.measurePieceSquareValue PieceSquareArray x y pieceSquareValue
pieceSquareArray Game x y
seedGame
				) (
					EvaluationOptions criterionWeight pieceSquareValue rankValue x y
-> Maybe (PieceSquareArray x y pieceSquareValue)
forall criterionWeight pieceSquareValue rankValue x y.
EvaluationOptions criterionWeight pieceSquareValue rankValue x y
-> Maybe (PieceSquareArray x y pieceSquareValue)
Input.EvaluationOptions.getMaybePieceSquareArray EvaluationOptions criterionWeight pieceSquareValue rankValue x y
evaluationOptions
				) positionHash
apexPositionHash Game x y
seedGame
			) ([Tree (Game x y)]
 -> Forest (NodeLabel x y positionHash criterionValue weightedMean))
-> [Tree (Game x y)]
-> Forest (NodeLabel x y positionHash criterionValue weightedMean)
forall a b. (a -> b) -> a -> b
$ Tree (Game x y) -> [Tree (Game x y)]
forall a. Tree a -> Forest a
Data.Tree.subForest Tree (Game x y)
bareGameTree
		}
		else (Game x y
 -> NodeLabel x y positionHash criterionValue weightedMean)
-> Tree (Game x y)
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (
			(positionHash
 -> QuantifiedGame x y criterionValue weightedMean
 -> NodeLabel x y positionHash criterionValue weightedMean)
-> (positionHash, QuantifiedGame x y criterionValue weightedMean)
-> NodeLabel x y positionHash criterionValue weightedMean
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry positionHash
-> QuantifiedGame x y criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean
forall x y positionHash criterionValue weightedMean.
positionHash
-> QuantifiedGame x y criterionValue weightedMean
-> NodeLabel x y positionHash criterionValue weightedMean
MkNodeLabel ((positionHash, QuantifiedGame x y criterionValue weightedMean)
 -> NodeLabel x y positionHash criterionValue weightedMean)
-> (Game x y
    -> (positionHash, QuantifiedGame x y criterionValue weightedMean))
-> Game x y
-> NodeLabel x y positionHash criterionValue weightedMean
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (
				(Game x y -> Zobrist x y positionHash -> positionHash
forall positionHash (hashable :: * -> * -> *) x y.
(Bits positionHash, Hashable2D hashable x y) =>
hashable x y -> Zobrist x y positionHash -> positionHash
`Component.Zobrist.hash2D` Zobrist x y positionHash
zobrist) (Game x y -> positionHash)
-> (Game x y -> QuantifiedGame x y criterionValue weightedMean)
-> Game x y
-> (positionHash, QuantifiedGame x y criterionValue weightedMean)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& (Reader
  (EvaluationOptions criterionWeight pieceSquareValue rankValue x y)
  (QuantifiedGame x y criterionValue weightedMean)
-> EvaluationOptions criterionWeight pieceSquareValue rankValue x y
-> QuantifiedGame x y criterionValue weightedMean
forall r a. Reader r a -> r -> a
`Control.Monad.Reader.runReader` EvaluationOptions criterionWeight pieceSquareValue rankValue x y
evaluationOptions) (Reader
   (EvaluationOptions criterionWeight pieceSquareValue rankValue x y)
   (QuantifiedGame x y criterionValue weightedMean)
 -> QuantifiedGame x y criterionValue weightedMean)
-> (Game x y
    -> Reader
         (EvaluationOptions criterionWeight pieceSquareValue rankValue x y)
         (QuantifiedGame x y criterionValue weightedMean))
-> Game x y
-> QuantifiedGame x y criterionValue weightedMean
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe pieceSquareValue
-> Game x y
-> Reader
     (EvaluationOptions criterionWeight pieceSquareValue rankValue x y)
     (QuantifiedGame x y criterionValue weightedMean)
forall x y criterionValue pieceSquareValue rankValue weightedMean
       criterionWeight.
(Enum x, Enum y, Fractional criterionValue,
 Fractional pieceSquareValue, Fractional rankValue,
 Fractional weightedMean, Ord x, Ord y, Real criterionValue,
 Real criterionWeight, Real pieceSquareValue, Real rankValue,
 Show x, Show y) =>
Maybe pieceSquareValue
-> Game x y
-> Reader
     criterionWeight
     pieceSquareValue
     rankValue
     x
     y
     (QuantifiedGame x y criterionValue weightedMean)
Evaluation.QuantifiedGame.fromGame Maybe pieceSquareValue
forall a. Maybe a
Nothing
			)
		) Tree (Game x y)
bareGameTree
 ) where
	bareGameTree :: Tree (Game x y)
bareGameTree	= GameTree x y -> Tree (Game x y)
forall x y. GameTree x y -> BareGameTree x y
Model.GameTree.deconstruct (GameTree x y -> Tree (Game x y))
-> (GameTree x y -> GameTree x y)
-> GameTree x y
-> Tree (Game x y)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool
 -> Maybe CaptureMoveSortAlgorithm
 -> EvaluateRank rankValue
 -> MoveFrequency x y
 -> GameTree x y
 -> GameTree x y)
-> (Bool, Maybe CaptureMoveSortAlgorithm)
-> EvaluateRank rankValue
-> MoveFrequency x y
-> GameTree x y
-> GameTree x y
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Bool
-> Maybe CaptureMoveSortAlgorithm
-> EvaluateRank rankValue
-> MoveFrequency x y
-> GameTree x y
-> GameTree x y
forall x y rankValue.
(Integral x, Integral y, Num rankValue, Ord rankValue) =>
Bool
-> Maybe CaptureMoveSortAlgorithm
-> EvaluateRank rankValue
-> MoveFrequency x y
-> Transformation x y
Model.GameTree.sortGameTree (
		SearchOptions -> Bool
Input.SearchOptions.getPreferMovesTowardsCentre (SearchOptions -> Bool)
-> (SearchOptions -> Maybe CaptureMoveSortAlgorithm)
-> SearchOptions
-> (Bool, Maybe CaptureMoveSortAlgorithm)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& SearchOptions -> Maybe CaptureMoveSortAlgorithm
Input.SearchOptions.getMaybeCaptureMoveSortAlgorithm (SearchOptions -> (Bool, Maybe CaptureMoveSortAlgorithm))
-> SearchOptions -> (Bool, Maybe CaptureMoveSortAlgorithm)
forall a b. (a -> b) -> a -> b
$ SearchOptions
searchOptions
	 ) (
		Rank -> RankValues rankValue -> rankValue
forall rankValue. Rank -> RankValues rankValue -> rankValue
`Attribute.RankValues.findRankValue` EvaluationOptions criterionWeight pieceSquareValue rankValue x y
-> RankValues rankValue
forall criterionWeight pieceSquareValue rankValue x y.
EvaluationOptions criterionWeight pieceSquareValue rankValue x y
-> RankValues rankValue
Input.EvaluationOptions.getRankValues EvaluationOptions criterionWeight pieceSquareValue rankValue x y
evaluationOptions
	 ) MoveFrequency x y
moveFrequency (GameTree x y -> Tree (Game x y))
-> GameTree x y -> Tree (Game x y)
forall a b. (a -> b) -> a -> b
$ Game x y -> GameTree x y
forall x y.
(Enum x, Enum y, Ord x, Ord y, Show x, Show y) =>
Game x y -> GameTree x y
Model.GameTree.fromGame Game x y
seedGame

-- | Accessor.
getRootPositionHash :: PositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean -> positionHash
getRootPositionHash :: PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> positionHash
getRootPositionHash MkPositionHashQuantifiedGameTree {
	deconstruct :: forall x y positionHash criterionValue weightedMean.
PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
deconstruct = Data.Tree.Node {
		rootLabel :: forall a. Tree a -> a
Data.Tree.rootLabel	= MkNodeLabel { getPositionHash :: forall x y positionHash criterionValue weightedMean.
NodeLabel x y positionHash criterionValue weightedMean
-> positionHash
getPositionHash = positionHash
positionHash }
	}
} = positionHash
positionHash

-- | Accessor.
getRootQuantifiedGame :: PositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean -> Evaluation.QuantifiedGame.QuantifiedGame x y criterionValue weightedMean
getRootQuantifiedGame :: PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> QuantifiedGame x y criterionValue weightedMean
getRootQuantifiedGame MkPositionHashQuantifiedGameTree {
	deconstruct :: forall x y positionHash criterionValue weightedMean.
PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
deconstruct = Data.Tree.Node {
		rootLabel :: forall a. Tree a -> a
Data.Tree.rootLabel	= MkNodeLabel { getQuantifiedGame :: forall x y positionHash criterionValue weightedMean.
NodeLabel x y positionHash criterionValue weightedMean
-> QuantifiedGame x y criterionValue weightedMean
getQuantifiedGame = QuantifiedGame x y criterionValue weightedMean
quantifiedGame }
	}
} = QuantifiedGame x y criterionValue weightedMean
quantifiedGame

-- | Forward request.
reduce
	:: Data.RoseTree.IsMatch (NodeLabel x y positionHash criterionValue weightedMean)
	-> PositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean
	-> Maybe (PositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean)
reduce :: IsMatch (NodeLabel x y positionHash criterionValue weightedMean)
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> Maybe
     (PositionHashQuantifiedGameTree
        x y positionHash criterionValue weightedMean)
reduce IsMatch (NodeLabel x y positionHash criterionValue weightedMean)
isMatch MkPositionHashQuantifiedGameTree { deconstruct :: forall x y positionHash criterionValue weightedMean.
PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
deconstruct = BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
barePositionHashQuantifiedGameTree }	= BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
forall x y positionHash criterionValue weightedMean.
BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
MkPositionHashQuantifiedGameTree (BarePositionHashQuantifiedGameTree
   x y positionHash criterionValue weightedMean
 -> PositionHashQuantifiedGameTree
      x y positionHash criterionValue weightedMean)
-> Maybe
     (BarePositionHashQuantifiedGameTree
        x y positionHash criterionValue weightedMean)
-> Maybe
     (PositionHashQuantifiedGameTree
        x y positionHash criterionValue weightedMean)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` IsMatch (NodeLabel x y positionHash criterionValue weightedMean)
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> Maybe
     (BarePositionHashQuantifiedGameTree
        x y positionHash criterionValue weightedMean)
forall a. IsMatch a -> Tree a -> Maybe (Tree a)
Data.RoseTree.reduce IsMatch (NodeLabel x y positionHash criterionValue weightedMean)
isMatch BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
barePositionHashQuantifiedGameTree

-- | Forward request.
traceRoute
	:: (Component.Turn.Turn x y -> Data.RoseTree.IsMatch (NodeLabel x y positionHash criterionValue weightedMean))
	-> PositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean
	-> [Component.Turn.Turn x y]
	-> Maybe [NodeLabel x y positionHash criterionValue weightedMean]
traceRoute :: (Turn x y
 -> IsMatch
      (NodeLabel x y positionHash criterionValue weightedMean))
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> [Turn x y]
-> Maybe [NodeLabel x y positionHash criterionValue weightedMean]
traceRoute Turn x y
-> IsMatch (NodeLabel x y positionHash criterionValue weightedMean)
isMatch MkPositionHashQuantifiedGameTree { deconstruct :: forall x y positionHash criterionValue weightedMean.
PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
deconstruct = BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
barePositionHashQuantifiedGameTree }	= (Turn x y
 -> IsMatch
      (NodeLabel x y positionHash criterionValue weightedMean))
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> [Turn x y]
-> Maybe [NodeLabel x y positionHash criterionValue weightedMean]
forall datum a.
(datum -> IsMatch a) -> Tree a -> [datum] -> Maybe [a]
Data.RoseTree.traceRoute Turn x y
-> IsMatch (NodeLabel x y positionHash criterionValue weightedMean)
isMatch BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
barePositionHashQuantifiedGameTree

-- | Follow the specified move-sequence down the /positionHashQuantifiedGameTree/.
traceMatchingMoves
	:: (Eq x, Eq y)
	=> PositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean
	-> [Component.Move.Move x y]
	-> Maybe [NodeLabel x y positionHash criterionValue weightedMean]	-- ^ Returns 'Nothing' on failure to match a move.
traceMatchingMoves :: PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> [Move x y]
-> Maybe [NodeLabel x y positionHash criterionValue weightedMean]
traceMatchingMoves MkPositionHashQuantifiedGameTree { deconstruct :: forall x y positionHash criterionValue weightedMean.
PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
deconstruct = BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
barePositionHashQuantifiedGameTree }	= (Move x y
 -> IsMatch
      (NodeLabel x y positionHash criterionValue weightedMean))
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> [Move x y]
-> Maybe [NodeLabel x y positionHash criterionValue weightedMean]
forall datum a.
(datum -> IsMatch a) -> Tree a -> [datum] -> Maybe [a]
Data.RoseTree.traceRoute Move x y
-> IsMatch (NodeLabel x y positionHash criterionValue weightedMean)
forall x y positionHash criterionValue weightedMean.
(Eq x, Eq y) =>
Move x y
-> IsMatch (NodeLabel x y positionHash criterionValue weightedMean)
equalsLastMove BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
barePositionHashQuantifiedGameTree

-- | Amend the apex-game to reflect the resignation of the next player.
resign :: PositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean -> PositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean
resign :: PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
resign MkPositionHashQuantifiedGameTree {
	deconstruct :: forall x y positionHash criterionValue weightedMean.
PositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
deconstruct	= barePositionHashQuantifiedGameTree :: BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
barePositionHashQuantifiedGameTree@Data.Tree.Node {
		rootLabel :: forall a. Tree a -> a
Data.Tree.rootLabel	= nodeLabel :: NodeLabel x y positionHash criterionValue weightedMean
nodeLabel@MkNodeLabel { getQuantifiedGame :: forall x y positionHash criterionValue weightedMean.
NodeLabel x y positionHash criterionValue weightedMean
-> QuantifiedGame x y criterionValue weightedMean
getQuantifiedGame = QuantifiedGame x y criterionValue weightedMean
quantifiedGame }
	}
} = BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
forall x y positionHash criterionValue weightedMean.
BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
MkPositionHashQuantifiedGameTree (BarePositionHashQuantifiedGameTree
   x y positionHash criterionValue weightedMean
 -> PositionHashQuantifiedGameTree
      x y positionHash criterionValue weightedMean)
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> PositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
forall a b. (a -> b) -> a -> b
$ BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
barePositionHashQuantifiedGameTree {
	rootLabel :: NodeLabel x y positionHash criterionValue weightedMean
Data.Tree.rootLabel	= NodeLabel x y positionHash criterionValue weightedMean
nodeLabel {
		getQuantifiedGame :: QuantifiedGame x y criterionValue weightedMean
getQuantifiedGame	= QuantifiedGame x y criterionValue weightedMean
quantifiedGame { getGame :: Game x y
Evaluation.QuantifiedGame.getGame = Transformation x y
forall x y. Transformation x y
Model.Game.resign Transformation x y -> Transformation x y
forall a b. (a -> b) -> a -> b
$ QuantifiedGame x y criterionValue weightedMean -> Game x y
forall x y criterionValue weightedMean.
QuantifiedGame x y criterionValue weightedMean -> Game x y
Evaluation.QuantifiedGame.getGame QuantifiedGame x y criterionValue weightedMean
quantifiedGame }
	}
}

-- | Self-documentation.
type Forest x y positionHash criterionValue weightedMean	= [BarePositionHashQuantifiedGameTree x y positionHash criterionValue weightedMean]

{- |
	* Promotes the first matching /move/ to the head of the forest, then descends & recursively promotes the next matching move in the sub-forest.

	* N.B.: this can be used to dynamically re-order the forest when a transposition is detected.
-}
promoteMatchingMoves
	:: (Eq x, Eq y)
	=> [Component.Move.Move x y]					-- ^ The list of moves, which should be promoted at successively deeper levels in the tree.
	-> Forest x y positionHash criterionValue weightedMean
	-> Maybe (Forest x y positionHash criterionValue weightedMean)	-- ^ Returns 'Nothing' on failure to match a move.
promoteMatchingMoves :: [Move x y]
-> Forest x y positionHash criterionValue weightedMean
-> Maybe (Forest x y positionHash criterionValue weightedMean)
promoteMatchingMoves	= (Move x y
 -> IsMatch
      (NodeLabel x y positionHash criterionValue weightedMean))
-> [Move x y]
-> Forest x y positionHash criterionValue weightedMean
-> Maybe (Forest x y positionHash criterionValue weightedMean)
forall datum a.
(datum -> IsMatch a) -> [datum] -> [Tree a] -> Maybe [Tree a]
Data.RoseTree.promote Move x y
-> IsMatch (NodeLabel x y positionHash criterionValue weightedMean)
forall x y positionHash criterionValue weightedMean.
(Eq x, Eq y) =>
Move x y
-> IsMatch (NodeLabel x y positionHash criterionValue weightedMean)
equalsLastMove

{- |
	* Sorts the forest, starting just after any initial capture-moves.

	* N.B.: this can be used to dynamically re-order the forest using the killer heuristic.
-}
sortNonCaptureMoves
	:: (Forest x y positionHash criterionValue weightedMean -> Forest x y positionHash criterionValue weightedMean)
	-> Forest x y positionHash criterionValue weightedMean
	-> Forest x y positionHash criterionValue weightedMean
sortNonCaptureMoves :: (Forest x y positionHash criterionValue weightedMean
 -> Forest x y positionHash criterionValue weightedMean)
-> Forest x y positionHash criterionValue weightedMean
-> Forest x y positionHash criterionValue weightedMean
sortNonCaptureMoves Forest x y positionHash criterionValue weightedMean
-> Forest x y positionHash criterionValue weightedMean
sortForest	= (Forest x y positionHash criterionValue weightedMean
 -> Forest x y positionHash criterionValue weightedMean
 -> Forest x y positionHash criterionValue weightedMean)
-> (Forest x y positionHash criterionValue weightedMean,
    Forest x y positionHash criterionValue weightedMean)
-> Forest x y positionHash criterionValue weightedMean
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Forest x y positionHash criterionValue weightedMean
-> Forest x y positionHash criterionValue weightedMean
-> Forest x y positionHash criterionValue weightedMean
forall a. [a] -> [a] -> [a]
(++) ((Forest x y positionHash criterionValue weightedMean,
  Forest x y positionHash criterionValue weightedMean)
 -> Forest x y positionHash criterionValue weightedMean)
-> (Forest x y positionHash criterionValue weightedMean
    -> (Forest x y positionHash criterionValue weightedMean,
        Forest x y positionHash criterionValue weightedMean))
-> Forest x y positionHash criterionValue weightedMean
-> Forest x y positionHash criterionValue weightedMean
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Forest x y positionHash criterionValue weightedMean
 -> Forest x y positionHash criterionValue weightedMean)
-> (Forest x y positionHash criterionValue weightedMean,
    Forest x y positionHash criterionValue weightedMean)
-> (Forest x y positionHash criterionValue weightedMean,
    Forest x y positionHash criterionValue weightedMean)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
Control.Arrow.second Forest x y positionHash criterionValue weightedMean
-> Forest x y positionHash criterionValue weightedMean
sortForest ((Forest x y positionHash criterionValue weightedMean,
  Forest x y positionHash criterionValue weightedMean)
 -> (Forest x y positionHash criterionValue weightedMean,
     Forest x y positionHash criterionValue weightedMean))
-> (Forest x y positionHash criterionValue weightedMean
    -> (Forest x y positionHash criterionValue weightedMean,
        Forest x y positionHash criterionValue weightedMean))
-> Forest x y positionHash criterionValue weightedMean
-> (Forest x y positionHash criterionValue weightedMean,
    Forest x y positionHash criterionValue weightedMean)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (BarePositionHashQuantifiedGameTree
   x y positionHash criterionValue weightedMean
 -> Bool)
-> Forest x y positionHash criterionValue weightedMean
-> (Forest x y positionHash criterionValue weightedMean,
    Forest x y positionHash criterionValue weightedMean)
forall a. (a -> Bool) -> [a] -> ([a], [a])
span (
	Turn x y -> Bool
forall x y. Turn x y -> Bool
Component.Turn.isCapture (Turn x y -> Bool)
-> (BarePositionHashQuantifiedGameTree
      x y positionHash criterionValue weightedMean
    -> Turn x y)
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QuantifiedGame x y criterionValue weightedMean -> Turn x y
forall x y criterionValue weightedMean.
QuantifiedGame x y criterionValue weightedMean -> Turn x y
Evaluation.QuantifiedGame.getLastTurn (QuantifiedGame x y criterionValue weightedMean -> Turn x y)
-> (BarePositionHashQuantifiedGameTree
      x y positionHash criterionValue weightedMean
    -> QuantifiedGame x y criterionValue weightedMean)
-> BarePositionHashQuantifiedGameTree
     x y positionHash criterionValue weightedMean
-> Turn x y
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> QuantifiedGame x y criterionValue weightedMean
forall x y positionHash criterionValue weightedMean.
BarePositionHashQuantifiedGameTree
  x y positionHash criterionValue weightedMean
-> QuantifiedGame x y criterionValue weightedMean
getRootQuantifiedGame'	-- Shield any capture-moves, which were previously advanced by static sorting, from the sort.
 )