Exemple #1
0
        /* This is the minimax function with alpha beta pruning
         *
         * Inputs:  board, the current state; depth, the desired search depth;
         *          a, the alpha value; b, the beta value; finalDepth, the total search depth
         * Output:  Tuple<int,int> Result:  Item1 = The heuristic of the move.  Item2 = the move number
         */
        private Tuple <int, int> alphaBeta(Board board, int depth, int a, int b, int finalDepth)
        {
            int v    = 0;
            int v2   = 0;
            int move = -1;

            if (board.gameOver() || depth == 0)
            {
                return(new Tuple <int, int>(0, evaluate(board, finalDepth)));
            }

            if (board.whoseMove() == Position.Top)  // Max player's turn
            {
                v = -99999;
                for (int i = 12; i >= 7; i--)   // Try each of the possible moves
                {
                    if (board.legalMove(i) && (move == -1 || timer.ElapsedMilliseconds < getTimePerMove() - 1))
                    {
                        Board board1 = new Board(board);
                        board1.makeMove(i, false);
                        v2 = alphaBeta(board1, depth - 1, a, b, finalDepth).Item2; // Find value of that move
                        if (v2 > v)                                                // pick the best move
                        {
                            v    = v2;
                            move = i;
                        }
                        a = Math.Max(a, v);
                        if (b <= a)
                        {
                            break;
                        }
                    }
                }
                return(new Tuple <int, int>(move, v)); // Return the result
            }
            else                                       // Minimizing player's turn
            {
                v = 99999;
                for (int i = 5; i >= 0; i--)    // Try each of the possible moves
                {
                    if (board.legalMove(i) && (move == -1 || timer.ElapsedMilliseconds < getTimePerMove() - 1))
                    {
                        Board board1 = new Board(board);
                        board1.makeMove(i, false);
                        v2 = alphaBeta(board1, depth - 1, a, b, finalDepth).Item2; // Find value of that move
                        if (v2 < v)                                                // Pick the best move
                        {
                            v    = v2;
                            move = i;
                        }
                        b = Math.Min(b, v);
                        if (b <= a)
                        {
                            break;
                        }
                    }
                }
                return(new Tuple <int, int>(move, v));    // Return the result
            }
        }
Exemple #2
0
        /*
         * minimax function
         * based on the psuedocode from Prof Plantiga's lecture slides
         */
        private Result minimax(Board b, int depth, int alpha, int beta)
        {
            int bestNum         = 0;
            int currentBestMove = 0;

            if (b.gameOver() || depth == 0)  // game is over or depth is 0
            {
                return(new Result(0, evaluate(b)));
            }

            if (b.whoseMove() == Position.Top) // searching moves for when top player
            {
                bestNum = Int32.MinValue;

                for (int move = 7; move <= 12; move++)
                {
                    if (b.legalMove(move))
                    {
                        Board b1 = new Board(b);
                        b1.makeMove(move, false);

                        Result num = minimax(b1, depth - 1, alpha, beta);
                        if (num.getBestScore() > bestNum)
                        {
                            bestNum         = num.getBestScore();
                            currentBestMove = move;
                        }
                        if (bestNum > alpha)
                        {
                            alpha = bestNum;
                        }
                    }
                }
                return(new Result(currentBestMove, bestNum));
            }
            else // search moves for when bottom player
            {
                bestNum = int.MaxValue;
                for (int move = 0; move <= 5; move++)
                {
                    if (b.legalMove(move))
                    {
                        Board b1 = new Board(b);
                        b1.makeMove(move, false);

                        Result num = minimax(b1, (depth - 1), alpha, beta);
                        if (num.getBestScore() < bestNum)
                        {
                            bestNum         = num.getBestScore();
                            currentBestMove = move;
                        }
                        if (bestNum < beta)
                        {
                            beta = bestNum;
                        }
                    }
                }
                return(new Result(currentBestMove, bestNum));
            }
        }
        private int[] minmaxVal(Board b, int d, float alpha, float beta, ref Stopwatch timer)
        {
            if (d == 0 || b.gameOver())
            {
                return(new int[] { 0, evaluate(b) });
            }
            int[] bestMove = { 0, int.MinValue };
            if (b.whoseMove() == us)
            {
                int bestVal = int.MinValue;
                for (int move = 0; move <= 13; move++)
                {
                    if (b.legalMove(move) && timer.ElapsedMilliseconds < (max_time - 200))
                    {
                        Board b1 = new Board(b);
                        b1.makeMove(move, false);
                        int[] val = minmaxVal(b1, d - 1, alpha, beta, ref timer);
                        if (val[1] > bestVal)
                        {
                            bestVal     = val[1];
                            bestMove[0] = move;
                            bestMove[1] = bestVal;
                        }

                        alpha = Math.Max(alpha, bestMove[1]);
                        if (beta <= alpha)
                        {
                            break;
                        }
                    }
                }
            }
            else
            {
                int bestVal = int.MaxValue;
                bestMove = new int[] { 0, bestVal };
                for (int move = 0; move <= 13; move++)
                {
                    if (b.legalMove(move) && timer.ElapsedMilliseconds < (max_time - 200))
                    {
                        Board b1 = new Board(b);
                        b1.makeMove(move, false);
                        int[] val = minmaxVal(b1, d - 1, alpha, beta, ref timer);
                        if (val[1] < bestVal)
                        {
                            bestVal     = val[1];
                            bestMove[0] = move;
                            bestMove[1] = bestVal;
                        }

                        beta = Math.Min(beta, bestMove[1]);
                        if (beta <= alpha)
                        {
                            break;
                        }
                    }
                }
            }
            return(bestMove);
        }
