Jump to content
Dante Unbound: Share Bug Reports and Feedback Here! ×

Rng: Explanation, Theory, Algorithms & Practice


SonicSonedit
 Share

Recommended Posts

This feedback article/open letter will cover why RNG is flawed and how to fix RNG itself (without tokens or anything).

 

TL; DR:

Current RNG gives flawed resulsts (like 40% to get Bronco Prime Barrel from T3 cap and reduced chance for other items) and here is a solution (working program code included) how to fix it and make RNG nearly perfectly fair.

 

Theory
In Warframe, when we say RNG we don't actually mean random seed feed/scheldue/generating algorithm itself, but the system which determines what rewards we will obtain in general. In other words, the RNG itself is not what we need to fix, but how we use numbers which it provides: RNG is just RNG, it does what it does - spits out numbers randomly. But how we use them is a different story.

Lets assume we have a drop table
xFVYdYy.png
(this drop table is only for testing purposes and does not relate to actual reward table)

The RNG provided us with number 10. What does it mean? What do we apply it for? There are 2 most common RNG algorithms, and I will review both of them.

Simple RNG
This algorithm rolls a dice for every item in list and checks if item passed. If not, it rolls for next item and keeps on until we get a reward. If the end of the list is reached, it starts over.

Logic:
1) Roll a dice from 0 to 99.
2) Check if item chance is lower then rolled dice
3) If it is lower - select this item as a reward and exit!
4) If not, roll for next item in list.
5) If end of list is reached, start from first item in list.

FAQ:

("0..99? but 99 is not 100%! Why not 0..100??" You may ask. Well, 0..99 is actually 100 numbers (0 included). And also we compare if dice is LOWER (not lower or equal) than item chance. Therefore item with 1% will only pass for the dice value of 0, which has 1% when rolling 0..99)



Code:



code tag is going crazy. If anyone knows how can I make code readable - much appreciated.

procedure TSimpleRNG.Execute;
var
i: Integer;
RNGing: Boolean;
tempchance, tempresult: integer;
templabel:TLabel;
begin
TestsCount:=0;
for i:= 0 to 6 do // reseting test values
ItemResult:=0;

while not(Terminated) and not(Application.Terminated) do begin
Inc(TestsCount); // Tests Count +1
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('T3 Capture run #'+IntToStr(TestsCount)+':'); // debug info
RNGing:=True; // getting random reward is in progress
while (RNGing) and not(Terminated) and not(Application.Terminated) do begin
for i:= 0 to 6 do begin // going through rewards list
Randomize; // reset random seed
RNGResult:=Random(100); // get random value from 0 to 99 with new seed
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('Rolling Dice for item '+IntToStr(i)+': Item chance = '+IntToStr(ItemChance)+', rolled '+IntToStr(RNGResult)); // debug info
if RNGResult<ItemChance then begin // if item passed
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('Item '+IntToStr(i)+' was obtained from T3 capture run #'+IntToStr(TestsCount)+':'); // debug info
Inc(ItemResult); // amount of passed item obtained from void runs +1
RNGing:=False; // we got our random reward and can exit endless cycle now
Break; // exiting i loop
end;
Sleep(1); // 1msec delay to make sure next random seed IS random
end;
Synchronize(UpdateGUI); // updating GUI if needed
end;
end;
end;



Result:
IZUHcjf.png

Holly Dolly! Isn't this exactly what we see in-game? Do you know why you can build a palisade from Orthos Prime Handles? Because hello 40% of getting Orthos Prime Handle from T2 cap!

Theory:
Why this result is SO flawed?
Well, the reason is pretty obvious if you are familiar with probability theory. For people who a familiar: j3EWILf.png, so yeah, this pretty much explains it.
For people who are not familiar with it, I will try to explain it as accessibly as I can.
Lets assume we flip a coin. If we get heads, we take a reward and go away, if we get tails, we flip coin for the next reward. What is the chance of getting first reward? Obviously 50%. But what is the chance of getting the second reward? It's actually 25%. Why? Because there is 50% that we get head and take first reward and go away. And only if we do not take first reward, we have a chance to get second, by flipping a coin, hence reducing the chance of acquiring 2nd reward by half (Because we start from 1st reward every time). For 3rd reward the chance will be 12.5%, for 4th 6.25% and so on.

Summing things up:

If we use simple RNG algorithm, RNG will favor items that come first in list much much more then items in the end of list. Thats why the chance of getting newly added items (which are added in the end of reward list) is super low. Yes, I'm talking about Ember Prime parts here.

So, moving on.
There is another commonly used RNG algorithm, which I will call "Advanced RNG".

Advanced RNG
This algorithm first selects a dice size depending on highest item chance and then rolls a dice, checking which items have passed. Then it randomly selects an item from the passed items pool.

Logic:
1) Select dice size (for our drop table that will be 25).
2) Roll a dice from 0 to 24.
3) Check which items passed and add them to the "passed items" pool.
4) Pull random item for passed items pool.

Code:


procedure TAdvancedRNG.Execute;
var
i: Integer;
DiceSize: Integer;
PassedRewards: array [0..6] of integer;
PassedRewardsCount: Integer;
RewardWeight: array [0..6] of integer;
MinimalWeight: integer;
begin
TestsCount:=0;
for i:= 0 to 6 do // reseting test values
ItemResult:=0;

DiceSize:=0;
for i:= 0 to 6 do // determinating dice size to optimize algorithm
if ItemChance>DiceSize then
DiceSize:=ItemChance;

while not(Terminated) and not(Application.Terminated) do begin
Inc(TestsCount); // Tests Count +1
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('T3 Capture run #'+IntToStr(TestsCount)+':'); // debug info
PassedRewardsCount:=0; // passed rewards list is empty
Randomize; // reset random seed
RNGResult:=Random(DiceSize); // get random value from 0 to DiceSize. DiceSize is item rewards highest chance (25 probably).
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('Rolled: '+IntToStr(RNGResult)); // debug info
for i:= 0 to 6 do // going through rewards list
if RNGResult<ItemChance then begin // if item passed
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('Item '+IntToStr(i)+' passed!'); // debug info
PassedRewards[PassedRewardsCount]:=i; // adding item to passed rewards list
Inc(PassedRewardsCount); // passed rewards count +1
end;
Sleep(1); // 1msec delay to make sure next random seed IS random
Randomize; // reset random seed
RNGResult:=Random(PassedRewardsCount); // get random value from 0 to (passed rewards list size -1)
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('Item #'+IntToStr(PassedRewards[RNGResult])+' was selected!'); // debug info
Inc(ItemResult[PassedRewards[RNGResult]]); // amount of item (randomly selected from passed rewards list) obtained from void runs +1
Synchronize(UpdateGUI); // update GUI if needed
end;
end;



Result:
z7pwu9z.png

Well, this does look better. At least we can have a ton of forma now. But still, results are flawed. Why is that?
This is because all items have same chance of being pulled from passed rewards pool while some item have a much lower chance to be in passed items pool then others.
Lets say we rolled 20. Forma and Bronco Barrel have passed and then Bronco is pulled from passed items pool. Next time we rolled 7. Forma, Bronco Barrel, Bronco Receiver and Orthos Blade have passed. But guess what? We pulled Bronco Barrel from passed rewards pool!

Summing things up:

this algorithm favors large numbers.

But isn't there anything that can be done!? Maybe sacrafices of virgin Novas will appease RNG gods? Not really, but we can try and fix the algorithm itself.
So, the problem is: items which have a lower chance of being in passed items pool have a same chance to be pulled from this pool as items which pass almost every time. How can we fix it? We can try to pull items with lowest pass chance from passed items chance, but this is a bad idea. Lets assume we have item with 10% to pass and 9%. The will almost always pass together due to small selection space beetween 9% and 10% and we will always pull item with 9%, which will make item with 10% nearly extinct, it will actually have less then 1% of being rolled. So what else can we do?
We can introduce weights!
What weights? Item weights. Each item will have "weight" - the more item was pulled from passed item pool the "heavier" it will be. And every time we get an passed items pool, we filter it from the most heavy items.

Logic:
1) Select dice size (for our drop table that will be 25).
2) Roll a dice from 0 to 24.
3) Check which items passed and add them to the "passed items" pool.
4) Search for lowest weight of items within passed items pool and select this weight as minimal.
5) Remove all items which are above minimal weight from passed items pool.
6) Pull random item from filtered passed items pool.
7) Increase weight of pulled item.

Code:


procedure TAdvancedRNG.Execute;
var
i: Integer;
DiceSize: Integer;
PassedRewards: array [0..6] of integer;
PassedRewardsCount: Integer;
RewardWeight: array [0..6] of integer;
MinimalWeight: integer;
begin
TestsCount:=0;
for i:= 0 to 6 do // reseting test values
ItemResult:=0;

DiceSize:=0;
for i:= 0 to 6 do // determinating dice size to optimize algorithm
if ItemChance>DiceSize then
DiceSize:=ItemChance;

if WeightRewards then
for i:= 0 to 6 do // reset weights
RewardWeight:=0;

while not(Terminated) and not(Application.Terminated) do begin
Inc(TestsCount); // Tests Count +1
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('T3 Capture run #'+IntToStr(TestsCount)+':'); // debug info
PassedRewardsCount:=0; // passed rewards list is empty
Randomize; // reset random seed
RNGResult:=Random(DiceSize); // get random value from 0 to DiceSize. DiceSize is item rewards highest chance (25 probably).
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('Rolled: '+IntToStr(RNGResult)); // debug info
for i:= 0 to 6 do // going through rewards list
if RNGResult<ItemChance then begin // if item passed
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('Item '+IntToStr(i)+' passed!'); // debug info
PassedRewards[PassedRewardsCount]:=i; // adding item to passed rewards list
Inc(PassedRewardsCount); // passed rewards count +1
end;
if WeightRewards then begin // here come the weights!
MinimalWeight:=0; // reset minimal weight
for i:= 0 to PassedRewardsCount-1 do // determinating minimal weight
if (RewardWeight[PassedRewards]<MinimalWeight) or (MinimalWeight=0) then // if minimal weight is 0 (reseted) or above item weight, set it to item weight
MinimalWeight:=RewardWeight[PassedRewards];
i:=0;
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('Minimal weight: '+IntToStr(MinimalWeight)); // debug info then
while i<PassedRewardsCount do begin // didnt use for here because working with cycle control vars
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('Item '+IntToStr(PassedRewards)+' weight: '+IntToStr(RewardWeight[PassedRewards])); // debug info then
if RewardWeight[PassedRewards]>MinimalWeight then begin // remove everything which above minimal weight
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('Item '+IntToStr(PassedRewards)+' was removed due to overweight.'); // debug info then
move(PassedRewards[i+1], PassedRewards, (PassedRewardsCount-i-1)*SizeOf(PassedRewards[0])); // remove overweighted reward from passed rewards list
Dec(PassedRewardsCount); // decrease passed rewards counter
Dec(i);
end;
Inc(i);
end;
end;
Sleep(1); // 1msec delay to make sure next random seed IS random
Randomize; // reset random seed
RNGResult:=Random(PassedRewardsCount); // get random value from 0 to (passed rewards list size -1)
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('Item #'+IntToStr(PassedRewards[RNGResult])+' was selected!'); // debug info
Inc(ItemResult[PassedRewards[RNGResult]]); // amount of item (randomly selected from passed rewards list) obtained from void runs +1
if WeightRewards then
Inc(RewardWeight[PassedRewards[RNGResult]]); // increase weight of the rewards if weight are enabled
Synchronize(UpdateGUI); // update GUI if needed
end;
end;



Result:
W8miMx9.png

Well this does look better. But still, RNG does favor large numbers a lot if we use Advanced RNG, even if we add weights.
But wait...maybe we can also add some sort of weights or something for Simple RNG? Lets see!


Back to Simple RNG
So what was our problem with Simple RNG? Oh yeah it favored items which were first in list and hated items in the end of list. How can we fix it. Actually, quite simple: move item we just got to the end of the list! Lets try and see what happens.

Logic:
1) Roll a dice from 0 to 99.
2) Check if item chance is lower then rolled dice
3) If it is lower - select this item as a reward and exit!
4) If not, roll for next item in list.
5) If end of list is reached, start from first item in list.
6) move the reward we got to the very end of the list, without shifting elements which go before it.

