3
\$\begingroup\$

I'm trying to check the probabilities of rolling 2d20, and dropping the farthest from ten using anydice. (i.e. "Most Average" weighted roll, similar to 5e advantage/disadvantage. Basically you'd always roll 2, and drop one based on adv/std/dis.) I'm having trouble with the syntax. I can lay out the nested if/then statements, I think but it's not working out, and I don't really understand it from the documentation.

Because I want to maintain the 5% ish criticals, I need to reconsider them, and I think they'll still work with Adv/Dis rolls. So I opted for pairs and 'opposites' between the two dice. (But not exactly, I'd use 21's but 20's are easier to calculate at a glance.)

For totals of 20 (19 + 1, etc.) it counts as a critical success. For pairs, (A = B) it counts as a critical failure. For double 20's it's a double critical. For double 1's it's a double fail. For double 10's it's a critical s/f. (Auto crit, not an auto S/F like the others, I just want it to tell me when it happens.) Otherwise, it will output the die closest to 10 and drop the other.

Can I get some help writing this out?

\$\endgroup\$
  • 1
    \$\begingroup\$ I think this would be easier to answer if you add a code block of what you have written so far, so that answerers experts can spot where an improvement can be made. \$\endgroup\$ – KorvinStarmast Aug 3 '18 at 16:07
  • \$\begingroup\$ Dang. I lost it. I need to kill that cookie-deletion-on-exit preference I think. \$\endgroup\$ – spicklesandwich Aug 3 '18 at 16:56
  • 1
    \$\begingroup\$ Maybe try again, and if it works this time fine; if not, C&P to a text file so that you can present it here. \$\endgroup\$ – KorvinStarmast Aug 3 '18 at 17:49
5
\$\begingroup\$

Does this code do what you want?

function: roll ROLL:s {
  \ we assume that ROLL always has exactly two dice; AnyDice sorts them in descending order \
  HI: 1@ROLL
  LO: 2@ROLL
  \ handle the special cases first \
  if LO = 10 & HI = 10 { result: -1 } \ double 10 = "crit success/fail" \
  if LO + HI = 20      { result: 20 } \ mirror pair = crit success \
  if LO = HI           { result:  0 } \ equal pair = crit failure \ 
  \ at this point, we know there's no equal or mirror pair \
  if [absolute LO - 10] < [absolute HI - 10] { result: LO } else { result: HI }
}

output [roll 2d20]

The output, summarized, looks like this:

Roll          | AnyDice result | Probability
--------------+----------------+------------
Double 10     |       -1       |      0.25 %
Crit success  |       20       |      4.50 %
Crit fail     |        0       |      4.75 %
Normal N < 10 |        N       |   N - 0.5 %  
Normal N = 10 |        N       |       9.5 %
Normal N > 10 |        N       |  19.5 - N %

That is, except for the crits, you get the same kind of triangle-shaped probability distribution as for a normal 2d20 roll, except that in this case the range of normal rolls is only from 1 to 19 (since the only way the roll closest to 10 could be 20 is if you rolled a double 20, but that's a crit fail).

Also, you can see that if a double 10 was considered a critical success, then the probabilities of a crit fail and a crit success would both be exactly 4.75%, i.e. just slightly below the 5% chance of rolling a natural 1 or a nat 20 on 1d20. This symmetry may or may not be something you'd like to have.

In fact, the way I organized the code above, you can test the effects of this change simply by deleting the "double 10" line (since, if that line isn't there, the code will continue into the following "mirror pair" case). Of course, you can also easily enough test the effect of handling a double 10 in other ways (e.g. treating it as a crit fail, or just as a normal 10) simply by replacing the -1 result value in the code with any other number.

\$\endgroup\$
  • \$\begingroup\$ This is actually perfect. My main ideal was to add a non-flat probability curve, and second to try to keep a 5% crit probability. \$\endgroup\$ – spicklesandwich Aug 3 '18 at 18:44
  • \$\begingroup\$ You're welcome. BTW, one problem you may have had with your original code is that the ROLL parameter here really does need to be a sequence (i.e. marked with :s). That's what causes AnyDice to call the function for each possible (ordered) pair of 2d20 rolls and to collect the results into a "custom die" (i.e. a probability distribution over the integers). That's one quite essential feature of AnyDice that is unfortunately rather briefly documented. \$\endgroup\$ – Ilmari Karonen Aug 3 '18 at 18:53
  • \$\begingroup\$ How would you add the same doubling/canceling rules to advantage? I'd just assume replace the last function line with 'highest' but it doesn't like that. \$\endgroup\$ – spicklesandwich Aug 3 '18 at 18:58
  • \$\begingroup\$ Ah. NM, I got it. \$\endgroup\$ – spicklesandwich Aug 3 '18 at 19:01
  • \$\begingroup\$ @spicklesandwich: You'll have to decide how you want to actually handle advantage with your new rolling rules. One really basic way would be to just have the player roll 2d20 twice, apply the same closer-to-10 rule to both 2d20 rolls, and then take the higher one of the results. One way to implement that in AnyDice would be to save the output of the single closest-to-10 roll as a custom die, as in X: [roll 2d20], and then do output [highest 1 of 2dX]. \$\endgroup\$ – Ilmari Karonen Aug 3 '18 at 19:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.