module BishBosh.State.EnPassantAbscissa (
EnPassantAbscissa(getAbscissa),
mkMaybeEnPassantAbscissa
) where
import qualified BishBosh.Attribute.LogicalColour as Attribute.LogicalColour
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.Component.QualifiedMove as Component.QualifiedMove
import qualified BishBosh.Component.Turn as Component.Turn
import qualified BishBosh.Component.Zobrist as Component.Zobrist
import qualified BishBosh.Property.FixedMembership as Property.FixedMembership
import qualified BishBosh.Property.Opposable as Property.Opposable
import qualified BishBosh.State.MaybePieceByCoordinates as State.MaybePieceByCoordinates
import qualified BishBosh.StateProperty.Hashable as StateProperty.Hashable
import qualified BishBosh.Type.Length as Type.Length
import qualified Control.DeepSeq
import qualified Data.Maybe
newtype EnPassantAbscissa = MkEnPassantAbscissa {
EnPassantAbscissa -> X
getAbscissa :: Type.Length.X
} deriving (EnPassantAbscissa -> EnPassantAbscissa -> Bool
(EnPassantAbscissa -> EnPassantAbscissa -> Bool)
-> (EnPassantAbscissa -> EnPassantAbscissa -> Bool)
-> Eq EnPassantAbscissa
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: EnPassantAbscissa -> EnPassantAbscissa -> Bool
$c/= :: EnPassantAbscissa -> EnPassantAbscissa -> Bool
== :: EnPassantAbscissa -> EnPassantAbscissa -> Bool
$c== :: EnPassantAbscissa -> EnPassantAbscissa -> Bool
Eq, Eq EnPassantAbscissa
Eq EnPassantAbscissa
-> (EnPassantAbscissa -> EnPassantAbscissa -> Ordering)
-> (EnPassantAbscissa -> EnPassantAbscissa -> Bool)
-> (EnPassantAbscissa -> EnPassantAbscissa -> Bool)
-> (EnPassantAbscissa -> EnPassantAbscissa -> Bool)
-> (EnPassantAbscissa -> EnPassantAbscissa -> Bool)
-> (EnPassantAbscissa -> EnPassantAbscissa -> EnPassantAbscissa)
-> (EnPassantAbscissa -> EnPassantAbscissa -> EnPassantAbscissa)
-> Ord EnPassantAbscissa
EnPassantAbscissa -> EnPassantAbscissa -> Bool
EnPassantAbscissa -> EnPassantAbscissa -> Ordering
EnPassantAbscissa -> EnPassantAbscissa -> EnPassantAbscissa
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: EnPassantAbscissa -> EnPassantAbscissa -> EnPassantAbscissa
$cmin :: EnPassantAbscissa -> EnPassantAbscissa -> EnPassantAbscissa
max :: EnPassantAbscissa -> EnPassantAbscissa -> EnPassantAbscissa
$cmax :: EnPassantAbscissa -> EnPassantAbscissa -> EnPassantAbscissa
>= :: EnPassantAbscissa -> EnPassantAbscissa -> Bool
$c>= :: EnPassantAbscissa -> EnPassantAbscissa -> Bool
> :: EnPassantAbscissa -> EnPassantAbscissa -> Bool
$c> :: EnPassantAbscissa -> EnPassantAbscissa -> Bool
<= :: EnPassantAbscissa -> EnPassantAbscissa -> Bool
$c<= :: EnPassantAbscissa -> EnPassantAbscissa -> Bool
< :: EnPassantAbscissa -> EnPassantAbscissa -> Bool
$c< :: EnPassantAbscissa -> EnPassantAbscissa -> Bool
compare :: EnPassantAbscissa -> EnPassantAbscissa -> Ordering
$ccompare :: EnPassantAbscissa -> EnPassantAbscissa -> Ordering
$cp1Ord :: Eq EnPassantAbscissa
Ord)
instance Control.DeepSeq.NFData EnPassantAbscissa where
rnf :: EnPassantAbscissa -> ()
rnf MkEnPassantAbscissa { getAbscissa :: EnPassantAbscissa -> X
getAbscissa = X
x } = X -> ()
forall a. NFData a => a -> ()
Control.DeepSeq.rnf X
x
instance StateProperty.Hashable.Hashable EnPassantAbscissa where
listRandoms :: EnPassantAbscissa -> Zobrist positionHash -> [positionHash]
listRandoms MkEnPassantAbscissa { getAbscissa :: EnPassantAbscissa -> X
getAbscissa = X
x } = positionHash -> [positionHash]
forall (m :: * -> *) a. Monad m => a -> m a
return (positionHash -> [positionHash])
-> (Zobrist positionHash -> positionHash)
-> Zobrist positionHash
-> [positionHash]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. X -> Zobrist positionHash -> positionHash
forall positionHash. X -> Zobrist positionHash -> positionHash
Component.Zobrist.dereferenceRandomByEnPassantAbscissa X
x
mkMaybeEnPassantAbscissa
:: Attribute.LogicalColour.LogicalColour
-> State.MaybePieceByCoordinates.MaybePieceByCoordinates
-> Component.Turn.Turn
-> Maybe EnPassantAbscissa
mkMaybeEnPassantAbscissa :: LogicalColour
-> MaybePieceByCoordinates -> Turn -> Maybe EnPassantAbscissa
mkMaybeEnPassantAbscissa LogicalColour
nextLogicalColour MaybePieceByCoordinates
maybePieceByCoordinates Turn
lastTurn
| LogicalColour -> Turn -> Bool
Component.Turn.isPawnDoubleAdvance (LogicalColour -> LogicalColour
forall a. Opposable a => a -> a
Property.Opposable.getOpposite LogicalColour
nextLogicalColour) Turn
lastTurn
, let lastMoveDestination :: Coordinates
lastMoveDestination = Move -> Coordinates
Component.Move.getDestination (Move -> Coordinates)
-> (QualifiedMove -> Move) -> QualifiedMove -> Coordinates
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QualifiedMove -> Move
Component.QualifiedMove.getMove (QualifiedMove -> Coordinates) -> QualifiedMove -> Coordinates
forall a b. (a -> b) -> a -> b
$ Turn -> QualifiedMove
Component.Turn.getQualifiedMove Turn
lastTurn
, Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [Piece] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [
Piece
passedPawn |
Coordinates
adjacentCoordinates <- Coordinates -> [Coordinates]
Cartesian.Coordinates.getAdjacents Coordinates
lastMoveDestination,
LogicalColour -> Piece
Component.Piece.mkKing LogicalColour
nextLogicalColour Piece -> [Piece] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [
Piece
blockingPiece |
Direction
threatDirection <- [Direction]
forall a. FixedMembership a => [a]
Property.FixedMembership.members,
(Coordinates
_, Rank
attackerRank) <- Maybe (Coordinates, Rank) -> [(Coordinates, Rank)]
forall a. Maybe a -> [a]
Data.Maybe.maybeToList (Maybe (Coordinates, Rank) -> [(Coordinates, Rank)])
-> Maybe (Coordinates, Rank) -> [(Coordinates, Rank)]
forall a b. (a -> b) -> a -> b
$ LogicalColour
-> Direction
-> Coordinates
-> MaybePieceByCoordinates
-> Maybe (Coordinates, Rank)
State.MaybePieceByCoordinates.findAttackerInDirection LogicalColour
nextLogicalColour Direction
threatDirection Coordinates
adjacentCoordinates MaybePieceByCoordinates
maybePieceByCoordinates,
Rank
attackerRank Rank -> [Rank] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Rank]
Attribute.Rank.fixedAttackRange,
(Coordinates
_, Piece
blockingPiece) <- Maybe (Coordinates, Piece) -> [(Coordinates, Piece)]
forall a. Maybe a -> [a]
Data.Maybe.maybeToList (Maybe (Coordinates, Piece) -> [(Coordinates, Piece)])
-> Maybe (Coordinates, Piece) -> [(Coordinates, Piece)]
forall a b. (a -> b) -> a -> b
$ Direction
-> Coordinates
-> MaybePieceByCoordinates
-> Maybe (Coordinates, Piece)
State.MaybePieceByCoordinates.findBlockingPiece (Direction -> Direction
forall a. Opposable a => a -> a
Property.Opposable.getOpposite Direction
threatDirection) Coordinates
adjacentCoordinates MaybePieceByCoordinates
maybePieceByCoordinates
],
Piece
passedPawn <- (Piece -> Bool) -> [Piece] -> [Piece]
forall a. (a -> Bool) -> [a] -> [a]
filter (Piece -> Piece -> Bool
forall a. Eq a => a -> a -> Bool
== LogicalColour -> Piece
Component.Piece.mkPawn LogicalColour
nextLogicalColour) ([Piece] -> [Piece])
-> (Maybe Piece -> [Piece]) -> Maybe Piece -> [Piece]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Piece -> [Piece]
forall a. Maybe a -> [a]
Data.Maybe.maybeToList (Maybe Piece -> [Piece]) -> Maybe Piece -> [Piece]
forall a b. (a -> b) -> a -> b
$ Coordinates -> MaybePieceByCoordinates -> Maybe Piece
State.MaybePieceByCoordinates.dereference Coordinates
adjacentCoordinates MaybePieceByCoordinates
maybePieceByCoordinates
] = EnPassantAbscissa -> Maybe EnPassantAbscissa
forall a. a -> Maybe a
Just (EnPassantAbscissa -> Maybe EnPassantAbscissa)
-> (X -> EnPassantAbscissa) -> X -> Maybe EnPassantAbscissa
forall b c a. (b -> c) -> (a -> b) -> a -> c
. X -> EnPassantAbscissa
MkEnPassantAbscissa (X -> Maybe EnPassantAbscissa) -> X -> Maybe EnPassantAbscissa
forall a b. (a -> b) -> a -> b
$ Coordinates -> X
Cartesian.Coordinates.getX Coordinates
lastMoveDestination
| Bool
otherwise = Maybe EnPassantAbscissa
forall a. Maybe a
Nothing