예제 #1
0
        private static void AppendAndOrNext(StringBuilder andNext, Requirement requirement, NumberFormat numberFormat,
                                            StringBuilder addSources, StringBuilder subSources, StringBuilder addAddress, ref RequirementType lastAndNext)
        {
            if (addSources.Length > 0 || subSources.Length > 0 || addAddress.Length > 0)
            {
                andNext.Append('(');
                requirement.AppendString(andNext, numberFormat,
                                         addSources.Length > 0 ? addSources.ToString() : null,
                                         subSources.Length > 0 ? subSources.ToString() : null,
                                         null,
                                         null,
                                         addAddress.Length > 0 ? addAddress.ToString() : null);
                andNext.Append(')');

                addAddress.Clear();
                addSources.Clear();
                subSources.Clear();
            }
            else
            {
                requirement.AppendString(andNext, numberFormat);
            }

            if (lastAndNext != requirement.Type)
            {
                if (lastAndNext != RequirementType.None)
                {
                    andNext.Insert(0, '(');
                    andNext.Append(')');
                }

                lastAndNext = requirement.Type;
            }

            if (requirement.Type == RequirementType.OrNext)
            {
                andNext.Append(" || ");
            }
            else
            {
                andNext.Append(" && ");
            }
        }
예제 #2
0
        private static void AppendFieldModifier(StringBuilder builder, Requirement requirement, NumberFormat numberFormat)
        {
            switch (requirement.Operator)
            {
            case RequirementOperator.Multiply:
                builder.Append(" * ");
                requirement.Right.AppendString(builder, numberFormat);
                break;

            case RequirementOperator.Divide:
                builder.Append(" / ");
                requirement.Right.AppendString(builder, numberFormat);
                break;

            case RequirementOperator.BitwiseAnd:
                builder.Append(" & ");
                requirement.Right.AppendString(builder, numberFormat);
                break;
            }
        }
예제 #3
0
 internal Achievement()
 {
     CoreRequirements      = new Requirement[0];
     AlternateRequirements = new IEnumerable <Requirement> [0];
 }
예제 #4
0
        /// <summary>
        /// Constructs a series of <see cref="RequirementEx" />s from a series of <see cref="Requirement" />s.
        /// </summary>
        public static List <RequirementEx> Combine(IEnumerable <Requirement> requirements)
        {
            var group = new List <RequirementEx>();

            Requirement combiningRequirement = null;

            foreach (var requirement in requirements)
            {
                if (combiningRequirement != null &&
                    (combiningRequirement.Type == RequirementType.AndNext ||
                     combiningRequirement.Type == RequirementType.OrNext))
                {
                    // "A || always_false()" and "A && always_true()" are both just "A",
                    // but we need to preserve the flag and hit target from the second condition.

                    // create a copy without the hit count for evaluation
                    var newRequirement = new Requirement
                    {
                        Left     = requirement.Left,
                        Operator = requirement.Operator,
                        Right    = requirement.Right
                    };

                    bool redundantEvaluation = (combiningRequirement.Type == RequirementType.AndNext);
                    if (newRequirement.Evaluate() == redundantEvaluation)
                    {
                        if (combiningRequirement.HitCount != 0 && requirement.HitCount != 0)
                        {
                            // if both requirements have separate hit targets, we can't combine them
                        }
                        else
                        {
                            // going to be modifying the combiningRequirement, create a copy
                            newRequirement = new Requirement
                            {
                                // use the flag from the redundant condition
                                Type = requirement.Type,

                                Left     = combiningRequirement.Left,
                                Operator = combiningRequirement.Operator,
                                Right    = combiningRequirement.Right
                            };

                            // one of the two conditions has a hit count of zero, so this
                            // effectively takes whichever isn't zero.
                            newRequirement.HitCount = requirement.HitCount + combiningRequirement.HitCount;

                            // replace the last requirement with the updated requirement
                            var lastGroupRequirements = group.Last().Requirements;
                            lastGroupRequirements.Remove(combiningRequirement);
                            lastGroupRequirements.Add(newRequirement);

                            // decide if the condition is still combining
                            combiningRequirement = requirement.IsCombining ? newRequirement : null;

                            continue;
                        }
                    }
                }
                else
                {
                    switch (requirement.Type)
                    {
                    case RequirementType.AddHits:
                    case RequirementType.SubHits:
                        // an always_false() condition will never generate a hit
                        if (requirement.Evaluate() == false)
                        {
                            continue;
                        }
                        break;

                    case RequirementType.AndNext:
                        // an always_true() condition will not affect the next condition
                        if (requirement.Evaluate() == true)
                        {
                            continue;
                        }
                        break;

                    case RequirementType.OrNext:
                        // an always_false() condition will not affect the next condition
                        if (requirement.Evaluate() == false)
                        {
                            continue;
                        }
                        break;
                    }
                }

                if (combiningRequirement == null)
                {
                    group.Add(new RequirementEx());
                }

                group.Last().Requirements.Add(requirement);

                combiningRequirement = requirement.IsCombining ? requirement : null;
            }

            return(group);
        }
