Пример #1
0
        public void PlaceDomino(DominoController domino)
        {
            if (!mFirstDominoSet)
            {
                mFirstDominoSet = true;
            }

            mPickNewDomino = true;
            GameOnHold     = true;
            mBoardController.AddDomino(domino);
        }
Пример #2
0
        /// <summary>
        ///  Alpha Beta search for optimal move
        ///
        /// </summary>
        /// <param name="board"></param>
        /// <param name="domino"></param>
        /// <param name="mAlpha"></param>
        /// <param name="beta"></param>
        /// <param name="depth">depth to search - 0 is base case</param>
        /// <param name="maxDepth">maximize vs. minimize</param>
        /// <returns></returns>
        public int AlphaBeta(BoardController board, int alpha, int beta, int depth,
                             bool maximizeScore, bool player1Playing,
                             ref int optimalRow, ref int optimalCol, ref int optimalRotation, List <IDomino> myDominoes, List <IDomino> enemyDominoes,
                             out IDomino playedDomino)
        {
            playedDomino = null;

            // if we're at depth zero , just return board value
            if (depth == 0)
            {
#if TESTALPHABETA
                Debug.WriteLine("alphaBeta depth 0 Calculate Board Value");
#endif
                return(player1Playing ? -board.GetBoardValue() : board.GetBoardValue());
            }

            // search bounds
            int minRow, maxRow, minColumn, maxColumn;

            //For the First Move only Domino Rotation is allowed;
            if (!(GamePlayManager.Instance.FirstDominoSet))
            {
                minRow    = board.StartPosition;
                maxRow    = board.StartPosition + 1;
                minColumn = board.StartPosition;
                maxColumn = board.StartPosition + 1;
            }
            else
            {
                minRow    = Math.Max(0, board.BoundingBox.RowMin - 2);
                maxRow    = Math.Min(board.Size, board.BoundingBox.RowMax + 3);
                minColumn = Math.Max(0, board.BoundingBox.ColumnMin - 2);
                maxColumn = Math.Min(board.Size, board.BoundingBox.ColumnMax + 3);
            }

            // first time this is called, we'll use this to restore
            int boardRowMin    = board.BoundingBox.RowMin;
            int boardRowMax    = board.BoundingBox.RowMax;
            int boardColumnMin = board.BoundingBox.ColumnMin;
            int boardColumnMax = board.BoundingBox.ColumnMax;


            // counts number of follow on moves (if zero, we're at a leaf)
            int positionsAvailable = 0;


#if TESTALPHABETA
            if (depth == mComputerDepth)
            {
                Debug.WriteLine("Start Main Alpha Beta : depth " + mComputerDepth);
            }
            else if (depth > 0)
            {
                Debug.WriteLine("");
                Debug.WriteLine("Start recursive alpha beta depth " + depth);
                Debug.WriteLine("myDominoes");
                foreach (IDomino idomino in myDominoes)
                {
                    if (!(idomino == null))
                    {
                        Debug.WriteLine("  Domino row " + idomino.Controller.Row + " Column " + idomino.Controller.Column + " label " + idomino.Controller.Label);
                    }
                }
                Debug.WriteLine("Ennemy Dominoes");
                foreach (IDomino idomino in enemyDominoes)
                {
                    if (!(idomino == null))
                    {
                        Debug.WriteLine("  Domino row " + idomino.Controller.Row + " Column " + idomino.Controller.Column + " label " + idomino.Controller.Label);
                    }
                }
                if (maximizeScore)
                {
                    Debug.WriteLine("Max Node " + "beta " + beta + " alpha" + alpha);
                }
                else
                {
                    Debug.WriteLine("Min Node " + "beta " + beta + " alpha" + alpha);
                }
            }
#endif
            //state of bag


            //Pick Random Domino in the Bag
            // start in a random location

            int dominoIndex              = mRandom.Next(0, myDominoes.Count) - 1;
            int randomStartRow           = mRandom.Next(minRow, maxRow) - 1;
            int randomStartColumn        = mRandom.Next(minColumn, maxColumn) - 1;
            int randomStartRotationState = mRandom.Next(0, 4) - 1;
            DominoController domino;

            for (int index = 0; index < myDominoes.Count; index++)
            {
                dominoIndex++;
                if (dominoIndex == myDominoes.Count)
                {
                    dominoIndex = 0;
                }
                domino = myDominoes[dominoIndex].Controller;
#if TESTALPHABETA
                Debug.WriteLine("");
                Debug.WriteLine("Check Domino Label " + domino.Label + " depth " + depth + " computer depth " + mComputerDepth);
#endif
                domino.Row           = randomStartRow;
                domino.Column        = randomStartColumn;
                domino.RotationState = randomStartRotationState;

                // perform a grid search (row, col, rotation)
                for (int row = 0; row < (maxRow - minRow); row++)
                {
                    domino.Row++;
                    if (domino.Row == maxRow)
                    {
                        domino.Row = minRow;
                    }
                    for (int column = 0; column < (maxColumn - minColumn); column++)
                    {
                        domino.Column++;
                        if (domino.Column == maxColumn)
                        {
                            domino.Column = minColumn;
                        }
                        for (int rotationState = 0; rotationState < 4; rotationState++)
                        {
                            domino.RotationState++;
                            if (domino.RotationState == 4)
                            {
                                domino.RotationState = 0;
                            }
//                            Debug.WriteLine("Domino Index"+dominoIndex+" Label"+domino.Label+" Row "+ domino.Row+ " Column "+domino.Column+ " RotationState"+ domino.RotationState);

                            // if we can place a domino here, then we'll
                            // begin the recursive search
                            if (GamePlayManager.Instance.IsLegalMove(domino))
                            {
 #if TESTALPHABETA
                                Debug.WriteLine("AlphaBetaDepth" + depth + "(" + mComputerDepth + ")");
#endif
                                // marks this as a possible move
                                positionsAvailable++;
#if TESTALPHABETA
                                if (positionsAvailable == 2)
                                {
                                    rotationState = 4;
                                    row           = maxRow - minRow;
                                    column        = maxColumn - minColumn;
                                    index         = myDominoes.Count;
                                }
#endif
                                // place the domino on the board
                                board.AddDomino(domino);
                                myDominoes.Remove(domino.Parent);

                                if (maximizeScore)
                                {
                                    // this is the recursive call
                                    int score = AlphaBeta(board, alpha, beta, (depth - 1), !maximizeScore, player1Playing, enemyDominoes, myDominoes);
#if TESTALPHABETA
                                    Debug.WriteLine("Score" + score);
#endif
                                    // prune
                                    if (score >= beta)
                                    {
#if TESTALPHABETA
                                        Debug.WriteLine("mScore >= beta: End AlphaBeta with Depth" + depth);
                                        Debug.WriteLine("CUTOFF");
                                        Debug.WriteLine("");
#endif
                                        // undoes the move on the board and bag
                                        myDominoes.Insert(dominoIndex, domino.Parent);
                                        board.PopUndo(domino); //
                                        return(beta);
                                    }

                                    if (score > alpha)
                                    {
                                        alpha = score;
#if TESTALPHABETA
                                        Debug.WriteLine("New alpha " + alpha);
#endif
                                        if (depth == mComputerDepth)
                                        {
#if TESTALPHABETA
                                            Debug.WriteLine("New Optimal Domino: Label " + domino.Label + " Row " + domino.Row + " Column " + domino.Column + " RotationState " + domino.RotationState);
#endif
                                            optimalRow      = domino.Row;
                                            optimalCol      = domino.Column;
                                            optimalRotation = domino.RotationState;
                                            playedDomino    = domino.Parent;
                                        }
                                    }
                                }
                                else
                                {
                                    // this is the recursive call
                                    int score = AlphaBeta(board, alpha, beta, (depth - 1), !maximizeScore, player1Playing, enemyDominoes, myDominoes);
#if TESTALPHABETA
                                    Debug.WriteLine("Score" + score);
#endif
                                    // prune
                                    if (score <= alpha)
                                    {
#if TESTALPHABETA
                                        Debug.WriteLine("mScore<=alpha End AlphaBeta with Depth" + depth);
                                        Debug.WriteLine("CUTOFF");
                                        Debug.WriteLine("");
#endif                                                                //// undoes the move on the board
                                        myDominoes.Insert(dominoIndex, domino.Parent);
                                        board.PopUndo(domino);
                                        return(alpha);
                                    }
                                    if (score < beta)
                                    {
                                        beta = score;
#if TESTALPHABETA
                                        Debug.WriteLine("New beta " + beta);
#endif
                                        if (depth == mComputerDepth)
                                        {
                                            optimalRow      = domino.Row;
                                            optimalCol      = domino.Column;
                                            optimalRotation = domino.RotationState;
                                            playedDomino    = domino.Parent;
                                        }
                                    }
                                }
                                // restore board state
                                myDominoes.Insert(dominoIndex, domino.Parent);
                                board.PopUndo(domino);
                            }
                        }
                    }
                }
#if TESTALPHABETA
                Debug.WriteLine(positionsAvailable + " Positions Available: try another Domino in the Bag ");
#endif
            }

            // restore the board's row min/max state
            board.BoundingBox.RowMin    = boardRowMin;
            board.BoundingBox.RowMax    = boardRowMax;
            board.BoundingBox.ColumnMin = boardColumnMin;
            board.BoundingBox.ColumnMax = boardColumnMax;


            // leaf case
            if (positionsAvailable == 0)
            {
#if TESTALPHABETA
                Debug.WriteLine("No Position Available (Leaf Case)");
                Debug.WriteLine("Board Value" + board.GetBoardValue());
                Debug.WriteLine("End AlphaBeta with Depth" + depth);
                //TODO                domino.UpdateDominoLocation();
                Debug.WriteLine("");
                Debug.WriteLine("");
#endif

                return(player1Playing ? -board.GetBoardValue() : board.GetBoardValue());
            }
            else
            {
#if TESTALPHABETA
                Debug.WriteLine(positionsAvailable + " Positions Available ");
                if (mComputerDepth == depth)
                {
                    Debug.WriteLine("End Main AlphaBeta with Depth" + depth);
                }
                else
                {
                    Debug.WriteLine("End Recursive AlphaBeta with Depth" + depth);
                }
                if (maximizeScore)
                {
                    Debug.WriteLine("return Max alpha " + alpha);
                }
                else
                {
                    Debug.WriteLine("return Min Beta " + beta);
                }
#endif
                // return alpha value
                return(maximizeScore ? alpha : beta);
            }
        }