For the last action (#6) I decided to draw a picture:
v9agV2P.png

Code:


A5Dr7Ke.png

procedure TSimpleRNG.Execute;
var
i: Integer;
RNGing: Boolean;
tempchance, tempresult: integer;
templabel:TLabel;
begin
TestsCount:=0;
for i:= 0 to 6 do // reseting test values
ItemResult:=0;

while not(Terminated) and not(Application.Terminated) do begin
Inc(TestsCount); // Tests Count +1
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('T3 Capture run #'+IntToStr(TestsCount)+':'); // debug info
RNGing:=True; // getting random reward is in progress
while (RNGing) and not(Terminated) and not(Application.Terminated) do begin
for i:= 0 to 6 do begin // going through rewards list
Randomize; // reset random seed
RNGResult:=Random(100); // get random value from 0 to 99 with new seed
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('Rolling Dice for item '+IntToStr(i)+': Item chance = '+IntToStr(ItemChance)+', rolled '+IntToStr(RNGResult)); // debug info
if RNGResult<ItemChance then begin // if item passed
if not(DontUpdateGUI) then form1.MemoLog.Lines.Add('Item '+IntToStr(i)+' was obtained from T3 capture run #'+IntToStr(TestsCount)+':'); // debug info
Inc(ItemResult); // amount of passed item obtained from void runs +1
RNGing:=False; // we got our random reward and can exit endless cycle now
if ShiftRewards then begin // here goes shifting!
if i<Length(ItemChance)-1 then begin // if item is NOT last in list
tempchance:=ItemChance;
tempresult:=ItemResult; // store item information in temp variables
templabel:=LabelItemResult;
move(ItemChance[i+1], ItemChance, (Length(ItemChance)-i-1)*SizeOf(ItemChance[0])); // shift chance array
ItemChance[Length(ItemChance)-1]:=tempchance; // restore last index (restore moved item chance)
move(ItemResult[i+1], ItemResult, (Length(ItemResult)-i-1)*SizeOf(ItemResult[0])); // shift result (obtained count) array
ItemResult[Length(ItemResult)-1]:=tempresult; // restore last index
move(LabelItemResult[i+1], LabelItemResult, (Length(LabelItemResult)-i-1)*SizeOf(LabelItemResult[0])); // shift GUI array
LabelItemResult[Length(ItemResult)-1]:=templabel; // restore last index
// it would be much better to simply create a class for item and move the class within array instead of each element individually, but im too lazy. maybe later.
end;
end;
Break; // exiting i loop
end;
Sleep(1); // 1msec delay to make sure next random seed IS random
end;
Synchronize(UpdateGUI); // updating GUI if needed
end;
end;
end;



Result:
RiSv5OX.png

Woah! This is nearly perfect result!
For reference, here are nominal values:
Bronco Prime Barrel: 30,875%
Bronco Prime Receiver: 12,35%
Forma: 30,875%
Forma: 6,175%
Orthos Prime Blade:12,35%
Emper Prime Chassis: 1,235%
Ember Prime Systems: 6,175%
FAQ:

Summ of all item chances: 81; 100/81=1,235 therefore all rewards amount should be 23,5% bigger than it's chance


Yeah, the numbers deviant a little, but they are very very close to perfect values.


Summing Everything Up
Can DE fix the RNG?
Yes, they surely can. They have everything they need now - even the source code for RNG algorithm.
What will it take?
They will have to store shifted rewards arrays on either client of server side. Preferably server.
How much of bytes is this?
This depends on how many rewards in reward list. For Void its about 15 items. Int32 has a size of 4 bytes. Therefore it will be 4*15*5=300 bytes for void drop tables.
Lorane_Airwing was kind enough to calculate that it will take 4,5gb to store all reward tables on server for 3m players (1722 bytes per player), check out his post: https://forums.warframe.com/index.php?/topic/166725-rng-explanation-theory-algorithms-practice/?p=1955576


RNG Test tool - both source code & exe: download

P.S.
Please let me know if you see any logic flaws, typos, etc!

Edited by SonicSonedit
Link to comment
Share on other sites

 

 

-snip-

 

Back to Simple RNG
So what was our problem with Simple RNG? Oh yeah it favored items which were first in list and hated items in the end of list. How can we fix it. Actually, quite simple: move item we just got to the end of the list! Lets try and see what happens.

Logic:
1) Roll a dice from 0 to 99.
2) Check if item chance is lower then rolled dice
3) If it is lower - select this item as a reward and exit!
4) If not, roll for next item in list.
5) If end of list is reached, start from first item in list.
6) move the reward we got to the very end of the list, without shifting elements which go before it.

 

-snip-

 

 

image.png

DE!

Edited by Namacyst
Link to comment
Share on other sites

For anybody who doesn't understand the code or just wants a suuuuper simplified explanation for his RNG fix idea:

 

When you get a reward, that reward becomes less likely for you to get again until other rewards have been received.

 

Super kudos to you, sir. This is the most thorough user idea I have ever seen submitted about anything ever. 

Link to comment
Share on other sites

From what i understand each mission simply uses a table shared between all missions of the same type, some even lack end mission reward tables! meaning we can get the estimated storage MUCH smaller :D

Using your estimate formula of   4*reward# = byte count I have calculated all the tables I'm aware of.( wiki helped a ton )

<void defense, NOTE apparently  these are changing to endless in U12? >
void defense - tier 1 - 7 rewards - 28 bytes
void defense - tier 2 - 7 rewards - 28 bytes
void defense - tier 3 - 7 rewards - 28 bytes

void survival - tier 1 - 10 rewards - 40 bytes
void survival - tier 2 - 11 rewards - 44 bytes
void survival - tier 3 - 8 rewards - 32 bytes

void capture - tier 1 - 8 rewards - 32 bytes
void capture - tier 2 - 9 rewards - 36 bytes
void capture - tier 3 - 8 rewards - 32 bytes

void exterminate - tier 1 - 7 rewards - 28 bytes
void exterminate - tier 2 - 7 rewards - 28 bytes
void exterminate - tier 3 - 6 rewards - 24 bytes

void mobile defense - tier 1 - 7 rewards - 28 bytes
void mobile defense - tier 2 - 6 rewards - 24 bytes
void mobile defense - tier 3 - 7 rewards - 28 bytes


OD defense - no tier - 7 rewards - 28 bytes

OD survival - no tier - 8 rewards - 32 bytes

OD capture - no tier - 25 rewards?< uses normal capture table? > - 100 bytes?

OD exterminate - no tier - no rewards?< uses normal exterminate table? > - 0 bytes?


< defense tiers appear to be seperated by faction, i assume here that they each have faction specific tables per tier >
endless defense - tier 1 grineer - 15 rewards - 60 bytes
endless defense - tier 2 grineer - 23 rewards - 92 bytes
endless defense - tier 3 grineer - 17 rewards - 68 bytes

endless defense - tier 1 corpus - 15 rewards - 60 bytes
endless defense - tier 2 corpus - 23 rewards - 23 bytes
endless defense - tier 3 corpus - 17 rewards - 68 bytes

endless defense - tier 1 infested - 15 rewards - 60 bytes
endless defense - tier 2 infested - 23 rewards - 23 bytes
endless defense - tier 3 infested - 17 rewards - 68 bytes


< possibly simplified, they may be seperated into 5 minute table intervals >
survivial - tier 1 - 29 rewards - 116 bytes
survivial - tier 2 - 33 rewards - 132 bytes
survivial - tier 3 - 34 rewards - 136 bytes


capture - no tiers - 25 rewards - 100 bytes
spy - no tiers - 24 rewards - 96 bytes


< some missions do not appear to have clear reward tables >
exterminate - no tiers - no rewards....?
rescue - no tiers - no rewards....?
deception - no tiers - no rewards....?
mobile defense - no tiers - no rewards....?
sabotage - no tiers - no rewards....?


1722 bytes total for all unique tables


1.68 kilobytes of data per player; so... with 3 million estimated players.... 4.80 gigabytes, MUCH smaller than my original calculations ( with the improper math )

Edited by Lorane_Airwing
Link to comment
Share on other sites

Lorane_Airwing

Yes, some tables are indeed shared. ODD used Xini reward table for a very long time. A lot of missions still use some shared tables (But all derelict mission have unique tables by now). And yes. some missions dont have reward tables.

Using your estimate formula of 4*reward#*5 = byte count I have calculated all the tables I'm aware of.( wiki helped a ton )

You misunderstood a little bit here. It wa 4*reward#*5 because there are 5 void mission types. So actually it's 4*rewardcount*missoncount. Edited by SonicSonedit
Link to comment
Share on other sites

You misunderstood a little bit here. It wa 4*reward#*5 because there are 5 void mission types. So actually it's 4*rewardcount*missoncount.

 

I'll go back and change the data than. I was a bit unsure what the 5 was for but decided to include it.

 

EDIT:

math has been updated and gives us a MUCH smaller number.

 

1.68 kilobytes per player, and around 5 gigs for all of them together. heck, if we wanted to hit my old calculation of 26 gigabytes warframe would need 16227962 players/accounts!

