module MoveGen.PositionQueries (isDefeat, isNotWinnable, isDraw, isEndgame, isKingInCheck, hasSingleMove, isWonEndgame) where

import           AppPrelude

import           Models.Position
import           Search.Perft
import           Utils.Board


isEndgame :: Position -> Bool
isEndgame :: Position -> Bool
isEndgame Position {Phase
[ZKey]
Ply
Board
Color
previousPositions :: [ZKey]
halfMoveClock :: Ply
phase :: Phase
color :: Color
player :: Board
enemy :: Board
pawns :: Board
knights :: Board
bishops :: Board
rooks :: Board
queens :: Board
kings :: Board
enPassant :: Board
castling :: Board
attacked :: Board
leapingCheckers :: Board
sliderCheckers :: Board
pinnedPieces :: Board
$sel:previousPositions:Position :: Position -> [ZKey]
$sel:halfMoveClock:Position :: Position -> Ply
$sel:phase:Position :: Position -> Phase
$sel:color:Position :: Position -> Color
$sel:player:Position :: Position -> Board
$sel:enemy:Position :: Position -> Board
$sel:pawns:Position :: Position -> Board
$sel:knights:Position :: Position -> Board
$sel:bishops:Position :: Position -> Board
$sel:rooks:Position :: Position -> Board
$sel:queens:Position :: Position -> Board
$sel:kings:Position :: Position -> Board
$sel:enPassant:Position :: Position -> Board
$sel:castling:Position :: Position -> Board
$sel:attacked:Position :: Position -> Board
$sel:leapingCheckers:Position :: Position -> Board
$sel:sliderCheckers:Position :: Position -> Board
$sel:pinnedPieces:Position :: Position -> Board
..} =
  Board -> Int
popCount (Board
player Board -> Board -> Board
& Board
majorAndMinorPieces) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
  where
    majorAndMinorPieces :: Board
majorAndMinorPieces = Board
queens Board -> Board -> Board
.| Board
rooks Board -> Board -> Board
.| Board
bishops Board -> Board -> Board
.| Board
knights


isKingInCheck :: Position -> Bool
isKingInCheck :: Position -> Bool
isKingInCheck Position {Phase
[ZKey]
Ply
Board
Color
$sel:previousPositions:Position :: Position -> [ZKey]
$sel:halfMoveClock:Position :: Position -> Ply
$sel:phase:Position :: Position -> Phase
$sel:color:Position :: Position -> Color
$sel:player:Position :: Position -> Board
$sel:enemy:Position :: Position -> Board
$sel:pawns:Position :: Position -> Board
$sel:knights:Position :: Position -> Board
$sel:bishops:Position :: Position -> Board
$sel:rooks:Position :: Position -> Board
$sel:queens:Position :: Position -> Board
$sel:kings:Position :: Position -> Board
$sel:enPassant:Position :: Position -> Board
$sel:castling:Position :: Position -> Board
$sel:attacked:Position :: Position -> Board
$sel:leapingCheckers:Position :: Position -> Board
$sel:sliderCheckers:Position :: Position -> Board
$sel:pinnedPieces:Position :: Position -> Board
previousPositions :: [ZKey]
halfMoveClock :: Ply
phase :: Phase
color :: Color
player :: Board
enemy :: Board
pawns :: Board
knights :: Board
bishops :: Board
rooks :: Board
queens :: Board
kings :: Board
enPassant :: Board
castling :: Board
attacked :: Board
leapingCheckers :: Board
sliderCheckers :: Board
pinnedPieces :: Board
..} =
  Board
sliderCheckers Board -> Board -> Board
.| Board
leapingCheckers Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
/= Board
0


hasSingleMove :: Position -> Bool
hasSingleMove :: Position -> Bool
hasSingleMove = [Move] -> Bool
forall {a}. [a] -> Bool
hasOne ([Move] -> Bool) -> (Position -> [Move]) -> Position -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Position -> [Move]
allMoves
  where
  hasOne :: [a] -> Bool
hasOne [a
_] = Bool
True
  hasOne [a]
_   = Bool
False


isDefeat :: Position -> Bool
isDefeat :: Position -> Bool
isDefeat = Position -> Bool
isCheckmate


