Exemple #1
0
        /*
         * Evaluate function to evaluate the nodes of my tree. I added a variable to keep track of how many turns players got.
         * if each player got equal number of turns then the number is 0, if top got more is <0 and opposite for bottom
         * Note: my Max is for the bottom because I could visualize it better that way.
         * */
        public int evaluate(Board b, int playsinarow)
        {
            int score             = b.stonesAt(6) - b.stonesAt(13);
            int stones            = 0;
            int distributedstones = 0;



            for (int i = 0; i < 6; i++)
            {
                stones = stones + (b.stonesAt(i) - b.stonesAt(12 - i));//who has controll of more stones
            }

            if (b.gameOver())
            {
                score += stones; //if game is over add the extra stones to the scores
            }
            int goagains = 0;    //figure out how many go agains may be possible at the begininng of the next turn

            if (b.whoseMove() == Position.Top)
            {
                for (int i = 12; i >= 7; i--)
                {               // try first go-again
                    if (b.stonesAt(i) == 13 - i)
                    {
                        goagains--;
                    }
                    distributedstones = i - 13 + b.stonesAt(i); //find the distribution of the stones
                }
            }
            else
            {
                for (int i = 5; i >= 0; i--)
                {
                    if (b.stonesAt(i) == 6 - i)
                    {
                        goagains++;
                    }
                    distributedstones = 6 - i - b.stonesAt(i);
                }
            }
            //note that plays and go agains are raised to the power of three to conserve signs and help promote sprees.
            return(40 * score + 2 * Convert.ToInt32(Math.Pow((playsinarow + goagains), 3)) + 30 * distributedstones);//weights were found be tweeking to find the most defensive and offensive bot.
        }
Exemple #2
0
        /*
         * Evaluate: return a number saying how much we like this board.
         * TOP is MAX, so positive scores should be better for TOP.
         * This default just counts the score so far. Override to improve!
         */
        public virtual int evaluate(Board b)
        {
            int  score       = 0;
            bool allZeros    = true;
            int  endCaptures = 0;
            int  stonesAt    = 0;

            score += (b.stonesAt(13) - b.stonesAt(6)) * 100;

            for (int i = 12; i >= 7; i--)
            {
                stonesAt = b.stonesAt(i);
                if (b.stonesAt(12 - i) > 0)
                {
                    allZeros = false;
                }
                //if (stonesAt == 0)
                //    score += 2 * b.stonesAt(12 - i);
                endCaptures += stonesAt;
            }
            if (allZeros)
            {
                score += endCaptures * 100;
            }

            allZeros    = true;
            endCaptures = 0;

            for (int i = 5; i >= 0; i--)
            {
                stonesAt = b.stonesAt(i);
                if (b.stonesAt(12 - i) > 0)
                {
                    allZeros = false;
                }
                //if (stonesAt == 0)
                //    score -= 2 * b.stonesAt(12 - i);
                endCaptures += stonesAt;
            }
            if (allZeros)
            {
                score -= endCaptures * 100;
            }

            return(score);
        }
