rolls dnd-style dice
Online demo page: https://wyattscarpenter.github.io/nicedice
NPM listing: https://www.npmjs.com/package/nicedice
The d, which I think of as an infix dice operator with extremely high precedence, may be upper or lower case.
Additionally, "advantage"/"disadvantage" (or certain abbreviations thereof) may be added before roll expressions to repeat the roll twice and take the higher/lower number. These also may be in any letter case.
Nicedice accepts nicedice shorthand, which is equivalent to conventional dice notation, like "2d6+d6+3d4+adv d5", or nicedice longhand, like "d(2,6)+d(1,6)+d(3,4)+advantage(1,5)". Internally, the former is converted to the latter before the expressions are evaluated, and the two notations can be mixed freely in the same expression without problem.
In addition to a result, nicedice also returns a roll record showing how the result was achieved. See the code for the full API.
Internally, dice expressions are evaluated using the Function object constructor, which is kind of like using eval. However, the input is sanitized to remove so many characters that not even JSFuck-style attacks have enough leeway to work. If you manage a JSFuck-style arbitrary code execution attack using only the characters mentioned above, digits, and/or parentheses, please tell me!!!
I consider NiceDice to be completely feature-complete, mature, and finished. I do not expect to ever have to update it.
I have realized one can construct somewhat-arbitrary strings within these expressions, which is somewhat worrying. This is because
/ / + 0 evaluates to
"/ /0". One can also get
"NaN" this way. However, one can't use indices or methods of the string because there is no
. allowed. JSFuck relies really heavily on
 ( see https://github.com/aemkei/jsfuck/blob/master/jsfuck.js ) to both get characters in the right order for certain strings, and, crucially, get
eval, which are needed to evaluate functions and variables, which is the scary part. One can't just run
"alert"(), using a string as a function name, for example. So, I think we're still safe. I mean, JSFuck doesn't even work if one takes away the
! ( see https://codegolf.stackexchange.com/questions/75423/jsfk-with-only-5-symbols ), which we already have taken away, and it sure as heck doesn't work if one takes away the
. However, we do give the user more operators that aren't in JSFuck, like
,, so it's possible that I've missed something and one can somehow use those to achieve the same result—but I still think it's unlikely. Still, anyone who figures something out, let me know!
Initially, I became worried that a user could construct a pathological regex using
\1 to require matching against a previous match again) which are NP-complete, as described in https://swtch.com/~rsc/regexp/regexp1.html. However, I do not currently allow
Whoops, that assumption proved incorrect! https://neil.fraser.name/software/JS-Interpreter/demos/regexp.html contains the helpful example
'1111111111111111111111111111111113'.match(/(1+)+2/) and it still works (uh, in a "task failed successfully" sense of "works"), and both
1111111111111111111111111111111113 can be written in nicedice shorthand. We can even get
1111111111111111111111111111111113 to be a string by adding it to
/ /! (For reasons unclear to me, adding these the naive way doesn't work, but I assume some trickery could get us to an appropriate string in the end.)
/1*2/('1122') or whatever, one needs to actually invoke methods with names, such as
.match, etc. So we're still safe. One can construct a regex literal in nicedice shorthand, but one can't do anything with it.
Edit, 2023-02-13: Similar "nicedice" projects.
There are a number of things called "nicedice" in the world—apparently, it's a very easy rhyme to think of!—for example, companies that sell you physical dice, online dice games, visual dice simulators, and also some things that have nothing to do with dice. However, there are also "nicedice" projects extremely similar to this nicedice, being also textual dice-expression evaluators. I list them here, for the sake of clarity. My method for gathering these was principally to search github.com for "nicedice" on 2023-02-13 and click on every repository result (there were 16), listing only the truly relevant:
https://github.com/EavesofIT/nicediceroller from 2020. "This is the python bot for our dnd [Discord] servers to roll dice when we need to roll remotely." MIT license. Judging from the source code, this is just a thin wrapper over https://pypi.org/project/dice/, which is also MIT license, but by other people.
dicesupports a lot of features, such as Fudge dice, exploding dice, and advantage.
nicedicerollerseems to have special handling for the case of adding or subtracting a constant from the dice expression, even though
dicealready handles basic arithmetic; this is presumably because, playing dnd, these fellows want to be able to see natural 20s and 1s. Perhaps the
dicewould have worked for them.
https://github.com/greerrrr/nicedice from 2014. "python dice rolling module intended for IRC bots". Judging from https://pypi.org/project/nicedice/, which is under the same name and username, this is "Public domain, I don’t care what you do with it. Credit would be nice. Currently outputs with IRC color codes at all times." Judging from the source code, this has special handling of Fate/Fudge dice and World of Darkness(I assume that's what WoD means) dice. It seems to have special handling for the case of adding or subtracting a constant from the dice expression.
That's it! (Honorable mention to https://github.com/kimrejstrom/nicer-dicer.) All the other NiceDices are hopefully distinct enough in purpose and form from this that I don't have to cover them here. Actually now that I've written this section, I question why I did. Well, from now on, if anyone asks you if the pypi nicedice is the same as the npm nicedice, hopefully you can confidently say, "no".