packages feed

bishbosh 0.1.3.1 → 0.1.4.0

raw patch · 82 files changed

+1253/−784 lines, 82 filesdep +ghc-primdep ~arrayPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: ghc-prim

Dependency ranges changed: array

API changes (from Hackage documentation)

- BishBosh.Component.PieceSquareByCoordinatesByRank: data PieceSquareByCoordinatesByRank
- BishBosh.Component.PieceSquareByCoordinatesByRank: findPieceSquareValue :: PieceSquareByCoordinatesByRank -> NPieces -> LogicalColour -> Rank -> Coordinates -> PieceSquareValue
- BishBosh.Component.PieceSquareByCoordinatesByRank: formatForGNUPlot :: PieceSquareByCoordinatesByRank -> (PieceSquareValue -> ShowS) -> ShowS -> (PieceSquareValueByNPieces -> PieceSquareValue) -> ShowS
- BishBosh.Component.PieceSquareByCoordinatesByRank: gnuPlotComment :: Char
- BishBosh.Component.PieceSquareByCoordinatesByRank: instance Control.DeepSeq.NFData BishBosh.Component.PieceSquareByCoordinatesByRank.PieceSquareByCoordinatesByRank
- BishBosh.Component.PieceSquareByCoordinatesByRank: instance GHC.Classes.Eq BishBosh.Component.PieceSquareByCoordinatesByRank.PieceSquareByCoordinatesByRank
- BishBosh.Component.PieceSquareByCoordinatesByRank: instance GHC.Show.Show BishBosh.Component.PieceSquareByCoordinatesByRank.PieceSquareByCoordinatesByRank
- BishBosh.Component.PieceSquareByCoordinatesByRank: interpolatePieceSquareValues :: PieceSquareValue -> PieceSquareValue -> PieceSquareValueByNPieces
- BishBosh.Component.PieceSquareByCoordinatesByRank: mkPieceSquareByCoordinatesByRank :: (Rank -> EitherPieceSquareValueByNPiecesByCoordinates) -> PieceSquareByCoordinatesByRank
- BishBosh.Component.PieceSquareByCoordinatesByRank: nPiecesBounds :: (NPieces, NPieces)
- BishBosh.Input.PieceSquareTable: dereference :: Rank -> PieceSquareTable -> Maybe PieceSquareValueByCoordinates
- BishBosh.Metric.RankValue: data RankValue
- BishBosh.Metric.RankValue: instance BishBosh.Property.ShowFloat.ShowFloat BishBosh.Metric.RankValue.RankValue
- BishBosh.Metric.RankValue: instance Control.DeepSeq.NFData BishBosh.Metric.RankValue.RankValue
- BishBosh.Metric.RankValue: instance GHC.Classes.Eq BishBosh.Metric.RankValue.RankValue
- BishBosh.Metric.RankValue: instance GHC.Classes.Ord BishBosh.Metric.RankValue.RankValue
- BishBosh.Metric.RankValue: instance GHC.Num.Num BishBosh.Metric.RankValue.RankValue
- BishBosh.Metric.RankValue: instance GHC.Read.Read BishBosh.Metric.RankValue.RankValue
- BishBosh.Metric.RankValue: instance GHC.Real.Fractional BishBosh.Metric.RankValue.RankValue
- BishBosh.Metric.RankValue: instance GHC.Real.Real BishBosh.Metric.RankValue.RankValue
- BishBosh.Metric.RankValue: instance GHC.Show.Show BishBosh.Metric.RankValue.RankValue
- BishBosh.Metric.RankValue: instance Text.XML.HXT.Arrow.Pickle.Xml.XmlPickler BishBosh.Metric.RankValue.RankValue
+ BishBosh.Attribute.MoveType: apply :: (IsShort -> a, a, (Maybe Rank, Maybe Rank) -> a) -> MoveType -> a
+ BishBosh.Attribute.Rank: type UArrayByRank = UArray Rank
+ BishBosh.Cartesian.Coordinates: isBetween :: Coordinates -> Coordinates -> Coordinates -> Bool
+ BishBosh.Cartesian.Coordinates: type QualifiedStraightLine = [(Coordinates, Int)]
+ BishBosh.Cartesian.Coordinates: type UArrayByCoordinates = UArray Coordinates
+ BishBosh.Component.PieceSquareValueByCoordinates: data PieceSquareValueByCoordinates
+ BishBosh.Component.PieceSquareValueByCoordinates: dereference :: PieceSquareValueByCoordinates -> Coordinates -> PieceSquareValue
+ BishBosh.Component.PieceSquareValueByCoordinates: fromList :: [PieceSquareValue] -> PieceSquareValueByCoordinates
+ BishBosh.Component.PieceSquareValueByCoordinates: getPieceSquareValue :: PieceSquareValueByCoordinates -> LogicalColour -> Coordinates -> PieceSquareValue
+ BishBosh.Component.PieceSquareValueByCoordinates: instance Control.DeepSeq.NFData BishBosh.Component.PieceSquareValueByCoordinates.PieceSquareValueByCoordinates
+ BishBosh.Component.PieceSquareValueByCoordinates: instance GHC.Classes.Eq BishBosh.Component.PieceSquareValueByCoordinates.PieceSquareValueByCoordinates
+ BishBosh.Component.PieceSquareValueByCoordinates: instance GHC.Show.Show BishBosh.Component.PieceSquareValueByCoordinates.PieceSquareValueByCoordinates
+ BishBosh.Component.PieceSquareValueByCoordinates: toList :: PieceSquareValueByCoordinates -> [PieceSquareValue]
+ BishBosh.Component.PieceSquareValueByCoordinatesByRank: data PieceSquareValueByCoordinatesByRank
+ BishBosh.Component.PieceSquareValueByCoordinatesByRank: formatForGNUPlot :: PieceSquareValueByCoordinatesByRank -> (PieceSquareValue -> ShowS) -> ShowS -> NPieces -> ShowS
+ BishBosh.Component.PieceSquareValueByCoordinatesByRank: getPieceSquareValueByCoordinates :: PieceSquareValueByCoordinatesByRank -> NPieces -> Rank -> PieceSquareValueByCoordinates
+ BishBosh.Component.PieceSquareValueByCoordinatesByRank: gnuPlotComment :: Char
+ BishBosh.Component.PieceSquareValueByCoordinatesByRank: instance Control.DeepSeq.NFData BishBosh.Component.PieceSquareValueByCoordinatesByRank.PieceSquareValueByCoordinatesByRank
+ BishBosh.Component.PieceSquareValueByCoordinatesByRank: mkPieceSquareValueByCoordinatesByRank :: (Rank -> PieceSquareValueByCoordinatesByEitherNPieces) -> PieceSquareValueByCoordinatesByRank
+ BishBosh.Input.EvaluationOptions: nPiecesBounds :: (NPieces, NPieces)
+ BishBosh.Input.PieceSquareTable: findPieceSquareValueByCoordinates :: Rank -> PieceSquareTable -> Maybe PieceSquareValueByCoordinates
+ BishBosh.Metric.RankValue: tag :: String
+ BishBosh.Metric.RankValue: type RankValue = Base
+ BishBosh.Property.ShowFloat: instance BishBosh.Property.ShowFloat.ShowFloat GHC.Types.Double
+ BishBosh.Property.ShowFloat: instance BishBosh.Property.ShowFloat.ShowFloat GHC.Types.Float
+ BishBosh.Property.ShowFloat: instance GHC.Real.Integral r => BishBosh.Property.ShowFloat.ShowFloat (GHC.Real.Ratio r)
+ BishBosh.State.Board: passesThroughCheck :: Board -> LogicalColour -> Move -> Bool
+ BishBosh.State.TurnsByLogicalColour: deriveMoveNumber :: TurnsByLogicalColour turn -> NMoves
- BishBosh.Cartesian.Coordinates: applyAlongDirectionsFrom :: ([Coordinates] -> [a]) -> Coordinates -> Maybe [Direction] -> [a]
+ BishBosh.Cartesian.Coordinates: applyAlongDirectionsFrom :: (QualifiedStraightLine -> [a]) -> Coordinates -> Maybe [Direction] -> [a]
- BishBosh.Cartesian.Coordinates: extrapolate :: Coordinates -> Direction -> [Coordinates]
+ BishBosh.Cartesian.Coordinates: extrapolate :: Coordinates -> Direction -> QualifiedStraightLine
- BishBosh.Cartesian.Coordinates: interpolate :: Coordinates -> Coordinates -> [Coordinates]
+ BishBosh.Cartesian.Coordinates: interpolate :: Coordinates -> Coordinates -> QualifiedStraightLine
- BishBosh.Component.Accountant: sumPieceSquareValueByLogicalColour :: Accountant accountant => PieceSquareByCoordinatesByRank -> accountant -> NPieces -> [Base]
+ BishBosh.Component.Accountant: sumPieceSquareValueByLogicalColour :: Accountant accountant => PieceSquareValueByCoordinatesByRank -> accountant -> NPieces -> [Base]
- BishBosh.Component.Move: interpolate :: Move -> [Coordinates]
+ BishBosh.Component.Move: interpolate :: Move -> QualifiedStraightLine
- BishBosh.Evaluation.Fitness: measurePieceSquareValueDifference :: PieceSquareByCoordinatesByRank -> Game -> Base
+ BishBosh.Evaluation.Fitness: measurePieceSquareValueDifference :: PieceSquareValueByCoordinatesByRank -> Game -> Base
- BishBosh.Evaluation.Fitness: measurePieceSquareValueDifferenceIncrementally :: Base -> PieceSquareByCoordinatesByRank -> Game -> Base
+ BishBosh.Evaluation.Fitness: measurePieceSquareValueDifferenceIncrementally :: Base -> PieceSquareValueByCoordinatesByRank -> Game -> Base
- BishBosh.Input.StandardOpeningOptions: mkStandardOpeningOptions :: TryToMatchMoves -> TryToMatchViaJoiningMove -> TryToMatchColourFlippedPosition -> PreferVictories -> StandardOpeningOptions
+ BishBosh.Input.StandardOpeningOptions: mkStandardOpeningOptions :: Maybe NPlies -> PreferVictories -> TryToMatchMoves -> TryToMatchViaJoiningMove -> TryToMatchColourFlippedPosition -> StandardOpeningOptions
- BishBosh.State.Board: sumPieceSquareValueByLogicalColour :: PieceSquareByCoordinatesByRank -> Board -> ArrayByLogicalColour Base
+ BishBosh.State.Board: sumPieceSquareValueByLogicalColour :: PieceSquareValueByCoordinatesByRank -> Board -> [Base]
- BishBosh.StateProperty.Censor: type NPiecesByRank = ArrayByRank NPieces
+ BishBosh.StateProperty.Censor: type NPiecesByRank = UArrayByRank NPieces
- BishBosh.StateProperty.Mutator: movePiece :: Mutator mutator => Move -> Piece -> Maybe Rank -> Either Coordinates (Maybe Rank) -> mutator -> mutator
+ BishBosh.StateProperty.Mutator: movePiece :: Mutator mutator => Move -> MoveType -> Piece -> mutator -> mutator

Files

