Skip to content

Commit

Permalink
#1 Add fudge dices (XdF)
Browse files Browse the repository at this point in the history
  • Loading branch information
olinox14 committed Jun 24, 2018
1 parent f39d452 commit 4bef172
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 12 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*xdice* is a lightweight python library for managing dice, scores, and
dice-notation patterns.

- Parse almost any Dice Notation pattern: '1d6+1', 'd20', '3d%', '1d20//2 - 2*(6d6+2)', 'max(1d4+1,1d6)', '3D6L2', 'R3(1d6+1)'...etc.
- Parse almost any Dice Notation pattern: '1d6+1', 'd20', '3d%', '1d20//2 - 2*(6d6+2)', 'max(1d4+1,1d6)', '3D6L2', 'R3(1d6+1)', '3dF'...etc.
- API help you to easily manipulate dices, patterns, and scores as objects
- A command line tool for convenience

Expand Down
6 changes: 6 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ def test_patterns_validation(self):
xdice.roll("3d6!")
xdice.roll("3d6x")
xdice.roll("3d6h1x")
xdice.roll("3df")
xdice.roll("3d6+1df")

# test invalid expressions
self.assertRaises(ValueError, xdice.roll, "")
Expand All @@ -67,6 +69,8 @@ def test_patterns_validation(self):
self.assertRaises(ValueError, xdice.roll, "1d6l2")
self.assertRaises(ValueError, xdice.roll, "1d6h2")
self.assertRaises(ValueError, xdice.roll, "1d6lh")
self.assertRaises(SyntaxError, xdice.roll, "1d6f")
self.assertRaises(SyntaxError, xdice.roll, "3f")
self.assertRaises(SyntaxError, xdice.roll, "1+R3(1d6+1")

def test_dice_object(self):
Expand Down Expand Up @@ -109,6 +113,8 @@ def test_dice_object(self):
self.assertEqual(xdice.Dice.parse("3d1x").roll(), 6)
self.assertEqual(xdice.Dice.parse("3d1lhx").roll(), 2)

self.assertIn(xdice.Dice("f", 1).roll(), [-1, 0, 1])

def test_score_object(self):

s = xdice.Score([1, 2, 3])
Expand Down
31 changes: 20 additions & 11 deletions xdice.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import random
import re

__VERSION__ = 1.1
__VERSION__ = 1.2

def compile(pattern_string): # @ReservedAssignment
"""
Expand Down Expand Up @@ -69,7 +69,7 @@ class Dice():
Use roll() to get a Score() object.
"""
DEFAULT_SIDES = 20
DICE_RE_STR = r"(?P<amount>\d*)d(?P<sides>\d*)(?:l(?P<lowest>\d*))?(?:h(?P<highest>\d*))?([x!])?"
DICE_RE_STR = r"(?P<amount>\d*)d(?P<sides>f|\d*)(?:l(?P<lowest>\d*))?(?:h(?P<highest>\d*))?([x!])?"
DICE_RE = re.compile(DICE_RE_STR)

def __init__(self, sides, amount=1, drop_lowest=0, drop_highest=0, explode=False):
Expand All @@ -93,7 +93,9 @@ def sides(self):
@sides.setter
def sides(self, sides):
""" Set the number of faces of the dice """
_assert_int_ge_to(sides, 1, "Invalid value for sides ('{}')".format(sides))
if sides != "f":
_assert_int_ge_to(sides, 1, "Invalid value for sides ('{}')".format(sides))
sides = int(sides)
self._sides = sides

@property
Expand Down Expand Up @@ -160,7 +162,8 @@ def __repr__(self):
lowstr = "; drop_lowest={}".format(self.drop_lowest) if self.drop_lowest else ""
highstr = "; drop_highest={}".format(self.drop_highest) if self.drop_highest else ""
explodestr = "; explode"if self.explode else ""
return "<Dice; sides={}; amount={}{}{}{}>".format(self.sides, self.amount, lowstr, highstr, explodestr)
fudgestr = "; fudge"if self.sides == "f" else ""
return "<Dice; sides={}; amount={}{}{}{}{}>".format(self.sides, self.amount, lowstr, highstr, explodestr, fudgestr)

def __eq__(self, d):
"""
Expand All @@ -169,14 +172,17 @@ def __eq__(self, d):
"""
return self.sides == d.sides and self.amount == d.amount

def _rollone(self):
return random.randint(1, self._sides) if self._sides != "f" else random.randint(-1, 1)

def roll(self):
""" Role the dice and return a Score object """
# Sort results
results = [random.randint(1, self._sides) for _ in range(self._amount)]
results = [self._rollone() for _ in range(self._amount)]
dropped = [_pop_lowest(results) for _ in range(self._drop_lowest)] + \
[_pop_highest(results) for _ in range(self._drop_highest)]
if self._explode:
exploded = [random.randint(1, self._sides) for _ in range(len([score for score in results if score == self._sides]))]
exploded = [self._rollone() for _ in range(len([score for score in results if score == self._sides]))]
results += exploded
return Score(results, dropped, self.name)

Expand All @@ -193,11 +199,14 @@ def parse(cls, pattern):

amount = amount or 1
sides = sides or cls.DEFAULT_SIDES
lowest = (lowest or 1) if lowest is not None else 0
highest = (highest or 1) if highest is not None else 0
explode = bool(explode)

return Dice(*map(int, [sides, amount, lowest, highest, explode]))
if lowest == "":
lowest = 1
lowest = lowest or 0
if highest == "":
highest = 1
highest = highest or 0

return Dice(*[sides, int(amount), int(lowest), int(highest), bool(explode)])

class Score(int):
""" Score is a subclass of integer.
Expand Down

0 comments on commit 4bef172

Please sign in to comment.