isNotWinnable :: Position -> Bool
isNotWinnable :: Position -> Bool
isNotWinnable Position {Phase
[ZKey]
Ply
Board
Color
$sel:previousPositions:Position :: Position -> [ZKey]
$sel:halfMoveClock:Position :: Position -> Ply
$sel:phase:Position :: Position -> Phase
$sel:color:Position :: Position -> Color
$sel:player:Position :: Position -> Board
$sel:enemy:Position :: Position -> Board
$sel:pawns:Position :: Position -> Board
$sel:knights:Position :: Position -> Board
$sel:bishops:Position :: Position -> Board
$sel:rooks:Position :: Position -> Board
$sel:queens:Position :: Position -> Board
$sel:kings:Position :: Position -> Board
$sel:enPassant:Position :: Position -> Board
$sel:castling:Position :: Position -> Board
$sel:attacked:Position :: Position -> Board
$sel:leapingCheckers:Position :: Position -> Board
$sel:sliderCheckers:Position :: Position -> Board
$sel:pinnedPieces:Position :: Position -> Board
previousPositions :: [ZKey]
halfMoveClock :: Ply
phase :: Phase
color :: Color
player :: Board
enemy :: Board
pawns :: Board
knights :: Board
bishops :: Board
rooks :: Board
queens :: Board
kings :: Board
enPassant :: Board
castling :: Board
attacked :: Board
leapingCheckers :: Board
sliderCheckers :: Board
pinnedPieces :: Board
..} =
  Board
player Board -> Board -> Board
& (Board
pawns Board -> Board -> Board
.| Board
majorPieces) Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
  Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
player Board -> Board -> Board
& Board
minorPieces) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1
  Bool -> Bool -> Bool
&& Board
enemy Board -> Board -> Board
& Board
pawns Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
/= Board
0
  where
    minorPieces :: Board
minorPieces = Board
bishops Board -> Board -> Board
.| Board
knights
    majorPieces :: Board
majorPieces = Board
queens  Board -> Board -> Board
.| Board
rooks


isDraw :: Position -> Bool
isDraw :: Position -> Bool
isDraw Position
pos =
    Position -> Bool
isDrawByHalfMoves Position
pos
  Bool -> Bool -> Bool
|| Position -> Bool
isPawnlessEndgame Position
pos Bool -> Bool -> Bool
&& Position -> Bool
isDrawByMaterial Position
pos
  Bool -> Bool -> Bool
|| Position -> Bool
isStalemate Position
pos
  Bool -> Bool -> Bool
|| Position -> Bool
isDrawByRepetition Position
pos


isCheckmate :: Position -> Bool
isCheckmate :: Position -> Bool
isCheckmate Position
pos = [Move] -> Bool
forall mono. MonoFoldable mono => mono -> Bool
null (Position -> [Move]
allMoves Position
pos) Bool -> Bool -> Bool
&& Position -> Bool
isKingInCheck Position
pos


isStalemate :: Position -> Bool
isStalemate :: Position -> Bool
isStalemate Position
pos = [Move] -> Bool
forall mono. MonoFoldable mono => mono -> Bool
null (Position -> [Move]
allMoves Position
pos) Bool -> Bool -> Bool
&& Bool -> Bool
not (Position -> Bool
isKingInCheck Position
pos)


isDrawByHalfMoves :: Position -> Bool
isDrawByHalfMoves :: Position -> Bool
isDrawByHalfMoves Position {Ply
$sel:halfMoveClock:Position :: Position -> Ply
halfMoveClock :: Ply
halfMoveClock} =
  Ply
halfMoveClock Ply -> Ply -> Bool
forall a. Ord a => a -> a -> Bool
>= Ply
100


isDrawByRepetition :: Position -> Bool
isDrawByRepetition :: Position -> Bool
isDrawByRepetition Position
pos =
  ZKey -> Position -> Bool
isRepeatedPosition (Position -> ZKey
getZobristKey Position
pos) Position
pos


