Example #1
0
        private IEnumerable <ChessDraw> getRochadeDraws(IChessBoard board, ChessColor drawingSide)
        {
            // TODO: do optimizations!!!

            // get enemy capturable positions
            var enemyKing = (drawingSide == ChessColor.White) ? board.BlackKing : board.WhiteKing;
            var enemyCapturablePositions =
                board.GetPiecesOfColor(drawingSide.Opponent()).Where(x => x.Piece.Type != ChessPieceType.King)
                .SelectMany(x => ChessDrawGenerator.Instance.GetDraws(board, x.Position, null, false)).Select(x => x.NewPosition)
                .Concat(getStandardDrawPositions(enemyKing.Position));

            // get the allied king and towers
            int row                = (drawingSide == ChessColor.White) ? 0 : 7;
            var alliedKing         = (drawingSide == ChessColor.White) ? board.WhiteKing : board.BlackKing;
            var farAlliedTowerPos  = new ChessPosition(row, 0);
            var farAlliedTower     = board.GetPieceAt(farAlliedTowerPos);
            var nearAlliedTowerPos = new ChessPosition(row, 7);
            var nearAlliedTower    = board.GetPieceAt(nearAlliedTowerPos);

            // define the fields that must not be capturable by the opponent
            var bigRochadeKingPassagePositions   = (drawingSide == ChessColor.White) ? whiteKingBigRochadePassagePositions   : blackKingBigRochadePassagePositions;
            var smallRochadeKingPassagePositions = (drawingSide == ChessColor.White) ? whiteKingSmallRochadePassagePositions : blackKingSmallRochadePassagePositions;

            bool canBigRochade =
                // check for preconditions of big rochade
                (board.IsCapturedAt(farAlliedTowerPos) && !alliedKing.Piece.WasMoved && !farAlliedTower.WasMoved &&
                 bigRochadeKingPassagePositions.All(x => !board.IsCapturedAt(x) || (board.GetPieceAt(x).Color == drawingSide && board.GetPieceAt(x).Type == ChessPieceType.King)) &&
                 !board.IsCapturedAt(new ChessPosition(row, 1)))
                // make sure that no rochade field can be captured by the opponent
                && !enemyCapturablePositions.Any(pos => bigRochadeKingPassagePositions.Contains(pos));

            bool canSmallRochade =
                // check for preconditions of small rochade
                (board.IsCapturedAt(nearAlliedTowerPos) && !alliedKing.Piece.WasMoved && !nearAlliedTower.WasMoved &&
                 smallRochadeKingPassagePositions.All(x => !board.IsCapturedAt(x) || (board.GetPieceAt(x).Color == drawingSide && board.GetPieceAt(x).Type == ChessPieceType.King)))
                // make sure that no rochade field can be captured by the opponent and the rochade field on the B-line is not captured
                && !enemyCapturablePositions.Any(pos => smallRochadeKingPassagePositions.Contains(pos));

            // write result draws
            int index      = 0;
            int drawsCount = (canSmallRochade ? 1 : 0) + (canBigRochade ? 1 : 0);

            ChessDraw[] draws = new ChessDraw[drawsCount];
            if (canSmallRochade)
            {
                draws[index++] = new ChessDraw(board, alliedKing.Position, new ChessPosition(row, 6));
            }
            if (canBigRochade)
            {
                draws[index++] = new ChessDraw(board, alliedKing.Position, new ChessPosition(row, 2));
            }

            return(draws);
        }
        /// <summary>
        /// Simulate the given chess draw on the given chess board and determine whether it draws into an allied check situation.
        /// </summary>
        /// <param name="board">The chess board with the game situation to evaluate</param>
        /// <param name="draw">The chess draw to be evaluated</param>
        /// <returns>boolean that indicates whether the draw would cause an allied check situation</returns>
        public bool IsDrawIntoCheck(IChessBoard board, ChessDraw draw)
        {
            // TODO: remove clone operation if it causes performance issues

            // clone chess board and simulate the draw
            var simulatedBoard = board.ApplyDraw(draw);

            // get all enemy chess pieces and their possible answers
            var enemyPieces          = simulatedBoard.GetPiecesOfColor(draw.DrawingSide.Opponent());
            var possibleEnemyAnswers = enemyPieces.SelectMany(piece => ChessDrawGenerator.Instance.GetDraws(simulatedBoard, piece.Position, draw, false));

            // find out if the allied king could be taken by at least one enemy answer
            var  alliedKing = (draw.DrawingSide == ChessColor.White) ? simulatedBoard.WhiteKing : simulatedBoard.BlackKing;
            bool ret        = possibleEnemyAnswers.Any(x => x.NewPosition == alliedKing.Position);

            return(ret);
        }
