Jordan Navarro
Ph.D. Student
University of Illinois
Urbana-Champaign
jmn5@illinois.edu
2016
The information included in this post is for educational purposes only. Any material on this webpage may not be reproduced, retransmitted, or redisplayed other than for personal or educational use.
Random number generation is a process which generates a sequence of numbers or symbols that cannot be reasonably predicted better than by a random chance. Warframe uses Donald Knuth’s variation of a linear congruential generator (LCG) as a base for its random number generation algorithm and scales from rarity weights assigned by Digital Extremes that influence the drop chances of items in DropTables
and MissionDecks
. The recursive aspect of the algorithm only applies to missions in which players receive rewards over time, such as Defense and Survival. Other mission types simply use the process explained below.
Warframe uses four rarity weights in its random number generation algorithm. These weights are uniform across DropTables
and MissionDecks
, except for any table that uses FixedWeights
(weights of fixed values that may deviate from the standard).
Rarity | Weight | Percentage |
---|---|---|
COMMON | 0.755 | 75.50% |
UNCOMMON | 0.22 | 22.00% |
RARE | 0.02 | 2.00% |
LEGENDARY | 0.005 | 0.50% |
The independent drop chance of an item can be computed through the following equation, with Rarity
being COMMON, UNCOMMON, RARE, or LEGENDARY:
Rarity Drop Chance Per Item = Base Rarity Drop Chance / Number of Rarity Items
Exercise 1. This exercise demonstrates the formulae with a test case of 8 COMMON, 6 UNCOMMON, 4 RARE, and 2 LEGENDARY items.
Rarity | Weight | Count | Quotient | Drop Chance Per Item |
---|---|---|---|---|
COMMON | 0.755 | 8 | 0.094375 | 9.44% |
UNCOMMON | 0.22 | 6 | 0.03666666666 | 3.67% |
RARE | 0.02 | 4 | 0.005 | 0.50% |
LEGENDARY | 0.005 | 2 | 0.0025 | 0.25% |
Normalization refers to the division of available values in order that rarity weights of all items within a table fall between zero and one and amount to one. Normalization occurs when at least one of the rarity weights is not present within a DropTable
or MissionDeck
.
Exercise 1. This exercise demonstrates the normalization procedure with a test case of 1 COMMON, 1 UNCOMMON, 1 RARE, and 0 LEGENDARY items. The value of any rarity weight that does not exist within a table is zero.
Rarity | Weight | Normalization Procedure | Count | Quotient | Drop Chance Per Item |
---|---|---|---|---|---|
COMMON | 0.755 | 0.755 / (0.755 + 0.22 + 0.02) | 1 | 0.75879396984 | 75.88% |
UNCOMMON | 0.22 | 0.22 / (0.755 + 0.22 + 0.02) | 1 | 0.22110552763 | 22.11% |
RARE | 0.02 | 0.02 / (0.755 + 0.22 + 0.02) | 1 | 0.02010050251 | 2.01% |
LEGENDARY | 0 | 0 / (0.755 + 0.22 + 0.02) | 0 | 0 | 0.00% |
Attenuation is a variable exclusive to DropTables
. The boolean variable OverrideLevelAdjustedBiasAtten
determines whether attenuation is present within a DropTable
or not. Attenuation is defined as "the reduction of the force, effect, or value of something." As the value of attenuation increases, the drop chance of the item it impacts should decrease. However, due to the insignificance of its set value (0.5) and the fact that it impacts DropTables
globally rather than individually across items, it is impossible to determine if it has a noticeable effect at all.
Bias is a variable exclusive to DropTables
. Bias is applied to individual items within DropTables
. Bias is defined as "a feature of a statistical technique or of its results whereby the expected value of the results differs from the true underlying quantitative parameter being estimated." The intended purpose of bias is to unequally weigh items within DropTables
(through a positive (+) or negative (−) value change), even if said items have identical rarity weights. In Warframe, as the value of bias increases, the drop chance of an item decreases. Additionally, because bias scales from the rarity weight that the item it is impacting is assigned to, items with rarity weights of a higher value will be reduced more drastically, depending on the amount of bias which is present. This is evident from the following tables:
Specter | Mod | Drop Chance | Bias | Count | Observed |
---|---|---|---|---|---|
Feyarch Specter | Shotgun Amp | 45.83% | 0.05 | 22 | 52.38% |
Feyarch Specter | Empowered Blades | 4.17% | 0 | 3 | 7.14% |
Feyarch Specter | Final Harbinger | 45.83% | 0.1 | 14 | 33.33% |
Feyarch Specter | High Noon | 4.17% | 0 | 3 | 7.14% |
Specter | Mod | Drop Chance | Bias | Count | Observed |
---|---|---|---|---|---|
Knave Specter | Pistol Amp | 45.83% | 0.05 | 60 | 53.57% |
Knave Specter | Growing Power | 4.17% | 0 | 4 | 3.57% |
Knave Specter | Blind Justice | 45.83% | 0.1 | 43 | 38.39% |
Knave Specter | Crimson Dervish | 4.17% | 0 | 5 | 4.46% |
Specter | Mod | Drop Chance | Bias | Count | Observed |
---|---|---|---|---|---|
Orphid Specter | Stand United | 30.56% | 0.05 | 29 | 27.62% |
Orphid Specter | Brief Respite | 30.56% | 0 | 51 | 48.57% |
Orphid Specter | Atlantis Vulcan | 30.56% | 0.1 | 17 | 16.19% |
Orphid Specter | Crossing Snakes | 8.33% | 0 | 8 | 7.62% |
rewardSeed
is a variable exclusive to MissionDecks
, and its function is to determine the missionReward
players receive at the end of a mission. rewardSeeds
are given to the host, and members of the host’s group receive the sessionId
in order to participate in the same session. You will only receive a rewardSeed
when your client needs to distribute it to players in a group (as the host). This means that you will receive a rewardSeed
if you begin a Public, Friends Only, or Invite Only session. But if you begin a Solo session, then you will not be given a rewardSeed
. Despite the SRand
variable (the seeding for the random number generator which generates a pseudo-random integer between 0 and RAND_MAX) being different for each player, each player will always receive the same missionReward
as the host because of their identical sessionIds
.
This generates text simulations of an integer seeded by an SRand variable based upon time. The following is my implementation in C:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main ()
{
int n = 0;
printf ("NULL SRand:\t %d\n", rand ());
srand (time (0));
for (n = 0; n <= 5; n++)
{
printf ("SRand seeded with:\t %d\n", rand ());
}
return 0;
}
This generates text simulations of weighted random number generation based upon one million instances. Initial values are set such that it emulates the Warframe random number generation algorithm. The following is my implementation in PHP:
<?php
function WarframeRNG() {
$Uncommon = 0.22 * 1000;
$Rare = 0.02 * 1000;
$Legendary = 0.005 * 1000;
$RarityClass = array();
for ($i = 0; $i <= 1000; $i++) {
if ($i <= $Legendary) {
$RarityClass[$i] = "LEGENDARY";
} else if ($i <= $Legendary + $Rare) {
$RarityClass[$i] = "RARE";
} else if ($i <= $Legendary + $Rare + $Uncommon) {
$RarityClass[$i] = "UNCOMMON";
} else {
$RarityClass[$i] = "COMMON";
}
}
$Rarity = mt_rand(1, 1000);
return ($RarityClass);
}
$RarityArray = WarframeRNG();
$i = 0;
$CommonDrop = 0;
$UncommonDrop = 0;
$RareDrop = 0;
$LegendaryDrop = 0;
$times_to_run = 1000000;
$array = array();
while ($i++ < $times_to_run) {
$RarityClass = $RarityArray[mt_rand(1, 1000)];
if ($RarityClass == "COMMON") {
$CommonDrop = $CommonDrop + 1;
} else if ($RarityClass == "UNCOMMON") {
$UncommonDrop = $UncommonDrop + 1;
} else if ($RarityClass == "RARE") {
$RareDrop = $RareDrop + 1;
} else if ($RarityClass == "LEGENDARY") {
$LegendaryDrop = $LegendaryDrop + 1;
}
}
echo "COMMON: " . $CommonDrop . ", ";
echo "UNCOMMON: " . $UncommonDrop . ", ";
echo "RARE: " . $RareDrop . ", ";
echo "LEGENDARY: " . $LegendaryDrop;
?>
Copyright © Jordan Navarro. All rights reserved.