public BoardMove Find(StandardAlgebraicNotation san, Colours forPlayer)
        {
            var t = san.ToNotation();

            if (san.CastleMove != StandardAlgebraicNotation.CastleSide.None)
            {
                return(FindCastleMove(san, forPlayer));
            }

            var destination = BoardLocation.At(san.ToFileX, san.ToRankY);

            if (san.HaveFrom)
            {
                var exact = FindExactMove(san, destination);

                if (exact == null)
                {
                    Throw.MoveNotFound($"Move not found: {san.ToNotation()}");
                }

                return(exact);
            }

            var items = _boardState
                        .GetItems((int)forPlayer, (int)san.Piece)
                        .ThatCanMoveTo(destination);

            if (TryFindMove(items, destination, san, out var move))
            {
                return(move);
            }

            if (san.FromFileX.HasValue)
            {
                items = items.Where(i => i.Paths.FlattenMoves().Any(m => m.From.X == san.FromFileX.Value));
                if (TryFindMove(items, destination, san, out move))
                {
                    return(move);
                }
            }

            if (san.FromRankY.HasValue)
            {
                items = items.Where(i => i.Paths.FlattenMoves().Any(m => m.From.Y == san.FromRankY.Value));
                if (TryFindMove(items, destination, san, out move))
                {
                    return(move);
                }
            }


            Throw.MoveNotFound($"Couldn't disambiguate move: {san.ToNotation()}");
            return(null);
        }
        public bool ValidateMove(BoardMove move, IReadOnlyBoardState <TEntity> roBoardState)
        {
            var piece = roBoardState.GetItem(move.From);

            if (piece == null)
            {
                return(false);
            }

            var owner = piece.Item.Owner;

            var enemyPaths = new Paths();
            var enemyItems = roBoardState.GetItems().Where(i => i.Item.Owner != owner);

            enemyPaths.AddRange(enemyItems.SelectMany(li => li.Paths));

            var attackMoveTypes = new [] { (int)DefaultActions.MoveOrTake, (int)DefaultActions.TakeOnly, (int)ChessMoveTypes.KingMove };

            return(!enemyPaths.ContainsMoveTypeTo(move.To, attackMoveTypes));
        }