isDrawByMaterial :: Position -> Bool
isDrawByMaterial :: Position -> Bool
isDrawByMaterial Position {Phase
[ZKey]
Ply
Board
Color
$sel:previousPositions:Position :: Position -> [ZKey]
$sel:halfMoveClock:Position :: Position -> Ply
$sel:phase:Position :: Position -> Phase
$sel:color:Position :: Position -> Color
$sel:player:Position :: Position -> Board
$sel:enemy:Position :: Position -> Board
$sel:pawns:Position :: Position -> Board
$sel:knights:Position :: Position -> Board
$sel:bishops:Position :: Position -> Board
$sel:rooks:Position :: Position -> Board
$sel:queens:Position :: Position -> Board
$sel:kings:Position :: Position -> Board
$sel:enPassant:Position :: Position -> Board
$sel:castling:Position :: Position -> Board
$sel:attacked:Position :: Position -> Board
$sel:leapingCheckers:Position :: Position -> Board
$sel:sliderCheckers:Position :: Position -> Board
$sel:pinnedPieces:Position :: Position -> Board
previousPositions :: [ZKey]
halfMoveClock :: Ply
phase :: Phase
color :: Color
player :: Board
enemy :: Board
pawns :: Board
knights :: Board
bishops :: Board
rooks :: Board
queens :: Board
kings :: Board
enPassant :: Board
castling :: Board
attacked :: Board
leapingCheckers :: Board
sliderCheckers :: Board
pinnedPieces :: Board
..} =

   Board
allPieces Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
majorPieces Board -> Board -> Board
.| Board
minorPieces Bool -> Bool -> Bool
&&
     (Board -> Board -> Bool) -> Bool
forBoth Board -> Board -> Bool
queenVsRookAndMinor

  Bool -> Bool -> Bool
|| Board
allPieces Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
majorPieces Bool -> Bool -> Bool
&&
    (Board -> Board -> Bool) -> Bool
forBoth Board -> Board -> Bool
queenVsRooks

  Bool -> Bool -> Bool
|| Board
allPieces Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
queens Bool -> Bool -> Bool
&&
    (Board -> Int
popCount (Board
player Board -> Board -> Board
& Board
queens) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
    Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemy Board -> Board -> Board
& Board
queens) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1)

  Bool -> Bool -> Bool
|| Board
allPieces Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
rooks Bool -> Bool -> Bool
&&
    (Board -> Int
popCount (Board
player Board -> Board -> Board
& Board
rooks) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
    Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemy Board -> Board -> Board
& Board
rooks) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1)

  Bool -> Bool -> Bool
|| Board
allPieces Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
queens Board -> Board -> Board
.| Board
minorPieces Bool -> Bool -> Bool
&&
    ((Board -> Board -> Bool) -> Bool
forBoth Board -> Board -> Bool
queenVsBishops
    Bool -> Bool -> Bool
|| (Board -> Board -> Bool) -> Bool
forBoth Board -> Board -> Bool
queenVsKnights)

  Bool -> Bool -> Bool
|| Board
allPieces Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
rooks Board -> Board -> Board
.| Board
minorPieces Bool -> Bool -> Bool
&&
    ((Board -> Board -> Bool) -> Bool
forBoth Board -> Board -> Bool
rooksVsRookAndMinor
    Bool -> Bool -> Bool
|| (Board -> Board -> Bool) -> Bool
forBoth Board -> Board -> Bool
rooksVsRookBishopAndKnight
    Bool -> Bool -> Bool
|| (Board -> Board -> Bool) -> Bool
forBoth Board -> Board -> Bool
rookVsMinor
    Bool -> Bool -> Bool
|| (Board -> Board -> Bool) -> Bool
forBoth Board -> Board -> Bool
rookAndMinorVsRook
    Bool -> Bool -> Bool
|| (Board -> Board -> Bool) -> Bool
forBoth Board -> Board -> Bool
rookVsBishopAndKnight)

  Bool -> Bool -> Bool
|| Board
allPieces Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
minorPieces Bool -> Bool -> Bool
&&

    ((Int
playerMinorPiecesCount Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1
        Bool -> Bool -> Bool
&& Int
enemyMinorPiecesCount Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1)

    Bool -> Bool -> Bool
|| (Board -> Int
popCount Board
bishops Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
3 Bool -> Bool -> Bool
&& Board
knights Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0)

    Bool -> Bool -> Bool
|| (Board -> Board -> Bool) -> Bool
forBoth Board -> Board -> Bool
knightsVsMinor

    Bool -> Bool -> Bool
|| (Board -> Board -> Bool) -> Bool
forBoth Board -> Board -> Bool
bishopAndKnightVsMinor)

  where
    knightsVsMinor :: Board -> Board -> Bool
