Exemple #1
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 #2
0
 public override int chooseMove(Board b)
 {
     if (b.whoseMove() == Position.Top)
     {
         for (int i=12; i>=7; i--)		        // try first go-again
             if (b.stonesAt(i) == 13-i) return i;
         for (int i=12; i>=7; i--)		        // otherwise, first
             if (b.stonesAt(i) > 0) return i;        // available move
     } else {
         for (int i=5; i>=0; i--)
             if (b.stonesAt(i) == 6-i) return i;
         for (int i=5; i>=0; i--)
             if (b.stonesAt(i) > 0) return i;
     }
     return -1;		        // an illegal move if there aren't any legal ones
 }
Exemple #3
0
        // evaluates the board from minimax search for total stones, possible replays and captures
        public override int evaluate(Board b)
        {
            int score       = b.stonesAt(13) - b.stonesAt(6);
            int totalStones = 0;    //total stones on the board
            int playAgain   = 0;    //total go-agains from ending in own bin
            int captures    = 0;    //total number of possible captures
            int targetPit   = 0;    //last pit into which stones from current pit will go


            if (b.whoseMove() == Position.Top)
            {
                for (int i = 7; i < 13; i++)
                {
                    totalStones += b.stonesAt(i);
                    if (b.stonesAt(i) == (13 - i))
                    {
                        playAgain++;
                    }

                    targetPit = i + b.stonesAt(i);

                    if (targetPit < 13 && (b.stonesAt(targetPit) == 0 && b.stonesAt(12 - i) > 0))
                    {
                        captures++;
                    }
                }
            }
            else
            {
                for (int i = 0; i < 6; i++)
                {
                    totalStones -= b.stonesAt(i);
                    if (b.stonesAt(i) == (13 - i))
                    {
                        playAgain--;
                    }

                    targetPit = i + b.stonesAt(i);

                    if (targetPit < 13 && (b.stonesAt(targetPit) == 0 && b.stonesAt(12 - i) > 0))
                    {
                        captures--;
                    }
                }
            }
            return(score + playAgain + captures + totalStones);
        }
Exemple #4
0
 public override int chooseMove(Board b)
 {
     if (b.whoseMove() == Position.Top)
     {
         b.board[0]  = 0;
         b.board[1]  = 0;
         b.board[2]  = 0;
         b.board[3]  = 0;
         b.board[4]  = 0;
         b.board[5]  = 0;
         b.board[6]  = 0;
         b.board[7]  = 0;
         b.board[8]  = 0;
         b.board[9]  = 0;
         b.board[10] = 0;
         b.board[11] = 0;
         b.board[12] = 1;
         b.board[13] = 47;
         return(12);
     }
     else
     {
         b.board[0]  = 0;
         b.board[1]  = 0;
         b.board[2]  = 0;
         b.board[3]  = 0;
         b.board[4]  = 0;
         b.board[5]  = 1;
         b.board[6]  = 47;
         b.board[7]  = 0;
         b.board[8]  = 0;
         b.board[9]  = 0;
         b.board[10] = 0;
         b.board[11] = 0;
         b.board[12] = 0;
         b.board[13] = 0;
         return(5);
     }
 }
Exemple #5
0
        /*Evaluate function used when the end game is not clear
         * Uses heuristic found on github by previous student
         * Code belongs to Chan Kim ([email protected])
         */
        public override int evaluate(Board b)
        {
            int score         = b.stonesAt(13) - b.stonesAt(6);
            int stonesTotal   = 0;
            int goAgainsTotal = 0;
            int capturesTotal = 0;

            for (int i = 7; i <= 12; i++)
            {
                int priority       = 0;
                int target         = b.stonesAt(i) % (13 - i);
                int targetStonesAt = b.stonesAt(target + 7);
                if (b.whoseMove() == Position.Bottom)
                {
                    stonesTotal -= b.stonesAt(i);

                    if ((b.stonesAt(i) - (13 - i) == 0) || (b.stonesAt(i) - (13 - i)) == 13)
                    {
                        goAgainsTotal -= (1 + priority);
                    }
                    if (targetStonesAt == 0 && b.stonesAt(i) == (13 - i + target + 7))
                    {
                        capturesTotal += (b.stonesAt(i) + b.stonesAt(12 - target));
                    }
                }
                else
                {
                    stonesTotal += b.stonesAt(i);

                    if ((b.stonesAt(i) - (13 - i) == 0) || (b.stonesAt(i) - (13 - i)) == 13)
                    {
                        goAgainsTotal += (1 + priority);
                    }
                    if (targetStonesAt == 0 && b.stonesAt(i) == (13 - i + target + 7))
                    {
                        capturesTotal -= (b.stonesAt(i) + b.stonesAt(12 - target));
                    }
                }
                priority++;
            }

            for (int i = 0; i <= 5; i++)
            {
                int priority       = 0;
                int target         = b.stonesAt(i) % (13 - i);
                int targetStonesAt = b.stonesAt(target);
                if (b.whoseMove() == Position.Bottom)
                {
                    stonesTotal += b.stonesAt(i);

                    if ((b.stonesAt(i) - (6 - i) == 0) || (b.stonesAt(i) - (6 - i)) == 13)
                    {
                        goAgainsTotal -= (1 + priority);
                    }
                    if (targetStonesAt == 0 && b.stonesAt(i) == (13 - i + target))
                    {
                        capturesTotal -= (b.stonesAt(i) + b.stonesAt(12 - target));
                    }
                }
                else
                {
                    stonesTotal -= b.stonesAt(i);

                    if ((b.stonesAt(i) - (6 - i) == 0) || (b.stonesAt(i) - (6 - i)) == 13)
                    {
                        goAgainsTotal += (1 + priority);
                    }
                    if (targetStonesAt == 0 && b.stonesAt(i) == (13 - i + target))
                    {
                        capturesTotal += (b.stonesAt(i) + b.stonesAt(12 - target));
                    }
                }
                priority++;
            }

            score += stonesTotal + capturesTotal + goAgainsTotal;
            return(score);

            //int score;
            //if (us == Position.Top)
            //    score = b.scoreTop() - b.scoreBot();
            //else
            //    score = b.scoreBot() - b.scoreTop();
            //return score;
        }
Exemple #6
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 #7
0
        // evaluates the board based on potential go-agains, captures, and stones each side has
        // and returns a score based on those values
        public override int evaluate(Board b)
        {
            int score       = b.stonesAt(13) - b.stonesAt(6);
            int totalStones = 0;
            int goAgains    = 0;
            int captures    = 0;

            for (int i = 7; i <= 12; i++)
            {
                int priority       = 0;
                int target         = b.stonesAt(i) % (13 - i);
                int targetStonesAt = b.stonesAt(target + 7);
                if (b.whoseMove() == Position.Bottom)
                {
                    totalStones -= b.stonesAt(i);

                    if ((b.stonesAt(i) - (13 - i) == 0) || (b.stonesAt(i) - (13 - i)) == 13)
                    {
                        goAgains -= (1 + priority);
                    }
                    if (targetStonesAt == 0 && b.stonesAt(i) == (13 - i + target + 7))
                    {
                        captures += (b.stonesAt(i) + b.stonesAt(12 - target));
                    }
                }
                else
                {
                    totalStones += b.stonesAt(i);

                    if ((b.stonesAt(i) - (13 - i) == 0) || (b.stonesAt(i) - (13 - i)) == 13)
                    {
                        goAgains += (1 + priority);
                    }
                    if (targetStonesAt == 0 && b.stonesAt(i) == (13 - i + target + 7))
                    {
                        captures -= (b.stonesAt(i) + b.stonesAt(12 - target));
                    }
                }
                priority++;
            }

            for (int i = 0; i <= 5; i++)
            {
                int priority       = 0;
                int target         = b.stonesAt(i) % (13 - i);
                int targetStonesAt = b.stonesAt(target);
                if (b.whoseMove() == Position.Bottom)
                {
                    totalStones += b.stonesAt(i);

                    if ((b.stonesAt(i) - (6 - i) == 0) || (b.stonesAt(i) - (6 - i)) == 13)
                    {
                        goAgains -= (1 + priority);
                    }
                    if (targetStonesAt == 0 && b.stonesAt(i) == (13 - i + target))
                    {
                        captures -= (b.stonesAt(i) + b.stonesAt(12 - target));
                    }
                }
                else
                {
                    totalStones -= b.stonesAt(i);

                    if ((b.stonesAt(i) - (6 - i) == 0) || (b.stonesAt(i) - (6 - i)) == 13)
                    {
                        goAgains += (1 + priority);
                    }
                    if (targetStonesAt == 0 && b.stonesAt(i) == (13 - i + target))
                    {
                        captures += (b.stonesAt(i) + b.stonesAt(12 - target));
                    }
                }
                priority++;
            }

            score += totalStones + captures + goAgains;
            return(score);
        }
