dice-roller / rpg-dice-roller

An advanced JS based dice roller that can roll various types of dice and modifiers, along with mathematical equations.
https://dice-roller.github.io/documentation
MIT License
243 stars 59 forks source link

Check for doublets/triplets, etc. #210

Closed alucard87pl closed 3 years ago

alucard87pl commented 3 years ago

I'm trying to adapt the roller to a dice mechanic from the Adventure Game Engine (age). It uses mostly a 3d6 roll against a value, but one of these dice is a special 'stunt' die, that is looked at separately. I figured that out to be {2d6+d6}>=X.

AGE however also has a 'doubles' mechanic where if the test is successful AND any of the rolled d6 have the same result (no matter if it's on the 'stunt') die or not, that's when you get the stunt points indicated by the stunt die.

Examples for {2d6+d6}>=10: Result AGE Result
[3, 4]+[5] = 12 Sucess, no Stunt
[4, 4]+[2] = 10 Success, Stunts: 2
[4, 3]+[4] = 11 Success, Stunts: 4
[1, 4]+[1] = 6 FAIL, no Stunt
[1, 2]+[3] = 6 FAIL, no Stunt

What would be the best way of implementing this? I can't seem to find a way to access the individual roll result arrays to try and concatenate them and calculate if it contains any doubles.

GreenImp commented 3 years ago

Hi @alucard87pl

Interesting, and a few questions:

I'm curious as to whether this could be achieved with a new modifier, but not sure how it would work.

Retrieiving rolls

You should also be able to access the roll results, from the DiceRoll or DiceRoller object (Depending on what you're using).

DiceRoller

https://greenimp.github.io/rpg-dice-roller/api/DiceRoller.html

The DiceRoller.roll() method returns either a DiceRoll object, or an array of DiceRoll objects. It also has a log property, that is an array of the DiceRoll objects that have been rolled so far. You can get the rolls from the DiceRoll object as detailed below.

DiceRoll

https://greenimp.github.io/rpg-dice-roller/api/DiceRoll.html

The DiceRoll object has a rolls property, which is an array of ResultGroup|RollResults|string|number

A ResultGroup has a results property, is an array of ResultGroup|RollResults|number|string.

You need to get a list of all of the RollResults objects, either in the top level DiceRoll.rolls, or as a descendant in any ResultGroup.results property. So you'll need to recursively loop through the list, and all the ResultGroups.

Your structure may look something like this:

// DiceRoll.rolls:
[
    RollResults, // 1
    '+',
    ResultGroup {
        results: [
            ResultGroup  {
                results: [
                    RollResults, // 2
                ],
            },
            '*',
            RollResults, // 3
        ],
    },
]

And you need to map it to:

[
    RollResults, // 1
    RollResults, // 2
    RollResults, // 3
]

For your example above; [4, 4]+[2] = 10 I would expect you to be left with two RollResults objects; one for the [4, 4] and another for the [2] (Stunt)

Now, a RollResults object has a rolls property, which is an array of RollResult (Note singular - not RollResults) objects. These are the actual individual rolls.

RollResult has a calculationValue property. This is what you want to look at, and compare with the RollResult objects.

So you should have two RollResults like:

[
    RollResults {
        rolls: [
            RollResult {
                calculationValue: 4
            },
            RollResult {
                calculationValue: 4
            },
        ]
    }
    RollResults {
        rolls: [
            RollResult {
                calculationValue: 2
            },
        ]
    }
]

I think that should enable you to do your manual calculations. Hopefuly it's of some help.

alucard87pl commented 3 years ago

@GreenImp thanks for the reply. The stunt is a regular die in the pool, always summed together, so in essence, it's a 3d6. In real life it would be somehow distinct from the others (two blue, one red for example). The mechanics only care about the stunt die if the total 3d6 roll is a success. So, to reiterate: out of 3d6, three things need to be checked:

As for retrieving the result, I'll hammer something out. Thanks :)

GreenImp commented 3 years ago

So, if I roll:

// total greater than 8 is a success
{3d6>8}: [4, 4, 3] = 1

The above will be a success, and return 1.

If we assume that the final roll is the "stunt" roll; What would you expect the result of that roll to be?

alucard87pl commented 3 years ago

Referring back to my original post:

Result AGE Result
[3, 4]+[5] = 12 Sucess, no Stunt
[4, 4]+[2] = 10 Success, Stunts: 2
[4, 3]+[4] = 11 Success, Stunts: 4
[1, 4]+[1] = 6 FAIL, no Stunt
[1, 2]+[3] = 6 FAIL, no Stunt

The issue is, that both the success/fail and the stunt (it's value, if it exists) would need to be returned. Since I'm writing it as a Discord bot, the ideal result for me would be a Rich Embed, with each die result, it's total and the amount of stunt points.

GreenImp commented 3 years ago

Ah right, so you need both results returned, rather than a single result. Yeah, that's a tricky one, because the dice roller is only designed to return a single result. I was thinking that a modifier could be created to do the calculation for you, but that still wont be able to return more than a single result.

I think you're probably going to have to go down the manual route, as described above, unfortunately.

alucard87pl commented 3 years ago

Yeah, there's no real need for an edge case like this to be internally suported. The manual workaround is good enough. Feel free to close :)

GreenImp commented 3 years ago

Will do. Let me know if it doesn't work for you!