├── pack.png ├── .gitattributes ├── data ├── minecraft │ └── tags │ │ └── functions │ │ └── load.json └── random │ ├── predicates │ ├── coin_toss.json │ ├── score_invert.json │ ├── score_percentage.json │ ├── score_ppb.json │ └── score_fraction.json │ └── functions │ ├── private │ ├── number_provider │ │ ├── constant.mcfunction │ │ ├── geometric.mcfunction │ │ ├── poisson.mcfunction │ │ ├── uniform.mcfunction │ │ └── binomial.mcfunction │ ├── geometric_loop.mcfunction │ ├── binomial_loop.mcfunction │ ├── true_uniform_loop.mcfunction │ ├── choose_loop.mcfunction │ ├── poisson_loop.mcfunction │ └── load.mcfunction │ ├── geometric.mcfunction │ ├── binomial.mcfunction │ ├── uniform.mcfunction │ ├── true_uniform.mcfunction │ ├── choose.mcfunction │ ├── number_provider.mcfunction │ └── poisson.mcfunction ├── pack.mcmeta ├── LICENSE └── README.md /pack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aeldrion/Minecraft-Random/HEAD/pack.png -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /data/minecraft/tags/functions/load.json: -------------------------------------------------------------------------------- 1 | { 2 | "values": [ 3 | "random:private/load" 4 | ] 5 | } -------------------------------------------------------------------------------- /data/random/predicates/coin_toss.json: -------------------------------------------------------------------------------- 1 | { 2 | "condition": "minecraft:random_chance", 3 | "chance": 0.5 4 | } -------------------------------------------------------------------------------- /pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "pack_format": 15, 4 | "description": "A utility data pack for generating random numbers or evaluating random predicates" 5 | } 6 | } -------------------------------------------------------------------------------- /data/random/functions/private/number_provider/constant.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:private/number_provider/constant 2 | # 3 | # @private 4 | # @within random:number_provider 5 | # @input 6 | # storage random:input 7 | # lambda: float 8 | # The rate or inverse scale 9 | 10 | execute store result score $out random run data get storage random:input value -------------------------------------------------------------------------------- /data/random/predicates/score_invert.json: -------------------------------------------------------------------------------- 1 | { 2 | "condition": "minecraft:value_check", 3 | "value": { 4 | "min": 1, 5 | "max": { 6 | "type": "minecraft:score", 7 | "score": "random", 8 | "target": { 9 | "type": "minecraft:fixed", 10 | "name": "$chance" 11 | } 12 | } 13 | }, 14 | "range": { 15 | "min": 1, 16 | "max": 1 17 | } 18 | } -------------------------------------------------------------------------------- /data/random/predicates/score_percentage.json: -------------------------------------------------------------------------------- 1 | { 2 | "condition": "minecraft:value_check", 3 | "value": { 4 | "min": 1, 5 | "max": 100 6 | }, 7 | "range": { 8 | "min": 1, 9 | "max": { 10 | "type": "minecraft:score", 11 | "score": "random", 12 | "target": { 13 | "type": "minecraft:fixed", 14 | "name": "$chance" 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /data/random/predicates/score_ppb.json: -------------------------------------------------------------------------------- 1 | { 2 | "condition": "minecraft:value_check", 3 | "value": { 4 | "min": 1, 5 | "max": 1000000000 6 | }, 7 | "range": { 8 | "min": 1, 9 | "max": { 10 | "type": "minecraft:score", 11 | "score": "random", 12 | "target": { 13 | "type": "minecraft:fixed", 14 | "name": "$chance" 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /data/random/functions/private/geometric_loop.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:private/geometric_loop 2 | # 3 | # Runs a single Bernoulli trial 4 | # Repeats until the trial fails or until $out reaches 1000 5 | # 6 | # @private 7 | # @within random:geometric 8 | # @within random:private/geometric_loop 9 | 10 | scoreboard players add $out random 1 11 | execute unless predicate random:score_ppb unless score $out random matches 1000 run function random:private/geometric_loop -------------------------------------------------------------------------------- /data/random/functions/private/binomial_loop.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:private/binomial_loop 2 | # 3 | # Runs a single Bernoulli trial 4 | # Repeats until #trials is 0 5 | # 6 | # @private 7 | # @within random:binomial 8 | # @within random:private/binomial_loop 9 | 10 | execute if predicate random:score_ppb run scoreboard players add $out random 1 11 | scoreboard players remove #trials random 1 12 | execute if score #trials random matches 1.. run function random:private/binomial_loop -------------------------------------------------------------------------------- /data/random/functions/geometric.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:geometric 2 | # 3 | # Generates a random number following a geometric distribution of probability p, supported on {1, 2, 3, ...} 4 | # Caps at 1000 5 | # 6 | # @public 7 | # @input 8 | # score $chance random 9 | # The probability of success of each Bernoulli trial, with a scale of 1,000,000,000 10 | # @output 11 | # score $out random 12 | # An integer in [1, 1000] 13 | 14 | scoreboard players set $out random 0 15 | function random:private/geometric_loop -------------------------------------------------------------------------------- /data/random/predicates/score_fraction.json: -------------------------------------------------------------------------------- 1 | { 2 | "condition": "minecraft:value_check", 3 | "value": { 4 | "min": 1, 5 | "max": { 6 | "type": "minecraft:score", 7 | "score": "random", 8 | "target": { 9 | "type": "minecraft:fixed", 10 | "name": "$b" 11 | } 12 | } 13 | }, 14 | "range": { 15 | "min": 1, 16 | "max": { 17 | "type": "minecraft:score", 18 | "score": "random", 19 | "target": { 20 | "type": "minecraft:fixed", 21 | "name": "$a" 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /data/random/functions/private/true_uniform_loop.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:private/true_uniform_loop 2 | # 3 | # Generates uniform variates until the result is not subject to modulo bias (i.e. x < maxint/size*size where size=max-min+1) 4 | # 5 | # @private 6 | # @within random:true_uniform 7 | # @winthin random:private/true_uniform_loop 8 | 9 | # Xn+1 = (aXn + c) mod m 10 | scoreboard players operation #lcg random *= #lcg_a random 11 | scoreboard players operation #lcg random += #lcg_c random 12 | scoreboard players operation #lcg random %= #lcg_m random 13 | 14 | # Loop if necessary 15 | execute if score #lcg random >= #max random run function random:private/true_uniform_loop -------------------------------------------------------------------------------- /data/random/functions/private/choose_loop.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:private/choose_loop 2 | # 3 | # Recursively selects an NBT tag from a list given index from the end of the list 4 | # Repeats until #index is 0 5 | # 6 | # @private 7 | # @within random:choose 8 | # @within random:private/choose_loop 9 | 10 | scoreboard players remove #index random 1 11 | 12 | # If the requested tag is now at the end of the list, send it to output 13 | execute if score #index random matches 0 run data modify storage random:output Tag set from storage random:data List[-1] 14 | 15 | # Otherwise, pop and run this function again 16 | data remove storage random:data List[-1] 17 | execute if score #index random matches 1.. run function random:private/choose_loop -------------------------------------------------------------------------------- /data/random/functions/binomial.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:binomial 2 | # 3 | # Generates a random number with binomial distribution of parameters n, p using a value_check predicate on a loop 4 | # 5 | # @public 6 | # @input 7 | # score $trials random 8 | # The number of Bernoulli trials. Maximum accepted value is 1000. Otherwise, output is 0. 9 | # score $chance random 10 | # The probability of success of each Bernoulli trial, with a scale of 1,000,000,000. 11 | # @output 12 | # score $out random 13 | # An integer in [0, n] 14 | 15 | scoreboard players operation #trials random = $trials random 16 | scoreboard players set $out random 0 17 | execute if score $trials random matches 1..1000 if score $chance random matches 1..1000000000 run function random:private/binomial_loop 18 | scoreboard players reset #trials random -------------------------------------------------------------------------------- /data/random/functions/private/poisson_loop.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:private/poisson_loop 2 | # 3 | # In this loop, p is multiplied by a uniform random number u in [0, 1] until p is smaller than L = exp(-l) 4 | # Because we are working with integers, u is represented with a scale of 2^16 and p is divided by 2^16 after every multiplication 5 | # At the end of the loop, #k is one less than the total number of repetitions of this function 6 | # 7 | # @private 8 | # @within random:poisson 9 | # @within random:private/poisson_loop 10 | 11 | scoreboard players add #k random 1 12 | 13 | scoreboard players set $min random 0 14 | scoreboard players set $max random 65536 15 | function random:uniform 16 | scoreboard players operation #p random /= #65536 random 17 | scoreboard players operation #p random *= $out random 18 | 19 | execute if score #p random > #L random run function random:private/poisson_loop -------------------------------------------------------------------------------- /data/random/functions/private/number_provider/geometric.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:private/number_provider/geometric 2 | # 3 | # @private 4 | # @within random:number_provider 5 | # @input 6 | # storage random:input 7 | # p: float 8 | # The probability of success of each Bernoulli trial. 9 | 10 | # Save storage values as scores 11 | execute if score $chance random matches -2147483648..2147483647 run scoreboard players operation #user_chance_input random = $chance random 12 | execute store result score $chance random run data get storage random:input p 1000000000 13 | 14 | # Run main function 15 | function random:geometric 16 | 17 | # Clean up 18 | execute unless score #user_chance_input random matches -2147483648..2147483647 run scoreboard players reset $chance random 19 | execute if score #user_chance_input random matches -2147483648..2147483647 run scoreboard players operation $chance random = #user_chance_input random 20 | scoreboard players reset #user_chance_input random -------------------------------------------------------------------------------- /data/random/functions/private/number_provider/poisson.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:private/number_provider/poisson 2 | # 3 | # @private 4 | # @within random:number_provider 5 | # @input 6 | # storage random:input 7 | # lambda: float 8 | # The expected value, a number between 0.1 and 10 9 | # Decimal values are supported but only the first decimal place is taken into account 10 | 11 | # Save storage values as scores 12 | execute if score $lambda random matches -2147483648..2147483647 run scoreboard players operation #user_lambda_input random = $lambda random 13 | execute store result score $lambda random run data get storage random:input lambda 10 14 | 15 | # Run main function 16 | function random:poisson 17 | 18 | # Clean up 19 | execute unless score #user_lambda_input random matches -2147483648..2147483647 run scoreboard players reset $lambda random 20 | execute if score #user_lambda_input random matches -2147483648..2147483647 run scoreboard players operation $lambda random = #user_lambda_input random 21 | scoreboard players reset #user_lambda_input random -------------------------------------------------------------------------------- /data/random/functions/uniform.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:uniform 2 | # 3 | # Generates a random number between two given bounds using a linear congruential generator 4 | # 5 | # @public 6 | # @within random:exponential 7 | # @within random:private/poisson_loop 8 | # @input 9 | # score $min random 10 | # The minimum value (inclusive) 11 | # score $max random 12 | # The maximum value (inclusive) 13 | # @output 14 | # score $out random 15 | # An integer in range [min, max] 16 | 17 | # Calculate size of range 18 | scoreboard players operation #size random = $max random 19 | scoreboard players operation #size random -= $min random 20 | scoreboard players add #size random 1 21 | 22 | # Xn+1 = (aXn + c) mod m 23 | scoreboard players operation #lcg random *= #lcg_a random 24 | scoreboard players operation #lcg random += #lcg_c random 25 | scoreboard players operation #lcg random %= #lcg_m random 26 | 27 | # Trim "low quality" bits 28 | scoreboard players operation $out random = #lcg random 29 | scoreboard players operation $out random /= #8 random 30 | 31 | # Get within desired range 32 | scoreboard players operation $out random %= #size random 33 | scoreboard players operation $out random += $min random -------------------------------------------------------------------------------- /data/random/functions/true_uniform.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:true_uniform 2 | # 3 | # Generates a random number between two given bounds using a linear congruential generator 4 | # Adjusts for modulo bias: if the range is small, or if max-min almost divides 2147483648, the bias should not be noticeable and random:uniform should be used instead for efficiency 5 | # 6 | # @public 7 | # @input 8 | # score $min random 9 | # The minimum value (inclusive) 10 | # score $max random 11 | # The maximum value (inclusive) 12 | # @output 13 | # score $out random 14 | # An integer in range [min, max] 15 | 16 | # Calculate size of range 17 | scoreboard players operation #size random = $max random 18 | scoreboard players operation #size random -= $min random 19 | scoreboard players add #size random 1 20 | 21 | # Calculate maximum authorised value 22 | scoreboard players set #max random 2147483647 23 | scoreboard players operation #max random /= #size random 24 | scoreboard players operation #max random *= #size random 25 | 26 | # Loop 27 | function random:private/true_uniform_loop 28 | scoreboard players operation $out random = #lcg random 29 | 30 | # Get within desired range 31 | scoreboard players operation $out random %= #size random 32 | scoreboard players operation $out random += $min random -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /data/random/functions/private/number_provider/uniform.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:private/number_provider/uniform 2 | # 3 | # @private 4 | # @within random:number_provider 5 | # @input 6 | # storage random:input 7 | # min: int 8 | # The minimum value 9 | # max: int 10 | # The maximum value 11 | 12 | # Save storage values as scores 13 | execute if score $min random matches -2147483648..2147483647 run scoreboard players operation #user_min_input random = $min random 14 | execute if score $max random matches -2147483648..2147483647 run scoreboard players operation #user_max_input random = $max random 15 | execute store result score $min random run data get storage random:input min 16 | execute store result score $max random run data get storage random:input max 17 | 18 | # Run main function 19 | function random:uniform 20 | 21 | # Clean up 22 | execute unless score #user_min_input random matches -2147483648..2147483647 run scoreboard players reset $min random 23 | execute unless score #user_max_input random matches -2147483648..2147483647 run scoreboard players reset $max random 24 | execute if score #user_min_input random matches -2147483648..2147483647 run scoreboard players operation $min random = #user_min_input random 25 | execute if score #user_max_input random matches -2147483648..2147483647 run scoreboard players operation $max random = #user_max_input random 26 | scoreboard players reset #user_min_input random 27 | scoreboard players reset #user_max_input random -------------------------------------------------------------------------------- /data/random/functions/private/number_provider/binomial.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:private/number_provider/binomial 2 | # 3 | # @private 4 | # @within random:number_provider 5 | # @input 6 | # storage random:input 7 | # n: int 8 | # The number of Bernoulli trials. Maximum accepted value is 1000. Otherwise, output is 0. 9 | # p: float 10 | # The probability of success of each Bernoulli trial. 11 | 12 | # Save storage values as scores 13 | execute if score $trials random matches -2147483648..2147483647 run scoreboard players operation #user_trials_input random = $trials random 14 | execute if score $chance random matches -2147483648..2147483647 run scoreboard players operation #user_chance_input random = $chance random 15 | execute store result score $trials random run data get storage random:input n 16 | execute store result score $chance random run data get storage random:input p 1000000000 17 | 18 | # Run main function 19 | function random:binomial 20 | 21 | # Clean up 22 | execute unless score #user_trials_input random matches -2147483648..2147483647 run scoreboard players reset $trials random 23 | execute unless score #user_chance_input random matches -2147483648..2147483647 run scoreboard players reset $chance random 24 | execute if score #user_trials_input random matches -2147483648..2147483647 run scoreboard players operation $trials random = #user_trials_input random 25 | execute if score #user_chance_input random matches -2147483648..2147483647 run scoreboard players operation $chance random = #user_chance_input random 26 | scoreboard players reset #user_trials_input random 27 | scoreboard players reset #user_chance_input random -------------------------------------------------------------------------------- /data/random/functions/private/load.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:private/load 2 | # 3 | # Sets up the scoreboard for RNG 4 | # 5 | # @private 6 | # @handles #minecraft:load 7 | 8 | # Definitions for Data-pack Helper Plus 9 | #define storage random:input 10 | #define storage random:output 11 | #define storage random:data 12 | 13 | # Create scoreboard objective and initialise LCG 14 | scoreboard objectives add random dummy 15 | execute unless score #lcg random = #lcg random store result score #lcg random run seed 16 | 17 | # Define constants 18 | scoreboard players set #3 random 3 19 | scoreboard players set #5 random 5 20 | scoreboard players set #7 random 7 21 | scoreboard players set #8 random 8 22 | scoreboard players set #9 random 9 23 | scoreboard players set #10 random 10 24 | scoreboard players set #100 random 100 25 | scoreboard players set #1000 random 1000 26 | scoreboard players set #10000 random 10000 27 | scoreboard players set #log(10) random 23026 28 | scoreboard players set #exp(-0.9)*65536 random 26645 29 | scoreboard players set #exp(-0.8)*65536 random 29447 30 | scoreboard players set #exp(-0.7)*65536 random 32544 31 | scoreboard players set #exp(-0.6)*65536 random 35967 32 | scoreboard players set #exp(-0.5)*65536 random 39750 33 | scoreboard players set #exp(-0.4)*65536 random 43930 34 | scoreboard players set #exp(-0.3)*65536 random 48550 35 | scoreboard players set #exp(-0.2)*65536 random 53656 36 | scoreboard players set #exp(-0.1)*65536 random 59299 37 | scoreboard players set #65536 random 65536 38 | scoreboard players set #lcg_a random 1630111353 39 | scoreboard players set #lcg_c random 1623164762 40 | scoreboard players set #lcg_m random 2147483647 41 | -------------------------------------------------------------------------------- /data/random/functions/choose.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:choose 2 | # 3 | # Outputs a random tag from a list 4 | # 5 | # @public 6 | # @input 7 | # storage random:input List 8 | # The list a tag is picked from 9 | # @output 10 | # storage random:output Tag 11 | # The tag that is chosen 12 | 13 | # Save scores and tags before modifying them 14 | execute if score $min random matches -2147483648..2147483647 run scoreboard players operation #user_min_input random = $min random 15 | execute if score $max random matches -2147483648..2147483647 run scoreboard players operation #user_max_input random = $max random 16 | execute if score $out random matches -2147483648..2147483647 run scoreboard players operation #user_out_value random = $out random 17 | 18 | # Choose random index 19 | scoreboard players set $min random 1 20 | execute store result score $max random if data storage random:input List[] 21 | function random:uniform 22 | scoreboard players operation #index random = $out random 23 | 24 | # Pick nth tag from the end of the list 25 | data modify storage random:data List set from storage random:input List 26 | execute if data storage random:data List[0] run function random:private/choose_loop 27 | 28 | # Clean up 29 | data remove storage random:data List 30 | execute unless score #user_min_input random matches -2147483648..2147483647 run scoreboard players reset $min random 31 | execute unless score #user_max_input random matches -2147483648..2147483647 run scoreboard players reset $max random 32 | execute unless score #user_out_value random matches -2147483648..2147483647 run scoreboard players reset $out random 33 | execute if score #user_min_input random matches -2147483648..2147483647 run scoreboard players operation $min random = #user_min_input random 34 | execute if score #user_max_input random matches -2147483648..2147483647 run scoreboard players operation $max random = #user_max_input random 35 | execute if score #user_out_value random matches -2147483648..2147483647 run scoreboard players operation $out random = #user_out_value random 36 | scoreboard players reset #user_min_input random 37 | scoreboard players reset #user_max_input random 38 | scoreboard players reset #user_out_value random -------------------------------------------------------------------------------- /data/random/functions/number_provider.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:number_provider 2 | # 3 | # Generates a random number using input from storage 4 | # 5 | # @public 6 | # @input 7 | # storage random:input 8 | # type: string 9 | # The probability law 10 | # Either "uniform", "binomial", "poisson" or "exponential" 11 | # min: int 12 | # (For uniform RNG) The minimum value 13 | # max: int 14 | # (For uniform RNG) The maximum value 15 | # n: int 16 | # (For binomial RNG) The number of Bernoulli trials 17 | # p: double 18 | # (For binomial RNG) The probability of each Bernoulli trial 19 | # lambda: float 20 | # For exponential RNG: The rate/inverse scale 21 | # For Poisson RNG: The expected value, a number between 0.1 and 10 - decimal values are supported but only the first decimal place is taken into account 22 | 23 | # Constant 24 | execute if data storage random:input {type: "constant"} run function random:private/number_provider/constant 25 | execute if data storage random:input {type: "minecraft:constant"} run function random:private/number_provider/constant 26 | 27 | # Uniform 28 | execute if data storage random:input {type: "uniform"} run function random:private/number_provider/uniform 29 | execute if data storage random:input {type: "minecraft:uniform"} run function random:private/number_provider/uniform 30 | execute unless data storage random:input type if data storage random:input min if data storage random:input max run function random:private/number_provider/uniform 31 | 32 | # Binomial 33 | execute if data storage random:input {type: "binomial"} run function random:private/number_provider/binomial 34 | execute if data storage random:input {type: "minecraft:binomial"} run function random:private/number_provider/binomial 35 | execute unless data storage random:input type unless data storage random:input min if data storage random:input n if data storage random:input p run function random:private/number_provider/binomial 36 | 37 | # Geometric 38 | execute if data storage random:input {type: "geometric"} run function random:private/number_provider/geometric 39 | execute if data storage random:input {type: "minecraft:geometric"} run function random:private/number_provider/geometric 40 | 41 | # Poisson 42 | execute if data storage random:input {type: "poisson"} run function random:private/number_provider/poisson 43 | execute if data storage random:input {type: "minecraft:poisson"} run function random:private/number_provider/poisson 44 | -------------------------------------------------------------------------------- /data/random/functions/poisson.mcfunction: -------------------------------------------------------------------------------- 1 | #> random:poisson 2 | # 3 | # Generates a random number using a Poisson distribution 4 | # 5 | # @public 6 | # @input 7 | # score $lambda random 8 | # The expected value with a scale of 10, a number between 1 and 100 9 | # @output 10 | # score $out random 11 | # The Poisson variate, rounded down to an integer in {0, 1, 2, 3, ...} 12 | 13 | # Save expected value as two scores 14 | scoreboard players operation #lambda_int random = $lambda random 15 | scoreboard players operation #lambda_int random /= #10 random 16 | scoreboard players operation #lambda_dec random = $lambda random 17 | scoreboard players operation #lambda_dec random %= #10 random 18 | 19 | # Make sure expected value is valid 20 | execute if score #lambda_int random matches ..-1 run scoreboard players set #lambda_int random 0 21 | execute if score #lambda_int random matches 11.. run scoreboard players set #lambda_int random 10 22 | execute if score #lambda_int random matches 0 if score #lambda_dec random matches 0 run scoreboard players set #lambda_dec random 1 23 | 24 | # Evaluate exp(-l). The result is a number between 0 and 1 (but not 0), we save it with a scale of 2147483648 25 | execute if score #lambda_int random matches 0 run scoreboard players set #exp(-l) random 32768 26 | execute if score #lambda_int random matches 1 run scoreboard players set #exp(-l) random 12054 27 | execute if score #lambda_int random matches 2 run scoreboard players set #exp(-l) random 4434 28 | execute if score #lambda_int random matches 3 run scoreboard players set #exp(-l) random 1631 29 | execute if score #lambda_int random matches 4 run scoreboard players set #exp(-l) random 600 30 | execute if score #lambda_int random matches 5 run scoreboard players set #exp(-l) random 221 31 | execute if score #lambda_int random matches 6 run scoreboard players set #exp(-l) random 81 32 | execute if score #lambda_int random matches 7 run scoreboard players set #exp(-l) random 30 33 | execute if score #lambda_int random matches 8 run scoreboard players set #exp(-l) random 11 34 | execute if score #lambda_int random matches 9 run scoreboard players set #exp(-l) random 4 35 | execute if score #lambda_int random matches 10 run scoreboard players set #exp(-l) random 2 36 | 37 | execute if score #lambda_dec random matches 0 run scoreboard players operation #exp(-l) random *= #65536 random 38 | execute if score #lambda_dec random matches 1 run scoreboard players operation #exp(-l) random *= #exp(-0.1)*65536 random 39 | execute if score #lambda_dec random matches 2 run scoreboard players operation #exp(-l) random *= #exp(-0.2)*65536 random 40 | execute if score #lambda_dec random matches 3 run scoreboard players operation #exp(-l) random *= #exp(-0.3)*65536 random 41 | execute if score #lambda_dec random matches 4 run scoreboard players operation #exp(-l) random *= #exp(-0.4)*65536 random 42 | execute if score #lambda_dec random matches 5 run scoreboard players operation #exp(-l) random *= #exp(-0.5)*65536 random 43 | execute if score #lambda_dec random matches 6 run scoreboard players operation #exp(-l) random *= #exp(-0.6)*65536 random 44 | execute if score #lambda_dec random matches 7 run scoreboard players operation #exp(-l) random *= #exp(-0.7)*65536 random 45 | execute if score #lambda_dec random matches 8 run scoreboard players operation #exp(-l) random *= #exp(-0.8)*65536 random 46 | execute if score #lambda_dec random matches 9 run scoreboard players operation #exp(-l) random *= #exp(-0.9)*65536 random 47 | 48 | # Draw random number using Knuth's method 49 | scoreboard players operation #L random = #exp(-l) random 50 | scoreboard players set #p random 2147483647 51 | scoreboard players set #k random -1 52 | execute if score $min random matches -2147483648..2147483647 run scoreboard players operation #user_min_input random = $min random 53 | execute if score $max random matches -2147483648..2147483647 run scoreboard players operation #user_max_input random = $max random 54 | function random:private/poisson_loop 55 | scoreboard players operation $out random = #k random 56 | 57 | # Clean up 58 | execute unless score #user_min_input random matches -2147483648..2147483647 run scoreboard players reset $min random 59 | execute unless score #user_max_input random matches -2147483648..2147483647 run scoreboard players reset $max random 60 | execute if score #user_min_input random matches -2147483648..2147483647 run scoreboard players operation $min random = #user_min_input random 61 | execute if score #user_max_input random matches -2147483648..2147483647 run scoreboard players operation $max random = #user_max_input random 62 | scoreboard players reset #user_min_input random 63 | scoreboard players reset #user_max_input random -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Random 2 | 3 | **Random** is a utility data pack for Minecraft 1.17+ that adds functions for random number generation and randomness-based predicates. 4 | 5 | ## Functions 6 | 7 | ### `random:uniform` 8 | 9 | Generates a random number between `$min` and `$max` using a linear congruential generator. 10 | The generated value is saved to score `$out random`. 11 | 12 | ```mcfunction 13 | scoreboard players set $min random 0 14 | scoreboard players set $max random 10 15 | function random:uniform 16 | ``` 17 | 18 | Note: The resulting distribution is not truly uniform for values of `$max`-`$min`+1 that do not divide ![2^31](https://render.githubusercontent.com/render/math?math=2^31). 19 | While this is insignificant in almost all cases, `random:true_uniform` implements a method that counters modulo-induced bias. 20 | 21 | ![Generating 10000 numbers in range 0-10](https://cdn.discordapp.com/attachments/925818091475202118/926850852709359616/unknown.png) 22 | 23 | ### `random:binomial` 24 | 25 | Generates a random number following a binomial distribution given parameters `$trials` and `$chance`. 26 | The generated value is saved to score `$out random`. 27 | 28 | ```mcfunction 29 | scoreboard players set $trials random 5 30 | scoreboard players set $chance 500000 31 | function random:binomial 32 | ``` 33 | 34 | ![Generating 10000 numbers with n=5 and p=0.5](https://cdn.discordapp.com/attachments/925818091475202118/925820827851698236/unknown.png) 35 | 36 | ### `random:geometric` 37 | 38 | Generates a random number following a geometric distribution given parameter `$chance`, the probability of each Bernoulli trial with a scale of 1,000,000,000. 39 | The distribution is supported on {1, 2, 3, ...} 40 | The generated value is saved to score `$out random`. 41 | 42 | ```mcfunction 43 | scoreboard players set $chance 400000000 44 | function random:geometric 45 | ``` 46 | 47 | ![Generating 10000 numbers with p=0.4](https://cdn.discordapp.com/attachments/925818091475202118/957630561965465610/unknown.png) 48 | 49 | ### `random:poisson` 50 | 51 | Generates a random number using a Poisson distribution given the expected value `lambda` with a scale of 10. 52 | The generated value is saved to score `$out random`. 53 | 54 | ```mcfunction 55 | scoreboard players set $lambda random 20 56 | function random:poisson 57 | ``` 58 | 59 | ![Generating 10000 Poisson variates with lambda=2.0](https://cdn.discordapp.com/attachments/925818091475202118/926851511345119262/unknown.png) 60 | 61 | ### `random:true_uniform` 62 | 63 | Generates a random number between `$min` and `$max` using a linear congruential generator and countering modulo-induced bias. 64 | The generated value is saved to score `$out random`. 65 | For low values of `$min` and `$max`, the bias is negligible and `random:uniform` should be used instead for efficiency. 66 | 67 | ```mcfunction 68 | scoreboard players set $min random 1 69 | scoreboard players set $max random 1000000000 70 | function random:true_uniform 71 | ``` 72 | 73 | ### `random:number_provider` 74 | 75 | Generates a random number from storage using a syntax similar to number providers. 76 | `type` can be `constant`, `uniform`, `binomial`, `geometric`, or `poisson`. 77 | The `minecraft` namespace can optionally be used. 78 | Like vanilla number providers, `type` can be omitted if `min`/`max` or `n`/`p` are specified. 79 | 80 | For type `constant`, the function will return the value of parameter `value`. 81 | 82 | ```mcfunction 83 | # Constant 84 | data merge storage random:input {type: "constant", value: 5} 85 | function random:number_provider 86 | ``` 87 | 88 | For type `uniform`, the function will return a random number between parameters `min` and `max` (inclusive). 89 | `type` is optional as long as `min` and `max` are specified. 90 | 91 | ```mcfunction 92 | # Uniform 93 | data merge storage random:input {type: "uniform", min: 1, max: 6} 94 | function random:number_provider 95 | ``` 96 | 97 | For type `binomial`, the function will return a random number following a binomial distribution with `n` trials of probability `p`. 98 | `type` is optional as long as `n` and `p` are specified. 99 | 100 | ```mcfunction 101 | # Binomial 102 | data merge storage random:input {type: "binomial", n: 10, p: 0.166666667d} 103 | function random:number_provider 104 | ``` 105 | 106 | For type `geometric`, the function will return a random number following a geometric distribution of parameter `p`. 107 | 108 | ```mcfunction 109 | # Geometric 110 | data merge storage random:input {type: "geometric", p: 0.2d} 111 | function random:number_provider 112 | ``` 113 | 114 | For type `poisson`, the function will return a Poisson variate of expected value `lambda`. Unlike `random:poisson`, no scale is expected for input. 115 | 116 | ```mcfunction 117 | # Poisson 118 | data merge storage random:input {type: "poisson", lambda: 5.0f} 119 | function random:number_provider 120 | ``` 121 | 122 | ### `random:choose` 123 | 124 | Chooses a random tag from storage list `random:input List` and saves it to storage tag `random:output Tag`. 125 | 126 | ```mcfunction 127 | data modify storage random:input List set value ["green", "yellow", "orange", "pink"] 128 | function random:choose 129 | tellraw @a {"nbt": "Tag", "storage": "random:output"} 130 | ``` 131 | 132 | ## Predicates 133 | 134 | ### `random:coin_toss` 135 | 136 | Has a 50% chance of evaluating to true. 137 | 138 | ```mcfunction 139 | execute if predicate random:coin_toss run say hi! 140 | ``` 141 | 142 | ```mcfunction 143 | # Simulating a coin toss 144 | execute store result score if predicate random:coin_toss 145 | execute if score matches 0 run say Heads 146 | execute if score matches 1 run say Tails 147 | ``` 148 | 149 | ### `random:score_fraction` 150 | 151 | Succeeds with a probability of `$a`/`$b`. 152 | 153 | ```mcfunction 154 | scoreboard players set $a random 7 155 | scoreboard players set $b random 12 156 | execute if predicate:score_fraction run say 7/12 157 | ``` 158 | 159 | ### `random:score_invert` 160 | 161 | Succeeds with a probability of 1/`$chance`. 162 | 163 | ```mcfunction 164 | scoreboard players set $chance random 6 165 | execute if predicate random:score_invert run say 1/6 166 | ``` 167 | 168 | ### `random:score_percentage` 169 | 170 | Succeeds with probability `$chance` in percents. At 0, the predicate always fails; at 100, it always succeeds. 171 | 172 | ```mcfunction 173 | scoreboard players set $chance random 5 174 | execute if predicate random:score_percentage run say 5% 175 | ``` 176 | 177 | ### `random:score_ppb` 178 | 179 | Succeeds with probability `$chance` in parts per billion. At 0, the predicate always fails; at 1,000,000,000, it always succeeds. 180 | 181 | ```mcfunction 182 | scoreboard players set $chance random 123456789 183 | execute if predicate random:score_ppb run say 12.3456789% 184 | ``` 185 | 186 | ## Version 187 | 188 | This data pack was designed for Minecraft: Java Edition 1.17 and works in 1.18 and 1.19 snapshots. 189 | The data pack format in `pack.mcmeta` is 10, but you can safely downgrade it to data pack formats used in previous game versions. 190 | 191 | Some functions/predicates work in versions before 1.17: 192 | 193 | | Function | Supported versions | 194 | |--------------------------|-----------------------------------------------------| 195 | | `random:uniform` | 1.13+ | 196 | | `random:binomial` | 1.17+ | 197 | | `random:geometric` | 1.17+ | 198 | | `random:poisson` | 1.13+ | 199 | | `random:number_provider` | 1.15+, 1.17+ if `type` is `binomial` or `geometric` | 200 | 201 | | Predicate | Version | 202 | |---------------------------|---------| 203 | | `random:coin_toss` | 1.15+ | 204 | | `random:score_inverse` | 1.17+ | 205 | | `random:score_percentage` | 1.17+ | 206 | | `random:score_ppb` | 1.17+ | 207 | 208 | Minecraft Random does not work in Minecraft: Bedrock Edition. 209 | --------------------------------------------------------------------------------