30 Days of Code — Day 3
Simple TTRPG Dice Roller
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.
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:
\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!