ArtemGr / Sidekick

Dice and LFG bot for Discord.
MIT License
250 stars 39 forks source link

Cannot limit number of rerolls for a die using "o" operatior #199

Open ryushinji opened 5 years ago

ryushinji commented 5 years ago

So, in Legend of the Five Rings 4e, there is a mechanic called Emphases that allow the player to reroll any dice that roll a 1, but only the first time they roll a 1.

Roll20 has an "o" operator which its documentation states is an "only once" operator, which is used in tandem with the "r" reroll operator., so e.g. /r 10d10k10ro1 would roll 10 d10, keep all of them, and reroll1s the first time they come up.

I just tested Sidekick on a server on 2019-07-29, and the "r" operator seems to exist and behave as I'd expect, but the "o" operator results in an error message.

Since a LOT of L5R 4e games I'm lately tend to use Discord and Sidekick, I think this will be a useful feature, especially as it is a generic operator that could be utilized by any system with a "reroll only once" mechanic.

(Also, per the Patreon page, it seems issues lodged by patrons get priority, and I am a Patron and can validate this if needed.)

ArtemGr commented 5 years ago

@ryushinji , we're currently working on #195, will look into the o operator and Five Rings right after the internal communication rewrite. Thanks for your support.

ArtemGr commented 5 years ago

Sorry for the delay. I've checked the code and we're currently only rerolling once.

// #31: Parse https://wiki.roll20.net/Dice_Reference#Rerolling_Dice.
named! (reroll (&str) -> DiceOp,
  do_parse! (char! ('r') >> spec: nom_le_ge >>
    (DiceOp::Reroll {le_ge: spec.0, face: spec.1, lim: 1})));
      DiceOp::Reroll {le_ge, face, lim} => {
        let mut idx = 0;
        let mut recurrent = 0;
        loop {
          if idx >= rolls.len() {break}
          if recurrent >= lim {recurrent = 0; idx += 1; continue}  // Protect against an infinite loop, "1d1r1".
          if !rolls[idx].counts {recurrent = 0; idx += 1; continue}
          if !le_ge_match (rolls[idx].face, le_ge, face) {recurrent = 0; idx += 1; continue}
          rolls[idx].counts = false;
          let new_face = roll (dice.faces);
          rolls.insert (idx + 1, Roll {face: new_face, counts: true, failure: false});
          recurrent += 1;
          idx += 1}},

E.g. [A = 1, B = 2, C = 1] will become [A = ~1~, Ar = x, B = 2, C = ~1~, Cr = x].

I think we can reroll more than once by increasing the lim, but I'm not sure what the actual lim should be. Rerolling indefinitely doesn't sound right to me. E.g. /r 1d1r1 would not compute.