knightsVsMinor !Board
board !Board
enemyBoard =
      Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
knights)              Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
2
        Bool -> Bool -> Bool
&& Board
board Board -> Board -> Board
& Board
bishops                     Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
        Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
minorPieces) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1

    bishopAndKnightVsMinor :: Board -> Board -> Bool
bishopAndKnightVsMinor !Board
board !Board
enemyBoard =
      Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
bishops)              Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
        Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
knights)          Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
        Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
minorPieces) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1

    queenVsRooks :: Board -> Board -> Bool
queenVsRooks !Board
board !Board
enemyBoard =
      Board
board Board -> Board -> Board
& Board
rooks                     Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
        Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
queens)     Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
        Bool -> Bool -> Bool
&& Board
enemyBoard Board -> Board -> Board
& Board
queens           Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
        Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
rooks) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2

    rookVsMinor :: Board -> Board -> Bool
rookVsMinor !Board
board !Board
enemyBoard =
      Board
board Board -> Board -> Board
& Board
minorPieces                    Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
       Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
rooks)            Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
       Bool -> Bool -> Bool
&& Board
enemyBoard Board -> Board -> Board
& Board
rooks                  Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
       Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
minorPieces) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1

    rookAndMinorVsRook :: Board -> Board -> Bool
rookAndMinorVsRook !Board
board !Board
enemyBoard =
      Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
rooks)         Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
minorPieces) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
rooks)  Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
      Bool -> Bool -> Bool
&& Board
enemyBoard Board -> Board -> Board
& Board
minorPieces       Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0

    rookVsBishopAndKnight :: Board -> Board -> Bool
rookVsBishopAndKnight !Board
board !Board
enemyBoard =
      Board
board Board -> Board -> Board
& Board
rooks                Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
bishops) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
knights) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
      Bool -> Bool -> Bool
&& Board
enemyBoard Board -> Board -> Board
& Board
minorPieces   Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
rooks)   Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1

    queenVsRookAndMinor :: Board -> Board -> Bool
queenVsRookAndMinor !Board
board !Board
enemyBoard =
      Board
board Board -> Board -> Board
& (Board
rooks Board -> Board -> Board
.| Board
minorPieces)        Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
queens)           Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
      Bool -> Bool -> Bool
&& Board
enemyBoard Board -> Board -> Board
& Board
queens                 Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
rooks)       Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
minorPieces) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1

    rooksVsRookAndMinor :: Board -> Board -> Bool
rooksVsRookAndMinor !Board
board !Board
enemyBoard =
      Board
board Board -> Board -> Board
& Board
minorPieces        Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
rooks)           Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
rooks)       Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
minorPieces) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1

    rooksVsRookBishopAndKnight :: Board -> Board -> Bool
rooksVsRookBishopAndKnight !Board
board !Board
enemyBoard =
      Board
board Board -> Board -> Board
& Board
minorPieces               Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
rooks)        Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
rooks)   Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
knights) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
rooks)   Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1

    queenVsKnights :: Board -> Board -> Bool
queenVsKnights !Board
board !Board
enemyBoard =
      Board
board Board -> Board -> Board
& Board
minorPieces Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
queens) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
      Bool -> Bool -> Bool
&& Board
enemyBoard Board -> Board -> Board
& (Board
queens Board -> Board -> Board
.| Board
bishops) Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
knights) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2

    queenVsBishops :: Board -> Board -> Bool
queenVsBishops !Board
board !Board
enemyBoard =
      Board
board Board -> Board -> Board
& Board
minorPieces Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
board Board -> Board -> Board
& Board
queens) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
      Bool -> Bool -> Bool
&& Board
enemyBoard Board -> Board -> Board
& (Board
queens Board -> Board -> Board
.| Board
knights) Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0
      Bool -> Bool -> Bool
&& Board -> Int
popCount (Board
enemyBoard Board -> Board -> Board
& Board
bishops) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2


    !playerMinorPiecesCount :: Int
playerMinorPiecesCount = Board -> Int
popCount (Board
player Board -> Board -> Board
& Board
minorPieces)
    !enemyMinorPiecesCount :: Int
enemyMinorPiecesCount  = Board -> Int
popCount (Board
enemy  Board -> Board -> Board
& Board
minorPieces)
    !allPieces :: Board
allPieces              = (Board
player Board -> Board -> Board
.| Board
enemy) Board -> Board -> Board
.\ Board
kings
    !minorPieces :: Board
