IEnumerator ManageGoals()
    {
        while (goalDirectory.GoalList.Count() > 0)
        {
            currentGoal = null;
            foreach (Goal g in goalDirectory.GoalList)
            {
                if (g.IsSatisfied())
                {
                    if (g.Type == GoalType.Pursuit)
                    {
                        Testing.WriteToLog(transform.name, transform.name + " achieved goal: " + g.Name);
                        goalDirectory.RemoveGoal(g);
                    }
                    else if (g.Type == GoalType.Interest && !g.Dormant)
                    {
                        Testing.WriteToLog(transform.name, transform.name + " achieved goal: " + g.Name);
                        g.Dormant = true;
                    }
                    yield return(new WaitForSeconds(manager.GetRandomInt(2, 8)));
                }
                else
                {
                    currentGoal = g;
                    if (currentGoal.Type == GoalType.Interest)
                    {
                        currentGoal.Dormant = false;
                    }
                    break;
                }
            }
            //if the goal isn't satisifed then check if the goal has a plan associated with it.
            if (currentGoal != null)
            {
                if (currentGoal.TimesFailed >= Goal.MaxFail)
                {
                    currentGoal.ClearFailedActions();
                }
                //If the goal hasn't got a plan then let's create one!
                if (currentGoal.Plan == null)
                {
                    Testing.WriteToLog(transform.name, transform.name + " is evaluating " + Testing.GetGoalInfo(currentGoal));
                    //create a plan
                    // Create a LinkedList to store the plans and populate it.
                    PlanList planList = new PlanList();
                    CreatePlans(currentGoal, currentGoal.TargetCharacter, currentGoal.SuccessCondition, planList, new Plan(), currentGoal.FailedActions);
                    // If there are no plans in the collection then the goal is already satisifed or its impossible to reach.
                    if (planList.Count() < 1)
                    {
                        // Set the goal to complete and it will be removed from the collection the next time Update() is run.
                        currentGoal.Complete = true;
                        Testing.WriteToLog(transform.name, transform.name + " cancelled goal: " + currentGoal.Name + " because a plan is impossible to make.");
                        currentGoal.ClearFailedActions();
                        Testing.WriteToLog(transform.name, "Clearing previously failed action list in attempt to satisfy goal...");
                    }
                    // If we successfully constructed one or more plans then we need to pick one for the agent to use.
                    else
                    {
                        Testing.WriteToLog(transform.name, transform.name + " created at least one plan for goal: " + currentGoal.Name);
                        //pick a plan from List<LinkedList<Action>> plans and assign to g.plan
                        currentGoal.SetPlan(planList.GetBestPlan(manager, actionQueue, GetComponent <MemoryManager>(), transform));
                        Testing.WriteToLog(transform.name, transform.name + " nominated a best plan for goal: " + currentGoal.Name + ":");
                        Testing.WriteToLog(transform.name, Testing.GetPlanInfo(currentGoal.Plan));
                    }
                }
                // if the goal has got a plan...
                else
                {
                    //manage its execution
                    Plan   plan          = currentGoal.Plan;
                    Action currentAction = plan.GetCurrentAction();
                    if (currentAction != null)
                    {
                        switch (currentAction.Status)
                        {
                        case Status.notSent:
                            currentAction.SetStatus(Status.Sent);
                            Testing.WriteToLog(transform.name, transform.name + " is queueing action: " + Testing.GetActionInfo(currentAction));
                            actionQueue.QueueAction(currentAction);
                            break;

                        case Status.Resend:
                            currentAction.SetStatus(Status.ResendSent);
                            actionQueue.QueueAction(currentAction);
                            break;

                        case Status.Failed:
                            //action repair
                            currentGoal.TimesFailed++;
                            Testing.WriteToLog(transform.name, transform.name + " failed action: " + Testing.GetActionInfo(currentAction));
                            currentAction.SetStatus(Status.notSent);
                            currentGoal.AddFailedAction(new Action(currentAction));
                            currentGoal.SetPlan(null);
                            Testing.WriteToLog(transform.name, transform.name + " is replanning: " + Testing.GetGoalInfo(currentGoal));
                            yield return(new WaitForSeconds(manager.GetRandomInt(1, 3)));

                            break;

                        case Status.Successful:
                            Testing.WriteToLog(transform.name, transform.name + " succeeded action: " + Testing.GetActionInfo(currentAction));
                            currentAction.SetStatus(Status.notSent);
                            plan.RemoveAction(currentAction);
                            yield return(new WaitForSeconds(manager.GetRandomInt(1, 3)));

                            break;
                        }
                    }
                    else
                    {
                        currentGoal.SetPlan(null);
                    }
                }
            }
            yield return(null);
        }
    }