Beispiel #1
0
 static LandPredatorBrain()
 {
     PredatorTreeRoot = BT.Selector(
         LandAnimalBrain.LyingDownTree,
         BT.If(x => x.Alertness > LandAnimalBrain.AlertThreshold && x.Alertness < LandAnimalBrain.FullyAlertThreshold && x.AnimationState != AnimalAnimationState.Flee && x.AnimationState != AnimalAnimationState.AlertIdle && x.OnFlatGround,
               // play an alert reaction before fleeing and intermittently while alert
               PlayFixedTimeAnimation(AnimalAnimationState.AlertIdle, LandAnimalBrain.AlertIdleTime)),
         MovementBehaviors.Flee,
         GroupBehaviors.SleepNearLeader,
         BT.If(x => x.Hunger > HungerThreshold,
               BT.Selector(
                   TryEatNearbyCorpses,
                   new HuntMemoryBehavior()
     {
         NoNearbyFoodBehavior = LandAnimalBrain.LandAnimalFindFood
     })),
         GroupBehaviors.StayNearLeader(10f),
         //TODO: show a failed chase if there are no corpses neary to eat
         BT.If(MovementBehaviors.ShouldReturnHome,
               MovementBehaviors.WanderHome),
         BT.If(x => x.Alertness < Animal.FleeThreshold && RandomUtil.Chance(LandAnimalBrain.ChanceToLieDown) && x.OnFlatGround,
               PlayAnimation(AnimalAnimationState.LyingDown, LandAnimalBrain.LyingTickDuration)),
         BT.If(x => RandomUtil.Chance(LandAnimalBrain.ChanceToIdle) && x.OnFlatGround,
               PlayAnimation(AnimalAnimationState.Idle, _ => RandomUtil.Range(LandAnimalBrain.MinIdleTime, LandAnimalBrain.MaxIdleTime))),
         MovementBehaviors.Wander);
 }
        public void LayerTick()
        {
            if (this.rate != -1)
            {
                // TODO this should be implemented via pull/interact/push pattern
                foreach (var layer in this.targetLayers)
                {
                    var layerPos   = layer.WorldPosToLayerPos(this.Parent.Position.XZi);
                    var layerValue = layer.SafeEntry(layerPos);

                    // 8 times faster than fish traps
                    if (RandomUtil.Chance(layerValue / (layer.MaxValue * (float)this.rate)))
                    {
                        var organisms = layer.SafePopMapEntry(layerPos);
                        if (organisms == null)
                        {
                            return;
                        }
                        var animal = organisms.Random() as Animal;

                        // give items
                        var newItems = Item.Create(animal.Species.ResourceItem, (int)animal.Species.ResourceRange.Max);
                        if (this.storage.Inventory.TryAddItems(animal.Species.ResourceItem, (int)animal.Species.ResourceRange.Max))
                        {
                            animal.Kill(DeathType.Harvesting);
                        }
                        return;
                    }
                }
            }
            else
            {
                return;
            }
        }
        static FishBrain()
        {
            const float MinIdleTime  = 1f;
            const float MaxIdleTime  = 5f;
            const float ChanceToIdle = 0.3f;

            FishTreeRoot =
                BT.Selector(
                    MovementBehaviors.SwimFlee,
                    BT.If(MovementBehaviors.ShouldReturnHome,
                          MovementBehaviors.SwimWanderHome),
                    BT.If(x => RandomUtil.Chance(1 - ChanceToIdle),
                          MovementBehaviors.SwimWander),
                    PlayAnimation(AnimalAnimationState.Idle, _ => RandomUtil.Range(MinIdleTime, MaxIdleTime))
                    );
        }