Example #3
0
        // TODO: maybe rework this attibute as this is quite "quick n dirty"

        #endregion Members

        #region Methods

        /// <summary>
        /// Apply the chess draw to the current game situation on the chess board.
        /// Furthermore change the side that has to draw and store the chess draw in the chess draws history (stack).
        /// </summary>
        /// <param name="draw">The chess draw to be made</param>
        /// <param name="validate">Indicates whether the chess draw should be validated</param>
        /// <returns>boolean whether the draw could be applied</returns>
        public bool ApplyDraw(ChessDraw draw, bool validate = false)
        {
            var  lastDraw    = (_drawHistory?.Count > 0) ? (ChessDraw?)_drawHistory.Peek() : null;
            bool isDrawValid = !validate || draw.IsValid(Board, lastDraw);

            // info: Validate() throws an exception if the draw is invalid -> catch this exception and make use of the exception message
            if (isDrawValid)
            {
                // draw the chess piece
                Board = Board.ApplyDraw(draw);

                // apply the chess draw to the chess draws history
                _drawHistory.Push(draw);

                // change the side that has to draw
                SideToDraw = SideToDraw.Opponent();
            }

            return(isDrawValid);
        }
        /// <summary>
        /// Check whether the game situation on the given chess board is a simple check, checkmate or tie situation.
        /// </summary>
        /// <param name="board">the chess board to be evaluated</param>
        /// <param name="precedingEnemyDraw">the preceding opponent chess draw</param>
        /// <returns>a check game status</returns>
        public ChessGameStatus GetCheckGameStatus(IChessBoard board, ChessDraw precedingEnemyDraw)
        {
            var alliedSide = (precedingEnemyDraw.DrawingSide == ChessColor.White) ? ChessColor.Black : ChessColor.White;
            var enemySide  = precedingEnemyDraw.DrawingSide;

            // analyze the chess piece types on the board => determine whether any player can even achieve a checkmate with his remaining pieces
            bool canAllyCheckmate  = canAchieveCheckmate(board, alliedSide);
            bool canEnemyCheckmate = canAchieveCheckmate(board, enemySide);

            // quit game status analysis if ally has lost due to unsufficient pieces
            if (!canAllyCheckmate && canEnemyCheckmate)
            {
                return(ChessGameStatus.UnsufficientPieces);
            }
            if (!canAllyCheckmate && !canEnemyCheckmate)
            {
                return(ChessGameStatus.Tie);
            }

            // find out if any allied chess piece can draw
            var  alliedPieces = board.GetPiecesOfColor(alliedSide);
            bool canAllyDraw  = alliedPieces.Any(piece => ChessDrawGenerator.Instance.GetDraws(board, piece.Position, precedingEnemyDraw, true).Count() > 0);

            // find out whether the allied king is checked
            var  alliedKing          = (alliedSide == ChessColor.White) ? board.WhiteKing : board.BlackKing;
            var  enemyPieces         = board.GetPiecesOfColor(alliedSide.Opponent());
            bool isAlliedKingChecked = enemyPieces.Any(piece => ChessDrawGenerator.Instance.GetDraws(board, piece.Position, null, false).Any(y => y.NewPosition == alliedKing.Position));

            // none:      ally can draw and is not checked
            // check:     ally is checked, but can at least draw
            // stalemate: ally cannot draw but is also not checked (end of game)
            // checkmate: ally is checked and cannot draw anymore (end of game)

            var status =
                canAllyDraw
                    ? (isAlliedKingChecked ? ChessGameStatus.Check : ChessGameStatus.None)
                    : (isAlliedKingChecked ? ChessGameStatus.Checkmate : ChessGameStatus.Stalemate);

            return(status);
        }