ID:97975
 
Resolved
Using roll() with too high a number of rolls could take a very long time to compute, causing the server to freeze in some extreme cases. Because rolling more dice makes the result less likely to deviate far from the average roll, a simpler method is now used in which most of the rolls are computed as an average, and the rest are done the old-fashioned way one at a time. This only affects very large numbers of dice; otherwise the old method is used.
BYOND Version:471
Operating System:Windows 7 Ultimate
Web Browser:
Applies to:Dream Daemon
Status: Resolved (472)

This issue has been resolved.
Descriptive Problem Summary:
Using the text parameter version of roll(example roll("1d6") can cause DS to freeze when using large values for number of sides and number of dice. When using the separate parameter version of roll(example roll(1,6) DS will not freeze and simply return 0 when using large values for number of sides and number of dice.

Code Snippet (if applicable) to Reproduce Problem:
mob/verb/roll_bad()
//Text string version of roll()
//This verb will freeze DS
world << roll("2323232132d56567655")

mob/verb/roll_okay()
//"Expanded" form of roll with separate params for num_sides and num_dice
//This verb will not lock up DS, and will output simply 0
world << roll(2323232132,56567655)



Expected Results:
Both formats of roll to process the input and not cause DS to freeze.

Actual Results:
Text format roll() freezes DS and separate parameter roll() does not freeze DS and returns a value.

Does the problem occur:
Every time? Or how often?
This issue always happens.

When does the problem NOT occur?
The text format of roll() does not freeze DS and returns a value when given smaller values to process. An example would be roll("1d6"). That will not freeze DS and will return a value.

Workarounds:
Taking a string such as "2323232132d56567655" and parsing it so that you can do roll(2323232132,56567655) and not freeze DS. Or use smaller values.
This appears to stem from a lack of bounds checking. There is no upper limit on the number of rolls, and you're using such a large number that the server is simply taking a very long time to roll.

The numerical format returning 0 is occurring because the number of reps is being interpreted as a negative number, again simply because it is so high.
I'm not using roll() in any capacity in anything, but merely stumbled across this while attending to a post in one of the dev forums. Since that poster was allowing user input to be fed into roll(), I figured they might not want people blowing up a server with large input. Seeing as this is technically not a bug, I should probably go and edit that post with some greater clarifications.
Yes, while it technically isn't a bug I left it open because it makes sense to implement some kind of common-sense cutoff or a statistical optimization for very large numbers of rolls.

I think for instance that we could safely handle several hundred rolls without much trouble, but beyond that you'd be looking at a significant delay. However at that level of repetition, even a perfectly random number generator would be so unlikely to stray from the mean that any significant deviation would be an extreme statistical anomaly. So 1250 rolls could probably be reduced to summing up 250 actual rolls and 1000 times the average (rounded) without a problem.