Ejemplo n.º 1
0
        public double GetScore(IChessBoard board, ChessColor sideToDraw)
        {
            // get allied pieces and calculate the score
            double allyScore  = board.GetPiecesOfColor(sideToDraw).Select(x => getPieceScore(board, x.Position)).Sum();
            double enemyScore = board.GetPiecesOfColor(sideToDraw.Opponent()).Select(x => getPieceScore(board, x.Position)).Sum();

            // calculate the relative score: the own score compared to the opponent's score
            return(allyScore - enemyScore);
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 3
0
        /// <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);
        }
Ejemplo n.º 4
0
        private ChessDraw[] generateDraws(IChessBoard board, ChessDraw?lastDraw = null)
        {
            ChessDraw[] draws       = new ChessDraw[0];
            var         drawingSide = lastDraw?.DrawingSide.Opponent() ?? ChessColor.White;

            if (board?.GetType() == typeof(ChessBoard))
            {
                var alliedPieces = board.GetPiecesOfColor(drawingSide);
                draws = alliedPieces.SelectMany(x => ChessDrawGenerator.Instance.GetDraws(board, x.Position, lastDraw, true)).ToArray();
            }
            else if (board?.GetType() == typeof(ChessBitboard))
            {
                draws = ((ChessBitboard)board).GetAllDraws(drawingSide, lastDraw, true);
            }

            return(draws);
        }
Ejemplo n.º 5
0
        private bool canAchieveCheckmate(IChessBoard board, ChessColor side)
        {
            // minimal pieces required for checkmate:
            // ======================================
            //  (1) king + queen
            //  (2) king + rook
            //  (3) king + 2 bishops (onto different chess field colors)
            //  (4) king + bishop + knight
            //  (5) king + 3 knights
            //  (6) king + peasant (with promotion)
            //
            // source: http://www.eudesign.com/chessops/basics/cpr-mate.htm

            // get all allied pieces
            var alliedPieces = board.GetPiecesOfColor(side);

            // determine whether the allied side can still achieve a checkmate
            bool ret = (
                // check if ally at least has his king + another piece (precondition for all options)
                alliedPieces.Count() >= 2 && alliedPieces.Any(x => x.Piece.Type == ChessPieceType.King)
                &&
                (
                    // check for options 1, 2, 6
                    alliedPieces.Any(x => x.Piece.Type == ChessPieceType.Queen || x.Piece.Type == ChessPieceType.Rook || x.Piece.Type == ChessPieceType.Peasant)
                    ||
                    // check for options 3, 4, 5
                    (
                        // check precondition of options 3, 4, 5
                        alliedPieces.Count() >= 3 &&
                        (
                            // check for option 3
                            alliedPieces.Where(x => x.Piece.Type == ChessPieceType.Bishop).Select(x => x.Position.ColorOfField)?.Distinct().Count() == 2
                            ||
                            // check for option 4
                            alliedPieces.Any(x => x.Piece.Type == ChessPieceType.Bishop) && alliedPieces.Any(x => x.Piece.Type == ChessPieceType.Knight)
                            ||
                            // check for option 5
                            alliedPieces.Where(x => x.Piece.Type == ChessPieceType.Knight).Count() >= 3
                        )
                    )
                )
                );

            return(ret);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Compute the field positions that can be captured by the given chess piece.
        /// </summary>
        /// <param name="board">The chess board representing the game situation</param>
        /// <param name="drawingPiecePosition">The chess position of the chess piece to be drawn</param>
        /// <param name="precedingEnemyDraw">The last draw made by the opponent</param>
        /// <param name="analyzeDrawIntoCheck">Indicates whether drawing into a check situation should be analyzed</param>
        /// <returns>a list of all possible chess draws</returns>
        public IEnumerable <ChessDraw> GetDraws(IChessBoard board, ChessPosition drawingPiecePosition, ChessDraw?precedingEnemyDraw = null, bool analyzeDrawIntoCheck = false)
        {
            var piece = board.GetPieceAt(drawingPiecePosition);

            // make sure the chess piece is a king
            if (piece.Type != ChessPieceType.King)
            {
                throw new InvalidOperationException("The chess piece is not a king.");
            }

            // get the possible draw positions
            var positions = getStandardDrawPositions(drawingPiecePosition);

            // only retrieve positions that are not captured by an allied chess piece
            var alliedPieces = board.GetPiecesOfColor(piece.Color);

            positions = positions.Except(alliedPieces.Select(x => x.Position));

            // only retrieve positions that cannot be captured by the enemy king (-> avoid draw into check)
            var enemyKing             = piece.Color == ChessColor.White ? board.BlackKing : board.WhiteKing;
            var enemyKingDrawPositons = getStandardDrawPositions(enemyKing.Position);

            positions = positions.Except(enemyKingDrawPositons);

            // transform positions to draws
            IEnumerable <ChessDraw> draws = positions.Select(newPos => new ChessDraw(board, drawingPiecePosition, newPos)).ToArray();

            // analyze draw into a check situation
            if (analyzeDrawIntoCheck && draws?.Count() > 0)
            {
                draws = draws.Where(draw => !ChessDrawSimulator.Instance.IsDrawIntoCheck(board, draw)).ToArray();
            }

            // add rochade draws
            bool canRochade = (drawingPiecePosition == new ChessPosition("E1") || drawingPiecePosition == new ChessPosition("E8"));

            if (canRochade)
            {
                draws = draws.Concat(getRochadeDraws(board, piece.Color));
            }

            return(draws);
        }