Discuss Scratch
- gggamer24
-
Scratcher
49 posts
sort of an RNG?
im wondering if this is even possible, but im wondering if you could like generate a number through a rarity, like getting 10 would have the chances of 1 in 10. and this would work with all the numbers scratch could compute, from 1 through 1.8e308.
If its not clear enough, heres a “better” explanation: so, scratch would generate a value, with each value X having the chances of being generated being 1 in X value.
sorta like this(?):
If its not clear enough, heres a “better” explanation: so, scratch would generate a value, with each value X having the chances of being generated being 1 in X value.
sorta like this(?):
when green flag clickedidk if this would even work, even with the custom block. i hope you get the jist, and can find a solution. Thanks in advance!
set [x v] to (pick (x) (1) to (1.8e308))
- ploppiedog
-
Scratcher
24 posts
sort of an RNG?
This solution is pretty math-heavy, but it's one of the simplest.
Use a system like this:
Do a system like this, adjusting values for different rarities
Use a system like this:
set [num] to (pick random (1) to (6))
if <(num) > [3]> then
say [1 in 2]
else
if <(num) > [1]> then
say [1 in 3]
else
say [1 in 6]
end
Do a system like this, adjusting values for different rarities
Last edited by ploppiedog (May 19, 2026 16:41:47)
- gggamer24
-
Scratcher
49 posts
sort of an RNG?
This solution is pretty math-heavy, but it's one of the simplest.the problem with that is that i mean the variable should display the number based on its rarity, not the sprite saying it. so it would display 1 most often, 10 a bit less commonly, and 1 million almost never. each numbers rarity is based on the number itself. this is just saying rarities based on the number generator, and also in your example 4, 5, and 6 all share the same rarity, 1 in 2, and so do 2 and 3. also, its backwards (the numbers get rarer the smaller they are, instead they are supposed to get rarer the bigger they are).
Use a system like this:set [num] to (pick random (1) to (6))
if <(num) > [3]> then
say [1 in 2]
else
if <(num) > [1]> then
say [1 in 3]
else
say [1 in 6]
end
Do a system like this, adjusting values for different rarities
- dem_bot
-
Scratcher
1000+ posts
sort of an RNG?
im wondering if this is even possible, but im wondering if you could like generate a number through a rarity, like getting 10 would have the chances of 1 in 10. and this would work with all the numbers scratch could compute, from 1 through 1.8e308.You make a list of the weigths for every item. for example if you have
If its not clear enough, heres a “better” explanation: so, scratch would generate a value, with each value X having the chances of being generated being 1 in X value.
sorta like this(?):when green flag clickedidk if this would even work, even with the custom block. i hope you get the jist, and can find a solution. Thanks in advance!
set [x v] to (pick (x) (1) to (1.8e308))
1
10
89
theres a 1% chance you get item 1, a 10% chance for item 2 and a 89% chance for item 89
Every time you change the list, you have to either have a script go through it count everything up or do it by hand. In my example the total is 100.
You can then pick a random number between 1 and the total and store that in a variable.
You set a second variable to 1 as your counter.
repeat until <<(random number) < [0]> or <(i) > (length of [weights v] :: list)>>after this i is the item number of the thing you rolled.
change [random number v] by (()-(item (i) of [list v] :: list))
change [i v] by (1)
end
change [i v] by (-1)
If you have a second list of the variables you're choosing between, you can just pick item i of that second list.
- DragonBeast829
-
Scratcher
100+ posts
sort of an RNG?
Adding onto this, this is called weighted RNG and has a lot of applications in many places. For instance, loot tables defining what an enemy might drop when killed. Also, dem_bot's system only works for your purpose if all of the weights add up to 100, because weights are not percentages on their own, they're relative to each other.
- some1atskool
-
Scratcher
100+ posts
sort of an RNG?
the best way to do an RNG is with 2d lists, which scratch does not have and is NOT adding. SO you have to do a bunch of code, as @ploppiedog said
- dem_bot
-
Scratcher
1000+ posts
sort of an RNG?
Adding onto this, this is called weighted RNG and has a lot of applications in many places. For instance, loot tables defining what an enemy might drop when killed. Also, dem_bot's system only works for your purpose if all of the weights add up to 100, because weights are not percentages on their own, they're relative to each other.as I said, you have to count up everything and pick a random number from 1 to total. In my example I used 100 as total to make the maths easier to follow, but as long as the total is up to date, it's also fine to have a completely arbitrary total such as 387.44 million.
- gggamer24
-
Scratcher
49 posts
sort of an RNG?
so, im a little confused by your system and how it works. also, is there a way to make it so smaller numbers are more common, like instead of 89 being an 89% chance (in your example), could you make it 1 in 89? and if i were to go to the highest number scratch can handle, 1.8e308, once you get past even just 1,000,000,000 (i say “just” because 1 billion is nothing compared to 1.8e308), if im understanding correctly, the weights should start to become arbitrary. right? but as i said, im still a little confused so, i could be wrong.¯\_(ツ)_/¯Adding onto this, this is called weighted RNG and has a lot of applications in many places. For instance, loot tables defining what an enemy might drop when killed. Also, dem_bot's system only works for your purpose if all of the weights add up to 100, because weights are not percentages on their own, they're relative to each other.as I said, you have to count up everything and pick a random number from 1 to total. In my example I used 100 as total to make the maths easier to follow, but as long as the total is up to date, it's also fine to have a completely arbitrary total such as 387.44 million.
- g6g6g66g6g
-
Scratcher
100+ posts
sort of an RNG?
For starters, let me address the obvious: If the probabilities of picking each number is 1/n for each value n, then the probabilities will sum to more than 1 or 100%. You will need to scale down each of the probabilities so the total is 1 (i mean you don't have to, but then it's just a weighting, not a probability). Instead of getting 2 having a probability of 1/2, it will be 1/2 the probability of getting 1, whatever that probability happens to be.
That aside, the easiest and most versatile (if not slightly inaccurate) way to handle this in my opinion is to use an inverse cumulative distribution function (CDF). The CDF takes a number, e.g. 3, and outputs the probability of randomly selecting any number up to and including 3. There is a CDF for every probability distribution so I am talking specifically about the one for our case. The inverse CDF does the reverse, where we input a probability p between [0.0, 1.0] and output a number n where the probability of getting n or any number lower is equal to p. This is very useful since that means if we know the inverse CDF, we can just generate random numbers between 0 and 1 and transform them with the inverse CDF to get the randomly generated numbers we want.
A small issue is that the inverse CDF for the distribution you want doesn't exist, at least in any easy to use form. No matter, we can just use an approximation. This is the approximation we can use:
I won't fully explain how this approximation works right now, but if we look at an infinite series for the harmonic sum (where H(1) = 1, H(2) = 1 + 1/2 …), we get
H(n) ≈ ln(n) + 0.577215664 + 1/2n - 1/12n^2 …
Notice that the first two terms are used in the inverse CDF approximation, and the others would be included as well if it were easy to get the inverse of H(n), which it's not.
For an extra note, 0.577215664… is known as the Euler-Mascheroani constant and relates to things involving the harmonic series.
Now that we have the approximation, we have to apply the function to work with the max value of 1.8e308. Part of the reason I included complicated scratch code in my post when I usually wouldn't is to show that this is actually easy to do, because we only need to actually type out the natural log of 1.8e308 which is
ln(1.8 * 10^308)
= ln(1.8) * ln(10^308)
= ln(1.8) * 308 * ln(10)
= 416.8560742390062
After 10 million samples using the approximation and normalizing the frequency of getting 1, I got the following relative frequencies, trimmed down to the first 5 numbers:
DEMO
That aside, the easiest and most versatile (if not slightly inaccurate) way to handle this in my opinion is to use an inverse cumulative distribution function (CDF). The CDF takes a number, e.g. 3, and outputs the probability of randomly selecting any number up to and including 3. There is a CDF for every probability distribution so I am talking specifically about the one for our case. The inverse CDF does the reverse, where we input a probability p between [0.0, 1.0] and output a number n where the probability of getting n or any number lower is equal to p. This is very useful since that means if we know the inverse CDF, we can just generate random numbers between 0 and 1 and transform them with the inverse CDF to get the randomly generated numbers we want.
A small issue is that the inverse CDF for the distribution you want doesn't exist, at least in any easy to use form. No matter, we can just use an approximation. This is the approximation we can use:
define random zipf (max)
set [r v] to (pick random (0.0) to (1.0))
set [EM v] to [0.577215664]
set [output v] to ([floor v] of (([e^ v] of (((r) * (([ln v] of (max)::operators) + (EM))) - (EM))::operators) + (0.5))::operators)
I won't fully explain how this approximation works right now, but if we look at an infinite series for the harmonic sum (where H(1) = 1, H(2) = 1 + 1/2 …), we get
H(n) ≈ ln(n) + 0.577215664 + 1/2n - 1/12n^2 …
Notice that the first two terms are used in the inverse CDF approximation, and the others would be included as well if it were easy to get the inverse of H(n), which it's not.
For an extra note, 0.577215664… is known as the Euler-Mascheroani constant and relates to things involving the harmonic series.
Now that we have the approximation, we have to apply the function to work with the max value of 1.8e308. Part of the reason I included complicated scratch code in my post when I usually wouldn't is to show that this is actually easy to do, because we only need to actually type out the natural log of 1.8e308 which is
ln(1.8 * 10^308)
= ln(1.8) * ln(10^308)
= ln(1.8) * 308 * ln(10)
= 416.8560742390062
After 10 million samples using the approximation and normalizing the frequency of getting 1, I got the following relative frequencies, trimmed down to the first 5 numbers:
- 1
- 0.5356
- 0.3416
- 0.2602
- 0.2069
DEMO
Last edited by g6g6g66g6g (May 20, 2026 13:12:28)
- gggamer24
-
Scratcher
49 posts
sort of an RNG?
Alright, it seems like it works. it also seems like i was right about something: by the time you get to the large numbers, even what seems to be 1000, the differences between rarities is pretty arbitrary. but this is 1. a lot of math (holy yap) 2. really cool. and one more thing: i plan to use this for some sort of rng. like sol rng, but instead of auras, you roll numbers. there's a lot of numbers, and i wanted to fit all of them in. i wonder if its even possible to make it so the rarities of large numbers become less arbitrary. probably not. but who knows?
- gggamer24
-
Scratcher
49 posts
sort of an RNG?
For starters, let me address the obvious: If the probabilities of picking each number is 1/n for each value n, then the probabilities will sum to more than 1 or 100%. You will need to scale down each of the probabilities so the total is 1 (i mean you don't have to, but then it's just a weighting, not a probability). Instead of getting 2 having a probability of 1/2, it will be 1/2 the probability of getting 1, whatever that probability happens to be.um, also, which code in the demo is actually doing the calculation in your discussion post?
That aside, the easiest and most versatile (if not slightly inaccurate) way to handle this in my opinion is to use an inverse cumulative distribution function (CDF). The CDF takes a number, e.g. 3, and outputs the probability of randomly selecting any number up to and including 3. There is a CDF for every probability distribution so I am talking specifically about the one for our case. The inverse CDF does the reverse, where we input a probability p between [0.0, 1.0] and output a number n where the probability of getting n or any number lower is equal to p. This is very useful since that means if we know the inverse CDF, we can just generate random numbers between 0 and 1 and transform them with the inverse CDF to get the randomly generated numbers we want.
A small issue is that the inverse CDF for the distribution you want doesn't exist, at least in any easy to use form. No matter, we can just use an approximation. This is the approximation we can use:define random zipf (max)
set [r v] to (pick random (0.0) to (1.0))
set [EM v] to [0.577215664]
set [output v] to ([floor v] of (([e^ v] of (((r) * (([ln v] of (max)::operators) + (EM))) - (EM))::operators) + (0.5))::operators)
I won't fully explain how this approximation works right now, but if we look at an infinite series for the harmonic sum (where H(1) = 1, H(2) = 1 + 1/2 …), we get
H(n) ≈ ln(n) + 0.577215664 + 1/2n - 1/12n^2 …
Notice that the first two terms are used in the inverse CDF approximation, and the others would be included as well if it were easy to get the inverse of H(n), which it's not.
For an extra note, 0.577215664… is known as the Euler-Mascheroani constant and relates to things involving the harmonic series.
Now that we have the approximation, we have to apply the function to work with the max value of 1.8e308. Part of the reason I included complicated scratch code in my post when I usually wouldn't is to show that this is actually easy to do, because we only need to actually type out the natural log of 1.8e308 which is
ln(1.8 * 10^308)
= ln(1.8) * ln(10^308)
= ln(1.8) * 308 * ln(10)
= 416.8560742390062
After 10 million samples using the approximation and normalizing the frequency of getting 1, I got the following relative frequencies, trimmed down to the first 5 numbers:So it is unfortunately noticeably imperfect but hopefully it's still good enough for your use case. I'm not sure how exactly you intend to use 300 digit values with the floating point limitations but that's not my business. If you have any questions just let me know.
- 1
- 0.5356
- 0.3416
- 0.2602
- 0.2069
DEMO
- DragonBeast829
-
Scratcher
100+ posts
sort of an RNG?
The arbitrariness between larger rarities likely stems from floating-point precision errors. Really small numbers are not precise. You can test this really easily by trying this:
and getting… 0.30000000000000004? You can see why relying on very tiny numbers probably is not the best of ideas.
((0.2) + (0.1))
and getting… 0.30000000000000004? You can see why relying on very tiny numbers probably is not the best of ideas.
- g6g6g66g6g
-
Scratcher
100+ posts
sort of an RNG?
which code in the demo is actually doing the calculation in your discussion post?If you scroll to the right in sprite 1 you'll see a “pick random value” custom block, partially precalculated based on a max value of 1.8e308. I just combined the 3 lines from the discussion script into 1 line. Right below it there's a disconnected alternate script where you can input the max value when running the custom block.
i wonder if its even possible to make it so the rarities of large numbers become less arbitraryWhat does less arbitrary mean in this case? Less similar? If you can specify an alternate set of rarities and the math connecting them there's a good chance it can be turned into a generator
Last edited by g6g6g66g6g (May 23, 2026 03:10:53)
- Jlerpy
-
Scratcher
1000+ posts
sort of an RNG?
A method I'm fond of is to put all the outcomes in a list, from rarest to most common.
Then use
Then use
([Ceiling v] of ([sqrt v] of (pick random () to ())::operators)::operators)
- g6g6g66g6g
-
Scratcher
100+ posts
sort of an RNG?
Speaking to no one in particular, I think it has been made evidently clear that any method that requires putting every outcome in a list is something that cannot be done for this case and that we should let OP specify what distribution they want
- SuperGeoACE
-
Scratcher
64 posts
sort of an RNG?
so in gd there is a advanced random trigger which could help ill code it real quick based off that idea
- SuperGeoACE
-
Scratcher
64 posts
sort of an RNG?
so in gd there is a advanced random trigger which could help ill code it real quick based off that ideaDONE OMG no lists, 4/5 variables yeah yeah yeah
uses triangle numbers so in just 1-3, 1 is 60%, 2 is 30% and 3 is 10%
https://scratch.mit.edu/projects/1323862639/
move 10 steps
- Jackson2161
-
Scratcher
51 posts
sort of an RNG?
This solution is pretty math-heavy, but it's one of the simplest.i agree, it is more complex and looks more true RNG
Use a system like this:set [num] to (pick random (1) to (6))
if <(num) > [3]> then
say [1 in 2]
else
if <(num) > [1]> then
say [1 in 3]
else
say [1 in 6]
end
Do a system like this, adjusting values for different rarities
- 6767super
-
Scratcher
1 post
sort of an RNG?
can you send a full example from one of your games it would make it a lot easier
- gggamer24
-
Scratcher
49 posts
sort of an RNG?
OK…………….. this thread has gotten alot of attention i have been apperently unaware about, and let me clear a few things up:
1. when i say arbitrary, i indeed mean less similar, like for example 1e+80 is basically the same rarity as 1e+80 + 1.
2. the distribution i want is specified in the first post, but i dont know what it is called, if it even has a name. it goes like this: 2: 1 in 2, 50%, 3: 1 in 3, 33%, 4: 1 in 4, 25%, 5: 1 in 5, 20%, etc. getting 100 would be a 1 in 100 chance, 1%. getting 50 would be 2%. once we get to even a small number like 75 or even 50, the rarities become “arbitrary”.
3. i like the GD reference, SuperGeoACE.
hope this clears up a bunch of stuff!
1. when i say arbitrary, i indeed mean less similar, like for example 1e+80 is basically the same rarity as 1e+80 + 1.
2. the distribution i want is specified in the first post, but i dont know what it is called, if it even has a name. it goes like this: 2: 1 in 2, 50%, 3: 1 in 3, 33%, 4: 1 in 4, 25%, 5: 1 in 5, 20%, etc. getting 100 would be a 1 in 100 chance, 1%. getting 50 would be 2%. once we get to even a small number like 75 or even 50, the rarities become “arbitrary”.
3. i like the GD reference, SuperGeoACE.
hope this clears up a bunch of stuff!