public void BurningHands() { // Let's create a smart sorcerer first: var sorcerer = new Character { Int = 16, BurningHandsSpellLevel = 1 }; // Then let's create a provider for a modifier derived from the sorcerer's Intelligence: var intMod = new IntModProvider { Character = sorcerer }; // Create a provider for a spell damage dice count, which depends on the sorcerer's current spell level. var spellDiceCount = new BurningHandsDiceCountProvider { Character = sorcerer }; // Merge these into a chain: DiceChain damageDice = Dice.Take(spellDiceCount).D(8).EachPlus(intMod); // Let's burn some poor fella: double damage = damageDice.Roll(); // Let's say we want to display the spell damage, so check the dice chain stats: Trace.WriteLine("Damage: " + damageDice.Minimum + " to " + damageDice.Maximum); // Outputs 'Damage: 4 to 11', which is equal to '1d8+3', looks good. // What if sorcerer gains two levels of proficiency in the spell? sorcerer.BurningHandsSpellLevel += 2; Console.WriteLine("Damage: " + damageDice.Minimum + " to " + damageDice.Maximum); // Outputs 'Damage: 8 to 22', which is equal to '2d8(+3)', once again looks good. // Parens mean that 3 is apllied to each die separately instead of affecting dice sum. // Now let's say when you miss an enemy with burning hands, you still can deal some damage. // In this case damage dealt to the target equals to sum of each damage die that rolled its maximum result. // Normally you don't want to deal with individual roll values when using dice chain, // but there is a method just in case: List <DiceChainRollStep> rollParts; // Normal hit damage is returned by dice chain as usual: damage = damageDice.RollStepByStep(out rollParts); // Damage on a miss is calculated as a sum of each damage die that rolled its maximum result. // Looking at dice chain 'Xd8+Y' we can see that damage dice are rolled in the first (leftmost) step. double missedDamage = rollParts[0].Rolls.Where(roll => roll == Dice.D8.Maximum).Sum(); // For the sake of completeness, there is a way of achieving the same thing without a dice chain. // That way we have to do all calculations manually. // Let's bundle D8 with spell damage dice count: var rawSpellDamage = new SeveralDice(Dice.D8, spellDiceCount); // Make a damage roll, rolling each die separately: var rawRolls = rawSpellDamage.RollSeparately().ToArray(); // .ToArray() is important here. Otherwise different roll values would be generated on each enumeration. // Damage on a miss: missedDamage = rawRolls.Where(roll => roll == Dice.D8.Maximum).Sum(); // Damage on a hit: damage = rawRolls.Select(roll => roll + intMod.Roll()).Sum(); }
/// <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; }
public void EntryLevel() { // Roll a standard cubic die one time: var d6 = new Die(6); var roll = d6.Roll(); // Roll an interval die from 10 to 20 four times: var interval10t20 = new Die(10, 20); roll = interval10t20.Roll(4).Sum(); // There is also a fixed die, which always returns the same value. // It's useful when something expects IDie as value provider and you want to pass a constant value: var fixed50 = new FixedDie(50); // Roll two d10's: var d2d10 = new SeveralDice(Dice.D10, 2); roll = d2d10.Roll(); // Compared to simple Dice.D10.Roll(2), SeveralDice provides statistics and serialization Console.WriteLine("Possible roll value range: " + d2d10.Minimum + " to " + d2d10.Maximum); // Roll a d4d10 / d2 * 3: var d4d10divD2mul3 = Dice.Take(Dice.D4).D(10).Divide(Dice.D2).Multiply(3); // This is a dice chain. // Math operations in dice chains are always executed from left to right, so this chain translates to: // take a 1-4 of d10 dice and divide their roll value by 2 with 50 % chance, then multiply resulting roll value by 3. roll = d4d10divD2mul3.Roll(); // Dice chains also provide statistics and serialization. // This chain was created via fluent interface, but it is also possible to create such chain in a more explicit way: d4d10divD2mul3 = new DiceChain( new SeveralDice(new Die(10), new Die(4))) // d4d10 .Append(DiceOperation.Divide, new SeveralDice(2)) // / 2 .Append(DiceOperation.Multiply, new SeveralDice(3)); // * 3 // Oh, and where is a random number generator? Built-in dice get it from thread-local `Dice.Random`. }
/// <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); }