Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections.Generic;
- using System.Linq;
- using MonKey.Extensions;
- using QFSW.QC;
- using Sirenix.Utilities;
- using UnityEngine;
- using Random = UnityEngine.Random;
- namespace Overfors.Dices
- {
- public static class Dice
- {
- public static int Roll(int sides, bool debug = false)
- {
- int result = Random.Range(1, sides + 1);
- //if(debug) Debug.LogFormat("d{0} => {1}", sides, result);
- return result;
- }
- public static int Roll(int sides, DiceMod modifier, int modParameter)
- {
- int result = 0;
- switch (modifier)
- {
- case DiceMod.Advantage:
- result = Advantage(1, sides);
- break;
- case DiceMod.Disadvantage:
- result = Disadvantage(1, sides);
- break;
- case DiceMod.KeepHighest:
- result = KeepHighest(1, sides, modParameter);
- break;
- case DiceMod.KeepLowest:
- result = KeepLowest(1, sides, modParameter);
- break;
- case DiceMod.BaseAll:
- result = BaseAll(1, sides, modParameter);
- break;
- case DiceMod.BaseEach:
- result = BaseEach(1, sides, modParameter);
- break;
- }
- return result;
- }
- public static int Roll(int nbr, int sides, bool debug = false)
- {
- int result = 0;
- for (int i = 0; i < nbr; i++)
- {
- result += Roll(sides);
- }
- //if(debug) Debug.LogFormat("{0}d{1} => {2}", nbr, sides, result);
- return result;
- }
- public static int Roll(int nbr, int sides, DiceMod modifier, int modParameter = 0)
- {
- int result = 0;
- switch (modifier)
- {
- case DiceMod.Advantage:
- result = Advantage(nbr, sides);
- break;
- case DiceMod.Disadvantage:
- result = Disadvantage(nbr, sides);
- break;
- case DiceMod.KeepHighest:
- result = KeepHighest(nbr, sides, modParameter);
- break;
- case DiceMod.KeepLowest:
- result = KeepLowest(nbr, sides, modParameter);
- break;
- case DiceMod.BaseAll:
- result = BaseAll(nbr, sides, modParameter);
- break;
- case DiceMod.BaseEach:
- result = BaseEach(nbr, sides, modParameter);
- break;
- }
- return result;
- }
- private static int Advantage(int nbr, int sides)
- {
- (int first, int second) results = (Roll(nbr, sides), Roll(nbr, sides));
- int result = results.first < results.second ? results.second : results.first;
- string message = string.Format("Advantage {0}d{1} =>\n", nbr, sides);
- //Debug.LogFormat(message + "1st {0}d{1}: {2} | 2nd {0}d{1}: {3} | Result: {4}", nbr, sides, results.first, results.second, result);
- return result;
- }
- private static int Disadvantage(int nbr, int sides)
- {
- (int first, int second) results = (Roll(nbr, sides), Roll(nbr, sides));
- int result = results.first < results.second ? results.first : results.second;
- string message = string.Format("Disadvantage {0}d{1} =>\n", nbr, sides);
- //Debug.LogFormat(message + "1st {0}d{1}: {2} | 2nd {0}d{1}: {3} | Result: {4}", nbr, sides, results.first, results.second, result);
- return result;
- }
- private static int KeepHighest(int nbr, int sides, int modParameter)
- {
- if (modParameter > nbr)
- {
- //Debug.Log("Asked to keep more dice than there is. If you use KeepHighest or KeepLowest, you need to throw at least as much dices as you keep.");
- return 0;
- }
- int[] results = new int[nbr];
- int result = 0;
- for (int i = 0; i < results.Length; i++)
- {
- results[i] = Roll(sides);
- }
- results.Sort();
- results = results.Reverse().ToArray();
- string message = string.Format("KeepHighest {0}d{1} keep {2} =>\n", nbr, sides, modParameter);
- for (int i = 0; i < modParameter; i++)
- {
- result += results[i];
- message += string.Format("{0}{1} Best d{2}: {3}\n", i+1, NbrSuffixe(i+1), sides, results[i]);
- }
- message += string.Format("Result: {0}", result);
- //Debug.Log(message);
- return result;
- }
- private static int KeepLowest(int nbr, int sides, int modParameter)
- {
- if (modParameter > nbr)
- {
- Debug.Log("Asked to keep more dice than there is. If you use KeepHighest or KeepLowest, you need to throw at least as much dices as you keep.");
- return 0;
- }
- int[] results = new int[nbr];
- int result = 0;
- for (int i = 0; i < results.Length; i++)
- {
- results[i] = Roll(sides);
- }
- results.Sort();
- string message = string.Format("KeepLowest {0}d{1} keep {2} =>\n", nbr, sides, modParameter);
- for (int i = 0; i < modParameter; i++)
- {
- result += results[i];
- message += string.Format("{0}{1} Worst d{2}: {3}\n", i+1, NbrSuffixe(i+1), sides, results[i]);
- }
- message += string.Format("Result: {0}", result);
- //Debug.Log(message);
- return result;
- }
- private static int BaseAll(int nbr, int sides, int modParameter)
- {
- int rolls = Roll(nbr, sides);
- int result = rolls < modParameter ? modParameter : rolls;
- //Debug.LogFormat("BaseAll {0}d{1} =>\nBase: {2} | Rolls: {3} | Result: {4}", nbr, sides, modParameter, rolls, result);
- return result;
- }
- private static int BaseEach(int nbr, int sides, int modParameter)
- {
- int result = 0;
- string message = string.Format("BaseEach {0}d{1} =>\n", nbr, sides);
- for (int i = 0; i < nbr; i++)
- {
- int roll = Roll(sides);
- int rollResult = roll < modParameter ? modParameter : roll;
- message += string.Format("{0}{1} d{2} => Base: {3} | Roll: {4} | Result: {5}\n", i+1, NbrSuffixe(i+1), sides, modParameter, roll, rollResult);
- result += rollResult;
- }
- //Debug.LogFormat(message + "Final Result for {0}d{1}: {2}", nbr, sides, result);
- return result;
- }
- public static int StringToRoll(string diceString, bool debug = false)
- {
- //If doesn't contain d, it's not a dice roll
- if (!diceString.Contains('d') && !diceString.Contains('D')) { WrongSyntax();
- return 0;
- }
- //Turn d6 into 1d6
- if (diceString[0] == 'd') diceString = diceString.Insert(0, "1");
- //Split in: Dice, Modifier, Modifier Amount
- List<string> split = diceString.Split('[', ':', ']').ToList();
- string dice = split[0];
- //Parse nbr and sides
- int nbr = int.Parse(dice.Split('d', 'D')[0]);
- int sides = int.Parse(dice.Split('d', 'D')[1]);
- //Remove empty splits
- for (int i = 0; i < split.Count; i++)
- {
- if(split[i] == "") {
- split.RemoveAt(i);
- i--;
- }
- }
- //Debug every split
- /*
- foreach (var line in _split)
- {
- Debug.Log(line);
- }*/
- //If more than 1 split, means there's a modifier
- if (split.Count > 1)
- {
- //If more than 2 splits, means the modifier has a value
- if (split.Count > 2) return Roll(nbr, sides, StringToMod(split[1]), int.Parse(split[2]));
- return Roll(nbr, sides, StringToMod(split[1]));
- }
- return Roll(nbr, sides, debug);
- void WrongSyntax(string[] line = null)
- {
- string message = "";
- if (line != null)
- {
- for (int i = 0; i < line.Length; i++)
- {
- message += string.Format("({0})", line[i]);
- }
- }
- Debug.LogFormat("Syntax isn't parseable into a dice. Syntax:\n" +
- "Roll 1 dice: dX | Note: d isn't case sensitive\n" +
- "Roll N dice: NdX | Note: can roll 1 dice\n" +
- "Roll N dice with mod: NdX[mod:modValue] | Note: modValue is optional\n" +
- "N => number of dice rolls | X number of sides\n" +
- "You typed : {0}", message);
- }
- DiceMod StringToMod(string modString)
- {
- switch (@modString)
- {
- case "KeepHigh":
- case "k":
- case "K":
- case "kh":
- case "Kh":
- return DiceMod.KeepHighest;
- case "KeepLow":
- case "kl":
- case "Kl":
- return DiceMod.KeepLowest;
- case "Base":
- case "BaseAll":
- case "b":
- case "B":
- case "ba":
- case "Ba":
- case "<":
- return DiceMod.BaseAll;
- case "BaseEach":
- case "be":
- case "Be":
- case "<<":
- return DiceMod.BaseEach;
- case "Advantage":
- case "adv":
- case "Adv":
- case "a":
- case "a²":
- case "best²":
- return DiceMod.Advantage;
- case "Disadvantage":
- case "dis":
- case "Dis":
- case "d":
- case "d²":
- case "worst²":
- return DiceMod.Disadvantage;
- }//
- return DiceMod.None;
- }
- }
- private static float StringToFloat(string value)
- {
- if (value.Contains('d') || value.Contains('D')) return StringToRoll(value);
- else return float.Parse(value);
- }
- private static readonly Dictionary<char, Operation> OperationDico = new Dictionary<char, Operation>()
- {
- {'+', Operation.Add},
- {'-', Operation.Subtract},
- {'*', Operation.Multiply},
- {'x', Operation.Multiply},
- {'/', Operation.Divide},
- {'^', Operation.Power}
- };
- [Command("roll", "Roll a macro of dices. Ex : 1d6 * 3d5")]
- public static string StringRollCommand(string macro)
- {
- StringToOperation(macro, out string message);
- return message;
- }
- public static float StringToOperation(string macro, out string description)
- {
- description = "Operation Failed";
- //Check if it is an operation or just a simple roll
- #region isOperation?
- List<char> opChars = OperationDico.Keys.ToList();
- bool isOperation = false;
- for (int i = 0; i < opChars.Count; i++)
- {
- if (macro.Contains(opChars[i])) isOperation = true;
- }
- if (!isOperation) return StringToRoll(macro, true);
- #endregion
- //Remove every space
- string operation = macro.Replace(" ", "");
- //Parenthesis work in progress
- /*
- List<string> splits = operation.Split('(', ')').ToList();
- if (splits.Count == 1 && splits[0].IsNullOrEmpty()) return 0;
- for (int i = 0; i < splits.Count; i++)
- {
- if (splits[i].IsNullOrEmpty())
- {
- splits.RemoveAt(i);
- i--;
- }
- }
- Debug.Log(splits.Count);*/
- Dictionary<int, Operation> splitIndexes = new Dictionary<int, Operation>();
- //Split at every operation and memorize operation
- for (int i = 0; i < operation.Length; i++)
- {
- foreach (var opChar in OperationDico.Keys)
- {
- if (operation[i] == opChar)
- {
- splitIndexes.Add(i, OperationDico[opChar]);
- operation = operation.Remove(i, 1);
- i--;
- break;
- }
- }
- }
- var stringValues = operation.SplitAt(splitIndexes.Keys.ToArray()).ToList();
- List<Operation> operations = splitIndexes.Values.ToList();
- List<float> values = new List<float>();
- //Convert strings to floats
- for (int i = 0; i < stringValues.Count; i++)
- {
- values.Add(StringToFloat(stringValues[i]));
- }
- description = "";
- for (int i = 0; i < values.Count; i++)
- {
- description += $" {values[i]}";
- if (values[i].ToString() != stringValues[i]) description += $"({stringValues[i]})";
- if(i+1 != values.Count) description += $" {operationSymbols[operations[i]]} ";
- }
- //Priority one operations: Multiply, Divide, Power
- for (int i = 0; i < operations.Count; i++)
- {
- if(operations[i] == Operation.Add || operations[i] == Operation.Subtract) continue;
- values[i] = ValuesOperation(values[i], values[i + 1], operations[i]);
- values.RemoveAt(i+1);
- operations.RemoveAt(i);
- i--;
- }
- //Priority two operations: Add, Substract
- for (int i = 0; i < operations.Count; i++)
- {
- values[i] = ValuesOperation(values[i], values[i + 1], operations[i]);
- values.RemoveAt(i+1);
- operations.RemoveAt(i);
- i--;
- }
- //Debug.LogFormat("{0} => {1}", macro, values[0]);
- return values[0];
- }
- public static Dictionary<Operation, string> operationSymbols = new Dictionary<Operation, string>()
- {
- {Operation.Add, "+"},
- {Operation.Subtract, "-"},
- {Operation.Multiply, "*"},
- {Operation.Divide, "/"},
- {Operation.Power, "^"},
- };
- private static float ValuesOperation(float valueOne, float valueTwo, Operation operation)
- {
- switch (operation)
- {
- case Operation.Add:
- return valueOne + valueTwo;
- case Operation.Subtract:
- return valueOne - valueTwo;
- case Operation.Multiply:
- return valueOne * valueTwo;
- case Operation.Divide:
- return valueOne / valueTwo;
- case Operation.Power:
- return Mathf.Pow(valueOne, valueTwo);
- }
- Debug.LogError("Operation not Added");
- return 0;
- }
- public static string NbrSuffixe(int nbr)
- {
- Dictionary<int, string> suffixes = new Dictionary<int, string>()
- {
- {1, "st"},
- {2, "nd"},
- {3, "rd"}
- };
- if (nbr < 4) return suffixes[nbr];
- else return "th";
- }
- }
- public enum DiceMod
- {
- None,
- KeepHighest,
- KeepLowest,
- BaseAll,
- BaseEach,
- Advantage,
- Disadvantage
- }
- public enum Operation{
- Add,
- Subtract,
- Multiply,
- Divide,
- Power
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement