packages feed

bishbosh-0.1.4.0: src-lib/BishBosh/Component/PieceSquareValueByCoordinatesByRank.hs

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