예제 #1
0
        /*
         * Play one Kalah game with the two given players, with firstPlayer
         * starting. This function returns TOP's score.
         */
        public static int playGame(Player pTop, Player pBot, Position firstPlayer)
        {
            b = new Board(firstPlayer);

            if (firstPlayer == Position.Top)
            {
                Console.WriteLine("Player " + pTop.getName() + " starts.");
            }
            else
            {
                Console.WriteLine("Player " + pBot.getName() + " starts.");
            }

            b.display();

            while (!b.gameOver())
            {
                Console.WriteLine();
                if (b.whoseMove() == Position.Top)
                {
                    move = pTop.chooseMove(b);
                    Console.WriteLine(pTop.getName() + " chooses move " + move);
                }
                else
                {
                    move = pBot.chooseMove(b);
                    Console.WriteLine(pBot.getName() + " chooses move " + move);
                }

                b.makeMove(move, true);                 // last parameter says to be chatty
                b.display();

                if (b.gameOver())
                {
                    if (b.winner() == Position.Top)
                    {
                        Console.WriteLine("Player " + pTop.getName() +
                                          " (TOP) wins " + b.scoreTop() + " to " + b.scoreBot());
                    }
                    else if (b.winner() == Position.Bottom)
                    {
                        Console.WriteLine("Player " + pBot.getName() +
                                          " (BOTTOM) wins " + b.scoreBot() + " to " + b.scoreTop());
                    }
                    else
                    {
                        Console.WriteLine("A tie!");
                    }
                }
                else
                if (b.whoseMove() == Position.Top)
                {
                    Console.WriteLine(pTop.getName() + " to move.");
                }
                else
                {
                    Console.WriteLine(pBot.getName() + " to move.");
                }
            }
            return(b.scoreTop());
        }
예제 #2
0
        /* 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));
        }
예제 #3
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);
        }
예제 #4
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);
        }
예제 #5
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));
        }