Skip to main content

make Dungeons & Dragons characters as serializable objects

Project description

dnd-character

A Python library to make 5e Dungeons & Dragons characters for use in another app. Characters are serializable into Python dicts so they can be saved and loaded however you wish.

SRD rules are fetched from the 5e SRD API the first time they're requested, then the JSON is cached locally for faster retrieval in the future. I've included the json_cache containing the SRD inside the repo in case this API changes, but when the API does change I will update this library. So please pin your version if you want to avoid any breaking changes.

You can use this library as a CLI tool to generate character sheets from the terminal; see python -m dnd_character --help for details.

Installation and Use

  1. Install from PyPI using pip install dnd-character
  2. See example.py for example code on how to use the library.
  3. Generate random character sheet text file with python -m dnd_character --random > mycharactername.txt

Licenses

The software is EPL-2.0 and the text for this license is in LICENSE as is standard for software. Originally forked from PyDnD. The contents of dnd_character/json_cache are retrieved from 5e-srd-api, and are covered by the Open Game License. See dnd_character/json_cache/OGLv1.0a.txt for details.

Example Code

Creating Characters and Monsters

The classes module has functions for creating all 12 classes from the System Reference Document. The monsters module has a factory function for creating monsters.

from dnd_character.classes import Bard
from dnd_character.monsters import Monster
from random import randint

brianna = Bard(
    name="Brianna",
    level=10,
    )
zombie = Monster("zombie")
attack_bonus = zombie.actions[0]["attack_bonus"]
# Zombie rolls a d20 to attack a Bard
if randint(1, 20) + attack_bonus >= brianna.armor_class:
    print(f"{brianna.name} was hit by {zombie.name}!")
else:
    print(f"{brianna.name} bravely dodged the attack")

Leveling and Experience

The library should help leveling up characters automatically if you manage the Character's experience attribute. It's simpler to avoid modifying the level directly.

from dnd_character import Character
thor = Character(name="Thor")
assert thor.level == 1
thor.experience += 1000
assert thor.level == 3
assert thor.experience.to_next_level == 1700
thor.experience += thor.experience.to_next_level
assert thor.level == 4

Starting Equipment

Characters initialized with a class will have the starting equipment of that class, and an attribute called player_options which lists the optional starting equipment.

from dnd_character.classes import Paladin
from dnd_character.equipment import Item
from pprint import pprint
sturm = Paladin(dexterity=10)
pprint(sturm.inventory)
print(sturm.armor_class)
# Remove Chain Mail
sturm.remove_item(sturm.inventory[0])
print(sturm.armor_class)
# New Item
dragonlance = Item('lance')
dragonlance.name = "Dragonlance®"
sturm.give_item(dragonlance)
# View optional starting equipment
pprint(sturm.player_options)

Using Spells

Spells are represented by _SPELL objects from dnd_character.spellcasting. The best way to find spells is using the spells_for_class_level function.

from dnd_character.spellcasting import spells_for_class_level
cantrips = spells_for_class_level('wizard', 0)
print(f"Cantrips available to a Wizard:")
for spell in cantrips:
    print(spell)

Characters have lists to store _SPELL objects:

  • spells_prepared
  • spells_known
  • cantrips_known

Characters have a spell_slots dictionary which shows the total spell slots. Depletion and rest mechanics are planned for a future version.

from dnd_character import Wizard
from dnd_character.spellcasting import SPELLS
# Create wizard and teach Identify, a level 1 spell
my_wizard = Wizard(name="Gormwinkle")
my_wizard.spells_prepared.append(SPELLS["identify"])
# Get total spell slots
spell_slots_level_1 = my_wizard.spell_slots["spell_slots_level_1"]
print(f"{my_wizard.name} has {spell_slots_level_1} spell slots of 1st level")
# Cast until wizard runs out of spell slots
while spell_slots_level_1 > 0:
    print(f"Casting {SPELLS['identify'].name}!")
    spell_slots_level_1 -= 1

There is currently no way to manage wizard spellbooks or class-specific features such as the Wizard's arcane recovery or the Sorcerer's metamagic.

Character Object

Normal initialization arguments for a Character object:

name         (str)
age          (str)
gender       (str)
level        (int): starting level
hp           (int)
alignment    (str): character's two letter alignment (LE, CG, TN, etc.)
description  (str): physical description of player character
background   (str): one-word backstory (e.g., knight, chef, acolyte)
wealth       (int): if None, roll 4d10 for starting gp (gold pieces)
strength     (int): if None, roll 4d6 and drop the lowest
dexterity    (int): if None, roll 4d6 and drop the lowest
constitution (int): if None, roll 4d6 and drop the lowest
wisdom       (int): if None, roll 4d6 and drop the lowest
intelligence (int): if None, roll 4d6 and drop the lowest
charisma     (int): if None, roll 4d6 and drop the lowest
classs    (_CLASS): a D&D class object (e.g., CLASSES['bard'])

In addition, the Character object can receive attributes that are normally set automatically, such as the UUID. This is for re-loading the objects from serialized data (via Character(**characterData)) and probably aren't arguments you would write manually into your code.

Serializing objects

All objects in this library can be turned into Python dicts, which can then be turned back into objects. This means characters (along with their items and spells), and monsters as well.

  • dict(object) creates a serializable dict that could be reloaded from text (e.g., suitable for conversion to and from JSON)
  • repr(object) prints a string that would re-construct the Python object if pasted into a REPL
  • str(object) is not for serialization. It creates a "user-friendly" string

Contributing

I greatly appreciate feedback about desired features and information about how you're using this library. Please feel free to open an issue or pull request on GitHub! I would be happy to help merge any contributions no matter your skill level.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dnd_character-23.7.29.tar.gz (474.7 kB view details)

Uploaded Source

Built Distribution

dnd_character-23.7.29-py3-none-any.whl (1.2 MB view details)

Uploaded Python 3

File details

Details for the file dnd_character-23.7.29.tar.gz.

File metadata

  • Download URL: dnd_character-23.7.29.tar.gz
  • Upload date:
  • Size: 474.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.10.6

File hashes

Hashes for dnd_character-23.7.29.tar.gz
Algorithm Hash digest
SHA256 43391ac1d2ea648b615bb8027eea80327a046285287e265e0b8a89fceef10426
MD5 1ae9748ec01613fde77ade3aedfd5150
BLAKE2b-256 f501def7ad48e90036b108cf853cca6f289cb7f5efe309ed4c767159b3e00697

See more details on using hashes here.

File details

Details for the file dnd_character-23.7.29-py3-none-any.whl.

File metadata

File hashes

Hashes for dnd_character-23.7.29-py3-none-any.whl
Algorithm Hash digest
SHA256 ea1283db0743e2785de3ca879017a2aea4c0cb837699e545965790e537446a7d
MD5 d1aa3b39f85502d7c8c686b33a7610e0
BLAKE2b-256 e0f450ef2fa8aa1754a5a56e6fc5414a3f3804f1c898eba1e39102a0d613eacf

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page