Exemple #4
0
        /* Minimax search
         * top player is max and bottom is min
         * returns a resulting move from recursive calculations
         */
        private Result minimax(Board board, int depth, int alpha, int beta)
        {
            if (board.gameOver() || depth == 0)
            {
                return(new Result(0, evaluate(board)));
            }

            int bestVal  = int.MinValue;
            int bestMove = 0;

            if (board.whoseMove() == Position.Top)
            {
                for (int move = 7; move < 13 && alpha < beta; move++)
                {
                    if (board.legalMove(move))
                    {
                        Board b1 = new Board(board);
                        b1.makeMove(move, false);
                        Result val = minimax(b1, depth - 1, alpha, beta);
                        if (val.getBestScore() > bestVal)
                        {
                            bestVal  = val.getBestScore();
                            bestMove = move;
                        }
                        if (bestVal > alpha)
                        {
                            alpha = bestVal;
                        }
                    }
                }
            }

            else
            {
                bestVal = Int32.MaxValue;
                for (int move = 0; move < 6 && alpha < beta; move++)
                {
                    if (board.legalMove(move))
                    {
                        Board b1 = new Board(board);
                        b1.makeMove(move, false);
                        Result val = minimax(b1, depth - 1, alpha, beta);
                        if (val.getBestScore() < bestVal)
                        {
                            bestVal  = val.getBestScore();
                            bestMove = move;
                        }
                        if (bestVal < beta)
                        {
                            beta = bestVal;
                        }
                    }
                }
            }
            return(new Result(bestMove, bestVal));
        }
Exemple #5
0
        /* minimax()
         * @param: b, a Board type && d, and int type
         * returns new Result w/ bestMove && bestValue
         * this code follows the pseudocode given in class
         */
        private Result minimaxVal(Board b, int d, int alpha, int beta) //d is depth
        {
            int bestValue = 0;
            int bestMove  = 0;

            if (b.gameOver() || d == 0) //if the game is over or depth is 0
            {
                return(new Result(0, evaluate(b)));
            }
            if (b.whoseMove() == Position.Top)
            { //if TOP is max
                bestValue = Int32.MinValue;
                for (int move = 7; move <= 12 && alpha < beta; move++)
                {
                    if (b.legalMove(move))
                    {
                        Board b1 = new Board(b); //duplicate board
                        b1.makeMove(move, false);
                        Result val = minimaxVal(b1, d - 1, alpha, beta);
                        if (val.GetScore() > bestValue)
                        {
                            bestValue = val.GetScore(); bestMove = move;
                        }
                        if (bestValue > alpha)
                        {
                            alpha = bestValue;
                        }
                    }
                }
                return(new Result(bestMove, bestValue));
            }
            else
            {
                bestValue = int.MaxValue;
                for (int move = 0; move <= 5 && alpha < beta; move++) //bottom row
                {
                    if (b.legalMove(move))
                    {
                        Board b1 = new Board(b);
                        b1.makeMove(move, false);
                        Result val = minimaxVal(b1, d - 1, alpha, beta);
                        if (val.GetScore() < bestValue)
                        {
                            bestValue = val.GetScore(); bestMove = move;
                        }
                        if (bestValue < beta)
                        {
                            beta = bestValue;
                        }
                    }
                }
            }
            return(new Result(bestMove, bestValue));
        }
