/// <summary>Initializes a new weighted die with known weights.</summary> /// <param name="rnd"><c>Random</c> object to be used when rolling the die.</param> /// <param name="weights">Pre-calculated weights of the sides of the die. Total of weights must add up to 1.0.</param> public WeightedDie(IRandomizable rnd, params double[] weights) : base(rnd, weights.Length) { decimal total = 0M; decimal[] decWeights = new decimal[weights.Length]; for (int i = 0; i < weights.Length; i++) { decWeights[i] = Convert.ToDecimal(weights[i]); } var smallest = decWeights[0]; int[] normalizedWeights = new int[decWeights.Length]; foreach (var w in decWeights) { smallest = w < smallest ? w : smallest; total += w; } if (total != 1.0M) { throw new NDiceException($"Weights must add up to 1.0. Current sum: {total}"); } var multiplier = 1 / smallest; for (int i = 0; i < decWeights.Length; i++) { normalizedWeights[i] = (int)(decWeights[i] * multiplier); } Weight = normalizedWeights; }
/// <summary>Initializes a new weighted die with the specified number of sides. Default is six.</summary> /// <param name="rnd"><c>Random</c> object to be used when rolling the die.</param> /// <param name="sides">Number of sides on the die.</param> public WeightedDie(IRandomizable rnd, int sides = 6) : base(rnd, sides) { Weight = new int[Sides]; for (int i = 0; i < Sides; i++) { Weight[i] = 1; } }
public void RollInRange(IRandomizable rnd) { var die = new Die(rnd, 10); for (int i = 0; i < 50; i++) { Assert.InRange(die.Roll(), 0, 10); } }
/// <summary> /// This allows overrideable behavior that can replace or extend the basic behavior, /// which is to call Randomize on any public properties that are listed as randomizeable. /// This does nothing to normal properties or non public members and needs to be overriden /// to provide the special case functionality for sub-classes. /// </summary> /// <param name="generator">The random number generator to be used during randomization.</param> protected virtual void OnRandomize(Random generator) { Type original = GetType(); PropertyInfo[] originalProperties = original.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo originalProperty in originalProperties) { object prop = originalProperty.GetValue(this, null); IRandomizable rnd = prop as IRandomizable; rnd?.Randomize(generator); } }
/// <summary>Initializes a new weighted die with known weights.</summary> /// <param name="rnd"><c>Random</c> object to be used when rolling the die.</param> /// <param name="weights">Pre-calculated weights of the sides of the die.</param> public WeightedDie(IRandomizable rnd, params int[] weights) : base(rnd, weights.Length) => Weight = weights;
/// <summary>Initializes a new fair die with the specified number of sides. Default is six.</summary> /// <param name="rnd"><c>Random</c> object to be used when rolling the die.</param> /// <param name="sides">Number of sides on the die.</param> public Die(IRandomizable rnd, int sides = 6) { _rnd = rnd; Sides = sides; }
/// <summary>Initializes a new gambler's die with known weights. Number of sides is the <c>Length</c> of the weights.</summary> /// <param name="rnd"><c>Random</c> object to be used when rolling the die.</param> /// <param name="weights">Pre-calculated weights of the sides of the die. Total of weights must add up to 1.0.</param> public GamblersDie(IRandomizable rnd, params double[] weights) : base(rnd, weights) { }
/// <summary>Initializes a new gambler's die with the specified number of sides. Default is six.</summary> /// <param name="rnd"><c>Random</c> object to be used when rolling the die.</param> /// <param name="sides">Number of sides on the die.</param> public GamblersDie(IRandomizable rnd, int sides = 6) : base(rnd, sides) { }
/// <summary>Initializes a new tapper's die with known weights. Number of sides is the <c>Length</c> of the weights.</summary> /// <param name="rnd"><c>Random</c> object to be used when rolling the die.</param> /// <param name="weights">Pre-calculated weights of the sides of the die. Total of weights must add up to 1.0.</param> public TappersDie(IRandomizable rnd, params double[] weights) : this(rnd, false, weights) { }
/// <summary>Initializes a new tapper's die with known weights. Number of sides is the <c>Length</c> of the weights.</summary> /// <param name="rnd"><c>Random</c> object to be used when rolling the die.</param> /// <param name="tapped">Whether the die is tapped (weighted) or not (unweighted). Default is false.</param> /// <param name="weights">Pre-calculated weights of the sides of the die. Total of weights must add up to 1.0.</param> public TappersDie(IRandomizable rnd, bool tapped, params double[] weights) : base(rnd, weights) { Tapped = tapped; _die = new Die(_rnd, weights.Length); }
/// <summary>Initializes a new tapper's die with the specified number of sides. Default is six.</summary> /// <param name="rnd"><c>Random</c> object to be used when rolling the die.</param> /// <param name="tapped">Whether the die is tapped (weighted) or not (unweighted). Default is false.</param> /// <param name="sides">Size of the die. Default is six.</param> public TappersDie(IRandomizable rnd, bool tapped, int sides = 6) : base(rnd, sides) { Tapped = tapped; _die = new Die(_rnd, sides); }
/// <summary>Initializes a new tapper's die with the specified number of sides. Default is six.</summary> /// <param name="rnd"><c>Random</c> object to be used when rolling the die.</param> public TappersDie(IRandomizable rnd) : base(rnd) { Tapped = false; _die = new Die(_rnd, 6); }
/// <summary>Initializes a new tapper's die with the specified number of sides.</summary> /// <param name="rnd"><c>Random</c> object to be used when rolling the die.</param> /// <param name="sides">Size of the die.</param> public TappersDie(IRandomizable rnd, int sides) : this(rnd, false, sides) { }