Example #1
0
        private void game_PlayerActed(Guid playerId, ActionType action, int amountToCall, int amount)
        {
            var actionBucket = ActionAbstracter.MapToBucket(action, amountToCall, currentGame.PotSize, amount);

            actionHistory.Add(actionBucket);

            FeatureAction featureAction = FeatureActionAbstracter.FromActionBucket(actionBucket);

            var currentPhasehistory = actionHistoriesPerPhase.FirstOrDefault(x => x.Phase == currentGame.Phase);

            currentPhasehistory.ActionHistory.Add(featureAction);

            if (this.Id != playerId)
            {
                Positioning opponentPositioning = Positioning.None;
                Aggression  opponentAggression  = Aggression.None;
                if (currentGame.Phase > GamePhase.PreFlop)
                {
                    opponentPositioning = getOpponentPositioning(currentPhasehistory.ActionHistory.Count);
                    opponentAggression  = getOpponentAggression(opponentPositioning);
                }

                opponent.UpdateFeaturesAfterAction(currentPhasehistory.ActionHistory, currentGame.Phase, opponentAggression, opponentPositioning);
            }
        }
Example #2
0
        /// <summary>
        /// Body or another living has been attacked.
        /// </summary>
        /// <param name="living"></param>
        /// <param name="attackData"></param>
        protected virtual void OnAttacked(AttackData attackData)
        {
            if (attackData == null)
            {
                return;
            }

            if (attackData.Target == Body)
            {
                if (Body.IsReturningToSpawnPoint)
                {
                    Body.CancelWalkToSpawn();
                }

                if (!attackData.IsMeleeAttack)
                {
                    ISpellHandler spellhandler = attackData.SpellHandler;

                    if (spellhandler != null && spellhandler is TauntSpellHandler)
                    {
                        OnTaunted(attackData);
                        return;
                    }
                }

                Aggression.Raise(attackData.Attacker, attackData.Damage);

                // TODO: Process attack data and change the amount of aggro
                //       accordingly.
            }
            else
            {
                OnLivingAttacked(attackData.Target, attackData.Attacker);
            }
        }
Example #3
0
 public void OnUnlinkPet()
 {
     m_Pet        = null;
     m_Anchor     = null;
     m_Aggression = Aggression.Aggressive;
     InvalidateProperties();
 }
Example #4
0
    private bool ShouldTargetHuman <T>(Human otherHuman) where T : IResource
    {
        if (otherHuman.Dead)
        {
            return(false);
        }

        var isFoodSource = typeof(T) == typeof(IFoodSource);
        var aggression   = Aggression.Get(_team, otherHuman._team);

        if (aggression == Aggression.Level.Neutral)
        {
            // Only if I'm starving
            return(isFoodSource && Hunger <= 5);
        }

        if (aggression == Aggression.Level.Aggressive)
        {
            // Only if I'm hungry
            return(isFoodSource && Hunger <= MAX_HUNGER / 2);
        }

        // If we're friendly we'll share, if we're murderous we'll kill
        return(true);
    }
Example #5
0
        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
            int v = reader.ReadInt();

            m_Owner       = reader.ReadMobile();
            m_Pet         = reader.ReadMobile() as DespiseCreature;
            m_LeashLength = (LeashLength)reader.ReadInt();
            m_Aggression  = (Aggression)reader.ReadInt();
            m_Alignment   = (Alignment)reader.ReadInt();
            m_Conscripted = reader.ReadBool();

            switch (reader.ReadInt())
            {
            case 0: break;

            case 1: m_Anchor = reader.ReadMobile(); break;

            case 2: m_Anchor = reader.ReadItem(); break;
            }

            if (m_Anchor == null && m_Pet != null)
            {
                Anchor = m_Owner;
            }

            m_Orbs.Add(this);
        }
Example #6
0
        /// <summary>
        /// An enemy has been killed.
        /// </summary>
        /// <param name="living"></param>
        protected virtual void OnEnemyKilled(GameLiving living)
        {
            if (living == null)
            {
                return;
            }

            Aggression.Remove(living);
        }