Exemple #6
0
        /* miniMaxVal implements the minimax search of a board for a given depth
         * @param: board, the Board whose child boards will be evaluated
         * @param: depth, how many generations will be analyzed
         * @return: a Result that is the optimal move and its value
         */
        private Result miniMaxVal(Board board, int depth)
        {
            int bestMove = -1; // dummy value
            int bestVal  = 0;  // dummy value

            if (board.gameOver() || (depth == 0))
            {
                return(new Result(0, evaluate(board)));
            }

            if (board.whoseMove() == Position.Top) // max
            {
                bestVal = -9999999;                // impossible to get less than this
                for (int move = 7; move <= 12; move++)
                {
                    if (board.legalMove(move) && !timeUp)   // stop if the timer has finished
                    {
                        Board boardCopy = new Board(board);
                        boardCopy.makeMove(move, false);
                        Result moveResult = miniMaxVal(boardCopy, depth - 1);
                        if (moveResult.value > bestVal)
                        {
                            bestVal  = moveResult.value;
                            bestMove = move;
                        }
                    }
                }
            }
            else                   // BOTTOM'S MOVE (min)
            {
                bestVal = 9999999; // impossible to get more than this
                for (int move = 0; move <= 5; move++)
                {
                    if (board.legalMove(move) && !timeUp)   // stop if the timer has finished
                    {
                        Board boardCopy = new Board(board);
                        boardCopy.makeMove(move, false);
                        Result moveResult = miniMaxVal(boardCopy, depth - 1);
                        if (moveResult.value < bestVal)
                        {
                            bestVal  = moveResult.value;
                            bestMove = move;
                        }
                    }
                }
            }
            return(new Result(bestMove, bestVal));
        }
Exemple #7
0
        public override int chooseMove(Board b)
        {
            int    move = -1;
            string moveString;

            while (!b.legalMove(move))
            {
                Console.Write("Your move: ");
                moveString = Console.ReadLine();
                if (!int.TryParse(moveString, out move) || !b.legalMove(move))
                {
                    Console.WriteLine("Illegal move. Try again.");
                }
            }
            return(move);
        }
        /// <summary>
        /// MiniMax algorithm for mankalah. Uses the moveResult class, probably doesn't need to and
        /// could use it much more efficiently, but for times sake...
        /// This method finds returns the best move based on its rating.
        /// </summary>
        /// <param name="b"></param> which mankalah board
        /// <param name="d"></param> depth of which algotithm will recurse
        /// <returns></returns>
        private moveResult miniMax(Board b, int d)
        {
            moveResult moveVal     = new moveResult(0, 0);  //uses result class at bottom
            moveResult bestMoveVal = new moveResult(0, 0);  // ^^

            if (b.gameOver() || d == 0)
            {
                return(new moveResult(0, evaluate(b)));                       //evaluate function is simple. Bad thing?
            }
            if (b.whoseMove() == Position.Bottom)
            {
                bestMoveVal.val = 999;
                for (int move = 0; move <= 5; move++)                                   //for all possible moves,
                {
                    if (b.legalMove(move) && myWatch.ElapsedMilliseconds < timePerMove) /*and time not expired*/
                    {
                        Board b1 = new Board(b);                                        //dup board b
                        b1.makeMove(move, false);                                       //make move
                        moveVal = miniMax(b1, d - 1);                                   //recurse and return value
                        if (moveVal.val < bestMoveVal.val)
                        {
                            bestMoveVal = moveVal; bestMoveVal.move = move;
                        }                                                                                     //overwrite if better move
                    }
                }
                return(bestMoveVal); //return best move found.
            }
            else                     //similar comments as above...
            {
                bestMoveVal.val = -999;
                for (int move = 7; move <= 12; move++)
                {
                    if (b.legalMove(move) && myWatch.ElapsedMilliseconds < timePerMove) /*and time not expired*/
                    {
                        Board b1 = new Board(b);                                        //dup board b
                        b1.makeMove(move, false);
                        moveVal = miniMax(b1, d - 1);
                        if (moveVal.val > bestMoveVal.val)
                        {
                            bestMoveVal = moveVal; bestMoveVal.move = move;
                        }
                    }
                }
                return(bestMoveVal);
            }
        }
Exemple #9
0
        public override int chooseMove(Board b)
        {
            int   tL    = 4;
            Timer timer = new Timer(tL);

            timeOut         = false;
            timer.Elapsed  += timeOutTrigger;
            timer.Enabled   = true;
            timer.AutoReset = false;
            timer.Start();
            List <int> choices    = new List <int>();
            int        choice     = 0;
            int        startDepth = 11;

            //Pass in timer to minimax?

            //If the elapsed time matches or exceeds the time limit, break the loop
            while (true)
            {
                if (timeOut || b.gameOver())
                {
                    break;
                }
                Console.WriteLine("Depth: " + startDepth);
                if (startDepth > 20)
                {
                    Console.WriteLine("We might have a problem");
                }
                //If the value of choice is not 0, add it to the list of choices.
                moveResult choiceResult = new moveResult(0, 0);
                if (!timeOut)
                {
                    choiceResult = miniMax(b, startDepth, tL, 1, timer);
                }

                if (choiceResult.getScore() != 0 && b.legalMove(choiceResult.getMove()))
                {
                    //TODO: Adding stuff to a list seems to not work
                    choices.Add(choiceResult.getMove());
                }
                //choice = miniMax(b, startDepth, tL).getScore();


                //TODO: Modify timer and Stop, store and print time elapsed

                //update depth.
                startDepth += 1;
                if (timeOut == true)
                {
                    timer.Stop();
                }
            }

            //Close the timer and return the move from the last item in the list of choices
            timer.Close();
            return(choices.Last());
        }
