private MapNodeDecisionTree BuildDecisionTree(MapNode head, int recurseLevel)
        {
            MapNodeDecisionTree decisionNode = new MapNodeDecisionTree(head);

            if (recurseLevel > 0)
            {
                foreach (MapNode neighbor in head.GetNeighbors().Distinct(new MapNodeColorComparer()))
                {
                    MapNode headClone = head.Clone();
                    headClone.PickColor(neighbor.Color); //make the move
                    MapNodeDecisionTree childNode = BuildDecisionTree(headClone, recurseLevel - 1);
                    decisionNode.Children.Add(childNode);
                }
            }
            return(decisionNode);
        }
 /// <summary>
 /// Walks down each "branch" of the currentDecisionTree to see which has the best surface area
 /// </summary>
 /// <param name="currentDecisionTree"></param>
 /// <param name="bestSurfaceArea"></param>
 /// <param name="highestColorStack"></param>
 /// <returns>The colors that result in the highest decision tree</returns>
 private SurfaceAreaResult GetBest(MapNodeDecisionTree currentDecisionTree, SurfaceAreaResult bestSurfaceArea, Stack <Color> highestColorStack)
 {
     highestColorStack.Push(currentDecisionTree.Color); //mirror the execution stack
     if (GetSurfaceArea(currentDecisionTree.CurrentMap) > bestSurfaceArea.SurfaceArea)
     {
         bestSurfaceArea.SurfaceArea = GetSurfaceArea(currentDecisionTree.CurrentMap);
         bestSurfaceArea.Path        = highestColorStack.ToArray();
     }
     foreach (MapNodeDecisionTree decisionTreeChild in currentDecisionTree.Children)
     {
         SurfaceAreaResult childSurfaceArea = GetBest(decisionTreeChild, bestSurfaceArea, highestColorStack);
         if (childSurfaceArea.SurfaceArea > bestSurfaceArea.SurfaceArea)
         {
             bestSurfaceArea = childSurfaceArea;
         }
     }
     highestColorStack.Pop(); //mirror the execution stack
     return(bestSurfaceArea);
 }
        public override SuggestedMoves ChooseColor(Color[,] board)
        {
            MapNode head = MapBuilder.BuildMap(board);

            MapNodeDecisionTree decisionTree            = BuildDecisionTree(head.Clone(), _lookAheadLevel);
            Stack <Color>       currentDecisionTreePath = new Stack <Color>();
            SurfaceAreaResult   bestSurfaceArea         = GetBest(decisionTree, new SurfaceAreaResult {
                SurfaceArea = 0, Path = new Color[0]
            }, currentDecisionTreePath);

            //convert the result to SuggestedMove
            SuggestedMoves moves = new SuggestedMoves();

            for (int i = 0; i < bestSurfaceArea.Path.Length - 1; i++)
            {
                moves.AddFirst(new SuggestedMove(bestSurfaceArea.Path[i]));
            }
            return(moves);
        }