Exemple #3
0
        /*
         * Evaluate: return a number saying how much we like this board.
         * h1 = the difference in score
         * h2 = stones in my home
         * h3 = stones in opponent's home
         * h4 = whether or not to go again
         * h5 = whether or not to capture opponent's pieces
         */
        public override int evaluate(Board b)
        {
            int h1;
            int h2;
            int h3;
            int h4 = 0;
            int h5 = 0;
            int target;
            int captureTarget;
            int score;

            if (me == Position.Top)
            {
                h2 = b.stonesAt(13);    // stones in my home
                h3 = b.stonesAt(6);     // stones in opponent's home
                h1 = h2 - b.scoreBot(); // my margin of winning/losing
                for (int i = 7; i < 13; i++)
                {
                    target        = (i + b.stonesAt(i)) % 12;
                    captureTarget = ((target - 12) + (2 * (12 - target))); // lookup the spot on the opposite of the board for a potential capture
                    if (target == 13 && b.whoseMove() == me)               // if the move will end in my home -- a go-again
                    {
                        h4 = 1;
                    }
                    else if (b.stonesAt(target) == 0 && target > 6 && b.whoseMove() == me) // if it is possible to get a capture
                    {
                        if (b.stonesAt(captureTarget) > 2)                                 // see if capture is worth it
                        {
                            h5 = 50;
                        }
                    }
                }
            }
            else
            { // if I'm on the bottom, do the same thing but changed for the bottom half of the board
                h2 = b.stonesAt(6);
                h3 = b.stonesAt(13);
                h1 = h2 - b.scoreTop();
                for (int i = 0; i < 6; i++)
                {
                    target        = (i + b.stonesAt(i)) % 12;
                    captureTarget = ((target + 12) - (2 * target));
                    if (target == 6 && b.whoseMove() == me)
                    {
                        h4 = 1;
                    }
                    else if (b.stonesAt(target) == 0 && target < 6 && b.whoseMove() == me) // if it is possible to get a capture
                    {
                        if (b.stonesAt(captureTarget) > 2)                                 // see if capture is worth it
                        {
                            h5 = 50;
                        }
                    }
                }
            }
            score = h1 + h2 + h5 + h4;
            score = (me == Position.Top) ? score : -1 * score;
            if (h2 > 24) // if we've won -- really want this
            {
                score += 500;
            }
            else if (h3 > 24) // if opponent has won -- really don't want this
            {
                score -= 500;
            }
            return(score);
        }