Beispiel #4
0
        static FishBrain()
        {
            const float ChanceToWander = 0.7f;

            FishTreeRoot =
                BT.Selector("Fish Brain",
                            BT.If("Try Swim", x => (!x.IsStunned, $"available for swimming"),
                                  BT.Selector("Swimming",
                                              MovementBehaviors.SwimFlee,
                                              BT.If("Try Return Home", MovementBehaviors.ShouldReturnHome,
                                                    MovementBehaviors.SwimWanderHome),
                                              BT.If("Swim Wander", x => (RandomUtil.Chance(ChanceToWander), $"{ChanceToWander.ToString("P0")} chance"),
                                                    MovementBehaviors.SwimWander)
                                              )
                                  ),
                            RelaxBehaviors.Idle
                            );
        }
        public static (bool result, string msg) ConsiderFleeing(Animal agent, bool skipChance = false)
        {
            // Run immediately if just attacked player or randomly choose run or not
            // For immediate run remember that we need to run away for a long time
            var fleePosition = agent.Position + agent.FacingDir;
            var chanceToFlee = !skipChance && RandomUtil.Chance(ChanceToFleeFromEnemy);

            agent.TryGetMemory(Animal.IsPlayerAttackedMemory, out bool attackedPlayer);
            if (attackedPlayer)
            {
                chanceToFlee = true;
            }
            if (agent.Prey != null)
            {
                if (!chanceToFlee && agent.Prey is Player playerEnemy)
                {
                    // Be aware of a player with fire
                    var selectedItem   = playerEnemy.User.Inventory?.Toolbar?.SelectedItem;
                    var playerWithFire = selectedItem is TorchItem;
                    if (playerWithFire)
                    {
                        chanceToFlee = true;
                    }
                }
                fleePosition = agent.Prey.Position;
            }

            if (!chanceToFlee)
            {
                return(false, "no flee");
            }
            agent.Prey = null;
            if (attackedPlayer)
            {
                agent.FleeFromImmediately(fleePosition);
                agent.SetMemory(Animal.ShouldFleeTillMemory, WorldTime.Seconds + RunTimeAfterAttackingPlayer);
                agent.SetMemory(Animal.IsPlayerAttackedMemory, false);
            }
            else
            {
                agent.FleeFrom(fleePosition);
            }
            return(true, "preparing to flee");
        }
Beispiel #6
0
    public void randomRule()
    {
        GameManagerOne.Instance.activeRule = GameManagerOne.Instance.partFaceList.RandomItem <string>();
        switch (GameManagerOne.Instance.activeRule)
        {
        case "eye":
            GameManagerOne.Instance.activeColor = colorEyeN.RandomItem <string>();
            GameManagerOne.Instance.noColor     = RandomUtil.Chance(0.5f);
            break;

        case "hair":
            GameManagerOne.Instance.activeColor = colorHairN.RandomItem <string>();
            GameManagerOne.Instance.noColor     = RandomUtil.Chance(0.5f);
            break;

        case "skin":
            GameManagerOne.Instance.activeColor = colorSkinN.RandomItem <string>();
            GameManagerOne.Instance.noColor     = RandomUtil.Chance(0.5f);
            break;
        }
        GameManagerOne.Instance.ruleText(GameObject.FindGameObjectWithTag("ruleText").GetComponent <Text>());
    }
Beispiel #7
0
        // temporary solution for hunting without affecting the environment
        // spawn a corpse nearby when a hungry animal becomes visible
        public override void OnBecameVisible(IWorldObserver observer, Animal animal)
        {
            base.OnBecameVisible(observer, animal);

            if (animal.Dead || animal.Hunger < HungerThreshold || !RandomUtil.Chance(ChanceCaughtPreyWhileOffscreen))
            {
                return;
            }

            var preyType = this.GetRegionalPrey(animal);

            if (preyType != null)
            {
                var preySpecies = EcoSim.GetSpecies(preyType.Name) as AnimalSpecies;
                var spawnPos    = (Vector3)animal.Position.WorldPosition3i.SpiralOutXZIter(10).Skip(20)
                                  .Select(x => RouteManager.NearestWalkableY(x, 10)).Where(x => x.IsValid && RouteCacheData.IsFlatGround(x)).FirstOrDefault();
                if (spawnPos != default(Vector3))
                {
                    EcoSim.AnimalSim.SpawnCorpse(preySpecies, spawnPos);
                }
            }
        }
Beispiel #8
0
        public virtual void DoWork(Settlement.Settlement settlement)
        {
            //Can't work
            if (Workplace == null)
            {
                return;
            }

            var discipline = Traits[Trait.Discipline];

            if (discipline == TraitLevel.BelowAverage && RandomUtil.Chance(1, 40) ||
                discipline == TraitLevel.Low && RandomUtil.Chance(1, 20) ||
                discipline == TraitLevel.VeryLow && RandomUtil.Chance(1, 10))
            {
                //skipped work
                settlement.AddMessage(new SettlerSkippedWorkMessage(this));
            }
            else
            {
                Workplace.HostWork(this, settlement);
            }
        }