Exemple #10
0
        public override int chooseMove(Board b)
        {
            int    move;
            Random rnd = new Random();

            while (true)
            {
                move = rnd.Next(13);
                if (b.legalMove(move))
                {
                    return(move);
                }
            }
        }
Exemple #11
0
        //Minimax function. Note that the Max is for the bottom play, It just made more sense to me that way. returns best score and best move.
        private int[] prunedminimax(Board b, int depth, Stopwatch timer, int lastbestscore, Position lastplayer, int playsinarow)
        {
            int[] value = new int[2];
            int   bestscore;

            if (b.whoseMove() == Position.Top) //set the infinity max or infinity min depending on whose turn it is.
            {
                bestscore = 1111111;
            }
            else
            {
                bestscore = -1111111;
            }


            int bestmove = -1;                //returns this number if DFS doesnt finish

            int[] tempvalue = new int[2];     //temporary value that will be used to find the best score and value
            if ((depth > 0 && !b.gameOver())) //as long as game isnt over, or you reached the depth
            {
                bool firstturn = true;        //used to keep track of the first turn
                for (int i = 0; i < 6; i++)
                {
                    if (b.whoseMove() == Position.Top)
                    {
                        if (b.legalMove(i + 7))
                        {
                            Board currentBoard = new Board(b);
                            currentBoard.makeMove(i + 7, false);
                            if (lastplayer == Position.Top)//this is used to keep track of who has had the most turns
                            {
                                tempvalue = prunedminimax(currentBoard, depth - 1, timer, bestscore, Position.Top, playsinarow - 1);
                            }
                            else
                            {
                                tempvalue = prunedminimax(currentBoard, depth - 1, timer, bestscore, Position.Top, playsinarow);
                            }
                            if (firstturn)
                            {
                                bestscore = tempvalue[0];
                                bestmove  = i + 7;
                                firstturn = false;//no longer first turn so set to false
                            }
                            //for non-first turns, check to see if tempvalue is lower then best score.
                            else if (tempvalue[0] < bestscore)
                            {
                                bestscore = tempvalue[0];
                                bestmove  = i + 7;
                            }

                            if ((lastplayer == Position.Bottom) && (bestscore < lastbestscore))
                            {
                                break;                                                                //prunes the branches if necesary.
                            }
                        }
                    }
                    else
                    {
                        if (b.legalMove(i))
                        {
                            Board currentBoard = new Board(b);
                            currentBoard.makeMove(i, false);
                            if (lastplayer == Position.Bottom)
                            {
                                tempvalue = prunedminimax(currentBoard, depth - 1, timer, bestscore, Position.Bottom, playsinarow + 1);
                            }
                            else
                            {
                                tempvalue = prunedminimax(currentBoard, depth - 1, timer, bestscore, Position.Bottom, playsinarow);
                            }
                            if (firstturn)
                            {
                                bestscore = tempvalue[0];
                                bestmove  = i;
                                firstturn = false;
                            }
                            else if (tempvalue[0] > bestscore)
                            {
                                bestscore = tempvalue[0];
                                bestmove  = i;
                            }
                            if ((lastplayer == Position.Top) && (bestscore > lastbestscore))
                            {
                                break;
                            }
                        }
                    }
                    if (!(timer.ElapsedMilliseconds < getTimePerMove() - 10))//if there are only 10 ms till the turn is up,  return -1 for the best move
                    {
                        value[1] = -1;
                        return(value);
                    }
                }
            }
            else //reaches this if it is a node.
            {
                bestscore = evaluate(b, playsinarow);
            }
            value[0] = bestscore;
            value[1] = bestmove;

            return(value);
        }