Exemple #4
0
        /* Evaluate: override --> consider at least 3 more factors
         * The University of Kansas researched that there are 7
         * factors that play an important role for winning in Mancala
         * for the sake of time, I will focus on 3 of them.
         * total stones, go agains, and captures total
         */


        public override int evaluate(Board b)           // ---> change this
        {
            int score = b.stonesAt(13) - b.stonesAt(6); //followed from example of player class
                                                        //  score = (b.whoseMove() == Position.Top) ? score : -1 * score;
            int totalStones   = 0;
            int goAgainTotal  = 0;
            int capturesTotal = 0;


            if (b.whoseMove() == Position.Top)
            {
                for (int i = 7; i <= 12; i++)          //position == TOP
                {
                    totalStones += b.stonesAt(i);      //add all of the stones in the top row
                    if (b.stonesAt(i) - (13 - i) == 0) //add the times you can go again
                    {
                        goAgainTotal += 1;
                    }
                    int target = i + b.stonesAt(i);
                    if (target < 13)
                    {
                        int tStones = b.stonesAt(target);
                        if (b.whoseMove() == Position.Top)
                        {
                            if (tStones == 0 && b.stonesAt(13 - target - 1) != 0)
                            {
                                capturesTotal += b.stonesAt(13 - target - 1);
                            }
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i <= 5; i++)
                {                                 //position == BOTTOM
                    totalStones -= b.stonesAt(i); //subtract all the stones from the bottom row
                    if (b.stonesAt(i) - (6 - i) == 0)
                    {                             //for the bottom row
                        goAgainTotal -= 1;        //subtract go agains
                    }
                    int target = i + b.stonesAt(i);
                    if (target < 6)
                    {
                        int tStones = b.stonesAt(target);
                        if (b.whoseMove() == Position.Bottom)
                        {
                            if (tStones == 0 && b.stonesAt(13 - target - 1) != 0)
                            {
                                capturesTotal -= b.stonesAt(13 - target - 1);
                            }
                        }
                    }
                }
            }

            capturesTotal = (b.whoseMove() == Position.Top) ? capturesTotal : -1 * capturesTotal;
            totalStones   = (b.whoseMove() == Position.Top) ? totalStones : -1 * totalStones;
            goAgainTotal  = (b.whoseMove() == Position.Top) ? goAgainTotal : -1 * goAgainTotal;


            score += totalStones + capturesTotal + goAgainTotal;
            return(score);
        }
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
        // 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 #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 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);
        }
Exemple #9
0
 /*
  * Evaluate: return a number saying how much we like this board.
  * TOP is MAX, so positive scores should be better for TOP.
  * This default just counts the score so far. Override to improve!
  */
 public virtual int evaluate(Board b)
 {
     return(b.stonesAt(13) - b.stonesAt(6));
 }
Exemple #10
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 #11
0
        /*Evaluate function used when the end game is not clear
         * Uses 5 heuristics found by researchers at the University of Kansas to be the best
         * Heuristic research found at https://fiasco.ittc.ku.edu/publications/documents/Gifford_ITTC-FY2009-TR-03050-03.pdf
         * h1 is my score - opponent's score
         * h2 is how close I am to winning
         * h3 is how close the opponent is to winning
         * h4 is the number of stones close to my home
         * h5 is the number of stones far from my home (on my side of the board)
         */
        public override int evaluate(Board b)
        {
            int h1, h2, h3, h4, h5, h6, target, sum;

            h6 = 0;
            if (us == Position.Top)
            {
                h2 = b.stonesAt(13);
                h3 = b.stonesAt(6);
                h1 = h2 - b.scoreBot();
                h4 = b.stonesAt(11) + b.stonesAt(12);
                h5 = b.stonesAt(7) + b.stonesAt(8);
                for (int i = 7; i < 13; i++)
                {
                    target = i + b.stonesAt(i);
                    if (target == 13)    //calculating go-agains
                    {
                        //if (b.stonesAt(target) == 0 && b.stonesAt(12 - target) != 0)
                        //    h6 += b.stonesAt(12 - target);
                        h6 = 100;
                    }
                }
            }
            else
            {
                h2 = b.stonesAt(6);
                h3 = b.stonesAt(13);
                h1 = h2 - b.scoreTop();
                h4 = b.stonesAt(4) + b.stonesAt(5);
                h5 = b.stonesAt(0) + b.stonesAt(1);
                for (int i = 0; i < 6; i++)
                {
                    target = i + b.stonesAt(i);
                    if (target == 6)    //calculating go-agains
                    {
                        //if (b.stonesAt(target) == 0 && b.stonesAt(12 - target) != 0)
                        //    h6 += b.stonesAt(12 - target);
                        h6 = 100;
                    }
                }
            }
            sum = (h1 + 10) + (h2 + 8) - (h3 + 8) - (h4 + 4) + (h5 + 4) + (h6 + 0);
            sum = (us == Position.Top) ? sum : -1 * sum;
            if (h2 > 24)    //If we have at least half of the stones
            {
                sum += 500;
            }
            else if (h3 > 24)   //If opponent has at least half of the stones
            {
                sum -= 500;
            }
            return(sum);

            //int score;
            //if (us == Position.Top)
            //    score = b.scoreTop() - b.scoreBot();
            //else
            //    score = b.scoreBot() - b.scoreTop();
            //return score;
        }
        /*Evaluate function used when the end game is not clear
         * Uses 5 heuristics found by researchers at the University of Kansas to be the best
         * Heuristic research found at https://fiasco.ittc.ku.edu/publications/documents/Gifford_ITTC-FY2009-TR-03050-03.pdf
         * h1 is my score - opponent's score
         * h2 is how close I am to winning
         * h3 is how close the opponent is to winning
         * h4 is the number of stones close to my home
         * h5 is the number of stones far from my home (on my side of the board)
         */
        public override int evaluate(Board b)
        {
            int h1, h2, h3, h4, h5, sum;

            if (us == Position.Top)
            {
                h2 = b.stonesAt(13);
                h3 = b.stonesAt(6);
                h1 = h2 - b.scoreBot();
                h4 = b.stonesAt(11) + b.stonesAt(12);
                h5 = b.stonesAt(7) + b.stonesAt(8);
            }
            else
            {
                h2 = b.stonesAt(6);
                h3 = b.stonesAt(13);
                h1 = h2 - b.scoreTop();
                h4 = b.stonesAt(4) + b.stonesAt(5);
                h5 = b.stonesAt(0) + b.stonesAt(1);
            }
            sum = (h1 + 10) + (h2 + 8) - (h3 + 8) - (h4 + 4) + (h5 + 4);
            sum = (us == Position.Top) ? sum : -1 * sum;
            if (h2 > 24)    //If we have at least half of the stones
            {
                sum += 500;
            }
            else if (h3 > 24)   //If opponent has at least half of the stones
            {
                sum -= 500;
            }
            return(sum);

            //int score;
            //if (us == Position.Top)
            //    score = b.scoreTop() - b.scoreBot();
            //else
            //    score = b.scoreBot() - b.scoreTop();
            //return score;
        }