Beispiel #9
0
    public void randomLevelN()
    {
        bool previousLapsus = GameManagerOne.Instance.lapsus;

        switch (countLevel)
        {
        case 1:
            GameManagerOne.Instance.randomTender = Random.Range(5, 9);
            break;

        case 2:
            GameManagerOne.Instance.randomTender = Random.Range(4, 7);
            break;

        case 3:
            GameManagerOne.Instance.randomTender = Random.Range(3, 5);
            GameManagerOne.Instance.lapsus       = RandomUtil.Chance(0.5f);
            if (!previousLapsus && GameManagerOne.Instance.lapsus)
            {
                AudioManager.Instance.PlaySoundEffect(effectLapsus);
            }
            break;

        default:
            GameManagerOne.Instance.randomTender = Random.Range(2, 4);
            GameManagerOne.Instance.lapsus       = RandomUtil.Chance(0.5f);
            if (!previousLapsus && GameManagerOne.Instance.lapsus)
            {
                AudioManager.Instance.PlaySoundEffect(effectLapsus);
            }
            break;
        }

        if (previousLapsus != GameManagerOne.Instance.lapsus)
        {
            GameManagerOne.Instance.OnLapsusChanged(GameManagerOne.Instance.lapsus);
        }
    }
 static HerdAnimalBrain()
 {
     HerdAnimalTreeRoot =
         BT.Selector(
             LandAnimalBrain.LyingDownTree,
             BT.If(x => x.Alertness > LandAnimalBrain.AlertThreshold && x.Alertness < LandAnimalBrain.FullyAlertThreshold && x.AnimationState != AnimalAnimationState.Flee && x.AnimationState != AnimalAnimationState.AlertIdle && x.OnFlatGround,
                   // play an alert reaction before fleeing and intermittently while alert
                   PlayFixedTimeAnimation(AnimalAnimationState.AlertIdle, LandAnimalBrain.AlertIdleTime)),
             MovementBehaviors.Flee,
             GroupBehaviors.SleepNearLeader,
             new FindAndEatPlantsMemoryBehavior()
     {
         NoNearbyFoodBehavior = LandAnimalBrain.LandAnimalFindFood
     },
             GroupBehaviors.StayNearLeader(20f),
             BT.If(MovementBehaviors.ShouldReturnHome,
                   MovementBehaviors.WanderHome),
             BT.If(x => x.Alertness < Animal.FleeThreshold && RandomUtil.Chance(LandAnimalBrain.ChanceToLieDown) && x.OnFlatGround,
                   PlayAnimation(AnimalAnimationState.LyingDown, LandAnimalBrain.LyingTickDuration)),
             BT.If(x => RandomUtil.Chance(LandAnimalBrain.ChanceToIdle) && x.OnFlatGround,
                   PlayAnimation(AnimalAnimationState.Idle, _ => RandomUtil.Range(LandAnimalBrain.MinIdleTime, LandAnimalBrain.MaxIdleTime))),
             MovementBehaviors.Wander);
 }
        static LandAnimalBrain()
        {
            LyingDownTree =
                BT.If(animal => animal.LyingDown,
                      BT.Selector(
                          BT.If(x => x.AnimationState == AnimalAnimationState.Sleeping && x.Alertness > Animal.WakeUpAlertness,
                                // waking up takes time, start the transition animation then decide what to do next tick
                                PlayFixedTimeAnimation(AnimalAnimationState.LyingDown, x => x.Species.TimeWakeUp)),
                          BT.If(x => x.Alertness > Animal.FleeThreshold,
                                PlayFixedTimeAnimation(AnimalAnimationState.Flee, x => x.Species.TimeLayToStand)),
                          BT.If(x => x.Hunger > HungerThreshold,
                                PlayFixedTimeAnimation(AnimalAnimationState.Idle, x => x.Species.TimeLayToStand)),
                          BT.If(x => x.ShouldSleep,
                                PlayAnimation(AnimalAnimationState.Sleeping, LyingTickDuration)),
                          BT.If(x => RandomUtil.Chance(ChanceToStopLyingDown),
                                PlayAnimation(AnimalAnimationState.Idle, x => x.Species.TimeLayToStand + RandomUtil.Range(MinIdleTime, MaxIdleTime))),
                          PlayAnimation(AnimalAnimationState.LyingDown, _ => RandomUtil.Range(MinLyingIdleTime, MaxLyingIdleTime))));

            LandAnimalTreeRoot =
                BT.Selector(
                    LyingDownTree,
                    BT.If(x => x.Alertness > AlertThreshold && x.Alertness < FullyAlertThreshold && x.AnimationState != AnimalAnimationState.Flee && x.AnimationState != AnimalAnimationState.AlertIdle && x.OnFlatGround,
                          // play an alert reaction before fleeing and intermittently while alert
                          PlayFixedTimeAnimation(AnimalAnimationState.AlertIdle, AlertIdleTime)),
                    MovementBehaviors.Flee,
                    new FindAndEatPlantsMemoryBehavior()
            {
                NoNearbyFoodBehavior = LandAnimalFindFood
            },
                    BT.If(MovementBehaviors.ShouldReturnHome,
                          MovementBehaviors.WanderHome),
                    BT.If(x => x.Alertness < Animal.FleeThreshold && RandomUtil.Chance(ChanceToLieDown) && x.OnFlatGround,
                          PlayAnimation(AnimalAnimationState.LyingDown, LyingTickDuration)),
                    BT.If(x => RandomUtil.Chance(ChanceToIdle) && x.OnFlatGround,
                          PlayAnimation(AnimalAnimationState.Idle, _ => RandomUtil.Range(MinIdleTime, MaxIdleTime))),
                    MovementBehaviors.Wander);
        }