Example #7
0
        public static bool CheckCombat(Mobile m, bool restrict = true)
        {
            if (!restrict)
            {
                return(false);
            }

            return(Aggression.CheckHasAggression(m, true));
        }
Example #8
0
    public void ResourceDestroyed(IResource resource, Human culprit)
    {
        if (Dead)
        {
            return;
        }

        if (resource == _targetResource)
        {
            _targetResource = null;
            SetAnimationState(AnimationState.Standing);
            Aggression.Adjust(_team, culprit._team, 5);
        }
    }
Example #9
0
    public AI_FSM(NavMeshAgent _agent, Unit _unit)
    {
        agent = _agent;
        unit = _unit;

        state = State.idle;
        status = Status.inactive;
        aggression = Aggression.defensive;
        timer = 0;
        ally = null;
        enemy = null;
        location = agent.transform.position;
        caller = State.idle;
    }
Example #10
0
        /// <summary>
        /// The NPC has been taunted (spell).
        /// </summary>
        /// <param name="attackData"></param>
        protected virtual void OnTaunted(AttackData attackData)
        {
            GameLiving attacker = attackData.Attacker;

            if (attackData.Target == Body)
            {
                Aggression.Raise(attackData.Attacker, attackData.IsSpellResisted
                    ? 0 : TauntAggressionAmount);
            }
            else
            {
                OnLivingAttacked(attackData.Target, attacker);
            }
        }
Example #11
0
        /// <summary>
        /// The NPC has nothing to do.
        /// </summary>
        protected virtual void OnIdle()
        {
            if (Body == null)
            {
                return;
            }

            foreach (GamePlayer player in Body.GetPlayersInRadius(AggressionRange))
            {
                if (Util.Chance(GetChanceToAggroOn(player)))
                {
                    Aggression.Raise(player, InternalAggression.Initial);
                    return;
                }
            }
        }
Example #12
0
        /// <summary>
        /// An enemy was healed.
        /// </summary>
        /// <param name="source"></param>
        /// <param name="amount"></param>
        protected virtual void OnEnemyHealed(GameObject source, int amount)
        {
            if (source == null)
            {
                return;
            }

            if (source is GameLiving && amount > 1)
            {
                Aggression.Raise(source as GameLiving, amount / 2);
            }

            // TODO: Track the source of the heal, e.g. if the heal originated
            //       from an object, find out who the owner is.
            //       Adjust amount of aggro generated.
        }
Example #13
0
        protected override void WriteDataXML(XElement ele, ElderScrollsPlugin master)
        {
            XElement subEle;

            ele.TryPathTo("Aggression", true, out subEle);
            subEle.Value = Aggression.ToString();

            ele.TryPathTo("Confidence", true, out subEle);
            subEle.Value = Confidence.ToString();

            ele.TryPathTo("EnergyLevel", true, out subEle);
            subEle.Value = EnergyLevel.ToString();

            ele.TryPathTo("Responsibility", true, out subEle);
            subEle.Value = Responsibility.ToString();

            ele.TryPathTo("Mood", true, out subEle);
            subEle.Value = Mood.ToString();

            WriteUnusedXML(ele, master);

            ele.TryPathTo("Services", true, out subEle);
            subEle.Value = Services.ToString();

            ele.TryPathTo("Teaches", true, out subEle);
            subEle.Value = Teaches.ToString();

            ele.TryPathTo("MaxTrainingLevel", true, out subEle);
            subEle.Value = MaxTrainingLevel.ToString();

            ele.TryPathTo("Assistance", true, out subEle);
            subEle.Value = Assistance.ToString();

            ele.TryPathTo("AggroRadiusBehavior", true, out subEle);
            subEle.Value = AggroRadiusBehavior.ToString();

            ele.TryPathTo("AggroRadius", true, out subEle);
            subEle.Value = AggroRadius.ToString();
        }
