예제 #1
0
        /// <summary>
        /// Return available castling options for <paramref name="king"/>, given
        /// a <paramref name="position"/> and <paramref name="moveEntries"/>.
        /// </summary>
        /// <param name="king">Must be <see cref="King"/>.</param>
        /// <param name="position">A given <see cref="Board.Position"/>.</param>
        /// <param name="moveEntries">A read-only <see cref="MoveEntry"/> collection of
        /// previously proccessed moves.</param>
        /// <returns></returns>
        public static IReadOnlyCollection <Move> Castles(
            this IPiece king,
            IReadOnlyDictionary <Square, IPiece> position,
            IReadOnlyCollection <MoveEntry> moveEntries)
        {
            var kingSquare = ((Piece)king).GetSquareFrom(position);

            if (
                king is not King ||
                kingSquare is null ||
                kingSquare.Rank != (king.Color ? Ranks.one : Ranks.eight) ||
                king.HasMoved(position, moveEntries))
            {
                return(Enumerable.Empty <Move>().ToList());
            }

            var rookSquares = position
                              .Where(kv => kv.Value.Color == king.Color && kv.Value is Rook)
                              .Where(kv => !kv.Value.HasMoved(position, moveEntries))
                              .Where(kv => kv.Key.IsSameRankAs(kingSquare))
                              .Select(kv => kv.Key)
                              .ToList();

            return(rookSquares
                   .Where(
                       rs => kingSquare
                       .InBetweenSquares(rs)
                       .All(s => !position.TryGetValue(s, out IPiece piece)))
                   .Select(rs =>
                           (rs.File < kingSquare.File) ?
                           new Move(
                               new Square(kingSquare),
                               new Square(Files.c, kingSquare.Rank),
                               MoveType.Castle) :
                           new Move(
                               new Square(kingSquare),
                               new Square(Files.g, kingSquare.Rank),
                               MoveType.Castle))
                   .ToList());
        }