Exemplo n.º 1
0
        public double RateDraw(IChessBoard board, ChessDraw draw, int searchDepth)
        {
            // simulate the given draw
            var simulatedBoard = board.ApplyDraw(draw);

            // use the minimax algorithm to rate the score of the given draw
            double score = negamax(simulatedBoard, draw, searchDepth - 1, double.MinValue, double.MaxValue, false) * -1;

            return(score);
        }
Exemplo n.º 2
0
        /// <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);
        }
Exemplo n.º 3
0
        private double negamax(IChessBoard board, ChessDraw?lastDraw, int depth, double alpha, double beta, bool isMaximizing = true)
        {
            var drawingSide = lastDraw?.DrawingSide.Opponent() ?? ChessColor.White;

            // recursion anchor: depth <= 0
            if (depth <= 0)
            {
                return(_estimator.GetScore(board, drawingSide));
            }

            // init max score
            double maxScore = alpha;

            // compute possible draws
            var draws = generateDraws(board, lastDraw);

            // order draws by possible gain, so the alpha-beta prune can achieve fast cut-offs
            // at high-level game tree nodes which ideally saves lots of computation effort
            var preorderedDraws = getPreorderedDrawsByPossibleGain(board, draws, drawingSide);

            // loop through all possible draws
            for (int i = 0; i < preorderedDraws.Length; i++)
            {
                // simulate draw
                var simDraw  = preorderedDraws[i];
                var simBoard = board.ApplyDraw(simDraw);

                // start recursion
                double score = negamax(simBoard, simDraw, depth - 1, -beta, -maxScore, !isMaximizing) * -1;

                // update max score
                if (score > maxScore)
                {
                    maxScore = score;
                }

                // check for beta cut-off
                if (maxScore >= beta)
                {
                    break;
                }
            }

            return(maxScore);
        }
Exemplo n.º 4
0
        private ChessDraw[] getPreorderedDrawsByPossibleGain(IChessBoard board, IList <ChessDraw> draws, ChessColor drawingSide)
        {
            // initialize score array
            var drawsXScoreTuples = new ChessDrawScore[draws.Count()];

            // loop through all draws
            for (int i = 0; i < draws.Count(); i++)
            {
                // simulate the draw
                var simDraw  = draws[i];
                var simBoard = board.ApplyDraw(simDraw);

                // compute the score of the resulting position (= score of the draw)
                double score = _estimator.GetScore(simBoard, drawingSide);

                // add the (draw, score) tuple to the list
                drawsXScoreTuples[i] = new ChessDrawScore()
                {
                    Draw = simDraw, Score = score
                };
            }

            return(sortByScoreDesc(drawsXScoreTuples));
        }
        public void GetCheckGameStatusTest()
        {
            // test no check
            IChessBoard board     = ChessBoard.StartFormation;
            var         enemyDraw = new ChessDraw(board, new ChessPosition(0, 0), new ChessPosition(0, 0));

            board = board.ApplyDraw(enemyDraw);
            Assert.True(ChessDrawSimulator.Instance.GetCheckGameStatus(board, enemyDraw) == ChessGameStatus.None);

            // test simple check
            var pieces = new List <ChessPieceAtPos>()
            {
                new ChessPieceAtPos(new ChessPosition(0, 4), new ChessPiece(ChessPieceType.King, ChessColor.White, true)),
                new ChessPieceAtPos(new ChessPosition(1, 5), new ChessPiece(ChessPieceType.Peasant, ChessColor.White, true)),
                new ChessPieceAtPos(new ChessPosition(7, 3), new ChessPiece(ChessPieceType.Queen, ChessColor.Black, true)),
                new ChessPieceAtPos(new ChessPosition(7, 4), new ChessPiece(ChessPieceType.King, ChessColor.Black, true)),
            };

            board     = new ChessBoard(pieces);
            enemyDraw = new ChessDraw(board, new ChessPosition(7, 3), new ChessPosition(6, 4));
            board     = board.ApplyDraw(enemyDraw);
            Assert.True(ChessDrawSimulator.Instance.GetCheckGameStatus(board, enemyDraw) == ChessGameStatus.Check);

            // test checkmate
            for (int putSavingPieceValue = 0; putSavingPieceValue < 2; putSavingPieceValue++)
            {
                pieces = new List <ChessPieceAtPos>()
                {
                    new ChessPieceAtPos(new ChessPosition(0, 4), new ChessPiece(ChessPieceType.King, ChessColor.White, true)),
                    new ChessPieceAtPos(new ChessPosition(6, 1), new ChessPiece(ChessPieceType.Peasant, ChessColor.White, true)),
                    new ChessPieceAtPos(new ChessPosition(2, 3), new ChessPiece(ChessPieceType.Queen, ChessColor.Black, true)),
                    new ChessPieceAtPos(new ChessPosition(2, 4), new ChessPiece(ChessPieceType.King, ChessColor.Black, true)),
                };

                // allow the ally to avoid the checkmate by putting an additional chess piece on the board
                // and test if the simulator makes use of this opportunity
                bool putSavingPiece = (putSavingPieceValue == 1);
                if (putSavingPiece)
                {
                    pieces.Add(new ChessPieceAtPos(new ChessPosition(1, 7), new ChessPiece(ChessPieceType.Rook, ChessColor.White, true)));
                }

                board     = new ChessBoard(pieces);
                enemyDraw = new ChessDraw(board, new ChessPosition(2, 3), new ChessPosition(1, 4));
                board     = board.ApplyDraw(enemyDraw);

                Assert.True(
                    (!putSavingPiece && ChessDrawSimulator.Instance.GetCheckGameStatus(board, enemyDraw) == ChessGameStatus.Checkmate) ||
                    (putSavingPiece && ChessDrawSimulator.Instance.GetCheckGameStatus(board, enemyDraw) == ChessGameStatus.Check)
                    );
            }

            // test stalemate
            pieces = new List <ChessPieceAtPos>()
            {
                new ChessPieceAtPos(new ChessPosition(0, 4), new ChessPiece(ChessPieceType.King, ChessColor.White, true)),
                new ChessPieceAtPos(new ChessPosition(6, 1), new ChessPiece(ChessPieceType.Peasant, ChessColor.White, true)),
                new ChessPieceAtPos(new ChessPosition(2, 3), new ChessPiece(ChessPieceType.Queen, ChessColor.Black, true)),
                new ChessPieceAtPos(new ChessPosition(3, 5), new ChessPiece(ChessPieceType.Queen, ChessColor.Black, true)),
                new ChessPieceAtPos(new ChessPosition(2, 4), new ChessPiece(ChessPieceType.King, ChessColor.Black, true)),
                new ChessPieceAtPos(new ChessPosition(7, 1), new ChessPiece(ChessPieceType.Rook, ChessColor.Black, true)),
            };

            board     = new ChessBoard(pieces);
            enemyDraw = new ChessDraw(board, new ChessPosition(3, 5), new ChessPosition(2, 5));
            board     = board.ApplyDraw(enemyDraw);
            Assert.True(ChessDrawSimulator.Instance.GetCheckGameStatus(board, enemyDraw) == ChessGameStatus.Stalemate);
        }