Beispiel #12
0
        public static void GenerateChildTraits(Human child)
        {
            List <Settler> parents = new List <Settler>();

            foreach (var relationship in child.Relationships)
            {
                if (relationship is ParentChildRelationship pcr && pcr.Role(child) == ParentChildRelationship.Child)
                {
                    parents.Add(pcr.Other(child));
                }
            }

            var badRelationshipParents = parents.Where(parent =>
                                                       child.Relationships
                                                       .FirstOrDefault(rel => rel is ParentChildRelationship pcr && pcr.Other(parent) == child)?.Level <=
                                                       RelationshipLevel.Dislike).ToList();

            foreach (var trait in Trait.Traits)
            {
                var parentsTraitsArray = parents.ToArray().Select(parent => parent.Traits[trait].Value).ToArray();

                if (badRelationshipParents.Count > 0 && RandomUtil.Chance(1, 3))
                {
                    var parent = RandomUtil.Get(badRelationshipParents);
                    var level  = parent.Traits[trait];

                    if (level == TraitLevel.Average) //Reaction goes extreme
                    {
                        child.Traits[trait] = RandomUtil.Get(new[]
                                                             { TraitLevel.VeryLow, TraitLevel.Low, TraitLevel.High, TraitLevel.VeryHigh });
                    }
                    else if (level == TraitLevel.AboveAverage) // Reaction goes extreme, more down
                    {
                        child.Traits[trait] = RandomUtil.Get(new[]
                                                             { TraitLevel.VeryLow, TraitLevel.Low, TraitLevel.VeryHigh });
                    }
                    else if (level == TraitLevel.BelowAverage)
                    {
                        child.Traits[trait] = RandomUtil.Get(new[]
                                                             { TraitLevel.VeryLow, TraitLevel.High, TraitLevel.VeryHigh });
                    }
                    else if (level >= TraitLevel.High)
                    {
                        child.Traits[trait] = RandomUtil.Get(new[] { TraitLevel.VeryLow, TraitLevel.Low, TraitLevel.BelowAverage });
                    }
                    else
                    {
                        child.Traits[trait] = RandomUtil.Get(new[] { TraitLevel.AboveAverage, TraitLevel.High, TraitLevel.VeryHigh });
                    }
                }
                else
                {
                    var baseLevel = TraitLevel.Average.Get(MathUtil.RoundTowardsZero(MathUtil.UnroundedAverage(parentsTraitsArray)));

                    if (RandomUtil.CoinFlip()) //Drift
                    {
                        if (baseLevel == TraitLevel.VeryLow || baseLevel <= TraitLevel.High && RandomUtil.CoinFlip())
                        {
                            baseLevel = baseLevel.Get(baseLevel.Value + 1);
                        }
                        else
                        {
                            baseLevel = baseLevel.Get(baseLevel.Value - 1);
                        }
                    }

                    child.Traits[trait] = baseLevel as TraitLevel;
                }
            }

            TraitGenerator.EnsureMajorTrait(child);
        }
Beispiel #13
0
 // Alligators can spawn on land or water
 public override bool IsValidSpawnPathPos(Vector3i pos) => World.World.IsUnderwater(pos) || RandomUtil.Chance(.3f);
