public static MinMax CalculateDiceRoll(DiceRoll diceRoll) { // check if dice roll is too large foreach (var die in diceRoll.Dice) { if (Math.Pow(die.DiceType, die.TotalDiceAmount) > int.MaxValue) // basically >2.5billion { Printer.PrintError("Dice roll too large to calculate in a decent amount of time"); return(new MinMax(0, 0, 0)); } } var calcs = CalculateMinAndMaxValues(diceRoll); var min = calcs.First().Key; var max = calcs.Last().Key; float tempAvg = 0f; foreach (var item in calcs) { tempAvg += item.Key * item.Value.Percentage; } var avg = (float)Math.Round(tempAvg / 100, 3); // round percentages to three decimals after finding average foreach (var item in calcs) { item.Value.Percentage = (float)Math.Round(item.Value.Percentage, 3); } return(new MinMax(min, avg, max, calcs)); }
public static int RollDice(DiceRoll diceRoll, int?seed = null) { var rolls = GetDiceRolls(diceRoll.Dice, seed); var rollBeforeMods = AddRolls(rolls); var roll = AddModifiers(rollBeforeMods, diceRoll.Modifiers); return(roll); }
public static void Print(string line, DiceRoll result) { string separator = new string('-', line.Length); Console.WriteLine($"\n {line}\n {separator}"); var die = result.Dice.First(); string lineToPrint = $" {die.TotalDiceAmount}d{die.DiceType}"; var mod = result.Modifiers.First(); if (mod.Number != 0) { lineToPrint += $" {mod.Operation} {mod.Number}"; } lineToPrint += "\n"; Console.WriteLine(lineToPrint); }
private static Dictionary <int, Calculations> CalculateMinAndMaxValues(DiceRoll diceRoll) { var summedMatrix = new List <int>(); foreach (var die in diceRoll.Dice) { var dice = new List <int>(); for (int i = 0; i < die.TotalDiceAmount; i++) { dice.Add(die.DiceType); } int rows = (int)Math.Pow(die.DiceType, die.TotalDiceAmount); var partialMatrix = new List <int> [rows]; var diceIndex = 0; var rowIndex = 0; CalculateRecursively(dice, ref diceIndex, partialMatrix, ref rowIndex, colList: new List <int>()); // TODO: merge with DiceRoller.GetDiceRolls if (die.KeepAmount != 0 && die.KeepAmount < die.TotalDiceAmount) { foreach (var row in partialMatrix) { row.Sort(); var amtToRemove = die.TotalDiceAmount - die.KeepAmount; if (die.KeepHigh) { row.RemoveRange(0, amtToRemove); } else { row.RemoveRange(die.KeepAmount, amtToRemove); } } } // add together each row of the partial matrix, // turning it negative if the die operation is subtract var dieSumMatrix = partialMatrix.Select(row => { var sum = 0; foreach (var num in row) { sum += num; } if (die.Operation == Operation.Subtract) { sum *= -1; } return(sum); }); if (summedMatrix.Count == 0) { summedMatrix.AddRange(dieSumMatrix); } else { var tempSummedMatrix = new List <int>(); foreach (var item in summedMatrix) { foreach (var item2 in dieSumMatrix) { tempSummedMatrix.Add(item + item2); } } summedMatrix = tempSummedMatrix; } } var calcs = new Dictionary <int, Calculations>(); // calculate frequency of each dice num foreach (var num in summedMatrix) { var key = (int)AddModifiers(num, diceRoll.Modifiers); if (calcs.ContainsKey(key)) { calcs[key].Frequency++; } else { calcs.Add(key, new Calculations(1, 0)); } } // put dice nums in order from lowest to highest calcs = calcs.OrderBy(kvp => kvp.Key).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); // calculate percentages var totalNums = calcs.Values.Sum(v => v.Frequency); foreach (var calc in calcs) { var pct = (calc.Value.Frequency * 100f) / totalNums; calc.Value.Percentage = pct; } return(calcs); }