Edited by Lorane_Airwing
Link to comment
Share on other sites

All these proposed methods are completely insane.  Consider, if you have 4 items, one is 50% to drop, and the others are 25% to drop, are you going to make 5+ rolls to decide what you get?  Or are you going to say "Roll a 4 sided die.  1 or 2 get item A, 3 is B, and 4 is C?"

 

 

There's a much, much simpler way to get a purely linear and predictable drop,  with precisely one roll.  And given the way defense rewards are awarded - with a linear table, and a random stepping number, it's almost certainly what's already in use.

 

The method is this:  Have a rewards table.  Every item in the rewards table has a probability value.  This value is a simple integer - no percentages, no nothing.

 

When you make a roll, first you sum up all the values in the table.  Then you roll a number between 0 and that sum, and assign it to a variable.

 

Start at the top of the list.  Subtract that item's probability from your variable.  If your variable is now negative, that item is your reward.  If not, move on to the next item and repeat.

 

Unbelievably easy to implement, and behaves exactly as you'd expect.  To get the actual percentage of any particular drop in the table, just add up all probabilities, and divide the item's probability value by that.

 

No rolling for rolls, no meta-probability games.  Just a basic linear distribution innately equal to your listed values.

Edited by Phatose
Link to comment
Share on other sites

skimmed bc @ work but....

 

What about the other basic RNG algo that only has a single dice roll.

 

It doesn't use a 'pass check' to see if the dice is under the 'rarity value' of each item...and instead each item has a set range. if the dice value is within that range, that is always the reward.

 

EX:

 

0-2 = orthos prime blade

3-40 = forma BP

41-55 = ember p systems

56-98 = ember p helm

99 = forma

 

so, some single roll examples:

1 = orthos prime blade

5 = forma BP

99 = forma

 

etc...

Link to comment
Share on other sites

  • 1 month later...

What about the other basic RNG algo that only has a single dice roll.

 

Honestly, I appreciate OP's work, but, uh, this is how you do it. His RNG is... uh, ... awful. I'm sorry OP, but that's not how you do it.

$itemArray = Array(0, 0, 0, 0, 0);for($i = 0; $i < 10000; $i++) {    $rand = rand(0, 99); //Generates a value from 0 to 99. 100 different values.    if($rand < 1) {      //If it is 0, (1% of the time)        $itemArray[0] += 1;    } else if ($rand < 6) { //If it's less than 6, and not 0 (5% of the time, since 0 is already used.)        $itemArray[1] += 1;    } else if ($rand < 31) { //If it's less than 31, and not 0-6 (25% of the time, since 0-6 is already used.)        $itemArray[2] += 1;    } else if ($rand < 61) { //If it's less than 61, etc        $itemArray[3] += 1;    } else {                  //Else, 61-99 = 39        $itemArray[4] += 1;    }}

Finally: here is a trial of the above RNG after 10,000,000 cases. IHhRfNs.png

 

And, for a working example of the exact above code (which is written in PHP): http://goaggro.com/warframeGenome/rngTest.php

Edited by Zerrien
Link to comment
Share on other sites

Yeah, the topic is hillarious. I mean, "how to make broken RNG" is valid part, however "how to fix it"...

Anyways, devs said that problem is not how you select reward, problem is how you generate random number. I mean that "Random(100)" in OP post or "rand(0, 99)" in post above is just too slow. https://forums.warframe.com/index.php?/topic/128402-rng-algorithm-bugschanges/ It's highly arguable (for drops they can use such slow algorithm), but they closed that topic.

Edited by (PS4)vivan000
Link to comment
Share on other sites

Yeah, the topic is hillarious. I mean, "how to make broken RNG" is valid part, however "how to fix it"...

Anyways, devs said that problem is not how you select reward, problem is how you generate random number. I mean that "Random(100)" in OP post or "rand(0, 99)" in post above is just too slow. https://forums.warframe.com/index.php?/topic/128402-rng-algorithm-bugschanges/ It's highly arguable (for drops they can use such slow algorithm), but they closed that topic.

Thanks. I've been looking for that thread. Why is it not in Developer Workshop is beyond me... Anyway. Around the release of Ember Prime their algorithms got reverted to the "bugged" state where you get the same PP String over and over and over again while running T2 caps. Time to hit support

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...