Beispiel #14
0
        static Otter()
        {
            const float MinIdleTime            = 3f;
            const float MaxIdleTime            = 10f;
            const float MinFloatIdleTime       = 10f;
            const float MaxFloatIdleTime       = 20f;
            const float ChanceToIdle           = 0.3f;
            const float ChanceToSurface        = 0.3f;
            const float ChanceToDive           = 0.1f;
            const float TimeToStopFloating     = 2f;
            const float DiveAlertness          = 200;
            const float MaxHeightAboveSeaLevel = 5;

            OtterLandTree =
                BT.If(x => !World.World.IsUnderwater(x.Position.WorldPosition3i),
                      BT.Selector(
                          MovementBehaviors.AmphibiousFlee,
                          BT.If(x => RandomUtil.Chance(ChanceToIdle),
                                Brain.PlayAnimation(AnimalAnimationState.Idle, _ => RandomUtil.Range(MinIdleTime, MaxIdleTime))),
                          BT.If(x => x.Position.y > WorldLayerManager.ClimateSim.State.SeaLevel + MaxHeightAboveSeaLevel,
                                x => MovementBehaviors.RouteToWater(x, x.Species.WanderingSpeed, AnimalAnimationState.Wander)),
                          BT.If(MovementBehaviors.ShouldReturnHome,
                                MovementBehaviors.AmphibiousWanderHome),
                          MovementBehaviors.AmphibiousWander));

            OtterFloatingTree =
                BT.If(x => x.floating,
                      BT.Selector(
                          BT.If(x => x.AnimationState == AnimalAnimationState.FloatingIdle,
                                // floating otters need time to flip back over before doing other things
                                Brain.PlayFixedTimeAnimation(AnimalAnimationState.SurfaceSwimming, TimeToStopFloating)),
                          BT.If(x => x.Alertness > DiveAlertness,
                                // dive when scared
                                BT.Success(x => x.floating = false),
                                BT.Selector(MovementBehaviors.SwimFlee, MovementBehaviors.SwimWander)),
                          MovementBehaviors.AmphibiousFlee,
                          BT.If(x => RandomUtil.Chance(ChanceToDive),
                                BT.Success(x => x.floating = false),
                                MovementBehaviors.SwimWander),
                          BT.If(MovementBehaviors.ShouldReturnHome,
                                MovementBehaviors.AmphibiousWanderHome),
                          BT.If(x => RandomUtil.Chance(ChanceToIdle),
                                Brain.PlayAnimation(AnimalAnimationState.FloatingIdle, _ => RandomUtil.Range(MinFloatIdleTime, MaxFloatIdleTime))),
                          MovementBehaviors.AmphibiousWander));

            OtterDivingTree =
                BT.Selector(
                    MovementBehaviors.SwimFlee,
                    BT.If(MovementBehaviors.ShouldReturnHome,
                          BT.Success(x => x.floating = true),
                          MovementBehaviors.SwimWanderHomeSurface),
                    BT.If(x => x.Alertness < DiveAlertness && RandomUtil.Chance(ChanceToSurface),
                          BT.Success(x => x.floating = true),
                          MovementBehaviors.SwimWanderSurface),
                    BT.If(x => RandomUtil.Chance(1 - ChanceToIdle),
                          MovementBehaviors.SwimWander),
                    Brain.PlayAnimation(AnimalAnimationState.SwimmingIdle, _ => RandomUtil.Range(MinIdleTime, MaxIdleTime)));

            OtterTreeRoot =
                BT.Selector(
                    OtterLandTree,
                    // TODO: dive for food & eat on surface (need tummy eating animation)
                    OtterFloatingTree,
                    OtterDivingTree
                    );

            Brain <Otter> .SharedBehavior = OtterTreeRoot;
        }
