Example #1
0
        private static bool ProcessValueExpression(ExpressionBase expression, InterpreterScope scope, List <Term> terms, out ExpressionBase result)
        {
            var functionCall = expression as FunctionCallExpression;

            if (functionCall != null)
            {
                var requirements = new List <Requirement>();
                var context      = new ValueBuilderContext()
                {
                    Trigger = requirements
                };
                var valueScope = new InterpreterScope(scope)
                {
                    Context = context
                };
                var error = context.CallFunction(functionCall, valueScope);
                if (error != null)
                {
                    result = error;
                    return(false);
                }

                SetImpliedMeasuredTarget(requirements);
                return(ProcessMeasuredValue(requirements, expression, terms, out result));
            }

            var field = AchievementBuilder.CreateFieldFromExpression(expression);

            if (field.Type != FieldType.None)
            {
                terms.Last().field = field;
                result = null;
                return(true);
            }

            var mathematic = expression as MathematicExpression;

            if (mathematic != null)
            {
                if (mathematic.Operation == MathematicOperation.Multiply || mathematic.Operation == MathematicOperation.Divide)
                {
                    var mathematicLeft = mathematic.Left as MathematicExpression;
                    if (mathematicLeft != null && MathematicExpression.GetPriority(mathematicLeft.Operation) == MathematicPriority.Add)
                    {
                        var newLeft  = new MathematicExpression(mathematicLeft.Left, mathematic.Operation, mathematic.Right);
                        var newRight = new MathematicExpression(mathematicLeft.Right, mathematic.Operation, mathematic.Right);
                        mathematic = new MathematicExpression(newLeft, mathematicLeft.Operation, newRight);
                    }
                }

                if (!ProcessValueExpression(mathematic.Left, scope, terms, out result))
                {
                    return(false);
                }

                field = AchievementBuilder.CreateFieldFromExpression(mathematic.Right);
                if (MergeFields(field, terms.Last(), mathematic.Operation))
                {
                    return(true);
                }

                switch (mathematic.Operation)
                {
                case MathematicOperation.Add:
                    terms.Add(new Term {
                        multiplier = 1.0
                    });
                    return(ProcessValueExpression(mathematic.Right, scope, terms, out result));

                case MathematicOperation.Subtract:
                    terms.Add(new Term {
                        multiplier = -1.0
                    });
                    return(ProcessValueExpression(mathematic.Right, scope, terms, out result));

                case MathematicOperation.Multiply:
                case MathematicOperation.Divide:
                    return(ProcessValueExpression(WrapInMeasured(expression), scope, terms, out result));
                }
            }

            var conditionalExpression = expression as ConditionalExpression;

            if (conditionalExpression != null)
            {
                ParseErrorExpression parseError;
                var achievement = new ScriptInterpreterAchievementBuilder();
                if (!achievement.PopulateFromExpression(expression, scope, out parseError))
                {
                    result = parseError;
                    return(false);
                }

                SetImpliedMeasuredTarget(achievement.CoreRequirements);
                foreach (var alt in achievement.AlternateRequirements)
                {
                    SetImpliedMeasuredTarget(alt);
                }

                var message = achievement.Optimize();
                if (message != null)
                {
                    result = new ParseErrorExpression(message, expression);
                    return(false);
                }

                if (achievement.AlternateRequirements.Any())
                {
                    result = new ParseErrorExpression("Alt groups not supported in value expression", expression);
                    return(false);
                }

                return(ProcessMeasuredValue(achievement.CoreRequirements, expression, terms, out result));
            }

            result = new ParseErrorExpression("Value must be a constant or a memory accessor", expression);
            return(false);
        }
