示例#1
0
    //Check the creature's stats + priorities to see if they need to change
    private void CheckBehaviourState()
    {
        //Check stats + priorities
        //If priorities/Stats change, change FSM
        //Dont forget to change "currentState" either!
        //Priotity Order:
        //      1. SAFETY           2. WATER            3. FOOD             4. SPACE

        //First check if traits are ok

        BEHAVIOUR_STATE targetState = currentState;

        //If current "Engaged" (Actively reproducing etc) do not change state
        if (currentState == BEHAVIOUR_STATE.ENGAGED)
        {
            return;
        }

        if (GetComponent <Stats>().canMate&& InTheMood())        //3 core stats below are at 75% or higher AND is of age
        {
            targetState = BEHAVIOUR_STATE.REPRODUCE;
        }
        else
        {
            float currentVal = traits["Energy Level"];
            if (currentVal <= capacityTraits["Energy Level"] * 0.15)
            {
                targetState = BEHAVIOUR_STATE.SLEEP;
            }

            currentVal = traits["Food Level"];
            if (currentVal <= capacityTraits["Food Level"] * 0.15)
            {
                targetState = BEHAVIOUR_STATE.EAT;
            }

            currentVal = traits["Water Level"];
            if (currentVal <= capacityTraits["Water Level"] * 0.25)
            {
                targetState = BEHAVIOUR_STATE.DRINK;
                //Only override IF is less than Water val and in immindent danger - prevent lfip flopping
                if (traits["Food Level"] < currentVal)
                {
                    if (traits["Food Level"] <= capacityTraits["Food Level"] * 0.15f)
                    {
                        targetState = BEHAVIOUR_STATE.EAT;
                    }
                }
            }
        }

        float energyVal = traits["Energy Level"];

        if (energyVal <= 0)
        {
            traits["Energy Level"] = 0.0f;
            targetState            = BEHAVIOUR_STATE.SLEEP;
        }

        //Check make sure the water + food levels aren't at dangerous levels
        if (GetComponent <CreatureManager>().population.averageIntellect >= GlobalGEPSettings.MIN_WATER_STORE_INTELLECT &&
            GetComponent <CreatureManager>().population.popWaterStores.currentAmount <= 0.20f)
        {
            currentPriority = PRIORITY.WATER;
        }
        else if (GetComponent <CreatureManager>().population.popFoodStores.currentAmount <= 0.20f)
        {
            currentPriority = PRIORITY.FOOD;
        }

        //Then check the Priorities. Do space first...check POPULATION class for space avialability (Could ignore this for first prototype)

        //Do Food Storage, Water Storage and Space availability Checks here
        //PRIORITY tempPriority = CheckPriority();

        //For Fitness evaluation, keep the fitness in that state for 1 period (otherwise it wll be constantly changing)
        //      Possibly a setting for "sensitivity"?


        //This focuses on CONSTITUTION ATTRIBUTE for reproduction/Fitness/Attractiveness etc
        //This focus will be linked directly with the Population class that has a Population_Status variable, tracking whether the pop is colonizing
        //      or not. If colonizing then the population may only be in "SPACE" Priority
        //Extremely Vain creatures will still take Charisma into account (IE if Vanity >= averageVanity + 25-50%, add Charisma to the fitness calculations)
        if (GetComponent <CreatureManager>().population.popState == POPULATION_STATE.MIGRATE)
        {
            //Explore for a new population location
            //      A random number of creatures from the population (between 25-50%) will split off and create a new population centre
            //      They will then choose a random location a minimum distance away from the original location (AILERP)
            //      They will not Hunt, or gather until a new location is found
            //          If not enough space will never find a new location and will eventually starve
            //          Alternatively, any other population becomes an enemy so may attack
            //              If this is the case, will need to make sure they don't attack original population (and vice versa)
            //                  Possibly add a check of "immunity" for 1 period, or until far enough away
            //                      During immunity, either ALL species are non-threat (including food so will not hunt them)
            //                      OR can set it so only their own species is a non-threat (will have to program additional check if they can hunt yet etc)
            //                      But can be attacked and killed whilst searching elsewhere if this is the case.
            //                      This priority will be active and be linked with the population until the pop has settled.
            //
            //When inthis state, a creature is part of a "New Population" (colony) and is preparing to move out
            //Each pop will set their energy, food and water levels to max, and then head out.
            //Whilst in this state, they are moving, and if one stops to sleep, all stop to sleep. Same with eat + drink until food runs out.
            //Can still mate en-route to new location, and will look at the constitution attribute
            //Check if there is sufficient time to live (IE minimum of 1.5-2 periods)

            //If is in Space mode/Migrating, then make population.population[0] act as the leader/alpha, and have every other population follow them
            //      Swarm behaviour? (0<-1-<-2<-3<-4....) if x distance from 0, start a new column?
            //                      OR move randomly, but when gets certain distance from Alpha, make goal to move to their last position (AILERP)
            //                              then continue random movement etc


            //Still need to check hunger etc - but apply Swarm AI behaviours
            energyVal = traits["Energy Level"];
            if (energyVal <= 0)
            {
                traits["Energy Level"] = 0.0f;
                targetState            = BEHAVIOUR_STATE.SLEEP;
            }
        }
        else
        {
            //This focuses on STRENGTH/CONSTITUTION ATTRIBUTES for reproduction/Fitness/Attractiveness etc
            //Extremely Vain creatures will still take Charisma into account (IE if Vanity >= averageVanity + 25-50%, add Charisma to the fitness calculations)
            if (currentPriority == PRIORITY.SAFETY)
            {
                //Determine Fight vs Flight
                //      Use Wisdom + intellect to compare their strength with the average strenght of population
                //          If one of the strongest members in the population, more likely to fight
                //          If one ofthe weaker members, more likely to flee
                //          If has low wisdom or intellect, AND one of weaker members, increased chance they will fight (despite risk of losing)
                //                  If wins...increase their Charisma???
                //          If has low wisdom/intellect, And one of stronger members, possibly increased chance will flee? (Wisdom/Intellect acting as 'courage' etc)

                //Could combine ATTACK/FLEE states into one substate ("COMBAT") which then divides into ATTACK/FLEE?
                //      Potentially more optimized
                //      Could perform these fight vs flight checks in there rather than in AI behaviour

                //Check if there is a threat near by (IE another pop within a certain distance AND is Omnivore/Carnivore)
                if (threatNearby)
                {
                    float wisdom    = GetComponent <Stats>().attributes["wisdom"];
                    float intellect = GetComponent <Stats>().attributes["intellect"];
                    float strength  = GetComponent <Stats>().attributes["strength"];
                    //If one of the strongest in the population then fight
                    //Otherwise, if Wisdom * Intellect (/10) added to strength is STILL less than average strength, Fight
                    //Otherwise flee
                    //          IE W=30, I=25, S=8. Avg = 15.
                    //          (3 * 2.5) + 8 = 15.5
                    //                  Results in Fleeing (smart enough to know not strong enough)
                    //
                    //          IE W=10, I=25, S=8. Avg = 15
                    //          (1 * 2.5) + 8 = 10.5
                    //                  Results in fighting (Too irrational/not smart enough to realize weaker and less chance of winning etc)
                    bool fightFlight = strength >= GetComponent <CreatureManager>().population.averageStrength ? true :
                                       ((wisdom / 10) * (intellect / 10) + strength) <= GetComponent <CreatureManager>().population.averageStrength ? true : false;

                    if (fightFlight)
                    {
                        targetState = BEHAVIOUR_STATE.ATTACK;
                    }
                    else
                    {
                        //Temporarily set to Attack. Eventually will be Flee
                        //  This will need to have it so other pop members come to help if in range (which requires 'Update Priorities' for Safety to work
                        //      Regarding checking nearby threats (Detection radius)
                        //  During fleeing, use 2x energy
                        targetState = BEHAVIOUR_STATE.ATTACK;
                    }
                }
                //Cause creature to pass out from exhaustion, regardless of the other stats
                //Difference between this and the first is the first instance of energy level is by the creature's choice
                //This will be forced on the entity regardless and cannot be overridden (aside from imminent danger - ADRENALINE!)
                //  Will only "pass out" if energy is at negative capacity (absolutely no energy that even adrenaline does nothing)
                //      Can result in being killed if still being pursued
                energyVal = traits["Energy Level"];
                if (energyVal <= 0 && energyVal >= -capacityTraits["Energy Level"])
                {
                    traits["Energy Level"] = 0.0f;
                    targetState            = BEHAVIOUR_STATE.FLEE;
                }
                else if (energyVal < -capacityTraits["Energy Level"])
                {
                    traits["Energy Level"] = capacityTraits["Energy Level"];
                    targetState            = BEHAVIOUR_STATE.SLEEP;
                }
            }
            //This focuses on INTELLECT ATTRIBUTE for reproduction/Fitness/Attractiveness etc
            //Extremely Vain creatures will still take Charisma into account (IE if Vanity >= averageVanity + 25-50%, add Charisma to the fitness calculations)
            else if (currentPriority == PRIORITY.WATER)
            {
                //Find fresh water and/or refille supplies
                //Drink FSM will use water sources but find it's own if null
                //This priority will update list of water sources before assigning this individual to gather water

                //Only assign a hunter if current water level is lower than 80%
                //  AND if there are less than 5 gatherers
                //  Otherwise allow them to do whatever they were doing before
                if (GetComponent <CreatureManager>().population.popWaterStores.currentAmount < 0.80f && GetComponent <CreatureManager>().population.gatherers < 2)
                {
                    if (targetState != BEHAVIOUR_STATE.EAT && targetState != BEHAVIOUR_STATE.DRINK)
                    {
                        //Change to GATHER - Gather = Gather up water
                        FindWaterSources();
                        //targetState = BEHAVIOUR_STATE.HUNT;
                    }
                }

                energyVal = traits["Energy Level"];
                if (energyVal <= 0)
                {
                    traits["Energy Level"] = 0.0f;
                    targetState            = BEHAVIOUR_STATE.SLEEP;
                }
            }

            //This focuses on INTELLECT/STRENGTH ATTRIBUTES for reproduction/Fitness/Attractiveness etc
            //Extremely Vain creatures will still take Charisma into account (IE if Vanity >= averageVanity + 25-50%, add Charisma to the fitness calculations)
            else if (currentPriority == PRIORITY.FOOD)
            {
                //Find Food sources/Hunt and/or gather more food
                //  If this creature is not already eating, and not too many hunters, assign this pop to a hunter
                //HERBIVORES DO NOT HUNT - no need to store food because can just eat from the ground
                //          Later on could add in Trees/fruits etc that they can gather

                //Hunting:
                //          1. Find nearest population (ideally threatening/enemy)
                //          2. Find nearest creature from that population
                //          3. Move to that creature
                //          4. Start attacking creature
                //          5. If victorious return to pop centre with food

                //Only assign a hunter if current food level is lower than 80%
                //  AND if there are less than 5 hunters
                //  Otherwise allow them to do whatever they were doing before
                float val = GetComponent <CreatureManager>().population.hunters;
                float amt = GetComponent <CreatureManager>().population.popFoodStores.currentAmount;
                if (GetComponent <CreatureManager>().population.popFoodStores.currentAmount < 0.60f && GetComponent <CreatureManager>().population.hunters < 2)
                {
                    //Has minimum HP to right AND not pregnant
                    if (GetComponent <Stats>().currHP >= GetComponent <Stats>().maxHP * 0.25f && !GetComponent <Stats>().pregnant)
                    {
                        //Is at least of average strength
                        if (attributes["strength"] >= (GetComponent <CreatureManager>().population.averageStrength - (GetComponent <CreatureManager>().population.averageStrength * 0.25f)))
                        {
                            isHunter = true;
                            GetComponent <CreatureManager>().population.hunters++;
                        }
                    }
                }
                else if (GetComponent <CreatureManager>().population.popFoodStores.currentAmount >= 0.65f && isHunter)
                {
                    isHunter = false;
                    GetComponent <CreatureManager>().population.hunters--;
                }

                if (isHunter)
                {
                    if (targetState != BEHAVIOUR_STATE.EAT && targetState != BEHAVIOUR_STATE.DRINK)
                    {
                        targetState = BEHAVIOUR_STATE.HUNT;
                    }
                }

                energyVal = traits["Energy Level"];
                if (energyVal <= 0)
                {
                    traits["Energy Level"] = 0.0f;
                    targetState            = BEHAVIOUR_STATE.SLEEP;
                }
            }

            //This focuses on Vanity attribute, ignoring all Survival attributes (even if REALLY good). The population is complacent and cares about
            //      physical attractiveness of mates rather than practical/survival attractiveness of mates
            else if (currentPriority == PRIORITY.QUALITY)
            {
                //Do whatever - Don't change the FSM/Activity, just change the Fitness evaluation
                //Check that all needs are met (as with all other priorities where relevant)
            }
        }
        //Change the current state
        //Defaults to Idle

        if (currentState != targetState)
        {
            //Force an update to the creature window if its open
            updateStats = true;
            switch (targetState)
            {
            case BEHAVIOUR_STATE.SLEEP:
                ChangeState(new Sleep(), BEHAVIOUR_STATE.SLEEP);
                break;

            case BEHAVIOUR_STATE.EAT:
                ChangeState(new Eat(), BEHAVIOUR_STATE.EAT);
                break;

            case BEHAVIOUR_STATE.DRINK:
                ChangeState(new Drink(), BEHAVIOUR_STATE.DRINK);
                break;

            case BEHAVIOUR_STATE.REPRODUCE:
                ChangeState(new Reproduce(), BEHAVIOUR_STATE.REPRODUCE);
                break;

            case BEHAVIOUR_STATE.HUNT:
                ChangeState(new Hunt(), BEHAVIOUR_STATE.HUNT);
                break;

            case BEHAVIOUR_STATE.EXPLORE:
                ChangeState(new Sleep(), BEHAVIOUR_STATE.EXPLORE);
                break;

            case BEHAVIOUR_STATE.ATTACK:
                ChangeState(new Attack(), BEHAVIOUR_STATE.ATTACK);
                break;

            case BEHAVIOUR_STATE.FLEE:
                ChangeState(new Sleep(), BEHAVIOUR_STATE.FLEE);
                break;

            default:
                ChangeState(new Idle(), BEHAVIOUR_STATE.IDLE);
                break;
            }
        }
    }
示例#2
0
 //Change FSM state (Behaviours)
 public void ChangeState(FSMState <AIBehaviour> state, BEHAVIOUR_STATE newState)
 {
     previousState = currentState;
     currentState  = newState;
     fsm.ChangeState(state);
 }