How to Get Errors and Bugs¶
get_dict errors¶
Every time you instantiate any IntegerEvents, it is checked. The get_dict() method returns a dict, and every value in get_dict().values() must be >=1. get_dict() may not be empty. since dt.Die(-2).get_dict() returns {}
>>> import dicetables as dt
>>> dt.Die(-2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
InvalidEventsError: events may not be empty. a good alternative is the identity - {0: 1}.
>>> dt.AdditiveEvents({1.0: 2})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
InvalidEventsError: all values must be ints
>>> dt.WeightedDie({1: 1, 2: -5})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
InvalidEventsError: no negative or zero occurrences in Events.get_dict()
Because AdditiveEvents and WeightedDie specifically scrub the zeroes from their get_dict() methods, these will not throw errors.
>>> dt.AdditiveEvents({1: 1, 2: 0}).get_dict()
{1: 1}
>>> weird = dt.WeightedDie({1: 1, 2: 0})
>>> weird.get_dict()
{1: 1}
>>> weird.get_size()
2
>>> weird.get_raw_dict() == {1: 1, 2: 0}
True
errors for dice¶
Special rule for WeightedDie and ModWeightedDie
>>> dt.WeightedDie({0: 1})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: rolls may not be less than 1. use ModWeightedDie
>>> dt.ModWeightedDie({0: 1}, 1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: rolls may not be less than 1. use ModWeightedDie
Here’s how to add 0 one time (which does nothing, btw)
>>> dt.ModWeightedDie({1: 1}, -1).get_dict()
{0: 1}
StrongDie also has a weird case that can be unpredictable. Basically, don’t multiply by zero
>>> table = dt.DiceTable.new().add_die(dt.Die(6))
>>> table = table.add_die(dt.StrongDie(dt.Die(100), 0), 100)
>>> table.get_dict() == {1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1}
True
>>> print(table)
1D6
(100D100)X(0)
>>> stupid_die = dt.StrongDie(dt.ModWeightedDie({1: 2, 3: 4}, -1), 0)
>>> table = table.add_die(stupid_die, 2) # this rolls zero with weight 4
>>> print(table)
(2D3-2 W:6)X(0)
1D6
(100D100)X(0)
>>> table.get_dict() == {1: 16, 2: 16, 3: 16, 4: 16, 5: 16, 6: 16} # this is correct, it's just stupid.
True
ExplodingOn will raise an error if the values in “explodes_on” are not in input_die.get_dict()
>>> input_die = dt.WeightedDie({1: 2, 3: 1, 5: 1, 7: 2})
>>> dt.ExplodingOn(input_die, ()).get_dict() == {1: 72, 3: 36, 5: 36, 7: 72}
True
>>> dt.ExplodingOn(input_die, (2,))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: "explodes_on" value not present in input_die.get_dict()
add_die and remove_die are relatively safe¶
dicetables.dicetable.DiceTable.add_die()
and dicetables.dicetable.DiceTable.add_die()
are safe. They raise an error if you
remove too many dice or add or remove a negative number.
If you “remove” or “combine” with a negative number, nothing should happen, but i make no guarantees.
If you use “remove” to remove what you haven’t added, it may or may not raise an error, but it’s guaranteed buggy.
Here are “add_die” and “remove_die” failing fast:
>>> table = dt.DiceTable.new().add_die(dt.Die(6))
>>> table = table.remove_die(dt.Die(6), 4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
DiceRecordError: Tried to create a DiceRecord with a negative value at Die(6): -3
>>> table = table.remove_die(dt.Die(10))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
DiceRecordError: Tried to create a DiceRecord with a negative value at Die(10): -1
>>> table = table.add_die(dt.Die(6), -3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
DiceRecordError: Tried to add_die or remove_die with a negative number.
>>> table = table.remove_die(dt.Die(6), -3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
DiceRecordError: Tried to add_die or remove_die with a negative number.
combine and remove are not¶
And now, this is the trouble you can get into with
dicetables.additiveevents.AdditiveEvents.combine()
and
dicetables.additiveevents.AdditiveEvents.remove()
>>> table = dt.DiceTable.new().add_die(dt.Die(6))
>>> table.get_dict() == {1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1}
True
>>> table = table.combine(dt.Die(10000), -100)
>>> table.get_dict() == {1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1}
True
>>> table = table.remove(dt.Die(2), 10)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: min() arg is an empty sequence <-didn't know this would happen, but at least failed loudly
>>> table = table.remove(dt.Die(2), 2)
>>> table.get_dict() == {-1: 1, 1: 1} # bad. this is a random answer
True
- (I know why you’re about to get wacky and inaccurate errors, and I could fix the bug, except …
YOU SHOULD NEVER EVER DO THIS!!!!)
>>> table = table.remove(dt.AdditiveEvents({-5: 100}))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
EventsFactoryError: Error Code: SIGNATURES DIFFERENT
Factory: <class 'dicetables.factory.eventsfactory.EventsFactory'>
Error At: <class 'dicetables.dicetable.DiceTable'>
Attempted to construct a class already present in factory, but with a different signature.
Class: <class 'dicetables.dicetable.DiceTable'>
Signature In Factory: ('get_dict', 'dice_data')
To reset the factory to its base state, use EventsFactory.reset()
Calling combine_by_flattened_list can be risky
>>> x = dt.AdditiveEvents({1:1, 2: 5})
>>> x = x.combine_by_flattened_list(dt.AdditiveEvents({1: 2, 3: 4}), 5)
>>> x = x.combine_by_flattened_list(dt.AdditiveEvents({1: 2, 3: 4*10**10}), 5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
MemoryError
>>> x = x.combine_by_flattened_list(dt.AdditiveEvents({1: 2, 3: 4*10**700}))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: cannot fit 'int' into an index-sized integer
making a DiceTable with nonsense¶
Since you can instantiate a DiceTable with any legal input, you can make a table with utter nonsense. It will work horribly. for instance, the dictionary for 2D6 is:
{2: 1, 3: 2, 4: 3, 5: 4, 6: 5, 7: 6, 8: 5, 9: 4, 10: 3, 11: 2, 12: 1}
>>> nonsense = dt.DiceTable({1: 1}, dt.DiceRecord({dt.Die(6): 2})) # <- BAD DATA!!!!
>>> print(nonsense) # <- the dice record says it has 2D6, but the events dictionary is WRONG
2D6
>>> nonsense = nonsense.remove_die(dt.Die(6), 2) # <- so here's your error. I hope you're happy.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: min() arg is an empty sequence
But, you cannot instantiate a DiceTable with negative values for dice. And you cannot instantiate a DiceTable with non-sense values for dice.
>>> dt.DiceTable({1: 1}, dt.DiceRecord({dt.Die(3): 3, dt.Die(5): -1}))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
DiceRecordError: Tried to create a DiceRecord with a negative value at Die(5): -1
>>> dt.DiceTable({1: 1}, dt.DiceRecord({'a': 2.0}))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
DiceRecordError: input must be {ProtoDie: int, ...}