예제 #1
0
        /// <remarks>
        /// Iterating would scale better if filter names were:
        ///     (A) a bitfield instead of a hash set.  Or,
        ///     (B) an array instead of a hash set.
        /// </remarks>
        /// <returns>
        /// If receiver is empty and candidate has any of the receiver's filter components.
        /// </returns>
        public static bool Filter(ReceiverComponent receiver, GameEntity candidate)
        {
            if (IsFull(receiver))
            {
                return(false);
            }

            HashSet <int> filterIndexes = receiver.filterComponentIndexes;

            if (filterIndexes == null)
            {
                DebugUtil.Assert(filterIndexes != null,
                                 "ReceiverUtils.Filter: Expects filter component indexes are defined on " + receiver);
                return(false);
            }

            foreach (int filterIndex in filterIndexes)
            {
                if (candidate.HasComponent(filterIndex))
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #2
0
        public static void AddOccupant(GameEntity receiver, int occupantId)
        {
            Log("AddOccupant");

            ReceiverComponent component = receiver.receiver;

            component.occupantIds[component.availableIndex] = occupantId;
            component.availableIndex = GetNextAvailableIndex(component);
            receiver.ReplaceComponent(GameComponentsLookup.Receiver, component);
        }
예제 #3
0
        public static void SetEmpty(GameEntity receiver)
        {
            ReceiverComponent component = receiver.receiver;

            for (int occupantIndex = component.occupantIds.Length - 1; occupantIndex >= 0; --occupantIndex)
            {
                component.occupantIds[occupantIndex] = kEmpty;
            }

            receiver.ReplaceComponent(GameComponentsLookup.Receiver, component);
        }
예제 #4
0
        public void Filter_ExcludesNonConsumable()
        {
            GameEntity mountain = m_Context.CreateEntity();

            ReceiverComponent consumableReceiver = new ReceiverComponent();
            int consumableIndex = GameComponentsLookup.Consumable;

            consumableReceiver.filterComponentIndexes.Add(consumableIndex);

            Assert.IsFalse(ReceiverUtils.Filter(consumableReceiver, mountain));
        }
예제 #5
0
        private static int GetNextOccupantId(ReceiverComponent component)
        {
            foreach (int occupantId in component.occupantIds)
            {
                if (occupantId != kEmpty)
                {
                    return(occupantId);
                }
            }

            return(-1);
        }
예제 #6
0
        public static bool IsEmpty(ReceiverComponent receiver)
        {
            foreach (int occupantId in receiver.occupantIds)
            {
                if (occupantId != kEmpty)
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #7
0
        public void Filter_IncludesConsumable()
        {
            GameEntity grape = m_Context.CreateEntity();

            grape.AddConsumable("Grape");

            ReceiverComponent consumableReceiver = new ReceiverComponent();
            int consumableIndex = GameComponentsLookup.Consumable;

            consumableReceiver.filterComponentIndexes.Add(consumableIndex);

            Assert.IsTrue(ReceiverUtils.Filter(consumableReceiver, grape));
        }
예제 #8
0
        public void Filter_ExcludesNonGlucoseConsumable()
        {
            GameEntity grape = m_Context.CreateEntity();

            grape.AddConsumable("Grape");

            ReceiverComponent glucoseReceiver = new ReceiverComponent();
            int glucoseIndex = GameComponentsLookup.Glucose;

            glucoseReceiver.filterComponentIndexes.Add(glucoseIndex);

            Assert.IsFalse(ReceiverUtils.Filter(glucoseReceiver, grape));
        }
예제 #9
0
        /// <summary>
        /// Gives quantity from giver to receiver without exchanging the entities.
        /// </summary>
        public static bool TryGiveQuantity(GameContext context, int[] receiverIds, int[] giverIds)
        {
            Log("TryGiveQuantity");

            bool gaveAnything = false;

            GameEntity[] giverEntities = GameLinkUtils.GetEntitiesWithIds(context, giverIds);
            foreach (GameEntity giverEntity in giverEntities)
            {
                int giftId = GetNextOccupantId(giverEntity.receiver);
                if (giftId == kEmpty)
                {
                    continue;
                }

                GameEntity gift = context.GetEntityWithId(giftId);
                DebugUtil.Assert(gift != null,
                                 "ReceiverUtils.TryOccupy: Expected gift was not null. Gift ID=" + giftId);
                if (gift == null)
                {
                    continue;
                }

                if (!gift.hasQuantity || gift.quantity.value == 0)
                {
                    continue;
                }

                foreach (int receiverId in receiverIds)
                {
                    GameEntity        receiver  = context.GetEntityWithId(receiverId);
                    ReceiverComponent component = receiver.receiver;
                    if (!Filter(component, gift))
                    {
                        continue;
                    }

                    if (!receiver.hasQuantity)
                    {
                        continue;
                    }

                    receiver.ReplaceQuantity(receiver.quantity.value + gift.quantity.value);
                    gift.ReplaceQuantity(0);
                    gaveAnything = true;
                    break;
                }
            }
            return(gaveAnything);
        }
예제 #10
0
        public void Filter_IncludesGlucose()
        {
            GameEntity glucose = m_Context.CreateEntity();

            glucose.AddConsumable("Glucose");
            glucose.isGlucose = true;

            ReceiverComponent glucoseReceiver = new ReceiverComponent();
            int glucoseIndex = GameComponentsLookup.Glucose;

            glucoseReceiver.filterComponentIndexes.Add(glucoseIndex);

            Assert.IsTrue(ReceiverUtils.Filter(glucoseReceiver, glucose));
        }
예제 #11
0
        public static int GetNextAvailableIndex(ReceiverComponent component)
        {
            int availableIndex = component.availableIndex;
            int maxOccupants   = component.occupantIds.Length;

            for (int offset = 0; offset < maxOccupants; ++offset)
            {
                int occupantIndex = (offset + availableIndex) % maxOccupants;
                if (component.occupantIds[occupantIndex] == kEmpty)
                {
                    return(occupantIndex);
                }
            }
            return(-1);
        }
예제 #12
0
        public static void RemoveOccupant(GameEntity receiver, int occupantId)
        {
            ReceiverComponent component = receiver.receiver;

            int[] occupantIds   = component.occupantIds;
            int   occupantIndex = Array.IndexOf(occupantIds, occupantId);

            DebugUtil.Assert(occupantIndex != -1,
                             "RemoveOccupant: Expected occupant ID=" + occupantId +
                             " found in occupant IDs=" + DataUtil.ToString(occupantIds) +
                             ". So an array out of bounds error will occur."
                             );
            component.occupantIds[occupantIndex] = kEmpty;
            component.availableIndex             = GetNextAvailableIndex(component);
            receiver.ReplaceComponent(GameComponentsLookup.Receiver, component);
        }
예제 #13
0
        /// <summary>
        /// Receiver might be an input or an output of a transmitter.
        /// As in a Petri Net, only transmits if all receivers are occupied.
        /// Unlike a Petri Net, only transmits if to outputs with an empty occupant position.
        /// Also unlike a Petri Net, preserves the input entity if it would be a suitable output.
        ///
        /// Expects each input and output has a receiver, or else Entitas throws an exception.
        /// </summary>
        ///
        /// <param name="giverIds">
        /// Selects first acceptable giver or gift in that giver's receiver.  Sets that giver ID to empty if selected.
        /// </param>
        public static void TryOccupy(GameContext context, int[] receiverIds, int[] giverIds)
        {
            Log("TryOccupy");

            GameEntity[] giverEntities = GameLinkUtils.GetEntitiesWithIds(context, giverIds);
            foreach (GameEntity giverEntity in giverEntities)
            {
                int giftId = GetNextOccupantId(giverEntity.receiver);
                if (giftId == kEmpty)
                {
                    continue;
                }

                RemoveOccupant(giverEntity, giftId);

                GameEntity gift = context.GetEntityWithId(giftId);
                DebugUtil.Assert(gift != null,
                                 "ReceiverUtils.TryOccupy: Expected gift was not null. Gift ID=" + giftId);
                if (gift == null)
                {
                    continue;
                }

                foreach (int receiverId in receiverIds)
                {
                    GameEntity        receiver  = context.GetEntityWithId(receiverId);
                    ReceiverComponent component = receiver.receiver;
                    if (IsFull(component))
                    {
                        continue;
                    }

                    if (Filter(component, giverEntity))
                    {
                        AddOccupant(receiver, giverEntity.id.value);
                        break;
                    }

                    if (Filter(component, gift))
                    {
                        AddOccupant(receiver, giftId);
                        break;
                    }
                }
            }
        }
예제 #14
0
        /// <returns>
        /// If receiver is empty and accepts a component of the given name.
        /// </returns>
        public static bool Filter(ReceiverComponent receiver, string componentName)
        {
            if (IsFull(receiver))
            {
                return(false);
            }

            HashSet <int> filterIndexes = receiver.filterComponentIndexes;

            if (filterIndexes == null)
            {
                DebugUtil.Assert(filterIndexes != null,
                                 "ReceiverUtils.Filter: Expects filter component indexes are defined on " + receiver +
                                 ". componentName='" + componentName + "'");
                return(false);
            }

            int componentIndex = ToComponentIndex(componentName);

            return(filterIndexes.Contains(componentIndex));
        }
예제 #15
0
        /// <returns>
        /// If receiver is empty and accepts a component of the given name.
        /// </returns>
        public static bool Filter(ReceiverComponent receiver, int componentIndex)
        {
            DebugUtil.Assert(componentIndex >= 0 && componentIndex < GameComponentsLookup.componentNames.Length,
                             "ReceiverUtils.Filter: Expects component index " + componentIndex +
                             " is in range of game component names " +
                             DataUtil.ToString(GameComponentsLookup.componentNames));

            if (IsFull(receiver))
            {
                return(false);
            }

            HashSet <int> filterIndexes = receiver.filterComponentIndexes;

            if (filterIndexes == null)
            {
                DebugUtil.Assert(filterIndexes != null,
                                 "ReceiverUtils.Filter: Expects filter component indexes are defined on " + receiver +
                                 ". componentIndex='" + componentIndex + "'");
                return(false);
            }

            return(filterIndexes.Contains(componentIndex));
        }
예제 #16
0
 // TODO: Gets quantity of each occupant.
 public static bool IsFull(ReceiverComponent receiver)
 {
     return(receiver.availableIndex < 0);
 }