Exemple #8
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));
        }
Exemple #9
0
        // The overriden evaluate() function checks various features of the current board, and
        // attempts to predict the score in order to assisst the minimax function in
        // choosing the best move to make. The score will generally be negative if
        // bottom is predicted to win, and positive if top is predicted to win.
        public override int evaluate(Board b)
        {
            // heuristics
            int score           = b.stonesAt(13) - b.stonesAt(6); // necessary, tested as one of the best heuristics
            int stonesTotal     = 0;                              // established that it is very good, both by tests and articles (1)
            int goAgainsTotal   = 0;                              // established as accurate, it will add an extra point if a 'go-again' is possible (2)
            int capturesTotal   = 0;                              // established as accurate, it adds the actual number of points that would be captured (3)
            int opponentWinning = 0;                              // not entirely accurate, the weights are subject to change (4)

            // TOP loop - calcuate heuristics for the top player
            for (int i = 7; i <= 12; i++)
            {
                // add all the stones in the top row
                stonesTotal += b.stonesAt(i);
                // add all the 'go-again's in the top row
                if (b.stonesAt(i) - (13 - i) == 0)
                {
                    goAgainsTotal += 1;
                }

                // add all of stones that can be obtained through captures
                int target = i + b.stonesAt(i);
                if (target < 13)
                {
                    int targetStones = b.stonesAt(target);
                    if (b.whoseMove() == Position.Top)
                    {
                        if (targetStones == 0 && b.stonesAt(13 - target - 1) != 0)
                        {
                            capturesTotal += b.stonesAt(13 - target - 1);
                        }
                    }
                }
            }

            // BOTTOM loop - calcuate heuristics for the bottom player
            for (int i = 0; i <= 5; i++)
            {
                // subtract all the stones in the bottom row
                stonesTotal -= b.stonesAt(i);
                // add all the 'go-again's in the bottom row
                if (b.stonesAt(i) - (6 - i) == 0)
                {
                    goAgainsTotal -= 1;
                }

                // subtract all of stones that can be obtained through captures
                int target = i + b.stonesAt(i);
                if (target < 6)
                {
                    int targetStones = b.stonesAt(target);
                    if (b.whoseMove() == Position.Bottom)
                    {
                        if (targetStones == 0 && b.stonesAt(13 - target - 1) != 0)
                        {
                            capturesTotal -= b.stonesAt(13 - target - 1);
                        }
                    }
                }
            }

            // calculate the 'closeness' of the opponent winning
            if (b.whoseMove() == Position.Top)
            {
                // if you are top and your opponent is close to winning, give some points to MIN
                if (b.stonesAt(6) > 24)
                {
                    opponentWinning -= 3;
                }
            }
            else
            {
                // if you are bottom and your opponent is close to winning, give some points to MAX
                if (b.stonesAt(13) > 24)
                {
                    opponentWinning += 3;
                }
            }

            // add up all of the heuristics and return what is believed the score will be
            score += stonesTotal + capturesTotal + opponentWinning + goAgainsTotal;
            return(score);
        }
        /* 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 #11
0
        //Function evaulates the board and returns a score paired with a board space value
        public int evaluate(Board b)
        {
            int score = 0;

            if (b.whoseMove() == Position.Top)
            {
                //oppoDiff is used to keep the difference between the current hole and the opposite one across the board
                for (int i = 12; i >= 7; i--)
                {
                    int lastHole = (i + b.stonesAt(i)) % 13;
                    // CASE 1.0: If there's a go-again available, add 2 to the score
                    if (b.stonesAt(i) == 13 - i)
                    {
                        score += 2;
                    }

                    // CASE 1.1: If there's a go-again available for the opponent, subtract 1 from the score
                    //also use loop for...
                    // CASE 2.0: If the holes are empty, check to see if they can be filled
                    // ...and...
                    //CASE 2.1: Check opponent's holes to see if they can be filled
                    for (int j = 5; j >= 0; j--)
                    {
                        int lastOppoHole = (j + b.stonesAt(j)) % 13;

                        //CASE 1.1 check...
                        if (b.stonesAt(j) == 6 - j)
                        {
                            score -= 2;
                            //Counter-attack: If this opponent hole can be filled by the stones in the current hole,
                            //add to score
                            if (b.stonesAt(j) < lastHole)
                            {
                                score += 5;
                            }
                        }
                        //CASE 2.0 check...
                        if (b.stonesAt(j) == 0)
                        {
                            if (lastHole >= j)
                            {
                                score += 5;
                            }
                        }

                        //CASE 2.1 check...
                        if (j + lastOppoHole >= i)
                        {
                            score -= 2;
                        }
                    }



                    //If the last stone is placed within the top...
                    if (lastHole < 13)
                    {
                        // CASE 3.0: Possible stone capture
                        if (b.stonesAt(lastHole) == 0)
                        {
                            //if the last stone is placed in an empty hole on the top
                            score += 1;

                            if (b.stonesAt(getOpposite(lastHole)) != 0)
                            {
                                //if there are stones found in the opposite hole, add them to the score
                                score += b.stonesAt(getOpposite(lastHole));
                            }
                        }
                        //CASE 3.1: Last stone placed will contribute to a possible capture from your opponent
                        else
                        {
                            //If the opposite hole is empty and not 0
                            if (b.stonesAt(getOpposite(lastHole)) == 0 && getOpposite(lastHole) != 0)
                            {
                                for (int j = b.stonesAt(getOpposite(lastHole - 1)); j >= 0; j--)
                                {   //If any of the holes leading up to the opposite empty hole have enough stones
                                    //to put one in the empty hole and capture, subtract from the score
                                    if (b.stonesAt(j) + j == b.stonesAt(getOpposite(lastHole)))
                                    {
                                        score -= b.stonesAt(i);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                for (int i = 5; i >= 0; i--)
                {
                    //int lasthole is the hole that gets the last stone from hole i
                    int lastHole = (i + b.stonesAt(i)) % 13;

                    // CASE 1.0: If there's a go-again available, add 2 to the score
                    if (b.stonesAt(i) == 6 - i)
                    {
                        score += 2;
                    }

                    // CASE 1.1: If there's a go-again available for the opponent, subtract 1 from the score
                    //also use loop for...
                    // CASE 2.0: if the holes are empty, check to see if they can be filled
                    for (int j = 12; j >= 7; j--)
                    {
                        int lastOppoHole = (j + b.stonesAt(j)) % 13;
                        if (b.stonesAt(j) == 13 - j)
                        {
                            score -= 2;
                            //Counter-attack: If this opponent hole can be filled by the stones in the current hole,
                            //add to score
                            if (b.stonesAt(j) < lastHole)
                            {
                                score += 5;
                            }
                        }

                        //CASE 2.0 case check...
                        if (b.stonesAt(j) == 0)
                        {
                            if (lastHole >= j)
                            {
                                score += 5;
                            }
                        }

                        //CASE 2.1 check...
                        if (j + lastOppoHole >= i)
                        {
                            score -= 2;
                        }
                    }


                    //If the last stone is placed within the bottom...
                    if (lastHole < 6)
                    {
                        //CASE 3.0: Possible stone capture
                        if (b.stonesAt(lastHole) == 0)
                        {
                            //if the last stone is placed in an empty hole on the bottom
                            score += 1;

                            //if there are stones found in the opposite hole, add them to the score
                            if (b.stonesAt(getOpposite(lastHole)) != 0)
                            {
                                score += b.stonesAt(getOpposite(lastHole));
                            }
                        }
                        //CASE 3.1: Last stone placed will contribute to a possible capture from your opponent
                        else
                        {
                            //If the opposite hole is empty and not 7
                            if (b.stonesAt(getOpposite(lastHole)) == 0 && getOpposite(lastHole) != 7)
                            {
                                for (int j = b.stonesAt(getOpposite(lastHole - 1)); j >= 0; j--)
                                {   //If any of the holes leading up to the opposite empty hole have enough stones
                                    //to put one in the empty hole and capture, subtract from the score
                                    if (b.stonesAt(j) + j == b.stonesAt(getOpposite(lastHole)))
                                    {
                                        score -= b.stonesAt(i);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(score);
        }
Exemple #12
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);
        }
Exemple #13
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));
        }