bishbosh.cabal view
@@ -16,7 +16,7 @@ -- along with BishBosh.  If not, see <http://www.gnu.org/licenses/>.  Name:		bishbosh-Version:	0.1.3.1+Version:	0.1.4.0 Copyright:	(C) 2018 Dr. Alistair Ward License:	GPL-3.0-or-later License-file:	LICENSE@@ -57,46 +57,55 @@     type:	git     location:	https://github.com/functionalley/BishBosh --- Enable using: 'runhaskell Setup configure -f llvm --verbose'.-flag llvm-    Description:	Whether the 'llvm' compiler-backend has been installed and is required for code-generation.+-- Whether to use unsafe array-indexing where possible.+flag arrayunsafeat+    Description:	Use unsafe array-indexing.     Manual:		True-    Default:		False+    Default:		True  -- Automatically disabled when the required package isn't available.--- To force validation of the XML-configuration against the packaged DTD, manually disable using one of:+-- To force validation of the XML-configuration against the packaged DTD.+-- Disable using: --	runhaskell Setup configure -f -hxtrelaxng --verbose;---	stack build --flag 'bishbosh:-hxtrelaxng' --cabal-verbose;+--	stack build --flag='bishbosh:-hxtrelaxng'; flag hxtrelaxng     Description:	Link with package "hxt-relaxng" when available, for more precise specification of the XML-configuration than a traditional DTD.     Default:		True +-- Compile using LLVM; requires the 'llc' & 'opt' tools (from 'llvm') to be on one's PATH.+-- CAVEAT: build-time ~150 %, runtime ~97 % (i.e. slightly faster).+-- Enable using:+--	runhaskell Setup configure -f llvm --verbose.+--	stack build --flag='bishbosh:llvm';+flag llvm+    Description:	Whether the 'llvm' compiler-backend has been installed and is required for code-generation.+    Manual:		True+    Default:		False+ -- Whether to use narrower numerical types than machine-defaults. CAVEAT: this option increases both the space allocated & the execution-time.--- CAVEAT: incompatble with the flag 'precision'. flag narrownumbers     Description:	Use narrow numerical types.     Manual:		True     Default:		False --- Whether, to wrap common types in 'newtype' for increased type-safety. CAVEAT: there's a ~10% performance-penalty.--- CAVEAT: partly incompatible with 'narrownumbers'.+-- Whether to wrap common types in 'newtype' for increased type-safety. CAVEAT: there's a small performance-penalty. flag newtypewrappers     Description:	Wrap common types in newtype for increased type-safety.     Manual:		True     Default:		False  -- Automatically disabled when the required package isn't available.--- To access Parsec's more precise error-messages, manually disable using one of:+-- To access Parsec's more precise error-messages.+-- Disable using: --	runhaskell Setup configure -f -polyparse --verbose;---	stack build --flag 'bishbosh:-polyparse' --cabal-verbose;+--	stack build --flag='bishbosh:-polyparse'; flag polyparse     Description:	Link with package "polyparse" when available, rather than "parsec".     Default:		True --- Whether to use precise (rational) types rather than floating-point.--- CAVEAT: conceptually incompatible with 'narrownumbers'.-flag precision-    Description:	Use precise numerical types. CAVEAT: this is incompatible with either 'unboxedarrays' or 'narrownumbers'.+-- Whether to use precise (rational) numeric types rather than faster floating-point.+flag precisenumbers+    Description:	Use precise rational numeric types.     Manual:		True     Default:		False @@ -106,15 +115,14 @@     Manual:		True     Default:		True --- Whether to use unboxed arrays where possible.--- CAVEAT: incompatible with the flag 'precision', & to some extent 'newtypewrappers'.-flag unboxedarrays-    Description:	Use unboxed arrays.+-- Whether to use unboxed types where possible; e.g. in arrays or in primitive arithmetic.+flag unbox+    Description:	Use unboxed types.     Manual:		True-    Default:		False+    Default:		True  -- Automatically disabled when the required package isn't available.--- CAVEAT: on MS-Windows, it may be available but won't necessarily build, so specify "-f -unix --verbose" when configuring the package.+-- CAVEAT: on MS-Windows, it may be available but won't necessarily build; disable using 'runhaskell Setup configure -f -unix --verbose'. flag unix     Description:	Link with package "unix" when available.     Default:		True@@ -130,6 +138,9 @@      GHC-options:	-Wall -Wredundant-constraints -fno-warn-tabs +    if impl(ghc >= 7.0) && flag(llvm)+        GHC-options:	-fllvm+ common exeStanza     Hs-source-dirs:	src-exe     GHC-options:	-O2@@ -139,9 +150,6 @@         bishbosh,         hxt	^>= 9.3.1 -    if impl(ghc >= 7.0) && flag(llvm)-        GHC-options:	-fllvm- common profStanza     if impl(ghc >= 7.4.1)         GHC-prof-options:	-fprof-auto -fprof-cafs@@ -154,12 +162,16 @@ common testStanza     Hs-source-dirs:	src-test     Build-depends:-        array		^>= 0.5.1.1,+        array		>= 0.5.2.0,         bishbosh,         mtl		^>= 2.2.2,         random,         toolshed	^>= 0.18.0 +-- Hackage complains about the fragility resulting from new warnings added to ghc.+--    if impl(ghc >= 6.8)+--        GHC-options:	-Werror+     if flag(polyparse)         Build-depends:	polyparse ^>= 1.13         CPP-Options:	-DUSE_POLYPARSE='L'@@ -168,7 +180,7 @@  Library     Import:		commonStanza, profStanza-    GHC-options:	-O2 -fno-warn-unused-top-binds -Wno-all-missed-specialisations+    GHC-options:	-O2 -fno-warn-unused-top-binds     Hs-source-dirs:	src-lib      Exposed-modules:@@ -189,7 +201,8 @@         BishBosh.Component.EitherQualifiedMove         BishBosh.Component.Move         BishBosh.Component.Piece-        BishBosh.Component.PieceSquareByCoordinatesByRank+        BishBosh.Component.PieceSquareValueByCoordinates+        BishBosh.Component.PieceSquareValueByCoordinatesByRank         BishBosh.Component.QualifiedMove         BishBosh.Component.Turn         BishBosh.Component.Zobrist@@ -301,7 +314,7 @@         BishBosh.UI.SetObject      Build-depends:-        array		^>= 0.5.1.1,+        array		>= 0.5.2.0,         deepseq		>= 1.4.3,         extra		^>= 1.7.4,         factory		^>= 0.3.1,@@ -312,21 +325,26 @@         time,         toolshed	^>= 0.18.0 -    if impl(ghc >= 7.0) && flag(llvm)-        GHC-options:	-fllvm--    if flag(precision)-        CPP-Options:	-DUSE_PRECISION-    else-        if flag(narrownumbers)-            CPP-Options:	-DUSE_NARROW_NUMBERS+    if flag(arrayunsafeat)+        CPP-Options:	-DUSE_ARRAY_UNSAFEAT -        if flag(unboxedarrays)-            CPP-Options:	-DUSE_UNBOXED_ARRAYS+    if flag(precisenumbers)+        CPP-Options:	-DUSE_PRECISE_NUMBERS+    elif flag(narrownumbers)+        CPP-Options:	-DUSE_NARROW_NUMBERS      if flag(newtypewrappers)-        CPP-Options:		-DUSE_NEWTYPE_WRAPPERS+        CPP-Options:	-DUSE_NEWTYPE_WRAPPERS+    elif flag(unbox)+        CPP-Options:	-DUNBOX_TYPECOUNT_ARRAYS +        if !flag(narrownumbers)+            Build-depends:	ghc-prim+            CPP-Options:	-DUSE_PRIMITIVE++        if !flag(precisenumbers)+            CPP-Options:	-DUNBOX_TYPEMASS_ARRAYS+     if flag(polyparse)         Build-depends:		polyparse ^>= 1.13         CPP-Options:		-DUSE_POLYPARSE='L'@@ -335,8 +353,8 @@         Build-depends:		parsec ^>= 3.1.14.0      if flag(threaded)-        Build-depends:		parallel >= 3.0-        CPP-Options:		-DUSE_PARALLEL+        Build-depends:	parallel >= 3.0+        CPP-Options:	-DPARALLELISE  Executable bishbosh     Import:	commonStanza, exeStanza, profStanza@@ -354,7 +372,7 @@         Other-modules:	BishBosh.Concurrent.SignalHandlers      Build-depends:-        array		^>= 0.5.1.1,+        array		>= 0.5.2.0,         deepseq		^>= 1.4.1,         directory,         extra		^>= 1.7.4,@@ -473,13 +491,12 @@         BishBosh.Test.QuickCheck.Input.Options         BishBosh.Test.QuickCheck.Input.PGNOptions         BishBosh.Test.QuickCheck.Input.PieceSquareTable-        BishBosh.Test.QuickCheck.Input.RankValues         BishBosh.Test.QuickCheck.Input.SearchOptions+        BishBosh.Test.QuickCheck.Input.RankValues         BishBosh.Test.QuickCheck.Input.StandardOpeningOptions         BishBosh.Test.QuickCheck.Input.UIOptions         BishBosh.Test.QuickCheck.Input.Verbosity         BishBosh.Test.QuickCheck.Metric.CriterionWeight-        BishBosh.Test.QuickCheck.Metric.RankValue         BishBosh.Test.QuickCheck.Model.Game         BishBosh.Test.QuickCheck.Model.GameTree         BishBosh.Test.QuickCheck.Model.MoveFrequency@@ -520,10 +537,11 @@         QuickCheck	^>= 2.13.2      if flag(newtypewrappers)+        Other-modules:	BishBosh.Test.QuickCheck.Metric.RankValue         CPP-Options:	-DUSE_NEWTYPE_WRAPPERS -    if flag(precision)-        CPP-Options:	-DUSE_PRECISION+    if flag(precisenumbers)+        CPP-Options:	-DUSE_PRECISE_NUMBERS     elif flag(narrownumbers)         CPP-Options:	-DUSE_NARROW_NUMBERS 
bishbosh.spec view
@@ -24,7 +24,7 @@  Summary:	BishBosh is a chess-game. Name:		bishbosh-Version:	0.1.3.1+Version:	0.1.4.0 Release:	1 License:	GPLv3 # From '/usr/share/doc/packages/rpm/GROUPS'.
changelog.markdown view
@@ -165,3 +165,18 @@ ## 0.1.3.1 * Increased minimum version for package **deepseq**, to access function **rwhnf**. +## 0.1.4.0+* Rationalised the type-signature of function **BishBosh.StateProperty.Mutator.movePiece** & refactored **BishBosh.State.{Board, CoordinatesByRankByLogicalColour, MaybePieceByCoordinates}.movePiece**.+* Created function **Cartesian.Coordinates.isBetween** to support function **Model.Game.listQualifiedMovesAvailableTo**.+* Efficiency:+	+ Implemented functions **BishBosh.Cartesian.{Coordinates.fromEnum, Ordinate.reflect}** in unboxed primitive arithmetic.+	+ Moved **Either** outwards in the data-type **BishBosh.Component.PieceSquareByCoordinatesByRank.PieceSquareByCoordinatesByRank**, reducing its size, improving performance, & increasing LR symmetry.+	+ Added function **BishBosh.Attribute.MoveType.apply**, & called it from **BishBosh.Evaluation.Fitness.measurePieceSquareValueDifferenceIncrementally** to facilitate catering for *Castling* & *Promotion*.+	+ Added record-field **BishBosh.Input.StandardOpeningOptions.getMaybeMaximumPliesSinceMatch**, to limit the number of failures to match the position against a prerecorded game, before abandoning further attempts.+	+ Unboxed arrays **BishBosh.Input.RankValue.RankValues** & **BishBosh.StateProperty.Censor.NPiecesByRank** (used in record-field **BishBosh.State.Board.getNPiecesDifferenceByRank**), to improve the efficiency of function **BishBosh.Evaluation.Fitness.measureValueOfMaterial**.+	+ Added function **Cartesian.Coordinates.ixInterpolate** to support **State.MaybePieceByCoordinates.isClear**, where it can use **Data.Array.Base.unsafeAt** to bypass repeated conversion from coordinates to array-indices.+	+ Amended **BishBosh.Cartesian.Coordinates.{extrapolate, interpolate}** to also return an array-index, i.e. *(Coordinates, Int)*, thus reducing repeated calls to **Data.Array.IArray.Ix.index Coordinates**.+* Structural:+	+ Split module **BishBosh.Component.PieceSquareByCoordinatesByRank** into **BishBosh.Component.PieceSquareValueByCoordinates** & **BishBosh.Component.PieceSquareValueByCoordinatesByRank**.+	+ Migrated the **CPP**-logic to establish compatibility between environment-variables, into the Cabal-file; also renamed some environment-variables & flags for clarity.+
config/CECP/bishbosh_black.xml view
@@ -28,7 +28,7 @@ 	</evaluationOptions> 	<searchOptions captureMoveSortAlgorithm="MVVLVA" retireKillerMovesAfter="3" sortOnStandardOpeningMoveFrequency="True" usePondering="True"> 		&transpositions;-		<standardOpeningOptions preferVictories="False"/>	<!-- the SCID PGN-database only contains standard-openings -->+		&standardOpeningOptions; 		<searchDepthByLogicalColour> 			<byLogicalColour logicalColour="Black" searchDepth="5"/> 		</searchDepthByLogicalColour>
config/Raw/bishbosh_black.xml view
@@ -28,7 +28,7 @@ 	</evaluationOptions> 	<searchOptions captureMoveSortAlgorithm="MVVLVA" retireKillerMovesAfter="3" sortOnStandardOpeningMoveFrequency="True" usePondering="True"> 		&transpositions;-		<standardOpeningOptions preferVictories="False"/>	<!-- the SCID PGN-database only contains standard-openings -->+		&standardOpeningOptions; 		<searchDepthByLogicalColour> 			<byLogicalColour logicalColour="Black" searchDepth="4"/> 		</searchDepthByLogicalColour>
config/Raw/bishbosh_black_figurine.xml view
@@ -28,7 +28,7 @@ 	</evaluationOptions> 	<searchOptions captureMoveSortAlgorithm="MVVLVA" retireKillerMovesAfter="3" sortOnStandardOpeningMoveFrequency="True" usePondering="True"> 		&transpositions;-		<standardOpeningOptions preferVictories="False"/>	<!-- the SCID PGN-database only contains standard-openings -->+		&standardOpeningOptions; 		<searchDepthByLogicalColour> 			<byLogicalColour logicalColour="Black" searchDepth="4"/> 		</searchDepthByLogicalColour>
config/Raw/bishbosh_both.xml view
@@ -28,7 +28,7 @@ 	</evaluationOptions> 	<searchOptions captureMoveSortAlgorithm="MVVLVA" retireKillerMovesAfter="3" sortOnStandardOpeningMoveFrequency="True"> 		&transpositions;-		<standardOpeningOptions preferVictories="False"/>	<!-- the SCID PGN-database only contains standard-openings -->+		&standardOpeningOptions; 		<searchDepthByLogicalColour> 			<byLogicalColour logicalColour="Black" searchDepth="4"/> 			<byLogicalColour logicalColour="White" searchDepth="4"/>
config/Raw/bishbosh_duel_black.xml view
@@ -33,7 +33,7 @@ 	</evaluationOptions> 	<searchOptions captureMoveSortAlgorithm="MVVLVA" retireKillerMovesAfter="3" sortOnStandardOpeningMoveFrequency="True" usePondering="False">	<!-- CAVEAT: pondering uses time more productively used by the other instance --> 		&transpositions;-		<standardOpeningOptions preferVictories="False"/>	<!-- maximise randomness -->+		&standardOpeningOptions; 		<searchDepthByLogicalColour> 			<byLogicalColour logicalColour="Black" searchDepth="3"/> 		</searchDepthByLogicalColour>
config/Raw/bishbosh_duel_white.xml view
@@ -33,7 +33,7 @@ 	</evaluationOptions> 	<searchOptions captureMoveSortAlgorithm="MVVLVA" retireKillerMovesAfter="3" sortOnStandardOpeningMoveFrequency="True" usePondering="False">	<!-- CAVEAT: pondering uses time more productively used by the other instance --> 		&transpositions;-		<standardOpeningOptions preferVictories="False"/>	<!-- maximise randomness -->+		&standardOpeningOptions; 		<searchDepthByLogicalColour> 			<byLogicalColour logicalColour="White" searchDepth="3"/> 		</searchDepthByLogicalColour>
config/Raw/bishbosh_prof.xml view
@@ -28,7 +28,7 @@ 	</evaluationOptions> 	<searchOptions captureMoveSortAlgorithm="MVVLVA" retireKillerMovesAfter="3" sortOnStandardOpeningMoveFrequency="True"> 		&transpositions;-		<standardOpeningOptions preferVictories="False"/>	<!-- the SCID PGN-database only contains standard-openings -->+		&standardOpeningOptions; 		<searchDepthByLogicalColour> 			<byLogicalColour logicalColour="Black" searchDepth="4"/> 			<byLogicalColour logicalColour="White" searchDepth="4"/>
config/Raw/bishbosh_white.xml view
@@ -28,7 +28,7 @@ 	</evaluationOptions> 	<searchOptions captureMoveSortAlgorithm="MVVLVA" retireKillerMovesAfter="3" sortOnStandardOpeningMoveFrequency="True" usePondering="True"> 		&transpositions;-		<standardOpeningOptions preferVictories="False"/>	<!-- the SCID PGN-database only contains standard-openings -->+		&standardOpeningOptions; 		<searchDepthByLogicalColour> 			<byLogicalColour logicalColour="White" searchDepth="4"/> 		</searchDepthByLogicalColour>
config/bishbosh.dtd view
@@ -75,25 +75,27 @@ 			trapRepeatedPositions			(False | True)	#IMPLIED 			usePondering				(False | True)	#IMPLIED 		>+		<!ELEMENT transpositions EMPTY>+			<!ATTLIST transpositions+				retireTranspositionsAfter	CDATA	#REQUIRED+				minimumTranspositionSearchDepth	CDATA	#REQUIRED+			>+		<!ENTITY transpositions SYSTEM "transpositions.xml"> 		<!ELEMENT standardOpeningOptions EMPTY> 			<!ATTLIST standardOpeningOptions+				maximumPliesSinceMatch		CDATA		#IMPLIED+				preferVictories			(False | True)	#IMPLIED 				tryToMatchMoves			(False | True)	#IMPLIED 				tryToMatchViaJoiningMove	(False | True)	#IMPLIED 				tryToMatchColourFlippedPosition	(False | True)	#IMPLIED-				preferVictories			(False | True)	#IMPLIED 			>+		<!ENTITY standardOpeningOptions SYSTEM "standardOpeningOptions.xml"> 		<!ELEMENT searchDepthByLogicalColour (byLogicalColour)*> 			<!ELEMENT byLogicalColour EMPTY> 				<!ATTLIST byLogicalColour 					logicalColour	(Black | White) #REQUIRED 					searchDepth	CDATA		#REQUIRED 				>-		<!ELEMENT transpositions EMPTY>-			<!ATTLIST transpositions-				retireTranspositionsAfter	CDATA	#REQUIRED-				minimumTranspositionSearchDepth	CDATA	#REQUIRED-			>-		<!ENTITY transpositions SYSTEM "transpositions.xml"> 	<!ELEMENT ioOptions ((pgnOptions)*, (persistence)?, (uiOptions)?)> 		<!ATTLIST ioOptions 			outputConfigFilePath	CDATA	#IMPLIED
config/bishbosh.rng view
@@ -93,19 +93,23 @@ 					</optional><optional> 						<element name="standardOpeningOptions"> 							<optional>-								<attribute name="tryToMatchMoves">+								<attribute name="maximumPliesSinceMatch">+									<data type="nonNegativeInteger"/>+								</attribute>+							</optional><optional>+								<attribute name="preferVictories"> 									<ref name="Boolean"/> 								</attribute> 							</optional><optional>-								<attribute name="tryToMatchViaJoiningMove">+								<attribute name="tryToMatchMoves"> 									<ref name="Boolean"/> 								</attribute> 							</optional><optional>-								<attribute name="tryToMatchColourFlippedPosition">+								<attribute name="tryToMatchViaJoiningMove"> 									<ref name="Boolean"/> 								</attribute> 							</optional><optional>-								<attribute name="preferVictories">+								<attribute name="tryToMatchColourFlippedPosition"> 									<ref name="Boolean"/> 								</attribute> 							</optional>
+ config/standardOpeningOptions.xml view
@@ -0,0 +1,24 @@+<!--+	AUTHOR: Dr. Alistair Ward++	Copyright (C) 2021 Dr. Alistair Ward++	This file is part of BishBosh.++	BishBosh is free software: you can redistribute it and/or modify+	it under the terms of the GNU General Public License as published by+	the Free Software Foundation, either version 3 of the License, or+	(at your option) any later version.++	BishBosh is distributed in the hope that it will be useful,+	but WITHOUT ANY WARRANTY; without even the implied warranty of+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+	GNU General Public License for more details.++	You should have received a copy of the GNU General Public License+	along with BishBosh.  If not, see <http://www.gnu.org/licenses/>.+-->+<!--+	This controls standard-opening options.+-->+<standardOpeningOptions maximumPliesSinceMatch="3" preferVictories="False"/>       <!-- Permits the tightest transposition away from a prerecorded game, & back. Standard-openings don't typically describe an entire game.  -->
makefile view
@@ -31,46 +31,44 @@ hlint: $(BIN_DIR)/hlint 	@$@ -j	--no-exit-code\ 		--cpp-define 'USE_NEWTYPE_WRAPPERS'\-		--cpp-define 'USE_PARALLEL'\+		--cpp-define 'PARALLELISE'\ 		--cpp-define 'USE_POLYPARSE=L'\-		--cpp-define 'USE_UNBOXED_ARRAYS'\ 		--ignore 'Use tuple-section'\ 		src-lib/ +RTS -N -RTS 	@$@ -j	--no-exit-code\ 		--cpp-define 'MOVE_NOTATION=S'\ 		--cpp-define 'USE_HXTRELAXNG'\-		--cpp-define 'USE_UNBOXED_ARRAYS'\ 		--cpp-define 'USE_UNIX'\-		--ignore 'Reduce duplication'\ 		src-exe/ +RTS -N -RTS 	@$@ -j	--cpp-define 'USE_NEWTYPE_WRAPPERS'\-		--cpp-define 'USE_POLYPARSE=L'\ 		--cpp-define 'USE_BRATKO_KOPEC'\ 		--ignore 'Use tuple-section'\ 		src-test/ +RTS -N -RTS  # Serially compile with various CPP-flags & run the test-suites. test:-	@for FLAG in -polyparse newtypewrappers narrownumbers unboxedarrays -hxtrelaxng -threaded precision; do\+	@for FLAG in -polyparse newtypewrappers unbox precisenumbers narrownumbers -hxtrelaxng -arrayunsafeat -threaded llvm; do\ 		echo $${FLAG};\ 		stack '$@' --flag="$(PACKAGE_NAME):$${FLAG}" $(GHC_OPTIONS) '$(PACKAGE_NAME):test:hunit-tests' '$(PACKAGE_NAME):test:quickcheck-tests' || break;\ 	done -# Compile with random CPP-flags & run the test-suites.+# Repeatedly compile with random CPP-flags & run the test-suites, until failure. randomTest:-	FLAGS=$$(shuf --echo -- hxtrelaxng narrownumbers newtypewrappers polyparse precision threaded unboxedarrays | head --lines=3 | sed -e '1s/^/-/' -e 's/\(.*\)/--flag=$(PACKAGE_NAME):\1/');\+	@FLAGS=$$(shuf --echo -- arrayunsafeat hxtrelaxng llvm narrownumbers newtypewrappers polyparse precisenumbers threaded unbox | head --lines=4 | sed -e '1,2s/^/-/' -e 's/\(.*\)/--flag=$(PACKAGE_NAME):\1/');\ 	echo $${FLAGS};\-	stack test $${FLAGS} $(GHC_OPTIONS) '$(PACKAGE_NAME):test:hunit-tests' '$(PACKAGE_NAME):test:quickcheck-tests'+	stack test $${FLAGS} $(GHC_OPTIONS) '$(PACKAGE_NAME):test:hunit-tests' '$(PACKAGE_NAME):test:quickcheck-tests';+	make '$@'; # Recurse.  # Profile a single-threaded build, to access entry-counts. prof: 	@stack install --profile --flag='$(PACKAGE_NAME):-threaded' $(GHC_OPTIONS) '$(PACKAGE_NAME):exe:$(PACKAGE_NAME)';-	sleep 32;	# Let the test-machine reach a quiescent state.+	sleep 60;	# Let the test-machine reach a quiescent state. 	@$(PACKAGE_NAME) -i 'config/Raw/$(PACKAGE_NAME)_$@.xml' +RTS -p -RTS  # Profile. profN2: 	@stack install --profile $(GHC_OPTIONS) '$(PACKAGE_NAME):exe:$(PACKAGE_NAME)';+	sleep 60;	# Let the test-machine reach a quiescent state. 	@$(PACKAGE_NAME) -i 'config/Raw/$(PACKAGE_NAME)_prof.xml' +RTS -p -N2 -RTS  # Install 'bishbosh'.
man/man5/bishbosh.5 view
@@ -137,10 +137,11 @@ lb	li	lb	l	. Attribute	Type	Default	Meaning =========	====	=======	=======+maximumPliesSinceMatch	Int		the maximum number of plies since the last match with a prerecorded game, before abandoning further attempts; defaulting to \fIunlimited\fR.+preferVictories	Bool	True	whether from all matching positions extracted from the PGN-database, to prefer moves which result in a greater probability of victory, for the player who has the next move. tryToMatchMoves	Bool	True	whether to attempt to exactly match the moves already made, with a standard opening; i.e. without matching transpositions. tryToMatchViaJoiningMove	Bool	True	whether to attempt to join the current position (irrespective of the means by which it was achieved) to a standard opening that's only one move away. tryToMatchColourFlippedPosition	Bool	True	whether to attempt to match a colour-flipped (<\fBhttps://www.chessprogramming.org/Color_Flipping\fR>) version of the current position with a standard opening.-preferVictories	Bool	True	whether from all matching positions extracted from the PGN-database, to prefer moves which result in a greater probability of victory, for the player who has the next move. .TE .IP \(bu \fBsearchDepth\fR \fIInt\fR, defaulting to "\fB4\fR" (minimum "\fB1\fR"): the number of plies (half moves) to search ahead, when selecting the next move.@@ -162,7 +163,7 @@ Attribute	Type	Default	Meaning =========	====	=======	======= databaseFilePath	\fIFile-path\fR		The path in the local file-system, to a PGN-database.-decompressor	String		The optional name of an executable (available in the OS) used to decompress (to \fIstdout\fR) the specified file; the file's suffix isn't considered significant.+decompressor	\fIString\fR		The optional name of an executable (available in the OS) used to decompress (to \fIstdout\fR) the specified file; the file's suffix isn't considered significant. minimumPlies	\fIInt\fR	1	The minimum number of half moves, for an archived game to be considered valuable. maximumGames	\fIInt\fR		The optional maximum number of games to read from the database. isStrictlySequential	(\fBTrue\fR|\fBFalse\fR)	True	Whether the recorded move-numbers are accurate.
src-exe/BishBosh/Concurrent/Pondering.hs view
@@ -66,10 +66,7 @@ 	-> Control.Concurrent.MVar answer 	-> IO (Pondering premise) ponder putStrLn' (premiseString, premise) answer mVar	= do-	threadId	<- Control.Concurrent.forkIO $ do-		Control.Concurrent.putMVar mVar $!! answer--		putStrLn' $ showString "pondering-thread has a response based on " premiseString+	threadId	<- Control.Concurrent.forkIO . Control.Concurrent.putMVar mVar $!! answer  	putStrLn' . showString "pondering (on " . shows threadId $ showString ") a response to " premiseString 
src-exe/BishBosh/Play.hs view
@@ -23,7 +23,7 @@  	* Constructs the Zobrist data-type. -	* Analyses standard-opening moves in order to statically sort the move-tree.+	* Analyses standard opening moves in order to statically sort the move-tree.  	* Reads any persistent game-state from file, to initialise the play-state, which constructs the quantified move tree. 
src-exe/BishBosh/State/PlayState.hs view
@@ -34,7 +34,8 @@ --		getMoveFrequency, 		getSearchState, 		getOptions,-		getMaybeApplicationTerminationReason+		getMaybeApplicationTerminationReason,+		getNPliesSinceStandardOpeningMatch 	), -- * Functions 	calculateCriterionValueStatistics,@@ -46,6 +47,7 @@ -- ** Mutators 	reconstructPositionHashQuantifiedGameTree, 	resetPositionHashQuantifiedGameTree,+	rollBackPositionHashQuantifiedGameTree, --	setPositionHashQuantifiedGameTree, 	updateWithAutomaticMove, 	updateWithManualMove,@@ -71,6 +73,7 @@ import qualified	BishBosh.Search.SearchState				as Search.SearchState import qualified	BishBosh.State.ApplicationTerminationReason		as State.ApplicationTerminationReason import qualified	BishBosh.State.TurnsByLogicalColour			as State.TurnsByLogicalColour+import qualified	BishBosh.Type.Count					as Type.Count import qualified	BishBosh.Type.Crypto					as Type.Crypto import qualified	BishBosh.Type.Mass					as Type.Mass import qualified	Control.Exception@@ -88,7 +91,8 @@ 	getMoveFrequency			:: Model.GameTree.MoveFrequency,						-- ^ The constant frequency of moves extracted from file. 	getSearchState				:: Search.SearchState.SearchState positionHash, 	getOptions				:: Input.Options.Options,							-- ^ The constant options by which the game is configured.-	getMaybeApplicationTerminationReason	:: Maybe State.ApplicationTerminationReason.ApplicationTerminationReason	-- ^ Whether the game has terminated.+	getMaybeApplicationTerminationReason	:: Maybe State.ApplicationTerminationReason.ApplicationTerminationReason,	-- ^ Whether the game has terminated.+	getNPliesSinceStandardOpeningMatch	:: Type.Count.NPlies								-- ^ The number of plies since matching the position with a standard opening. }  -- | Constructor.@@ -114,7 +118,8 @@ 		Input.Options.getEvaluationOptions &&& Input.Options.getSearchOptions $ options 	) zobrist moveFrequency game, 	getOptions				= options,-	getMaybeApplicationTerminationReason	= Nothing+	getMaybeApplicationTerminationReason	= Nothing,+	getNPliesSinceStandardOpeningMatch	= 0 }  -- | Accessor.@@ -131,7 +136,10 @@ }  -- | Reconstruct the /positionHashQuantifiedGameTree/ (in the /searchState/), with the apex set to the specified game.-reconstructPositionHashQuantifiedGameTree :: Data.Bits.Bits positionHash => Model.Game.Game -> Transformation positionHash+reconstructPositionHashQuantifiedGameTree+	:: Data.Bits.Bits positionHash+	=> Model.Game.Game+	-> Transformation positionHash {-# SPECIALISE reconstructPositionHashQuantifiedGameTree :: Model.Game.Game -> Transformation Type.Crypto.PositionHash #-} reconstructPositionHashQuantifiedGameTree game playState@MkPlayState { 	getZobrist		= zobrist,@@ -148,22 +156,43 @@ {-# SPECIALISE resetPositionHashQuantifiedGameTree :: Transformation Type.Crypto.PositionHash #-} resetPositionHashQuantifiedGameTree playState	= reconstructPositionHashQuantifiedGameTree Data.Default.def playState { 	getCriterionValues			= [],-	getMaybeApplicationTerminationReason	= Nothing+	getMaybeApplicationTerminationReason	= Nothing,+	getNPliesSinceStandardOpeningMatch	= 0 } +-- | Roll-back the state by the specified number of plies.+rollBackPositionHashQuantifiedGameTree+	:: Data.Bits.Bits positionHash+	=> Model.Game.Game+	-> Type.Count.NPlies+	-> Transformation positionHash+{-# SPECIALISE rollBackPositionHashQuantifiedGameTree :: Model.Game.Game -> Type.Count.NPlies -> Transformation Type.Crypto.PositionHash #-}+rollBackPositionHashQuantifiedGameTree game nPlies playState@MkPlayState {+	getNPliesSinceStandardOpeningMatch	= nPliesSinceStandardOpeningMatch+} = reconstructPositionHashQuantifiedGameTree game playState {+	getNPliesSinceStandardOpeningMatch	= max 0 $ nPliesSinceStandardOpeningMatch - nPlies+}+ -- | Mutator. updateWithAutomaticMove 	:: [Metric.CriterionValue.CriterionValue] 	-> Search.SearchState.SearchState positionHash 	-> Transformation positionHash-updateWithAutomaticMove criterionValues searchState playState	= playState {-	getCriterionValues	= criterionValues : getCriterionValues playState,-	getSearchState		= searchState+updateWithAutomaticMove criterionValues' searchState playState@MkPlayState {+	getCriterionValues			= criterionValues,+	getNPliesSinceStandardOpeningMatch	= nPliesSinceStandardOpeningMatch+} = playState {+	getCriterionValues			= criterionValues' : criterionValues,+	getSearchState				= searchState,+	getNPliesSinceStandardOpeningMatch	= succ nPliesSinceStandardOpeningMatch }  -- | Mutator.-updateWithManualMove :: Model.Game.Game -> Transformation positionHash-updateWithManualMove game playState@MkPlayState { getSearchState = searchState }	= setPositionHashQuantifiedGameTree (+updateWithManualMove+	:: Model.Game.Game+	-> Bool	-- ^ Whether the move matches a standard opening.+	-> Transformation positionHash+updateWithManualMove game standardOpeningMatch playState@MkPlayState { getSearchState = searchState }	= setPositionHashQuantifiedGameTree ( 	Data.Maybe.fromMaybe ( 		Control.Exception.throw $ Data.Exception.mkIncompatibleData "BishBosh.State.PlayState.updateWithManualMove:\tEvaluation.PositionHashQuantifiedGameTree.reduce failed." 	) . Evaluation.PositionHashQuantifiedGameTree.reduce (@@ -175,7 +204,11 @@ 			) 		) . Evaluation.QuantifiedGame.getLastTurn . Evaluation.PositionHashQuantifiedGameTree.getQuantifiedGame 	) $ Search.SearchState.getPositionHashQuantifiedGameTree searchState- ) playState+ ) $ playState {+	getNPliesSinceStandardOpeningMatch	= if standardOpeningMatch+		then 0+		else succ $ getNPliesSinceStandardOpeningMatch playState+ }  -- | Calculate the /root-mean-square/ & the /standard-deviation/, of the values of each type of /criterion/. calculateCriterionValueStatistics :: (
src-exe/BishBosh/UI/CECP.hs view
@@ -198,14 +198,17 @@ 	-> State.PlayState.PlayState positionHash 	-> IO (State.PlayState.PlayState positionHash) {-# SPECIALISE readMove :: ContextualNotation.PositionHashQualifiedMoveTree.PositionHashQualifiedMoveTree Type.Crypto.PositionHash -> System.Random.StdGen -> Time.StopWatch.StopWatch -> State.PlayState.PlayState Type.Crypto.PositionHash -> IO (State.PlayState.PlayState Type.Crypto.PositionHash) #-}+{-# ANN readMove "HLint: ignore Reduce duplication" #-} readMove positionHashQualifiedMoveTree randomGen	= slave where 	slave runningWatch playState	= let 		(game, options)			= State.PlayState.getGame &&& State.PlayState.getOptions $ playState 		(searchOptions, ioOptions)	= Input.Options.getSearchOptions &&& Input.Options.getIOOptions $ options -		(searchDepthByLogicalColour, tryToMatchSwitches)	= Input.SearchOptions.getSearchDepthByLogicalColour &&& Input.StandardOpeningOptions.getMatchSwitches . Input.SearchOptions.getStandardOpeningOptions $ searchOptions+		(searchDepthByLogicalColour, standardOpeningOptions)	= Input.SearchOptions.getSearchDepthByLogicalColour &&& Input.SearchOptions.getStandardOpeningOptions $ searchOptions 		fullyManual						= Data.Foldable.null searchDepthByLogicalColour +		matchSwitches	= Input.StandardOpeningOptions.getMatchSwitches standardOpeningOptions+ 		uiOptions	= Input.IOOptions.getUIOptions ioOptions  		moveNotation	= Input.UIOptions.getMoveNotation uiOptions@@ -219,7 +222,21 @@  			onCommand :: UI.Command.Command -> IO (State.PlayState.PlayState positionHash) 			onCommand UI.Command.Hint	= do-				Control.Monad.unless (Model.Game.isTerminated game) . Data.Maybe.maybe (+				Control.Monad.unless (Model.Game.isTerminated game) $ (+					let+						nPliesSinceStandardOpeningMatch	= State.PlayState.getNPliesSinceStandardOpeningMatch playState+					in if Data.Maybe.maybe True {-unlimited-} (nPliesSinceStandardOpeningMatch <=) $ Input.StandardOpeningOptions.getMaybeMaximumPliesSinceMatch standardOpeningOptions+						then do+							Control.Monad.when (verbosity > Data.Default.def) . System.IO.hPutStrLn System.IO.stderr $ Text.ShowPrefix.showsPrefixInfo "attempting to match the current position with prerecorded games."++							return {-to IO-monad-} $ ContextualNotation.PositionHashQualifiedMoveTree.maybeRandomlySelectOnymousQualifiedMove randomGen (+								Input.StandardOpeningOptions.getPreferVictories standardOpeningOptions+							 ) matchSwitches positionHashQualifiedMoveTree game+						else do+							Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowPrefix.showsPrefixInfo $ shows nPliesSinceStandardOpeningMatch " plies since matching the position with a prerecorded game => not attempting."++							return {-to IO-monad-} Nothing	-- Don't attempt to match.+				 ) >>= Data.Maybe.maybe ( 					do 						Control.Monad.when (verbosity > Data.Default.def && not (ContextualNotation.PositionHashQualifiedMoveTree.isTerminal positionHashQualifiedMoveTree)) . System.IO.hPutStrLn System.IO.stderr $ Text.ShowPrefix.showsPrefixInfo "failed to find any suitable archived move." @@ -241,9 +258,7 @@ 					\(qualifiedMove, _) -> putStrLn . showString hintTag . showChar ' ' $ if displaySAN 						then ContextualNotation.StandardAlgebraic.showMove explicitEnpassant qualifiedMove game 						else Notation.MoveNotation.showNotation moveNotation qualifiedMove-				 ) $ ContextualNotation.PositionHashQualifiedMoveTree.maybeRandomlySelectOnymousQualifiedMove randomGen (-					Input.StandardOpeningOptions.getPreferVictories . Input.SearchOptions.getStandardOpeningOptions $ searchOptions-				 ) tryToMatchSwitches positionHashQualifiedMoveTree game+				 )  				return {-to IO-monad-} playState	-- N.B.: though one could merely call "eventLoop", a new random-generator is desirable in case an alternative hint is requested. 			onCommand (UI.Command.Print printObject)	= do@@ -301,7 +316,7 @@ 			onCommand (UI.Command.RollBack maybeNPlies)	= let 				rollBack :: Type.Count.NPlies -> IO (State.PlayState.PlayState positionHash) 				rollBack nPlies-					| (game', _) : _ <- drop (fromIntegral $ pred nPlies) $ Model.Game.rollBack game	= return {-to IO-monad-} $ State.PlayState.reconstructPositionHashQuantifiedGameTree game' playState+					| (game', _) : _ <- drop (fromIntegral $ pred nPlies) $ Model.Game.rollBack game	= return {-to IO-monad-} $ State.PlayState.rollBackPositionHashQuantifiedGameTree game' nPlies playState 					| otherwise										= onCommand UI.Command.Restart 			 in Data.Maybe.maybe ( 				let@@ -413,7 +428,7 @@ 										[(name, _result)]	-> showString ":\t" . showString name 										_			-> id 								) ""-							 ) $ ContextualNotation.PositionHashQualifiedMoveTree.findNextOnymousQualifiedMoves tryToMatchSwitches positionHashQualifiedMoveTree game+							 ) $ ContextualNotation.PositionHashQualifiedMoveTree.findNextOnymousQualifiedMoves matchSwitches positionHashQualifiedMoveTree game  							eventLoop 						"computer"	-> eventLoop	-- No action required.@@ -966,7 +981,7 @@  								let 									game'		= Model.Game.applyEitherQualifiedMove eitherQualifiedMove game-									playState'	= State.PlayState.updateWithManualMove game' playState+									playState'	= State.PlayState.updateWithManualMove game' False {-No match-} playState  								Control.Monad.when (verbosity == maxBound) $ do 									System.IO.hPutStrLn System.IO.stderr . Text.ShowPrefix.showsPrefixInfo . showString Component.Move.tag . Text.ShowList.showsAssociation . shows (@@ -1022,6 +1037,8 @@ 		evaluationOptions	= Input.Options.getEvaluationOptions options 		searchOptions		= Input.Options.getSearchOptions options +		standardOpeningOptions	= Input.SearchOptions.getStandardOpeningOptions searchOptions+ 		(uiOptions, maybeMaximumPGNNames)	= Input.IOOptions.getUIOptions &&& Input.IOOptions.getMaybeMaximumPGNNames $ ioOptions  		moveNotation	= Input.UIOptions.getMoveNotation uiOptions@@ -1060,7 +1077,23 @@ 								else return {-to IO-monad-} 						 ) maybePondering 				 ) (-					\searchDepth' -> Data.Maybe.maybe (+					\searchDepth' -> (+						let+							nPliesSinceStandardOpeningMatch	= State.PlayState.getNPliesSinceStandardOpeningMatch playState'+						in if Data.Maybe.maybe True {-unlimited-} (nPliesSinceStandardOpeningMatch <=) $ Input.StandardOpeningOptions.getMaybeMaximumPliesSinceMatch standardOpeningOptions+							then do+								Control.Monad.when (verbosity > Data.Default.def) . System.IO.hPutStrLn System.IO.stderr $ Text.ShowPrefix.showsPrefixInfo "attempting to match the current position with prerecorded games."++								return {-to IO-monad-} $ uncurry (+									ContextualNotation.PositionHashQualifiedMoveTree.maybeRandomlySelectOnymousQualifiedMove randomGen'+								 ) (+									Input.StandardOpeningOptions.getPreferVictories &&& Input.StandardOpeningOptions.getMatchSwitches $ standardOpeningOptions+								 ) positionHashQualifiedMoveTree game'	-- Determine whether the automated player's move can be decided by a search of recorded games or we must decide ourself.+							else do+								Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowPrefix.showsPrefixInfo $ shows nPliesSinceStandardOpeningMatch " plies since matching the position with a prerecorded game => not attempting."++								return {-to IO-monad-} Nothing	-- Don't attempt to match.+					) >>= Data.Maybe.maybe ( 						do 							Control.Monad.when ( 								verbosity > Data.Default.def && not (@@ -1157,7 +1190,7 @@ 							Data.Maybe.maybe ( 								return {-to IO-monad-} () 							 ) (-								Concurrent.Pondering.abort mVar >=> Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowPrefix.showsPrefixInfo . showString "pondering pre-empted by standard-opening match => "+								Concurrent.Pondering.abort mVar >=> Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowPrefix.showsPrefixInfo . showString "pondering pre-empted by a match with a prerecorded game => " 							 ) maybePondering  							let selectedGame	= Model.Game.applyQualifiedMove qualifiedMove game'@@ -1174,12 +1207,8 @@  							putStrLn . showString moveTag . showChar ' ' $ Notation.MoveNotation.showNotation moveNotation qualifiedMove	-- Send the move to the GUI. -							return {-to IO-monad-} (State.PlayState.updateWithManualMove selectedGame playState', Nothing)	-- N.B.: one could ponder, but would have to construct a game-tree, & the chance of a subsequent standard-opening move is high.-					 ) $ uncurry (-						ContextualNotation.PositionHashQualifiedMoveTree.maybeRandomlySelectOnymousQualifiedMove randomGen'-					 ) (-						Input.StandardOpeningOptions.getPreferVictories &&& Input.StandardOpeningOptions.getMatchSwitches $ Input.SearchOptions.getStandardOpeningOptions searchOptions-					 ) positionHashQualifiedMoveTree game'	-- Determine whether the automated player's move can be decided by a search of recorded games or we must decide ourself.+							return {-to IO-monad-} (State.PlayState.updateWithManualMove selectedGame True {-match-} playState', Nothing)	-- N.B.: one could ponder, but would have to construct a game-tree, & the chance of a subsequent standard opening move is high.+					 ) 				 ) ( 					if Input.UIOptions.isCECPManualMode uiOptions' 						then Nothing
src-exe/BishBosh/UI/Raw.hs view
@@ -64,7 +64,6 @@ import qualified	BishBosh.State.PlayState					as State.PlayState import qualified	BishBosh.Text.ShowColouredPrefix				as Text.ShowColouredPrefix import qualified	BishBosh.Text.ShowList						as Text.ShowList-import qualified	BishBosh.Text.ShowPrefix					as Text.ShowPrefix import qualified	BishBosh.Time.StopWatch						as Time.StopWatch import qualified	BishBosh.Type.Count						as Type.Count import qualified	BishBosh.Type.Crypto						as Type.Crypto@@ -103,13 +102,15 @@ 	-> State.PlayState.PlayState positionHash 	-> IO (State.PlayState.PlayState positionHash) {-# SPECIALISE readMove :: ContextualNotation.PositionHashQualifiedMoveTree.PositionHashQualifiedMoveTree Type.Crypto.PositionHash -> System.Random.StdGen -> Time.StopWatch.StopWatch -> State.PlayState.PlayState Type.Crypto.PositionHash -> IO (State.PlayState.PlayState Type.Crypto.PositionHash) #-}+{-# ANN readMove "HLint: ignore Reduce duplication" #-} readMove positionHashQualifiedMoveTree randomGen runningWatch playState	= let 	(game, options)			= State.PlayState.getGame &&& State.PlayState.getOptions $ playState 	(searchOptions, ioOptions)	= Input.Options.getSearchOptions &&& Input.Options.getIOOptions $ options -	searchDepthByLogicalColour	= Input.SearchOptions.getSearchDepthByLogicalColour searchOptions-	fullyManual			= Data.Foldable.null searchDepthByLogicalColour+	(searchDepthByLogicalColour, standardOpeningOptions)	= Input.SearchOptions.getSearchDepthByLogicalColour &&& Input.SearchOptions.getStandardOpeningOptions $ searchOptions +	fullyManual	= Data.Foldable.null searchDepthByLogicalColour+ 	(uiOptions, maybeMaximumPGNNames)	= Input.IOOptions.getUIOptions &&& Input.IOOptions.getMaybeMaximumPGNNames $ ioOptions  	moveNotation	= Input.UIOptions.getMoveNotation uiOptions@@ -132,7 +133,23 @@  		onCommand :: UI.Command.Command -> IO (State.PlayState.PlayState positionHash) 		onCommand UI.Command.Hint	= do-			Control.Monad.unless (Model.Game.isTerminated game) . Data.Maybe.maybe (+			Control.Monad.unless (Model.Game.isTerminated game) $ (+				let+					nPliesSinceStandardOpeningMatch	= State.PlayState.getNPliesSinceStandardOpeningMatch playState+				in if Data.Maybe.maybe True {-unlimited-} (nPliesSinceStandardOpeningMatch <=) $ Input.StandardOpeningOptions.getMaybeMaximumPliesSinceMatch standardOpeningOptions+					then do+						Control.Monad.when (verbosity > Data.Default.def) . System.IO.hPutStrLn System.IO.stderr $ Text.ShowColouredPrefix.showsPrefixInfo "attempting to match the current position with prerecorded games."++						return {-to IO-monad-} $ uncurry (+							ContextualNotation.PositionHashQualifiedMoveTree.maybeRandomlySelectOnymousQualifiedMove randomGen+						 ) (+							Input.StandardOpeningOptions.getPreferVictories &&& Input.StandardOpeningOptions.getMatchSwitches $ standardOpeningOptions+						 ) positionHashQualifiedMoveTree game+					else do+						Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowColouredPrefix.showsPrefixInfo $ shows nPliesSinceStandardOpeningMatch " plies since matching the position with a prerecorded game => not attempting."++						return {-to IO-monad-} Nothing	-- Don't attempt to match.+			 ) >>= Data.Maybe.maybe ( 				do 					Control.Monad.when (verbosity > Data.Default.def && not (ContextualNotation.PositionHashQualifiedMoveTree.isTerminal positionHashQualifiedMoveTree)) . System.IO.hPutStrLn System.IO.stderr $ Text.ShowColouredPrefix.showsPrefixInfo "failed to find any suitable archived move." @@ -152,11 +169,7 @@ 						_		-> Control.Exception.throwIO . Data.Exception.mkRequestFailure . showString "BishBosh.UI.Raw.readMove.onCommand:\tunexpectedly failed to find any moves; " $ shows game "."	-- CAVEAT: the game should have terminated. 			 ) ( 				\(qualifiedMove, names) -> putStrLn . Text.ShowColouredPrefix.showsPrefixInfo . showString "Try \"" . Notation.MoveNotation.showsNotation moveNotation qualifiedMove . showString "\" from:" $ ContextualNotation.QualifiedMoveForest.showsNames maybeMaximumPGNNames names ""-			 ) $ uncurry (-				ContextualNotation.PositionHashQualifiedMoveTree.maybeRandomlySelectOnymousQualifiedMove randomGen-			 ) (-				Input.StandardOpeningOptions.getPreferVictories &&& Input.StandardOpeningOptions.getMatchSwitches $ Input.SearchOptions.getStandardOpeningOptions searchOptions-			 ) positionHashQualifiedMoveTree game+			 )  			return {-to IO-monad-} playState	-- N.B.: though one could merely call "eventLoop", a new random-generator is desirable in case an alternative hint is requested. 		onCommand (UI.Command.Print printObject)	= do@@ -192,8 +205,6 @@ 		onCommand UI.Command.Restart	= do 			Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr $ Text.ShowColouredPrefix.showsPrefixInfo "restarting game." -			Input.IOOptions.persist ioOptions (verbosity == maxBound) (Data.Default.def :: Model.Game.Game)- 			return {-to IO-monad-} $ State.PlayState.resetPositionHashQuantifiedGameTree playState 		onCommand (UI.Command.RollBack maybeNPlies)	= let 			rollBack :: Type.Count.NPlies -> IO (State.PlayState.PlayState positionHash)@@ -201,7 +212,7 @@ 				| (game', _) : _ <- drop (fromIntegral $ pred nPlies) $ Model.Game.rollBack game	= do 					Control.Monad.when (verbosity == maxBound) . putStrLn $ show2D game' -					return {-to IO-monad-} $ State.PlayState.reconstructPositionHashQuantifiedGameTree game' playState+					return {-to IO-monad-} $ State.PlayState.rollBackPositionHashQuantifiedGameTree game' nPlies playState 				| otherwise	= onCommand UI.Command.Restart 		 in Data.Maybe.maybe ( 			let@@ -301,7 +312,7 @@  						let 							game'		= Model.Game.applyEitherQualifiedMove eitherQualifiedMove game-							playState'	= State.PlayState.updateWithManualMove game' playState+							playState'	= State.PlayState.updateWithManualMove game' False {-No match-} playState  						Control.Monad.when (verbosity == maxBound) $ do 							System.IO.hPutStrLn System.IO.stderr . Text.ShowColouredPrefix.showsPrefixInfo . showString Component.Move.tag . Text.ShowList.showsAssociation . shows (@@ -354,6 +365,8 @@  	(searchOptions, ioOptions)	= Input.Options.getSearchOptions &&& Input.Options.getIOOptions $ options +	standardOpeningOptions	= Input.SearchOptions.getStandardOpeningOptions searchOptions+ 	uiOptions	= Input.IOOptions.getUIOptions ioOptions  	moveNotation	= Input.UIOptions.getMoveNotation uiOptions@@ -398,13 +411,29 @@ 									then {-rolled-back-} Data.Maybe.maybe ( 										return {-to IO-monad-} Nothing 									) $ \pondering -> do-										Concurrent.Pondering.abort mVar pondering >>= Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowPrefix.showsPrefixInfo . showString "pondering invalidated by roll-back => "+										Concurrent.Pondering.abort mVar pondering >>= Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowColouredPrefix.showsPrefixInfo . showString "pondering invalidated by roll-back => "  										return {-to IO-monad-} Nothing	-- Pondering has been terminated. 									else return {-to IO-monad-} 							 ) maybePondering 					 ) (-						\searchDepth' -> Data.Maybe.maybe (+						\searchDepth' -> (+							let+								nPliesSinceStandardOpeningMatch	= State.PlayState.getNPliesSinceStandardOpeningMatch playState'+							in if Data.Maybe.maybe True {-unlimited-} (nPliesSinceStandardOpeningMatch <=) $ Input.StandardOpeningOptions.getMaybeMaximumPliesSinceMatch standardOpeningOptions+								then do+									Control.Monad.when (verbosity > Data.Default.def) . System.IO.hPutStrLn System.IO.stderr $ Text.ShowColouredPrefix.showsPrefixInfo "attempting to match the current position with prerecorded games."++									return {-to IO-monad-} $ uncurry (+										ContextualNotation.PositionHashQualifiedMoveTree.maybeRandomlySelectOnymousQualifiedMove randomGen'+									 ) (+										Input.StandardOpeningOptions.getPreferVictories &&& Input.StandardOpeningOptions.getMatchSwitches $ standardOpeningOptions+									 ) positionHashQualifiedMoveTree game'	-- Determine whether the automated player's move can be decided by a search of recorded games or we must decide ourself.+								else do+									Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowColouredPrefix.showsPrefixInfo $ shows nPliesSinceStandardOpeningMatch " plies since matching the position with a prerecorded game => not attempting."++									return {-to IO-monad-} Nothing	-- Don't attempt to match.+						) >>= Data.Maybe.maybe ( 							do 								Control.Monad.when ( 									verbosity > Data.Default.def && not (@@ -426,11 +455,11 @@ 										(== Concurrent.Pondering.getPremise pondering) . Component.QualifiedMove.getMove . Component.Turn.getQualifiedMove 									) $ Model.Game.maybeLastTurn game'	-- Confirm whether the pondering initiated at the start of the opponent's turn, was founded on the move they eventually made. 										then do-											Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr $ Text.ShowPrefix.showsPrefixInfo "move-premise validated => waiting."+											Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr $ Text.ShowColouredPrefix.showsPrefixInfo "move-premise validated => waiting."  											Control.Concurrent.takeMVar mVar	-- Blocking read, while the pondering terminates. 										else do-											Concurrent.Pondering.abort mVar pondering >>= Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowPrefix.showsPrefixInfo . showString "pondering invalidated by incorrect move-premise => "+											Concurrent.Pondering.abort mVar pondering >>= Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowColouredPrefix.showsPrefixInfo . showString "pondering invalidated by incorrect move-premise => "  											return {-to IO-monad-} searchResult	-- Pondering wasn't well-founded, so the search must be evaluated. 								 ) maybePondering >>= (@@ -468,7 +497,7 @@ 												then case continuation of 													quantifiedGame' {-1st move after ours in optimal move-sequence-} : _	-> fmap Just . ( 														\positionHashQuantifiedGameTree'' -> Concurrent.Pondering.ponder (-															Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowPrefix.showsPrefixInfo+															Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowColouredPrefix.showsPrefixInfo 														) ( 															showString "move-premise" . Text.ShowList.showsAssociation . ($ ".") . Notation.MoveNotation.showsNotation moveNotation &&& Component.QualifiedMove.getMove . Component.Turn.getQualifiedMove $ Evaluation.QuantifiedGame.getLastTurn quantifiedGame' 														) (@@ -490,7 +519,7 @@ 								Data.Maybe.maybe ( 									return {-to IO-monad-} () 								 ) (-									Concurrent.Pondering.abort mVar >=> Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowPrefix.showsPrefixInfo . showString "pondering pre-empted by standard-opening match => "+									Concurrent.Pondering.abort mVar >=> Control.Monad.when (verbosity == maxBound) . System.IO.hPutStrLn System.IO.stderr . Text.ShowColouredPrefix.showsPrefixInfo . showString "pondering pre-empted by match with a prerecorded game => " 								 ) maybePondering  								let selectedGame	= Model.Game.applyQualifiedMove qualifiedMove game'@@ -505,12 +534,8 @@  										putStrLn $ show2D selectedGame -								return {-to IO-monad-} (State.PlayState.updateWithManualMove selectedGame playState', Nothing)	-- N.B.: one could ponder, but would have to construct a game-tree, & the chance of a subsequent standard-opening move is high.-						 ) $ uncurry (-							ContextualNotation.PositionHashQualifiedMoveTree.maybeRandomlySelectOnymousQualifiedMove randomGen'-						 ) (-							Input.StandardOpeningOptions.getPreferVictories &&& Input.StandardOpeningOptions.getMatchSwitches $ Input.SearchOptions.getStandardOpeningOptions searchOptions-						 ) positionHashQualifiedMoveTree game'	-- Determine whether the automated player's move can be decided by a search of recorded games or we must decide ourself.+								return {-to IO-monad-} (State.PlayState.updateWithManualMove selectedGame True {-match-} playState', Nothing)	-- N.B.: one could ponder, but would have to construct a game-tree, & the chance of a subsequent standard opening move is high.+						 ) 					 ) ( 						Model.Game.getNextLogicalColour game' `Map.lookup` Input.SearchOptions.getSearchDepthByLogicalColour searchOptions'	-- Determinate whether the next player is manual. 					 ) >>= (
src-exe/Main.hs view
@@ -31,8 +31,7 @@  import			Control.Arrow((&&&), (***), (|||)) import			Control.Category((>>>))-import			Data.Array.IArray((!))-import qualified	BishBosh.Component.PieceSquareByCoordinatesByRank	as Component.PieceSquareByCoordinatesByRank+import qualified	BishBosh.Component.PieceSquareValueByCoordinatesByRank	as Component.PieceSquareValueByCoordinatesByRank import qualified	BishBosh.ContextualNotation.PGN				as ContextualNotation.PGN import qualified	BishBosh.ContextualNotation.PGNDatabase			as ContextualNotation.PGNDatabase import qualified	BishBosh.ContextualNotation.QualifiedMoveForest		as ContextualNotation.QualifiedMoveForest@@ -42,8 +41,8 @@ import qualified	BishBosh.Input.EvaluationOptions			as Input.EvaluationOptions import qualified	BishBosh.Input.IOOptions				as Input.IOOptions import qualified	BishBosh.Input.Options					as Input.Options-import qualified	BishBosh.Input.PieceSquareTable				as Input.PieceSquareTable import qualified	BishBosh.Input.PGNOptions				as Input.PGNOptions+import qualified	BishBosh.Input.PieceSquareTable				as Input.PieceSquareTable import qualified	BishBosh.Input.UIOptions				as Input.UIOptions import qualified	BishBosh.Input.Verbosity				as Input.Verbosity import qualified	BishBosh.Model.Game					as Model.Game@@ -267,24 +266,24 @@ 			formatPieceSquareTableForGNUPlot options	= Data.Maybe.maybe ( 				Control.Exception.throwIO $ Data.Exception.mkNullDatum "the piece-square table is undefined." 			 ) (-				\pieceSquareByCoordinatesByRank	-> putStr . foldr ($) "" . zipWith (.) (+				\pieceSquareValueByCoordinatesByRank	-> putStr . foldr ($) "" . zipWith (.) ( 					map (-						\gamePhase	-> showChar Component.PieceSquareByCoordinatesByRank.gnuPlotComment . showString gamePhase . showString "-game:\n"+						\gamePhase	-> showChar Component.PieceSquareValueByCoordinatesByRank.gnuPlotComment . showString gamePhase . showString "-game:\n" 					) ["Opening", "End"] 				) $ map (-					\selector	-> Component.PieceSquareByCoordinatesByRank.formatForGNUPlot pieceSquareByCoordinatesByRank (+					\selector	-> Component.PieceSquareValueByCoordinatesByRank.formatForGNUPlot pieceSquareValueByCoordinatesByRank ( 						Property.ShowFloat.showsFloatToN' (-							Input.UIOptions.getNDecimalDigits . Input.IOOptions.getUIOptions $ Input.Options.getIOOptions options	-- PieceSquareValue formatter.+							Input.UIOptions.getNDecimalDigits . Input.IOOptions.getUIOptions $ Input.Options.getIOOptions options	-- PieceSquareValue-formatter. 						) . ( 							realToFrac	:: Type.Mass.PieceSquareValue -> Input.PieceSquareTable.IOFormat 						) 					) ( 						showChar '\t'	-- Column-delimiter. 					) (-						! selector Component.PieceSquareByCoordinatesByRank.nPiecesBounds	-- Select from interpolated values.+						selector Input.EvaluationOptions.nPiecesBounds	-- Select from interpolated values. 					) 				) [snd, fst]-			 ) . Input.EvaluationOptions.getMaybePieceSquareByCoordinatesByRank $ Input.Options.getEvaluationOptions options+			 ) . Input.EvaluationOptions.getMaybePieceSquareValueByCoordinatesByRank $ Input.Options.getEvaluationOptions options  #ifdef USE_UNIX 	Concurrent.SignalHandlers.handleSignals
src-lib/BishBosh/Attribute/MoveType.hs view
@@ -39,6 +39,7 @@ 	enPassant, -- * Functions 	nPiecesMutator,+	apply, -- ** Constructors 	mkMaybeNormalMoveType, 	mkNormalMoveType,@@ -265,4 +266,23 @@ nPiecesMutator moveType 	| isCapture moveType	= pred 	| otherwise		= id++-- | Permit the caller to react in an arbitrary way, according to a specific move-type.+apply+	:: (+		IsShort -> a,	-- Castle.+		a,		-- En-passant+		(+			Maybe Attribute.Rank.Rank {-captured-},+			Maybe Attribute.Rank.Rank {-promotion-}+		) -> a+	)		-- ^ The handlers for each move-type; Castle, En-passant & Normal.+	-> MoveType+	-> a+apply (onCastle, _, _) (Castle isShort)	= onCastle isShort+apply (_, onEnPassant, _) EnPassant	= onEnPassant+apply (_, _, onNormal) Normal {+	getMaybeTakenRank	= maybeTakenRank,+	getMaybePromotionRank	= maybePromotionRank+}					= onNormal (maybeTakenRank, maybePromotionRank) 
src-lib/BishBosh/Attribute/Rank.hs view
@@ -31,6 +31,7 @@ -- ** Type-synonyms 	EvaluateRank, 	ArrayByRank,+	UArrayByRank, -- ** Data-types 	Rank(..), -- * Constants@@ -63,6 +64,7 @@ import qualified	Control.DeepSeq import qualified	Control.Exception import qualified	Data.Array.IArray+import qualified	Data.Array.Unboxed import qualified	Data.Char import qualified	Data.List import qualified	Data.Ord@@ -206,6 +208,9 @@  -- | A boxed array indexed by /rank/, of arbitrary values. type ArrayByRank	= Data.Array.IArray.Array Rank++-- | An unboxed array indexed by /rank/, of fixed-size elements.+type UArrayByRank	= Data.Array.Unboxed.UArray Rank  -- | Array-constructor from an ordered list of elements. listArrayByRank :: Data.Array.IArray.IArray a e => [e] -> a Rank e
src-lib/BishBosh/Cartesian/Abscissa.hs view
@@ -52,6 +52,7 @@ 	inBounds ) where +import			Control.Arrow((&&&)) import			Data.Array.IArray((!)) import qualified	BishBosh.Type.Length	as Type.Length import qualified	Control.Exception@@ -80,24 +81,20 @@  -- | Convert to an array-index. toIx :: Type.Length.X -> Int-{-# INLINE toIx #-} toIx	= fromIntegral . subtract xMin  -- | Convert from an array-index. fromIx :: Int -> Type.Length.X-{-# INLINE fromIx #-} fromIx	= (+ xMin) . fromIntegral  -- | Reflects about the mid-point of the axis. reflect :: Type.Length.X -> Type.Length.X-reflect	= (-	+ (2 * xMin + pred xLength)- ) . negate+reflect	= (2 * xMin + xMax -)  -- | Predicate. inBounds :: Type.Length.X -> Bool {-# INLINE inBounds #-}-inBounds x	= x >= xMin && x <= xMax+inBounds	= uncurry (&&) . ((>= xMin) &&& (<= xMax))  -- | Translate the specified ordinate. translate :: (Type.Length.X -> Type.Length.X) -> Type.Length.X -> Type.Length.X
src-lib/BishBosh/Cartesian/Coordinates.hs view
@@ -1,4 +1,9 @@ {-# LANGUAGE CPP #-}++#ifdef USE_PRIMITIVE+{-# LANGUAGE MagicHash #-}+#endif+ {- 	Copyright (C) 2018 Dr. Alistair Ward @@ -32,11 +37,10 @@ 		getY 	), -- ** Type-synonyms+	QualifiedStraightLine, --	Transformation, 	ArrayByCoordinates,-#ifdef USE_UNBOXED_ARRAYS 	UArrayByCoordinates,-#endif -- * Constants 	tag, 	topLeft,@@ -72,6 +76,7 @@ 	arrayByCoordinates, -- ** Predicates --	inBounds,+	isBetween, 	isPawnsFirstRank, 	isEnPassantRank, 	areSquaresIsochromatic@@ -95,17 +100,15 @@ import qualified	Control.DeepSeq import qualified	Control.Exception import qualified	Data.Array.IArray+import qualified	Data.Array.Unboxed import qualified	Data.Foldable import qualified	Data.List import qualified	Data.Map				as Map import qualified	Data.Maybe -#ifdef USE_PARALLEL-import qualified	Control.Parallel.Strategies-#endif--#ifdef USE_UNBOXED_ARRAYS-import qualified	Data.Array.Unboxed+#ifdef USE_PRIMITIVE+import			GHC.Exts(Int(I#))+import			GHC.Prim((+#), (*#)) #endif  -- | Used to qualify XML.@@ -129,7 +132,8 @@ 	} -- Top Right.  instance Control.DeepSeq.NFData Coordinates where-	rnf MkCoordinates { getX = x, getY = y }	= Control.DeepSeq.rnf (x, y)+--	rnf MkCoordinates { getX = x, getY = y }	= Control.DeepSeq.rnf (x, y)+	rnf _	= ()	-- N.B.: it's already strict.  instance Data.Array.IArray.Ix Coordinates where 	range (lower, upper)			= Control.Exception.assert (lower == minBound && upper == maxBound) Property.FixedMembership.members@@ -145,12 +149,18 @@ 	 ) . (`divMod` fromIntegral Cartesian.Abscissa.xLength)  	fromEnum MkCoordinates {+#ifdef USE_PRIMITIVE+		getX	= I# x,+		getY	= I# y+	} = I# (8# *# y +# x)	-- CAVEAT: bypasses modules 'Cartesian.{Abscissa, Ordinate}'.+#else 		getX	= x, 		getY	= y 	} = fromIntegral Cartesian.Abscissa.xLength * Cartesian.Ordinate.toIx y + Cartesian.Abscissa.toIx x+#endif  instance Ord Coordinates where-	MkCoordinates { getX = x, getY = y } `compare` MkCoordinates { getX = x', getY = y' }	= (y, x) `compare` (y', x')	-- N.B.: x is less significant than y, as required by the implementation of 'Data.Array.IArray.Ix.inRange'.+	MkCoordinates { getX = x, getY = y } `compare` MkCoordinates { getX = x', getY = y' }	= (y, x) `compare` (y', x')	-- N.B.: x is less significant than y.  instance Show Coordinates where 	showsPrec precedence MkCoordinates { getX = x, getY = y }	= showsPrec precedence (x, y)@@ -184,7 +194,9 @@ 		getX	= fromIntegral $! Cartesian.Ordinate.reflect y, 		getY	= fromIntegral x 	} -- +90 degrees, i.e. anti-clockwise.+ 	rotate180	= Property.Opposable.getOpposite+ 	rotate270 MkCoordinates { 		getX	= x, 		getY	= y@@ -382,6 +394,17 @@ 			| direction == Direction.Direction.nw	= (xDecreasing,	yIncreasing) 			| otherwise {-NE-}			= (xIncreasing,	yIncreasing) +-- | A line of /coordinates/, qualified by an array-index into any 'ArrayByCoordinates'.+type QualifiedStraightLine	= [(Coordinates, Int)]++-- | The constant lists of (/coordinates/, array-index), extrapolated from every /coordinate/ in the /board/, in every /direction/.+extrapolationsByDirectionByCoordinates :: ArrayByCoordinates (Direction.Direction.ArrayByDirection QualifiedStraightLine)+extrapolationsByDirectionByCoordinates	= listArrayByCoordinates $ map (+	\coordinates	-> Direction.Direction.listArrayByDirection $ map (+		map (id &&& fromEnum) . extrapolate' coordinates+	) Property.FixedMembership.members {-direction-}+ ) Property.FixedMembership.members {-coordinates-}+ {- | 	* Generates a line of /coordinates/, starting just after the specified source & proceeding in the specified /direction/ to the edge of the board. @@ -391,22 +414,12 @@ extrapolate 	:: Coordinates				-- ^ The point from which to start. 	-> Direction.Direction.Direction	-- ^ The direction in which to proceed.-	-> [Coordinates]+	-> QualifiedStraightLine extrapolate coordinates	direction	= extrapolationsByDirectionByCoordinates ! coordinates ! direction --- | The constant lists of /coordinates/, extrapolated from every /coordinate/ in the /board/, in every /direction/.-extrapolationsByDirectionByCoordinates :: ArrayByCoordinates (Direction.Direction.ArrayByDirection [Coordinates])-extrapolationsByDirectionByCoordinates	= listArrayByCoordinates-#ifdef USE_PARALLEL-	. Control.Parallel.Strategies.withStrategy (Control.Parallel.Strategies.parList Control.Parallel.Strategies.rdeepseq)-#endif-	$ map (-		\coordinates	-> Direction.Direction.listArrayByDirection $ extrapolate' coordinates `map` Property.FixedMembership.members {-direction-}-	) Property.FixedMembership.members {-coordinates-}---- | Apply the specified function to each line of /coordinates/ extrapolated from the specified central hub, in each of the specified /direction/s.+-- | Apply the specified function to each 'QualifiedStraightLine' extrapolated from the specified central hub, in each of the specified /direction/s. applyAlongDirectionsFrom-	:: ([Coordinates] -> [a])			-- ^ Individually map each straight line of coordinates extrapolated from the central hub.+	:: (QualifiedStraightLine -> [a])		-- ^ Individually map each 'QualifiedCoordinatesLine' extrapolated from the central hub. 	-> Coordinates					-- ^ The central hub from which to extrapolate. 	-> Maybe [Direction.Direction.Direction]	-- ^ The directions in which to extrapolate; 'Nothing' implies omnidirectional. 	-> [a]@@ -416,28 +429,28 @@ 	concatMap $ f . (extrapolationsByDirectionByCoordinates ! from !)  ) --- | The constant lists of /coordinates/, between every permutation of source & valid destination on the /board/.-interpolationsByDestinationBySource :: ArrayByCoordinates (Map.Map Coordinates [Coordinates])+-- | The constant 'QualifiedStraightLine', between every permutation of source & valid destination on the /board/.+interpolationsByDestinationBySource :: ArrayByCoordinates (Map.Map Coordinates QualifiedStraightLine) interpolationsByDestinationBySource	= Data.Array.IArray.amap ( 	Map.fromList . map (-		last {-destination-} &&& id {-interpolation-}+		fst {-coordinates-} . last {-destination-} &&& id {-interpolation-} 	) . concatMap ( 		tail {-remove null list-} . Data.List.inits	-- Generate all possible interpolations from this extrapolation. 	) . Data.Foldable.toList  ) extrapolationsByDirectionByCoordinates	-- Derive from extrapolations.  {- |-	* Generates a line of /coordinates/ covering the half open interval @(source, destination]@.+	* Generates a 'QualifiedStraightLine' covering the half open interval @(source, destination]@.  	* CAVEAT: the destination-/coordinates/ must be a valid @Queen@'s /move/ from the source; so that all intermediate points lie on a square of the board. -}-interpolate :: Coordinates -> Coordinates -> [Coordinates]+interpolate :: Coordinates -> Coordinates -> QualifiedStraightLine interpolate coordinatesSource coordinatesDestination	= interpolationsByDestinationBySource ! coordinatesSource Map.! coordinatesDestination  {- | 	* Measures the signed distance between source & destination /coordinates/. -	* N.B.: this isn't the /irrational/ distance a rational crow would fly, but rather the integral /x/ & /y/ components of that path.+	* N.B.: this isn't the typically /irrational/ distance a rational crow would fly, but rather the integral /x/ & /y/ components of that path.  	* CAVEAT: beware the potential fence-post error. -}@@ -465,6 +478,18 @@ areSquaresIsochromatic :: [Coordinates] -> Bool areSquaresIsochromatic	= uncurry (||) . (all (== minBound) &&& all (== maxBound)) . map getLogicalColourOfSquare +{- |+	* Whether the specified coordinates lie within the open interval (source, destination); neither source nor destination lies in this interval.++	* CAVEAT: the source & destination must form a straight line of non-zero length (i.e. a valid Queen's move).+-}+isBetween+	:: Coordinates	-- ^ Source.+	-> Coordinates	-- ^ Destination.+	-> Coordinates	-- ^ Potential intermediary.+	-> Bool+isBetween source destination intermediary	= Data.Maybe.isJust . Data.List.find ((== intermediary) . fst {-coordinates-}) . init {-drop the destination-} $ interpolate source destination+ -- | The conventional starting /coordinates/ for the @King@ of the specified /logical colour/. kingsStartingCoordinates :: Colour.LogicalColour.LogicalColour -> Coordinates kingsStartingCoordinates logicalColour	= MkCoordinates {@@ -488,10 +513,8 @@ -- | A boxed array indexed by /coordinates/, of arbitrary elements. type ArrayByCoordinates	= Data.Array.IArray.Array Coordinates -#ifdef USE_UNBOXED_ARRAYS -- | An unboxed array indexed by /coordinates/, of fixed-size elements. type UArrayByCoordinates	= Data.Array.Unboxed.UArray Coordinates-#endif  -- | Array-constructor from an ordered list of elements. listArrayByCoordinates :: Data.Array.IArray.IArray a e => [e] -> a Coordinates e
src-lib/BishBosh/Cartesian/Ordinate.hs view
@@ -1,3 +1,9 @@+{-# LANGUAGE CPP #-}++#ifdef USE_PRIMITIVE+{-# LANGUAGE MagicHash #-}+#endif+ {- 	Copyright (C) 2018 Dr. Alistair Ward @@ -49,12 +55,18 @@ 	inBounds ) where +import			Control.Arrow((&&&)) import qualified	BishBosh.Cartesian.Abscissa	as Cartesian.Abscissa import qualified	BishBosh.Colour.LogicalColour	as Colour.LogicalColour import qualified	BishBosh.Property.Opposable	as Property.Opposable import qualified	BishBosh.Type.Length		as Type.Length import qualified	Control.Exception +#ifdef USE_PRIMITIVE+import			GHC.Exts(Int(I#))+import			GHC.Prim((-#))+#endif+ -- | The constant length of the /y/-axis. yLength :: Type.Length.Y yLength	= fromIntegral Cartesian.Abscissa.xLength	-- I.E.: the board is square.@@ -70,12 +82,10 @@  -- | Convert to an array-index. toIx :: Type.Length.Y -> Int-{-# INLINE toIx #-} toIx	= fromIntegral . subtract yMin  -- | Convert from an array-index. fromIx :: Int -> Type.Length.Y-{-# INLINE fromIx #-} fromIx	= (+ yMin) . fromIntegral  -- | The /rank/ from which /piece/s conventionally start.@@ -101,14 +111,16 @@  -- | Reflects about the mid-point of the axis. reflect :: Type.Length.Y -> Type.Length.Y-reflect	= (-	+ (2 * yMin + pred yLength)- ) . negate+#ifdef USE_PRIMITIVE+reflect (I# y)	= I# (7# -# y)	-- CAVEAT: hard-coded bounds.+#else+reflect	= (2 * yMin + yMax -)+#endif  -- | Predicate. inBounds :: Type.Length.Y -> Bool {-# INLINE inBounds #-}-inBounds y	= y >= yMin && y <= yMax+inBounds	= uncurry (&&) . ((>= yMin) &&& (<= yMax))  -- | Translate the specified ordinate. translate :: (Type.Length.Y -> Type.Length.Y) -> Type.Length.Y -> Type.Length.Y
src-lib/BishBosh/Cartesian/Vector.hs view
@@ -66,10 +66,13 @@ } deriving (Eq, Show)  instance Control.DeepSeq.NFData Vector where+{- 	rnf MkVector { 		getXDistance	= xDistance, 		getYDistance	= yDistance 	} = Control.DeepSeq.rnf (xDistance, yDistance)+-}+	rnf _	= ()	-- N.B.: it's already strict.  instance Property.Opposable.Opposable Vector where 	getOpposite MkVector {@@ -157,7 +160,6 @@  -- | Whether the specified /vector/ represents a move a @Knight@ could make. isKnightsMove :: Vector -> Bool-{-# INLINE isKnightsMove #-} isKnightsMove MkVector { 	getXDistance	= xDistance, 	getYDistance	= yDistance
src-lib/BishBosh/Colour/LogicalColour.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, LambdaCase #-}+{-# LANGUAGE LambdaCase #-} {- 	Copyright (C) 2018 Dr. Alistair Ward @@ -31,9 +31,6 @@ -- * Types -- ** Type-synonyms 	ArrayByLogicalColour,-#ifdef USE_UNBOXED_ARRAYS-	UArrayByLogicalColour,-#endif -- ** Data-types 	LogicalColour(..), -- * Constants@@ -61,10 +58,6 @@ import qualified	Text.XML.HXT.Arrow.Pickle			as HXT import qualified	Text.XML.HXT.Arrow.Pickle.Schema -#ifdef USE_UNBOXED_ARRAYS-import qualified	Data.Array.Unboxed-#endif- -- | Used to qualify XML. tag :: String tag	= "logicalColour"@@ -135,11 +128,6 @@  -- | A boxed array indexed by /logical colour/, of arbitrary elements. type ArrayByLogicalColour	= Data.Array.IArray.Array LogicalColour--#ifdef USE_UNBOXED_ARRAYS--- | An unboxed array indexed by /logical colour/, of fixed-size values.-type UArrayByLogicalColour	= Data.Array.Unboxed.UArray LogicalColour-#endif  -- | Array-constructor from an ordered list of elements. listArrayByLogicalColour :: Data.Array.IArray.IArray a e => [e] -> a LogicalColour e
src-lib/BishBosh/Colour/LogicalColourOfSquare.hs view
@@ -34,7 +34,7 @@ 	black, 	white, -- * Functions--- ** Predicate+-- ** Predicates 	isBlack ) where 
src-lib/BishBosh/Component/Accountant.hs view
@@ -27,7 +27,7 @@ 	Accountant(..) ) where -import qualified	BishBosh.Component.PieceSquareByCoordinatesByRank	as Component.PieceSquareByCoordinatesByRank+import qualified	BishBosh.Component.PieceSquareValueByCoordinatesByRank	as Component.PieceSquareValueByCoordinatesByRank import qualified	BishBosh.Type.Count					as Type.Count import qualified	BishBosh.Type.Mass					as Type.Mass @@ -35,7 +35,7 @@ class Accountant accountant where 	-- | Calculate the total value of the /coordinates/ occupied by the /piece/s of either side. 	sumPieceSquareValueByLogicalColour-		:: Component.PieceSquareByCoordinatesByRank.PieceSquareByCoordinatesByRank+		:: Component.PieceSquareValueByCoordinatesByRank.PieceSquareValueByCoordinatesByRank 		-> accountant 		-> Type.Count.NPieces	-- ^ The number of pieces (of any logical colour or rank) remaining on the board; used to gauge progress through the game. 		-> [Type.Mass.Base]	-- CAVEAT: can't return '[Type.Mass.PieceSquareValue]' because it's bounded.
src-lib/BishBosh/Component/Move.hs view
@@ -156,7 +156,7 @@ } = Cartesian.Vector.measureDistance source destination  -- | Generates a line of /coordinates/ covering the half open interval @(source, destination]@.-interpolate :: Move -> [Cartesian.Coordinates.Coordinates]+interpolate :: Move -> Cartesian.Coordinates.QualifiedStraightLine interpolate move@MkMove { 	getSource	= source, 	getDestination	= destination
src-lib/BishBosh/Component/Piece.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, LambdaCase #-}+{-# LANGUAGE LambdaCase #-} {- 	Copyright (C) 2018 Dr. Alistair Ward @@ -103,10 +103,6 @@ import qualified	Text.XML.HXT.Arrow.Pickle			as HXT import qualified	Text.XML.HXT.Arrow.Pickle.Schema -#ifdef USE_PARALLEL-import qualified	Control.Parallel.Strategies-#endif- -- | Used to qualify XML. tag :: String tag	= "piece"@@ -234,18 +230,13 @@ type ByRankByLogicalColour element	= Colour.LogicalColour.ArrayByLogicalColour (Map.Map Attribute.Rank.Rank element)  -- | Constructor of a certain shape of container, but with arbitrary contents.-mkByRankByLogicalColour ::-#ifdef USE_PARALLEL-	Control.DeepSeq.NFData	element =>-#endif-	[Attribute.Rank.Rank] -> (Colour.LogicalColour.LogicalColour -> Attribute.Rank.Rank -> element) -> ByRankByLogicalColour element-mkByRankByLogicalColour ranks mkElement	= Colour.LogicalColour.listArrayByLogicalColour-#ifdef USE_PARALLEL-	. Control.Parallel.Strategies.withStrategy (Control.Parallel.Strategies.parList Control.Parallel.Strategies.rdeepseq)-#endif-	$ map (-		\logicalColour	-> Map.fromList $ map (id &&& mkElement logicalColour) ranks-	) Property.FixedMembership.members+mkByRankByLogicalColour+	:: [Attribute.Rank.Rank]+	-> (Colour.LogicalColour.LogicalColour -> Attribute.Rank.Rank -> element)+	-> ByRankByLogicalColour element+mkByRankByLogicalColour ranks mkElement	= Colour.LogicalColour.listArrayByLogicalColour $ map (+	\logicalColour	-> Map.fromList $ map (id &&& mkElement logicalColour) ranks+ ) Property.FixedMembership.members  {- | 	* The constant /vector/s over which the specified type of /piece/ can attack.
− src-lib/BishBosh/Component/PieceSquareByCoordinatesByRank.hs
@@ -1,181 +0,0 @@-{-# LANGUAGE CPP #-}-{--	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 the relative value of a specific /rank/ of piece, occupying a specific /coordinate/ on the board, at a specific stage in the game.--}--module BishBosh.Component.PieceSquareByCoordinatesByRank(--- * Types--- ** Type-synonyms---	PieceSquareValueByNPieces,---	EitherPieceSquareValueByNPiecesByCoordinates,--- ** Data-types-	PieceSquareByCoordinatesByRank(---		MkPieceSquareByCoordinatesByRank,---		deconstruct-	),--- * Constants-	nPiecesBounds,-	gnuPlotComment,--- * Functions-	findPieceSquareValue,-	interpolatePieceSquareValues,-	formatForGNUPlot,--- ** Constructor-	mkPieceSquareByCoordinatesByRank-) where--import			Control.Arrow((&&&), (|||))-import			Data.Array.IArray((!))-import qualified	BishBosh.Attribute.Rank			as Attribute.Rank-import qualified	BishBosh.Cartesian.Abscissa		as Cartesian.Abscissa-import qualified	BishBosh.Cartesian.Coordinates		as Cartesian.Coordinates-import qualified	BishBosh.Colour.LogicalColour		as Colour.LogicalColour-import qualified	BishBosh.Component.Piece		as Component.Piece-import qualified	BishBosh.Property.FixedMembership	as Property.FixedMembership-import qualified	BishBosh.Property.Reflectable		as Property.Reflectable-import qualified	BishBosh.Text.ShowList			as Text.ShowList-import qualified	BishBosh.Type.Count			as Type.Count-import qualified	BishBosh.Type.Mass			as Type.Mass-import qualified	Control.DeepSeq-import qualified	Data.Array.IArray-import qualified	Data.Foldable-import qualified	Data.List--#if defined(USE_UNBOXED_ARRAYS) && !(defined(USE_NEWTYPE_WRAPPERS) || defined(USE_PRECISION))-#define UNBOX-import qualified	Data.Array.Unboxed-#endif---- | The piece-square value may vary as the game progresses.-type PieceSquareValueByNPieces =-#ifdef UNBOX-	Data.Array.Unboxed.UArray-#else-	Data.Array.IArray.Array-#endif-		Type.Count.NPieces Type.Mass.PieceSquareValue---- | The bounds of the number of pieces on the board, at the end-game & opening-game respectively.-nPiecesBounds :: (Type.Count.NPieces, Type.Count.NPieces)-nPiecesBounds	= (-	3 {-minimum sufficient material-},-	fromIntegral Colour.LogicalColour.nDistinctLogicalColours * Component.Piece.nPiecesPerSide- )---- | Self-documentation.-type EitherPieceSquareValueByNPiecesByCoordinates	= Either (-#ifdef UNBOX-	Cartesian.Coordinates.UArrayByCoordinates-#else-	Cartesian.Coordinates.ArrayByCoordinates-#endif-		Type.Mass.PieceSquareValue	-- Uninterpolated.- ) (-	Cartesian.Coordinates.ArrayByCoordinates PieceSquareValueByNPieces	-- Interpolated.- )---- | The value for each type of /piece/ of occupying each coordinate, at each stage in the lifetime of the game.-newtype PieceSquareByCoordinatesByRank	= MkPieceSquareByCoordinatesByRank {-	deconstruct	:: Attribute.Rank.ArrayByRank EitherPieceSquareValueByNPiecesByCoordinates-} deriving (Eq, Show)--instance Control.DeepSeq.NFData PieceSquareByCoordinatesByRank where-	rnf-#ifdef UNBOX-		_								= ()-#else-		MkPieceSquareByCoordinatesByRank { deconstruct = byRank }	= Control.DeepSeq.rnf byRank-#endif---- | Constructor.-mkPieceSquareByCoordinatesByRank-	:: (Attribute.Rank.Rank -> EitherPieceSquareValueByNPiecesByCoordinates)	-- ^ Convert a /rank/ into either (a /pieceSquareValue/ or a /pieceSquareValue/ which linearly varies with the number of /piece/s remaining) by /coordinates/.-	-> PieceSquareByCoordinatesByRank-mkPieceSquareByCoordinatesByRank	= MkPieceSquareByCoordinatesByRank . Attribute.Rank.listArrayByRank . (`map` Property.FixedMembership.members)---- | Find the piece-square value, at a stage in the game's lifetime defined by the total number of pieces remaining, for the specified /rank/ & /coordinates/.-findPieceSquareValue-	:: PieceSquareByCoordinatesByRank-	-> Type.Count.NPieces			-- ^ The progress through the game.-	-> Colour.LogicalColour.LogicalColour	-- ^ The /piece/'s /logical colour/.-	-> Attribute.Rank.Rank			-- ^ The /piece/'s /rank/.-	-> Cartesian.Coordinates.Coordinates	-- ^ The /piece/'s location.-	-> Type.Mass.PieceSquareValue-findPieceSquareValue MkPieceSquareByCoordinatesByRank { deconstruct = byRank } nPieces logicalColour rank	= (-	(!) ||| (-		\byNPiecesByCoordinates	-> (! nPieces) . (byNPiecesByCoordinates !)-	) $ byRank ! rank- ) . if Colour.LogicalColour.isBlack logicalColour-	then Property.Reflectable.reflectOnX-	else id---- | Given the bounds over which two piece-square values vary as the game progresses from opening to end, return linearly interpolated values for all stages.-interpolatePieceSquareValues-	:: Type.Mass.PieceSquareValue	-- ^ Opening-game.-	-> Type.Mass.PieceSquareValue	-- ^ End-game.-	-> PieceSquareValueByNPieces-interpolatePieceSquareValues openingGame endGame	= Data.Array.IArray.listArray nPiecesBounds . map (-	fromRational . uncurry (+) . (-		(* toRational openingGame) &&& (* toRational endGame) . (1 -)-	) . (-		/ fromIntegral (-			uncurry subtract nPiecesBounds	-- N.B.: this can't reasonably be zero.-		) -- map into the closed unit-interval [0,1].-	) . fromIntegral . subtract (-		fst {-minimum-} nPiecesBounds-	)- ) $ uncurry enumFromTo nPiecesBounds---- | The character used in __GNUPlot__ to denote a comment.-gnuPlotComment :: Char-gnuPlotComment	= '#'---- | Format the data for input to __GNUPlot__.-formatForGNUPlot-	:: PieceSquareByCoordinatesByRank-	-> (Type.Mass.PieceSquareValue -> ShowS)			-- ^ Format a /pieceSquareValue/.-	-> ShowS							-- ^ The column-delimiter.-	-> (PieceSquareValueByNPieces -> Type.Mass.PieceSquareValue)	-- ^ Select one /PieceSquareValue/ from interpolated values.-	-> ShowS-formatForGNUPlot MkPieceSquareByCoordinatesByRank { deconstruct = byRank } pieceSquareValueFormatter columnDelimiter selector	= (-	showsRow (-		showChar gnuPlotComment . showChar 'x' : showChar 'y' : map shows Attribute.Rank.range	-- Header comment.-	) .- ) . foldr (-	\(coordinates, byRank') showS	-> let-		(x, y)	= Cartesian.Coordinates.getX &&& Cartesian.Coordinates.getY $ coordinates-	in showsRow (-		shows x : shows y : map pieceSquareValueFormatter byRank'-	) . (-		if x == Cartesian.Abscissa.xMax-			then terminateRow	-- Separate isolines.-			else id-	) . showS- ) id . zip (-	Property.FixedMembership.members	:: [Cartesian.Coordinates.Coordinates]- ) . Data.List.transpose . map (-	Data.Array.IArray.elems ||| map selector {-select one PieceSquareValue from interpolated values-} . Data.Foldable.toList {-ByCoordinates-}- ) $ Data.Foldable.toList {-ByRank-} byRank where-	terminateRow	= showChar '\n'-	showsRow	= Text.ShowList.showsDelimitedList columnDelimiter id terminateRow-
+ src-lib/BishBosh/Component/PieceSquareValueByCoordinates.hs view
@@ -0,0 +1,94 @@+{-# LANGUAGE CPP #-}+{-+	Copyright (C) 2021 Dr. Alistair Ward++	This file is part of BishBosh.++	BishBosh is free software: you can redistribute it and/or modify+	it under the terms of the GNU General Public License as published by+	the Free Software Foundation, either version 3 of the License, or+	(at your option) any later version.++	BishBosh is distributed in the hope that it will be useful,+	but WITHOUT ANY WARRANTY; without even the implied warranty of+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+	GNU General Public License for more details.++	You should have received a copy of the GNU General Public License+	along with BishBosh.  If not, see <http://www.gnu.org/licenses/>.+-}+{- |+ [@AUTHOR@]	Dr. Alistair Ward++ [@DESCRIPTION@]	Defines the values of a single unspecified piece, of occupying various coordinates.+-}++module BishBosh.Component.PieceSquareValueByCoordinates(+-- * Types+-- ** Type-synonyms+--	ByCoordinates,+-- ** Data-types+	PieceSquareValueByCoordinates(),+-- * Functions+-- ** Accessors+	dereference,+	getPieceSquareValue,+	toList,+-- ** Constructors+	fromList+) where++import			Data.Array.IArray((!))+import qualified	BishBosh.Cartesian.Coordinates	as Cartesian.Coordinates+import qualified	BishBosh.Colour.LogicalColour	as Colour.LogicalColour+import qualified	BishBosh.Property.Reflectable	as Property.Reflectable+import qualified	BishBosh.Type.Mass		as Type.Mass+import qualified	Control.DeepSeq+import qualified	Data.Array.IArray++type ByCoordinates	=+#ifdef UNBOX_TYPEMASS_ARRAYS+	Cartesian.Coordinates.UArrayByCoordinates+#else+	Cartesian.Coordinates.ArrayByCoordinates+#endif+		Type.Mass.PieceSquareValue++-- | The piece-square value varies with coordinates at which the unspecified piece is located.+newtype PieceSquareValueByCoordinates	= MkPieceSquareValueByCoordinates ByCoordinates deriving (Eq, Show)++instance Control.DeepSeq.NFData PieceSquareValueByCoordinates where+	rnf (MkPieceSquareValueByCoordinates pieceSquareValueByCoordinates)	=+#ifdef UNBOX_TYPEMASS_ARRAYS+		Control.DeepSeq.rwhnf+#else+		Control.DeepSeq.rnf+#endif+			pieceSquareValueByCoordinates++-- | Constructor from a list ordered by /coordinates/.+fromList :: [Type.Mass.PieceSquareValue] -> PieceSquareValueByCoordinates+fromList	= MkPieceSquareValueByCoordinates . Cartesian.Coordinates.listArrayByCoordinates++-- | Deconstruct, returning the ordered list from which it was constructed.+toList :: PieceSquareValueByCoordinates -> [Type.Mass.PieceSquareValue]+toList (MkPieceSquareValueByCoordinates pieceSquareValueByCoordinates)	= Data.Array.IArray.elems pieceSquareValueByCoordinates++-- | Extract the value for the specified /coordinates/ (from @White@'s perspective).+dereference :: PieceSquareValueByCoordinates -> Cartesian.Coordinates.Coordinates -> Type.Mass.PieceSquareValue+dereference (MkPieceSquareValueByCoordinates pieceSquareValueByCoordinates)	= (pieceSquareValueByCoordinates !)++{- |+	* Get the piece-square value, for the specified /coordinates/.++	* Utilises symmetry to infer values for @Black@, by reflecting the specified /coordinates/ into @White@'s domain.+-}+getPieceSquareValue+	:: PieceSquareValueByCoordinates+	-> Colour.LogicalColour.LogicalColour	-- ^ The /piece/'s /logical colour/.+	-> Cartesian.Coordinates.Coordinates	-- ^ The /piece/'s location.+	-> Type.Mass.PieceSquareValue+getPieceSquareValue (MkPieceSquareValueByCoordinates pieceSquareValueByCoordinates) logicalColour	= (pieceSquareValueByCoordinates !) . if Colour.LogicalColour.isBlack logicalColour+	then Property.Reflectable.reflectOnX+	else id+
+ src-lib/BishBosh/Component/PieceSquareValueByCoordinatesByRank.hs view
@@ -0,0 +1,114 @@+{-+	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 the relative value of a specific /rank/ of piece, occupying a specific square, at a each stage in the game's life-cycle.+-}++module BishBosh.Component.PieceSquareValueByCoordinatesByRank(+-- * Types+-- ** Type-synonyms+--	PieceSquareValueByCoordinatesByEitherNPieces,+-- ** Data-types+	PieceSquareValueByCoordinatesByRank(),+-- * Constants+	gnuPlotComment,+-- * Functions+--	unify,+	formatForGNUPlot,+-- ** Accessors+	getPieceSquareValueByCoordinates,+-- ** Constructor+	mkPieceSquareValueByCoordinatesByRank+) where++import			Control.Arrow((&&&), (|||))+import			Data.Array.IArray((!))+import qualified	BishBosh.Attribute.Rank					as Attribute.Rank+import qualified	BishBosh.Cartesian.Abscissa				as Cartesian.Abscissa+import qualified	BishBosh.Cartesian.Coordinates				as Cartesian.Coordinates+import qualified	BishBosh.Component.PieceSquareValueByCoordinates	as Component.PieceSquareValueByCoordinates+import qualified	BishBosh.Property.FixedMembership			as Property.FixedMembership+import qualified	BishBosh.Text.ShowList					as Text.ShowList+import qualified	BishBosh.Type.Count					as Type.Count+import qualified	BishBosh.Type.Mass					as Type.Mass+import qualified	Control.DeepSeq+import qualified	Data.Array.IArray+import qualified	Data.Foldable+import qualified	Data.List++-- | The piece-square value may vary with /coordinates/ & optionally also the number of pieces remaining.+type PieceSquareValueByCoordinatesByEitherNPieces	= Either Component.PieceSquareValueByCoordinates.PieceSquareValueByCoordinates (+	Data.Array.IArray.Array Type.Count.NPieces Component.PieceSquareValueByCoordinates.PieceSquareValueByCoordinates+ )++-- | The piece-square value for various /coordinates/, optionally the number of pieces remaining, & /rank/.+newtype PieceSquareValueByCoordinatesByRank	= MkPieceSquareValueByCoordinatesByRank (Attribute.Rank.ArrayByRank PieceSquareValueByCoordinatesByEitherNPieces)++instance Control.DeepSeq.NFData PieceSquareValueByCoordinatesByRank where+	rnf (MkPieceSquareValueByCoordinatesByRank pieceSquareValueByCoordinatesByEitherNPiecesByRank)	= Control.DeepSeq.rnf pieceSquareValueByCoordinatesByEitherNPiecesByRank	-- Forward.++-- | Constructor.+mkPieceSquareValueByCoordinatesByRank :: (Attribute.Rank.Rank -> PieceSquareValueByCoordinatesByEitherNPieces) -> PieceSquareValueByCoordinatesByRank+mkPieceSquareValueByCoordinatesByRank	= MkPieceSquareValueByCoordinatesByRank . Attribute.Rank.listArrayByRank . (`map` Property.FixedMembership.members)++-- | Unify the /Left/ & /Right/ sides of 'PieceSquareValueByCoordinatesByEitherNPieces'.+unify :: Type.Count.NPieces -> PieceSquareValueByCoordinatesByEitherNPieces -> Component.PieceSquareValueByCoordinates.PieceSquareValueByCoordinates+unify nPieces	= id ||| (! nPieces)++-- | Retrieve the appropriate /PieceSquareValueByCoordinates/ for the specified /rank/, @ the current stage of the game's life-cycle.+getPieceSquareValueByCoordinates+	:: PieceSquareValueByCoordinatesByRank+	-> Type.Count.NPieces	-- ^ An inverse proxy for the age of the game.+	-> Attribute.Rank.Rank	-- ^ The /piece/'s /rank/.+	-> Component.PieceSquareValueByCoordinates.PieceSquareValueByCoordinates+getPieceSquareValueByCoordinates (MkPieceSquareValueByCoordinatesByRank pieceSquareValueByCoordinatesByEitherNPiecesByRank) nPieces rank	= unify nPieces $ pieceSquareValueByCoordinatesByEitherNPiecesByRank ! rank++-- | The character used in __GNUPlot__ to denote a comment.+gnuPlotComment :: Char+gnuPlotComment	= '#'++-- | Format the data for input to __GNUPlot__.+formatForGNUPlot+	:: PieceSquareValueByCoordinatesByRank+	-> (Type.Mass.PieceSquareValue -> ShowS)	-- ^ Format a /pieceSquareValue/.+	-> ShowS					-- ^ The column-delimiter.+	-> Type.Count.NPieces				-- ^ Select from interpolated values.+	-> ShowS+formatForGNUPlot (MkPieceSquareValueByCoordinatesByRank pieceSquareValueByCoordinatesByEitherNPiecesByRank) pieceSquareValueFormatter columnDelimiter nPieces	= (+	showsRow (+		showChar gnuPlotComment . showChar 'x' : showChar 'y' : map shows Attribute.Rank.range	-- Header comment.+	) .+ ) . foldr (+	\(coordinates, byRank') showS	-> let+		(x, y)	= Cartesian.Coordinates.getX &&& Cartesian.Coordinates.getY $ coordinates+	in showsRow (+		shows x : shows y : map pieceSquareValueFormatter byRank'+	) . (+		if x == Cartesian.Abscissa.xMax+			then terminateRow	-- Separate isolines.+			else id+	) . showS+ ) id . zip Property.FixedMembership.members . Data.List.transpose . map (+	Component.PieceSquareValueByCoordinates.toList . unify nPieces+ ) $ Data.Foldable.toList {-ByRank-} pieceSquareValueByCoordinatesByEitherNPiecesByRank where+	terminateRow	= showChar '\n'+	showsRow	= Text.ShowList.showsDelimitedList columnDelimiter id terminateRow+
src-lib/BishBosh/Component/QualifiedMove.hs view
@@ -24,7 +24,7 @@  module BishBosh.Component.QualifiedMove( -- * Types--- * Type-synonyms+-- ** Type-synonyms 	QualifiedMoveSequence, -- ** Data-types 	QualifiedMove(
src-lib/BishBosh/ContextualNotation/PGN.hs view
@@ -464,15 +464,15 @@  -- | Parses a /game/ from PGN move-text. moveTextParser-#ifdef USE_POLYPARSE 	:: IsStrictlySequential 	-> ContextualNotation.StandardAlgebraic.ValidateMoves+#ifdef USE_POLYPARSE 	-> Text.Poly.TextParser Model.Game.Game moveTextParser isStrictlySequential validateMoves	= let 	elementSequenceParser :: Model.Game.Game -> Text.Poly.TextParser Model.Game.Game 	elementSequenceParser game	= let 		expectedMoveNumber :: Type.Count.NMoves-		expectedMoveNumber	= fromIntegral . succ . (`div` 2) . State.TurnsByLogicalColour.getNPlies $ Model.Game.getTurnsByLogicalColour game+		expectedMoveNumber	= State.TurnsByLogicalColour.deriveMoveNumber $ Model.Game.getTurnsByLogicalColour game 	 in do 		moveNumber	<- ( 			if Colour.LogicalColour.isBlack $ Model.Game.getNextLogicalColour game@@ -504,14 +504,12 @@  in do 	game	<- fmap (Data.Maybe.fromMaybe Data.Default.def {-game-}) . Control.Applicative.optional $ elementSequenceParser Data.Default.def {-game-} #else /* Parsec */-	:: IsStrictlySequential-	-> ContextualNotation.StandardAlgebraic.ValidateMoves 	-> Parsec.Parser Model.Game.Game moveTextParser isStrictlySequential validateMoves	= let 	elementSequenceParser :: Model.Game.Game -> Parsec.Parser Model.Game.Game 	elementSequenceParser game	= let 		expectedMoveNumber :: Type.Count.NMoves-		expectedMoveNumber	= fromIntegral . succ . (`div` 2) . State.TurnsByLogicalColour.getNPlies $ Model.Game.getTurnsByLogicalColour game+		expectedMoveNumber	= State.TurnsByLogicalColour.deriveMoveNumber $ Model.Game.getTurnsByLogicalColour game 	 in do 		moveNumber	<- ( 			if Colour.LogicalColour.isBlack $ Model.Game.getNextLogicalColour game@@ -540,7 +538,7 @@  in do 	game	<- Parsec.option Data.Default.def {-game-} . Parsec.try $ elementSequenceParser Data.Default.def {-game-} #endif-	Data.Maybe.maybe game (`Model.Game.updateTerminationReasonWith` game) `fmap` maybeResultParser+	Data.Maybe.maybe game (`Model.Game.updateTerminationReasonWith` game) <$> maybeResultParser  {- | 	* Parses /PGN/.
src-lib/BishBosh/ContextualNotation/PositionHashQualifiedMoveTree.hs view
@@ -82,7 +82,7 @@ import qualified	System.Random import qualified	ToolShed.System.Random -#ifdef USE_PARALLEL+#ifdef PARALLELISE import qualified	Control.Parallel.Strategies #endif @@ -100,7 +100,7 @@ 	getZobrist		:: Component.Zobrist.Zobrist positionHash,	-- ^ Used to hash each position in the tree. 	getTree			:: Tree positionHash, 	getMinimumPieces	:: ! Type.Count.NPieces,			-- ^ The minimum number of /piece/s remaining after the last /move/ in any game defined in the tree.-	getHasAnyVictories	:: Bool						-- ^ Whether a victory has been recorded for any game in the tree; which won't be the case if it was constructed from a PGN-database containing standard-openings.+	getHasAnyVictories	:: Bool						-- ^ Whether a victory has been recorded for any game in the tree; which won't be the case if it was constructed from a PGN-database containing standard openings. }  -- | Constructor: augment the specified /qualified-move forest/ with a /Zobrist-hash/ of the /position/ & include the default initial game at the apex.@@ -246,7 +246,7 @@ 	| otherwise			= [ 		Control.Arrow.second (concatMap snd {-[OnymousResult]-}) movePair |	-- Discard the opponent's matching move, but cite the names of archived games it reached. 			movePair@(_, _ : _)	<--#ifdef USE_PARALLEL+#ifdef PARALLELISE 				Control.Parallel.Strategies.withStrategy ( 					Control.Parallel.Strategies.parList $ Control.Parallel.Strategies.evalTuple2 Control.Parallel.Strategies.r0 {-pre-match move-} Control.Parallel.Strategies.rdeepseq {-matching moves-} 				) .
src-lib/BishBosh/ContextualNotation/StandardAlgebraic.hs view
@@ -501,7 +501,7 @@ 				else {-not a Pawn-} let 					mkNormalMoveType destination	= Attribute.MoveType.mkNormalMoveType (getMaybeRank destination) Nothing {-promotion-} -					resolveQualifiedMove destination candidates	= case candidates of+					resolveQualifiedMove destination	= \case 						[]			-> fail . showString "Failed to locate any " . shows piece . showString " able to move to " $ shows destination "." 						[source]		-> return {-to ParsecT-monad-} . Component.QualifiedMove.mkQualifiedMove (Component.Move.mkMove source destination) $ mkNormalMoveType destination 						sourceCandidates	-> Parsec.choice [@@ -514,7 +514,7 @@ 					Parsec.try $ do -- N.B. this scenario occurs when there are identical pieces on both the same row & the same column, as the intended attacker; i.e. after a promotion. 						source		<- Notation.PureCoordinate.coordinatesParser	<?> "Source" -						Parsec.optional captureParser		<?> "Optional capture"+						Parsec.optional captureParser	<?> "Optional capture"  						destination	<- Notation.PureCoordinate.coordinatesParser	<?> "Destination" @@ -530,13 +530,13 @@ 							) <$> Notation.PureCoordinate.ordinateParser 						 ) -- Build a filter from the source-qualifier. -						Parsec.optional captureParser		<?> "Optional capture"+						Parsec.optional captureParser	<?> "Optional capture"  						destination	<- Notation.PureCoordinate.coordinatesParser	<?> "Destination"  						resolveQualifiedMove destination . sourceFilter $ findAttacksBy destination, 					do	-- The most likely scenario, where the intended attacker is unambiguous.-						Parsec.optional captureParser		<?> "Optional capture"+						Parsec.optional captureParser	<?> "Optional capture"  						destination	<- Notation.PureCoordinate.coordinatesParser	<?> "Unqualified destination" 
src-lib/BishBosh/Data/RoseTree.hs view
@@ -27,7 +27,7 @@ -- ** Type-synonyms --	Transformation, 	IsMatch,--- * Function+-- * Functions 	countTerminalNodes, 	drawTree, 	drawForest,
src-lib/BishBosh/Evaluation/Fitness.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE LambdaCase #-} {- 	Copyright (C) 2018 Dr. Alistair Ward @@ -46,16 +47,19 @@ ) where  import			Control.Applicative((<|>))-import			Control.Arrow((&&&))+import			Control.Arrow((&&&), (***)) import			Data.Array.IArray((!)) import qualified	BishBosh.Attribute.MoveType				as Attribute.MoveType+import qualified	BishBosh.Attribute.Rank					as Attribute.Rank import qualified	BishBosh.Cartesian.Abscissa				as Cartesian.Abscissa import qualified	BishBosh.Cartesian.Coordinates				as Cartesian.Coordinates import qualified	BishBosh.Cartesian.Ordinate				as Cartesian.Ordinate import qualified	BishBosh.Colour.LogicalColour				as Colour.LogicalColour+import qualified	BishBosh.Component.CastlingMove				as Component.CastlingMove import qualified	BishBosh.Component.Move					as Component.Move import qualified	BishBosh.Component.Piece				as Component.Piece-import qualified	BishBosh.Component.PieceSquareByCoordinatesByRank	as Component.PieceSquareByCoordinatesByRank+import qualified	BishBosh.Component.PieceSquareValueByCoordinates	as Component.PieceSquareValueByCoordinates+import qualified	BishBosh.Component.PieceSquareValueByCoordinatesByRank	as Component.PieceSquareValueByCoordinatesByRank import qualified	BishBosh.Component.QualifiedMove			as Component.QualifiedMove import qualified	BishBosh.Component.Turn					as Component.Turn import qualified	BishBosh.Input.CriteriaWeights				as Input.CriteriaWeights@@ -77,48 +81,61 @@ import qualified	Data.Map.Strict						as Map import qualified	Data.Maybe --- | Measures the difference in piece-square value between players, from the perspective of the last player to move.+-- | Measures the difference in /piece-square value/ between players, from the perspective of the last player to move. measurePieceSquareValueDifference-	:: Component.PieceSquareByCoordinatesByRank.PieceSquareByCoordinatesByRank+	:: Component.PieceSquareValueByCoordinatesByRank.PieceSquareValueByCoordinatesByRank 	-> Model.Game.Game-	-> Type.Mass.Base-measurePieceSquareValueDifference pieceSquareByCoordinatesByRank game	= (+	-> Type.Mass.Base	-- ^ Unbounded difference.+measurePieceSquareValueDifference pieceSquareValueByCoordinatesByRank game	= Data.List.foldl1' ( 	if Colour.LogicalColour.isBlack $! Model.Game.getNextLogicalColour game-		then id-		else negate	-- Represent the piece-square value difference from Black's perspective.- ) $! whitesPieceSquareValue - blacksPieceSquareValue where-	[blacksPieceSquareValue, whitesPieceSquareValue]	= Data.Array.IArray.elems . State.Board.sumPieceSquareValueByLogicalColour pieceSquareByCoordinatesByRank $ Model.Game.getBoard game+		then subtract+		else (-)	-- Represent the piece-square value difference from Black's perspective; i.e. the last player to move.+ ) . State.Board.sumPieceSquareValueByLogicalColour pieceSquareValueByCoordinatesByRank $ Model.Game.getBoard game  {- |-	* Measures the difference in piece-square value between players, from the perspective of the last player to move.+	* Measures the difference in /piece-square value/ between players, from the perspective of the last player to move.  	* The previous value is provided, to enable calculation by difference. -	* N.B.: because of diminishing returns, the piece-square value for everything but simple moves is calculated from scratch.+	* CAVEAT: after a capture, the value is recounted from scratch, because there's one fewer pieces remaining & the piece-square value may depend on NPieces, so all pieces are potentially impacted. -} measurePieceSquareValueDifferenceIncrementally 	:: Type.Mass.Base	-- ^ The difference between players in the piece-square value, before the last move was applied & therefore also from the perspective of the previous player.-	-> Component.PieceSquareByCoordinatesByRank.PieceSquareByCoordinatesByRank+	-> Component.PieceSquareValueByCoordinatesByRank.PieceSquareValueByCoordinatesByRank 	-> Model.Game.Game-	-> Type.Mass.Base-measurePieceSquareValueDifferenceIncrementally previousPieceSquareValueDifference pieceSquareByCoordinatesByRank game-	| Attribute.MoveType.isSimple $! Component.QualifiedMove.getMoveType qualifiedMove	= let-		findPieceSquareValue :: Cartesian.Coordinates.Coordinates -> Type.Mass.Base-		findPieceSquareValue	= realToFrac . uncurry (-			Component.PieceSquareByCoordinatesByRank.findPieceSquareValue pieceSquareByCoordinatesByRank-		 ) (-			State.Board.getNPieces {- N.B.: no capture occurred-} . Model.Game.getBoard &&& Property.Opposable.getOpposite . Model.Game.getNextLogicalColour $ game	{-the last player to move-}-		 ) (-			Component.Turn.getRank turn	-- N.B.: no promotion occurred.-		 )-	in uncurry (-) (-		findPieceSquareValue . Component.Move.getDestination &&& findPieceSquareValue . Component.Move.getSource $ Component.QualifiedMove.getMove qualifiedMove-	) - previousPieceSquareValueDifference {-from the previous player's perspective-}-	| otherwise	= measurePieceSquareValueDifference pieceSquareByCoordinatesByRank game	-- N.B.: though non-simple (Castling, En-passant, promotion) can be calculated, the returns don't justify the effort.-	where-		Just turn	= Model.Game.maybeLastTurn game-		qualifiedMove	= Component.Turn.getQualifiedMove turn+	-> Type.Mass.Base	-- ^ Unbounded difference.+measurePieceSquareValueDifferenceIncrementally previousPieceSquareValueDifference pieceSquareValueByCoordinatesByRank game	= Data.Maybe.maybe (+	measurePieceSquareValueDifference pieceSquareValueByCoordinatesByRank game	-- Recalculate.+ ) (+	subtract previousPieceSquareValueDifference+ ) . Attribute.MoveType.apply (+	\isShort	-> Just . (+ quietMovePieceSquareDifference) . uncurry subtract . uncurry (***) (+		getPieceSquareValue &&& getPieceSquareValue $! getPieceSquareValueByCoordinates Attribute.Rank.Rook+	) . (+		Component.Move.getSource &&& Component.Move.getDestination+	) . Component.CastlingMove.getRooksMove . (+		if isShort then snd else fst+	) $ Component.CastlingMove.getLongAndShortMoves previousLogicalColour,+	Nothing,	-- En-passant.+	\case+		(Nothing, maybePromotionRank)	-> Just $! Data.Maybe.maybe quietMovePieceSquareDifference (+			uncurry subtract . uncurry (***) getMovePieceSquareValues . (,) (getPieceSquareValueByCoordinates rank) . getPieceSquareValueByCoordinates+		 ) maybePromotionRank+		_				-> Nothing	-- Capture.+ ) $! Component.QualifiedMove.getMoveType qualifiedMove where+	(previousLogicalColour, (qualifiedMove, rank))	= Property.Opposable.getOpposite . Model.Game.getNextLogicalColour &&& (Component.Turn.getQualifiedMove &&& Component.Turn.getRank) . Data.Maybe.fromJust . Model.Game.maybeLastTurn $ game	-- Deconstruct. +	getPieceSquareValueByCoordinates :: Attribute.Rank.Rank -> Component.PieceSquareValueByCoordinates.PieceSquareValueByCoordinates+	getPieceSquareValueByCoordinates	= Component.PieceSquareValueByCoordinatesByRank.getPieceSquareValueByCoordinates pieceSquareValueByCoordinatesByRank . State.Board.getNPieces $ Model.Game.getBoard game++	getPieceSquareValue :: Component.PieceSquareValueByCoordinates.PieceSquareValueByCoordinates -> Cartesian.Coordinates.Coordinates -> Type.Mass.Base+	getPieceSquareValue pieceSquareByCoordinates	= realToFrac . Component.PieceSquareValueByCoordinates.getPieceSquareValue pieceSquareByCoordinates previousLogicalColour++	getMovePieceSquareValues :: (Component.PieceSquareValueByCoordinates.PieceSquareValueByCoordinates -> Type.Mass.Base, Component.PieceSquareValueByCoordinates.PieceSquareValueByCoordinates -> Type.Mass.Base)+	getMovePieceSquareValues	= uncurry (***) (id &&& id $ flip getPieceSquareValue) . (Component.Move.getSource &&& Component.Move.getDestination) $ Component.QualifiedMove.getMove qualifiedMove++	quietMovePieceSquareDifference	= uncurry subtract . uncurry (&&&) getMovePieceSquareValues $! getPieceSquareValueByCoordinates rank+ -- | Measure the arithmetic difference between the total /rank-value/ of the /piece/s currently held by either side; <https://www.chessprogramming.org/Material>. measureValueOfMaterial 	:: Input.RankValues.RankValues@@ -293,9 +310,9 @@ 			else 0	-- A draw. 	) [] 	| otherwise	= do-		criteriaWeights				<- Control.Monad.Reader.asks Input.EvaluationOptions.getCriteriaWeights-		rankValuePair				<- Control.Monad.Reader.asks $ Input.EvaluationOptions.getRankValues &&& Input.EvaluationOptions.getMaximumTotalRankValue-		maybePieceSquareByCoordinatesByRank	<- Control.Monad.Reader.asks Input.EvaluationOptions.getMaybePieceSquareByCoordinatesByRank+		criteriaWeights					<- Control.Monad.Reader.asks Input.EvaluationOptions.getCriteriaWeights+		rankValuePair					<- Control.Monad.Reader.asks $ Input.EvaluationOptions.getRankValues &&& Input.EvaluationOptions.getMaximumTotalRankValue+		maybePieceSquareValueByCoordinatesByRank	<- Control.Monad.Reader.asks Input.EvaluationOptions.getMaybePieceSquareValueByCoordinatesByRank  		return {-to Reader-monad-} $! Input.CriteriaWeights.calculateWeightedMean criteriaWeights ( 			uncurry measureValueOfMaterial rankValuePair game@@ -304,7 +321,7 @@ 		 ) ( 			Data.Maybe.maybe 0 ( 				realToFrac . (/ fromIntegral Component.Piece.nPiecesPerSide)	-- Normalise.-			) $ maybePieceSquareValueDifference <|> fmap (`measurePieceSquareValueDifference` game) maybePieceSquareByCoordinatesByRank+			) $ maybePieceSquareValueDifference <|> fmap (`measurePieceSquareValueDifference` game) maybePieceSquareValueByCoordinatesByRank 		 ) ( 			measureValueOfCastlingPotential game 		 ) (
src-lib/BishBosh/Evaluation/PositionHashQuantifiedGameTree.hs view
@@ -177,7 +177,7 @@ 							positionHash'	= Model.Game.updateIncrementalPositionHash game positionHash game' zobrist 					in slave 				) (-					\pieceSquareByCoordinatesByRank -> let+					\pieceSquareValueByCoordinatesByRank -> let 						slave pieceSquareValueDifference positionHash game Data.Tree.Node { 							Data.Tree.rootLabel	= game', 							Data.Tree.subForest	= gameForest'@@ -187,11 +187,11 @@ 							) evaluationOptions, 							Data.Tree.subForest	= map (slave pieceSquareValueDifference' positionHash' game') gameForest'	-- Recurse. 						} where-							pieceSquareValueDifference'	= Evaluation.Fitness.measurePieceSquareValueDifferenceIncrementally pieceSquareValueDifference pieceSquareByCoordinatesByRank game'+							pieceSquareValueDifference'	= Evaluation.Fitness.measurePieceSquareValueDifferenceIncrementally pieceSquareValueDifference pieceSquareValueByCoordinatesByRank game' 							positionHash'			= Model.Game.updateIncrementalPositionHash game positionHash game' zobrist-					in slave $ Evaluation.Fitness.measurePieceSquareValueDifference pieceSquareByCoordinatesByRank seedGame+					in slave $ Evaluation.Fitness.measurePieceSquareValueDifference pieceSquareValueByCoordinatesByRank seedGame 				) (-					Input.EvaluationOptions.getMaybePieceSquareByCoordinatesByRank evaluationOptions+					Input.EvaluationOptions.getMaybePieceSquareValueByCoordinatesByRank evaluationOptions 				) apexPositionHash seedGame 			) $ Data.Tree.subForest bareGameTree 		}
src-lib/BishBosh/Input/EvaluationOptions.hs view
@@ -42,29 +42,35 @@ 		getCriteriaWeights, 		getIncrementalEvaluation, --		getMaybePieceSquareTablePair,-		getMaybePieceSquareByCoordinatesByRank+		getMaybePieceSquareValueByCoordinatesByRank 	), -- * Constants 	tag, --	incrementalEvaluationTag, --	pieceSquareTablesTag, --	pieceSquareTableEndGameTag,+	nPiecesBounds, -- * Functions+--	interpolatePieceSquareValues, --	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			Control.Arrow((&&&), (***))+import qualified	BishBosh.Colour.LogicalColour				as Colour.LogicalColour+import qualified	BishBosh.Component.Piece				as Component.Piece+import qualified	BishBosh.Component.PieceSquareValueByCoordinates	as Component.PieceSquareValueByCoordinates+import qualified	BishBosh.Component.PieceSquareValueByCoordinatesByRank	as Component.PieceSquareValueByCoordinatesByRank 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.FixedMembership			as Property.FixedMembership import qualified	BishBosh.Property.ShowFloat				as Property.ShowFloat import qualified	BishBosh.Text.ShowList					as Text.ShowList+import qualified	BishBosh.Type.Count					as Type.Count import qualified	BishBosh.Type.Mass					as Type.Mass import qualified	Control.DeepSeq import qualified	Control.Exception@@ -99,32 +105,32 @@  -- | Defines the options related to the automatic selection of /move/s. data EvaluationOptions	= MkEvaluationOptions {-	getRankValues				:: Input.RankValues.RankValues,								-- ^ The static value associated with each /piece/'s /rank/.-	getMaximumTotalRankValue		:: Type.Mass.RankValue,									-- ^ Used to normalise the total value of pieces. Derived from 'getRankValues'.-	getCriteriaWeights			:: Input.CriteriaWeights.CriteriaWeights,						-- ^ The weights applied to each of the heterogeneous criterion-values used to select a /move/.-	getIncrementalEvaluation		:: IncrementalEvaluation,								-- ^ Whether to generate position-hashes & evaluate the piece-square value, from the previous value or from scratch.-	getMaybePieceSquareTablePair		:: Maybe PieceSquareTablePair,								-- ^ A optional pair of piece-square tables representing the opening & end-games respectively.-	getMaybePieceSquareByCoordinatesByRank	:: Maybe Component.PieceSquareByCoordinatesByRank.PieceSquareByCoordinatesByRank	-- ^ The optional value for each rank of /piece/, when occupying each coordinate, at each phase of the game.-} deriving (Eq, Show)+	getRankValues					:: Input.RankValues.RankValues,									-- ^ The static value associated with each /piece/'s /rank/.+	getMaximumTotalRankValue			:: Type.Mass.RankValue,										-- ^ Used to normalise the total value of pieces. Derived from 'getRankValues'.+	getCriteriaWeights				:: Input.CriteriaWeights.CriteriaWeights,							-- ^ The weights applied to each of the heterogeneous criterion-values used to select a /move/.+	getIncrementalEvaluation			:: IncrementalEvaluation,									-- ^ Whether to generate position-hashes & evaluate the piece-square value, from the previous value or from scratch.+	getMaybePieceSquareTablePair			:: Maybe PieceSquareTablePair,									-- ^ A optional pair of piece-square tables representing the opening & end-games respectively.+	getMaybePieceSquareValueByCoordinatesByRank	:: Maybe Component.PieceSquareValueByCoordinatesByRank.PieceSquareValueByCoordinatesByRank	-- ^ The optional value for each rank of /piece/, when occupying each coordinate, at each phase of the game.+}  instance Control.DeepSeq.NFData EvaluationOptions where 	rnf MkEvaluationOptions {---		getRankValues				= rankValues,-		getMaximumTotalRankValue		= maximumTotalValue,-		getCriteriaWeights			= criteriaWeights,-		getIncrementalEvaluation		= incrementalEvaluation,---		getMaybePieceSquareTablePair		= maybePieceSquareTablePair,-		getMaybePieceSquareByCoordinatesByRank	= maybePieceSquareByCoordinatesByRank-	} = Control.DeepSeq.rnf (maximumTotalValue, criteriaWeights, incrementalEvaluation, maybePieceSquareByCoordinatesByRank)+--		getRankValues					= rankValues,+		getMaximumTotalRankValue			= maximumTotalValue,+		getCriteriaWeights				= criteriaWeights,+		getIncrementalEvaluation			= incrementalEvaluation,+--		getMaybePieceSquareTablePair			= maybePieceSquareTablePair,+		getMaybePieceSquareValueByCoordinatesByRank	= maybePieceSquareValueByCoordinatesByRank+	} = Control.DeepSeq.rnf (maximumTotalValue, criteriaWeights, incrementalEvaluation, maybePieceSquareValueByCoordinatesByRank)  instance Property.ShowFloat.ShowFloat EvaluationOptions where 	showsFloat fromDouble MkEvaluationOptions {-		getRankValues				= rankValues,---		getMaximumTotalRankValue		= maximumTotalValue,-		getCriteriaWeights			= criteriaWeights,-		getIncrementalEvaluation		= incrementalEvaluation,-		getMaybePieceSquareTablePair		= maybePieceSquareTablePair---		getMaybePieceSquareByCoordinatesByRank	= maybePieceSquareByCoordinatesByRank+		getRankValues					= rankValues,+--		getMaximumTotalRankValue			= maximumTotalValue,+		getCriteriaWeights				= criteriaWeights,+		getIncrementalEvaluation			= incrementalEvaluation,+		getMaybePieceSquareTablePair			= maybePieceSquareTablePair+--		getMaybePieceSquareValueByCoordinatesByRank	= maybePieceSquareValueByCoordinatesByRank 	} = Text.ShowList.showsAssociationList' $ [ 		( 			Input.RankValues.tag,		Property.ShowFloat.showsFloat fromDouble rankValues@@ -147,25 +153,42 @@  instance Data.Default.Default EvaluationOptions where 	def = MkEvaluationOptions {-		getRankValues				= rankValues,-		getMaximumTotalRankValue		= Input.RankValues.calculateMaximumTotalValue rankValues,-		getCriteriaWeights			= Data.Default.def,-		getIncrementalEvaluation		= True,-		getMaybePieceSquareTablePair		= Nothing,-		getMaybePieceSquareByCoordinatesByRank	= Nothing+		getRankValues					= rankValues,+		getMaximumTotalRankValue			= Input.RankValues.calculateMaximumTotalValue rankValues,+		getCriteriaWeights				= Data.Default.def,+		getIncrementalEvaluation			= True,+		getMaybePieceSquareTablePair			= Nothing,+		getMaybePieceSquareValueByCoordinatesByRank	= Nothing 	} where 		rankValues	= Data.Default.def +instance Eq EvaluationOptions where+	MkEvaluationOptions {+		getRankValues					= rankValues,+--		getMaximumTotalRankValue			= maximumTotalValue,+		getCriteriaWeights				= criteriaWeights,+		getIncrementalEvaluation			= incrementalEvaluation,+		getMaybePieceSquareTablePair			= maybePieceSquareTablePair+--		getMaybePieceSquareValueByCoordinatesByRank	= maybePieceSquareValueByCoordinatesByRank+	} == MkEvaluationOptions {+		getRankValues					= rankValues',+--		getMaximumTotalRankValue			= maximumTotalValue',+		getCriteriaWeights				= criteriaWeights',+		getIncrementalEvaluation			= incrementalEvaluation',+		getMaybePieceSquareTablePair			= maybePieceSquareTablePair'+--		getMaybePieceSquareValueByCoordinatesByRank	= maybePieceSquareValueByCoordinatesByRank'+	} = rankValues == rankValues' && criteriaWeights == criteriaWeights' && incrementalEvaluation == incrementalEvaluation' && maybePieceSquareTablePair == maybePieceSquareTablePair'+ instance HXT.XmlPickler EvaluationOptions where 	xpickle	= HXT.xpDefault def . HXT.xpElem tag . HXT.xpWrap ( 		\(a, b, c, d) -> mkEvaluationOptions a b c d,	-- Construct. 		\MkEvaluationOptions {-			getRankValues				= rankValues,---			getMaximumTotalRankValue		= maximumTotalRankValue,-			getCriteriaWeights			= criteriaWeights,-			getIncrementalEvaluation		= incrementalEvaluation,-			getMaybePieceSquareTablePair		= maybePieceSquareTablePair---			getMaybePieceSquareByCoordinatesByRank	= maybePieceSquareByCoordinatesByRank+			getRankValues					= rankValues,+--			getMaximumTotalRankValue			= maximumTotalRankValue,+			getCriteriaWeights				= criteriaWeights,+			getIncrementalEvaluation			= incrementalEvaluation,+			getMaybePieceSquareTablePair			= maybePieceSquareTablePair+--			getMaybePieceSquareValueByCoordinatesByRank	= maybePieceSquareValueByCoordinatesByRank 		} -> ( 			rankValues, 			criteriaWeights,@@ -177,18 +200,56 @@ 	 ) . HXT.xpOption . HXT.xpElem pieceSquareTablesTag $ HXT.xpElem Input.PieceSquareTable.tag HXT.xpickle `HXT.xpPair` HXT.xpElem pieceSquareTableEndGameTag HXT.xpickle where 		def	= Data.Default.def --- | Convert a /PieceSquareTablePair/ to a single linearly interpolated array.-fromPieceSquareTablePair :: PieceSquareTablePair -> Component.PieceSquareByCoordinatesByRank.PieceSquareByCoordinatesByRank-fromPieceSquareTablePair pieceSquareTablePair	= Component.PieceSquareByCoordinatesByRank.mkPieceSquareByCoordinatesByRank $ \rank -> (+instance Show EvaluationOptions where+	showsPrec precedence MkEvaluationOptions {+		getRankValues					= rankValues,+--		getMaximumTotalRankValue			= maximumTotalRankValue,+		getCriteriaWeights				= criteriaWeights,+		getIncrementalEvaluation			= incrementalEvaluation,+		getMaybePieceSquareTablePair			= maybePieceSquareTablePair+--		getMaybePieceSquareValueByCoordinatesByRank	= maybePieceSquareValueByCoordinatesByRank+	} = showsPrec precedence (rankValues, criteriaWeights, incrementalEvaluation, maybePieceSquareTablePair)++-- | The constant bounds of the number of pieces on the board, at the end-game & opening-game respectively.+nPiecesBounds :: (Type.Count.NPieces, Type.Count.NPieces)+nPiecesBounds	= (+	3 {-minimum sufficient material-},+	fromIntegral Colour.LogicalColour.nDistinctLogicalColours * Component.Piece.nPiecesPerSide+ )++-- | Given the bounds over which a piece-square value varies, as the game progresses from opening to end, return the linearly interpolated value for the specified stage.+interpolatePieceSquareValues+	:: Type.Count.NPieces						-- ^ The value to interpolate.+	-> (Type.Mass.PieceSquareValue, Type.Mass.PieceSquareValue)	-- ^ (Opening-game, End-game) values.+	-> Type.Mass.PieceSquareValue+interpolatePieceSquareValues nPieces (openingGame, endGame)	= realToFrac . uncurry (+) . (+	(* toRational openingGame) &&& (* toRational endGame) . (1 -)	-- N.B.: arithmetic must be conducted in an unbounded type, instead of 'PieceSquareValue'.+ ) $ fromIntegral (+	nPieces - fst {-minimum-} nPiecesBounds+ ) / fromIntegral (+	uncurry subtract nPiecesBounds	-- N.B.: this can't reasonably be zero.+ )++-- | Derive 'PieceSquareValueByCoordinatesByRank'.+fromPieceSquareTablePair :: PieceSquareTablePair -> Component.PieceSquareValueByCoordinatesByRank.PieceSquareValueByCoordinatesByRank+fromPieceSquareTablePair pieceSquareTablePair	= Component.PieceSquareValueByCoordinatesByRank.mkPieceSquareValueByCoordinatesByRank $ \rank -> ( 	\(openingGamePieceSquareValueByCoordinates, maybeEndGamePieceSquareValueByCoordinates) -> Data.Maybe.maybe (-		Left openingGamePieceSquareValueByCoordinates+		Left openingGamePieceSquareValueByCoordinates	-- There's only one value for this rank, so no interpolation is required. 	) (-		Right . Cartesian.Coordinates.listArrayByCoordinates . zipWith Component.PieceSquareByCoordinatesByRank.interpolatePieceSquareValues (-			Data.Array.IArray.elems openingGamePieceSquareValueByCoordinates-		) . Data.Array.IArray.elems+		\endGamePieceSquareValueByCoordinates -> Right $ Data.Array.IArray.listArray nPiecesBounds (+			map (+				\nPieces -> Component.PieceSquareValueByCoordinates.fromList $ map (+					interpolatePieceSquareValues nPieces . uncurry (&&&) (+						($ openingGamePieceSquareValueByCoordinates) &&& ($ endGamePieceSquareValueByCoordinates) $ Component.PieceSquareValueByCoordinates.dereference+					)+				) Property.FixedMembership.members	-- Coordinates.+			) $ uncurry enumFromTo nPiecesBounds+		 ) 	) maybeEndGamePieceSquareValueByCoordinates  ) $ (-	 Data.Maybe.fromJust {-values for the openingGame must be specified-} . Input.PieceSquareTable.dereference rank *** Input.PieceSquareTable.dereference rank+	uncurry (***) . (+		(.) Data.Maybe.fromJust {-all ranks must be defined for the openingGame-} &&& id+	) $ Input.PieceSquareTable.findPieceSquareValueByCoordinates rank  ) pieceSquareTablePair  -- | Smart constructor.@@ -208,12 +269,12 @@ 	= Control.Exception.throw . Data.Exception.mkIncompatibleData . showString "BishBosh.Input.EvaluationOptions.mkEvaluationOptions:\tweight of " . shows Input.CriteriaWeights.weightOfPieceSquareValueTag . showString " is defined but " $ shows Input.PieceSquareTable.tag " isn't." 	| maximumTotalRankValue == 0 && Input.CriteriaWeights.getWeightOfMaterial criteriaWeights /= 0	= Control.Exception.throw . Data.Exception.mkIncompatibleData . showString "BishBosh.Input.EvaluationOptions.mkEvaluationOptions:\tweight of " . shows Input.CriteriaWeights.weightOfMaterialTag . showString " is non-zero, but the maximum total rank-value is " $ shows rankValues "." 	| otherwise		= MkEvaluationOptions {-		getRankValues				= rankValues,-		getMaximumTotalRankValue		= maximumTotalRankValue,-		getCriteriaWeights			= criteriaWeights,-		getIncrementalEvaluation		= incrementalEvaluation,-		getMaybePieceSquareTablePair		= maybePieceSquareTablePair,-		getMaybePieceSquareByCoordinatesByRank	= fromPieceSquareTablePair <$> maybePieceSquareTablePair	-- Infer.+		getRankValues					= rankValues,+		getMaximumTotalRankValue			= maximumTotalRankValue,+		getCriteriaWeights				= criteriaWeights,+		getIncrementalEvaluation			= incrementalEvaluation,+		getMaybePieceSquareTablePair			= maybePieceSquareTablePair,+		getMaybePieceSquareValueByCoordinatesByRank	= fromPieceSquareTablePair <$> maybePieceSquareTablePair	-- Infer. 	} where 		maximumTotalRankValue	= Input.RankValues.calculateMaximumTotalValue rankValues 
src-lib/BishBosh/Input/PGNOptions.hs view
@@ -134,13 +134,12 @@ 		getIdentificationTags	= identificationTags, 		getMinimumPlies		= minimumPlies, 		getMaybeMaximumGames	= maybeMaximumGames-	} = Text.ShowList.showsAssociationList' [+	} = Text.ShowList.showsAssociationList' $ Data.Maybe.maybe id (+		(:) . (,) decompressorTag . shows+	 ) maybeDecompressor [ 		( 			databaseFilePathTag, 			shows databaseFilePath-		), (-			decompressorTag,-			shows maybeDecompressor 		), ( 			isStrictlySequentialTag, 			shows isStrictlySequential
src-lib/BishBosh/Input/PieceSquareTable.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {- 	Copyright (C) 2018 Dr. Alistair Ward @@ -41,7 +40,6 @@ -- ** Type-synonyms --	Normalise, --	ReflectOnY,---	PieceSquareValueByCoordinates, 	IOFormat, 	Assocs, -- ** Data-types@@ -58,8 +56,9 @@ 	normaliseToUnitInterval, 	mirror, 	unmirror,+-- ** Accessors 	findUndefinedRanks,-	dereference,+	findPieceSquareValueByCoordinates, -- ** Constructors 	mkPieceSquareTable, -- ** Predicates@@ -68,25 +67,25 @@  import			BishBosh.Data.Bool()	-- HXT.XmlPickler. import			Control.Arrow((&&&), (***))-import qualified	BishBosh.Attribute.Rank			as Attribute.Rank-import qualified	BishBosh.Cartesian.Abscissa		as Cartesian.Abscissa-import qualified	BishBosh.Cartesian.Coordinates		as Cartesian.Coordinates-import qualified	BishBosh.Data.Exception			as Data.Exception-import qualified	BishBosh.Data.Foldable			as Data.Foldable-import qualified	BishBosh.Data.Num			as Data.Num-import qualified	BishBosh.Property.Empty			as Property.Empty-import qualified	BishBosh.Property.FixedMembership	as Property.FixedMembership-import qualified	BishBosh.Property.ShowFloat		as Property.ShowFloat-import qualified	BishBosh.Text.Case			as Text.Case-import qualified	BishBosh.Text.ShowList			as Text.ShowList-import qualified	BishBosh.Type.Mass			as Type.Mass+import qualified	BishBosh.Attribute.Rank					as Attribute.Rank+import qualified	BishBosh.Cartesian.Abscissa				as Cartesian.Abscissa+import qualified	BishBosh.Cartesian.Coordinates				as Cartesian.Coordinates+import qualified	BishBosh.Component.PieceSquareValueByCoordinates	as Component.PieceSquareValueByCoordinates+import qualified	BishBosh.Data.Exception					as Data.Exception+import qualified	BishBosh.Data.Foldable					as Data.Foldable+import qualified	BishBosh.Data.Num					as Data.Num+import qualified	BishBosh.Property.Empty					as Property.Empty+import qualified	BishBosh.Property.FixedMembership			as Property.FixedMembership+import qualified	BishBosh.Property.ShowFloat				as Property.ShowFloat+import qualified	BishBosh.Text.Case					as Text.Case+import qualified	BishBosh.Text.ShowList					as Text.ShowList+import qualified	BishBosh.Type.Mass					as Type.Mass import qualified	Control.Arrow import qualified	Control.Exception-import qualified	Data.Array.IArray import qualified	Data.Default-import qualified	Data.Map.Strict				as Map+import qualified	Data.Map.Strict						as Map import qualified	Data.Set-import qualified	Text.XML.HXT.Arrow.Pickle		as HXT+import qualified	Text.XML.HXT.Arrow.Pickle				as HXT  -- | Used to qualify XML. tag :: String@@ -106,20 +105,11 @@ -- | Type-synonym. type ReflectOnY	= Bool --- | Self-documentation.-type PieceSquareValueByCoordinates	=-#if defined(USE_UNBOXED_ARRAYS) && !(defined(USE_NEWTYPE_WRAPPERS) || defined(USE_PRECISION))-	Cartesian.Coordinates.UArrayByCoordinates-#else-	Cartesian.Coordinates.ArrayByCoordinates-#endif-		Type.Mass.PieceSquareValue- -- | Defines the value for each type of piece, of occupying each square. data PieceSquareTable	= MkPieceSquareTable {-	getNormalise				:: Normalise,							-- ^ Whether to map the specified values into the closed unit-interval.	CAVEAT: incompatible with RelaxNG, the specification for which already constrains values to the unit-interval.-	getReflectOnY				:: ReflectOnY,							-- ^ Whether values for the RHS of the board should be inferred by reflection about the y-axis.-	getPieceSquareValueByCoordinatesByRank	:: Map.Map Attribute.Rank.Rank PieceSquareValueByCoordinates	-- ^ N.B.: on the assumption that the values for Black pieces are the reflection of those for White, merely the /rank/ of each /piece/ need be defined.+	getNormalise				:: Normalise,												-- ^ Whether to map the specified values into the closed unit-interval.	CAVEAT: incompatible with RelaxNG, the specification for which already constrains values to the unit-interval.+	getReflectOnY				:: ReflectOnY,												-- ^ Whether values for the RHS of the board should be inferred by reflection about the y-axis.+	getPieceSquareValueByCoordinatesByRank	:: Map.Map Attribute.Rank.Rank Component.PieceSquareValueByCoordinates.PieceSquareValueByCoordinates	-- ^ N.B.: on the assumption that the values for Black pieces are the reflection of those for White, merely the /rank/ of each /piece/ need be defined. } deriving (Eq, Show)  instance Property.ShowFloat.ShowFloat PieceSquareTable where@@ -140,7 +130,7 @@ 			if reflectOnY 				then unmirror 				else id-		) . Data.Array.IArray.elems+		) . Component.PieceSquareValueByCoordinates.toList 	 ) ( 		Map.toList pieceSquareValueByCoordinatesByRank 	 )@@ -170,7 +160,7 @@ 					if reflectOnY 						then unmirror 						else id-				) . Data.Array.IArray.elems+				) . Component.PieceSquareValueByCoordinates.toList 			) pieceSquareValueByCoordinatesByRank 		) -- Deconstruct to tuple. 	 ) . HXT.xpTriple (@@ -241,7 +231,7 @@ 		getNormalise				= normalise, 		getReflectOnY				= reflectOnY, 		getPieceSquareValueByCoordinatesByRank	= Map.fromList . map (-			Control.Arrow.second Cartesian.Coordinates.listArrayByCoordinates+			Control.Arrow.second Component.PieceSquareValueByCoordinates.fromList 		) . ( 			if reflectOnY 				then map $ Control.Arrow.second mirror@@ -266,6 +256,6 @@ findUndefinedRanks MkPieceSquareTable { getPieceSquareValueByCoordinatesByRank = pieceSquareValueByCoordinatesByRank }	= Data.Set.fromAscList Property.FixedMembership.members `Data.Set.difference` Map.keysSet pieceSquareValueByCoordinatesByRank  -- | Lookup the values for all /coordinates/, corresponding to the specified /rank/.-dereference :: Attribute.Rank.Rank -> PieceSquareTable -> Maybe PieceSquareValueByCoordinates-dereference rank MkPieceSquareTable { getPieceSquareValueByCoordinatesByRank = pieceSquareValueByCoordinatesByRank }	= Map.lookup rank pieceSquareValueByCoordinatesByRank+findPieceSquareValueByCoordinates :: Attribute.Rank.Rank -> PieceSquareTable -> Maybe Component.PieceSquareValueByCoordinates.PieceSquareValueByCoordinates+findPieceSquareValueByCoordinates rank MkPieceSquareTable { getPieceSquareValueByCoordinatesByRank = pieceSquareValueByCoordinatesByRank }	= Map.lookup rank pieceSquareValueByCoordinatesByRank 
src-lib/BishBosh/Input/RankValues.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {- 	Copyright (C) 2018 Dr. Alistair Ward @@ -51,6 +52,7 @@ 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.Arrow import qualified	Control.DeepSeq import qualified	Control.Exception import qualified	Data.Array.IArray@@ -70,9 +72,21 @@ 	* CAVEAT: a @King@ can never be taken, but assigning the value /infinity/ creates problems, so typically it has the value @0@. -} newtype RankValues	= MkRankValues {-	deconstruct	:: Attribute.Rank.ArrayByRank Metric.RankValue.RankValue-} deriving (Eq, Read, Show)+	deconstruct	::+#ifdef UNBOX_TYPEMASS_ARRAYS+		Attribute.Rank.UArrayByRank+#else+		Attribute.Rank.ArrayByRank+#endif+			Metric.RankValue.RankValue+} deriving Eq +instance Read RankValues where+	readsPrec precedence	= map (Control.Arrow.first fromAssocs) . readsPrec precedence++instance Show RankValues where+	showsPrec precedence MkRankValues { deconstruct = byRank }	= showsPrec precedence $ Data.Array.IArray.assocs byRank+ instance Property.ShowFloat.ShowFloat RankValues where 	showsFloat fromDouble	= Text.ShowList.showsAssociationList' . map (show *** Property.ShowFloat.showsFloat fromDouble) . Data.Array.IArray.assocs . deconstruct @@ -85,17 +99,27 @@ 		3, 		3, 		9,-		0	-- N.B.: move-selection is independent of the King's value (since it can't be taken), so it can be defined arbitrarily.+		0	-- N.B.: the King's value is immaterial (since it can't be taken), so it can be defined arbitrarily. 	 ]  instance Control.DeepSeq.NFData RankValues where-	rnf (MkRankValues byRank)	= Control.DeepSeq.rnf byRank+	rnf (MkRankValues byRank)	=+#ifdef UNBOX_TYPEMASS_ARRAYS+		Control.DeepSeq.rwhnf+#else+		Control.DeepSeq.rnf+#endif+			byRank  instance HXT.XmlPickler RankValues where 	xpickle	= HXT.xpDefault Data.Default.def . HXT.xpWrap ( 		fromAssocs,				-- Construct from an association-list. 		Data.Array.IArray.assocs . deconstruct	-- Deconstruct to an association-list.-	 ) . HXT.xpList1 . HXT.xpElem tag $ HXT.xpickle {-Rank-} `HXT.xpPair` HXT.xpickle {-RankValue-}+	 ) . HXT.xpList1 . HXT.xpElem tag $ HXT.xpickle {-Rank-} `HXT.xpPair`+#ifndef USE_NEWTYPE_WRAPPERS+		HXT.xpAttr Metric.RankValue.tag+#endif+		HXT.xpickle  -- | Smart constructor. fromAssocs :: [(Attribute.Rank.Rank, Metric.RankValue.RankValue)] -> RankValues
src-lib/BishBosh/Input/StandardOpeningOptions.hs view
@@ -19,7 +19,7 @@ {- |  [@AUTHOR@]	Dr. Alistair Ward - [@DESCRIPTION@]	Defines configurable options related to the process of searching standard-openings.+ [@DESCRIPTION@]	Defines configurable options related to the process of searching standard openings. -}  module BishBosh.Input.StandardOpeningOptions(@@ -30,7 +30,8 @@ --		getTryToMatchMoves, --		getTryToMatchViaJoiningMove, --		getTryToMatchColourFlippedPosition,-		getPreferVictories+		getPreferVictories,+		getMaybeMaximumPliesSinceMatch 	), -- * Constants 	tag,@@ -38,6 +39,7 @@ --	tryToMatchViaJoiningMoveTag, --	tryToMatchColourFlippedPositionTag, --	preferVictoriesTag,+--	maximumPliesSinceMatchTag, -- * Functions -- ** Constructor 	mkStandardOpeningOptions,@@ -47,8 +49,10 @@  import			BishBosh.Data.Bool()	-- For 'HXT.xpickle'. import qualified	BishBosh.Text.ShowList						as Text.ShowList+import qualified	BishBosh.Type.Count						as Type.Count import qualified	Control.DeepSeq import qualified	Data.Default+import qualified	Data.Maybe import qualified	BishBosh.ContextualNotation.PositionHashQualifiedMoveTree	as ContextualNotation.PositionHashQualifiedMoveTree import qualified	Text.XML.HXT.Arrow.Pickle					as HXT @@ -72,30 +76,42 @@ preferVictoriesTag :: String preferVictoriesTag			= "preferVictories" +-- | Used to qualify XML.+maximumPliesSinceMatchTag :: String+maximumPliesSinceMatchTag		= "maximumPliesSinceMatch"+ -- | Defines options related to searching for a move. data StandardOpeningOptions	= MkStandardOpeningOptions {+	getMaybeMaximumPliesSinceMatch		:: Maybe Type.Count.NPlies,								-- ^ The optional maximum number of plies, after the last match with a prerecorded game, before abandoning further attempts. If unspecified then there's no limit.+	getPreferVictories			:: ContextualNotation.PositionHashQualifiedMoveTree.PreferVictories,			-- ^ Whether from all matching positions extracted from PGN-Databases, to prefer moves which result in a greater probability of victory, for the player who has the next move. 	getTryToMatchMoves			:: ContextualNotation.PositionHashQualifiedMoveTree.TryToMatchMoves,			-- ^ Whether to attempt to exactly match moves with a standard opening; transpositions won't be matched. 	getTryToMatchViaJoiningMove		:: ContextualNotation.PositionHashQualifiedMoveTree.TryToMatchViaJoiningMove,		-- ^ Whether to attempt to join the current position to a standard opening that's only one ply away.-	getTryToMatchColourFlippedPosition	:: ContextualNotation.PositionHashQualifiedMoveTree.TryToMatchColourFlippedPosition,	-- ^ Whether to attempt to match a colour-flipped version of the current position with a standard opening.-	getPreferVictories			:: ContextualNotation.PositionHashQualifiedMoveTree.PreferVictories			-- ^ Whether from all matching positions extracted from PGN-Databases, to prefer moves which result in a greater probability of victory, for the player who has the next move.+	getTryToMatchColourFlippedPosition	:: ContextualNotation.PositionHashQualifiedMoveTree.TryToMatchColourFlippedPosition	-- ^ Whether to attempt to match a colour-flipped version of the current position with a standard opening. } deriving Eq  instance Control.DeepSeq.NFData StandardOpeningOptions where 	rnf MkStandardOpeningOptions {+		getMaybeMaximumPliesSinceMatch		= maybeMaximumPliesSinceMatch,+		getPreferVictories			= preferVictories, 		getTryToMatchMoves			= tryToMatchMoves, 		getTryToMatchViaJoiningMove		= tryToMatchViaJoiningMove,-		getTryToMatchColourFlippedPosition	= tryToMatchColourFlippedPosition,-		getPreferVictories			= preferVictories-	} = Control.DeepSeq.rnf (tryToMatchMoves, tryToMatchViaJoiningMove, tryToMatchColourFlippedPosition, preferVictories)+		getTryToMatchColourFlippedPosition	= tryToMatchColourFlippedPosition+	} = Control.DeepSeq.rnf (maybeMaximumPliesSinceMatch, preferVictories, tryToMatchMoves, tryToMatchViaJoiningMove, tryToMatchColourFlippedPosition)  instance Show StandardOpeningOptions where 	showsPrec _ MkStandardOpeningOptions {+		getMaybeMaximumPliesSinceMatch		= maybeMaximumPliesSinceMatch,+		getPreferVictories			= preferVictories, 		getTryToMatchMoves			= tryToMatchMoves, 		getTryToMatchViaJoiningMove		= tryToMatchViaJoiningMove,-		getTryToMatchColourFlippedPosition	= tryToMatchColourFlippedPosition,-		getPreferVictories			= preferVictories-	} = Text.ShowList.showsAssociationList' [+		getTryToMatchColourFlippedPosition	= tryToMatchColourFlippedPosition+	} = Text.ShowList.showsAssociationList' $ Data.Maybe.maybe id (+		(:) . (,) maximumPliesSinceMatchTag . shows+	 ) maybeMaximumPliesSinceMatch [ 		(+			preferVictoriesTag,+			shows preferVictories+		), ( 			tryToMatchMovesTag, 			shows tryToMatchMoves 		), (@@ -104,52 +120,55 @@ 		), ( 			tryToMatchColourFlippedPositionTag, 			shows tryToMatchColourFlippedPosition-		), (-			preferVictoriesTag,-			shows preferVictories 		) 	 ]  instance Data.Default.Default StandardOpeningOptions where 	def = MkStandardOpeningOptions {+		getMaybeMaximumPliesSinceMatch		= Nothing,	-- Unlimited.+		getPreferVictories			= True, 		getTryToMatchMoves			= True, 		getTryToMatchViaJoiningMove		= True,-		getTryToMatchColourFlippedPosition	= True,-		getPreferVictories			= True+		getTryToMatchColourFlippedPosition	= True 	}  instance HXT.XmlPickler StandardOpeningOptions where 	xpickle	= HXT.xpDefault Data.Default.def . HXT.xpElem tag . HXT.xpWrap (-		\(a, b, c, d) -> mkStandardOpeningOptions a b c d,	-- Construct.+		\(a, b, c, d, e) -> mkStandardOpeningOptions a b c d e,	-- Construct. 		\MkStandardOpeningOptions {+			getMaybeMaximumPliesSinceMatch		= maybeMaximumPliesSinceMatch,+			getPreferVictories			= preferVictories, 			getTryToMatchMoves			= tryToMatchMoves, 			getTryToMatchViaJoiningMove		= tryToMatchViaJoiningMove,-			getTryToMatchColourFlippedPosition	= tryToMatchColourFlippedPosition,-			getPreferVictories			= preferVictories-		} -> (tryToMatchMoves, tryToMatchViaJoiningMove, tryToMatchColourFlippedPosition, preferVictories) -- Deconstruct.-	 ) $ HXT.xp4Tuple (+			getTryToMatchColourFlippedPosition	= tryToMatchColourFlippedPosition+		} -> (maybeMaximumPliesSinceMatch, preferVictories, tryToMatchMoves, tryToMatchViaJoiningMove, tryToMatchColourFlippedPosition) -- Deconstruct.+	 ) $ HXT.xp5Tuple (+		HXT.xpOption $ HXT.xpAttr maximumPliesSinceMatchTag HXT.xpickle+	 ) (+		getPreferVictories def `HXT.xpDefault` HXT.xpAttr preferVictoriesTag HXT.xpickle+	 ) ( 		getTryToMatchMoves def `HXT.xpDefault` HXT.xpAttr tryToMatchMovesTag HXT.xpickle 	 ) ( 		getTryToMatchViaJoiningMove def `HXT.xpDefault` HXT.xpAttr tryToMatchViaJoiningMoveTag HXT.xpickle 	 ) ( 		getTryToMatchColourFlippedPosition def `HXT.xpDefault` HXT.xpAttr tryToMatchColourFlippedPositionTag HXT.xpickle-	 ) (-		getPreferVictories def `HXT.xpDefault` HXT.xpAttr preferVictoriesTag HXT.xpickle 	 ) where 		def	= Data.Default.def  -- | Smart constructor. mkStandardOpeningOptions-	:: ContextualNotation.PositionHashQualifiedMoveTree.TryToMatchMoves+	:: Maybe Type.Count.NPlies	-- ^ The optional maximum number of plies, after the last position matched against a standard opening, to abandon further match-attempts.+	-> ContextualNotation.PositionHashQualifiedMoveTree.PreferVictories+	-> ContextualNotation.PositionHashQualifiedMoveTree.TryToMatchMoves 	-> ContextualNotation.PositionHashQualifiedMoveTree.TryToMatchViaJoiningMove 	-> ContextualNotation.PositionHashQualifiedMoveTree.TryToMatchColourFlippedPosition-	-> ContextualNotation.PositionHashQualifiedMoveTree.PreferVictories 	-> StandardOpeningOptions-mkStandardOpeningOptions tryToMatchMoves tryToMatchViaJoiningMove tryToMatchColourFlippedPosition preferVictories	= MkStandardOpeningOptions {+mkStandardOpeningOptions maybeNPlies preferVictories tryToMatchMoves tryToMatchViaJoiningMove tryToMatchColourFlippedPosition	= MkStandardOpeningOptions {+	getMaybeMaximumPliesSinceMatch		= maybeNPlies,+	getPreferVictories			= preferVictories, 	getTryToMatchMoves			= tryToMatchMoves, 	getTryToMatchViaJoiningMove		= tryToMatchViaJoiningMove,-	getTryToMatchColourFlippedPosition	= tryToMatchColourFlippedPosition,-	getPreferVictories			= preferVictories+	getTryToMatchColourFlippedPosition	= tryToMatchColourFlippedPosition }  -- | Accessor.
src-lib/BishBosh/Metric/RankValue.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {- 	Copyright (C) 2021 Dr. Alistair Ward @@ -24,37 +25,48 @@ 	* The relative value of a /rank/ of chess-piece.  	* <https://en.wikipedia.org/wiki/Chess_piece_relative_value#Hans_Berliner.27s_system%20Chess-piece%20relative%20values>++	* CAVEAT: this isn't measured in conventional centi-pawns units; values are constrained to the closed unit interval, & there's no requirement /Pawn/'s value to be @1@. -}  module BishBosh.Metric.RankValue( -- * Types+#ifdef USE_NEWTYPE_WRAPPERS -- ** Data-types 	RankValue( --		MkRankValue, --		deconstruct 	),--- * Constants---	tag, -- * Functions -- ** Constructor---	mkRankValue+--	mkRankValue,+#else+-- ** Type-synonyms+	RankValue,+#endif+-- * Constants+	tag ) where +import qualified	BishBosh.Type.Mass		as Type.Mass++#ifdef USE_NEWTYPE_WRAPPERS import qualified	BishBosh.Data.Exception		as Data.Exception import qualified	BishBosh.Data.Num		as Data.Num import qualified	BishBosh.Property.ShowFloat	as Property.ShowFloat-import qualified	BishBosh.Type.Mass		as Type.Mass import qualified	Control.Arrow import qualified	Control.DeepSeq import qualified	Control.Exception import qualified	Data.List.Extra import qualified	Text.XML.HXT.Arrow.Pickle	as HXT+#endif  -- | Used to qualify XML. tag :: String tag	= "rankValue"  -- | The constant value associated with a /rank/; the higher, the more valuable it is considered to be.+#ifdef USE_NEWTYPE_WRAPPERS newtype RankValue = MkRankValue { 	deconstruct	:: Type.Mass.RankValue } deriving (Eq, Ord)@@ -94,4 +106,7 @@ mkRankValue rankValue 	| Data.Num.inClosedUnitInterval rankValue	= MkRankValue rankValue 	| otherwise					= Control.Exception.throw . Data.Exception.mkOutOfBounds . showString "BishBosh.Metric.RankValue.mkRankValue:\t" $ shows rankValue " must be within the closed unit-interval [0,1]."+#else+type RankValue	 = Type.Mass.Base+#endif 
src-lib/BishBosh/Metric/WeightedMeanAndCriterionValues.hs view
@@ -50,7 +50,7 @@ import qualified	Control.DeepSeq import qualified	Factory.Math.Statistics -#ifdef USE_PARALLEL+#ifdef PARALLELISE import qualified	Control.Parallel.Strategies #endif @@ -108,7 +108,7 @@ calculateWeightedMean	= uncurry mkWeightedMeanAndCriterionValues . ( 	Factory.Math.Statistics.getWeightedMean &&& map (realToFrac . fst)  )-#ifdef USE_PARALLEL+#ifdef PARALLELISE 	. Control.Parallel.Strategies.withStrategy ( 		Control.Parallel.Strategies.parList $ Control.Parallel.Strategies.evalTuple2 Control.Parallel.Strategies.rdeepseq Control.Parallel.Strategies.r0 	)
src-lib/BishBosh/Model/Game.hs view
@@ -500,9 +500,7 @@ 				Cartesian.Coordinates.kingsStartingCoordinates logicalColour 			) castlingRooksSource, 			let castlingKingsMove	= Component.CastlingMove.getKingsMove castlingMove,-			all (-				null . State.Board.findAttackersOf board logicalColour-			) $ Component.Move.interpolate castlingKingsMove	-- The King mustn't be checked anywhere alongs its route.+			not $ State.Board.passesThroughCheck board logicalColour castlingKingsMove 	] {-list-comprehension-} 	| otherwise	= [] {-have already Castled-} @@ -920,9 +918,7 @@ 								maybeChecked == Just sourceLogicalColour, 								"it can't castle out of check" 							), (-								not . all (-									null . State.Board.findAttackersOf board sourceLogicalColour-								) $ Component.Move.interpolate move,	-- The King mustn't pass through check when moving from source to destination (inclusive); a long castle still permits the square right of the Rook to be checked.+								State.Board.passesThroughCheck board sourceLogicalColour move,	-- The King mustn't pass through check when moving from source to destination (inclusive); a long castle still permits the square right of the Rook to be checked. 								"it can't castle through check" 							) 						] -- Tests which are independent of the implied Rook.@@ -1108,7 +1104,7 @@ 				let piece	= Component.Piece.mkPiece logicalColour rank, 				source			<- State.CoordinatesByRankByLogicalColour.dereference coordinatesByRankByLogicalColour logicalColour rank,	-- Find the source of a potential blocking move. 				(destination, Nothing)	<- State.MaybePieceByCoordinates.listDestinationsFor maybePieceByCoordinates source piece,	-- The blocker must move to an empty square, otherwise the checker was already blocked.-				Control.Exception.assert (checkedFrom /= kingsCoordinates) . elem destination . init {-drop King's location-} $ Cartesian.Coordinates.interpolate checkedFrom kingsCoordinates,+				Control.Exception.assert (checkedFrom /= kingsCoordinates) $ Cartesian.Coordinates.isBetween kingsCoordinates checkedFrom destination, 				maybePromotionRank	<- listMaybePromotionRanks destination piece 		 ] -- List-comprehension. 		attackers		-> Control.Exception.assert (
src-lib/BishBosh/Model/GameTree.hs view
@@ -38,7 +38,7 @@ --		MkGameTree, 		deconstruct 	),--- * Function+-- * Functions --	compareByMVVLVA, --	getLastMove, --	staticExchangeEvaluation,
src-lib/BishBosh/Model/PositionHashTree.hs view
@@ -28,7 +28,7 @@ --	BarePositionHashTree, -- ** Data-types 	PositionHashTree(),--- * Function+-- * Functions 	countDistinctPositions, -- ** Constructors 	mkPositionHashTree
src-lib/BishBosh/Notation/PureCoordinate.hs view
@@ -106,6 +106,7 @@  -- | Parse a pair of /coordinates/. coordinatesParser :: Text.Poly.TextParser Cartesian.Coordinates.Coordinates+{-# ANN coordinatesParser "HLint: ignore Use <$>" #-} coordinatesParser	= do 	x	<- abscissaParser 	y	<- ordinateParser
src-lib/BishBosh/Property/ShowFloat.hs view
@@ -31,6 +31,7 @@ ) where  import qualified	BishBosh.Type.Count	as Type.Count+import qualified	Data.Ratio import qualified	Numeric  -- | Render the specified data to the specified number of decimal digits.@@ -40,6 +41,15 @@ -- | An alternative to 'Show', for floating-point data. class ShowFloat a where 	showsFloat	:: (Double -> ShowS) -> a -> ShowS++instance ShowFloat Double where+	showsFloat	= id++instance ShowFloat Float where+	showsFloat fromDouble	= fromDouble . realToFrac++instance Integral r => ShowFloat (Data.Ratio.Ratio r) where+	showsFloat fromDouble	= fromDouble . realToFrac  -- | Render the specified data to the specified number of decimal digits. showsFloatToN :: ShowFloat a => Type.Count.NDecimalDigits -> a -> ShowS
src-lib/BishBosh/Rule/GameTerminationReason.hs view
@@ -31,7 +31,7 @@ -- * Types -- ** Data-types 	GameTerminationReason(),--- * Function+-- * Functions 	toResult, -- ** Constructors 	mkCheckMate,
src-lib/BishBosh/Rule/Result.hs view
@@ -30,7 +30,7 @@ --		VictoryBy, --		Draw 	),--- * Function+-- * Functions 	findMaybeVictor, -- ** Constructor 	mkResult,
src-lib/BishBosh/State/Board.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP, LambdaCase #-} {- 	Copyright (C) 2018 Dr. Alistair Ward @@ -61,11 +61,12 @@ -- ** Mutators 	movePiece, -- ** Predicates+	passesThroughCheck, 	isKingChecked, 	exposesKing ) where -import			Control.Arrow((&&&), (***), (|||))+import			Control.Arrow((&&&), (***)) import			Data.Array.IArray((!), (//)) import qualified	BishBosh.Attribute.MoveType				as Attribute.MoveType import qualified	BishBosh.Attribute.Rank					as Attribute.Rank@@ -75,7 +76,7 @@ import qualified	BishBosh.Component.Accountant				as Component.Accountant import qualified	BishBosh.Component.Move					as Component.Move import qualified	BishBosh.Component.Piece				as Component.Piece-import qualified	BishBosh.Component.PieceSquareByCoordinatesByRank	as Component.PieceSquareByCoordinatesByRank+import qualified	BishBosh.Component.PieceSquareValueByCoordinatesByRank	as Component.PieceSquareValueByCoordinatesByRank import qualified	BishBosh.Data.Exception					as Data.Exception import qualified	BishBosh.Direction.Direction				as Direction.Direction import qualified	BishBosh.Property.Empty					as Property.Empty@@ -133,7 +134,9 @@ 		getMaybePieceByCoordinates			= maybePieceByCoordinates, 		getCoordinatesByRankByLogicalColour		= coordinatesByRankByLogicalColour, 		getNDefendersByCoordinatesByLogicalColour	= nDefendersByCoordinatesByLogicalColour,+#ifndef UNBOX_TYPECOUNT_ARRAYS 		getNPiecesDifferenceByRank			= nPiecesDifferenceByRank,+#endif 		getNPawnsByFileByLogicalColour			= nPawnsByFileByLogicalColour, 		getNPieces					= nPieces, 		getPassedPawnCoordinatesByLogicalColour		= passedPawnCoordinatesByLogicalColour@@ -141,7 +144,9 @@ 		maybePieceByCoordinates, 		coordinatesByRankByLogicalColour, 		nDefendersByCoordinatesByLogicalColour,+#ifndef UNBOX_TYPECOUNT_ARRAYS 		nPiecesDifferenceByRank,+#endif 		nPawnsByFileByLogicalColour, 		nPieces, 		passedPawnCoordinatesByLogicalColour@@ -180,13 +185,8 @@ 	listRandoms zobrist MkBoard { getCoordinatesByRankByLogicalColour = coordinatesByRankByLogicalColour }	= StateProperty.Hashable.listRandoms zobrist coordinatesByRankByLogicalColour	-- Forward.  instance StateProperty.Mutator.Mutator Board where-	defineCoordinates maybePiece coordinates MkBoard {-		getMaybePieceByCoordinates	= maybePieceByCoordinates-	} = fromMaybePieceByCoordinates $ StateProperty.Mutator.defineCoordinates maybePiece coordinates maybePieceByCoordinates--	movePiece move sourcePiece maybePromotionRank eitherPassingPawnsDestinationOrMaybeTakenRank MkBoard {-		getMaybePieceByCoordinates	= maybePieceByCoordinates-	} = fromMaybePieceByCoordinates $ StateProperty.Mutator.movePiece move sourcePiece maybePromotionRank eitherPassingPawnsDestinationOrMaybeTakenRank maybePieceByCoordinates+	defineCoordinates maybePiece coordinates MkBoard { getMaybePieceByCoordinates = maybePieceByCoordinates }	= fromMaybePieceByCoordinates $ StateProperty.Mutator.defineCoordinates maybePiece coordinates maybePieceByCoordinates+	movePiece move moveType sourcePiece MkBoard { getMaybePieceByCoordinates = maybePieceByCoordinates }		= fromMaybePieceByCoordinates $ StateProperty.Mutator.movePiece move moveType sourcePiece maybePieceByCoordinates  instance StateProperty.Seeker.Seeker Board where 	findProximateKnights MkBoard {@@ -236,9 +236,9 @@ 	getNPieces					= nPieces } 	| Just sourcePiece <- State.MaybePieceByCoordinates.dereference maybePieceByCoordinates source	= let-		oppositePiece				= Property.Opposable.getOpposite sourcePiece-		(logicalColour, opponentsLogicalColour)	= ($! sourcePiece) &&& ($! oppositePiece) $ Component.Piece.getLogicalColour+		(logicalColour, (opponentsLogicalColour, oppositePiece))	= Component.Piece.getLogicalColour &&& ((Component.Piece.getLogicalColour &&& id) . Property.Opposable.getOpposite) $ sourcePiece +-- CAVEAT: this is an incomplete implementation, since Castling isn't represented, but rather implemented via two sequential calls to 'movePiece'. 		moveType :: Attribute.MoveType.MoveType 		moveType -- CAVEAT: one can't call 'State.MaybePieceByCoordinates.inferMoveType', since that performs some move-validation, & therefore exceeds the remit of this module. 			| Just explicitMoveType	<- maybeMoveType					= explicitMoveType@@ -250,21 +250,14 @@ 				else Nothing  -- Derive the required values from moveType.-		(maybePromotionRank, maybeExplicitlyTakenRank)	= Attribute.Rank.getMaybePromotionRank &&& Attribute.MoveType.getMaybeExplicitlyTakenRank $! moveType	-- Deconstruct.-		destinationPiece				= Data.Maybe.maybe id Component.Piece.promote maybePromotionRank sourcePiece-		wasPawnTakenExplicitly				= maybeExplicitlyTakenRank == Just Attribute.Rank.Pawn--		eitherPassingPawnsDestinationOrMaybeTakenRank :: Either Cartesian.Coordinates.Coordinates (Maybe Attribute.Rank.Rank)-		eitherPassingPawnsDestinationOrMaybeTakenRank-			| Attribute.MoveType.isEnPassant moveType	= Left $ Cartesian.Coordinates.retreat logicalColour destination-			| otherwise					= Right maybeExplicitlyTakenRank--		eitherPassingPawnsDestinationOrMaybeTakenPiece :: Either Cartesian.Coordinates.Coordinates (Maybe Component.Piece.Piece)-		eitherPassingPawnsDestinationOrMaybeTakenPiece	= fmap (Component.Piece.mkPiece opponentsLogicalColour) <$> eitherPassingPawnsDestinationOrMaybeTakenRank+		(destinationPiece, (maybeExplicitlyTakenPiece, wasPawnTakenExplicitly))	= ($ sourcePiece) . Data.Maybe.maybe id Component.Piece.promote . Attribute.Rank.getMaybePromotionRank &&& (fmap (Component.Piece.mkPiece opponentsLogicalColour) &&& (== Just Attribute.Rank.Pawn)) . Attribute.MoveType.getMaybeExplicitlyTakenRank $! moveType  		movePiece' :: StateProperty.Mutator.Mutator mutator => mutator -> mutator-		movePiece'	= StateProperty.Mutator.movePiece move sourcePiece maybePromotionRank eitherPassingPawnsDestinationOrMaybeTakenRank+		movePiece'	= StateProperty.Mutator.movePiece move moveType sourcePiece +		enpassantCaptureCoordinates :: Cartesian.Coordinates.Coordinates+		enpassantCaptureCoordinates	= Cartesian.Coordinates.retreat logicalColour destination	-- CAVEAT: only valid when the move-type is En-passant.+ 		board'@MkBoard { getMaybePieceByCoordinates = maybePieceByCoordinates' }	= MkBoard { 			getMaybePieceByCoordinates			= movePiece' maybePieceByCoordinates, 			getCoordinatesByRankByLogicalColour		= movePiece' coordinatesByRankByLogicalColour,@@ -286,14 +279,13 @@ 				(! Colour.LogicalColour.Black) &&& (! Colour.LogicalColour.White) $ nDefendersByCoordinatesByLogicalColour // ( 					let 						nDefendersByCoordinates	= nDefendersByCoordinatesByLogicalColour ! opponentsLogicalColour-					in (:) . (,) opponentsLogicalColour . (`Map.delete` nDefendersByCoordinates) {-Pawn has been taken-} ||| (-						\maybeExplicitlyTakenRank' -> if Data.Maybe.isJust maybeExplicitlyTakenRank'-							then (:) (-								opponentsLogicalColour,-								Map.delete destination nDefendersByCoordinates	-- This piece has been taken.-							)-							else id-					) $ eitherPassingPawnsDestinationOrMaybeTakenRank+					in Attribute.MoveType.apply (+						const id,	-- Castle.+						(:) . (,) opponentsLogicalColour $ Map.delete enpassantCaptureCoordinates nDefendersByCoordinates,	-- Pawn taken En-passant.+						\case+							(Just _, _)	-> (:) . (,) opponentsLogicalColour $ Map.delete destination nDefendersByCoordinates	-- Piece has been taken.+							_		-> id+					) moveType 				 ) [ 					id &&& Map.delete source . (nDefendersByCoordinatesByLogicalColour !) $ logicalColour	-- This piece has been moved. 				 ] -- Singleton.@@ -301,14 +293,16 @@ 				\l r -> fst l == fst r	-- Compare coordinates. 			) $ [ 				(affectedCoordinates, affectedPiece) |-					(knightsCoordinates, knight)	<- (source, sourcePiece) : (,) destination `map` (destinationPiece : (const [] ||| Data.Maybe.maybeToList) eitherPassingPawnsDestinationOrMaybeTakenPiece),+					(knightsCoordinates, knight)	<- (source, sourcePiece) : (,) destination `map` (+						destinationPiece : Data.Maybe.maybeToList maybeExplicitlyTakenPiece+					), 					Component.Piece.isKnight knight, 					affectedCoordinates		<- Data.Maybe.mapMaybe (`Cartesian.Vector.maybeTranslate` knightsCoordinates) Cartesian.Vector.attackVectorsForKnight, 					affectedPiece			<- Data.Maybe.maybeToList $! State.MaybePieceByCoordinates.dereference maybePieceByCoordinates' affectedCoordinates, 					Component.Piece.isFriend knight affectedPiece 			] {-list-comprehension-} ++ [ 				(blockingCoordinates, blockingPiece) |-					passingPawnsDestination			<- return {-to List-monad-} ||| const [] $ eitherPassingPawnsDestinationOrMaybeTakenRank,+					passingPawnsDestination			<- [enpassantCaptureCoordinates | Attribute.MoveType.isEnPassant moveType], 					(direction, antiParallelDirection)	<- Direction.Direction.opposites, 					(blockingCoordinates, blockingPiece)	<- case State.MaybePieceByCoordinates.findBlockingPieces maybePieceByCoordinates' passingPawnsDestination $ Just [direction, antiParallelDirection] of 						[cp, cp'] -> [@@ -331,7 +325,6 @@ 						 ) locatedPieces 			] {-list-comprehension-} ++ (destination, destinationPiece) : [ 				(blockingCoordinates, blockingPiece) |-					let maybeExplicitlyTakenPiece	= const Nothing ||| id $ eitherPassingPawnsDestinationOrMaybeTakenPiece, 					(direction, antiParallelDirection)	<- Direction.Direction.opposites, 					(coordinates, piece)			<- [(source, sourcePiece), (destination, destinationPiece)], 					(blockingCoordinates, blockingPiece)	<- case State.MaybePieceByCoordinates.findBlockingPieces maybePieceByCoordinates' coordinates $ Just [direction, antiParallelDirection] of@@ -354,21 +347,25 @@ 				if Colour.LogicalColour.isBlack logicalColour 					then (-)	-- Since White pieces are arbitrarily counted as positive, negate the adjustment if the current player is Black. 					else (+)-			) nPiecesDifferenceByRank $ if Attribute.MoveType.isEnPassant moveType-				then [(Attribute.Rank.Pawn, 1)]	-- Increment relative number of Pawns.-				else Data.Maybe.maybe id (-					(:) . flip (,) 1	-- Increment.-				) maybeExplicitlyTakenRank $ Data.Maybe.maybe [] (-					\promotionRank -> [-						(-							promotionRank,-							1	-- Increment.-						), (-							Attribute.Rank.Pawn,-							negate 1	-- Decrement relative number of Pawns.-						)-					]-				) maybePromotionRank,+			) nPiecesDifferenceByRank $ Attribute.MoveType.apply (+				const [],			-- Castle.+				[(Attribute.Rank.Pawn, 1)],	-- Enpassant => increment relative number of Pawns.+				uncurry ($) . (+					Data.Maybe.maybe id (+						(:) . flip (,) 1	-- Capture => Increment.+					) *** Data.Maybe.maybe [] (+						\promotionRank -> [+							(+								promotionRank,+								1		-- Increment.+							), (+								Attribute.Rank.Pawn,+								negate 1	-- Decrement relative number of Pawns.+							)+						]+					)+				) -- Normal.+			) moveType, 			getNPawnsByFileByLogicalColour		= if Component.Piece.isPawn sourcePiece && not (Attribute.MoveType.isQuiet moveType) || wasPawnTakenExplicitly 				then StateProperty.Seeker.countPawnsByFileByLogicalColour coordinatesByRankByLogicalColour'	-- Recalculate. 				else getNPawnsByFileByLogicalColour board,@@ -386,19 +383,13 @@  -- | Calculate the total value of the /coordinates/ occupied by the /piece/s of either side, at a stage in the game's life-span defined by the total number of pieces remaining. sumPieceSquareValueByLogicalColour-	:: Component.PieceSquareByCoordinatesByRank.PieceSquareByCoordinatesByRank+	:: Component.PieceSquareValueByCoordinatesByRank.PieceSquareValueByCoordinatesByRank 	-> Board-	->-#if defined(USE_UNBOXED_ARRAYS) && !defined(USE_PRECISION)-	Colour.LogicalColour.UArrayByLogicalColour-#else-	Colour.LogicalColour.ArrayByLogicalColour-#endif-		Type.Mass.Base	-- ^ Sum of PieceSquareValues.-sumPieceSquareValueByLogicalColour pieceSquareByCoordinatesByRank MkBoard {+	-> [Type.Mass.Base]	-- ^ Individual sums for each logical colours, of the PieceSquareValues.+sumPieceSquareValueByLogicalColour pieceSquareValueByCoordinatesByRank MkBoard { 	getCoordinatesByRankByLogicalColour	= coordinatesByRankByLogicalColour, 	getNPieces				= nPieces-} = Colour.LogicalColour.listArrayByLogicalColour $ Component.Accountant.sumPieceSquareValueByLogicalColour pieceSquareByCoordinatesByRank coordinatesByRankByLogicalColour nPieces+} = Component.Accountant.sumPieceSquareValueByLogicalColour pieceSquareValueByCoordinatesByRank coordinatesByRankByLogicalColour nPieces	-- Forward the request.  {- | 	* Lists the source-/coordinates/ from which the referenced destination can be attacked.@@ -455,6 +446,16 @@ isKingChecked board@MkBoard { getCoordinatesByRankByLogicalColour = coordinatesByRankByLogicalColour }	= not . null . uncurry ($!) . ( 	findAttackersOf board &&& State.CoordinatesByRankByLogicalColour.getKingsCoordinates coordinatesByRankByLogicalColour  )++-- | Confirm whether the specified move passes through check.+passesThroughCheck+	:: Board+	-> Colour.LogicalColour.LogicalColour	-- ^ The mover's /logical colour/.+	-> Component.Move.Move+	-> Bool+passesThroughCheck board logicalColour	= not . all (+	null . findAttackersOf board logicalColour . fst {-coordinates-}+ ) . Component.Move.interpolate  {- | 	* Whether one's own @King@ has become exposed in the proposed /board/.
src-lib/BishBosh/State/CoordinatesByRankByLogicalColour.hs view
@@ -54,8 +54,9 @@ 	sortCoordinates ) where -import			Control.Arrow((&&&), (|||))+import			Control.Arrow((&&&)) import			Data.Array.IArray((!), (//))+import qualified	BishBosh.Attribute.MoveType				as Attribute.MoveType import qualified	BishBosh.Attribute.Rank					as Attribute.Rank import qualified	BishBosh.Cartesian.Abscissa				as Cartesian.Abscissa import qualified	BishBosh.Cartesian.Coordinates				as Cartesian.Coordinates@@ -64,7 +65,8 @@ import qualified	BishBosh.Component.Accountant				as Component.Accountant import qualified	BishBosh.Component.Move					as Component.Move import qualified	BishBosh.Component.Piece				as Component.Piece-import qualified	BishBosh.Component.PieceSquareByCoordinatesByRank	as Component.PieceSquareByCoordinatesByRank+import qualified	BishBosh.Component.PieceSquareValueByCoordinates	as Component.PieceSquareValueByCoordinates+import qualified	BishBosh.Component.PieceSquareValueByCoordinatesByRank	as Component.PieceSquareValueByCoordinatesByRank import qualified	BishBosh.Component.Zobrist				as Component.Zobrist import qualified	BishBosh.Property.Empty					as Property.Empty import qualified	BishBosh.Property.FixedMembership			as Property.FixedMembership@@ -159,32 +161,36 @@ 		) maybePiece 	 ) . deconstruct . purgeCoordinates coordinates -	movePiece move sourcePiece maybePromotionRank eitherPassingPawnsDestinationOrMaybeTakenRank MkCoordinatesByRankByLogicalColour {-		deconstruct	= byLogicalColour-	} = MkCoordinatesByRankByLogicalColour $ byLogicalColour // (-		(:) . (`deleteOpponentsCoordinates` Attribute.Rank.Pawn) ||| Data.Maybe.maybe id {-quiet move-} (-			(:) . deleteOpponentsCoordinates destination-		) $ eitherPassingPawnsDestinationOrMaybeTakenRank+	movePiece move moveType sourcePiece MkCoordinatesByRankByLogicalColour { deconstruct = byLogicalColour }	= MkCoordinatesByRankByLogicalColour $ byLogicalColour // (+		let+			deleteOpponentsCoordinates coordinates rank	= id &&& deleteCoordinatesFromRank coordinates rank . (byLogicalColour !) $ Property.Opposable.getOpposite logicalColour+		in Attribute.MoveType.apply (+			const id,	-- Castle.+			(Cartesian.Coordinates.retreat logicalColour destination `deleteOpponentsCoordinates` Attribute.Rank.Pawn :),	-- En-passant.+			Data.Maybe.maybe id (+				(:) . deleteOpponentsCoordinates destination+			) . fst {-taken Rank-}+		) moveType 	 ) [ 		let 			byRank	= byLogicalColour ! logicalColour 		in ( 			logicalColour, 			byRank // Data.Maybe.maybe (-				return {-to List-monad-} . Control.Arrow.second (destination :)	-- Add the destination to the mover.+				return {-to List-monad-} . Control.Arrow.second (destination :)	-- Add the destination to the mover's unpromoted rank. 			) ( 				\promotionRank -> (:) (-					promotionRank,-					destination : byRank ! promotionRank	-- Add the destination to the mover's promoted rank.+					id &&& (destination :) . (byRank !) $ promotionRank	-- Add the destination to the mover's promoted rank. 				) . return {-to List-monad-}-			) maybePromotionRank (-				id &&& Data.List.delete (Component.Move.getSource move) . (byRank !) $ Component.Piece.getRank sourcePiece+			) (+				Attribute.MoveType.getMaybePromotedRank moveType+			) (+				id &&& Data.List.delete (Component.Move.getSource move) . (byRank !) $ Component.Piece.getRank sourcePiece	-- Remove the piece from the source. 			) 		) -- Pair. 	 ] where-		destination					= Component.Move.getDestination move-		logicalColour					= Component.Piece.getLogicalColour sourcePiece-		deleteOpponentsCoordinates coordinates rank	= id &&& deleteCoordinatesFromRank coordinates rank . (byLogicalColour !) $ Property.Opposable.getOpposite logicalColour+		destination	= Component.Move.getDestination move+		logicalColour	= Component.Piece.getLogicalColour sourcePiece  {- | 	* Find any @Knight@s of the specified /logical colour/, in attack-range around the specified /coordinates/.@@ -225,10 +231,12 @@ 	 )  instance Component.Accountant.Accountant CoordinatesByRankByLogicalColour where-	sumPieceSquareValueByLogicalColour pieceSquareByCoordinatesByRank MkCoordinatesByRankByLogicalColour { deconstruct = byLogicalColour } nPieces	= map (+	sumPieceSquareValueByLogicalColour pieceSquareValueByCoordinatesByRank MkCoordinatesByRankByLogicalColour { deconstruct = byLogicalColour } nPieces	= map ( 		\(logicalColour, byRank) -> Data.List.foldl' (-			\acc (rank, coordinatesList) -> Data.List.foldl' (-				\acc' -> (+ acc') . realToFrac . Component.PieceSquareByCoordinatesByRank.findPieceSquareValue pieceSquareByCoordinatesByRank nPieces logicalColour rank+			\acc (rank, coordinatesList) -> let+				pieceSquareValueByCoordinates	= Component.PieceSquareValueByCoordinatesByRank.getPieceSquareValueByCoordinates pieceSquareValueByCoordinatesByRank nPieces rank+			in pieceSquareValueByCoordinates `seq` Data.List.foldl' (+				\acc' coordinates -> acc' + (realToFrac $! Component.PieceSquareValueByCoordinates.getPieceSquareValue pieceSquareValueByCoordinates logicalColour coordinates) 			) acc coordinatesList 		) 0 $ Data.Array.IArray.assocs byRank 	 ) $ Data.Array.IArray.assocs byLogicalColour
src-lib/BishBosh/State/MaybePieceByCoordinates.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {- 	Copyright (C) 2018 Dr. Alistair Ward @@ -55,7 +56,7 @@ ) where  import			Control.Applicative((<|>))-import			Control.Arrow((&&&), (***), (|||))+import			Control.Arrow((&&&), (***)) import			Control.Category((>>>)) import			Data.Array.IArray((!), (//)) import qualified	BishBosh.Attribute.MoveType				as Attribute.MoveType@@ -72,7 +73,8 @@ import qualified	BishBosh.Component.CastlingMove				as Component.CastlingMove import qualified	BishBosh.Component.Move					as Component.Move import qualified	BishBosh.Component.Piece				as Component.Piece-import qualified	BishBosh.Component.PieceSquareByCoordinatesByRank	as Component.PieceSquareByCoordinatesByRank+import qualified	BishBosh.Component.PieceSquareValueByCoordinates	as Component.PieceSquareValueByCoordinates+import qualified	BishBosh.Component.PieceSquareValueByCoordinatesByRank	as Component.PieceSquareValueByCoordinatesByRank import qualified	BishBosh.Component.Zobrist				as Component.Zobrist import qualified	BishBosh.Data.Exception					as Data.Exception import qualified	BishBosh.Direction.Direction				as Direction.Direction@@ -82,7 +84,6 @@ import qualified	BishBosh.Property.FixedMembership			as Property.FixedMembership import qualified	BishBosh.Property.ForsythEdwards			as Property.ForsythEdwards import qualified	BishBosh.Property.Opposable				as Property.Opposable-import qualified	BishBosh.Property.Orientated				as Property.Orientated import qualified	BishBosh.Property.Reflectable				as Property.Reflectable import qualified	BishBosh.Property.SelfValidating			as Property.SelfValidating import qualified	BishBosh.StateProperty.Censor				as StateProperty.Censor@@ -104,6 +105,12 @@ import qualified	Data.Maybe import qualified	ToolShed.Data.List.Runlength +#ifdef USE_ARRAY_UNSAFEAT+import qualified	Data.Array.Base+#else+import qualified	BishBosh.Property.Orientated				as Property.Orientated+#endif+ {- | 	* This structure allows one to determine what /piece/ (if any) is located at specific /coordinates/. @@ -247,23 +254,24 @@ 	 ] -- List-comprehension.  instance StateProperty.Mutator.Mutator MaybePieceByCoordinates where-	defineCoordinates maybePiece coordinates MkMaybePieceByCoordinates {-		deconstruct	= byCoordinates-	} = Control.Exception.assert (+	defineCoordinates maybePiece coordinates MkMaybePieceByCoordinates { deconstruct = byCoordinates }	= Control.Exception.assert ( 		Data.Maybe.isJust maybePiece || Data.Maybe.isJust (byCoordinates ! coordinates) 	 ) . MkMaybePieceByCoordinates $ byCoordinates // [(coordinates, maybePiece)] -	movePiece move sourcePiece maybePromotionRank eitherPassingPawnsDestinationOrMaybeTakenRank MkMaybePieceByCoordinates {-		deconstruct	= byCoordinates-	} = MkMaybePieceByCoordinates $ byCoordinates // (-		(:) . flip (,) Nothing {-take en-passant-} ||| const id $ eitherPassingPawnsDestinationOrMaybeTakenRank+	movePiece move moveType sourcePiece MkMaybePieceByCoordinates { deconstruct = byCoordinates }	= MkMaybePieceByCoordinates $ byCoordinates // (+		if Attribute.MoveType.isEnPassant moveType+			then (:) (+				Cartesian.Coordinates.retreat (Component.Piece.getLogicalColour sourcePiece) $ Component.Move.getDestination move,+				Nothing+			)+			else id 	 ) [ 		( 			Component.Move.getSource move, 			Nothing	-- Remove the piece from the source. 		), ( 			Component.Move.getDestination move,-			Just $ Data.Maybe.maybe id Component.Piece.promote maybePromotionRank sourcePiece	-- Place the piece at the destination, removing any opposing incumbent as a side-effect.+			Just $ Data.Maybe.maybe id Component.Piece.promote (Attribute.MoveType.getMaybePromotedRank moveType) sourcePiece	-- Place the piece at the destination, removing any opposing incumbent as a side-effect. 		) 	 ] @@ -290,16 +298,17 @@ 	fromAssocs	= MkMaybePieceByCoordinates . Data.Array.IArray.accumArray (flip const) Nothing {-default-} (minBound, maxBound) . map (Control.Arrow.second Just)  instance Component.Accountant.Accountant MaybePieceByCoordinates where-	sumPieceSquareValueByLogicalColour pieceSquareByCoordinatesByRank maybePieceByCoordinates nPieces = (+	sumPieceSquareValueByLogicalColour pieceSquareValueByCoordinatesByRank maybePieceByCoordinates nPieces = ( 		\(b, w) -> [b, w] 	 ) . Data.List.foldl' ( 		\(b, w) (coordinates, piece) -> let 			logicalColour		= Component.Piece.getLogicalColour piece-			pieceSquareValue	= realToFrac $! Component.PieceSquareByCoordinatesByRank.findPieceSquareValue pieceSquareByCoordinatesByRank nPieces logicalColour (Component.Piece.getRank piece) coordinates+			pieceSquareValue	= realToFrac $! Component.PieceSquareValueByCoordinates.getPieceSquareValue (getPieceSquareValueByCoordinates $ Component.Piece.getRank piece) logicalColour coordinates 		in if Colour.LogicalColour.isBlack logicalColour 			then let b' = b + pieceSquareValue in b' `seq` (b', w) 			else let w' = w + pieceSquareValue in w' `seq` (b, w')-	 ) (0, 0) $ StateProperty.Seeker.findAllPieces maybePieceByCoordinates+	 ) (0, 0) $ StateProperty.Seeker.findAllPieces maybePieceByCoordinates where+		getPieceSquareValueByCoordinates	= Component.PieceSquareValueByCoordinatesByRank.getPieceSquareValueByCoordinates pieceSquareValueByCoordinatesByRank nPieces  instance Property.SelfValidating.SelfValidating MaybePieceByCoordinates where 	findInvalidity	= uncurry (++) . (StateProperty.Censor.findInvalidity &&& StateProperty.Seeker.findInvalidity)@@ -382,16 +391,22 @@ 			else []	-- The path immediately ahead is blocked. 		else {-N,K-} findAttackDestinations . Data.Maybe.maybe True {-unoccupied-} $ (/= logicalColour) . Component.Piece.getLogicalColour 	else {-R,B,Q-} let-		takeUntil :: [Cartesian.Coordinates.Coordinates] -> [(Cartesian.Coordinates.Coordinates, Maybe Attribute.Rank.Rank)]-		takeUntil (destination : remainder)-			| Just blockingPiece	<- byCoordinates ! destination	= [+		takeUntil :: Cartesian.Coordinates.QualifiedStraightLine -> [(Cartesian.Coordinates.Coordinates, Maybe Attribute.Rank.Rank)]+#ifdef USE_ARRAY_UNSAFEAT+		takeUntil ((destination, ix) : remainder)+			| Just blockingPiece	<- Data.Array.Base.unsafeAt byCoordinates ix+#else+		takeUntil ((destination, _) : remainder)+			| Just blockingPiece	<- byCoordinates ! destination+#endif+			= [ 				( 					destination, 					Just $ Component.Piece.getRank blockingPiece 				) | Component.Piece.getLogicalColour blockingPiece /= logicalColour 			] -- List-comprehension.-			| otherwise						= (destination, Nothing) : takeUntil remainder	-- Recurse.-		takeUntil _							= []+			| otherwise	= (destination, Nothing) : takeUntil remainder	-- Recurse.+		takeUntil _		= [] 	in Cartesian.Coordinates.applyAlongDirectionsFrom takeUntil source $ if Component.Piece.isQueen piece 		then Nothing	-- i.e. all directions. 		else Just $ Component.Piece.getAttackDirections piece@@ -472,11 +487,17 @@ 	-> Direction.Direction.Direction	-- ^ The direction in which to search. 	-> Maybe Component.Piece.LocatedPiece	-- ^ Any blocking piece. findBlockingPiece MkMaybePieceByCoordinates { deconstruct = byCoordinates } source	= slave . Cartesian.Coordinates.extrapolate source where-	slave :: [Cartesian.Coordinates.Coordinates] -> Maybe Component.Piece.LocatedPiece-	slave (coordinates : remainder)-		| Just blockingPiece	<- byCoordinates ! coordinates	= Just (coordinates, blockingPiece)	-- Terminate with success.-		| otherwise						= slave remainder			-- Recurse.-	slave _								= Nothing				-- Terminate with failure.+	slave :: Cartesian.Coordinates.QualifiedStraightLine -> Maybe Component.Piece.LocatedPiece+#ifdef USE_ARRAY_UNSAFEAT+	slave ((coordinates, ix) : remainder)+		| Just blockingPiece	<- Data.Array.Base.unsafeAt byCoordinates ix+#else+	slave ((coordinates, _) : remainder)+		| Just blockingPiece	<- byCoordinates ! coordinates+#endif+				= Just (coordinates, blockingPiece)	-- Terminate with success.+		| otherwise	= slave remainder			-- Recurse.+	slave _			= Nothing				-- Terminate with failure.  {- | 	* Find the first /piece/ of either /logical colour/, encountered in each of the specified /direction/s, from just after the specified /coordinates/.@@ -489,16 +510,22 @@ 	-> Maybe [Direction.Direction.Direction]	-- ^ The directions in which to search; 'Nothing' implies omni-directional. 	-> [Component.Piece.LocatedPiece]		-- ^ Blocking pieces in non-specific directions. findBlockingPieces MkMaybePieceByCoordinates { deconstruct = byCoordinates }	= Cartesian.Coordinates.applyAlongDirectionsFrom slave where-	slave :: [Cartesian.Coordinates.Coordinates] -> [Component.Piece.LocatedPiece]-	slave (coordinates : remainder)-		| Just blockingPiece	<- byCoordinates ! coordinates	= [(coordinates, blockingPiece)]	-- Terminate with success.-		| otherwise						= slave remainder			-- Recurse.-	slave _								= []					-- Terminate with failure.+	slave :: Cartesian.Coordinates.QualifiedStraightLine -> [Component.Piece.LocatedPiece]+#ifdef USE_ARRAY_UNSAFEAT+	slave ((coordinates, ix) : remainder)+		| Just blockingPiece	<- Data.Array.Base.unsafeAt byCoordinates ix+#else+	slave ((coordinates, _) : remainder)+		| Just blockingPiece	<- byCoordinates ! coordinates+#endif+				= [(coordinates, blockingPiece)]	-- Terminate with success.+		| otherwise	= slave remainder			-- Recurse.+	slave _			= []					-- Terminate with failure.  {- | 	* Find the /coordinates/ of any attacker who can strike the specified /coordinates/, from the specified /direction/ (as seen by the target). -	* N.B.: there no requirement for there to actually be a /piece/ to attack at the specified target.+	* N.B.: there's no requirement for there to actually be a /piece/ to attack at the specified target. -} findAttackerInDirection 	:: MaybePieceByCoordinates@@ -550,9 +577,19 @@ 	-> Cartesian.Coordinates.Coordinates	-- ^ Source. 	-> Cartesian.Coordinates.Coordinates	-- ^ Destination. 	-> Bool-isClear maybePieceByCoordinates source destination	= Control.Exception.assert (-	source /= destination && Property.Orientated.isStraight (Component.Move.mkMove source destination)- ) . all (isVacant maybePieceByCoordinates) . init {-discard the destination-} $ Cartesian.Coordinates.interpolate source destination+isClear+#ifdef USE_ARRAY_UNSAFEAT+	MkMaybePieceByCoordinates { deconstruct = byCoordinates } source destination	= all (+		Data.Maybe.isNothing . Data.Array.Base.unsafeAt byCoordinates . snd {-ix-}+	)+#else+	maybePieceByCoordinates source destination	= Control.Exception.assert (+		source /= destination && Property.Orientated.isStraight (Component.Move.mkMove source destination)+	) . all (+		isVacant maybePieceByCoordinates . fst {-coordinates-}+	)+#endif+	. init {-discard the destination-} $ Cartesian.Coordinates.interpolate source destination  -- | Whether there's a blockage between a /piece/ presumed to exist at the specified source, & a /piece/ presumed to exist @ the specified destination. isObstructed@@ -569,11 +606,12 @@ 	otherwise one would also need to confirm that the opponent's @Pawn@ had just double-advanced into the appropriate position. -} isEnPassantMove :: MaybePieceByCoordinates -> Component.Move.Move -> Bool-isEnPassantMove maybePieceByCoordinates@MkMaybePieceByCoordinates { deconstruct = byCoordinates } move-	| Just piece	<- byCoordinates ! source-	, let logicalColour	= Component.Piece.getLogicalColour piece-	= Cartesian.Coordinates.isEnPassantRank source logicalColour && Component.Piece.isPawn piece && destination `elem` Component.Piece.findAttackDestinations piece source && isVacant maybePieceByCoordinates destination	-- The move is either En-passant or invalid.-	| otherwise	= False	-- No piece.-	where-		(source, destination)	= Component.Move.getSource &&& Component.Move.getDestination $ move+isEnPassantMove maybePieceByCoordinates@MkMaybePieceByCoordinates { deconstruct = byCoordinates } move	= Data.Maybe.maybe False {-No piece-} (+	\piece -> uncurry (&&) (+		Cartesian.Coordinates.isEnPassantRank source . Component.Piece.getLogicalColour &&& Component.Piece.isPawn $ piece+	) && uncurry (&&) (+		(`elem` Component.Piece.findAttackDestinations piece source) &&& isVacant maybePieceByCoordinates $ Component.Move.getDestination move	-- The move is either En-passant or invalid.+	)+ ) $ byCoordinates ! source where+	source	= Component.Move.getSource move 
src-lib/BishBosh/State/TurnsByLogicalColour.hs view
@@ -35,6 +35,7 @@ -- * Functions 	inferNextLogicalColour, 	countPlies,+	deriveMoveNumber, 	dereference, -- ** Constructors 	fromAssocs,@@ -133,6 +134,10 @@ -} countPlies :: TurnsByLogicalColour turn -> Type.Count.NPlies countPlies MkTurnsByLogicalColour { getTurnsByLogicalColour = byLogicalColour }	= fromIntegral $ Data.Foldable.foldl' (\acc -> (+ acc) . length) 0 byLogicalColour++-- | Derive the move-number, as used in PGN.+deriveMoveNumber :: TurnsByLogicalColour turn -> Type.Count.NMoves+deriveMoveNumber MkTurnsByLogicalColour { getNPlies = nPlies }	= succ {-index from 1-} $! fromIntegral nPlies `div` 2  -- | Dereference. dereference :: TurnsByLogicalColour turn -> Colour.LogicalColour.LogicalColour -> [turn]
src-lib/BishBosh/StateProperty/Censor.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {- 	Copyright (C) 2018 Dr. Alistair Ward @@ -39,7 +40,13 @@ import qualified	BishBosh.Type.Count			as Type.Count  -- | The difference in the number of /piece/s of each /rank/ held by either side.-type NPiecesByRank	= Attribute.Rank.ArrayByRank Type.Count.NPieces+type NPiecesByRank	=+#ifdef UNBOX_TYPECOUNT_ARRAYS+	Attribute.Rank.UArrayByRank+#else+	Attribute.Rank.ArrayByRank+#endif+		Type.Count.NPieces  -- | An interface which may be implemented by data which can perform a census of the /piece/s on the /board/. class Censor censor where
src-lib/BishBosh/StateProperty/Mutator.hs view
@@ -34,11 +34,11 @@ 	removePiece ) where -import qualified	BishBosh.Attribute.Rank		as Attribute.Rank-import qualified	BishBosh.Cartesian.Coordinates	as Cartesian.Coordinates-import qualified	BishBosh.Component.Move		as Component.Move-import qualified	BishBosh.Component.Piece	as Component.Piece-import qualified	BishBosh.Property.Empty		as Property.Empty+import qualified	BishBosh.Attribute.MoveType		as Attribute.MoveType+import qualified	BishBosh.Cartesian.Coordinates		as Cartesian.Coordinates+import qualified	BishBosh.Component.Move			as Component.Move+import qualified	BishBosh.Component.Piece		as Component.Piece+import qualified	BishBosh.Property.Empty			as Property.Empty  {- | 	* An interface which may be implemented by data which can mutate the board.@@ -61,10 +61,9 @@  	-- | Move the specified piece, accounting for promotions & casualties. 	movePiece-		:: Component.Move.Move							-- ^ The source & destination /coordinates/.-		-> Component.Piece.Piece						-- ^ The /piece/ which moved.-		-> Maybe Attribute.Rank.Rank						-- ^ The (possibly promoted) /rank/ to place at the destination.-		-> Either Cartesian.Coordinates.Coordinates (Maybe Attribute.Rank.Rank)	-- ^ Either the /coordinates/ of any @Pawn@ which was just captured en-passant, or the /rank/ of any /piece/ taken.+		:: Component.Move.Move+		-> Attribute.MoveType.MoveType+		-> Component.Piece.Piece	-- ^ The /piece/ which moved, rather than the (ptentially promoted) one that arrived. 		-> mutator 		-> mutator 
src-lib/BishBosh/Text/Poly.hs view
@@ -31,13 +31,15 @@ 	char, 	string, 	spaces,-	unsignedDecimal,+	unsignedDecimal ) where  import qualified	BishBosh.Data.Integral			as Data.Integral import qualified	Data.Char -#if USE_POLYPARSE == 'L'+#ifndef USE_POLYPARSE+#	error "USE_POLYPARSE undefined"+#elif USE_POLYPARSE == 'L' import qualified	Text.ParserCombinators.Poly.Lazy	as Poly #elif USE_POLYPARSE == 'P' import qualified	Text.ParserCombinators.Poly.Plain	as Poly@@ -50,10 +52,8 @@  -- | Matches the specified char. char :: Char -> TextParser ()-char c	= do-	_	<- Poly.satisfyMsg (== c) [c]--	return {-to Parser-monad-} ()+{-# ANN char "HLint: ignore Use void" #-}+char c	= Poly.satisfyMsg (== c) [c] >> return {-to Parser-monad-} ()  {- | 	* Matches the specified string.@@ -70,10 +70,8 @@ -} spaces :: TextParser () -- spaces	= Control.Monad.void . Poly.many $ Poly.satisfy Data.Char.isSpace	-- CAVEAT: poor performance ?!-spaces	= do-	_	<- Poly.many $ Poly.satisfy Data.Char.isSpace--	return {-to Parser-monad-} ()+{-# ANN spaces "HLint: ignore Use void" #-}+spaces	= Poly.many (Poly.satisfy Data.Char.isSpace) >> return {-to Parser-monad-} ()  -- | Parses an unsigned base-10 integer. unsignedDecimal :: Num i => TextParser i
src-lib/BishBosh/Type/Length.hs view
@@ -41,7 +41,7 @@ 	Column ) where -#if defined(USE_NARROW_NUMBERS) || defined(USE_NEWTYPE_WRAPPERS)+#if defined USE_NARROW_NUMBERS || defined USE_NEWTYPE_WRAPPERS #	ifdef USE_NARROW_NUMBERS import qualified	Data.Int #	endif
src-lib/BishBosh/Type/Mass.hs view
@@ -49,7 +49,7 @@ import qualified	Control.Exception #endif -#ifdef USE_PRECISION+#ifdef USE_PRECISE_NUMBERS import			BishBosh.Data.Ratio() #else import qualified	Text.XML.HXT.Arrow.Pickle	as HXT@@ -57,7 +57,7 @@  -- | The underling type. type Base	=-#ifdef USE_PRECISION+#ifdef USE_PRECISE_NUMBERS 	Rational #else /* Floating-point */ #	ifdef USE_NARROW_NUMBERS
src-test/BishBosh/Test/HUnit/Cartesian/Coordinates.hs view
@@ -38,7 +38,9 @@ -- | Check the sanity of the implementation, by validating a list of static test-cases. testCases :: Test.HUnit.Test testCases	= Test.HUnit.test [-	all (Colour.LogicalColourOfSquare.isBlack . Cartesian.Coordinates.getLogicalColourOfSquare) (+	all (+		Colour.LogicalColourOfSquare.isBlack . Cartesian.Coordinates.getLogicalColourOfSquare . fst {-Coordinates-}+	) ( 		Cartesian.Coordinates.extrapolate (minBound :: Cartesian.Coordinates.Coordinates) maxBound {-direction-} 	) ~? "'BishBosh.Cartesian.Coordinates.getLogicalColourOfSquare' failed to find black squares on the main diagonal.", 	"'BishBosh.Cartesian.Coordinates.getLogicalColourOfSquare' failed to count equal numbers of black & white squares." ~: (
src-test/BishBosh/Test/HUnit/ContextualNotation/PGN.hs view
@@ -48,7 +48,7 @@ import qualified	Text.ParserCombinators.Parsec		as Parsec #endif -#if !defined(USE_POLYPARSE) || USE_POLYPARSE != 'L'+#if !defined USE_POLYPARSE || USE_POLYPARSE != 'L' import qualified	BishBosh.Data.Exception			as Data.Exception import qualified	Control.Exception #endif
src-test/BishBosh/Test/HUnit/ContextualNotation/PositionHashQualifiedMoveTree.hs view
@@ -78,7 +78,7 @@ -- | Check the sanity of the implementation, by validating a list of static test-cases. testCases :: Test.HUnit.Test testCases	= Test.HUnit.test [-	"ContextualNotation.PositionHashQualifiedMoveTree.findNextOnymousQualifiedMoves" ~: checkMatch (True, False, False) game2 (init moveStrings2) finalMove2,	-- Exact match for standard-opening.+	"ContextualNotation.PositionHashQualifiedMoveTree.findNextOnymousQualifiedMoves" ~: checkMatch (True, False, False) game2 (init moveStrings2) finalMove2,	-- Exact match for standard opening. 	"ContextualNotation.PositionHashQualifiedMoveTree.findNextOnymousQualifiedMoves/transposition" ~: checkMatch (False, False, False) game1 (words "e2e4 c7c5 d2d4 c5d4p g1f3 d7d6 f3d4p g8f6 b1c3") finalMove1,	-- White's 2nd & 3rd moves have been transposed & Black's 2nd & 3rd move also have been transposed. 	"ContextualNotation.PositionHashQualifiedMoveTree.findNextOnymousQualifiedMoves/transposition" ~: checkMatch (False, False, False) game2 (words "g1f3 d7d6 e2e4 c7c5 d2d4 c5d4p f3d4p g8f6 b1c3 a7a6 c1g5 e7e6 f2f4 d8b6 d1d2 b6b2p a1b1 b2a3 f4f5 b8c6 f5e6p f7e6p d4c6n b7c6n e4e5 d6e5p g5f6n g7f6b c3e4 f8e7 f1e2 h7h5 b1b3 a3a4") finalMove2,	-- White & also Black's 1st & 2nd moves have been transposed. 	"ContextualNotation.PositionHashQualifiedMoveTree.findNextOnymousQualifiedMoves/join" ~: checkMatch (False, True {-TryToMatchViaJoiningMove-}, False) game1 (words "e2e4 c7c5 g1f3 d7d6 d2d4 c5d4p b1c3 g8f6") (
src-test/BishBosh/Test/HUnit/ContextualNotation/StandardAlgebraic.hs view
@@ -57,6 +57,7 @@ import			Control.Arrow((|||)) import			Test.HUnit((~?=), (~?)) import qualified	Text.ParserCombinators.Parsec+{-# ANN module "HLint: ignore Use fewer imports" #-} #endif  -- | Check the sanity of the implementation, by validating a list of static test-cases.
src-test/BishBosh/Test/HUnit/Model/PositionHashTree.hs view
@@ -39,7 +39,7 @@ testCases :: Test.HUnit.Test testCases	= Test.HUnit.test [ 	let-		maxDepth	= 4+		maxDepth	= 4	-- CAVEAT: 5 requires to much RAM. 	in "'BishBosh.Model.PositionhashTree.countDistinctPositions' failed" ~: map ( 		\i -> Model.PositionHashTree.countDistinctPositions i (Data.Default.def :: Model.PositionHashTree.PositionHashTree Type.Crypto.PositionHash) 	) [0 .. maxDepth] ~?= take (succ maxDepth) [1, 20, 400, 5362, 72078, 822518, 9417681, 96400068, 988187354, 9183421888, 85375278064, 726155461002]	-- <https://oeis.org/A083276>. CAVEAT: the point at which this test fails, depends on the square-root of the bits in 'Crypto.PositionHash'.
src-test/BishBosh/Test/HUnit/State/Board.hs view
@@ -64,7 +64,7 @@ 	let 		kingsColour		= minBound 		destination		= Cartesian.Coordinates.mkRelativeCoordinates ((+ 3) *** (+ 3))-		directionToCoordinates	= last . Cartesian.Coordinates.extrapolate destination+		directionToCoordinates	= fst {-Coordinates-} . last . Cartesian.Coordinates.extrapolate destination 		mkPiece			= Component.Piece.mkPiece $ Property.Opposable.getOpposite kingsColour 		maybeShift		= (`Cartesian.Vector.maybeTranslate` destination) 	in all (
src-test/BishBosh/Test/QuickCheck/Cartesian/Coordinates.hs view
@@ -119,14 +119,20 @@ 					| null extrapolation	= source 					| otherwise		= last extrapolation 			 in source == destination || source : extrapolation == reverse (-				destination : Cartesian.Coordinates.interpolate destination source+				destination : map fst {-Coordinates-} (+					Cartesian.Coordinates.interpolate destination source+				) 			 )-		 ) $ Cartesian.Coordinates.extrapolate source direction+		 ) . map fst {-Coordinates-} $ Cartesian.Coordinates.extrapolate source direction 	in Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 64 } f, 	let 		f :: Cartesian.Coordinates.Coordinates -> Cartesian.Coordinates.Coordinates -> Test.QuickCheck.Property-		f source destination	= isValidMove source destination ==> Test.QuickCheck.label "Coordinates.prop_interpolate" $ source : Cartesian.Coordinates.interpolate source destination == reverse (-			destination : Cartesian.Coordinates.interpolate destination source+		f source destination	= isValidMove source destination ==> Test.QuickCheck.label "Coordinates.prop_interpolate" $ source : map fst {-Coordinates-} (+			Cartesian.Coordinates.interpolate source destination+		 ) == reverse (+			destination : map fst {-Coordinates-} (+				Cartesian.Coordinates.interpolate destination source+			) 		 ) 	in Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 64 } f, 	let@@ -142,6 +148,22 @@ 		f	= Test.QuickCheck.label "Coordinates.prop_applyAlongDirectionsFrom" . uncurry (==) . ( 			flip (Cartesian.Coordinates.applyAlongDirectionsFrom id) Nothing &&& flip (Cartesian.Coordinates.applyAlongDirectionsFrom id) (Just Property.FixedMembership.members) 		 )-	in Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 16 } f+	in Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 16 } f,+	let+		f :: Cartesian.Coordinates.Coordinates -> Direction.Direction.Direction -> Test.QuickCheck.Property+		f source direction	= not (null qualifiedStraightLine) ==> let+			destination	= fst {-coordinates-} $ last qualifiedStraightLine+		 in Test.QuickCheck.label "Coordinates.prop_isBetween(terminals)" . not $ any (Cartesian.Coordinates.isBetween source destination) [source, destination] where+			qualifiedStraightLine	= Cartesian.Coordinates.extrapolate source direction+	in Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 32 } f,+	let+		f :: Cartesian.Coordinates.Coordinates -> Direction.Direction.Direction -> Cartesian.Coordinates.Coordinates -> Test.QuickCheck.Property+		f source direction intermediary	= not (null qualifiedStraightLine) ==> let+			destination	= fst {-coordinates-} $ last qualifiedStraightLine+		 in Test.QuickCheck.label "Coordinates.prop_isBetween(symmetrical)" . uncurry (==) $ (+			Cartesian.Coordinates.isBetween source destination &&& Cartesian.Coordinates.isBetween destination source+		 ) intermediary where+			qualifiedStraightLine	= Cartesian.Coordinates.extrapolate source direction+	in Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 64 } f  ] 
src-test/BishBosh/Test/QuickCheck/Evaluation/PositionHashQuantifiedGameTree.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {- 	Copyright (C) 2018 Dr. Alistair Ward @@ -36,19 +37,23 @@ import qualified	BishBosh.Input.SearchOptions				as Input.SearchOptions import qualified	BishBosh.Model.Game					as Model.Game import qualified	BishBosh.Property.Empty					as Property.Empty-import qualified	BishBosh.State.Position					as State.Position import qualified	BishBosh.Test.QuickCheck.Component.Zobrist		as Test.QuickCheck.Component.Zobrist import qualified	BishBosh.Type.Crypto					as Type.Crypto import qualified	BishBosh.Type.Mass					as Type.Mass-import qualified	Data.List.Extra-import qualified	Data.Ord import qualified	Data.Tree import qualified	Test.QuickCheck++#ifndef USE_NARROW_NUMBERS+import qualified	BishBosh.State.Position					as State.Position+import qualified	Data.List.Extra+import qualified	Data.Ord import			Test.QuickCheck((==>))+#endif  -- | The constant test-results for this data-type. results :: IO [Test.QuickCheck.Result] results	= sequence [+#ifndef USE_NARROW_NUMBERS 	let 		f 			:: Input.EvaluationOptions.EvaluationOptions@@ -67,6 +72,7 @@ 				Data.Ord.comparing Evaluation.PositionHashQuantifiedGameTree.getPositionHash 			 ) . take 10000 . Data.Tree.flatten . Evaluation.PositionHashQuantifiedGameTree.deconstruct $ Evaluation.PositionHashQuantifiedGameTree.mkPositionHashQuantifiedGameTree evaluationOptions searchOptions zobrist Property.Empty.empty {-MoveFrequency-} game 	in Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 32 } f,+#endif 	let 		f 			:: Input.EvaluationOptions.EvaluationOptions
src-test/BishBosh/Test/QuickCheck/Input/EvaluationOptions.hs view
@@ -40,14 +40,13 @@ import qualified	BishBosh.Input.RankValues		as Input.RankValues import qualified	BishBosh.Property.Reflectable		as Property.Reflectable import qualified	BishBosh.State.Board			as State.Board-import qualified	Data.Array.IArray import qualified	Data.List import qualified	Data.Map.Strict				as Map import qualified	Data.Maybe import qualified	Test.QuickCheck import			Test.QuickCheck((==>)) -#ifdef USE_PRECISION+#ifdef USE_PRECISE_NUMBERS import qualified	BishBosh.Component.Accountant		as Component.Accountant import qualified	BishBosh.Type.Mass			as Type.Mass #endif@@ -72,25 +71,25 @@ -- | The constant test-results for this data-type. results :: IO [Test.QuickCheck.Result] results	= sequence [-#ifdef USE_PRECISION+#ifdef USE_PRECISE_NUMBERS 	let 		f :: Input.EvaluationOptions.EvaluationOptions -> State.Board.Board -> Test.QuickCheck.Property-		f evaluationOptions board	= Data.Maybe.isJust maybePieceSquareByCoordinatesByRank ==> Test.QuickCheck.label "EvaluationOptions.prop_sumPieceSquareValueByLogicalColour" . uncurry (==) $ (+		f evaluationOptions board	= Data.Maybe.isJust maybePieceSquareValueByCoordinatesByRank ==> Test.QuickCheck.label "EvaluationOptions.prop_sumPieceSquareValueByLogicalColour" . uncurry (==) $ ( 			sumPieceSquareValueByLogicalColour' . State.Board.getCoordinatesByRankByLogicalColour &&& sumPieceSquareValueByLogicalColour' . State.Board.getMaybePieceByCoordinates 		 ) board where-			maybePieceSquareByCoordinatesByRank	= Input.EvaluationOptions.getMaybePieceSquareByCoordinatesByRank evaluationOptions+			maybePieceSquareValueByCoordinatesByRank	= Input.EvaluationOptions.getMaybePieceSquareValueByCoordinatesByRank evaluationOptions  			sumPieceSquareValueByLogicalColour' :: Component.Accountant.Accountant accountant => accountant -> [Type.Mass.Base]-			sumPieceSquareValueByLogicalColour'	= flip (Component.Accountant.sumPieceSquareValueByLogicalColour $ Data.Maybe.fromJust maybePieceSquareByCoordinatesByRank) $ State.Board.getNPieces board+			sumPieceSquareValueByLogicalColour'	= flip (Component.Accountant.sumPieceSquareValueByLogicalColour $ Data.Maybe.fromJust maybePieceSquareValueByCoordinatesByRank) $ State.Board.getNPieces board 	in Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 64 } f, #endif 	let 		f :: Input.EvaluationOptions.EvaluationOptions -> State.Board.Board -> Test.QuickCheck.Property-		f evaluationOptions board	= Data.Maybe.isJust maybePieceSquareByCoordinatesByRank ==> Test.QuickCheck.label "EvaluationOptions.prop_sumPieceSquareValueByLogicalColour/reflectOnX" . uncurry (==) $ (-			Data.Array.IArray.elems . sumPieceSquareValueByLogicalColour &&& reverse . Data.Array.IArray.elems . sumPieceSquareValueByLogicalColour . Property.Reflectable.reflectOnX+		f evaluationOptions board	= Data.Maybe.isJust maybePieceSquareValueByCoordinatesByRank ==> Test.QuickCheck.label "EvaluationOptions.prop_sumPieceSquareValueByLogicalColour/reflectOnX" . uncurry (==) $ (+			sumPieceSquareValueByLogicalColour &&& reverse . sumPieceSquareValueByLogicalColour . Property.Reflectable.reflectOnX 		 ) board where-			maybePieceSquareByCoordinatesByRank	= Input.EvaluationOptions.getMaybePieceSquareByCoordinatesByRank evaluationOptions-			sumPieceSquareValueByLogicalColour	= State.Board.sumPieceSquareValueByLogicalColour $ Data.Maybe.fromJust maybePieceSquareByCoordinatesByRank+			maybePieceSquareValueByCoordinatesByRank	= Input.EvaluationOptions.getMaybePieceSquareValueByCoordinatesByRank evaluationOptions+			sumPieceSquareValueByLogicalColour		= State.Board.sumPieceSquareValueByLogicalColour $ Data.Maybe.fromJust maybePieceSquareValueByCoordinatesByRank 	in Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 32 } f  ] 
src-test/BishBosh/Test/QuickCheck/Input/RankValues.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# OPTIONS_GHC -fno-warn-orphans #-} {- 	Copyright (C) 2018 Dr. Alistair Ward@@ -23,15 +24,47 @@  [@DESCRIPTION@]	Implements 'Test.QuickCheck.Arbitrary'. -} -module BishBosh.Test.QuickCheck.Input.RankValues() where+module BishBosh.Test.QuickCheck.Input.RankValues(+-- * Constants+	results+) where -import			BishBosh.Test.QuickCheck.Metric.RankValue() import qualified	BishBosh.Attribute.Rank			as Attribute.Rank import qualified	BishBosh.Input.RankValues		as Input.RankValues import qualified	BishBosh.Property.FixedMembership	as Property.FixedMembership import qualified	Data.List import qualified	Test.QuickCheck+import qualified	ToolShed.Test.ReversibleIO +#ifdef USE_NEWTYPE_WRAPPERS+import			BishBosh.Test.QuickCheck.Metric.RankValue()+#endif+ instance Test.QuickCheck.Arbitrary Input.RankValues.RankValues where-	arbitrary	= Input.RankValues.fromAssocs . zip Property.FixedMembership.members . Data.List.sort {-ensures Q is most valuable (except K)-} <$> Test.QuickCheck.vector (fromIntegral Attribute.Rank.nDistinctRanks)+	arbitrary	= Input.RankValues.fromAssocs . zip Property.FixedMembership.members . Data.List.sort {-ensures Q is most valuable (except K)-} +#ifndef USE_NEWTYPE_WRAPPERS+		. map (recip . fromInteger . succ . abs)	-- Map into the closed unit interval.+#endif+		<$> Test.QuickCheck.suchThat (+			Test.QuickCheck.vector $ fromIntegral Attribute.Rank.nDistinctRanks+		) (any (/= 0))++-- | The constant test-results for this data-type.+results :: IO [Test.QuickCheck.Result]+results	= sequence [+	let+		f :: Input.RankValues.RankValues -> Test.QuickCheck.Property+		f	= Test.QuickCheck.label "RankValues.prop_readPrependedWhiteSpace" . ToolShed.Test.ReversibleIO.readPrependedWhiteSpace+	in Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 32 } f,+	let+		f :: String -> Test.QuickCheck.Property+		f garbage	= Test.QuickCheck.label "RankValues.prop_read" $ case (reads garbage :: [(Input.RankValues.RankValues, String)]) of+			[_]	-> True+			_	-> True	-- Unless the read-implementation throws an exception.+	in Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 256 } f,+	let+		f :: Input.RankValues.RankValues -> String -> Test.QuickCheck.Property+		f rankValue	= Test.QuickCheck.label "RankValues.prop_readTrailingGarbage" . ToolShed.Test.ReversibleIO.readTrailingGarbage (const True) rankValue+	in Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 256 } f+ ] 
src-test/BishBosh/Test/QuickCheck/Input/StandardOpeningOptions.hs view
@@ -25,9 +25,15 @@  module BishBosh.Test.QuickCheck.Input.StandardOpeningOptions() where +import			BishBosh.Test.QuickCheck.Type.Count() import qualified	BishBosh.Input.StandardOpeningOptions	as Input.StandardOpeningOptions import qualified	Test.QuickCheck  instance Test.QuickCheck.Arbitrary Input.StandardOpeningOptions.StandardOpeningOptions where-	arbitrary	= Input.StandardOpeningOptions.mkStandardOpeningOptions <$> Test.QuickCheck.arbitrary <*> Test.QuickCheck.arbitrary <*> Test.QuickCheck.arbitrary <*> Test.QuickCheck.arbitrary+	arbitrary	= Input.StandardOpeningOptions.mkStandardOpeningOptions+		<$> Test.QuickCheck.arbitrary+		<*> Test.QuickCheck.arbitrary+		<*> Test.QuickCheck.arbitrary+		<*> Test.QuickCheck.arbitrary+		<*> Test.QuickCheck.arbitrary 
src-test/BishBosh/Test/QuickCheck/Model/Game.hs view
@@ -293,11 +293,11 @@ 	let 		f :: Input.EvaluationOptions.EvaluationOptions -> Model.Game.Game -> Test.QuickCheck.Property 		f evaluationOptions game	= Data.Maybe.isJust (-			Input.EvaluationOptions.getMaybePieceSquareByCoordinatesByRank evaluationOptions+			Input.EvaluationOptions.getMaybePieceSquareValueByCoordinatesByRank evaluationOptions 		 ) && not ( 			Property.Null.isNull game 		 ) ==> Test.QuickCheck.label "Game.prop_measurePieceSquareValueIncrementally" .-#ifdef USE_PRECISION+#ifdef USE_PRECISE_NUMBERS 		 uncurry (==) #else 		 (@@ -310,10 +310,10 @@ 		 ) . abs . uncurry (-)	-- Tolerance for floating-point errors. #endif 		 $ (-			measurePieceSquareValueDifference' &&& Evaluation.Fitness.measurePieceSquareValueDifferenceIncrementally (measurePieceSquareValueDifference' oldGame) pieceSquareByCoordinatesByRank+			measurePieceSquareValueDifference' &&& Evaluation.Fitness.measurePieceSquareValueDifferenceIncrementally (measurePieceSquareValueDifference' oldGame) pieceSquareValueByCoordinatesByRank 		 ) game where-			pieceSquareByCoordinatesByRank		= Data.Maybe.fromJust $ Input.EvaluationOptions.getMaybePieceSquareByCoordinatesByRank evaluationOptions-			measurePieceSquareValueDifference'	= Evaluation.Fitness.measurePieceSquareValueDifference pieceSquareByCoordinatesByRank+			pieceSquareValueByCoordinatesByRank	= Data.Maybe.fromJust $ Input.EvaluationOptions.getMaybePieceSquareValueByCoordinatesByRank evaluationOptions+			measurePieceSquareValueDifference'	= Evaluation.Fitness.measurePieceSquareValueDifference pieceSquareValueByCoordinatesByRank 			(oldGame, _) : _			= Model.Game.rollBack game 	in Test.QuickCheck.quickCheckWithResult Test.QuickCheck.stdArgs { Test.QuickCheck.maxSuccess = 2048 } f, 	let
src-test/BishBosh/Test/QuickCheck/State/Board.hs view
@@ -157,7 +157,9 @@ 				isClear	= State.MaybePieceByCoordinates.isClear maybePieceByCoordinates source 			in all ( 				\direction -> Data.Maybe.maybe (-					Data.Maybe.maybe True isClear . Data.Maybe.listToMaybe . reverse $ Cartesian.Coordinates.extrapolate source direction+					Data.Maybe.maybe True (+						isClear . fst {-Coordinates-}+					) .  Data.Maybe.listToMaybe . reverse $ Cartesian.Coordinates.extrapolate source direction 				) ( 					isClear . fst {-destination-} 				) $ State.MaybePieceByCoordinates.findBlockingPiece maybePieceByCoordinates source direction
src-test/BishBosh/Test/QuickCheck/StateProperty/Hashable.hs view
@@ -23,7 +23,7 @@ -}  module BishBosh.Test.QuickCheck.StateProperty.Hashable(--- * Constants,+-- * Constants 	results ) where 
src-test/BishBosh/Test/QuickCheck/StateProperty/Mutator.hs view
@@ -33,12 +33,10 @@ import			BishBosh.Test.QuickCheck.Model.Game() import			Control.Arrow((&&&)) import			Test.QuickCheck ((==>))-import qualified	BishBosh.Attribute.MoveType			as Attribute.MoveType import qualified	BishBosh.Cartesian.Coordinates			as Cartesian.Coordinates import qualified	BishBosh.Component.Move				as Component.Move import qualified	BishBosh.Component.QualifiedMove		as Component.QualifiedMove import qualified	BishBosh.Component.Piece			as Component.Piece-import qualified	BishBosh.Component.Turn				as Component.Turn import qualified	BishBosh.Model.Game				as Model.Game import qualified	BishBosh.Property.Null				as Property.Null import qualified	BishBosh.State.Board				as State.Board@@ -74,13 +72,9 @@ 				board			= Model.Game.getBoard game  				movePiece :: StateProperty.Mutator.Mutator mutator => mutator -> mutator-				movePiece	= StateProperty.Mutator.movePiece move (-					Data.Maybe.fromJust . State.MaybePieceByCoordinates.dereference (State.Board.getMaybePieceByCoordinates board) $ Component.Move.getSource move-				 ) (-					Attribute.MoveType.getMaybePromotedRank moveType-				 ) $ if Attribute.MoveType.isEnPassant moveType-					then Left . Component.Move.getDestination . Component.QualifiedMove.getMove . Component.Turn.getQualifiedMove . Data.Maybe.fromJust $ Model.Game.maybeLastTurn game-					else Right $ Attribute.MoveType.getMaybeExplicitlyTakenRank moveType+				movePiece	= StateProperty.Mutator.movePiece move moveType (+					Data.Maybe.fromJust . State.MaybePieceByCoordinates.dereference (State.Board.getMaybePieceByCoordinates board) . Component.Move.getSource $ Component.QualifiedMove.getMove qualifiedMove+				 ) 			in uncurry (==) $ ( 				normalise . StateProperty.View.translate . movePiece . State.Board.getMaybePieceByCoordinates &&& normalise . movePiece . State.Board.getCoordinatesByRankByLogicalColour 			) board
src-test/QuickCheck.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {- 	Copyright (C) 2018 Dr. Alistair Ward @@ -46,7 +47,7 @@ import qualified	BishBosh.Test.QuickCheck.Input.EvaluationOptions				as Test.QuickCheck.Input.EvaluationOptions import qualified	BishBosh.Test.QuickCheck.Input.Options						as Test.QuickCheck.Input.Options import qualified	BishBosh.Test.QuickCheck.Input.PieceSquareTable					as Test.QuickCheck.Input.PieceSquareTable-import qualified	BishBosh.Test.QuickCheck.Metric.RankValue					as Test.QuickCheck.Metric.RankValue+import qualified	BishBosh.Test.QuickCheck.Input.RankValues					as Test.QuickCheck.Input.RankValues import qualified	BishBosh.Test.QuickCheck.Model.Game						as Test.QuickCheck.Model.Game import qualified	BishBosh.Test.QuickCheck.Model.GameTree						as Test.QuickCheck.Model.GameTree import qualified	BishBosh.Test.QuickCheck.Model.MoveFrequency					as Test.QuickCheck.Model.MoveFrequency@@ -77,6 +78,10 @@ import qualified	System.Exit import qualified	ToolShed.Test.QuickCheck.Result +#ifdef USE_NEWTYPE_WRAPPERS+import qualified	BishBosh.Test.QuickCheck.Metric.RankValue					as Test.QuickCheck.Metric.RankValue+#endif+ -- | Entry-point to the test-suite. main :: IO () main	= mapM_ (@@ -89,9 +94,14 @@ 	Test.QuickCheck.Attribute.Rank.results, 	Test.QuickCheck.Attribute.MoveType.results, 	Test.QuickCheck.Direction.Direction.results,+#ifdef USE_NEWTYPE_WRAPPERS+	Test.QuickCheck.Metric.RankValue.results,+#endif+	Test.QuickCheck.Input.CriteriaWeights.results, 	Test.QuickCheck.Input.EvaluationOptions.results, 	Test.QuickCheck.Input.Options.results, 	Test.QuickCheck.Input.PieceSquareTable.results,+	Test.QuickCheck.Input.RankValues.results, 	Test.QuickCheck.Cartesian.Coordinates.results, 	Test.QuickCheck.Cartesian.Vector.results, 	Test.QuickCheck.Component.Piece.results,@@ -123,8 +133,6 @@ 	Test.QuickCheck.ContextualNotation.PGNComment.results, 	Test.QuickCheck.ContextualNotation.PGN.results, 	Test.QuickCheck.ContextualNotation.QualifiedMoveForest.results,-	Test.QuickCheck.Input.CriteriaWeights.results,-	Test.QuickCheck.Metric.RankValue.results, 	Test.QuickCheck.Evaluation.PositionHashQuantifiedGameTree.results, 	Test.QuickCheck.Search.KillerMoves.results, 	Test.QuickCheck.UI.PrintObject.results,