packages feed

turncoat-1.0: src/MoveGen/MakeMove.hs

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 {..} pos =
  makeNullMove
  $ movePiece piece promotion startBoard endBoard
  $ updatePlayerBoards startBoard endBoard pos
  where
    !startBoard = toBoard start
    !endBoard = toBoard end


makeNullMove :: Position -> Position
makeNullMove pos@Position {color, player,  enemy, enPassant} =
  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    = getBishopCheckerRays    pos
    rookCheckerRays      = getRookCheckerRays      pos
    sliderRays           = getEnemyKingSliderRays  pos
    enPassantPinnedPawns = getEnPassantPinnedPawns pos


updatePlayerBoards :: Board -> Board -> Position -> Position
updatePlayerBoards start end pos@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 Pawn NoProm start end pos@Position {..} =
  pos {
      halfMoveClock = 0
    , pawns         = (pawns ^ (start .| enPassantCapture)) .| end
    , enemy         = enemy ^ enPassantCapture
    , enPassant     = start <<! 8 & end !>> 8
  }
  where
    ((<<!), (!>>)) = case color of
      White -> ((<<), (>>))
      Black -> ((>>), (<<))
    enPassantCapture = (enPassant & end) !>> 8

movePiece Pawn KnightProm start end pos@Position {..} =
  pos {
      halfMoveClock = 0
    , pawns         = pawns ^ start
    , knights       = knights .| end
    , enPassant     = 0
  }

movePiece Pawn BishopProm start end pos@Position {..} =
  pos {
      halfMoveClock = 0
    , pawns         = pawns ^ start
    , bishops       = bishops .| end
    , enPassant     = 0
  }

movePiece Pawn RookProm !start !end pos@Position {..} =
  pos {
      halfMoveClock = 0
    , pawns         = pawns ^ start
    , rooks         = rooks .| end
    , enPassant     = 0
  }

movePiece Pawn QueenProm start end pos@Position {..} =
  pos {
      halfMoveClock = 0
    , pawns         = pawns ^ start
    , queens        = queens .| end
    , enPassant     = 0
  }

movePiece Knight _ start end pos@Position {..} =
  pos {
      knights   = (knights ^ start) .| end
    , enPassant = 0
  }

movePiece Bishop _ start end pos@Position {..} =
  pos {
      bishops   = (bishops ^ start) .| end
    , enPassant = 0
  }

movePiece Rook _ start end pos@Position {..} =
  pos {
      rooks     = (rooks ^ start) .| end
    , castling  = castling .\ start
    , enPassant = 0
  }

movePiece Queen _ start end pos@Position {..} =
  pos {
      queens    = (queens ^ start) .| end
    , enPassant = 0
  }

movePiece King _ start end pos@Position {..} =
  pos {
      kings     = (kings ^ start) .| end
    , castling  = castling .\ kingRank
    , player    = (player ^ rookStart) .| rookEnd
    , rooks     = (rooks ^ rookStart) .| rookEnd
    , enPassant = 0
  }
  where
    rookStart   = shortCastle << 1 .| longCastle >> 2
    rookEnd     = shortCastle >> 1 .| longCastle << 1
    shortCastle = (start << 2) & end
    longCastle  = (start >> 2) & end
    kingRank    = fileMovesVec !! lsb start