Example #14
0
        /// <summary>
        /// Pick the next target.
        /// </summary>
        private void PickTarget()
        {
            if (Body.IsIncapacitated)
            {
                return;
            }

            GameLiving target = Aggression.PrimaryTarget;

            if (target == null)
            {
                AttackBehaviour.Retreat();
                Aggression.Clear();
                Body.TargetObject = null;
                AttackBehaviour   = PassiveBehaviour;
                Body.WalkToSpawn();
            }
            else
            {
                if (AttackBehaviour is PassiveBehaviour)
                {
                    AttackBehaviour = (Body.CanCastHarmfulSpells)
                        ? CastingBehaviour
                        : MeleeBehaviour;
                }
                else
                {
                    if (AttackBehaviour is MeleeBehaviour)
                    {
                        if (Body.CanCastHarmfulSpells && Util.Chance(Properties.GAMENPC_CHANCES_TO_CAST))
                        {
                            AttackBehaviour = CastingBehaviour;
                        }
                    }
                }

                AttackBehaviour.Attack(target);
            }
        }
Example #15
0
 public void TakeFood(Human taker)
 {
     if (Aggression.Get(_team, taker._team) == Aggression.Level.Friendly)
     {
         // Sharing is caring
         if (HasFood)
         {
             Food--;
             taker.Feed(1);
         }
     }
     else
     {
         // I have been killed
         Dead = true;
         SetAnimationState(AnimationState.Dying);
         taker.Feed(Food);
         Food = 0;
         // I shall be avenged
         Aggression.Adjust(_team, taker._team, 15);
     }
 }
Example #16
0
        /// <summary>
        /// Check if any past or future action is within bet or fold range depending on opponent's past actions
        /// </summary>
        public FeatureAction?GetCounterAction(List <FeatureAction> possibleActions, List <FeatureAction> lastActions, GamePhase phase, Aggression aggression, Positioning positioning)
        {
            var reversedActions = new List <FeatureAction>(lastActions.ToArray());

            reversedActions.Reverse();

            //is there any past action feature?
            var pastActionFeature = Features.FirstOrDefault(x => x.Phase == phase && x.IsGlobal == false &&
                                                            (x.PreCondition == null ||
                                                             ((x.PreCondition.Aggression == Aggression.None ||
                                                               x.PreCondition.Aggression == aggression) &&
                                                              (x.PreCondition.Positioning == Positioning.None ||
                                                               x.PreCondition.Positioning == positioning) &&
                                                              (x.PreCondition.LastActions.Count == 0 ||
                                                               reversedActions.Take(x.PreCondition.LastActions.Count).SequenceEqual <FeatureAction>(x.PreCondition.LastActions)))));

            if (pastActionFeature != null && pastActionFeature.CountTotal > MinCountThreshold)
            {
                if (pastActionFeature.IsInBetRange)
                {
                    return(FeatureAction.Bet);
                }
                if (pastActionFeature.IsInPassRange)
                {
                    return(FeatureAction.Pass);
                }
            }

            foreach (var possibleAction in possibleActions)
            {
                var actions = new List <FeatureAction>(lastActions.ToArray());
                actions.Add(possibleAction);
                actions.Reverse();

                var futureActionFeature = Features.FirstOrDefault(x => x.Phase == phase && x.IsGlobal == false &&
                                                                  (x.PreCondition != null &&
                                                                   ((x.PreCondition.Aggression == Aggression.None ||
                                                                     x.PreCondition.Aggression == aggression) &&
                                                                    (x.PreCondition.Positioning == Positioning.None ||
                                                                     x.PreCondition.Positioning == positioning) &&
                                                                    (x.PreCondition.LastActions.Count == 0 ||
                                                                     actions.Take(x.PreCondition.LastActions.Count).SequenceEqual <FeatureAction>(x.PreCondition.LastActions)))));

                if (futureActionFeature != null && futureActionFeature.CountTotal > MinCountThreshold)
                {
                    if (futureActionFeature.IsInBetRange)
                    {
                        return(FeatureAction.Bet);
                    }
                    if (futureActionFeature.IsInPassRange)
                    {
                        return(FeatureAction.Pass);
                    }
                }
            }


            return(null);
        }
