turncoat-1.0: src/MoveGen/PieceQuietMoves.hs
module MoveGen.PieceQuietMoves (allQuietMoves) where
import AppPrelude
import Models.Move
import Models.Piece
import Models.Position
import MoveGen.PieceAttacks
import MoveGen.PieceCaptures
import Utils.Board
-- Quiet moves legal move generator:
-- - Non capture moves except for pawn promotions
allQuietMoves :: Position -> [Move]
allQuietMoves pos@Position {..}
| allCheckers == 0 = genMoves id
| leapingCheckers /= 0 || popCount allCheckers > 1 = allKingMoves
| otherwise = genMoves blockChecker
where
genMoves = quietMovesHelper allPieces king allKingMoves pos
blockChecker board = board & checkerRay
checkerRay = getKingQueenRay king checkerSquare
& queenAttacks allPieces kingSquare
& queenAttacks allPieces checkerSquare
checkerSquare = lsb allCheckers
allKingMoves =
foldBoardSquares King
(kingQuietMoves allPieces attacked castling (player&rooks) king) [] kingSquare
allCheckers = leapingCheckers .| sliderCheckers
allPieces = player .| enemy
kingSquare = lsb king
king = player&kings
quietMovesHelper :: Board -> Board -> [Move] -> Position -> (Board -> Board)
-> [Move]
quietMovesHelper allPieces king allKingMoves Position {..} !f =
foldBoardMoves Pawn (f . pawnAdvances noPieces color
. toBoard)
(unpinned&pawns .| filePinnedPawns)
$ foldBoardMoves Knight (f . knightCaptures noPieces)
(unpinned&knights)
$ foldBoardMoves Bishop (f . bishopQuietMoves noPieces
allPieces pinnedPieces king)
(player&bishops)
$ foldBoardMoves Rook (f . rookQuietMoves noPieces
allPieces pinnedPieces king)
(player&rooks)
$ foldBoardMoves Queen (f . queenQuietMoves noPieces
allPieces pinnedPieces king)
(player&queens)
allKingMoves
where
unpinned = player .\ pinnedPieces
pinnedPawns = pinnedPieces & pawns
filePinnedPawns = pinnedPawns & kingFile
kingFile = rankMovesVec !! kingSquare
kingSquare = lsb king
noPieces = (~) allPieces
pawnAdvances :: Board -> Color -> Board -> Board
pawnAdvances noPieces color board = advances & noPieces
where
advances = case color of
White -> (board .\ rank_7) << 8
.| ((board & rank_2) << 8 & noPieces) << 8
Black -> (board .\ rank_2) >> 8
.| ((board & rank_7) >> 8 & noPieces) >> 8
bishopQuietMoves :: Board -> Board -> Board -> Board -> Square -> Board
bishopQuietMoves noPieces allPieces pinnedPieces king n =
bishopMoves allPieces pinnedPieces king n & noPieces
rookQuietMoves :: Board -> Board -> Board -> Board -> Square -> Board
rookQuietMoves noPieces allPieces pinnedPieces king n =
rookMoves allPieces pinnedPieces king n & noPieces
queenQuietMoves :: Board -> Board -> Board -> Board -> Square -> Board
queenQuietMoves noPieces allPieces pinnedPieces king n =
queenMoves allPieces pinnedPieces king n & noPieces
kingQuietMoves :: Board -> Board -> Board -> Board -> Board -> Square -> Board
kingQuietMoves allPieces attacked castling rooks king n =
(kingAttacks n
.| kingCastlingMoves allPieces attacked castling rooks king n)
.\ (attacked .| allPieces)
kingCastlingMoves :: Board -> Board -> Board -> Board -> Board -> Square -> Board
kingCastlingMoves allPieces attacked castling rooks king n =
(shortCastlingCond
* fromIntegral (popCount (castling & rooks & file_H))
* ((castling & king) << 2))
.|
(longCastlingCond
* fromIntegral (popCount (castling & rooks & file_A))
* ((castling & king) >> 2))
where
shortCastlingCond =
toReverseCondition (shortCastleSlidingFiles & collisions .| inCheck)
longCastlingCond =
toReverseCondition (longCastleSlidingFiles & collisions
.| inCheck
.| allPieces & kingRank & file_B)
collisions = kingRank & (attacked .| allPieces)
kingRank = fileMovesVec !! n
inCheck = king & attacked