1
\$\begingroup\$

I'm trying to figure out the probabilities for the damage of a DOT spell which has the target roll a save each turn to see if they get rid of its effects. To do this I'm using a bunch of if/else statements, each with the damage for a certain number of turns, but for whatever reason, it doesn't like the formatting:

A: 1d20
B: 1d20
C: 1d20
D: 1d20
E: 1d20
F: 1d20
G: 1d20
H: 1d20
I: 1d20
J: 1d20
if A < 19 {
 if B < 19 {
  if C < 19 {
   if D < 19 {
    if E < 19 {
     if F < 19 {
      if G < 19 {
       if H < 19 {
        if I < 19 {
         if J < 19 {
          output 12d8 + 40d8
         }
         else {
          output 12d8 + 36d8
         }
        else {
         output 12d8 + 32d8
        }
       else {
        output 12d8 + 28d8
       }
      else {
       output 12d8 + 24d8
      }
     else {
      output 12d8 + 20d8
     }
    else {
     output 12d8 + 16d8
    }
   else {
    output 12d8 + 12d8
   }
  else {
   output 12d8 + 8d8
  }
 else {
  output 12d8 + 4d8
 }
else {
 output 12d8
}

Here's the link to what I'm trying, and if anyone can tell me what I'm doing wrong that would be great.

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to RPG.SE! Take the tour and visit the help center center if you need any guidance in posting questions/answers. Are you interested in the distribution of the damage over 11 rounds/turns or on the probability of a successfull saving throws in 11 rounds? For what I understood, the damage decreases by 4d8 at each round/turn, correct? \$\endgroup\$
    – Eddymage
    Jul 27 at 17:47
5
\$\begingroup\$

Toroid has explained how to fix the errors in your code. Here's how to make it simpler and better.

The magic word here is recursion. Basically, you want to write a function something like this:

function: damage on following turns {
  result: (d20 < 19) * (4d8 + [damage on following turns])
}

And then use it like this:

output 12d8 + [damage on following turns]

Now, if you do that, you'll see a funny-looking curve with two peaks and a warning that:

The maximum function depth was exceeded, results are truncated.

This is a deliberate feature of AnyDice: the function I wrote calls itself, and would keep doing so over and over forever if AnyDice didn't force it to stop after (by default) 10 nested calls. Basically this is equivalent to forcing the effect to end after at most 10 turns whether the target succeeds on the save or not.

It turns out, however, that with a DC of 19, the probability of the target not making the save in 10 turns is significant, meaning that the truncation changes the results we get. Fortunately we can increase the limit by adding something like the following line before the output statement:

set "maximum function depth" to 20

With this setting we still see a second peak in the graph, but it's a lot smaller now, and the average damage is noticeably higher (169.30 HP instead of 159.51 HP).

We can even change the maximum recursion depth during the program to plot the results using different settings in one graph, e.g. like this:

loop MAXDEPTH over {10, 20, 30, 40, 50} {
  set "maximum function depth" to MAXDEPTH
  output 12d8 + [damage on following turns] named "max [MAXDEPTH] turns"
}

The resulting graphs look like this:

AnyDice screenshot


Ps. Mathematically, the number of turns until a successful save is geometrically distributed. Thus, its average value is \$\frac1p-1\$, where \$p = \frac{21-\mathrm{DC}}{20}\$ is the probability of succeeding on the save. For a DC of 19, this means that \$p = \frac{2}{20} = \frac{1}{10}\$, and thus the average number of turns until a successful save is \$\frac1p - 1 = 10 - 1 = 9\$.

We can thus calculate the exact average damage of the spell as the average initial damage (\$12 \times 4.5 = 54\$ HP for 12d8) plus the average damage per turn (\$4 \times 4.5 = 18\$ HP for 4d8) times the average number of turns until save (\$9\$, as calculated above), for a total of \$54 + 9 \times 18 = 216\$ HP of damage on average. This is the same average number that AnyDice will (approximately) return if you increase the maximum recursion depth to a sufficiently large number (like, say, 99).

Of course, it should be noted that some of that average damage will only be dealt over a very large number of turns, and only if the target is unlucky and keeps failing their saves (and has enough HP to soak all that damage). If you're e.g. planning on using this spell in a combat that's likely to end in relatively few turns anyway, the truncated damage values returned by using a lower maximum recursion depth may actually better reflect realistic gameplay expectations.

\$\endgroup\$
3
\$\begingroup\$

The problem with your nested if/else blocks is that you're failing to close the an if block before each else. If we look at a smaller example:

if I < 19 {
    if J < 19 {
        ...
    }
    else {
        ...
    }
else {
    ...
}

we can see that the first if statement isn't closed before the else. You can fix this by introducing a } before each else. In the small example, this would be:

if I < 19 {
    if J < 19 {
        output 12d8 + 40d8
    }
    else {
        output 12d8 + 36d8
    }
}
else {
    output 12d8 + 32d8
}

In the full example, this is:

A: 1d20
B: 1d20
C: 1d20
D: 1d20
E: 1d20
F: 1d20
G: 1d20
H: 1d20
I: 1d20
J: 1d20
if A < 19 {
 if B < 19 {
  if C < 19 {
   if D < 19 {
    if E < 19 {
     if F < 19 {
      if G < 19 {
       if H < 19 {
        if I < 19 {
         if J < 19 {
          output 12d8 + 40d8
         }
         else {
          output 12d8 + 36d8
         }
        } 
        else {
         output 12d8 + 32d8
        }
       } 
       else {
        output 12d8 + 28d8
       }
      } 
      else {
       output 12d8 + 24d8
      }
     } 
     else {
      output 12d8 + 20d8
     }
    } 
    else {
     output 12d8 + 16d8
    }
   } 
   else {
    output 12d8 + 12d8
   }
  } 
  else {
   output 12d8 + 8d8
  }
 } 
 else {
  output 12d8 + 4d8
 }
} 
else {
 output 12d8
}

This new program gives a different error message but does solve your syntax problem. The new error message is:

calculation error
Boolean values can only be numbers, but you provided "d{?}".
Depending on what you want, you might need to create a function.

Guidance for this new error after the if/else syntax has been fixed can be found in How can I execute code depending on a die value in AnyDice?

\$\endgroup\$

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.