public override BehaviorStatus Update(Entity self, double dt)
        {
            BehaviorStatus   status = base.Update(self, dt);
            CitizenComponent citizen;

            switch (status)
            {
            case BehaviorStatus.SUCCESS:
            case BehaviorStatus.FAIL:
                if (Finished is ExitBuildingBehavior)
                {
                    ExitBuildingBehavior exit = (ExitBuildingBehavior)Finished;

                    if (status == BehaviorStatus.SUCCESS)
                    {
                        // make sure the citizen starts at the right position
                        PositionComponent position = self.Get <PositionComponent>();
                        Vector2           startAt  = World.Map.GetPositionFromIndex(exit.SelectedPath.Start.X, exit.SelectedPath.Start.Y);
                        position.X     = startAt.X;
                        position.Y     = startAt.Y;
                        position.Index = exit.SelectedPath.Start;

                        GoToBehavior g2b = new GoToBehavior()
                        {
                            GeneratedPath = exit.SelectedPath,
                            TargetID      = exit.TargetID
                        };
                        AddChild(g2b);
                    }
                }
                else if (Finished is GoToBehavior)
                {
                    if (status == BehaviorStatus.SUCCESS)
                    {
                        if (State == HaulerState.RETURNING)
                        {
                            // Add the items in out inventory to the stockpile
                            Inventory selfInventory = self.Get <Inventory>();

                            // move item back to job inventory
                            if (!string.IsNullOrWhiteSpace(CurrentItem) && selfInventory.Items[CurrentItem].Amount > 0)
                            {
                                citizen = self.Get <CitizenComponent>();
                                Inventory jobInventory = World.Entities.Get(citizen.JobID).Get <Inventory>();

                                jobInventory.Add(CurrentItem, selfInventory.Items[CurrentItem].Amount);
                                selfInventory.Set(CurrentItem, 0);
                            }

                            State = HaulerState.DELIVERING;
                            AddChild(new IdleBehavior()
                            {
                                IdleTime = 0.2
                            });
                        }
                        else if (State == HaulerState.DELIVERING)
                        {
                            // Add the items in out inventory to the stockpile
                            Inventory          selfInventory = self.Get <Inventory>();
                            Entity             se            = World.Entities.Get(((GoToBehavior)Finished).TargetID);
                            StockpileComponent stockpile     = se.Get <StockpileComponent>();

                            int movedAmount = stockpile.AddToItem(CurrentItem, selfInventory.Items[CurrentItem].Amount);
                            selfInventory.Add(CurrentItem, -movedAmount);

                            State = HaulerState.RETURNING;
                            AddChild(new IdleBehavior()
                            {
                                IdleTime = 0.2
                            });
                        }
                    }
                }
                break;

            case BehaviorStatus.RUN:
                citizen = self.Get <CitizenComponent>();

                if (State == HaulerState.RETURNING)
                {
                    AddChild(new ExitBuildingBehavior()
                    {
                        ExitID = citizen.InsideID, TargetID = citizen.JobID
                    });
                }
                else if (State == HaulerState.DELIVERING)
                {
                    Inventory jobInventory    = World.Entities.Get(citizen.JobID).Get <Inventory>();
                    Inventory haulerInventory = self.Get <Inventory>();

                    if (jobInventory.Items.Values.ToList().Find(delegate(InventoryData d) { return(d.Output && d.Amount > 0); }) != null)
                    {
                        List <Entity> stockpiles = World.GetBuildingsWithinWalkableDistance <StockpileComponent>(citizen.JobID, 30);

                        foreach (Entity se in stockpiles)
                        {
                            StockpileComponent stockpile = se.Get <StockpileComponent>();

                            foreach (InventoryData invItem in jobInventory.Items.Values)
                            {
                                if (!invItem.Output)
                                {
                                    continue;
                                }

                                // do the delivery
                                if (stockpile.IsAccepting(invItem.Item) && stockpile.Amount(invItem.Item) < stockpile.Maximum(invItem.Item) && invItem.Amount > 0)
                                {
                                    int amount = Math.Min(invItem.Amount, HaulerCapacity);
                                    haulerInventory.Add(invItem.Item, amount);
                                    jobInventory.Add(invItem.Item, -amount);
                                    CurrentItem = invItem.Item;
                                    AddChild(new ExitBuildingBehavior()
                                    {
                                        ExitID = citizen.InsideID, TargetID = se.ID
                                    });
                                    return(BehaviorStatus.WAIT);
                                }
                            }
                        }
                    }

                    // if no delivery sleep for a bit
                    AddChild(new IdleBehavior());
                }
                break;
            }

            return(BehaviorStatus.WAIT);
        }
        public override BehaviorStatus Update(Entity self, double dt)
        {
            BehaviorStatus status = base.Update(self, dt);

            switch (status)
            {
            // child returned a success
            case BehaviorStatus.SUCCESS:
                if (Finished is ExitBuildingBehavior)
                {
                    ExitBuildingBehavior exit = (ExitBuildingBehavior)Finished;

                    // make sure the citizen starts at the right position
                    PositionComponent position = self.Get <PositionComponent>();
                    Vector2           startAt  = World.Map.GetPositionFromIndex(exit.SelectedPath.Start.X, exit.SelectedPath.Start.Y);
                    position.X     = startAt.X;
                    position.Y     = startAt.Y;
                    position.Index = exit.SelectedPath.Start;

                    GoToBehavior g2b = new GoToBehavior()
                    {
                        GeneratedPath = exit.SelectedPath,
                        TargetID      = exit.TargetID
                    };
                    AddChild(g2b);
                }
                break;

            case BehaviorStatus.FAIL:

                break;

            case BehaviorStatus.RUN:
                // look for a secondary behavior to do
                CitizenComponent citizen = self.Get <CitizenComponent>();

                // TODO: need to implement "archetype" behaviors like: child, student, adult, retired etc
                // these top-level behaviors will manage the needs and invoke appropriate sub-behaviors

                // the citizen is homeless, find them a home!
                if (citizen.HousingID == 0 && PreviousBehavior.GetType() != typeof(FindHomeBehavior))
                {
                    AddChild(new FindHomeBehavior());
                }
                else if (citizen.JobID == 0 && citizen.HousingID != 0 && PreviousBehavior.GetType() != typeof(FindJobBehavior))
                {
                    AddChild(new FindJobBehavior());
                }
                else
                {
                    // do the hauling job
                    if (citizen.IsHauler && citizen.JobID != 0)
                    {
                        AddChild(new HaulerBehavior());
                    }
                    // go to work
                    //else if (citizen.JobID != -1 && PreviousBehavior.GetType() == typeof(IdleBehavior) && citizen.InsideID != citizen.JobID)
                    //{
                    //    state.Push(new ExitBuildingBehavior() { ExitID = citizen.InsideID, TargetID = citizen.JobID });
                    //    PreviousBehavior = state.Peek();
                    //}
                    // go home
                    else if (citizen.HousingID != 0 && PreviousBehavior.GetType() == typeof(IdleBehavior) && citizen.InsideID != citizen.HousingID)
                    {
                        AddChild(new ExitBuildingBehavior()
                        {
                            ExitID = citizen.InsideID, TargetID = citizen.HousingID
                        });
                    }
                    else
                    {
                        AddChild(new IdleBehavior());
                    }
                }
                PreviousBehavior = Child;
                break;
            }

            return(BehaviorStatus.RUN);
        }