Example #2
0
        private ParseErrorExpression ExecuteAchievementMathematic(MathematicExpression mathematic, InterpreterScope scope)
        {
            var left      = mathematic.Left;
            var operation = mathematic.Operation;
            var context   = scope.GetContext <TriggerBuilderContext>();
            ParseErrorExpression error;

            ExpressionBase right;

            if (!mathematic.Right.ReplaceVariables(scope, out right))
            {
                return((ParseErrorExpression)right);
            }

            if (operation == MathematicOperation.Subtract && (right is FunctionCallExpression || right is MathematicExpression))
            {
                // if subtracting a non-integer, swap the order to perform a SubSource
                var newEqualityModifiers = new Stack <ValueModifier>();
                var oldEqualityModifiers = _equalityModifiers;
                _equalityModifiers = newEqualityModifiers;

                var requirements = new List <Requirement>();
                var innerContext = new TriggerBuilderContext()
                {
                    Trigger = requirements
                };
                var innerScope = new InterpreterScope(scope)
                {
                    Context = innerContext
                };

                // generate the condition for the right side
                error = ExecuteAchievementExpression(right, innerScope);
                _equalityModifiers = oldEqualityModifiers;
                if (error != null)
                {
                    return(error);
                }

                foreach (var requirement in requirements)
                {
                    switch (requirement.Type)
                    {
                    case RequirementType.None:
                    case RequirementType.AddSource:
                        requirement.Type = RequirementType.SubSource;
                        break;

                    case RequirementType.SubSource:
                        requirement.Type = RequirementType.AddSource;
                        break;

                    default:
                        return(new ParseErrorExpression("Cannot normalize expression for negation", mathematic));
                    }

                    context.Trigger.Add(requirement);
                }

                foreach (var modifier in newEqualityModifiers)
                {
                    switch (modifier.Operation)
                    {
                    case MathematicOperation.Add:
                        _equalityModifiers.Push(new ValueModifier(MathematicOperation.Subtract, modifier.Amount));
                        break;

                    case MathematicOperation.Subtract:
                        _equalityModifiers.Push(new ValueModifier(MathematicOperation.Add, modifier.Amount));
                        break;

                    default:
                        return(new ParseErrorExpression("Cannot normalize expression for negation", mathematic));
                    }
                }

                right     = mathematic.Left;
                operation = MathematicOperation.Add;
            }
            else
            {
                // generate the condition for the first expression
                error = ExecuteAchievementExpression(left, scope);
                if (error != null)
                {
                    return(error);
                }
            }

            var integerOperand = right as IntegerConstantExpression;

            if (integerOperand != null)
            {
                var oppositeOperation = MathematicExpression.GetOppositeOperation(operation);
                if (oppositeOperation == MathematicOperation.None)
                {
                    return(new ParseErrorExpression(String.Format("Cannot normalize expression to eliminate {0}", MathematicExpression.GetOperatorType(mathematic.Operation)), mathematic));
                }

                var priority = MathematicExpression.GetPriority(mathematic.Operation);
                if (priority != MathematicPriority.Add)
                {
                    if (context.Trigger.Count > 1)
                    {
                        var previousRequirementType = context.Trigger.ElementAt(context.Trigger.Count - 2).Type;
                        if (previousRequirementType == RequirementType.AddSource || previousRequirementType == RequirementType.SubSource)
                        {
                            return(new ParseErrorExpression(String.Format("Cannot normalize expression to eliminate {0}", MathematicExpression.GetOperatorType(mathematic.Operation)), mathematic));
                        }
                    }

                    if (_equalityModifiers.Any(e => MathematicExpression.GetPriority(e.Operation) != priority))
                    {
                        return(new ParseErrorExpression(String.Format("Cannot normalize expression to eliminate {0}", MathematicExpression.GetOperatorType(mathematic.Operation)), mathematic));
                    }
                }

                _equalityModifiers.Push(new ValueModifier(oppositeOperation, integerOperand.Value));
                return(null);
            }

            if (operation == MathematicOperation.Add)
            {
                foreach (var modifier in _equalityModifiers)
                {
                    if (MathematicExpression.GetPriority(modifier.Operation) != MathematicPriority.Add)
                    {
                        return(new ParseErrorExpression(String.Format("Cannot normalize expression to eliminate {0}", MathematicExpression.GetOperatorType(MathematicExpression.GetOppositeOperation(modifier.Operation))), mathematic));
                    }
                }

                // adding two memory accessors - make sure previous is AddSource or SubSource
                if (context.LastRequirement.Type != RequirementType.SubSource)
                {
                    context.LastRequirement.Type     = RequirementType.AddSource;
                    context.LastRequirement.Operator = RequirementOperator.None;
                    context.LastRequirement.Right    = new Field();
                }
            }
            else
            {
                return(new ParseErrorExpression(String.Format("Cannot normalize expression to eliminate {0}", MathematicExpression.GetOperatorType(mathematic.Operation)), mathematic));
            }

            // generate the condition for the second expression
            error = ExecuteAchievementExpression(right, scope);
            if (error != null)
            {
                error = new ParseErrorExpression(error.Message, mathematic);
            }
            return(error);
        }