Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion src/Game/Chess/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ module Game.Chess.Internal where
import Control.DeepSeq
import Control.Lens (view)
import Control.Lens.Iso (from)
import Control.Monad (when)
import Control.Monad (when, guard)
import Control.Monad.ST
import Data.Binary
import Data.Bits (Bits (bit, complement, testBit, unsafeShiftL, unsafeShiftR, xor, (.&.), (.|.)),
Expand Down Expand Up @@ -350,9 +350,26 @@ toUCI (unpack -> (src, dst, promo)) = coord src <> coord dst <> p where
Just Knight -> "n"
_ -> ""

-- | Castling in the UCI format can sometimes be represented as king capturing
-- its own rook. UCI specifies this for Chess960, but e.g. Lichess seems to do
-- this even for normal, non-960 variants.
--
-- So when a move seems like it's illegal, we check if it's just a different
-- representation of castling.
correctUciCastle :: Position -> Ply -> Maybe Ply
correctUciCastle pos m = do
guard $ pieceAt pos (plySource m) == Just (color pos, King)
case (plySource m, plyTarget m) of
(E1, H1) -> Just wKscm
(E1, A1) -> Just wQscm
(E8, H8) -> Just bKscm
(E8, A8) -> Just bQscm
_ -> Nothing

-- | Validate that a certain move is legal in the given position.
relativeTo :: Position -> Ply -> Maybe Ply
relativeTo pos m | m `Vector.elem` legalPlies' pos = Just m
| Just m' <- correctUciCastle pos m, m' `Vector.elem` legalPlies' pos = Just m'
| otherwise = Nothing

shiftN, shiftNN, shiftNNE, shiftNE, shiftENE, shiftE, shiftESE, shiftSE, shiftSSE, shiftS, shiftSS, shiftSSW, shiftSW, shiftWSW, shiftW, shiftWNW, shiftNW, shiftNNW :: Bitboard -> Bitboard
Expand Down