/// <summary>
        /// Processes forall effects.
        /// </summary>
        /// <param name="relativeState">Relative state.</param>
        /// <returns>Effect relevance (relevant, irrelevant, or anti-relevant).</returns>
        private EffectRelevance ProcessForallEffects(IRelativeState relativeState)
        {
            bool anyRelevant = false;

            foreach (var forallEffect in Effects.ForallEffects)
            {
                EffectsRelevanceRelativeStateEvaluator evaluator = new EffectsRelevanceRelativeStateEvaluator(forallEffect.Effects, GroundingManager);

                IEnumerable <ISubstitution> localSubstitutions = GroundingManager.GenerateAllLocalSubstitutions(forallEffect.Parameters);
                foreach (var localSubstitution in localSubstitutions)
                {
                    OperatorSubstitution.AddLocalSubstitution(localSubstitution);

                    var result = evaluator.EvaluateInternal(relativeState, OperatorSubstitution);
                    anyRelevant |= (result == EffectRelevance.RELEVANT);

                    OperatorSubstitution.RemoveLocalSubstitution(localSubstitution);

                    if (result == EffectRelevance.ANTI_RELEVANT)
                    {
                        return(EffectRelevance.ANTI_RELEVANT);
                    }
                }
            }

            return((anyRelevant) ? EffectRelevance.RELEVANT : EffectRelevance.IRRELEVANT);
        }
        /// <summary>
        /// Processes conditional (when) effects.
        /// </summary>
        /// <param name="relativeState">Relative state.</param>
        /// <param name="relevantConditionalEffects">Output indices of relevant conditional effects (can be null).</param>
        /// <returns>Effect relevance (relevant, irrelevant, or anti-relevant).</returns>
        private EffectRelevance ProcessWhenEffects(IRelativeState relativeState, IList <int> relevantConditionalEffects = null)
        {
            bool anyRelevant     = false;
            int  whenEffectIndex = -1;

            foreach (var whenEffect in Effects.WhenEffects)
            {
                ++whenEffectIndex;

                List <IEffect> subEffects = new List <IEffect>();
                whenEffect.Effects.ForEach(subEffect => subEffects.Add(subEffect));
                EffectsRelevanceRelativeStateEvaluator evaluator = new EffectsRelevanceRelativeStateEvaluator(subEffects, GroundingManager);

                var result = evaluator.EvaluateInternal(relativeState, OperatorSubstitution, relevantConditionalEffects);
                if (result == EffectRelevance.ANTI_RELEVANT)
                {
                    // anti-relevant conditional effect -> can't be used (but it doesn't have to be, we just ignore it)
                    continue;
                }

                if (result == EffectRelevance.RELEVANT)
                {
                    relevantConditionalEffects?.Add(whenEffectIndex);
                    anyRelevant = true;
                }
            }

            return((anyRelevant) ? EffectRelevance.RELEVANT : EffectRelevance.IRRELEVANT);
        }
        /// <summary>
        /// Collects relevant when effects for the specified relative state.
        /// </summary>
        /// <param name="relativeState">Relative state.</param>
        /// <returns>List of relevant when effects.</returns>
        private List <WhenEffect> GetRelevantWhenEffectsForConditions(IRelativeState relativeState)
        {
            List <int> relevantWhenEffectsIndices = new List <int>();
            EffectsRelevanceRelativeStateEvaluator relevanceEvaluator = new EffectsRelevanceRelativeStateEvaluator(Effects, GroundingManager);

            relevanceEvaluator.Evaluate(relativeState, new Substitution(), relevantWhenEffectsIndices); // empty substitution here because effects already grounded

            List <WhenEffect> relevantWhenEffects = new List <WhenEffect>();

            relevantWhenEffectsIndices.ForEach(index => relevantWhenEffects.Add(Effects.WhenEffects[index]));
            return(relevantWhenEffects);
        }