minorPieces            = Board
knights Board -> Board -> Board
.| Board
bishops
    !majorPieces :: Board
majorPieces            = Board
rooks   Board -> Board -> Board
.| Board
queens
    forBoth :: (Board -> Board -> Bool) -> Bool
forBoth Board -> Board -> Bool
fn = Board -> Board -> Bool
fn Board
player Board
enemy Bool -> Bool -> Bool
|| Board -> Board -> Bool
fn Board
enemy Board
player


isWonEndgame :: Position -> Bool
isWonEndgame :: Position -> Bool
isWonEndgame Position {Phase
[ZKey]
Ply
Board
Color
$sel:previousPositions:Position :: Position -> [ZKey]
$sel:halfMoveClock:Position :: Position -> Ply
$sel:phase:Position :: Position -> Phase
$sel:color:Position :: Position -> Color
$sel:player:Position :: Position -> Board
$sel:enemy:Position :: Position -> Board
$sel:pawns:Position :: Position -> Board
$sel:knights:Position :: Position -> Board
$sel:bishops:Position :: Position -> Board
$sel:rooks:Position :: Position -> Board
$sel:queens:Position :: Position -> Board
$sel:kings:Position :: Position -> Board
$sel:enPassant:Position :: Position -> Board
$sel:castling:Position :: Position -> Board
$sel:attacked:Position :: Position -> Board
$sel:leapingCheckers:Position :: Position -> Board
$sel:sliderCheckers:Position :: Position -> Board
$sel:pinnedPieces:Position :: Position -> Board
previousPositions :: [ZKey]
halfMoveClock :: Ply
phase :: Phase
color :: Color
player :: Board
enemy :: Board
pawns :: Board
knights :: Board
bishops :: Board
rooks :: Board
queens :: Board
kings :: Board
enPassant :: Board
castling :: Board
attacked :: Board
leapingCheckers :: Board
sliderCheckers :: Board
pinnedPieces :: Board
..} = Board
enemy Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
enemy Board -> Board -> Board
& Board
kings
  Bool -> Bool -> Bool
&& (Board
player Board -> Board -> Board
& Board
majorPieces Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
/= Board
0
     Bool -> Bool -> Bool
|| Board -> Int
popCount (Board
player Board -> Board -> Board
& Board
minorPieces) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2 Bool -> Bool -> Bool
&& Board
bishops Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
/= Board
0)
  where
  !minorPieces :: Board
minorPieces      = Board
knights Board -> Board -> Board
.| Board
bishops
  !majorPieces :: Board
majorPieces      = Board
rooks   Board -> Board -> Board
.| Board
queens


isPawnlessEndgame :: Position -> Bool
isPawnlessEndgame :: Position -> Bool
isPawnlessEndgame Position {Phase
[ZKey]
Ply
Board
Color
$sel:previousPositions:Position :: Position -> [ZKey]
$sel:halfMoveClock:Position :: Position -> Ply
$sel:phase:Position :: Position -> Phase
$sel:color:Position :: Position -> Color
$sel:player:Position :: Position -> Board
$sel:enemy:Position :: Position -> Board
$sel:pawns:Position :: Position -> Board
$sel:knights:Position :: Position -> Board
$sel:bishops:Position :: Position -> Board
$sel:rooks:Position :: Position -> Board
$sel:queens:Position :: Position -> Board
$sel:kings:Position :: Position -> Board
$sel:enPassant:Position :: Position -> Board
$sel:castling:Position :: Position -> Board
$sel:attacked:Position :: Position -> Board
$sel:leapingCheckers:Position :: Position -> Board
$sel:sliderCheckers:Position :: Position -> Board
$sel:pinnedPieces:Position :: Position -> Board
previousPositions :: [ZKey]
halfMoveClock :: Ply
phase :: Phase
color :: Color
player :: Board
enemy :: Board
pawns :: Board
knights :: Board
bishops :: Board
rooks :: Board
queens :: Board
kings :: Board
enPassant :: Board
castling :: Board
attacked :: Board
leapingCheckers :: Board
sliderCheckers :: Board
pinnedPieces :: Board
..} =
  Board
pawns Board -> Board -> Bool
forall a. Eq a => a -> a -> Bool
== Board
0