/// <summary> /// Analyzes an attribute and returns whether or not it is valid. /// </summary> /// <param name="character">The character to analyze.</param> /// <param name="attribute">The characters attribute to check.</param> /// <param name="dependency">The dependency to check with.</param> /// <returns>A string array containing useful error messages. If empty, no errors were found.</returns> public static string[] ValidateAttribute(Character character, NumAttribute attribute) { List <string> errors = new List <string>(); attribute.setMax(FindHighestPossible(character, attribute)); attribute.setMin(FindLowestPossible(character, attribute)); if (attribute.getMax() < attribute.getMin()) { errors.Add(attribute.Name + " has a higher minimum value than its maximum value, meaning it can never be correct."); } foreach (NumDependency d in attribute.Dependancies) { if (d.type == Operand.QuotiantOf) { if (d.v2IsRef) { if (Zeroable(character, (NumAttribute)character.Attributes[d.v2Ref])) { errors.Add(attribute.Name + " is derived by dividing by zero, or could potentially be derived by dividing by zero.\n" + "Ensure that no attributes depended upon by " + attribute.Name + " can potentially be zero."); } } else if (d.Value2 == 0) { errors.Add(attribute.Name + " is derived by dividing by zero, or could potentially be derived by dividing by zero.\n" + "Ensure that no attributes depended upon by " + attribute.Name + " can potentially be zero."); } } } return(errors.ToArray()); }
/// <summary> /// Takes an instance of character and a specific attribute within that character, and returns the lowest value that attribute can potentially have. /// </summary> /// <param name="character">The instance of character your attribute is stored within.</param> /// <param name="attribute">The attribute you are validating</param> /// <returns>The lowest number the attribute is allowed to be based on its dependencies</returns> private static decimal FindLowestPossible(Character character, NumAttribute attribute) { decimal lowestPossible = -decimal.MaxValue; if (attribute.getMin() != null) { lowestPossible = (decimal)attribute.getMin(); } else { foreach (NumDependency d in attribute.Dependancies) { switch (d.type) { case Operand.Equals: if (d.v1IsRef) { lowestPossible = FindLowestPossible(character, (NumAttribute)character.Attributes[d.v1Ref]); } else { lowestPossible = d.Value1; } attribute.setMin(lowestPossible); break; case Operand.DifferenceOf: decimal x = d.v1IsRef ? FindLowestPossible(character, (NumAttribute)character.Attributes[d.v1Ref]) : d.Value1; decimal y = d.v2IsRef ? FindLowestPossible(character, (NumAttribute)character.Attributes[d.v2Ref]) : d.Value2; lowestPossible = x - y; attribute.setMin(lowestPossible); break; case Operand.GreaterThan: case Operand.GreaterOrEqualTo: if (d.v1IsRef) { NumAttribute n = (NumAttribute)character.Attributes[d.v1Ref]; lowestPossible = FindLowestPossible(character, n) - (d.type == Operand.LessOrEqualTo ? 0 : 1); } else { lowestPossible = d.Value1 - (d.type == Operand.LessOrEqualTo ? 0 : 1); } break; case Operand.ProductOf: x = d.v1IsRef ? FindLowestPossible(character, (NumAttribute)character.Attributes[d.v1Ref]) : d.Value1; y = d.v2IsRef ? FindLowestPossible(character, (NumAttribute)character.Attributes[d.v2Ref]) : d.Value2; lowestPossible = x * y; attribute.setMin(lowestPossible); break; case Operand.QuotiantOf: x = d.v1IsRef ? FindLowestPossible(character, (NumAttribute)character.Attributes[d.v1Ref]) : d.Value1; y = d.v2IsRef ? FindLowestPossible(character, (NumAttribute)character.Attributes[d.v2Ref]) : d.Value2; lowestPossible = x / y; attribute.setMin(lowestPossible); break; case Operand.SumOf: x = d.v1IsRef ? FindLowestPossible(character, (NumAttribute)character.Attributes[d.v1Ref]) : d.Value1; y = d.v2IsRef ? FindLowestPossible(character, (NumAttribute)character.Attributes[d.v2Ref]) : d.Value2; lowestPossible = x + y; attribute.setMin(lowestPossible); break; } } } attribute.setMin(lowestPossible); return(lowestPossible); }