mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-06-05 20:38:26 +02:00
New function to combine dice, and use this function for hit dice.
Fixes: https://github.com/canismarko/dungeon-sheets/issues/84
This commit is contained in:
@@ -24,6 +24,7 @@ from dungeonsheets import (
|
|||||||
from dungeonsheets.content_registry import find_content
|
from dungeonsheets.content_registry import find_content
|
||||||
from dungeonsheets.weapons import Weapon
|
from dungeonsheets.weapons import Weapon
|
||||||
from dungeonsheets.content import Creature
|
from dungeonsheets.content import Creature
|
||||||
|
from dungeonsheets.dice import combine_dice
|
||||||
|
|
||||||
|
|
||||||
dice_re = re.compile(r"(\d+)d(\d+)")
|
dice_re = re.compile(r"(\d+)d(\d+)")
|
||||||
@@ -789,9 +790,11 @@ class Character(Creature):
|
|||||||
@property
|
@property
|
||||||
def hit_dice(self):
|
def hit_dice(self):
|
||||||
"""What type and how many dice to use for re-gaining hit points.
|
"""What type and how many dice to use for re-gaining hit points.
|
||||||
|
|
||||||
To change, set hit_dice_num and hit_dice_faces."""
|
To change, set hit_dice_num and hit_dice_faces."""
|
||||||
return " + ".join([f"{c.level}d{c.hit_dice_faces}" for c in self.class_list])
|
dice_s = " + ".join([f"{c.level}d{c.hit_dice_faces}" for c in self.class_list])
|
||||||
|
dice_s = combine_dice(dice_s)
|
||||||
|
return dice_s
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hit_dice_faces(self):
|
def hit_dice_faces(self):
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
from itertools import groupby
|
||||||
|
|
||||||
from dungeonsheets.exceptions import DiceError
|
from dungeonsheets.exceptions import DiceError
|
||||||
|
|
||||||
dice_re = re.compile(r"(\d+)d(\d+)", flags=re.I)
|
dice_re = re.compile(r"(\d+)d(\d+)", flags=re.I)
|
||||||
|
dice_part_re = re.compile(r"[0-9d]+", flags=re.I)
|
||||||
Dice = namedtuple("Dice", ("num", "faces"))
|
Dice = namedtuple("Dice", ("num", "faces"))
|
||||||
|
|
||||||
|
|
||||||
@@ -25,6 +27,36 @@ def read_dice_str(dice_str):
|
|||||||
return dice
|
return dice
|
||||||
|
|
||||||
|
|
||||||
|
def combine_dice(dice_str):
|
||||||
|
"""Condense a dice string into its simplest representation.
|
||||||
|
|
||||||
|
For example: "1d8 + 5 + 2d8 + 2" would be reduced to "3d8 + 7".
|
||||||
|
|
||||||
|
Returns
|
||||||
|
=======
|
||||||
|
new_dice_str
|
||||||
|
A new, condensed string for the given dice.
|
||||||
|
|
||||||
|
"""
|
||||||
|
dice = []
|
||||||
|
bonuses = 0
|
||||||
|
# Sort out each portion of the dice string
|
||||||
|
for part in dice_part_re.findall(dice_str):
|
||||||
|
try:
|
||||||
|
dice.append(read_dice_str(part))
|
||||||
|
except DiceError:
|
||||||
|
bonuses += int(part)
|
||||||
|
# Recombine the dice into a more concise string
|
||||||
|
new_parts = []
|
||||||
|
dice = sorted(dice, key=lambda x: x.faces)
|
||||||
|
for faces, grp in groupby(dice, key=lambda x: x.faces):
|
||||||
|
new_parts.append(f"{sum([d.num for d in grp])}d{faces}")
|
||||||
|
if bonuses > 0:
|
||||||
|
new_parts.append(str(bonuses))
|
||||||
|
new_dice_str = " + ".join(new_parts)
|
||||||
|
return new_dice_str
|
||||||
|
|
||||||
|
|
||||||
def roll(a, b=None):
|
def roll(a, b=None):
|
||||||
"""roll(20) means roll 1d20, roll(2, 6) means roll 2d6"""
|
"""roll(20) means roll 1d20, roll(2, 6) means roll 2d6"""
|
||||||
if b is None:
|
if b is None:
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ class TestDice(TestCase):
|
|||||||
with self.assertRaises(DiceError):
|
with self.assertRaises(DiceError):
|
||||||
dice.read_dice_str("Ed15")
|
dice.read_dice_str("Ed15")
|
||||||
|
|
||||||
|
def test_combine_dice(self):
|
||||||
|
self.assertEqual(dice.combine_dice("1d8 + 6 + 2d8 + 12"), "3d8 + 18")
|
||||||
|
self.assertEqual(dice.combine_dice("1d8 + 1d5 + 2d8 + 1d5"), "2d5 + 3d8")
|
||||||
|
|
||||||
|
|
||||||
def test_simple_rolling(self):
|
def test_simple_rolling(self):
|
||||||
num_tests = 100
|
num_tests = 100
|
||||||
for _ in range(num_tests):
|
for _ in range(num_tests):
|
||||||
|
|||||||
Reference in New Issue
Block a user