I used to run a couple of Dungeons and Dragons games every month or so. I tried making my own worlds, but I could never foresee the interesting things my players would try in the game. If I wanted to reward them with loot that I hadn’t planned, I would try to randomly generate that loot from treasure tables provided by one of the guides for the game. In order to learn more about ASP.NET MVC systems, I took an online course to get started and then made a REST API in C# built on ASP.NET MVC and MySQL that should be able to provide the tabletop role-playing game treasure table experience in a web application.
Treasure tables are a good way of either getting through writer’s block or coming up with treasures on the fly without having to lay out a whole region full of loot, but the process of rolling on a loot table feels very archaic. You get a d100 (2 d10 dice for the 1s and 10s digits), roll them, and look up the value on the appropriate table. Then there might be some random lookups based on the content of that result, and so on. It’s a very understandable recursive process. For example, here is a wilderness encounter table that I made for a campaign:
In this case, I rolled 66 for the table and looked that up. The result is that the party finds a smashed chest with 1d6 10GP art items. I rolled 1d6 for the contents, so there would be 2 art items. Then I would find the 10GP art objects table wherever it is, like in the Dungeon Master’s Guide, see that it has 12 entries, and roll 1d12 twice to get the types of art items. So I would then tell my group that their party had stumbled upon a smashed chest containing a set of dice made from human bones and a silver necklace. I would often not roll treasures until after a session was over in order to keep the game moving, but that was kind of annoying in its own way.
As someone with experience using relational databases, I realize that there is a fundamental simplicity here:
- Items can contain sets of other items chosen from many possible sets
- Sets are chosen by generating a number at random and comparing it to a lookup table
- Sets may contain items in quantities that are either simply numerical or derived by rolling a group of dice, adding the results, and multiplying by a constant
With a couple of tweaks to this logic, I ended up with some additional definitions:
- All lookup tables are items, but not all items are lookup tables
- When a set contains a quantity of an item, that quantity can be represented by m * <sum of n d-sided dice> + b
For example, a table might have a quantity of “4d6 x 1000 copper pieces” or “2d4 + 2 health points”
I made a database in MySQL that relates items:contained groups:sets of quantities of items:items, which is obviously a recursive relationship. MySQL is missing a few features from PostgreSQL that would have made this process easier, but I am more familiar with MySQL, so I was able to get started quicker.
I spun up a Debian virtual machine in VirtualBox, then configured Visual Studio Code to SSH into that virtual machine. I installed MySQL server 8.0 and the dotnet core runtime and SDK. This environment is really nice, but I should have used a docker container to make it even simpler.
There are some hacky things in the database definition that I would like to improve, but the program works well. I filled out the database with item definitions from the Dungeons and Dragons DM Guide, and it only takes a couple of seconds to return a JSON object with the contents of a treasure hoard.
I would like to extend this tool in a few ways, like finishing the multilingual support, filling in the values for each item, adding put/post/delete methods in the API, adding recursion-limiting within the database, and actually documenting the source code. Unfortunately, I won’t really have a use for this project myself until I write the great American TTRPG campaign, so I don’t think I will be adding to it for quite a while. The repository is on Github here.