One of my hobbies has been Dungeons and Dragons. Although I don't play much these days, it has had a second lease of life as a subject to write computer programs for. Here is one such, when I was wondering how to generate a treasure hoard, given an approximate value and whether or not the treasure was mostly low-value copper coins, or high value gems and magic items.
#!/usr/bin/python3.5
import random
print ("Treasure hoard generating program")
print ("=================================")
print ("Please enter approximate value of treasure hoard: ")
total_value = input("? ")
total_value = int(total_value) # approximate total value. It doesn't work out precisely.
print ("On a scale of 1-10 how skewed is it towards high value items?")
skew = input("1= mostly low value coins, 10 = mostly magic items: ")
skew = int(skew) -1
# for ratio tuples [0] is copper, [1] is silver, [2] is electrum, [3] is gold
# [4] is platinum, [5] is gems, [6] is jewelry, [7] is magic items
skew_ratio1 = (0.75, 0.95, 0.98, 0, 0, 1, 0, 0)
skew_ratio2 = (0.50, 0.85, 0.90, 0.95, 0, 0.98, 1, 0)
skew_ratio3 = (0.30, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 1)
skew_ratio4 = (0.25, 0.50, 0.65, 0.80, 0.85, 0.90, 0.95, 1)
skew_ratio5 = (0.15, 0.30, 0.45, 0.60, 0.75, 0.83, 0.91, 1)
skew_ratio6 = (0.10, 0.20, 0.40, 0.60, 0.75, 0.90, 0.95, 1)
skew_ratio7 = (0.07, 0.14, 0.20, 0.50, 0.65, 0.80, 0.90, 1)
skew_ratio8 = (0.05, 0.10, 0.15, 0.35, 0.50, 0.65, 0.80, 1)
skew_ratio9 = (0.03, 0.07, 0.12, 0.30, 0.45, 0.60, 0.85, 1)
skew_ratio10 = (0.01, 0.02, 0.10, 0.20, 0.30, 0.50, 0.75, 1)
skew_ratio_tup = (skew_ratio1, skew_ratio2, skew_ratio3, skew_ratio4, skew_ratio5, skew_ratio6, skew_ratio7, skew_ratio8, skew_ratio9, skew_ratio10)
selected_skew_ratio = skew_ratio_tup[skew] # should select the right set of ratios
spent_value = 0
copper_value = 0
silver_value = 0
electrum_value = 0
gold_value = 0
platinum_value = 0
gem_value = 0
jewelry_value = 0
magic_item_value = 0
chunk_number = 0
while spent_value < total_value:
chunk_value = total_value * random.random() * 0.1
chunk_choice = random.random()
category_num = 0
chunk_done = False
for category in selected_skew_ratio:
if category > chunk_choice and chunk_done == False:
spent_value = spent_value + chunk_value
if category_num == 0:
copper_value = (copper_value + chunk_value)
elif category_num == 1:
silver_value = (silver_value + chunk_value)
elif category_num == 2:
electrum_value = (electrum_value + chunk_value)
elif category_num == 3:
gold_value = (gold_value + chunk_value)
elif category_num == 4:
platinum_value = (platinum_value + chunk_value)
elif category_num == 5:
gem_value = (gem_value + chunk_value)
elif category_num == 6:
jewelry_value = (jewelry_value + chunk_value)
else:
magic_item_value = (magic_item_value + chunk_value)
#print (category_num, chunk_value)
chunk_done = True
else:
category_num = category_num +1
chunk_number = chunk_number +1
print ("Coins")
print ("=====")
copper_coins = format(int(copper_value * 100), ',d')
print ("Copper value = ", copper_value, "\n\tCopper Coins = ", copper_coins)
silver_coins = format(int(silver_value * 10), ',d')
print ("Silver value = ", silver_value, "\n\tSilver Coins = ", silver_coins)
electrum_coins = format(int(electrum_value * 5), ',d')
print ("Electrum value = ", electrum_value, "\n\tElectrum Coins = ", electrum_coins)
print ("Gold value = ", gold_value, "\n\tGold coins = ", format(int(gold_value), ',d'))
platinum_coins = format(int(platinum_value / 5), ',d')
print ("Platinum value = ", platinum_value, "\n\tPlatinum coins = ", platinum_coins)
print ("Gem value = ", gem_value)
print ("Jewelry value = ", jewelry_value)
print ("Magic Item value =", magic_item_value)
print ("Total assigned value = ", spent_value)
print ('\n')
gemstash = [] # what the treasure hoard contains - starts empty
total_gemvalue = 0
if gem_value < 10 and gem_value > 0:
gem_string = ["1 small pretty stone worth ", int(gem_value)]
total_gemvalue = total_gemvalue + int(gem_value)
else:
gem_string = ""
handle = open('gemfile.txt', 'r')
gemlist = [] # table for storing data about gems
for line in handle:
linelist = line.split(', ')
gemlist.append(linelist)
remaining_gemvalue = gem_value
size_tuple = ((0.2, "very small "), (0.5, "small "), (0.5, "small "), (1, "medium "), (1, "medium "), (1, "medium "), (2, "large "), (5, "huge "))
quality_tuple = ((0.2, "poor "), (0.5, "flawed "), (0.5, "flawed "), (1, "normal "), (1, "normal "), (1, "normal "), (2, "flawless "), (5, "perfect "))
while remaining_gemvalue >= 10:
potential_gem = [random.choice(quality_tuple), random.choice(size_tuple), random.choice(gemlist)]
potential_value = float(potential_gem[0][0]) * float(potential_gem[1][0]) * float(potential_gem[2][1])
if potential_value <= remaining_gemvalue:
gem_descrip = potential_gem[0][1] + potential_gem[1][1] + potential_gem[2][0]
gem_final = [int(potential_value), gem_descrip]
gemstash.append(gem_final)
remaining_gemvalue = remaining_gemvalue - potential_value
total_gemvalue = total_gemvalue + potential_value
handle.close()
gemstash.append(gem_string)
print ("Gems")
print ("====")
for gem in gemstash:
print (gem)
print ("Gem value is ", total_gemvalue)
print ('\n')
jewelrystash = []
jewelrylist = []
total_jewelryvalue = 0
remaining_jewelryvalue = jewelry_value
handle = open('jewelryfile.txt', 'r')
for line in handle:
linelist = line.split(', ')
linelist[1] = int(linelist[1])
jewelrylist.append(linelist)
jewelry_tuple = (("plain ", 1), ("engraved ", 2), ("ornate ", 5), ("bejeweled ", 10))
metal_tuple = (("copper ", 1), ("silver ", 10), ("electrum ", 50), ("gold ", 100), ("platinum ", 500), ("mithril ", 2000))
while remaining_jewelryvalue >= 10:
potential_jewel = [random.choice(jewelry_tuple), random.choice(metal_tuple), random.choice(jewelrylist)]
potential_jewel_description = potential_jewel[0][0] + potential_jewel[1][0] + potential_jewel[2][0]
potential_jewel_value = potential_jewel[0][1] * potential_jewel[1][1] * int(potential_jewel[2][1])
if remaining_jewelryvalue > potential_jewel_value:
jewelrystash.append((potential_jewel_description, potential_jewel_value))
remaining_jewelryvalue = remaining_jewelryvalue - potential_jewel_value
total_jewelryvalue = total_jewelryvalue + potential_jewel_value
print ("Jewellery")
print ("=========")
for jewel in jewelrystash:
print (jewel)
print ("Jewelry value is", total_jewelryvalue)
print ("\n")
handle.close()
itemstash = []
itemlist = [] # magic items and values are from DMG 3.0
total_itemvalue = 0
remaining_itemvalue = magic_item_value
handle = open('magicitemfile.txt', 'r')
for line in handle:
linelist = line.split(', ')
linelist[1] = int(linelist[1])
itemlist.append(linelist)
while remaining_itemvalue >= 200:
potential_item = random.choice(itemlist)
if remaining_itemvalue >= potential_item[1]:
itemstash.append(potential_item)
remaining_itemvalue = remaining_itemvalue - potential_item[1]
total_itemvalue = total_itemvalue + potential_item[1]
print ("Magic Items")
print ("===========")
for magicitem in itemstash:
print (magicitem)
print ("Magic Item value is ", total_itemvalue)
total_treasurevalue = (int(copper_value)) + (int(silver_value)) + (int(electrum_value)) + int(gold_value) + int(platinum_value) + total_gemvalue + total_jewelryvalue + total_itemvalue
print ("total treasure value is", total_treasurevalue)
First of all, this is a big program.
Thirdly this is not entirely accurate in total value - it gives amounts about 10% either side of initial required value.
It works by splitting the treasure up into randomly-sized chunks between 0% and 10% of the required value.
That chunk is then randomly determined to be a particular treasure type (copper coins, silver coins, gems, jewellery etc). Rather than equal chances for each type, the chances are determined by looking up the skew_ratio which then gives the chances for each type.
If the chunk is made of coins, then the number of coins is determined based on the value of the chunk.
If the chunk is made of gems, jewellery or magic items, then random examples of those are generate. If their values are equal to or less than that of the chunk then the item is added and the value of the item deducted from the chunk. If there is enough value left over in the chunk, another example is generated until the remaining value of the chunk falls below a threshold.
And the end result? Here is a typical run, generating a 100,000gp-value treasure trove
RESTART: C:/Users/John/Dropbox/Misc Programming/Python/python3/test08a_treasure.py
Treasure hoard generating program
=================================
Please enter approximate value of treasure hoard:
? 100000
On a scale of 1-10 how skewed is it towards high value items?
1= mostly low value coins, 10 = mostly magic items: 5Coins
=====
Copper value = 14977.991665483956
Copper Coins = 1,497,799
Silver value = 15397.31065665539
Silver Coins = 153,973
Electrum value = 18959.482408553344
Electrum Coins = 94,797
Gold value = 2479.269646407558
Gold coins = 2,479
Platinum value = 24353.349234787212
Platinum coins = 4,870
Gem value = 1626.2385405454738
Jewelry value = 8493.713069086232
Magic Item value = 14708.117885848227
Total assigned value = 100995.4731073674
Gems
====
[30, 'poor small Aquamarine']
[100, 'poor huge Iolite']
[100, 'normal medium Amber']
[100, 'flawed very small Emerald']
[50, 'normal small Tourmaline']
[1000, 'flawless huge Carnelian']
[20, 'normal very small Peridot']
[30, 'normal medium Rose Quartz']
[7, 'flawed small Citrine']
[60, 'normal very small Garnet']
[120, 'flawless very small Pearl']
Gem value is 1617.5
Jewellery
=========
('ornate electrum vase', 7500)
('engraved silver fork', 100)
('plain copper spoon', 5)
('engraved copper torc', 100)
('ornate copper spurs', 50)
('plain copper crown', 100)
('plain silver spurs', 100)
('plain silver spurs', 100)
('plain silver necklace', 150)
('plain copper knife', 5)
('bejeweled copper pin', 50)
('plain copper dagger', 50)
('bejeweled copper fork', 50)
('plain copper chain', 20)
('ornate copper earring', 50)
('engraved copper nosering', 20)
('engraved copper headband', 40)
Jewelry value is 8490
Magic Items
===========
['Wand of Magic Missile', 750, 'DMG 3.0\n']
['Longsword +2', 8315, 'DMG 3.0\n']
['Scroll of 5th level cleric spell', 1125, 'DMG 3.0\n']
['Bolts +1 (50)', 2350, 'DMG 3.0\n']
['Scroll of 5th level wizard spell', 1125, 'DMG 3.0\n']
['Potion of Heroism', 900, 'DMG 3.0\n']
Magic Item value is 14565
total treasure value is 100837.5
>>>
The presentation could do with some cleaning up, but the idea is sound. And just in case you do play Dungeons & Dragons, the magicitemfile.txt derives its information from 3rd Edition Dungeon Master's Guide. If you prefer a different edition, feel free to generate your own magicitemfile.txt