Exemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="boardState"></param>
        /// <param name="move"></param>
        /// <param name="performCheckTest">
        /// This has a small performance impact when reverse engineering SAN from the board move
        /// (approx 20ms a game on my rig) which is why it's optional and defaults to off</param>
        /// <returns></returns>
        public StandardAlgebraicNotation BuildFrom(IBoardState <ChessPieceEntity> boardState, BoardMove move, bool performCheckTest = false)
        {
            var fromItem = boardState.GetItem(move.From);

            var piece    = fromItem.Item.Piece;
            int?fromFile = null;
            int?fromRank = null;
            var toFile   = move.To.X;
            var toRank   = move.To.Y;
            var moveType = boardState.IsEmpty(move.To) ? SanMoveTypes.Move : SanMoveTypes.Take;

            // Are they any other pieces,
            //      of same type as the from item
            //      that can also move to the same location
            var otherPieces = boardState.GetItems()
                              .Where(i => !i.Location.Equals(move.From))
                              .Where(i => i.Item.Is(fromItem.Item.Player, fromItem.Item.Piece))
                              .ThatCanMoveTo(move.To);

            // TODO: That I need this resharper disable is probably a smell
            // ReSharper disable PossibleMultipleEnumeration
            if (otherPieces.Any())
            {
                fromFile = move.From.X;
                var file = fromFile;
                otherPieces = otherPieces
                              .Where(i => i.Location.X == file);
            }
            if (otherPieces.Any())
            {
                fromRank    = move.From.Y;
                otherPieces = new List <LocatedItem <ChessPieceEntity> >();
            }

            if (otherPieces.Any())
            {
                Throw.InvalidSan($"Unable to disambiguate {move}");
            }
            // ReSharper restore PossibleMultipleEnumeration

            if (piece == ChessPieceName.Pawn && moveType == SanMoveTypes.Take)
            {
                fromFile = fromItem.Location.X;
            }

            ChessPieceName?promotionPiece = null;

            if (move.ExtraData is ChessPieceEntityFactory.ChessPieceEntityFactoryTypeExtraData data)
            {
                promotionPiece = data.PieceName;
            }

            var inCheck = performCheckTest && _checkDetectionService.DoesMoveCauseCheck(boardState, move);

            return(new StandardAlgebraicNotation(piece, fromFile, fromRank, toFile, toRank, moveType, promotionPiece, inCheck));
        }