getting proportional random numbers possible?
by Isaac Barbosa · in Torque Game Builder · 03/03/2009 (9:02 am) · 7 replies
Hi,
I don´t know if this is possible, and even if this is the correct way to ask. I want to get a random number from a given quantity using getRandom(). Lets say I use
to get a random number between 0 to 99, that works fine. But what if I want to have a 10% of chances to get a number from 0 to 9 instead of the whole 100 chance?
Purpose, I want to set a balanced letter proportion for a word game and I want to balance the number of letter the game grid has.
So I will state something like this in a function that I will call several times, up to 100
I undestand than this way there is a 75% of chance to get an "A" and a 25% of chance to get a "B", but in the practice it will be that most of times I get only "A"
I hope this makes any sense
I don´t know if this is possible, and even if this is the correct way to ask. I want to get a random number from a given quantity using getRandom(). Lets say I use
%pickANumber = getRandom(99);
to get a random number between 0 to 99, that works fine. But what if I want to have a 10% of chances to get a number from 0 to 9 instead of the whole 100 chance?
Purpose, I want to set a balanced letter proportion for a word game and I want to balance the number of letter the game grid has.
So I will state something like this in a function that I will call several times, up to 100
if(%pickANumber == "1" || %pickANumber == "2" || %pickANumber == "3")
%chosenLetter = "A";
else if(%pickANumber == "4")
{
%chosenLetter = "B";
}I undestand than this way there is a 75% of chance to get an "A" and a 25% of chance to get a "B", but in the practice it will be that most of times I get only "A"
I hope this makes any sense
#2
That gave some problems in the practice so I keep with my actual code, I guess it is the same thing:
Thanks
03/04/2009 (8:19 am)
Hi Phillip,That gave some problems in the practice so I keep with my actual code, I guess it is the same thing:
%color = getRandom(100);
if(%color == 0 || %color == 1 || %color == 2 || %color == 3 || %color == 4 || %color == 5 || %color == 6 || %color == 7 || %color == 8 || %color == 9)
{
%color = "A";
%thisletter = $letter[0];
%isprotected = false;
%colorGroup = %quedado;
}
if(%color == 10 || %color == 11 || %color == 12)
{
%color = "B";
%thisletter = $letter[1];
%isprotected = false;
%colorGroup = %quedado;
}
if(%color == 13 || %color == 14 || %color == 15)
{
%color = "C";
%thisletter = $letter[2];
%isprotected = false;
%colorGroup = %quedado;
}
if(%color == 16 || %color == 17 || %color == 18 || %color == 19 || %color == 20)
{
%color = "D";
%thisletter = $letter[3];
%isprotected = false;
%colorGroup = %quedado;
}
if(%color == 21 || %color == 22 || %color == 23 || %color == 24 || %color == 25 || %color == 26 || %color == 27 || %color == 28 || %color == 29)
{
%color = "E";
%thisletter = $letter[4];
%isprotected = false;
%colorGroup = %quedado;
}
if(%color == 30 || %color == 31)
{
%color = "F";
%thisletter = $letter[5];
%isprotected = false;
%colorGroup = %quedado;
}
if(%color == 32 || %color == 33 || %color == 34)
{
%color = "G";
%thisletter = $letter[6];
%isprotected = false;
%colorGroup = %quedado;
}
if(%color == 35 || %color == 36)
{
%color = "H";
%thisletter = $letter[7];
%isprotected = false;
%colorGroup = %quedado;
}
and so on... until get 100Thanks
#3
The point of this is that if you're going to give a letter, the most common ones should come first in your check, then return the value as soon as you find it. Also, it might just be good to have a FIFO buffer of upcoming letters so that you don't get hit with a request for 7 letters suddenly, not that it should be a problem with that small number.
Source for individual number probabilities:
H. Beker and F. Piper, Cipher Systems, Wiley-Interscience, 1982.
Source for the cumulative:
Jason Ravencroft and Microsoft Office Excel 2007. =D
03/04/2009 (2:13 pm)
That's a whole lot of 'if' statements. If you don't mind my saying, you may want to make it an incrementing case statement or incrementing if statements. I took the liberty of looking at the distribution of letters from a site and they have some rounding problems, but you get the point.LETTER Unique% Cumulative % E 12.702 12.702 T 9.056 21.758 A 8.167 29.925 O 7.507 37.432 I 6.996 44.428 N 6.749 51.177 S 6.327 57.504 H 6.094 63.598 R 5.987 69.585 D 4.253 73.838 L 4.025 77.863 C 2.782 80.645 U 2.758 83.403 M 2.406 85.809 W 2.36 88.169 F 2.228 90.397 G 2.015 92.412 Y 1.974 94.386 P 1.929 96.315 B 1.492 97.807 V 0.978 98.785 K 0.772 99.557 J 0.153 99.71 X 0.15 99.86 Q 0.095 99.955 Z 0.074 100.029
The point of this is that if you're going to give a letter, the most common ones should come first in your check, then return the value as soon as you find it. Also, it might just be good to have a FIFO buffer of upcoming letters so that you don't get hit with a request for 7 letters suddenly, not that it should be a problem with that small number.
Source for individual number probabilities:
H. Beker and F. Piper, Cipher Systems, Wiley-Interscience, 1982.
Source for the cumulative:
Jason Ravencroft and Microsoft Office Excel 2007. =D
#4
which requires a little bit more programming up-front,
but is quite flexible once you've done that.
Basically you declare each value you'd like to have and give it a "weight".
If you declare two items with the same weight, they have the same probability of being returned. You can picture it as you're putting a bunch of marbles of different colors in a bag, and the weight is the number of marbles of that color you put in. Except the bag is re-filled every time you ask for a marble.
So for example to set up say the scrabble tile probabilities,
you would set K, J, X, Q, and Z all to weight 1,
then B, C, M, P, F, H, V, W, Y, <blank> all to weight 2,
then G to 3, and so on.
here's the code.
and here's an example run where A, B, and C have weight 1, and D has weight 3:
03/04/2009 (3:05 pm)
Here's another approach to getting weighted random values,which requires a little bit more programming up-front,
but is quite flexible once you've done that.
Basically you declare each value you'd like to have and give it a "weight".
If you declare two items with the same weight, they have the same probability of being returned. You can picture it as you're putting a bunch of marbles of different colors in a bag, and the weight is the number of marbles of that color you put in. Except the bag is re-filled every time you ask for a marble.
So for example to set up say the scrabble tile probabilities,
you would set K, J, X, Q, and Z all to weight 1,
then B, C, M, P, F, H, V, W, Y, <blank> all to weight 2,
then G to 3, and so on.
here's the code.
function ensureRandomItemManager()
{
if (!isObject(gRandomItemManager))
{
new ScriptObject(gRandomItemManager);
if (isObject(MissionCleanup))
{
MissionCleanup.add(gRandomItemManager);
gRandomItemManager.numItems = 0;
}
}
}
function clearRandomItems()
{
ensureRandomItemManager();
gRandomItemManager.numItems = 0;
}
function declareRandomItem(%itemName, %itemWeight)
{
ensureRandomItemManager();
%n = gRandomItemManager.numItems;
gRandomItemManager.itemName [%n] = %itemName;
gRandomItemManager.itemWeight[%n] = %itemWeight;
gRandomItemManager.weightsNeedNormalizing = true;
gRandomItemManager.numItems += 1;
}
function getRandomItem()
{
ensureRandomItemManager();
if (gRandomItemManager.weightsNeedNormalizing)
{
gRandomItemManager.weightsNeedNormalizing = false;
%totalWeight = 0;
for (%n = 0; %n < gRandomItemManager.numItems; %n++)
{
gRandomItemManager.itemWeightCumulative[%n] = gRandomItemManager.itemWeight[%n] + %totalWeight;
%totalWeight += gRandomItemManager.itemWeight[%n];
// echo(gRandomItemManager.itemName[%n] SPC gRandomItemManager.itemWeight[%n] SPC gRandomItemManager.itemWeightCumulative[%n]);
}
gRandomItemManager.totalWeight = %totalWeight;
}
%rand = getRandom(0, gRandomItemManager.totalWeight - 1);
for (%n = 0; %n < gRandomItemManager.numItems; %n++)
{
if (%rand < gRandomItemManager.itemWeightCumulative[%n])
{
return gRandomItemManager.itemName[%n];
}
}
error("something went wrong.");
return "";
}
function testRandomItems(%iterations)
{
%totals["A"] = 0;
%totals["B"] = 0;
%totals["C"] = 0;
%totals["D"] = 0;
clearRandomItems();
declareRandomItem("A", 1);
declareRandomItem("B", 1);
declareRandomItem("C", 1);
declareRandomItem("D", 3);
for (%n = 0; %n < %iterations; %n++)
{
%item = getRandomItem();
%totals[%item] += 1;
// echo(%item);
}
echo("A -" SPC %totals["A"]);
echo("B -" SPC %totals["B"]);
echo("C -" SPC %totals["C"]);
echo("D -" SPC %totals["D"]);
}and here's an example run where A, B, and C have weight 1, and D has weight 3:
==>testRandomItems(6000); A - 996 B - 1021 C - 992 D - 2991
#5
For the purpose I´m pursuing I will try something with this.
Orion,
That code seems pretty interesting, I should study it to see what can be useful.
Thanks guys!
03/04/2009 (3:46 pm)
Jason,For the purpose I´m pursuing I will try something with this.
Orion,
That code seems pretty interesting, I should study it to see what can be useful.
Thanks guys!
#6
That should be a lot faster to tune and use.
03/04/2009 (4:03 pm)
I'll chime in for fun. Why not just make a letter string and randomly pull from it? Something like:%letters = "AAAAAABBBCCCCCCDDEEEEEEEFFFFGGHHHHH"; // etc... %choice = %letters[getRandom(0,strlen(%letters) - 1)];
That should be a lot faster to tune and use.
#7
Thanks Chris,
this did the trick. I pull a random letter from the string and then I update the string for a new pick up if needed.
04/13/2009 (8:34 am)
I forgot to say Thanks.Thanks Chris,
this did the trick. I pull a random letter from the string and then I update the string for a new pick up if needed.
Associate Phillip O'Shea
Violent Tulip
%num = getRandom(); if ( %num >= 0 && %num <= 0.1 ) { // 0-10% } else if ( %num > 0.1 && %num <= 0.2 ) { // 10%-20% } else if ( %num > 0.2 && %num <= 0.5 ) { // 20%-50% } else if ( %num > 0.5 && %num <= 1.0 ) { // 50%-100% }