Exemple #12
0
        public Result miniMax(Board b, int d, int alpha, int beta)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                throw new OperationCanceledException();
            }

            int      bestMove = first;
            int      bestVal  = 0;
            Result   res;
            Position opp;

            if (b.gameOver() || d == 0)
            {
                return(new Result(0, evaluate(b)));
            }

            if (b.whoseMove() == p)
            {     //top is max
                bestVal = -int.MaxValue;
                for (int move = first; move <= last; move++)
                {
                    if (b.legalMove(move))
                    {
                        Board b1 = new Board(b);               //duplicate board
                        b1.makeMove(move, false);              //make the move
                        res = miniMax(b1, d - 1, alpha, beta); //find its value

                        alpha = Math.Max(alpha, res.val);

                        if (res.val > bestVal)
                        {
                            bestVal  = res.val;
                            bestMove = move;
                        }
                        if (alpha >= beta)
                        {
                            break;
                        }
                    }
                }
            }
            else
            { // similarly for bottom’s move
                bestVal = int.MaxValue;
                for (int move = p2first; move <= p2last; move++)
                {
                    if (b.legalMove(move))
                    {
                        Board b1 = new Board(b);               //duplicate board
                        b1.makeMove(move, false);              //make the move
                        res = miniMax(b1, d - 1, alpha, beta); //find its value

                        beta = Math.Min(beta, res.val);

                        if (res.val < bestVal)         //remember if best
                        {
                            bestVal  = res.val;
                            bestMove = move;
                        }
                        if (alpha >= beta)
                        {
                            break;
                        }
                    }
                }
            }

            return(new Result(bestMove, bestVal));
        }
        public int[] minmaxVal(Board b, int depth, float alpha, float beta, ref Stopwatch sw)
        {
            if (depth == 0)
            {
                return new int[] { 0, evaluate(b) }
            }
            ;
            if (b.gameOver())
            {
                maxDepth = depth;

                return(new int[] { 0, endGameEval(b) });
            }
            int[] bestMove = { 0, int.MinValue };

            //our turn -> maximize
            if (b.whoseMove() == us)
            {
                bestMove = new int[] { 0, int.MinValue };
                for (int i = 0; i < 13; i++)
                {
                    if (b.legalMove(i))
                    {
                        if (sw.ElapsedMilliseconds >= timeLimit - 100)
                        {
                            //return new int[] { 0, int.MinValue };
                            return new int[] { i, evaluate(b) }
                        }
                        ;
                        Board modified = SimulateBoard(b, i);

                        int[] newMove = minmaxVal(modified, depth - 1, alpha, beta, ref sw);

                        if (newMove[1] > bestMove[1])
                        {
                            bestMove[0] = i;

                            bestMove[1] = newMove[1];
                            //Console.WriteLine($"Changed bestMove in max to move {i} with value {bestMove[1]}");
                        }

                        alpha = Math.Max(alpha, bestMove[1]);
                        if (beta <= alpha)
                        {
                            break;
                        }
                    }
                }
            }
            //Their turn -> minimize
            else
            {
                bestMove = new int[] { 0, int.MaxValue };

                for (int i = 0; i < 13; i++)
                {
                    if (b.legalMove(i))
                    {
                        if (sw.ElapsedMilliseconds >= timeLimit - 100)
                        {
                            //return new int[] { 0, int.MaxValue };
                            return new int[] { i, evaluate(b) }
                        }
                        ;

                        Board modified = SimulateBoard(b, i);

                        int[] newMove = minmaxVal(modified, depth - 1, alpha, beta, ref sw);

                        if (newMove[1] < bestMove[1])
                        {
                            bestMove[0] = i;

                            bestMove[1] = newMove[1];
                            //Console.WriteLine($"Changed bestMove in min to move {i} with value {bestMove[1]}");
                        }

                        beta = Math.Min(beta, bestMove[1]);
                        if (beta <= alpha)
                        {
                            break;
                        }
                    }
                }
            }

            if (maxDepth != 50)
            {
                maxDepth = depth;
            }
            return(bestMove);
        }
        public int[] minmaxVal(Board b, int d, float alpha, float beta, ref Stopwatch sw)  //d is depth
        {
            if (depth == 0 || b.gameOver())
            {
                return new int[] { 0, evaluate(b) }
            }
            ;
            int[] bestMove = { 0, int.MinValue };

            //our turn -> maximize
            if (b.whoseMove() == us)
            {
                bestMove = new int[] { 0, int.MinValue };

                for (int i = 0; i < 13; i++)
                {
                    if (b.legalMove(i))
                    {
                        if (sw.ElapsedMilliseconds >= timeLimit - 500)
                        {
                            return new int[] { 0, int.MinValue }
                        }
                        ;
                        Board modified = SimulateBoard(b, i);

                        int[] newMove = minmaxVal(modified, depth - 1, alpha, beta, ref sw);

                        if (newMove[1] > bestMove[1])
                        {
                            bestMove[0] = i;

                            bestMove[1] = newMove[1];
                        }

                        alpha = Math.Max(alpha, bestMove[1]);
                        if (beta <= alpha)
                        {
                            break;
                        }
                    }
                }
            }
            //Their turn -> minimize
            else
            {
                bestMove = new int[] { 0, int.MaxValue };

                for (int i = 0; i < 13; i++)
                {
                    if (!b.legalMove(i))
                    {
                        if (sw.ElapsedMilliseconds >= timeLimit - 500)
                        {
                            return new int[] { 0, int.MaxValue }
                        }
                        ;

                        Board modified = SimulateBoard(b, i);

                        int[] newMove = minmaxVal(modified, depth - 1, alpha, beta, ref sw);

                        if (newMove[1] > bestMove[1])
                        {
                            bestMove[0] = i;

                            bestMove[1] = newMove;
                        }

                        beta = Math.Min(beta, bestMove[1]);
                        if (beta <= alpha)
                        {
                            break;
                        }
                    }
                }
            }

            return(bestMove);
        }
    }