예제 #5
0
        internal void AppendCondition(StringBuilder builder, NumberFormat numberFormat,
                                      string addSources = null, string subSources = null, string addHits = null,
                                      string andNext    = null, string addAddress = null)
        {
            if (!string.IsNullOrEmpty(addSources))
            {
                builder.Append('(');
                builder.Append(addSources);
            }
            else if (!string.IsNullOrEmpty(subSources))
            {
                builder.Append('(');
            }
            else if (!string.IsNullOrEmpty(addHits))
            {
                builder.Append(addHits);
            }
            else if (!string.IsNullOrEmpty(andNext))
            {
                builder.Append(andNext);
            }

            string suffix = null;

            switch (Type)
            {
            case RequirementType.AddSource:
                Left.AppendString(builder, numberFormat);
                suffix = " + ";
                break;

            case RequirementType.SubSource:
                builder.Append(" - ");
                Left.AppendString(builder, numberFormat);
                break;

            default:
                if (Operator != RequirementOperator.None &&
                    string.IsNullOrEmpty(subSources) && string.IsNullOrEmpty(addSources))
                {
                    var clone = new Requirement
                    {
                        Left     = this.Left,
                        Operator = this.Operator,
                        Right    = this.Right
                    };
                    var result = clone.Evaluate();
                    if (result == true)
                    {
                        builder.Append("always_true()");
                        return;
                    }
                    else if (result == false)
                    {
                        builder.Append("always_false()");
                        return;
                    }
                }

                Left.AppendString(builder, numberFormat, addAddress);
                break;
            }

            // scaling operators need to be appended before chained operations
            switch (Operator)
            {
            case RequirementOperator.Multiply:
                builder.Append(" * ");
                Right.AppendString(builder, numberFormat, addAddress);
                break;

            case RequirementOperator.Divide:
                builder.Append(" / ");
                Right.AppendString(builder, numberFormat, addAddress);
                break;

            case RequirementOperator.BitwiseAnd:
                builder.Append(" & ");
                Right.AppendString(builder, numberFormat, addAddress);
                break;
            }

            // append chained operations
            if (!string.IsNullOrEmpty(subSources))
            {
                builder.Append(subSources);
                builder.Append(')');
            }
            else if (!string.IsNullOrEmpty(addSources))
            {
                builder.Append(')');
            }

            // handle comparison operators
            switch (Operator)
            {
            case RequirementOperator.Equal:
                builder.Append(" == ");
                break;

            case RequirementOperator.NotEqual:
                builder.Append(" != ");
                break;

            case RequirementOperator.LessThan:
                builder.Append(" < ");
                break;

            case RequirementOperator.LessThanOrEqual:
                builder.Append(" <= ");
                break;

            case RequirementOperator.GreaterThan:
                builder.Append(" > ");
                break;

            case RequirementOperator.GreaterThanOrEqual:
                builder.Append(" >= ");
                break;

            case RequirementOperator.Multiply:
            case RequirementOperator.Divide:
            case RequirementOperator.BitwiseAnd:
            // handled above, treat like none

            case RequirementOperator.None:
                if (suffix != null)
                {
                    builder.Append(suffix);
                }
                return;
            }

            Right.AppendString(builder, numberFormat, addAddress);

            if (suffix != null)
            {
                builder.Append(suffix);
            }
        }