public Player CreateNewPlayer(IDieScoreCalculator dieScoreCalculator, IDieRoller dieRoller, IUserInterface userInterface, string playerName) { var gameState = new PlayerGameState(); var playerTurnProcessor = new PlayerTurnProcessor(dieScoreCalculator, dieRoller, userInterface, gameState); return(new Player(gameState, playerTurnProcessor, playerName)); }
public PlayerTurnProcessor(IDieScoreCalculator dieScoreCalculator, IDieRoller dieRoller, IUserInterface userInterface, PlayerGameState playerGameState) { DieScoreCalculator = dieScoreCalculator; DieRoller = dieRoller; PlayerGameState = playerGameState; UserInterface = userInterface; }
/// <summary> /// Gets the die roller based on specified type. /// </summary> /// <param name="type">Type string</param> /// <param name="tracker">Die roll tracker to use</param> /// <returns>Instance of die roller, or null if none found.</returns> public IDieRoller GetDieRoller(string type, IDieRollTracker tracker = null) { IDieRoller roller = null; if (type == typeof(ConstantDieRoller).ToString()) { roller = new ConstantDieRoller(); } else if (type == typeof(RandomDieRoller).ToString()) { roller = new RandomDieRoller(tracker); } else if (type == typeof(SecureRandomDieRoller).ToString()) { roller = new SecureRandomDieRoller(tracker); } else if (type == typeof(MathNetDieRoller).ToString()) { roller = new MathNetDieRoller(tracker); } else { throw new ArgumentOutOfRangeException(nameof(type)); } return(roller); }
/// <summary> /// Initializes a new instance of the <see cref="DiceRollerViewModel"/> class. /// </summary> public DiceRollerViewModel() { AppServices services = AppServices.Instance; this.dice = services.DiceService; string rollerType = services.AppSettingsService.CurrentDieRollerType; this.dieRoller = services.DieRollerFactory.GetDieRoller(rollerType, services.DiceFrequencyTracker); }
/// <inheritdoc/> public IReadOnlyList <TermResult> CalculateResults(IDieRoller dieRoller) { List <TermResult> results = new List <TermResult> { new TermResult { Scalar = 1, Value = this.constant, Type = this.GetType().Name } }; return(results.AsReadOnly()); }
/// <summary> /// Parses the specified dice expression and converts it into a /// Dice instance to perform oprations on. /// </summary> /// <param name="expression">String expression to parse</param> /// <param name="config">Dice config to tell whether this result will be bounded or unbounded</param> /// <param name="dieRoller">Die roller to use</param> /// <returns>Dice result</returns> public DiceResult Parse(string expression, DiceConfiguration config, IDieRoller dieRoller) { this.config = config; // first clean up expression expression = this.CorrectExpression(expression); // then break the expression down into tokens. List <string> tokens = this.Tokenize(expression); // finally parse and evaluate the expression tokens return(this.ParseLogic(expression, tokens, dieRoller)); }
public IEnumerable <TermResult> GetResults(IDieRoller dieRoller) { IEnumerable <TermResult> results = from i in Enumerable.Range(0, Multiplicity) select new TermResult { Scalar = Scalar, Value = dieRoller.RollDie(Sides), Type = "d" + Sides }; return(results.OrderByDescending(d => d.Value).Take(Choose)); }
/// <inheritdoc/> public IReadOnlyList <TermResult> CalculateResults(IDieRoller dieRoller) { // ensure we have a die roller. if (dieRoller == null) { throw new ArgumentNullException(nameof(dieRoller)); } List <TermResult> results = new List <TermResult>(); string termType = string.Format(this.FormatResultType, this.GetType().Name, this.sides); int rerolls = 0; // go through the number of dice and roll each one, saving them as term results. for (int i = 0; i < this.numberDice + rerolls; i++) { int value = this.RollTerm(dieRoller, this.sides); if (this.exploding != null && value >= this.exploding) { if (rerolls > MaxRerollsAllowed) { throw new OverflowException("Rolling dice past the maximum allowed number of rerolls."); } rerolls++; } results.Add(new TermResult { Scalar = this.scalar, Value = value, Type = termType }); } // order by their value (high to low) and only take the amount specified in choose. int tempChoose = this.choose ?? results.Count; var ordered = (tempChoose > 0) ? results.OrderByDescending(d => d.Value).ToList() : results.OrderBy(d => d.Value).ToList(); for (int i = Math.Abs(tempChoose); i < ordered.Count(); i++) { ordered[i].AppliesToResultCalculation = false; } return(results); }
/// <inheritdoc/> protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); // when focus comes back to this page, then reset any app settings that may have // changed, if (this.appSettings != null) { if (this.ViewToggleButton.IsChecked != this.appSettings.UseDiceExpressionEditor) { // if the dice roll view has changed since last view, then reset the UI. this.ViewToggleButton.IsChecked = this.appSettings.UseDiceExpressionEditor; this.ViewToggleButton_Click(this, null); } if (this.appSettings.ClearResultsList == true) { // if user wanted results list cleared, then clear the list and reset the setting. this.DiceRollResults.Clear(); this.appSettings.ClearResultsList = false; } // set the dice configuration. this.diceService.Configuration.DefaultDieSides = this.appSettings.DefaultDiceSides; this.diceService.Configuration.HasBoundedResult = !this.appSettings.UseUnboundedResults; // get the current die roller to use. this.dieRoller = this.dieRollerFactory.GetDieRoller( this.appSettings.CurrentDieRollerType, this.diceFrequencyTracker); } // setup a time to save die frequency data every 5 minutes. DispatcherTimer timer = new DispatcherTimer(); timer.Tick += this.Timer_Tick; timer.Interval = new TimeSpan(0, 5, 0); timer.Start(); }
/// <summary> /// Parses the specified list of tokens with appropriate logic to convert /// it into a Dice instance to evaluate oprations on. /// </summary> /// <param name="expression">dice expression rolled</param> /// <param name="tokens">String expression to parse</param> /// <param name="dieRoller">Die roller to use</param> /// <returns>Dice result</returns> private DiceResult ParseLogic(string expression, List <string> tokens, IDieRoller dieRoller) { List <TermResult> results = new List <TermResult>(); while (tokens.IndexOf(this.GroupStartOperator) != -1) { // getting data between grouping symbols: "(" and ")" int open = tokens.LastIndexOf(this.GroupStartOperator); int close = tokens.IndexOf(this.GroupEndOperator, open); if (open >= close) { throw new ArithmeticException("No matching close-open parenthesis."); } // get a subexpression list for elements within the grouping symbols List <string> subExpression = new List <string>(); for (var i = open + 1; i < close; i++) { subExpression.Add(tokens[i]); } // run the operations on the subexpression int subValue = this.HandleBasicOperation(results, subExpression, dieRoller); // when subexpression calculation is done, replace the grouping start symbol // and removing the tokens for the subexpression from the token list tokens[open] = subValue.ToString(); tokens.RemoveRange(open + 1, close - open); } // at this point, we should have replaced all groups in the expression // with the appropriate values, so need to calculate last simple expression int value = this.HandleBasicOperation(results, tokens, dieRoller); // now return the dice result from the final value and TermResults list return(new DiceResult(expression, value, results, dieRoller.GetType().ToString(), this.config)); }
/// <summary> /// Performs the actual dice rolls for this term. /// </summary> /// <param name="dieRoller">IDieRoller to use</param> /// <param name="sides">Number of sides to roll</param> /// <returns>Returns rolled value.</returns> protected virtual int RollTerm(IDieRoller dieRoller, int sides) { return(dieRoller.Roll(sides)); }
public DieRollTrackerWithMathNetRollerTests() { this.roller = new MathNetDieRoller(new MersenneTwister(), this.tracker); }
/// <inheritdoc/> public DiceResult Roll(IDieRoller dieRoller) { List <TermResult> termResults = this.terms.SelectMany(t => t.CalculateResults(dieRoller)).ToList(); return(new DiceResult(this.ToString(), termResults, dieRoller.GetType().ToString(), this.Configuration)); }
/// <inheritdoc/> public DiceResult Roll(string expression, IDieRoller dieRoller) { return(this.parser.Parse(expression, this.Configuration, dieRoller)); }
public Rules(IDieRoller dieRoller) { this.dieRoller = dieRoller; }
/// <inheritdoc/> protected override int RollTerm(IDieRoller dieRoller, int sides) { return(dieRoller.Roll(sides, FudgeFactor)); }
/// <summary> /// Evaluate the term and save the value and results, and updates the token list to /// reflect the completion of the operation. /// </summary> /// <param name="results">List of term results</param> /// <param name="tokens">String expression to parse</param> /// <param name="dieRoller">Die roller to use</param> /// <param name="opPosition">Current operator position in tokens list</param> /// <param name="length">length of tokens that were affected</param> /// <param name="term">Dice term to evaluate</param> private void EvaluateDiceTerm(List <TermResult> results, List <string> tokens, IDieRoller dieRoller, int opPosition, int length, IExpressionTerm term) { IReadOnlyList <TermResult> t = term.CalculateResults(dieRoller); int value = t.Sum(r => (int)Math.Round(r.AppliesToResultCalculation ? r.Value * r.Scalar : 0)); results.AddRange(t); // put the evaluation result in the first entry and remove // the remaining processed tokens tokens[opPosition - 1] = value.ToString(); tokens.RemoveRange(opPosition, length); }
public DiceResult(IEnumerable <TermResult> results, IDieRoller rollerUsed) { RollerUsed = rollerUsed; Results = new ReadOnlyCollection <TermResult>(results.ToList()); Value = results.Sum(r => r.Value * r.Scalar); }
/// <summary> /// Handles the dice operator and its sub-expressions, and returns the result of the /// dice rolls in the results list and token value. /// </summary> /// <param name="results">List of term results</param> /// <param name="tokens">String expression to parse</param> /// <param name="op">current operator</param> /// <param name="dieRoller">Die roller to use</param> private void HandleDieOperator(List <TermResult> results, List <string> tokens, string op, IDieRoller dieRoller) { if (tokens.IndexOf("f") >= 0) { throw new FormatException("Fudge dice and regular dice cannot be used in the same expression"); } // find the previous and next numbers in the token list int opPosition = tokens.IndexOf(op); int sides = 0, length = 0; int numDice = int.Parse(tokens[opPosition - 1]); // allow default value for dice (if not digit is specified) if (opPosition + 1 < tokens.Count && char.IsDigit(tokens[opPosition + 1], 0)) { sides = int.Parse(tokens[opPosition + 1]); length += 2; } else { sides = this.config.DefaultDieSides; length++; } // look-ahead to find other dice operators (like the choose-keep/drop operators) int?choose = this.ChooseLookAhead(tokens, opPosition, numDice, ref length); int?explode = this.ExplodeLookAhead(tokens, opPosition, sides, ref length); // create a dice term based on the values DiceTerm term = new DiceTerm(numDice, sides, 1, choose, explode); // then evaluate the dice term to roll dice and get the result this.EvaluateDiceTerm(results, tokens, dieRoller, opPosition, length, term); }
/// <summary> /// Handles the fudge dice operator and its sub-expressions, and returns the result of the /// dice rolls in the results list and token value. /// </summary> /// <param name="results">List of term results</param> /// <param name="tokens">String expression to parse</param> /// <param name="op">current operator</param> /// <param name="dieRoller">Die roller to use</param> private void HandleFudgeOperator(List <TermResult> results, List <string> tokens, string op, IDieRoller dieRoller) { // find the previous and next numbers in the token list int opPosition = tokens.IndexOf(op); int numDice = int.Parse(tokens[opPosition - 1]); int length = 1; // look-ahead to find other dice operators (like the choose-keep/drop operators) int?choose = this.ChooseLookAhead(tokens, opPosition, numDice, ref length); // create a dice term based on the values IExpressionTerm term = new FudgeDiceTerm(numDice, choose); // then evaluate the dice term to roll dice and get the result this.EvaluateDiceTerm(results, tokens, dieRoller, opPosition, length, term); }
/// <summary> /// Processes through all of the operator and evaluates the tokens for a single strand /// of values. /// </summary> /// <param name="results">List of term results</param> /// <param name="tokens">String expression to parse</param> /// <param name="dieRoller">Die roller to use</param> /// <returns>value of operation total.</returns> private int HandleBasicOperation(List <TermResult> results, List <string> tokens, IDieRoller dieRoller) { if (tokens.Count == 0) { // if there's nothing in the list, just return 0 return(0); } else if (tokens.Count == 1) { // if there is only one token, then it much be a constant return(int.Parse(tokens[0])); } // loop through each operator in our operator list // operators order in the list signify their order of operations foreach (var op in this.Operators) { // loop through all of the tokens until we find the operator in the list while (tokens.IndexOf(op) != -1) { try { if (op == "d") { // if current operator is the die operator, then process // that part of the expression accordingly this.HandleDieOperator(results, tokens, op, dieRoller); } else if (op == "f") { // if current operator is the fudge die operator, then process // that part of the expression accordingly this.HandleFudgeOperator(results, tokens, op, dieRoller); } else { // otherwise, treat the operator as an arimethic operator, // and perform the correct math operation this.HandleArithmeticOperators(results, tokens, op); } } catch (Exception ex) { // if any error happens within this processing, then throw an exception throw new FormatException("Dice expression string is incorrect format.", ex); } } // if we are out of tokens, then just stop processing if (tokens.Count == 0) { break; } } if (tokens.Count == 1) { // if there is only one token left, then return it as the evaluation of this list of tokens return(int.Parse(tokens[0])); } else { // if there are left over toknes, then the parsing/evaluation failed throw new FormatException("Dice expression string is incorrect format: unexpected symbols in the string expression."); } }
public DieRollTrackerWithSecureRollerTests() { this.roller = new SecureRandomDieRoller(this.tracker); }
public BattleCalculator(IDieRoller dieRoller) { _dieRoller = dieRoller; }
public List <Player> CreateNPlayers(int n, IDieScoreCalculator dieScoreCalculator, IDieRoller dieRoller, IUserInterface userInterface) { var playerList = new List <Player>(); for (var i = 0; i < n; i++) { var playerName = string.Format("Player {0}", i + 1); playerList.Add(CreateNewPlayer(dieScoreCalculator, dieRoller, userInterface, playerName)); } return(playerList); }
public DieRollTrackerWithRandomRollerTests() { this.roller = new RandomDieRoller(this.tracker); }
public IEnumerable <TermResult> GetResults(IDieRoller dieRoller) { return(new[] { new TermResult { Scalar = 1, Value = _constant, Type = "constant" } }); }
public DiceResult Roll(IDieRoller roller) { IEnumerable <TermResult> termResults = _terms.SelectMany(t => t.GetResults(roller)).ToList(); return(new DiceResult(termResults, roller)); }