Example #17
0
 public SentientNpc(string name, int level, char gender, Race race, Caste caste, int team, Aggression aggression, int[] abilityScoreValues = null, MapPoint location = null) :
     base(name, level, gender, race, caste, team, abilityScoreValues, location)
 {
     Aggression = aggression;
 }
Example #18
0
        /// <summary>
        /// Updates the features which are relevant in the current state of the game.
        /// </summary>
        /// <param name="lastActions">Last actions of the current phase</param>
        /// <param name="phase">Phase of the game</param>
        /// <param name="aggression">Aggression of the player</param>
        /// <param name="positioning">Positioning of the player</param>
        public void UpdateFeaturesAfterAction(List <FeatureAction> lastActions, GamePhase phase, Aggression aggression, Positioning positioning)
        {
            //reverse action list to make it easier comparable
            var reversedActions = new List <FeatureAction>(lastActions.ToArray());

            reversedActions.Reverse();
            FeatureAction lastAction = reversedActions[0];

            reversedActions = reversedActions.Skip(1).ToList();

            var featuresToUpdate = Features.Where(x => x.AlreadyIncremented == false &&
                                                  x.Phase == phase &&
                                                  (x.PreCondition == null ||
                                                   ((x.PreCondition.Aggression == Aggression.None ||
                                                     x.PreCondition.Aggression == aggression) &&
                                                    (x.PreCondition.Positioning == Positioning.None ||
                                                     x.PreCondition.Positioning == positioning) &&
                                                    (x.PreCondition.LastActions.Count == 0 ||
                                                     reversedActions.Take(x.PreCondition.LastActions.Count).SequenceEqual <FeatureAction>(x.PreCondition.LastActions)))));

            foreach (var feature in featuresToUpdate)
            {
                if (feature.ActionsToMeasure.Contains(lastAction))
                {
                    feature.Count++;
                    feature.AlreadyIncremented = true;
                }

                if (!feature.IsGlobal)
                {
                    feature.CountTotal++;
                }
            }
        }
Example #19
0
        public override Task <GameActionEntity> GetAction(List <ActionType> possibleActions, int amountToCall)
        {
            var possibleFeatureActions = new List <FeatureAction>();

            foreach (var possibleAction in possibleActions)
            {
                var featureAction = FeatureActionAbstracter.FromActionType(possibleAction);
                if (!possibleFeatureActions.Contains(featureAction))
                {
                    possibleFeatureActions.Add(featureAction);
                }
            }

            var         currentPhasehistory = actionHistoriesPerPhase.FirstOrDefault(x => x.Phase == currentGame.Phase);
            Positioning opponentPositioning = Positioning.None;
            Aggression  opponentAggression  = Aggression.None;

            if (currentGame.Phase > GamePhase.PreFlop)
            {
                opponentPositioning = getOpponentPositioning(currentPhasehistory.ActionHistory.Count);
                opponentAggression  = getOpponentAggression(opponentPositioning);
            }

            var          counterAction        = opponent.GetCounterAction(possibleFeatureActions, currentPhasehistory.ActionHistory, currentGame.Phase, opponentAggression, opponentPositioning);
            ActionBucket selectedActionBucket = ActionBucket.None;

            if (counterAction == null)
            {
                if (currentGame.Phase == GamePhase.PreFlop)
                {
                    switch (opponent.PlayStyle)
                    {
                    case PlayStyle.LooseAggressive:
                    case PlayStyle.LoosePassive:
                        if (this.IsBigBlind)
                        {
                            selectedActionBucket = ActionBucket.LowBet;
                        }
                        else
                        {
                            if (startHandBucket >= StartHandBucket.VeryBad)
                            {
                                selectedActionBucket = ActionBucket.LowBet;
                            }
                            else
                            {
                                selectedActionBucket = ActionBucket.Pass;
                            }
                        }

                        break;

                    case PlayStyle.TightAggressive:
                    case PlayStyle.TightPassive:
                        //play hyper aggressive
                        selectedActionBucket = ActionBucket.LowBet;
                        break;
                    }
                }
                else
                {
                    switch (opponent.PlayStyle)
                    {
                    case PlayStyle.LooseAggressive:
                        //play TightAggressive
                        if (handStrengthBucket >= HandStrengthBucket.HighCardAce)
                        {
                            selectedActionBucket = ActionBucket.LowBet;
                        }
                        else
                        {
                            selectedActionBucket = ActionBucket.Pass;
                        }
                        break;

                    case PlayStyle.LoosePassive:
                        selectedActionBucket = ActionBucket.LowBet;
                        break;

                    case PlayStyle.TightAggressive:
                        //play LooseAggressive
                        if (handStrengthBucket >= HandStrengthBucket.LowPair)
                        {
                            selectedActionBucket = ActionBucket.LowBet;
                        }
                        else
                        {
                            selectedActionBucket = ActionBucket.Pass;
                        }
                        break;

                    case PlayStyle.TightPassive:
                        //play LooseAggressive
                        if (handStrengthBucket >= HandStrengthBucket.HighCardElse)
                        {
                            selectedActionBucket = ActionBucket.LowBet;
                        }
                        else
                        {
                            selectedActionBucket = ActionBucket.Pass;
                        }
                        break;
                    }
                }
            }
            else
            {
                if (currentGame.Phase == GamePhase.PreFlop)
                {
                    switch (counterAction)
                    {
                    case FeatureAction.Bet:
                        if (startHandBucket > StartHandBucket.Worst)
                        {
                            selectedActionBucket = ActionBucket.LowBet;
                        }
                        break;

                    case FeatureAction.Pass:
                        if (startHandBucket < StartHandBucket.Bad)
                        {
                            selectedActionBucket = ActionBucket.Pass;
                        }
                        break;
                    }
                }
                else
                {
                    switch (counterAction)
                    {
                    case FeatureAction.Bet:
                        selectedActionBucket = ActionBucket.LowBet;
                        break;

                    case FeatureAction.Pass:
                        if (handStrengthBucket < HandStrengthBucket.LowPair)
                        {
                            selectedActionBucket = ActionBucket.Pass;
                        }
                        break;
                    }
                }
            }

            switch (selectedActionBucket)
            {
            case ActionBucket.None:
                //no counter move has been found. Fall back to randomness
                randomBot.ChipStack = this.ChipStack;
                return(randomBot.GetAction(possibleActions, amountToCall));

            default:
                ActionType selectedAction = ActionAbstracter.MapToAction(selectedActionBucket, amountToCall);
                int        betSize        = 0;
                switch (selectedAction)
                {
                case ActionType.Bet:
                case ActionType.Raise:
                    betSize = ActionAbstracter.GetBetSize(selectedActionBucket, amountToCall, currentGame.PotSize);
                    break;

                case ActionType.Call:
                    betSize = amountToCall;
                    break;
                }


                if (!possibleActions.Contains(selectedAction))
                {
                    switch (selectedAction)
                    {
                    case ActionType.Bet:
                    case ActionType.Raise:
                    case ActionType.Check:
                        if (possibleActions.Contains(ActionType.Call))
                        {
                            selectedAction = ActionType.Call;
                        }
                        break;

                    default:
                        throw new Exception("Selected action is illegal!");
                    }
                }

                if (ChipStack < betSize)
                {
                    betSize = this.ChipStack;
                }

                return(Task.FromResult <GameActionEntity>(
                           new GameActionEntity
                {
                    ActionType = selectedAction,
                    Amount = betSize,
                    PlayerId = this.Id
                }));
            }
        }
Example #20
0
 public void OnUnlinkPet()
 {
     m_Pet = null;
     m_Anchor = null;
     m_Aggression = Aggression.Following;
     InvalidateProperties();
 }
Example #21
0
 /// <summary>
 /// Check whether or not this living is an enemy.
 /// </summary>
 /// <param name="living"></param>
 /// <returns></returns>
 protected bool IsEnemy(GameLiving living)
 {
     return((living == null)
         ? false
         : (Aggression.IsEnemy(living)));
 }
Example #22
0
        /// <summary>
        /// Process game events.
        /// </summary>
        /// <param name="e"></param>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        public override void Notify(DOLEvent e, object sender, EventArgs args)
        {
            base.Notify(e, sender, args);

            // Process body only related events first.

            if (sender == Body)
            {
                if (e == GameNPCEvent.ArriveAtSpawnPoint)
                {
                    Body.TurnTo(Body.SpawnHeading);
                    return;
                }

                if (e == GameLivingEvent.Interrupted || e == GameLivingEvent.CastFailed ||
                    e == GameNPCEvent.CastFailed)
                {
                    AttackBehaviour = MeleeBehaviour;
                    PickTarget();
                    return;
                }

                if (e == GameLivingEvent.CastFinished || e == GameNPCEvent.CastFinished ||
                    e == GameLivingEvent.CrowdControlExpired ||
                    e == GameLivingEvent.InterruptExpired)
                {
                    PickTarget();
                    return;
                }

                if (e == GameLivingEvent.CrowdControlled)
                {
                    Body.TargetObject = null;
                    return;
                }
            }

            if (e == GameLivingEvent.AttackedByEnemy)
            {
                if (args is AttackedByEnemyEventArgs)
                {
                    AttackData attackData = (args as AttackedByEnemyEventArgs).AttackData;
                    OnAttacked(attackData);
                }

                return;
            }

            if (e == GameLivingEvent.EnemyHealed)
            {
                if (args is EnemyHealedEventArgs)
                {
                    EnemyHealedEventArgs healed = args as EnemyHealedEventArgs;

                    if (IsEnemy(healed.Enemy))
                    {
                        OnEnemyHealed(healed.HealSource, healed.HealAmount);
                    }
                }

                return;
            }

            if (e == GameLivingEvent.EnemyKilled)
            {
                if (args is EnemyKilledEventArgs)
                {
                    EnemyKilledEventArgs killed = args as EnemyKilledEventArgs;

                    if (IsEnemy(killed.Target))
                    {
                        OnEnemyKilled(killed.Target);
                    }
                }

                return;
            }

            if (e == GameLivingEvent.LowHealth)
            {
                OnLowHealth(sender as GameLiving);
                return;
            }

            if (e == GameLivingEvent.Dying)
            {
                if (sender == Body)
                {
                    Aggression.Clear();
                }

                // Aredhel: Although GameLivingEvent.Dying clearly is a GameLiving
                // event, DyingEventArgs.Killer is a mere GameObject. It might make
                // sense to send this event for GameObjects if, for example, the
                // GameObjects belonged to this brain's body and could be re-summoned.

                if (args is DyingEventArgs)
                {
                    OnDying(sender as GameObject, (args as DyingEventArgs).Killer);
                }

                return;
            }
        }
Example #23
0
		public override void Deserialize(GenericReader reader)
		{
			base.Deserialize(reader);
			int v = reader.ReadInt();
			
			m_Owner = reader.ReadMobile();
			m_Pet = reader.ReadMobile() as DespiseCreature;
			m_LeashLength = (LeashLength)reader.ReadInt();
			m_Aggression = (Aggression)reader.ReadInt();
			m_Alignment = (Alignment)reader.ReadInt();
            m_Conscripted = reader.ReadBool();

            switch (reader.ReadInt())
            {
                case 0: break;
                case 1: m_Anchor = (IPoint3D)reader.ReadMobile(); break;
                case 2: m_Anchor = (IPoint3D)reader.ReadPoint3D(); break;
            }

            if (m_Anchor == null && m_Pet != null)
                m_Pet.Home = m_Pet.Location;

			m_Orbs.Add(this);
		}
Example #24
0
 public void ChangeAggression(Aggression aggression)
 {
     CombatManager.ChangeAggression(_creature, aggression);
     _aggression = aggression;
 }
