Пример #1
0
        /// <summary>
        /// Move any memory or collections of memories that have an influence over the long term memory threshold
        /// from short to long term memory. For a collection to be moved the `about` Game Object must be identical
        /// and the total influence must be over the threshold level.
        /// </summary>
        internal void MoveFromShortToLongTermMemory()
        {
            var grouped = from memory in m_ShortTermMemories
                          group memory by new
            {
                memory.about,
                memory.stat,
                memory
            } into grp
                select new
            {
                about          = grp.Key.about,
                traitName      = grp.Key.stat,
                totalInfluence = grp.Sum(i => i.influence)
            };

            foreach (var item in grouped)
            {
                if (item.totalInfluence >= m_LongTermMemoryThreshold)
                {
                    MemorySO memory = ScriptableObject.CreateInstance <MemorySO>();
                    memory.about     = item.about;
                    memory.stat      = item.traitName;
                    memory.influence = item.totalInfluence;
                    AddToLongTermMemory(memory);

                    ForgetShortTermMemories(item.about);
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Add a memory to the short term memory.
        /// If there is an existing short term memory that is similar to the new one then do not duplicate;
        /// instead strengthen the existing memory.
        /// If there is space left in the memory then is simply inserted.
        /// If there is no space left then discard the weakest memory.
        /// </summary>
        /// <param name="memory">The memory to add</param>

        public void AddMemory(MemorySO memory)
        {
            MemorySO existingMemory = GetSimilarShortTermMemory(memory);

            if (existingMemory != null)
            {
                if (existingMemory.isGood != memory.isGood)
                {
                    if (Math.Abs(existingMemory.influence) < Math.Abs(memory.influence))
                    {
                        existingMemory.isGood = memory.isGood;
                    }
                }
                existingMemory.influence += memory.influence;
                existingMemory.time       = memory.time;
                return;
            }

            MoveFromShortToLongTermMemory();

            if (m_ShortTermMemories.Count == m_ShortTermMemorySize)
            {
                DiscardShortTermMemory();
            }

            m_ShortTermMemories.Add(memory);
        }
Пример #3
0
        /// <summary>
        /// Checks to see if any stats are not in their desired states. If any are not then
        /// look in memories to see if the character knows of a place to address that. If
        /// a place is recalled and they are ready to return then they move towards it.
        /// Otherwise wander.
        /// </summary>
        protected override void UpdateMove()
        {
            StatSO[] stats = statsController.GetStatsNotInDesiredState();

            nearestMemoryOfInterest = null;
            focusedStat             = null;
            float sqrMagnitude = float.PositiveInfinity;

            for (int i = 0; i < stats.Length; i++)
            {
                //Debug.Log(gameObject.name + " desires to " + stats[i].goal + " " + stats[i].name + " to " + stats[i].desiredState.targetValue);
                //Debug.Log(stats[i].name + " is currently " + stats[i].value);

                // Find the nearest place that is in current memory that helps achieve one of the characters goals
                MemorySO[] memories = memory.GetMemoriesInfluencingStat(stats[i].name);
                for (int y = 0; y < memories.Length; y++)
                {
                    if (memories[y].readyToReturn)
                    {
                        if (stats[i].goal == DesiredState.Goal.Increase && memories[y].influence < 0)
                        {
                            continue;
                        }
                        else if (stats[i].goal == DesiredState.Goal.Decrease && memories[y].influence > 0)
                        {
                            continue;
                        }

                        Collider col = memories[y].about.GetComponent <Collider>();
                        if (!col.bounds.Contains(transform.position))
                        {
                            float distance = Vector3.SqrMagnitude(memories[y].about.transform.position - gameObject.transform.position);
                            if (distance < sqrMagnitude)
                            {
                                focusedStat             = stats[i];
                                nearestMemoryOfInterest = memories[y];
                                sqrMagnitude            = distance;
                            }
                        }
                    }
                }

                // Head to the remembered place
                if (nearestMemoryOfInterest != null)
                {
                    //Debug.Log("It looks like " + nearestMemoryOfInterest.about + " is the best place to achieve that goal");

                    GameObject target = nearestMemoryOfInterest.about;
                    Collider   col    = target.GetComponent <Collider>();
                    SetCurrentTargetWithinTriggerOf(col);
                    return;
                }
            }

            // if no place in memory wander randomly
            base.UpdateMove();
        }
Пример #4
0
        /// <summary>
        /// Retrive all memories (long and short term) about influencers of a stat.
        /// </summary>
        /// <param name="statTemplate">Template of the stat we are interested in.</param>
        /// <returns>A set of influencers known to affect the desired stat.</returns>
        public MemorySO[] GetMemoriesInfluencingStat(StatSO statTemplate)
        {
            MemorySO[] shortTermMemories = m_ShortTermMemories.Where(m => m.stat.name == statTemplate.name).ToArray <MemorySO>();
            MemorySO[] longTermMemories  = m_LongTermMemories.Where(m => m.stat.name == statTemplate.name).ToArray <MemorySO>();

            MemorySO[] all = new MemorySO[shortTermMemories.Length + longTermMemories.Length];
            shortTermMemories.CopyTo(all, 0);
            longTermMemories.CopyTo(all, shortTermMemories.Length);

            return(all);
        }
Пример #5
0
        /// <summary>
        /// Create a memory about an influencer object. See `AddMemory(MemorySO memory)`.
        /// </summary>
        /// <param name="influencer">The influencer that this memory should record.</param>
        /// <param name="isGood">Is this a good memory that represents an experience to be repeated?</param>
        internal void AddMemory(StatInfluencerSO influencer, bool isGood)
        {
            MemorySO memory = ScriptableObject.CreateInstance <MemorySO>();

            memory.about     = influencer.generator;
            memory.stat      = influencer.stat;
            memory.influence = influencer.maxChange;
            memory.cooldown  = influencer.cooldown;
            memory.isGood    = isGood;
            AddMemory(memory);
        }
Пример #6
0
 /// <summary>
 /// Add a memory to the long term memory if there is space. If there is not space then remove the
 /// weakest memory that is weaker than the memory being added, or discard the added memory.
 /// </summary>
 /// <param name="memory">The memory to try to add</param>
 /// <returns>True if the memory was committed to long term memory.</returns>
 private bool AddToLongTermMemory(MemorySO memory)
 {
     if (m_LongTermMemories.Count <= m_LongTermMemorySize)
     {
         m_LongTermMemories.Add(memory);
         return(true);
     }
     else
     {
         throw new NotImplementedException("Make space in long term memory");
     }
 }
Пример #7
0
        internal override void FinishBehaviour()
        {
            base.FinishBehaviour();

            m_BuiltPrefab.InstantiatePrefabs(transform.position, "built by " + Brain.Actor.name);
            MemorySO memory = ScriptableObject.CreateInstance <MemorySO>();

            memory.about           = this.gameObject;
            memory.interactionName = DisplayName;
            memory.isGood          = true;

            Brain.Memory.AddMemory(memory);
        }
Пример #8
0
        /// <summary>
        /// Get all memories (long and short term), about a Game Object.
        /// </summary>
        /// <param name="go">The Game Object to retrieve memories about.</param>
        /// <returns></returns>
        public MemorySO[] GetAllMemoriesAbout(GameObject go)
        {
            MemorySO[] shortTerm = m_ShortTermMemories.Where(m => ReferenceEquals(go, m.about))
                                   .ToArray();
            MemorySO[] longTerm = m_LongTermMemories.Where(m => ReferenceEquals(go, m.about))
                                  .ToArray();

            MemorySO[] memories = new MemorySO[longTerm.Length + shortTerm.Length];
            longTerm.CopyTo(memories, 0);
            shortTerm.CopyTo(memories, longTerm.Length);

            return(memories);
        }
Пример #9
0
 /// <summary>
 /// Scan short term memory to see if there is an existing memory similar to this one.
 /// </summary>
 /// <param name="memory">The memory we are looking for similarities to</param>
 /// <returns>Return an existing short term memory that is similar, if one exists, or null.</returns>
 public MemorySO GetSimilarShortTermMemory(MemorySO memory)
 {
     MemorySO[] memories = GetShortTermMemoriesAbout(memory.about);
     if (memories.Length > 0)
     {
         for (int i = 0; i < memories.Length; i++)
         {
             if (memories[i].stat == memory.stat)
             {
                 return(memories[i]);
             }
         }
     }
     return(null);
 }
Пример #10
0
        /// <summary>
        /// Create a memory about an influencer object. See `AddMemory(MemorySO memory)`.
        /// </summary>
        /// <param name="influencer">The influencer that this memory should record.</param>
        /// <param name="isGood">Is this a good memory that represents an experience to be repeated?</param>
        internal void AddMemory(StatInfluencerSO influencer, bool isGood)
        {
            if (influencer.Generator == null)
            {
                return;                               // don't hold memories about behaviours only influencers
            }
            MemorySO memory = ScriptableObject.CreateInstance <MemorySO>();

            memory.about           = influencer.Generator;
            memory.interactionName = influencer.InteractionName;
            memory.stat            = influencer.stat;
            memory.influence       = influencer.maxChange;
            memory.cooldown        = influencer.CooldownDuration;
            memory.isGood          = isGood;
            AddMemory(memory);
        }