30 Days of Code — Day 3

Simple TTRPG Dice Roller

Jordan Fox
3 min readMay 17, 2024

Today I wanted to jump into some coding for the dice notation interpreting. I will get into it a bit, but I want to make sure it’s properly planned first. Let’s add a bit to the diagram from yesterday.

Photo by 2H Media on Unsplash

Interpreting the Dice Notation

I started by defining what the dice notation looks like. The user will need to enter the dice in a ‘NdS ± modifier’ notation where N is the number of dice to roll, S is the number of sides the die have, and the modifier can be either a constant, additional die, or a combination.

The interpreter will need to parse the user’s input into parts where the first part is the primary dice roll, and anything after is a modifier. It will need to add or subtract any constant modifiers, and parse/roll/return the values of any dice modifiers.


function parseInput(input) {
let inputParts = input.match(/(\d+d\d+|[+\-]\d+d\d+|[+\-]\d+)/g);
let primaryPart = inputParts.shift();
return { primaryPart, inputParts };
}

This looks deceptively simple given its size, so let’s break it down a bit. This regex consists of three main parts, each separated by the | (OR) operator:

  1. \d+d\d+:
  • \d+: Matches one or more digits (representing the number of dice).
  • d: Matches the character "d".
  • \d+: Matches one or more digits (representing the number of sides on each die).

This part matches dice rolls without a leading sign, e.g., “2d10”.

2.[+\-]\d+d\d+:

  • [+\-]: Matches either a "+" or "-" sign.
  • \d+: Matches one or more digits (representing the number of dice).
  • d: Matches the character "d".
  • \d+: Matches one or more digits (representing the number of sides on each die).

This part matches dice rolls with a leading “+” or “-” sign, e.g., “+2d6” or “-1d4”.

3.[+\-]\d+:

  • [+\-]: Matches either a "+" or "-" sign.
  • \d+: Matches one or more digits (representing a constant modifier).

This part matches constant modifiers with a leading “+” or “-” sign, e.g., “+4” or “-3”.

Putting It All Together

  • (\d+d\d+|[+\-]\d+d\d+|[+\-]\d+):
  • The parentheses () group the entire expression to ensure each part is captured as a single match.
  • The | operator combines the three parts, allowing the regex to match any one of the patterns.
  • g:
  • The global flag g tells the regex engine to find all matches in the input string, not just the first one.

Examples

Given the input string "2d10+2d6-1d4+4", the regex will match:

  • "2d10": Matches the first part using \d+d\d+.
  • "+2d6": Matches the second part using [+\-]\d+d\d+.
  • "-1d4": Matches the third part using [+\-]\d+d\d+.
  • "+4": Matches the fourth part using [+\-]\d+.

This function then returns the result of all of this as 2 values: primaryPart: 2d10, and inputParts: [‘+2d6’, ‘-1d4’, ‘+4’] which we will use later for our rolling function.

Design Flexibility

You may have noticed that this solution doesn’t exactly follow the design I mapped out above. In my diagram I have the result being returned as a single array with all of the parts, including the primary. In this case, I think deviating from the design was fine. The change wasn’t huge, and it will make life just a little bit easier when we’re trying to format the final output later.

Looking Ahead

Tomorrow we will work on the rolling functionality and the format of the output. If I have time I may also set it up as an API, but if not, I will try to do that for Day 4. Thanks for reading, and please leave any questions or feedback in the comments!

--

--

Jordan Fox
Jordan Fox

Written by Jordan Fox

Chicago with my husband. Father of one (dog). Passionate about technology. Occasionally political. Working on my mental health, my family, and my career.