Part 5: Ability Stability
This series of posts is dedicated to building tools that support a simulation of simplified D&D gameplay. To implement the simulation I’ll be using Python, PostgreSQL, Elastic, and Docker. The idea behind these blog posts is to document my progress through this project and interesting bits I find along the way. If you’d like to start from the beginning, have a look at part 1, where I talked about where this idea came from, and what I’d like to accomplish. The github repository for this project holds the latest version of the files mentioned in these posts. In this part, I’ll be working to determine how the simulation will describe the abilities of characters and foes.
In D&D, every creature’s physical and mental characteristics are summarized by six ability categories: Strength, Dexterity, Constitution, Intelligence, Wisdom, and Charisma. Their scores are used in three different types of rolls: ability checks, saving throws, and attack rolls (melee and spell).
One of the interesting things about the Ability Scores is that they can be populated different ways.
- The Common approach. For each ability, roll a six sided (d6) die four times and sum up the three highest values. Noted in the standard rules.
- The Strict approach. Each ability is determined by rolling a d6 three times and summing up the values. This is a variant that I used way back in the mists of time.
- The Standard approach. Use an array – 15,14,13,12,10, and 8 – to distribute. Noted in the standard rules.
- The Point Buy approach. Use a system of points where you start out with one pool of 27 points to spend on the characters ability scores. The scores cannot be lower than 8 or higher than 15 when using this system. As the higher the ability score increases, so does its cost in points. This variant system is described on dndbeyond really well.
To cover the Point Buy approach, I will use the four basic combinations that it can generate:
Even Point Buy [13, 13, 13, 12, 12 ,12]
One Max Point Buy [15, 12, 12, 12, 11, 11]
Two Max Point Buy [15, 15, 11, 10, 10, 10]
Three Max Point Buy [15, 15, 15, 8, 8, 8]
Then once the values are calculated, you populate the character’s array with the values that make sense for each of the classes. A Fighter usually relies on Strength most, so they put their highest rolled score in that ability. A Rogue’s best friend is Dexterity, so their highest score goes into that ability. This is a spot where the player can really customize their character to a specific way they want to role play that character. For the current project, I’m going to set this to be a specific order for each class, attempting to give each character the most offensive output. It should also be noted that there is a variant here as well. There are some strict schools of thought that populate the ability arrays as rolled. So, the first ability score generated will be Strength, second, Dexterity, and so on. I will build that into our process as a further variant when either the Common or Strict approaches are used.
The reason that I’m pointing these differences out is that I’m curious about the impact, if any, of these on the game. So, in the design for how the Ability Arrays are created, I want to make sure all the approaches are covered, and later when making the character, add the ability to make clones of the same character with different ability arrays.
Implementing this class will be pretty straight forward. We’ll pass in the type of approach we want, an array that holds the order we want our stats in, and if we want that order ignored. In the python_rpg_sim repository, Python/AbilityArray.py holds the code for this class.
The file that defines the tests for this class is called test/test_AbilityArray.py. Just like in the Die class, I’ve implemented a list of dictionary entries, called classEval, to hold values that can be used with the testing. Apart from bounds checking, there wouldn’t be much that could realistically be tested otherwise. Being able to reach in and look at the ‘candidate_array’ value array simplifies the verification that the selection of the static array types (Standard, and all the point buy options) work out. The testing for this class should again run without error
(rpg) ~/Git/python_rpg_sim/Python$ pytest test/test_AbilityArray.py ============================= test session starts ============================== platform linux -- Python 3.6.5, pytest-3.5.1, py-1.5.3, pluggy-0.6.0 rootdir: /home/mdbdba/Git/python_rpg_sim/Python, inifile: plugins: cov-2.5.1 collected 9 items test/test_AbilityArray.py ......... [100%] =========================== 9 passed in 0.01 seconds ===========================
With this class built there’s a way to determine and store our character and foe ability arrays in the simulation. In the next post I’ll look at another piece of infrastructure that will be needed going forward: databases and database version control. Once those are set up, the process of character creation will start to form up nicely. Until then, go play!