2

(This question is tagged [minecraft-commands] because it involves predicates/advancements.)

The Advancement

Here is a custom advancement I made:

{
  "display": {
    "icon": {
      "item": "minecraft:lime_concrete"
    },
    "title": "Dream Luck",
    "description": "You have a 1 in 7.5 trillion chance of getting this advancement every tick"
  },
  "parent": "dmmc.advancements:root",
  "criteria": {
    "requirement": {
      "trigger": "minecraft:tick",
      "conditions": {
        "player": [
          {
            "condition": "minecraft:random_chance",
            "chance": 1.33333333e-13
          }
        ]
      }
    }
  }
}

As you can see, it is quite simple. Players can achieve this advancement every tick, with 1 requirement: a predicate random_chance condition must succeed a 1 in 7.5 trillion chance.

Scientific Notation


Some background info on the random_chance condition: It tests if a random number 0.0–1.0 is less than a specified value. For example, a specified value of 0.5 would be equivalent to a 50% chance.


Since I wanted a 1 in 7.5 trillion chance, I divided 1 by 7,500,000,000,000 to get the astronomically low number of 1.33333333e-13. Immediately, a question arose: can a predicate's "chance" value accept numbers in scientific notation? It seems that the answer is yes. Using Misode's predicate generator, entering a chance of 0.000000001 would automatically convert into 1e-9. This suggests the feature does exist. The advancement also did not fail to load when using this value. Normally, when using an invalid value, such as a value greater than 1.0, the advancement would simply fail to load.

Statistically Unlikely Occurrence?

Everything seems fine so far, so I had added this advancement onto my server. Then 11 days later, a player got the advancement. I was shocked, because according to my math, this should have been nearly impossible.

I was aware that rolling this chance every tick would increase the odds, but the odds are still extremely low:

(1/7.5 trillion)×(20 ticks per second)×(3600 seconds per hour)×(24 hours per day)×(365 days per year)=8.4096e-5 or a 0.0084096% chance.

Also take into consideration that this assumes optimal conditions, where a player is online 24/7 for a year. Realistically, we can assume the player who earned this achievement played a maximum of 6 hours each day for all 11 days after the advancement was added. The adjusted chance of getting the advancement would then become:

(1/7.5 trillion)×(20 ticks per second)×(3600 seconds per hour)×(66 hours of playtime)=6.336e-7 or a 0.00006336% chance.

Predicate random_chance Limitations

After this occurrence, I suspected that a predicate might not be able to accurately represent the extremely low odds of 1 in 7.5 trillion, and might be limiting/capping the chance (1 in 1 billion, for example). Or perhaps there is some overflow error going on? Unfortunately, I had no way to confirm my suspicions.

So, what is the lowest chance that can be represented by a predicate's random_chance condition?

1 Answer 1

2

Parsing the advancement

The advancements are stored in JSON format which is a standard format. The format itself does support scientific notation. Minecraft Java Edition uses the gson library to parse json. This library supports double precision floating point format for numbers, which can hold pretty broad range of values (in the orders of +/-1e+/-308). When Minecraft gets the parsed value from the library, it takes it as a single precision floating point value, which can hold a smaller range of values (+/-1e+/-38). This is still more than enough precision to hold 1.33333333e-13.

When the advancement is checked it generates a random single precision number and checks if it is less than the change property. There is no other processing, rounding, capping etc.

Calculating the probability

The way you are calculating the probability right now is not correct. Take as a simple example a dice roll where you want to roll 6 and you have N rolls: (1/6 probability)×(N times) gives incorrect answer since if N = 12 you'll get probability = 2, which is clearly wrong. In the same way your formula above says that if you wait long enough you can reach a probability > 1.

To calculate the probability of some number of events happening in a number of subsequent tests, you need to use binomial distribution. There is also a more intuitive way to think about that: we can calculate the probability of NOT getting the advancement after N ticks. For a single dice roll, the probability of not rolling a 6 is (1 - 1/6) = 5/6. For two dice rolls the probability of not rolling a 6 on both rolls is 5/6 × 5/6. We can generalise the probability of not rolling a 6 after N rolls is 5/6 ^ N (to the power of N). Then if we want to see the probability of rolling a 6 we just calculate 1 - 5/6 ^ N

Going back to the advancement, the probability of getting the advancement after N ticks is 1 - (1 - 1 / 7.5e12) ^ N. Since N is equal to the number of predicate tests performed on the server this means we need to multiply by the number of players as well. I assume you have 10 players with roughly the same playtime, no bot or camera accounts that are always online. Then, if N = (20 ticks per second)×(3600 seconds per hour)×(66 hours of playtime)×(10 players), we get... roughly ... 6.336e-6 :D. Well, it turns out that the correct way of calculating the probability does not give a different result for low number of hours of playtime.

Conclusion

It seems the way you setup the advancement aligns with your intentions and there is nothing funky going on in the advancement calculation. You (that is, your server) either got very lucky or the advancement is somehow calculated more times than we predict. More data is needed to be able to settle the question.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .