/// <summary> Applies specified dice operation to the given roll values. </summary> /// <remarks> <see cref="DiceOperation.Plus"/> and <see cref="DiceOperation.Minus"/> are modifying roll totals, /// so there isn't any good way to shove them in. For these operations /// <paramref name="opValueProvider"/>'s value is being added to the first roll value.</remarks> /// <param name="rolls">Roll values to modify.</param> /// <param name="operation"></param> /// <param name="opValueProvider">Rolls a value which will be used for modification.</param> /// <returns>Rolls modified with <paramref name="opValueProvider"/>'s value according to the given operation. /// </returns> public static IEnumerable<double> ApplyOperation(IEnumerable<double> rolls, DiceOperation operation, IDie opValueProvider) { Contract.Requires(rolls != null); Contract.Requires(operation != DiceOperation.None); Contract.Requires(opValueProvider != null); Contract.Ensures(Contract.Result<IEnumerable<double>>() != null); // Plus and Minus are modifying roll totals, so there isn't any good way to shove them in. // Let's just add them to first value. if (operation == DiceOperation.Minus || operation == DiceOperation.Plus) { bool applied = false; foreach (var roll in rolls) { if (!applied) { yield return PerformRollCombination(roll, operation, opValueProvider.Roll()); applied = true; } else { yield return roll; } } // If rolls were empty, return the total modifier as is: if (!applied) { var value = opValueProvider.Roll(); yield return (operation == DiceOperation.Minus) ? -value : value; } } else { // For other operations just modify each roll value using the value provider. foreach (var roll in rolls) { yield return PerformRollCombination(roll, operation, opValueProvider.Roll()); } } }
/// <summary> Appends a new chain node to the dice chain using a specified operation.</summary> /// <remarks> Append(DiceOperation.Minus, Dice.D10) is equivalent to Minus(Dice.D10). </remarks> /// <param name="linkOperation">The operation used to operate on dice rolls between chain nodes.</param> /// <param name="linkContent">Actual content of the chain node.</param> /// <returns>Dice chain with new node appended.</returns> public DiceChain Append(DiceOperation linkOperation, SeveralDice linkContent) { Contract.Requires(linkOperation != DiceOperation.None); Contract.Requires(linkContent != null); LastLink = new DiceChainLink(linkOperation, linkContent, LastLink); return(this); }
internal DiceChainRollStep(double[] rolls, DiceOperation operationToUseWithPreviousStep) { Contract.Requires(rolls != null); Contract.Requires(operationToUseWithPreviousStep != DiceOperation.None); Rolls = rolls; Total = rolls.Sum(); Operation = operationToUseWithPreviousStep; }
/// <summary> Applies specified dice operation to the given roll values. </summary> /// <remarks> <see cref="DiceOperation.Plus"/> and <see cref="DiceOperation.Minus"/> are modifying roll totals, /// so there isn't any good way to shove them in. For these operations /// <paramref name="opValue"/> is being added to the first roll value.</remarks> /// <param name="rolls">Roll values to modify.</param> /// <param name="operation"></param> /// <param name="opValue">A value which will be used for modification.</param> /// <returns>Rolls modified with <paramref name="opValue"/> according to the given operation. /// </returns> public static IEnumerable<double> ApplyOperation(IEnumerable<double> rolls, DiceOperation operation, double opValue) { Contract.Requires(rolls != null); Contract.Requires(operation != DiceOperation.None); Contract.Ensures(Contract.Result<IEnumerable<double>>() != null); return ApplyOperation(rolls, operation, new FixedDie(opValue)); }
/// <summary> Initializes a new instance of the <see cref="DiceChainLink" /> class. </summary> /// <param name="operation">The dice operation which will be used with a dice chain node.</param> /// <param name="node">This dice chain node.</param> /// <param name="previous">The link to previous node in the dice chain.</param> internal DiceChainLink(DiceOperation operation, SeveralDice node, DiceChainLink previous) { Contract.Requires(operation != DiceOperation.None); Contract.Requires(node != null); Operation = operation; Node = node; Previous = previous; }
/// <summary> Initializes a new instance of the <see cref="DiceChainSetup" /> struct. </summary> /// <param name="amountProvider">The amount of dice added to the created <see cref="DiceChain" />.</param> /// <param name="previousOperation">The operation to use with previous <see cref="DiceChain"/>.</param> /// <param name="previousDice">The previous <see cref="DiceChain"/> to carry on to next one.</param> public DiceChainSetup(IDie amountProvider, DiceOperation previousOperation, DiceChain previousDice) { Contract.Requires(previousOperation != DiceOperation.None); Contract.Requires(amountProvider != null); Amount = amountProvider; PreviousOperation = previousOperation; PreviousDice = previousDice; }
/// <summary>Returns a <see cref="String" /> that represents a specified <see cref="DiceOperation"/>.</summary> /// <param name="diceOperation">The dice operation.</param> /// <returns> A <see cref="String" /> that represents a specified <see cref="DiceOperation"/>. </returns> public static string ToOpString(DiceOperation diceOperation) { Contract.Ensures(Contract.Result<string>() != null); switch (diceOperation) { case DiceOperation.Divide: return "/"; case DiceOperation.EachPlus: case DiceOperation.Plus: return "+"; case DiceOperation.EachMinus: case DiceOperation.Minus: return "-"; case DiceOperation.Multiply: return "*"; default: return String.Empty; } }
/// <summary>Returns a <see cref="String" /> that represents a specified <see cref="DiceOperation"/>.</summary> /// <param name="diceOperation">The dice operation.</param> /// <returns> A <see cref="String" /> that represents a specified <see cref="DiceOperation"/>. </returns> public static string ToOpString(DiceOperation diceOperation) { Contract.Ensures(Contract.Result <string>() != null); switch (diceOperation) { case DiceOperation.Divide: return("/"); case DiceOperation.EachPlus: case DiceOperation.Plus: return("+"); case DiceOperation.EachMinus: case DiceOperation.Minus: return("-"); case DiceOperation.Multiply: return("*"); default: return(String.Empty); } }
internal static double PerformRollCombination(double left, DiceOperation op, double right, int leftRollCount = 1) { switch (op) { case DiceOperation.Plus: return(left + right); case DiceOperation.Minus: return(left - right); case DiceOperation.Divide: return(!right.EqualsZero() ? left / right : 0); case DiceOperation.Multiply: return(left * right); case DiceOperation.EachPlus: return(left + (leftRollCount * right)); case DiceOperation.EachMinus: return(left - (leftRollCount * right)); default: throw new InvalidOperationException("Unknown dice operation."); } }
/// <summary> Applies specified dice operation to the given roll values. </summary> /// <remarks> <see cref="DiceOperation.Plus"/> and <see cref="DiceOperation.Minus"/> are modifying roll totals, /// so there isn't any good way to shove them in. For these operations /// <paramref name="opValueProvider"/>'s value is being added to the first roll value.</remarks> /// <param name="rolls">Roll values to modify.</param> /// <param name="operation"></param> /// <param name="opValueProvider">Rolls a value which will be used for modification.</param> /// <returns>Rolls modified with <paramref name="opValueProvider"/>'s value according to the given operation. /// </returns> public static IEnumerable <double> ApplyOperation(IEnumerable <double> rolls, DiceOperation operation, IDie opValueProvider) { Contract.Requires(rolls != null); Contract.Requires(operation != DiceOperation.None); Contract.Requires(opValueProvider != null); Contract.Ensures(Contract.Result <IEnumerable <double> >() != null); // Plus and Minus are modifying roll totals, so there isn't any good way to shove them in. // Let's just add them to first value. if (operation == DiceOperation.Minus || operation == DiceOperation.Plus) { bool applied = false; foreach (var roll in rolls) { if (!applied) { yield return(PerformRollCombination(roll, operation, opValueProvider.Roll())); applied = true; } else { yield return(roll); } } // If rolls were empty, return the total modifier as is: if (!applied) { var value = opValueProvider.Roll(); yield return((operation == DiceOperation.Minus) ? -value : value); } } else // For other operations just modify each roll value using the value provider. { foreach (var roll in rolls) { yield return(PerformRollCombination(roll, operation, opValueProvider.Roll())); } } }
/// <summary> Applies specified dice operation to the given roll values. </summary> /// <remarks> <see cref="DiceOperation.Plus"/> and <see cref="DiceOperation.Minus"/> are modifying roll totals, /// so there isn't any good way to shove them in. For these operations /// <paramref name="opValue"/> is being added to the first roll value.</remarks> /// <param name="rolls">Roll values to modify.</param> /// <param name="operation"></param> /// <param name="opValue">A value which will be used for modification.</param> /// <returns>Rolls modified with <paramref name="opValue"/> according to the given operation. /// </returns> public static IEnumerable <double> ApplyOperation(IEnumerable <double> rolls, DiceOperation operation, double opValue) { Contract.Requires(rolls != null); Contract.Requires(operation != DiceOperation.None); Contract.Ensures(Contract.Result <IEnumerable <double> >() != null); return(ApplyOperation(rolls, operation, new FixedDie(opValue))); }
/// <summary> Determines whether a specified operation is applied to each roll value instead of total. </summary> /// <param name="op">The dice operation.</param> /// <returns> True if each roll is modified. </returns> public static bool IsEach(DiceOperation op) { return(op == DiceOperation.EachPlus || op == DiceOperation.EachMinus); }
/// <summary> Initializes a new instance of the <see cref="DiceChainLink" /> class. </summary> /// <param name="operation">The dice operation which will be used with a dice chain node.</param> /// <param name="node">This dice chain node.</param> internal DiceChainLink(DiceOperation operation, SeveralDice node) : this(operation, node, null) { Contract.Requires(operation != DiceOperation.None); Contract.Requires(node != null); }
/// <summary> Appends a new chain node to the dice chain using a specified operation.</summary> /// <remarks> Append(DiceOperation.Minus, Dice.D10) is equivalent to Minus(Dice.D10). </remarks> /// <param name="linkOperation">The operation used to operate on dice rolls between chain nodes.</param> /// <param name="linkContent">Actual content of the chain node.</param> /// <returns>Dice chain with new node appended.</returns> public DiceChain Append(DiceOperation linkOperation, SeveralDice linkContent) { Contract.Requires(linkOperation != DiceOperation.None); Contract.Requires(linkContent != null); LastLink = new DiceChainLink(linkOperation, linkContent, LastLink); return this; }
/// <summary> Determines whether a specified operation is applied to each roll value instead of total. </summary> /// <param name="op">The dice operation.</param> /// <returns> True if each roll is modified. </returns> public static bool IsEach(DiceOperation op) { return op == DiceOperation.EachPlus || op == DiceOperation.EachMinus; }
internal static double PerformRollCombination(double left, DiceOperation op, double right, int leftRollCount = 1) { switch (op) { case DiceOperation.Plus: return left + right; case DiceOperation.Minus: return left - right; case DiceOperation.Divide: return !right.EqualsZero() ? left / right : 0; case DiceOperation.Multiply: return left * right; case DiceOperation.EachPlus: return left + (leftRollCount * right); case DiceOperation.EachMinus: return left - (leftRollCount * right); default: throw new InvalidOperationException("Unknown dice operation."); } }