예제 #1
0
        /// <summary>
        /// Checks if a <paramref name="move"/> is legal (does not place own king under check).
        /// </summary>
        /// <typeparam name="TChess">Derived type. <paramref name="chess"/>
        /// must be <typeparamref name="TChess"/>.</typeparam>
        /// <param name="chess">A given set of <see cref="Chess"/> rules.</param>
        /// <param name="move">A given <see cref="Move"/>.</param>
        /// <returns><see langword="true"/> if the move is legal.
        /// Otherwise, <see langword="false"/>.</returns>
        /// <exception cref="ArgumentException"><paramref name="chess"/> must
        /// be a <typeparamref name="TChess"/> instance.</exception>
        public static bool IsLegal <TChess>(this IChess chess, Move move) where TChess : Chess
        {
            // Legal restraints
            if (!(chess is TChess))
            {
                throw new ArgumentException(
                          message: "Chess must be a TChess instance",
                          paramName: nameof(chess));
            }

            // Create a new chess state instance...
            IChess chessInstance = (TChess)Activator.CreateInstance(
                typeof(TChess),
                new object[] { (TChess)chess });

            // Legal logic for castle
            if (move.Type == MoveType.Castle)
            {
                return(chessInstance.IsCastlingLegal <TChess>(move));
            }


            // ... use it to get moved IPiece color
            var color = chessInstance.Position[move.FromSquare].Color;

            // Execute given move on instance...
            chessInstance.Process(move, out IPiece piece);

            // ... and returns wether own king is not checked
            return(!chessInstance.IsChecked <TChess>(color));
        }
예제 #2
0
        /// <summary>
        /// Checks if castling is legal or not, for a given castles <paramref name="move"/>.
        /// </summary>
        /// <typeparam name="TChess">Derived type. <paramref name="chess"/>
        /// must be <typeparamref name="TChess"/>.</typeparam>
        /// <param name="chess">A given set of <see cref="Chess"/> rules.</param>
        /// <param name="move">A given <see cref="Move"/>.</param>
        /// <returns><see langword="true"/> if the move is legal.
        /// Otherwise, <see langword="false"/>.</returns>
        private static bool IsCastlingLegal <TChess>(this IChess chess, Move move) where TChess : Chess

        {
            // Get the castling king
            var king = chess.Position[move.FromSquare];

            // Castle can't occur when king is checked
            if (chess.IsChecked <TChess>(king.Color))
            {
                return(false);
            }

            // Define the type of castle
            var kingSideCastle = move.ToSquare.File == Files.g;

            // Determines the rook squares
            var rookFromSquare = new Square(
                kingSideCastle ? Files.h : Files.a,
                move.FromSquare.Rank
                );
            var rookToSquare = new Square(
                kingSideCastle ? Files.f : Files.d,
                move.ToSquare.Rank
                );

            // Remove rook
            ((Chess)chess).RemovePiece(rookFromSquare, out IPiece rook);

            // Get all squares between fromSquare and toSquare
            var currentSquare = new Square(move.FromSquare);
            var kingSquares   = Helper
                                .InBetweenSquares(move.FromSquare, move.ToSquare)
                                .ToList()
                                .Append(move.ToSquare)
                                .ToList();

            // Loop and test for checks
            foreach (var square in kingSquares)
            {
                // Move king along the castling path...
                if (!chess.Process(
                        new Move(
                            currentSquare,
                            square,
                            MoveType.Normal),
                        out IPiece p))
                {
                    return(false);
                }

                // ... and check for checks.
                if (chess.IsChecked <TChess>(king.Color))
                {
                    return(false);
                }

                currentSquare = new Square(square);
            }

            // Put rook at his destination square
            ((Chess)chess).PlaceAt(rookToSquare, rook);

            return(true);
        }