module MoveGen.MakeMove (makeMove, makeNullMove) where import AppPrelude import Models.Move import Models.Piece import Models.Position import MoveGen.PieceAttacks import Utils.Board makeMove :: Move -> Position -> Position makeMove :: Move -> Position -> Position makeMove Move {Square Promotion Piece piece :: Piece promotion :: Promotion start :: Square end :: Square $sel:piece:Move :: Move -> Piece $sel:promotion:Move :: Move -> Promotion $sel:start:Move :: Move -> Square $sel:end:Move :: Move -> Square ..} Position pos = Position -> Position makeNullMove (Position -> Position) -> Position -> Position forall a b. (a -> b) -> a -> b $ Piece -> Promotion -> Board -> Board -> Position -> Position movePiece Piece piece Promotion promotion Board startBoard Board endBoard (Position -> Position) -> Position -> Position forall a b. (a -> b) -> a -> b $ Board -> Board -> Position -> Position updatePlayerBoards Board startBoard Board endBoard Position pos where !startBoard :: Board startBoard = Square -> Board toBoard Square start !endBoard :: Board endBoard = Square -> Board toBoard Square end makeNullMove :: Position -> Position makeNullMove :: Position -> Position makeNullMove pos :: Position pos@Position {Color color :: Color $sel:color:Position :: Position -> Color color, Board player :: Board $sel:player:Position :: Position -> Board player, Board enemy :: Board $sel:enemy:Position :: Position -> Board enemy, Board enPassant :: Board $sel:enPassant:Position :: Position -> Board enPassant} = Position pos { color = reverseColor color , phase = getPhase pos , player = enemy , enemy = player , attacked = allAttacks pos , enPassant = toReverseCondition enPassantPinnedPawns * enPassant , leapingCheckers = getLeapingCheckers pos , sliderCheckers = getSliderCheckers bishopCheckerRays rookCheckerRays pos , pinnedPieces = getPinnedPieces bishopCheckerRays rookCheckerRays sliderRays pos } where bishopCheckerRays :: Board bishopCheckerRays = Position -> Board getBishopCheckerRays Position pos rookCheckerRays :: Board rookCheckerRays = Position -> Board getRookCheckerRays Position pos sliderRays :: Board sliderRays = Position -> Board getEnemyKingSliderRays Position pos enPassantPinnedPawns :: Board enPassantPinnedPawns = Position -> Board getEnPassantPinnedPawns Position pos updatePlayerBoards :: Board -> Board -> Position -> Position updatePlayerBoards :: Board -> Board -> Position -> Position updatePlayerBoards Board start Board end pos :: Position pos@Position {Phase [ZKey] Ply Board Color $sel:color:Position :: Position -> Color $sel:player:Position :: Position -> Board $sel:enemy:Position :: Position -> Board $sel:enPassant:Position :: Position -> Board $sel:phase:Position :: Position -> Phase $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 $sel:previousPositions:Position :: Position -> [ZKey] $sel:halfMoveClock:Position :: Position -> Ply $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:castling:Position :: Position -> Board ..} = Position pos { previousPositions = getZobristKey pos : if halfMoveClock == 0 then [] else previousPositions , halfMoveClock = fromIntegral (toReverseCondition (enemy & end)) * (halfMoveClock + 1) , player = (player ^ start) .| end , enemy = enemy .\ end , pawns = pawns .\ end , knights = knights .\ end , bishops = bishops .\ end , rooks = rooks .\ end , queens = queens .\ end } movePiece :: Piece -> Promotion -> Board -> Board -> Position -> Position movePiece :: Piece -> Promotion -> Board -> Board -> Position -> Position movePiece Piece Pawn Promotion NoProm Board start Board end pos :: Position pos@Position {Phase [ZKey] Ply Board Color $sel:color:Position :: Position -> Color $sel:player:Position :: Position -> Board $sel:enemy:Position :: Position -> Board $sel:enPassant:Position :: Position -> Board $sel:phase:Position :: Position -> Phase $sel:attacked:Position :: Position -> Board $sel:leapingCheckers:Position :: Position -> Board $sel:sliderCheckers:Position :: Position -> Board $sel:pinnedPieces:Position :: Position -> Board $sel:previousPositions:Position :: Position -> [ZKey] $sel:halfMoveClock:Position :: Position -> Ply $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:castling: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 ..} = Position pos { halfMoveClock = 0 , pawns = (pawns ^ (start .| enPassantCapture)) .| end , enemy = enemy ^ enPassantCapture , enPassant = start <<! 8 & end !>> 8 } where (Board -> Square -> Board (<<!), Board -> Square -> Board (!>>)) = case Color color of Color White -> (Board -> Square -> Board forall a. Bits a => a -> Square -> a (<<), Board -> Square -> Board forall a. Bits a => a -> Square -> a (>>)) Color Black -> (Board -> Square -> Board forall a. Bits a => a -> Square -> a (>>), Board -> Square -> Board forall a. Bits a => a -> Square -> a (<<)) enPassantCapture :: Board enPassantCapture = (Board enPassant Board -> Board -> Board & Board end) Board -> Square -> Board !>> Square 8 movePiece Piece Pawn Promotion KnightProm Board start Board end pos :: Position pos@Position {Phase [ZKey] Ply Board Color $sel:color:Position :: Position -> Color $sel:player:Position :: Position -> Board $sel:enemy:Position :: Position -> Board $sel:enPassant:Position :: Position -> Board $sel:phase:Position :: Position -> Phase $sel:attacked:Position :: Position -> Board $sel:leapingCheckers:Position :: Position -> Board $sel:sliderCheckers:Position :: Position -> Board $sel:pinnedPieces:Position :: Position -> Board $sel:previousPositions:Position :: Position -> [ZKey] $sel:halfMoveClock:Position :: Position -> Ply $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:castling: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 ..} = Position pos { halfMoveClock = 0 , pawns = pawns ^ start , knights = knights .| end , enPassant = 0 } movePiece Piece Pawn Promotion BishopProm Board start Board end pos :: Position pos@Position {Phase [ZKey] Ply Board Color $sel:color:Position :: Position -> Color $sel:player:Position :: Position -> Board $sel:enemy:Position :: Position -> Board $sel:enPassant:Position :: Position -> Board $sel:phase:Position :: Position -> Phase $sel:attacked:Position :: Position -> Board $sel:leapingCheckers:Position :: Position -> Board $sel:sliderCheckers:Position :: Position -> Board $sel:pinnedPieces:Position :: Position -> Board $sel:previousPositions:Position :: Position -> [ZKey] $sel:halfMoveClock:Position :: Position -> Ply $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:castling: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 ..} = Position pos { halfMoveClock = 0 , pawns = pawns ^ start , bishops = bishops .| end , enPassant = 0 } movePiece Piece Pawn Promotion RookProm !Board start !Board end pos :: Position pos@Position {Phase [ZKey] Ply Board Color $sel:color:Position :: Position -> Color $sel:player:Position :: Position -> Board $sel:enemy:Position :: Position -> Board $sel:enPassant:Position :: Position -> Board $sel:phase:Position :: Position -> Phase $sel:attacked:Position :: Position -> Board $sel:leapingCheckers:Position :: Position -> Board $sel:sliderCheckers:Position :: Position -> Board $sel:pinnedPieces:Position :: Position -> Board $sel:previousPositions:Position :: Position -> [ZKey] $sel:halfMoveClock:Position :: Position -> Ply $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:castling: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 ..} = Position pos { halfMoveClock = 0 , pawns = pawns ^ start , rooks = rooks .| end , enPassant = 0 } movePiece Piece Pawn Promotion QueenProm Board start Board end pos :: Position pos@Position {Phase [ZKey] Ply Board Color $sel:color:Position :: Position -> Color $sel:player:Position :: Position -> Board $sel:enemy:Position :: Position -> Board $sel:enPassant:Position :: Position -> Board $sel:phase:Position :: Position -> Phase $sel:attacked:Position :: Position -> Board $sel:leapingCheckers:Position :: Position -> Board $sel:sliderCheckers:Position :: Position -> Board $sel:pinnedPieces:Position :: Position -> Board $sel:previousPositions:Position :: Position -> [ZKey] $sel:halfMoveClock:Position :: Position -> Ply $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:castling: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 ..} = Position pos { halfMoveClock = 0 , pawns = pawns ^ start , queens = queens .| end , enPassant = 0 } movePiece Piece Knight Promotion _ Board start Board end pos :: Position pos@Position {Phase [ZKey] Ply Board Color $sel:color:Position :: Position -> Color $sel:player:Position :: Position -> Board $sel:enemy:Position :: Position -> Board $sel:enPassant:Position :: Position -> Board $sel:phase:Position :: Position -> Phase $sel:attacked:Position :: Position -> Board $sel:leapingCheckers:Position :: Position -> Board $sel:sliderCheckers:Position :: Position -> Board $sel:pinnedPieces:Position :: Position -> Board $sel:previousPositions:Position :: Position -> [ZKey] $sel:halfMoveClock:Position :: Position -> Ply $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:castling: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 ..} = Position pos { knights = (knights ^ start) .| end , enPassant = 0 } movePiece Piece Bishop Promotion _ Board start Board end pos :: Position pos@Position {Phase [ZKey] Ply Board Color $sel:color:Position :: Position -> Color $sel:player:Position :: Position -> Board $sel:enemy:Position :: Position -> Board $sel:enPassant:Position :: Position -> Board $sel:phase:Position :: Position -> Phase $sel:attacked:Position :: Position -> Board $sel:leapingCheckers:Position :: Position -> Board $sel:sliderCheckers:Position :: Position -> Board $sel:pinnedPieces:Position :: Position -> Board $sel:previousPositions:Position :: Position -> [ZKey] $sel:halfMoveClock:Position :: Position -> Ply $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:castling: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 ..} = Position pos { bishops = (bishops ^ start) .| end , enPassant = 0 } movePiece Piece Rook Promotion _ Board start Board end pos :: Position pos@Position {Phase [ZKey] Ply Board Color $sel:color:Position :: Position -> Color $sel:player:Position :: Position -> Board $sel:enemy:Position :: Position -> Board $sel:enPassant:Position :: Position -> Board $sel:phase:Position :: Position -> Phase $sel:attacked:Position :: Position -> Board $sel:leapingCheckers:Position :: Position -> Board $sel:sliderCheckers:Position :: Position -> Board $sel:pinnedPieces:Position :: Position -> Board $sel:previousPositions:Position :: Position -> [ZKey] $sel:halfMoveClock:Position :: Position -> Ply $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:castling: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 ..} = Position pos { rooks = (rooks ^ start) .| end , castling = castling .\ start , enPassant = 0 } movePiece Piece Queen Promotion _ Board start Board end pos :: Position pos@Position {Phase [ZKey] Ply Board Color $sel:color:Position :: Position -> Color $sel:player:Position :: Position -> Board $sel:enemy:Position :: Position -> Board $sel:enPassant:Position :: Position -> Board $sel:phase:Position :: Position -> Phase $sel:attacked:Position :: Position -> Board $sel:leapingCheckers:Position :: Position -> Board $sel:sliderCheckers:Position :: Position -> Board $sel:pinnedPieces:Position :: Position -> Board $sel:previousPositions:Position :: Position -> [ZKey] $sel:halfMoveClock:Position :: Position -> Ply $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:castling: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 ..} = Position pos { queens = (queens ^ start) .| end , enPassant = 0 } movePiece Piece King Promotion _ Board start Board end pos :: Position pos@Position {Phase [ZKey] Ply Board Color $sel:color:Position :: Position -> Color $sel:player:Position :: Position -> Board $sel:enemy:Position :: Position -> Board $sel:enPassant:Position :: Position -> Board $sel:phase:Position :: Position -> Phase $sel:attacked:Position :: Position -> Board $sel:leapingCheckers:Position :: Position -> Board $sel:sliderCheckers:Position :: Position -> Board $sel:pinnedPieces:Position :: Position -> Board $sel:previousPositions:Position :: Position -> [ZKey] $sel:halfMoveClock:Position :: Position -> Ply $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:castling: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 ..} = Position pos { kings = (kings ^ start) .| end , castling = castling .\ kingRank , player = (player ^ rookStart) .| rookEnd , rooks = (rooks ^ rookStart) .| rookEnd , enPassant = 0 } where rookStart :: Board rookStart = Board shortCastle Board -> Square -> Board forall a. Bits a => a -> Square -> a << Square 1 Board -> Board -> Board .| Board longCastle Board -> Square -> Board forall a. Bits a => a -> Square -> a >> Square 2 rookEnd :: Board rookEnd = Board shortCastle Board -> Square -> Board forall a. Bits a => a -> Square -> a >> Square 1 Board -> Board -> Board .| Board longCastle Board -> Square -> Board forall a. Bits a => a -> Square -> a << Square 1 shortCastle :: Board shortCastle = (Board start Board -> Square -> Board forall a. Bits a => a -> Square -> a << Square 2) Board -> Board -> Board & Board end longCastle :: Board longCastle = (Board start Board -> Square -> Board forall a. Bits a => a -> Square -> a >> Square 2) Board -> Board -> Board & Board end kingRank :: Board kingRank = Vector Board fileMovesVec Vector Board -> Square -> Board forall a. Storable a => Vector a -> Square -> a !! Board -> Square lsb Board start