Example #25
0
 public NonSentientNpc(string name, int level, char gender, int team, Aggression aggression, int[] abilityScoreValues = null, Die hitDie = null, MapPoint location = null) :
     base(name, level, gender, team, abilityScoreValues, hitDie, location)
 {
     Aggression = aggression;
 }
Example #26
0
 public override int GetHashCode()
 {
     return(Aggression.GetHashCode());
 }
Example #27
0
    public override void _Process(float delta)
    {
        if (Dead)
        {
            return;
        }

        Thirst -= delta;
        Hunger -= delta;

        if (Thirst < MAX_THIRST / 2)
        {
            var waterSource = _targetResource as IWaterSource;
            if (waterSource == null || !waterSource.HasWater)
            {
                // Seek water
                var waterSources = new List <IWaterSource>();
                Group.CallGroup(GetTree(), Group.WaterSources, source =>
                {
                    if (source.HasWater)
                    {
                        waterSources.Add(source);
                    }
                });
                TargetClosestResource(waterSources);
                waterSource = _targetResource as IWaterSource;
            }

            if (waterSource != null && waterSource.HasWater && Position.DistanceSquaredTo(_targetPosition) <= INTERACTION_RADIUS_SQUARED)
            {
                waterSource.TakeWater(this);
                _targetResource = null;
            }
        }
        else if (Hunger < MAX_HUNGER / 2)
        {
            if (Food > 0)
            {
                // If we have food, eat
                Eat();
            }
            else
            {
                // Otherwise, seek food
                var foodSource = _targetResource as IFoodSource;
                if (foodSource == null || !foodSource.HasFood)
                {
                    var foodSources = new List <IFoodSource>();
                    Group.CallGroup(GetTree(), Group.FoodSources, source =>
                    {
                        if (!source.HasFood)
                        {
                            return;
                        }

                        var humanSource = source as Human;
                        if (humanSource != null)
                        {
                            if (!ShouldTargetHuman <IFoodSource>(humanSource))
                            {
                                return;
                            }
                        }

                        foodSources.Add(source);
                    });
                    TargetClosestResource(foodSources);
                    foodSource = _targetResource as IFoodSource;
                }

                if (foodSource != null && foodSource.HasFood && Position.DistanceSquaredTo(_targetPosition) <= INTERACTION_RADIUS_SQUARED)
                {
                    foodSource.TakeFood(this);
                    _targetResource = null;
                }
            }
        }
        else
        {
            // Not thirsty and not hungry. Anyone we wanna murder nearby?
            var murderTarget = _targetResource as Human;
            if (murderTarget == null || murderTarget.Dead)
            {
                var peopleIWantToKill = new List <Human>();
                Group.Humans.Call(GetTree(), human =>
                {
                    if (human.Dead || Position.DistanceSquaredTo(human.Position) > RAGE_RADIUS_SQUARED)
                    {
                        return;
                    }

                    var aggression = Aggression.Get(_team, human._team);
                    if (aggression == Aggression.Level.Murderous)
                    {
                        peopleIWantToKill.Add(human);
                    }
                });
                TargetClosestResource(peopleIWantToKill);
            }

            murderTarget = _targetResource as Human;
            if (murderTarget != null && !murderTarget.Dead && Position.DistanceSquaredTo(murderTarget.Position) <= RAGE_RADIUS_SQUARED)
            {
                // Humans can move, so update the target position regularly
                _targetPosition = murderTarget.Position;
                if (Position.DistanceSquaredTo(_targetPosition) <= INTERACTION_RADIUS_SQUARED)
                {
                    // This will kill them and take all their stuff. Nice!
                    murderTarget.TakeFood(this);
                    _targetResource = null;
                }
            }
        }

        if (_targetResource != null)
        {
            SetAnimationState(AnimationState.Walking);
            var velocity = (_targetPosition - Position).Normalized() * SPEED * delta;
            Position += velocity;
        }
        else
        {
            SetAnimationState(AnimationState.Standing);
        }

        if (Thirst <= 0 || Hunger <= 0)
        {
            Dead = true;
            SetAnimationState(AnimationState.Dying);
        }
    }