public void TestUnderflowComplex(string input, string expected, string expectedSerialized)
        {
            var tokenizer = Tokenizer.CreateTokenizer(input);
            var expr      = ExpressionBase.Parse(new PositionalTokenizer(tokenizer));

            var scope = new InterpreterScope(RATools.Parser.AchievementScriptInterpreter.GetGlobalScope());

            scope.Context = new RATools.Parser.TriggerBuilderContext();

            ExpressionBase result;

            if (!expr.ReplaceVariables(scope, out result))
            {
                Assert.That(result, Is.InstanceOf <ParseErrorExpression>());
            }

            var builder = new StringBuilder();

            result.AppendString(builder);
            Assert.That(builder.ToString(), Is.EqualTo(expected));

            var achievementBuilder = new RATools.Parser.ScriptInterpreterAchievementBuilder();

            achievementBuilder.PopulateFromExpression(result);
            var serialized = achievementBuilder.SerializeRequirements();

            Assert.That(serialized, Is.EqualTo(expectedSerialized));
        }
Example #2
0
        /// <summary>
        /// Gets a serialized string for determining if memory matches the provided expression.
        /// </summary>
        /// <param name="expression">The expression to process.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="result">[out] The error if not successful.</param>
        /// <returns><c>true</c> if successful, <c>false</c> if not.</returns>
        public static string GetConditionString(ExpressionBase expression, InterpreterScope scope, out ExpressionBase result)
        {
            var achievement = new ScriptInterpreterAchievementBuilder();

            if (!ProcessAchievementConditions(achievement, expression, scope, out result))
            {
                return(null);
            }

            return(achievement.SerializeRequirements());
        }
Example #3
0
        /// <summary>
        /// Populates an achievement from an expression.
        /// </summary>
        /// <param name="achievement">The achievement to populate.</param>
        /// <param name="expression">The expression to populate from.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="result">[out] The error if not successful.</param>
        /// <returns><c>true</c> if successful, <c>false</c> if not.</returns>
        public static bool ProcessAchievementConditions(ScriptInterpreterAchievementBuilder achievement, ExpressionBase expression, InterpreterScope scope, out ExpressionBase result)
        {
            ParseErrorExpression parseError;

            if (!achievement.PopulateFromExpression(expression, scope, out parseError))
            {
                result = parseError;
                return(false);
            }

            var message = achievement.Optimize();

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

            result = null;
            return(true);
        }
Example #4
0
        /// <summary>
        /// Populates an achievement from an expression.
        /// </summary>
        /// <param name="achievement">The achievement to populate.</param>
        /// <param name="expression">The expression to populate from.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="result">[out] The error if not successful.</param>
        /// <returns><c>true</c> if successful, <c>false</c> if not.</returns>
        public static bool ProcessAchievementConditions(ScriptInterpreterAchievementBuilder achievement, ExpressionBase expression, InterpreterScope scope, out ExpressionBase result)
        {
            ParseErrorExpression parseError;

            if (!achievement.PopulateFromExpression(expression, scope, out parseError))
            {
                result = parseError;
                return(false);
            }

            // only optimize at the outermost level
            if (ReferenceEquals(scope.GetOutermostContext <TriggerBuilderContext>(), scope.GetContext <TriggerBuilderContext>()))
            {
                var message = achievement.Optimize();
                if (message != null)
                {
                    result = new ParseErrorExpression(message, expression);
                    return(false);
                }
            }

            result = null;
            return(true);
        }
Example #5
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);
        }