Example #1
0
        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`.
        }
 public void IntervalDie50T100ShouldBeValidlySerialized()
 {
     deserializedR50t100 = (Die)dieSerializer.ReadObject(serializedR50t100);
     serializedR50t100.Close();
     Assert.AreEqual(r50t100.Maximum, deserializedR50t100.Maximum, "Serialized die maximum is wrong");
     Assert.AreEqual(r50t100.Minimum, deserializedR50t100.Minimum, "Serialized die minimum is wrong");
     Assert.AreEqual(r50t100.ToString(), deserializedR50t100.ToString(), "Serialized die repr is wrong");
 }
Example #3
0
        /// <summary> Converts the string representation of a die to the actual die. </summary>
        /// <param name="representation">A string that contains a die to parse.</param>
        /// <returns> Parsed die. </returns>
        /// <exception cref="System.ArgumentException"> String is too short for a die.
        /// or
        /// Die face count is less than 1.
        /// or
        /// String is too short.
        /// or
        /// Interval minimum can't be greater than maximum.
        /// or
        /// String represents unknown die type.
        /// </exception>
        /// <exception cref="FormatException">Interval lacks a delimiter ','.</exception>
        public static Die Parse(string representation)
        {
            Contract.Ensures(Contract.Result<Die>() != null);

            Die result = null;
            if (!String.IsNullOrWhiteSpace(representation)) {
                string clean = representation.Trim();
                // It could be either a die or an interval, lets check for both:
                if (clean.StartsWith("d")) {    // die, "d[x]"
                    if (clean.Length < 2) { throw new ArgumentException("String is too short.", "representation"); }

                    int faces = Convert.ToInt32(clean.Substring(1), CultureInfo.InvariantCulture);
                    if (faces < 1) { throw new ArgumentException("Die face count is less than 1.", "representation"); }
                    result = new Die(faces);
                }
                else if (clean.StartsWith("[")) {   // interval, one of "r[x, y]", "r[-x, y]", "r[-x, -y]"
                    if (clean.Length < 5) { throw new ArgumentException("String is too short.", "representation"); }

                    int delimiter = clean.IndexOf(','); // Find interval delimiter.
                    if (delimiter > -1) {
                        // Parse interval minimum and maximum:
                        const int minStart = 1;
                        int maxStart = delimiter + 1;
                        int min = Convert.ToInt32(clean.Substring(minStart, delimiter - minStart).Trim(),
                            CultureInfo.InvariantCulture);
                        int max = Convert.ToInt32(clean.Substring(maxStart, clean.Length - 1 - maxStart).Trim(),
                            CultureInfo.InvariantCulture);
                        if (min > max) {
                            throw new ArgumentException("Interval minimum is greater than maximum.", "representation");
                        }

                        result = new Die(min, max);
                    }
                    else { throw new FormatException("Interval lacks a delimiter ','."); }
                }
                else { throw new ArgumentException("String represents unknown die type."); }
            }

            return result;
        }
 public void CreatedR50T100()
 {
     r50t100 = new Die(50, 100);
 }
Example #5
0
 private static IEnumerable<double> PropagateLuckyRolls(IEnumerable<double> rolls)
 {
     var d10 = new Die(10);  // Don't allocate a die for each recursive call in real code :)
     foreach (var roll in rolls) {
         yield return roll;
         if (roll == 9 || roll == 10) {
             foreach (double nextRoll in PropagateLuckyRolls(d10.Roll(1))) {
                 yield return nextRoll;
             }
         }
     }
 }
Example #6
0
        public void TrailingLuckyTens()
        {
            // With helper method:
            var rolls = Rolls.SpawnContinuously(Dice.D10.Roll(2), roll => roll == 9 || roll == 10, () => Dice.D10.Roll(1));

            // Manual way would be:
            var d10 = new Die(10);
            rolls = PropagateLuckyRolls(d10.Roll(2));
        }
Example #7
0
 /// <summary> Converts the string representation of a die to the actual die. 
 /// A return value indicates whether the conversion succeeded or failed. </summary>
 /// <param name="representation"> A string that contains a die to parse. </param>
 /// <param name="die"> When this method returns, contains the parsed die equivalent to the given string, if the
 /// conversion succeeded, or null if the conversion failed. This parameter is passed uninitialized. </param>
 /// <returns>true if string was converted successfully; otherwise, false.</returns>
 public static bool TryParse(string representation, out Die die)
 {
     // TODO: That's not a good style, better to do proper format validation someday.
     try {
         die = Parse(representation);
         return die != null;
     }
     catch {
         die = null;
         return false;
     }
 }
 public void IntervalStringParsedIntoADie()
 {
     rm100tm10 = Die.Parse(rm100tm10repr);
 }
 public void CreatedD12()
 {
     d12 = new Die(12);
 }