This blog is typically dedicated to my GIS work, but since I've had lots of time during COVID-19 quarantine to work on other things I thought I'd use this space to show off something else I've made in python. I made a
twitter bot that generates characters for the popular table top game Dungeons and Dragons. This bot comes up with a name, personality trait, fantasy race, and occupation for the character. It also generates a short bio and gives them a list of stats.
It started out as a very simple few lines of code to see if I could recreate rolling a six sided die:
|
A d6 is just a normal 6-sided die like you would use in a normal board game. The "quant" parameter asks for how many dice you want to roll. By default it is set to just one. |
Well that was easy enough. What can I do with this function?
A Dungeon and Dragon's character has six different stats: strength, dexterity, constitution, intelligence, wisdom, and charisma. Typically these stats range from 0 (very poor) to 20 (excellent). These stats determine how likely a character is to succeed or fail at a certain task. Throwing a javelin requires strength, while picking a lock involves dexterity. The next logical step with this program is to use dice rolling to assign numbers to these stats. The most straight forward way to roll for stats is simply rolling three six-sided die for each stat. In python this looks as follows:
|
This calls the d6 function six times and appends the value generated with three virtual dice to a list. |
Great! But what if you wanted a more complicated method of rolling? Some methods are designed to generate more powerful or more balanced characters. I ended up developing eleven different roll methods in all (some coming from
this source and others of my own creation).
Here's one of the more complicated ones. This one rolls four six-sided dice for each stat and drops the lowest of the for dice in the set. The tricky part comes in where the roll method dictates that at least one of the stats must be above 15. I achieve this with
if any(num > 15 for num in rollstats).
If any value in the list is above 15 the code will continue and return the list. If not the function becomes recursive and runs itself again until it meets the desired criteria.
|
This method continues recursively until it returns a list where at least one value is above 15. |
Now that I have different ways of assigning stats to a character the next step is to give them a name and some basic attributes. I accomplish this by making a different lists - firstname, lastname, trait, fantasyrace, and occupation. I fill these up with as many different values that I can think of and then use random.choice on each list to pick out a value for each one.
I added an extra level of depth here by making each fantasy race a tuple instead of just a simple string value. Why a tuple? Because each species has slightly different stat modifiers. Orcs are strong and dwarves are tough so that extra boosts should be reflected in their stats on top of those they roll for. Calling on a certain point in each tuple to add these values is much faster and easier than writing a complicated if/else statement that achieves the same thing.
|
There are a lot of different species available to play as in the game each with their own unique traits. |
After this to add a bit of flavor to the characters I gave them a short bio. This picks one of over forty sentences to call upon and pick different nouns from a variety of lists. This adds variety to the characters and gives the game master a little bit more to work with in terms of providing the character with a backstory or set of motivations.
Once all the individual pieces are created they are assigned to a single variable that makes up the whole character. With a little bit of work in git, heroku, and getting a twitter developer account approved the script was ready! In heroku the script is programmed to tweet out a new character four times a day. The code itself can be viewed
here on Github.
|
This guy is pretty strong as long as no one puts cream in his coffee. |