module BishBosh.State.InstancesByPosition(
leastCyclicPlies,
InstancesByPosition(),
countConsecutiveRepeatablePlies,
countPositionRepetitions,
getNDistinctPositions,
findMaximumInstances,
mkInstancesByPosition,
mkSingleton,
insertPosition,
deletePosition,
anyInstancesByPosition
) where
import qualified BishBosh.Component.Move as Component.Move
import qualified BishBosh.Data.Exception as Data.Exception
import qualified BishBosh.Property.Reflectable as Property.Reflectable
import qualified BishBosh.State.Board as State.Board
import qualified Control.DeepSeq
import qualified Control.Exception
import qualified Data.Foldable
import qualified Data.Map.Strict
leastCyclicPlies :: Component.Move.NPlies
leastCyclicPlies :: NPlies
leastCyclicPlies = NPlies
4
type NBoardsByPosition position = Data.Map.Strict.Map position State.Board.NBoards
newtype InstancesByPosition position = MkInstancesByPosition {
InstancesByPosition position -> NBoardsByPosition position
getNBoardsByPosition :: NBoardsByPosition position
} deriving InstancesByPosition position
-> InstancesByPosition position -> Bool
(InstancesByPosition position
-> InstancesByPosition position -> Bool)
-> (InstancesByPosition position
-> InstancesByPosition position -> Bool)
-> Eq (InstancesByPosition position)
forall position.
Eq position =>
InstancesByPosition position
-> InstancesByPosition position -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: InstancesByPosition position
-> InstancesByPosition position -> Bool
$c/= :: forall position.
Eq position =>
InstancesByPosition position
-> InstancesByPosition position -> Bool
== :: InstancesByPosition position
-> InstancesByPosition position -> Bool
$c== :: forall position.
Eq position =>
InstancesByPosition position
-> InstancesByPosition position -> Bool
Eq
instance Control.DeepSeq.NFData position => Control.DeepSeq.NFData (InstancesByPosition position) where
rnf :: InstancesByPosition position -> ()
rnf MkInstancesByPosition { getNBoardsByPosition :: forall position.
InstancesByPosition position -> NBoardsByPosition position
getNBoardsByPosition = NBoardsByPosition position
m } = NBoardsByPosition position -> ()
forall a. NFData a => a -> ()
Control.DeepSeq.rnf NBoardsByPosition position
m
instance (
Ord position,
Property.Reflectable.ReflectableOnX position
) => Property.Reflectable.ReflectableOnX (InstancesByPosition position) where
reflectOnX :: InstancesByPosition position -> InstancesByPosition position
reflectOnX MkInstancesByPosition { getNBoardsByPosition :: forall position.
InstancesByPosition position -> NBoardsByPosition position
getNBoardsByPosition = NBoardsByPosition position
m } = NBoardsByPosition position -> InstancesByPosition position
forall position.
NBoardsByPosition position -> InstancesByPosition position
MkInstancesByPosition (NBoardsByPosition position -> InstancesByPosition position)
-> NBoardsByPosition position -> InstancesByPosition position
forall a b. (a -> b) -> a -> b
$ (position -> position)
-> NBoardsByPosition position -> NBoardsByPosition position
forall k2 k1 a. Ord k2 => (k1 -> k2) -> Map k1 a -> Map k2 a
Data.Map.Strict.mapKeys position -> position
forall a. ReflectableOnX a => a -> a
Property.Reflectable.reflectOnX NBoardsByPosition position
m
mkInstancesByPosition :: NBoardsByPosition position -> InstancesByPosition position
mkInstancesByPosition :: NBoardsByPosition position -> InstancesByPosition position
mkInstancesByPosition NBoardsByPosition position
nBoardsByPosition
| (NPlies -> Bool) -> NBoardsByPosition position -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
Data.Foldable.any (NPlies -> NPlies -> Bool
forall a. Ord a => a -> a -> Bool
< NPlies
1) NBoardsByPosition position
nBoardsByPosition = Exception -> InstancesByPosition position
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> InstancesByPosition position)
-> Exception -> InstancesByPosition position
forall a b. (a -> b) -> a -> b
$ String -> Exception
Data.Exception.mkOutOfBounds String
"BishBosh.State.InstancesByPosition.mkInstancesByPosition:\teach specified position must have been visited at least once."
| Bool
otherwise = NBoardsByPosition position -> InstancesByPosition position
forall position.
NBoardsByPosition position -> InstancesByPosition position
MkInstancesByPosition NBoardsByPosition position
nBoardsByPosition
mkSingleton :: position -> InstancesByPosition position
mkSingleton :: position -> InstancesByPosition position
mkSingleton position
position = NBoardsByPosition position -> InstancesByPosition position
forall position.
NBoardsByPosition position -> InstancesByPosition position
MkInstancesByPosition (NBoardsByPosition position -> InstancesByPosition position)
-> NBoardsByPosition position -> InstancesByPosition position
forall a b. (a -> b) -> a -> b
$ position -> NPlies -> NBoardsByPosition position
forall k a. k -> a -> Map k a
Data.Map.Strict.singleton position
position NPlies
1
countConsecutiveRepeatablePlies :: InstancesByPosition position -> Component.Move.NPlies
countConsecutiveRepeatablePlies :: InstancesByPosition position -> NPlies
countConsecutiveRepeatablePlies MkInstancesByPosition { getNBoardsByPosition :: forall position.
InstancesByPosition position -> NBoardsByPosition position
getNBoardsByPosition = NBoardsByPosition position
m } = (NPlies -> NPlies -> NPlies)
-> NPlies -> NBoardsByPosition position -> NPlies
forall a b k. (a -> b -> a) -> a -> Map k b -> a
Data.Map.Strict.foldl' NPlies -> NPlies -> NPlies
forall a. Num a => a -> a -> a
(+) (
NPlies -> NPlies
forall a. Num a => a -> a
negate NPlies
1
) NBoardsByPosition position
m
countPositionRepetitions :: InstancesByPosition position -> State.Board.NBoards
countPositionRepetitions :: InstancesByPosition position -> NPlies
countPositionRepetitions MkInstancesByPosition { getNBoardsByPosition :: forall position.
InstancesByPosition position -> NBoardsByPosition position
getNBoardsByPosition = NBoardsByPosition position
m } = (NPlies -> NPlies -> NPlies)
-> NPlies -> NBoardsByPosition position -> NPlies
forall a b k. (a -> b -> a) -> a -> Map k b -> a
Data.Map.Strict.foldl' (
NPlies -> NPlies -> NPlies
forall a. Num a => a -> a -> a
(+) (NPlies -> NPlies -> NPlies)
-> (NPlies -> NPlies) -> NPlies -> NPlies -> NPlies
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NPlies -> NPlies
forall a. Enum a => a -> a
pred
) NPlies
0 NBoardsByPosition position
m
getNDistinctPositions :: InstancesByPosition position -> State.Board.NBoards
getNDistinctPositions :: InstancesByPosition position -> NPlies
getNDistinctPositions MkInstancesByPosition { getNBoardsByPosition :: forall position.
InstancesByPosition position -> NBoardsByPosition position
getNBoardsByPosition = NBoardsByPosition position
m } = NBoardsByPosition position -> NPlies
forall k a. Map k a -> NPlies
Data.Map.Strict.size NBoardsByPosition position
m
anyInstancesByPosition
:: (State.Board.NBoards -> Bool)
-> InstancesByPosition position
-> Bool
anyInstancesByPosition :: (NPlies -> Bool) -> InstancesByPosition position -> Bool
anyInstancesByPosition NPlies -> Bool
predicate MkInstancesByPosition { getNBoardsByPosition :: forall position.
InstancesByPosition position -> NBoardsByPosition position
getNBoardsByPosition = NBoardsByPosition position
m } = (NPlies -> Bool) -> NBoardsByPosition position -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
Data.Foldable.any NPlies -> Bool
predicate NBoardsByPosition position
m
findMaximumInstances :: InstancesByPosition position -> State.Board.NBoards
findMaximumInstances :: InstancesByPosition position -> NPlies
findMaximumInstances MkInstancesByPosition { getNBoardsByPosition :: forall position.
InstancesByPosition position -> NBoardsByPosition position
getNBoardsByPosition = NBoardsByPosition position
m }
| NBoardsByPosition position -> Bool
forall k a. Map k a -> Bool
Data.Map.Strict.null NBoardsByPosition position
m = NPlies
0
| Bool
otherwise = NBoardsByPosition position -> NPlies
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
Data.Foldable.maximum NBoardsByPosition position
m
type Transformation position = InstancesByPosition position -> InstancesByPosition position
insertPosition
:: Ord position
=> Bool
-> position
-> Transformation position
insertPosition :: Bool -> position -> Transformation position
insertPosition Bool
isRepeatable position
position MkInstancesByPosition { getNBoardsByPosition :: forall position.
InstancesByPosition position -> NBoardsByPosition position
getNBoardsByPosition = NBoardsByPosition position
m }
| Bool
isRepeatable = NBoardsByPosition position -> InstancesByPosition position
forall position.
NBoardsByPosition position -> InstancesByPosition position
MkInstancesByPosition (NBoardsByPosition position -> InstancesByPosition position)
-> NBoardsByPosition position -> InstancesByPosition position
forall a b. (a -> b) -> a -> b
$ (NPlies -> NPlies -> NPlies)
-> position
-> NPlies
-> NBoardsByPosition position
-> NBoardsByPosition position
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
Data.Map.Strict.insertWith ((NPlies -> NPlies) -> NPlies -> NPlies -> NPlies
forall a b. a -> b -> a
const NPlies -> NPlies
forall a. Enum a => a -> a
succ) position
position NPlies
1 NBoardsByPosition position
m
| Bool
otherwise = position -> InstancesByPosition position
forall position. position -> InstancesByPosition position
mkSingleton position
position
deletePosition :: Ord position => position -> Transformation position
deletePosition :: position -> Transformation position
deletePosition position
position MkInstancesByPosition { getNBoardsByPosition :: forall position.
InstancesByPosition position -> NBoardsByPosition position
getNBoardsByPosition = NBoardsByPosition position
m } = NBoardsByPosition position -> InstancesByPosition position
forall position.
NBoardsByPosition position -> InstancesByPosition position
MkInstancesByPosition (NBoardsByPosition position -> InstancesByPosition position)
-> (NBoardsByPosition position -> NBoardsByPosition position)
-> NBoardsByPosition position
-> InstancesByPosition position
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (NPlies -> Maybe NPlies)
-> position
-> NBoardsByPosition position
-> NBoardsByPosition position
forall k a. Ord k => (a -> Maybe a) -> k -> Map k a -> Map k a
Data.Map.Strict.update (
\NPlies
n -> if NPlies
n NPlies -> NPlies -> Bool
forall a. Eq a => a -> a -> Bool
== NPlies
1
then Maybe NPlies
forall a. Maybe a
Nothing
else NPlies -> Maybe NPlies
forall a. a -> Maybe a
Just (NPlies -> Maybe NPlies) -> NPlies -> Maybe NPlies
forall a b. (a -> b) -> a -> b
$ NPlies -> NPlies
forall a. Enum a => a -> a
pred NPlies
n
) position
position (NBoardsByPosition position -> InstancesByPosition position)
-> NBoardsByPosition position -> InstancesByPosition position
forall a b. (a -> b) -> a -> b
$ Bool -> NBoardsByPosition position -> NBoardsByPosition position
forall a. (?callStack::CallStack) => Bool -> a -> a
Control.Exception.assert (position -> NBoardsByPosition position -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Data.Map.Strict.member position
position NBoardsByPosition position
m) NBoardsByPosition position
m