Weighted Random Choice or Treasure Tables with Rarity

Project Goal: Develop an Abstraction for a random treasure generator, where some treasure is more rare than others.

Define a data structure to represent a sequence of weighted values. Then design an algorithm to make random selections from a weighted sequence;  such that the output distribution reflects the desired weights of the values in the sequence.

It is unknown at this time if a relative weighted strategy or a cumulative weighted strategy will be preferred, we should consider both.

Cumulative Weighted Table

#!/usr/bin/python3 
# file name: weighted_choice.py
from dice import d

treasure_table = (
[40, "Healing Potion"],
[70, "Dagger +1"],
[90, "Sword +2"],
[95, "Bag of Holding"],
[96, "Holy Avenger"],
[97, "Blackrazor"],
[98, "Hammer of Thunder"],
[99, "Wand of the War Mage"],
[100, "Orb of Annihilation"]
)

def cumulative_weighted_choice(cumulative_table):
max_weight = cumulative_table[-1][0]
rand_val = d(max_weight)
for weight, value in cumulative_table:
if rand_val <= weight:
return value

for _ in range(20):
print(cumulative_weighted_choice(treasure_table))

Relative Weighted Table

rel_treasure_table = (
[40, "Healing Potion"],
[30, "Dagger +1"],
[20, "Sword +2"],
[5, "Bag of Holding"],
[1, "Holy Avenger"],
[1, "Blackrazor"],
[1, "Hammer of Thunder"],
[1, "Wand of the War Mage"],
[1, "Orb of Annihilation"]
)

def cumulative_transform(relative_table):
cumulative_table = sorted(list(relative_table), reverse=True)
cum_weight = 0
for pair in cumulative_table:
cum_weight += pair[0]
pair[0] = cum_weight
return cumulative_table

transformed_treasure_table = cumulative_transform(rel_treasure_table)
for _ in range(20):
print(cumulative_weighted_choice(transformed_treasure_table))