module BishBosh.Search.Search(
Result (
getSearchState,
getQuantifiedGames,
getNPositionsEvaluated
),
showsSeparator,
search
) where
import Control.Arrow((&&&))
import qualified BishBosh.Data.Exception as Data.Exception
import qualified BishBosh.Evaluation.PositionHashQuantifiedGameTree as Evaluation.PositionHashQuantifiedGameTree
import qualified BishBosh.Evaluation.QuantifiedGame as Evaluation.QuantifiedGame
import qualified BishBosh.Input.SearchOptions as Input.SearchOptions
import qualified BishBosh.Model.Game as Model.Game
import qualified BishBosh.Notation.MoveNotation as Notation.MoveNotation
import qualified BishBosh.Search.AlphaBeta as Search.AlphaBeta
import qualified BishBosh.Search.EphemeralData as Search.EphemeralData
import qualified BishBosh.Search.SearchState as Search.SearchState
import qualified BishBosh.State.TurnsByLogicalColour as State.TurnsByLogicalColour
import qualified BishBosh.Text.ShowList as Text.ShowList
import qualified BishBosh.Type.Count as Type.Count
import qualified BishBosh.Type.Crypto as Type.Crypto
import qualified Control.DeepSeq
import qualified Control.Exception
import qualified Control.Monad.Reader
import qualified Data.Maybe
data Result positionHash = MkResult {
Result positionHash -> SearchState positionHash
getSearchState :: Search.SearchState.SearchState positionHash,
Result positionHash -> [QuantifiedGame]
getQuantifiedGames :: [Evaluation.QuantifiedGame.QuantifiedGame],
Result positionHash -> NPositions
getNPositionsEvaluated :: Type.Count.NPositions
}
instance Control.DeepSeq.NFData (Result positionHash) where
rnf :: Result positionHash -> ()
rnf MkResult { getQuantifiedGames :: forall positionHash. Result positionHash -> [QuantifiedGame]
getQuantifiedGames = [QuantifiedGame]
quantifiedGames } = [QuantifiedGame] -> ()
forall a. NFData a => a -> ()
Control.DeepSeq.rnf [QuantifiedGame]
quantifiedGames
showsSeparator :: ShowS
showsSeparator :: ShowS
showsSeparator = String -> ShowS
showString String
" -> "
instance Notation.MoveNotation.ShowNotationFloat (Result positionHash) where
showsNotationFloat :: MoveNotation -> (Double -> ShowS) -> Result positionHash -> ShowS
showsNotationFloat MoveNotation
moveNotation Double -> ShowS
showsDouble result :: Result positionHash
result@MkResult {
getQuantifiedGames :: forall positionHash. Result positionHash -> [QuantifiedGame]
getQuantifiedGames = [QuantifiedGame]
quantifiedGames,
getNPositionsEvaluated :: forall positionHash. Result positionHash -> NPositions
getNPositionsEvaluated = NPositions
nPositionsEvaluated
} = ShowS -> (QuantifiedGame -> ShowS) -> [QuantifiedGame] -> ShowS
forall a. ShowS -> (a -> ShowS) -> [a] -> ShowS
Text.ShowList.showsFormattedList ShowS
showsSeparator (
MoveNotation -> (Double -> ShowS) -> QuantifiedGame -> ShowS
forall a.
ShowNotationFloat a =>
MoveNotation -> (Double -> ShowS) -> a -> ShowS
Notation.MoveNotation.showsNotationFloat MoveNotation
moveNotation Double -> ShowS
showsDouble
) [QuantifiedGame]
quantifiedGames ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"; selected after analysing " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NPositions -> ShowS
forall a. Show a => a -> ShowS
shows NPositions
nPositionsEvaluated ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" nodes" ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (
if [QuantifiedGame] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [QuantifiedGame]
quantifiedGames Bool -> Bool -> Bool
|| NPositions
nPositionsEvaluated NPositions -> NPositions -> Bool
forall a. Eq a => a -> a -> Bool
== NPositions
0
then ShowS
forall a. a -> a
id
else String -> ShowS
showString String
" (branching-factor" ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
Text.ShowList.showsAssociation ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> ShowS
showsDouble (Result positionHash -> Double
forall branchingFactor positionHash.
Floating branchingFactor =>
Result positionHash -> branchingFactor
calculateBranchingFactor Result positionHash
result) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
')'
)
mkResult
:: Search.SearchState.SearchState positionHash
-> [Evaluation.QuantifiedGame.QuantifiedGame]
-> Type.Count.NPositions
-> Result positionHash
mkResult :: SearchState positionHash
-> [QuantifiedGame] -> NPositions -> Result positionHash
mkResult SearchState positionHash
searchState [QuantifiedGame]
quantifiedGames NPositions
nPositionsEvaluated
| [QuantifiedGame] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [QuantifiedGame]
quantifiedGames = Exception -> Result positionHash
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> Result positionHash)
-> (String -> Exception) -> String -> Result positionHash
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Exception
Data.Exception.mkNullDatum (String -> Exception) -> ShowS -> String -> Exception
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"BishBosh.Search.Search.mkResult:\tnull quantifiedGames; " (String -> Result positionHash) -> String -> Result positionHash
forall a b. (a -> b) -> a -> b
$ Game -> ShowS
forall a. Show a => a -> ShowS
shows Game
game String
"."
| NPositions
nPositionsEvaluated NPositions -> NPositions -> Bool
forall a. Ord a => a -> a -> Bool
< NPositions
0 = Exception -> Result positionHash
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> Result positionHash)
-> (String -> Exception) -> String -> Result positionHash
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Exception
Data.Exception.mkOutOfBounds (String -> Exception) -> ShowS -> String -> Exception
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"BishBosh.Search.Search.mkResult:\tnPositionsEvaluated=" ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NPositions -> ShowS
forall a. Show a => a -> ShowS
shows NPositions
nPositionsEvaluated ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" mustn't be negative; " (String -> Result positionHash) -> String -> Result positionHash
forall a b. (a -> b) -> a -> b
$ Game -> ShowS
forall a. Show a => a -> ShowS
shows Game
game String
"."
| Bool
otherwise = MkResult :: forall positionHash.
SearchState positionHash
-> [QuantifiedGame] -> NPositions -> Result positionHash
MkResult {
getSearchState :: SearchState positionHash
getSearchState = SearchState positionHash
searchState,
getQuantifiedGames :: [QuantifiedGame]
getQuantifiedGames = [QuantifiedGame]
quantifiedGames,
getNPositionsEvaluated :: NPositions
getNPositionsEvaluated = NPositions
nPositionsEvaluated
}
where
game :: Game
game = QuantifiedGame -> Game
Evaluation.QuantifiedGame.getGame (QuantifiedGame -> Game)
-> (PositionHashQuantifiedGameTree positionHash -> QuantifiedGame)
-> PositionHashQuantifiedGameTree positionHash
-> Game
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PositionHashQuantifiedGameTree positionHash -> QuantifiedGame
forall positionHash.
PositionHashQuantifiedGameTree positionHash -> QuantifiedGame
Evaluation.PositionHashQuantifiedGameTree.getRootQuantifiedGame (PositionHashQuantifiedGameTree positionHash -> Game)
-> PositionHashQuantifiedGameTree positionHash -> Game
forall a b. (a -> b) -> a -> b
$ SearchState positionHash
-> PositionHashQuantifiedGameTree positionHash
forall positionHash.
SearchState positionHash
-> PositionHashQuantifiedGameTree positionHash
Search.SearchState.getPositionHashQuantifiedGameTree SearchState positionHash
searchState
search
:: Ord positionHash
=> Type.Count.NPlies
-> Search.SearchState.SearchState positionHash
-> Input.SearchOptions.Reader (Result positionHash)
{-# SPECIALISE search :: Type.Count.NPlies -> Search.SearchState.SearchState Type.Crypto.PositionHash -> Input.SearchOptions.Reader (Result Type.Crypto.PositionHash) #-}
search :: NPositions
-> SearchState positionHash -> Reader (Result positionHash)
search NPositions
0 SearchState positionHash
_ = Exception -> Reader (Result positionHash)
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> Reader (Result positionHash))
-> (String -> Exception) -> String -> Reader (Result positionHash)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Exception
Data.Exception.mkOutOfBounds (String -> Exception) -> ShowS -> String -> Exception
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"BishBosh.Search.Search.search:\t" ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
forall a. Show a => a -> ShowS
shows String
Input.SearchOptions.searchDepthTag ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" must be at least " (String -> Reader (Result positionHash))
-> String -> Reader (Result positionHash)
forall a b. (a -> b) -> a -> b
$ NPositions -> ShowS
forall a. Show a => a -> ShowS
shows NPositions
Input.SearchOptions.minimumSearchDepth String
"."
search NPositions
searchDepth SearchState positionHash
searchState
| Just GameTerminationReason
terminationReason <- Game -> Maybe GameTerminationReason
Model.Game.getMaybeTerminationReason Game
game = Exception -> Reader (Result positionHash)
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> Reader (Result positionHash))
-> (String -> Exception) -> String -> Reader (Result positionHash)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Exception
Data.Exception.mkInvalidDatum (String -> Exception) -> ShowS -> String -> Exception
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"BishBosh.Search.Search.search:\tthe game has already terminated; " (String -> Reader (Result positionHash))
-> String -> Reader (Result positionHash)
forall a b. (a -> b) -> a -> b
$ GameTerminationReason -> ShowS
forall a. Show a => a -> ShowS
shows GameTerminationReason
terminationReason String
"."
| Bool
otherwise = do
(MaybeRetireAfterNMoves, MaybeRetireAfterNMoves)
pair <- (SearchOptions -> (MaybeRetireAfterNMoves, MaybeRetireAfterNMoves))
-> ReaderT
SearchOptions
Identity
(MaybeRetireAfterNMoves, MaybeRetireAfterNMoves)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
Control.Monad.Reader.asks ((SearchOptions
-> (MaybeRetireAfterNMoves, MaybeRetireAfterNMoves))
-> ReaderT
SearchOptions
Identity
(MaybeRetireAfterNMoves, MaybeRetireAfterNMoves))
-> (SearchOptions
-> (MaybeRetireAfterNMoves, MaybeRetireAfterNMoves))
-> ReaderT
SearchOptions
Identity
(MaybeRetireAfterNMoves, MaybeRetireAfterNMoves)
forall a b. (a -> b) -> a -> b
$ SearchOptions -> MaybeRetireAfterNMoves
Input.SearchOptions.getMaybeRetireKillerMovesAfter (SearchOptions -> MaybeRetireAfterNMoves)
-> (SearchOptions -> MaybeRetireAfterNMoves)
-> SearchOptions
-> (MaybeRetireAfterNMoves, MaybeRetireAfterNMoves)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& SearchOptions -> MaybeRetireAfterNMoves
Input.SearchOptions.maybeRetireTranspositionsAfter
let nPlies :: NPositions
nPlies = TurnsByLogicalColour Turn -> NPositions
forall turn. TurnsByLogicalColour turn -> NPositions
State.TurnsByLogicalColour.getNPlies (TurnsByLogicalColour Turn -> NPositions)
-> TurnsByLogicalColour Turn -> NPositions
forall a b. (a -> b) -> a -> b
$ Game -> TurnsByLogicalColour Turn
Model.Game.getTurnsByLogicalColour Game
game
Result positionHash
searchResult <- NPositions
-> SearchState positionHash -> Reader (Result positionHash)
forall positionHash.
Ord positionHash =>
NPositions
-> SearchState positionHash -> Reader (Result positionHash)
Search.AlphaBeta.negaMax NPositions
searchDepth (SearchState positionHash -> Reader (Result positionHash))
-> SearchState positionHash -> Reader (Result positionHash)
forall a b. (a -> b) -> a -> b
$ (MaybeRetireAfterNMoves
-> MaybeRetireAfterNMoves
-> SearchState positionHash
-> SearchState positionHash)
-> (MaybeRetireAfterNMoves, MaybeRetireAfterNMoves)
-> SearchState positionHash
-> SearchState positionHash
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (NPositions
-> MaybeRetireAfterNMoves
-> MaybeRetireAfterNMoves
-> SearchState positionHash
-> SearchState positionHash
forall a.
MaybeEphemeralData a =>
NPositions
-> MaybeRetireAfterNMoves -> MaybeRetireAfterNMoves -> a -> a
Search.EphemeralData.maybeEuthanise NPositions
nPlies) (MaybeRetireAfterNMoves, MaybeRetireAfterNMoves)
pair SearchState positionHash
searchState
case NPositions
-> Result positionHash
-> (DynamicMoveData positionHash, [Turn], NPositions)
forall positionHash.
NPositions
-> Result positionHash
-> (DynamicMoveData positionHash, [Turn], NPositions)
Search.AlphaBeta.extractSelectedTurns NPositions
nPlies Result positionHash
searchResult of
(DynamicMoveData positionHash
dynamicMoveData, turns :: [Turn]
turns@(Turn
turn : [Turn]
_), NPositions
nPositionsEvaluated) -> let
isMatch :: Turn -> NodeLabel positionHash -> Bool
isMatch Turn
turn' = (Turn -> Turn -> Bool
forall a. Eq a => a -> a -> Bool
== Turn
turn') (Turn -> Bool)
-> (NodeLabel positionHash -> Turn)
-> NodeLabel positionHash
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QuantifiedGame -> Turn
Evaluation.QuantifiedGame.getLastTurn (QuantifiedGame -> Turn)
-> (NodeLabel positionHash -> QuantifiedGame)
-> NodeLabel positionHash
-> Turn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NodeLabel positionHash -> QuantifiedGame
forall positionHash. NodeLabel positionHash -> QuantifiedGame
Evaluation.PositionHashQuantifiedGameTree.getQuantifiedGame
in Result positionHash -> Reader (Result positionHash)
forall (m :: * -> *) a. Monad m => a -> m a
return (Result positionHash -> Reader (Result positionHash))
-> Result positionHash -> Reader (Result positionHash)
forall a b. (a -> b) -> a -> b
$ SearchState positionHash
-> [QuantifiedGame] -> NPositions -> Result positionHash
forall positionHash.
SearchState positionHash
-> [QuantifiedGame] -> NPositions -> Result positionHash
mkResult (
PositionHashQuantifiedGameTree positionHash
-> DynamicMoveData positionHash -> SearchState positionHash
forall positionHash.
PositionHashQuantifiedGameTree positionHash
-> DynamicMoveData positionHash -> SearchState positionHash
Search.SearchState.mkSearchState (
PositionHashQuantifiedGameTree positionHash
-> Maybe (PositionHashQuantifiedGameTree positionHash)
-> PositionHashQuantifiedGameTree positionHash
forall a. a -> Maybe a -> a
Data.Maybe.fromMaybe (
Exception -> PositionHashQuantifiedGameTree positionHash
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> PositionHashQuantifiedGameTree positionHash)
-> (String -> Exception)
-> String
-> PositionHashQuantifiedGameTree positionHash
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.Search.Search.search:\tBishBosh.Evaluation.PositionHashQuantifiedGameTree.reduce failed; " (String -> PositionHashQuantifiedGameTree positionHash)
-> String -> PositionHashQuantifiedGameTree positionHash
forall a b. (a -> b) -> a -> b
$ Turn -> ShowS
forall a. Show a => a -> ShowS
shows Turn
turn String
"."
) (Maybe (PositionHashQuantifiedGameTree positionHash)
-> PositionHashQuantifiedGameTree positionHash)
-> Maybe (PositionHashQuantifiedGameTree positionHash)
-> PositionHashQuantifiedGameTree positionHash
forall a b. (a -> b) -> a -> b
$ IsMatch (NodeLabel positionHash)
-> PositionHashQuantifiedGameTree positionHash
-> Maybe (PositionHashQuantifiedGameTree positionHash)
forall positionHash.
IsMatch (NodeLabel positionHash)
-> PositionHashQuantifiedGameTree positionHash
-> Maybe (PositionHashQuantifiedGameTree positionHash)
Evaluation.PositionHashQuantifiedGameTree.reduce (Turn -> IsMatch (NodeLabel positionHash)
forall positionHash. Turn -> NodeLabel positionHash -> Bool
isMatch Turn
turn) PositionHashQuantifiedGameTree positionHash
positionHashQuantifiedGameTree
) DynamicMoveData positionHash
dynamicMoveData
) (
(NodeLabel positionHash -> QuantifiedGame)
-> [NodeLabel positionHash] -> [QuantifiedGame]
forall a b. (a -> b) -> [a] -> [b]
map NodeLabel positionHash -> QuantifiedGame
forall positionHash. NodeLabel positionHash -> QuantifiedGame
Evaluation.PositionHashQuantifiedGameTree.getQuantifiedGame ([NodeLabel positionHash] -> [QuantifiedGame])
-> (Maybe [NodeLabel positionHash] -> [NodeLabel positionHash])
-> Maybe [NodeLabel positionHash]
-> [QuantifiedGame]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [NodeLabel positionHash]
-> Maybe [NodeLabel positionHash] -> [NodeLabel positionHash]
forall a. a -> Maybe a -> a
Data.Maybe.fromMaybe (
Exception -> [NodeLabel positionHash]
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> [NodeLabel positionHash])
-> (String -> Exception) -> String -> [NodeLabel positionHash]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Exception
Data.Exception.mkSearchFailure (String -> Exception) -> ShowS -> String -> Exception
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"BishBosh.Search.Search.search:\tEvaluation.PositionHashQuantifiedGameTree.traceRoute failed; " (String -> [NodeLabel positionHash])
-> String -> [NodeLabel positionHash]
forall a b. (a -> b) -> a -> b
$ [Turn] -> ShowS
forall a. Show a => a -> ShowS
shows [Turn]
turns String
"."
) (Maybe [NodeLabel positionHash] -> [QuantifiedGame])
-> Maybe [NodeLabel positionHash] -> [QuantifiedGame]
forall a b. (a -> b) -> a -> b
$ (Turn -> IsMatch (NodeLabel positionHash))
-> PositionHashQuantifiedGameTree positionHash
-> [Turn]
-> Maybe [NodeLabel positionHash]
forall positionHash.
(Turn -> IsMatch (NodeLabel positionHash))
-> PositionHashQuantifiedGameTree positionHash
-> [Turn]
-> Maybe [NodeLabel positionHash]
Evaluation.PositionHashQuantifiedGameTree.traceRoute Turn -> IsMatch (NodeLabel positionHash)
forall positionHash. Turn -> NodeLabel positionHash -> Bool
isMatch PositionHashQuantifiedGameTree positionHash
positionHashQuantifiedGameTree [Turn]
turns
) NPositions
nPositionsEvaluated
(DynamicMoveData positionHash, [Turn], NPositions)
_ -> Exception -> Reader (Result positionHash)
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> Reader (Result positionHash))
-> Exception -> Reader (Result positionHash)
forall a b. (a -> b) -> a -> b
$ String -> Exception
Data.Exception.mkNullDatum String
"BishBosh.Search.Search.search:\tzero turns selected."
where
positionHashQuantifiedGameTree :: PositionHashQuantifiedGameTree positionHash
positionHashQuantifiedGameTree = SearchState positionHash
-> PositionHashQuantifiedGameTree positionHash
forall positionHash.
SearchState positionHash
-> PositionHashQuantifiedGameTree positionHash
Search.SearchState.getPositionHashQuantifiedGameTree SearchState positionHash
searchState
game :: Game
game = QuantifiedGame -> Game
Evaluation.QuantifiedGame.getGame (QuantifiedGame -> Game) -> QuantifiedGame -> Game
forall a b. (a -> b) -> a -> b
$ PositionHashQuantifiedGameTree positionHash -> QuantifiedGame
forall positionHash.
PositionHashQuantifiedGameTree positionHash -> QuantifiedGame
Evaluation.PositionHashQuantifiedGameTree.getRootQuantifiedGame PositionHashQuantifiedGameTree positionHash
positionHashQuantifiedGameTree
calculateBranchingFactor :: Floating branchingFactor => Result positionHash -> branchingFactor
calculateBranchingFactor :: Result positionHash -> branchingFactor
calculateBranchingFactor MkResult {
getQuantifiedGames :: forall positionHash. Result positionHash -> [QuantifiedGame]
getQuantifiedGames = [QuantifiedGame]
quantifiedGames,
getNPositionsEvaluated :: forall positionHash. Result positionHash -> NPositions
getNPositionsEvaluated = NPositions
nPositionsEvaluated
}
| [QuantifiedGame] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [QuantifiedGame]
quantifiedGames = Exception -> branchingFactor
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> branchingFactor) -> Exception -> branchingFactor
forall a b. (a -> b) -> a -> b
$ String -> Exception
Data.Exception.mkNullDatum String
"BishBosh.Search.Search.calculateBranchingFactor:\tnull quantifiedGames."
| NPositions
nPositionsEvaluated NPositions -> NPositions -> Bool
forall a. Eq a => a -> a -> Bool
== NPositions
0 = Exception -> branchingFactor
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> branchingFactor) -> Exception -> branchingFactor
forall a b. (a -> b) -> a -> b
$ String -> Exception
Data.Exception.mkOutOfBounds String
"BishBosh.Search.Search.calculateBranchingFactor:\tzero plies analysed."
| Bool
otherwise = NPositions -> branchingFactor
forall a b. (Integral a, Num b) => a -> b
fromIntegral NPositions
nPositionsEvaluated branchingFactor -> branchingFactor -> branchingFactor
forall a. Floating a => a -> a -> a
** branchingFactor -> branchingFactor
forall a. Fractional a => a -> a
recip (
NPositions -> branchingFactor
forall a b. (Integral a, Num b) => a -> b
fromIntegral (NPositions -> branchingFactor) -> NPositions -> branchingFactor
forall a b. (a -> b) -> a -> b
$ [QuantifiedGame] -> NPositions
forall (t :: * -> *) a. Foldable t => t a -> NPositions
length [QuantifiedGame]
quantifiedGames
)