Exemple #15
0
        // b = current board state, d = depth, w = clock, alpha and beta to keep track of max/min values for pruning
        private Result minimax(Board b, int d, Stopwatch w, int alpha, int beta)
        {
            // throw exception if time limit has reached
            if (w.ElapsedMilliseconds > getTimePerMove())
            {
                throw new MoveTimedOutException();
            }

            // initialize variables
            int  bestMove = 0;
            int  bestVal;
            bool gameCompleted = false;

            if (b.gameOver() || d == 0)
            {
                return(new Result(0, evaluate(b), b.gameOver()));
            }

            // if it's my move, maximize
            if (b.whoseMove() == mypos)                                  // TOP is MAX
            {
                bestVal = Int32.MinValue;                                // set bestVal to lowest possible number to update later on
                for (int move = myfirst; move <= mylast; move++)         // loop through all possible moves for this player
                {
                    if (b.legalMove(move))                               // if it's a legal move, make that move, look at board and see if it is best move
                    {
                        Board b1 = new Board(b);                         // duplicate board
                        b1.makeMove(move, false);                        // make the move
                        Result val = minimax(b1, d - 1, w, alpha, beta); // find its value
                        if (val.getScore() > bestVal)                    // remember if best maximum
                        {
                            bestVal       = val.getScore();              // update best move, value, and game state after this move
                            bestMove      = move;
                            gameCompleted = val.isEndGame();
                        }
                        // update alpha
                        if (bestVal > alpha)
                        {
                            alpha = bestVal;
                        }
                    }
                }
            }
            // else minimize
            else
            {
                bestVal = Int32.MaxValue;                                // set bestVal to highest possible number to update later on
                for (int move = myfirstOP; move <= mylastOP; move++)     // loop through all possible moves for this player
                {
                    if (b.legalMove(move))                               // if it's a legal move, make that move, look at board and see if it is best move
                    {
                        Board b1 = new Board(b);                         // duplicate board
                        b1.makeMove(move, false);                        // make the move
                        Result val = minimax(b1, d - 1, w, alpha, beta); // find its value
                        if (val.getScore() < bestVal)                    // remember if best minimum
                        {
                            bestVal       = val.getScore();              // update best move, value, and game state after this move
                            bestMove      = move;
                            gameCompleted = val.isEndGame();
                        }
                        // update beta
                        if (bestVal < beta)
                        {
                            beta = bestVal;
                        }
                    }
                }
            }
            // return the Result set with best move,  score, and game status
            return(new Result(bestMove, bestVal, gameCompleted));
        }
