tabatkins / roll

🎲 An exact-results dice-rolling library, for answering dice-related stat questions.
MIT License
14 stars 0 forks source link

Add parsers for common dice languages #3

Open tabatkins opened 1 year ago

tabatkins commented 1 year ago

While it's not hard for someone familiar with the library to construct the rolls they want, dice-rolling DSLs are much more convenient to use in many cases. Like, d4 + d6 is way simpler than R.flat([Roll.d4, Roll.d6]).

I should support at least a reasonable subset of some existing roll DSLs, particularly Roll20 and AnyDice.

ekkaiasmith commented 1 year ago

I made a very simple parser to handle strings like 2d4+3d6+2 for example.

export interface ParsedDices {
    parsed: (Dice | { constant: number })[];
}

function parseDice(stringDice: string): ParsedDices {
    let diceArray: ParsedDices = { parsed: [] };
    for (const dice of stringDice.split("+")) {
        const [numDie, numFaces] = dice.split("d").map(Number);

        if (!isNaN(numDie) && !isNaN(numFaces) && numDie > 0 && numFaces > 0) {
            diceArray.parsed.push({ numDie, numFaces });
        } else if (numFaces === undefined && !isNaN(numDie) && numDie > 0) {
            diceArray.parsed.push({ constant: numDie });
        } else {
            console.error(`Invalid dice string ${dice} in ${stringDice}`);
            return { parsed: [] };
        }
    }
    return diceArray;
}

const processDice = () => {
  const diceArray = parseDice("2d4+3d6+3");
    return R.flat([
      ...diceArray.parsed.map((d) => {
        if ("constant" in d) {
            return d.constant;
        } else {
            return R.Roll.nd(d.numDie, d.numFaces);
        }
    }),
  ]).sum() as unknown as DiceProbability;
});
tabatkins commented 1 year ago

Okay, a basic Roll.parse() is implemented. Check the docs for details on what's currently supported in it.

tabatkins commented 1 year ago

(If there's any Roll20 commands you'd find particularly useful, lemme know and I can prioritize them.)