/// <summary> /// Determine which action towards a target from a provided list of actions has the highest utility and perform it. /// </summary> /// <param name="target">The avatar that caused an event</param> /// <param name="possibleActions">The list of possible actions to choose from</param> private PersonalAction React(IEnumerable <PersonalAction> possibleActions, PriorityPlanningAgent target = null) { if (possibleActions == null) { //Log.Warn ("There are no actions!"); return(null); } PersonalAction highestUtilityAction = null; double highestUtility = Double.MinValue; foreach (PersonalAction action in possibleActions) { double testUtility = action.Utility(this); //save as its quite costly to calculate //Log.Info ("Performing: " + action.ToString () + ": " + testUtility.ToString ()); //line for debugging if (testUtility > highestUtility) { highestUtility = testUtility; highestUtilityAction = action; } } if (highestUtilityAction != null) { throw new NotImplementedException("MAKE THIS WORK!"); //highestUtilityAction.Perform (Agent, target); } return(highestUtilityAction); }
void Start() { // copy all actions into array var allActions = new List <ActionBt>(); if (actions == null) { Debug.LogError(gameObject.name + " has no actions assigned in his action set"); return; } actions.ForEach((a) => { if (a == null) { Debug.LogError("No actions assigned to: " + gameObject.name); return; } allActions.AddRange(a.actions); }); // initialise agent agent = new PriorityPlanningAgent(this.gameObject.name, allActions.ToArray(), () => timeControl.SunTime); agent.logger = this.UnityLog; // we need to keep time in order to filter actions by expiration if (timeControl == null) { timeControl = GameObject.FindObjectOfType <DayNightCycle>(); } }
/// <summary> /// Based on an eventMessage string, determines and applies the net emotional effect of an event to the agent /// and the reaction. For the expression of emotion, the bot will choose the dominant emotion it currently feels. /// We consider that this dominant emotion supresses other emotions the bot feels (though we still consider all /// feelings in the determination of a reaction to a bot's actions). /// This method takes into considering the individual personality attributes of an agent when determining the /// true net emotional effect of an event. /// </summary> /// <param name="eventMessage"></param> public void EvaluateEvent(string eventMessage, PriorityPlanningAgent target) { // parse input text and generate series of emotional actions and consequences List <Reaction> events = _emotionProcessor.ProcessText(eventMessage); // clasify generated actions and generate general emotions Dictionary <EmotionType, double> resultingEmotions = ClassifyEvent(events); // calculate real emotions based on personality Dictionary <EmotionType, double> resultingPersonalityAffectedEmotions = CalculateNetEmotions(resultingEmotions); // modify emotions in the emotion tree ModifyEmotions(resultingPersonalityAffectedEmotions); // evaluate which emotion is the strongest EmotionType dominantEmotion = Emotions.findDominantEmotion(resultingPersonalityAffectedEmotions); // notify which emotion is the strongest OnEmotionRaised(dominantEmotion); // perform action with the highest relevance to current emotional status and a goal DetermineReactionBasedOnPersonality(DominantEmotionalEffect(resultingPersonalityAffectedEmotions), target); }
public PhysiologyModel(float dayInSeconds, PriorityPlanningAgent agent) { // initialise multithreader // var mt = Loom.Current; this.hunger = 0; this.thirst = 0; this.energy = 100; this.agent = agent; // find the time control component // decay is calculated so that in some time interval in part of the day // 50 is the treshold value // increment = (50 / timeToFillInSeconds) * updateRateInSeconds; // agents get hungry two times hungerDecay = (50 / (dayInSeconds / 2)) * updateRateInSeconds; // agents get thirsty four times thirstDecay = (50 / (dayInSeconds / 4)) * updateRateInSeconds; // agents get tired three times energyDecay = (50 / (dayInSeconds / 3)) * updateRateInSeconds; }
/// <summary> /// Determine the reaction to an event based on the supplied emotional effect. /// </summary> /// <param name="dominantEmotionalEffect">The dominant emotional effect from an evaluated event</param> /// <param name="target">The agent from which an event was caused</param> private void DetermineReactionBasedOnPersonality(KeyValuePair <EmotionType, double> dominantEmotionalEffect, PriorityPlanningAgent target) { if (IsNegativeEmotion(dominantEmotionalEffect.Key)) { if (IsTargetBasedEmotion(dominantEmotionalEffect.Key)) { React(NegativeActionsTowardsTarget, target); } else { //normally, at this point we would work out an action for the bot for an emotion //based on reacting to the bot itself. (ie. how it may react to its dominant emotion) //We could then transfer control back to a reaction to the target (if applicable). //For the demonstrator, since we know all testing actions are the result of another bot //and would thus justify a response to that bot, we will simply the code and just //react to that bot. We have also done this because we have yet to work out //how different personalities would express different intensities of emotion...for now, //in a higher level of the code, the bot just performs an animation dependent upon its //dominant emotion...then control will fall to here. React(NegativeActions); } } else { if (IsTargetBasedEmotion(dominantEmotionalEffect.Key)) { React(PositiveActionsTowardsTarget, target); } else { //Refer to the comment in the above section... React(PositiveActions); } } }
public ScheduleManager(PriorityPlanningAgent agent, Schedule schedule) { this.agent = agent; this.schedule = schedule; }