Exemple #16
0
        // The function minimax() calculates the best possible move that Chappie can make by
        // recursing as far as it can within the time limit and keeping track of what the best move and
        // score are as it recurses. It is also implemented with AB pruning, meaning that if it
        // starts to go down a path where the outcome will inevitable be worse that our best values,
        // it prunes off that path, therefore saving time to go down a better path.
        private MoveResult minimax(Board b, int d, Stopwatch w, int alpha, int beta)
        {
            // check to see if the time limit is up
            if (w.ElapsedMilliseconds > getTimePerMove())
            {
                throw new MoveTimedOutException();
            }
            // base case
            if (b.gameOver() || d == 0)
            {
                return(new MoveResult(0, evaluate(b), b.gameOver()));
            }
            // initialization of trackers
            int  bestMove = 0;
            int  bestVal;
            bool gameCompleted = false;

            // check all the the moves that top could make, and act as if it is the MAX in minimax
            if (b.whoseMove() == Position.Top) // TOP is MAX
            {
                // smallest possible value so that it can only get better
                bestVal = Int32.MinValue;
                for (int move = 7; move <= 12 && alpha < beta; move++)
                {
                    if (b.legalMove(move))
                    {
                        Board b1 = new Board(b);                               // duplicate board
                        b1.makeMove(move, false);                              // make the move
                        MoveResult val = minimax(b1, d - 1, w, alpha, beta);   // find its value
                        if (val.getScore() > bestVal)                          // remember if best
                        {
                            bestVal  = val.getScore();
                            bestMove = move;
                            // track the current condition of the game
                            gameCompleted = val.isEndGame();
                        }
                        // prune
                        if (bestVal > alpha)
                        {
                            alpha = bestVal;
                        }
                    }
                }
            }
            // check all the the moves that bottom could make, and act as if it is the MIN in minimax
            else  // BOTTOM is MIN
            {
                // lergest possible value so that it can only get better
                bestVal = Int32.MaxValue;
                for (int move = 0; move <= 5 && alpha < beta; move++)
                {
                    if (b.legalMove(move))
                    {
                        Board b1 = new Board(b);                               // duplicate board
                        b1.makeMove(move, false);                              // make the move
                        MoveResult val = minimax(b1, d - 1, w, alpha, beta);   // find its value
                        if (val.getScore() < bestVal)                          // remember if best
                        {
                            bestVal  = val.getScore();
                            bestMove = move;
                            // track the current condition of the game
                            gameCompleted = val.isEndGame();
                        }
                        // prune
                        if (bestVal < beta)
                        {
                            beta = bestVal;
                        }
                    }
                }
            }
            return(new MoveResult(bestMove, bestVal, gameCompleted));
        }
        /* minimaxVal with Alpha-Beta Pruning
         * returns evaluation if it reaches maxDepth, else calculates min or max if it is opponent's turn or my turn respectively
         *
         */
        public DataWrapper minimaxVal(Board b, int d, int alpha, int beta)
        {
            //when time runs out, this evaluates to true
            //when the cancelled execption is thrown, the last best move will be returned in the chooseMove() try->catch statement
            if (cancellationToken.IsCancellationRequested)
            {
                throw new OperationCanceledException();
            }

            //return if reached gameover or max depth
            if (b.gameOver() || d == 0)
            {
                return(new DataWrapper(0, evaluate(b), 0, 0));
            }

            DataWrapper data;

            //look through right positions for moves
            int start = 0;
            int end   = 5;

            if (b.whoseMove() == Position.Top)
            {
                start = 7;
                end   = 12;
            }

            //initialize variables
            int bestMove       = -1;
            int secondBestMove = -1;

            int bestValue       = int.MinValue;
            int secondBestValue = int.MinValue;

            //loop through all possible moves
            for (int move = start; move <= end; move++)
            {
                //if it is a legal move, check the value of it
                if (b.legalMove(move))
                {
                    //create copy of board, make move, and evaluate it by recursing
                    Board newBoard = new Board(b);
                    newBoard.makeMove(move, false);
                    data = minimaxVal(newBoard, d - 1, alpha, beta);

                    //if value, move pair is best or worst, set bestValue and bestMove to it
                    //also set second best value, move pair to previous value
                    if (isBetterMove(b.whoseMove(), bestValue, data.getValue(), d))
                    {
                        secondBestValue = bestValue;
                        bestValue       = data.getValue();

                        secondBestMove = bestMove;
                        bestMove       = move;

                        //alpha beta pruning
                        if (b.whoseMove() == this.position)
                        {
                            alpha = Math.Max(alpha, bestValue);
                        }
                        else
                        {
                            beta = Math.Min(beta, bestValue);
                        }
                    }

                    //if alpha is greater than or equal to beta, we can skip other moves (pruning part of alpha beta pruning)
                    if (alpha >= beta)
                    {
                        break;
                    }
                }
            }

            //return move pairs
            return(new DataWrapper(bestMove, bestValue, secondBestMove, secondBestValue));
        }
