# Calculating probabilities for a custom drop table system

I have a "drop table" / "loot table" / "item table" / "whatever you want to call it" system and I need to solve two Problems. Apologies in advance for the text wall :/

The Problems:

1. Calculate the probability of pulling a specific item from a table
2. Calculate the probability of pulling ANY item from a table with a specific tag (such as "Epic", "Rare", "Weapon", "Sword", "Currency", etc)

A few details about the system:

1. Tables are setup with a certain number of 'Slots' and 'Rolls'
2. Slots determines the total number of unique items that can be dropped from the table
3. Rolls determines how many times we 'pull' an item out of the table
4. Each row within a table will drop one of a pre-calculated set of items
5. Each row can be marked as 'Guaranteed', 'Random' or both (more on that in a bit)
6. Rows have a 'MaxRollsToConsume' field (0 == infinite rolls), and a Weight field (used for weighted randomness, 0 Weight = never pulled)

And a bit of pseudo code for how we actually pull items out of the table

create a guaranteed set of rows
create a random pool of rows
create a result with a set number of slots available to fill

(note: adding an item to the result will only fill a slot if that item does not already exist in the result)

foreach row in table
if row is guaranteed, then add to guaranteed set
if row is random, then add to random pool

foreach row in guaranteed set
pull item out of row and add it to result
consume a roll

while there are rolls remaining and empty slots in the result
select a row from the random set using weighted randomness and respecting the MaxRollsToConsume field
pull item out of row and add it to result
consume a roll
if this row has reached its max rolls then remove it from the random pool

while there are rolls remaining
select an item from the current result using weighted randomness and respecting the MaxRollsToConsume field
add the item to the result
consume a roll

return the result


I understand how to calculate the probabilities for the 'Guaranteed' rows because, well, they are events that are guaranteed to happen so it's pretty easy to calculate.

Where I'm falling short is on how to calculate the 'Random' rows (especially with respect to the MaxRollsToConsume field) and only pulling a certain number of times. For example, I have 5 random rows, but only 2 Rolls to consume. How do I calculate the probability of an item being pulled from one of the those 2 Rolls while also taking into account how many Rolls are allowed per row?

I'm fairly confident that if I can solve Problem 1 with some help then I'll be able to solve Problem 2 on my own. Any help is appreciated and thanks in advance! If anything is unclear or more info is needed please let me know! :)

• For the last section, what weight do we use when selecting items from the current result? If an item in the current result came from a Guaranteed row, does it still have a weight associated with it? And if we pick an item from the result with weight 1, and add a copy of it to the result, does that item now effectively have weight 2 for the next roll, because the current result contains two copies that weigh 1 each? Commented Nov 10, 2020 at 21:19
• @DMGregory I edited my question to be a bit more explicit I hope "what weight do we use when selecting items from the current result?" We use the Weight field from the Row that the item was first pulled from, although I'm not sure why it matters as long as each item in the result has an associated Weight? "If an item in the current result came from a Guaranteed row, does it still have a weight associated with it" Yes, see above answer Commented Nov 10, 2020 at 22:15
• "And if we pick an item from the result with weight 1, and add a copy of it to the result, does that item now effectively have weight 2 for the next roll, because the current result contains two copies that weigh 1 each?" No, the weight of an item within the result never changes Sorry, needed two comments to say it all Commented Nov 10, 2020 at 22:16

I devised an answer based on my understanding here it is.

slots: total number of unique items in a table
rolls: maximum pull count from a table

rows = [[row1], [row2], ...]
# row 1
rows[0] = [g_or_r, MaxRollsToConsume, weight_change, weight_constant, items...]

# rows[0][0] = 0 => guaranteed
# rows[0][0] = 1 => random
# rows[0][0] = 2 => (not random and not guaranteed)

MaxRollsToConsume = 3 #if it's 0, you can't pull from the row

result = [ ] #where the pulled items will be at the end.
slot = 4 #how many items should result have

for i in rows.length:
#you have rolls, available slot, rolls to consume
#and this is a guaranteed row.
if(rolls > 0 and slot > 0 and rows[i][1] > 0 and rows[i][0] == 0):
#append a random item from the row
result.append(rows[i][random(4, rows[0].length)])
rolls -= 1
slot -= 1
rows[i][1] -= 1 # row can consume n-1 roll

# same but this row is random
elif(rolls > 0 and slot > 0 and rows[i][1] > 0 and rows[i][0] = 1):

#decrease weight. If the decreased weight is smaller than 5,
#choose an item from the row randomly
#and increase weight to its initial state.
row[i][2] -= random(1,5)
if(row[i][2]<5):
result.append(rows[i][random(4, rows[0].length)])
row[i][2] = row[i][3] #change the weight to its initial state
rolls -= 1
slot -= 1
rows[i][1] -= 0
if(rows[i][1] == 0):
rows[i][0] = 3 #removed from the random rows
else:
#you don't have rolls, available slot.
#you have consumed the rolls.
break;


About weighting system: let's say a row has 20 weight it's going to take minimum 4 and maximum 20 hits before an item can be selected from that row. so adjust the weight and/or decreasing factor(5, in this case) accordingly.

• Thank you for your help but I've already written the algorithm to pull items from the table. What I'm looking for is how to calculate the probability (0.0 - 1.0) of any given item being pulled out if that table Commented Nov 15, 2020 at 15:29