Beispiel #15
0
        static AmphibiousBrain()
        {
            LandTree = BT.If("Land Tree", x => (!World.World.IsUnderwater(x.Position.WorldPosition3i), "on land"),
                             BT.Selector("Amphibious On Land",
                                         MovementBehaviors.AmphibiousFlee,
                                         BT.If("Return Home", MovementBehaviors.ShouldReturnHome, MovementBehaviors.AmphibiousWanderHome),
                                         BT.If("Return to Water", x => (x.Position.y > WorldLayerManager.Obj.ClimateSim.State.SeaLevel + MaxHeightAboveSeaLevel, $"above sea-level {(x.Position.Y + WorldLayerManager.Obj.ClimateSim.State.SeaLevel).ToString("0.#")} not more than {MaxHeightAboveSeaLevel}"),
                                               MovementBehaviors.MoveToWater),
                                         BT.Random("Relax",
                                                   RelaxBehaviors.TryIdle,
                                                   MovementBehaviors.AmphibiousWander)));

            FloatingTree = BT.If("Floating", x => (x.Floating, "floating"),
                                 BT.Selector("Floating",
                                             BT.If("Surface swim", x => (x.State == AnimalState.FloatingIdle && !x.Species.IsPredator, "is idling and not predator"),
                                                   // floating amphibious need time to flip back over before doing other things
                                                   Anim(AnimalState.SurfaceSwimming, true, TimeToStopFloating)),
                                             BT.If("Flee Dive", x => (x.Alertness > DiveAlertness, $"alert {x.Alertness.ToString("0.#")} > {DiveAlertness.ToString("0.#")}"),
                                                   stopFloating,
                                                   BT.Selector("Flee or Wander",
                                                               MovementBehaviors.SwimFlee,
                                                               MovementBehaviors.SwimWander)),
                                             MovementBehaviors.AmphibiousFlee,
                                             BT.If("Random Dive", x => AIUtil.Chance(ChanceToDive),
                                                   stopFloating,
                                                   MovementBehaviors.SwimWander),
                                             BT.If("Return Home", MovementBehaviors.ShouldReturnHome,
                                                   MovementBehaviors.AmphibiousWanderHome),
                                             BT.If("Idle", x => AIUtil.Chance(ChanceToIdle),
                                                   Anim(AnimalState.FloatingIdle, true, _ => RandomUtil.Range(MinFloatIdleTime, MaxFloatIdleTime))),
                                             MovementBehaviors.AmphibiousWander));

            DivingTree = BT.Selector("Diving",
                                     MovementBehaviors.SwimFlee,
                                     BT.If("Return Home", MovementBehaviors.ShouldReturnHome,
                                           startFloating,
                                           MovementBehaviors.SwimWanderHomeSurface),
                                     BT.If("Surface", x => (x.Alertness < DiveAlertness && RandomUtil.Chance(ChanceToSurface), $"alert {x.Alertness.ToString("0.#")} < {DiveAlertness.ToString("0.#")} and {ChanceToSurface.ToString("P0")} chance"),
                                           startFloating,
                                           MovementBehaviors.SwimWanderSurface),
                                     BT.If("Wander", x => AIUtil.Chance(1 - ChanceToIdle),
                                           MovementBehaviors.SwimWander),
                                     Anim(AnimalState.SwimmingIdle, true, _ => RandomUtil.Range(MinIdleTime, MaxIdleTime)));

            // TODO: dive for food & eat on surface (need tummy eating animation)
            AmphibiousTreeRoot = BT.Selector("Amphibious",
                                             BT.If("Animal On Land", x => (!World.World.IsUnderwater(x.Position.WorldPosition3i), "on land"),
                                                   BT.Selector("Landing",
                                                               MovementBehaviors.Flee,
                                                               FindAndEatPlants,
                                                               LandTree)),
                                             BT.If("Animal In Water", x => (World.World.IsUnderwater(x.Position.WorldPosition3i), "in water"),
                                                   BT.Selector("Swimming",
                                                               MovementBehaviors.SwimFlee,
                                                               FloatingTree,
                                                               DivingTree)),
                                             RelaxBehaviors.Idle);

            PredatorAmphibiousTreeRoot = BT.Selector("Amphibious Predator",
                                                     BT.If("Predator On Land", x => (!World.World.IsUnderwater(x.Position.WorldPosition3i), "on land"),
                                                           BT.Selector("Landing",
                                                                       MovementBehaviors.Flee,
                                                                       LandPredatorBrain.FindAndAttackEnemyTree,
                                                                       LandPredatorBrain.FindAndEatCorpse,
                                                                       LandTree)
                                                           ),
                                                     BT.If("Predator In Water", x => (World.World.IsUnderwater(x.Position.WorldPosition3i), "in water"),
                                                           BT.Selector("Swimming",
                                                                       MovementBehaviors.SwimFlee,
                                                                       FloatingTree,
                                                                       DivingTree)
                                                           ),
                                                     RelaxBehaviors.Idle);
        }