Exemple #18
0
        private Result minimaxVal(Board b, int d, Stopwatch w, int alpha, int beta)
        {
            if (w.ElapsedMilliseconds > getTimePerMove())
            {
                throw new MoveTimedOutException();
            }
            int  bestMove = 0;
            int  bestVal;
            bool gameCompleted = false;

            if (b.gameOver() || d == 0)
            {
                return(new Result(0, evaluate(b), b.gameOver()));
            }

            if (b.whoseMove() == Position.Top)
            {
                bestVal = Int32.MinValue;
                for (int move = 7; move <= 12; move++)
                {
                    if (b.legalMove(move))
                    {
                        Board b1 = new Board(b);
                        b1.makeMove(move, false);
                        Result val = minimaxVal(b1, d - 1, w, alpha, beta);
                        if (val.getScore() > bestVal)
                        {
                            bestVal       = val.getScore();
                            bestMove      = move;
                            gameCompleted = val.isEndGame();
                        }
                        if (bestVal > alpha)
                        {
                            alpha = bestVal;
                        }
                    }
                }
            }
            else
            {
                bestVal = Int32.MaxValue;
                for (int move = 0; move <= 5; move++)
                {
                    if (b.legalMove(move))
                    {
                        Board b1 = new Board(b);
                        b1.makeMove(move, false);
                        Result val = minimaxVal(b1, d - 1, w, alpha, beta);
                        if (val.getScore() < bestVal)
                        {
                            bestVal       = val.getScore();
                            bestMove      = move;
                            gameCompleted = val.isEndGame();
                        }
                        if (bestVal < beta)
                        {
                            beta = bestVal;
                        }
                    }
                }
            }
            return(new Result(bestMove, bestVal, gameCompleted));
        }
Exemple #19
0
        //int d is depth of miniMax search. int max should be 1 for getting the max result, -1 for min. Should return moveResult object
        public moveResult miniMax(Board b, int d, double timeLimit, int max, Timer timer)
        {
            //Set up variables
            int        bestVal  = int.MinValue;
            int        bestMove = 0;
            moveResult bestMR   = new moveResult(bestMove, bestVal);

            //Base case: depth is 0, time is up or game is over. Returns a moveResult with the best score value and 0 move value
            if (d == 0 || timeOut || b.gameOver())
            {
                bestVal = evaluate(b);
                //Console.WriteLine("Best score found to be " + bestVal);
                moveResult bestMoveResult = new moveResult(bestMove, bestVal);
                return(bestMoveResult);
            }

            if (b.whoseMove() == Position.Top)
            {
                for (int move = 7; move <= 12; move++)
                {
                    //Console.WriteLine("");
                    //Recurse if the move is legal, time hasn't expired and game isn't over
                    int val = 0;
                    if (b.legalMove(move) && !timeOut && !b.gameOver())
                    {
                        Board b1 = new Board(b);
                        b1.makeMove(move, true);
                        int newDepth = d - 1;

                        //Switch the value of max to be the opposite for the recursion
                        int mnOrMx = max * -1;
                        //Console.WriteLine("Recursing from " + d + " to " + newDepth + "...");
                        val = miniMax(b1, newDepth, timeLimit, mnOrMx, timer).getScore();


                        //If at "max" level, prioritize and return maximum value
                        if (max == 1)
                        {
                            //If there's a new max, update bestValue and bestMove
                            if (val > bestVal)
                            {
                                bestVal  = val;
                                bestMove = move;
                            }
                        }

                        //If at "min" level, prioritize and return minimum value
                        if (max == -1)
                        {
                            //If there's a new min, update bestValue and bestMove
                            if (val < bestVal || val != int.MinValue)
                            {
                                bestVal  = val;
                                bestMove = move;
                            }
                        }
                    }
                }
                bestMR = new moveResult(bestMove, bestVal);
                return(bestMR);
            }
            else
            {
                for (int move = 0; move <= 5; move++)
                {
                    //Console.WriteLine("");
                    //Recurse if the move is legal, time hasn't expired and game isn't over
                    if (b.legalMove(move) && !timeOut && !b.gameOver())
                    {
                        Board b1 = new Board(b);
                        b1.makeMove(move, true);
                        int newDepth = d - 1;

                        //Switch the value of max to be the opposite for the recursion
                        int mnOrMx = max * -1;
                        // Console.WriteLine("Recursing from " + d + " to " + newDepth + "...");
                        int val = miniMax(b1, newDepth, timeLimit, mnOrMx, timer).getScore();
                        // Console.WriteLine("New Value: " + val);

                        //If at "max" level, prioritize and return maximum value
                        if (max == 1)
                        {
                            //If there's a new max, update bestValue and bestMove
                            if (val > bestVal)
                            {
                                bestVal  = val;
                                bestMove = move;
                            }
                        }

                        //If at "min" level, prioritize and return minimum value
                        if (max == -1)
                        {
                            //If there's a new min, update bestValue and bestMove
                            if (val < bestVal || val != int.MinValue)
                            {
                                bestVal  = val;
                                bestMove = move;
                            }
                        }
                    }
                }
                bestMR = new moveResult(bestMove, bestVal);
                return(bestMR);
            }

            //Console.WriteLine("Best move: " + bestMove + " Best score: " + bestVal);
            bestMR = new moveResult(bestMove, bestVal);
            return(bestMR);
        }