def test_pool(dice): """ Get the individual dice, for playing with the optional rules. """ assert ote.pool(dice).is_same(Pool(d6, count=dice)) assert ote.pool(dice, bonus=0).is_same(Pool(d6, count=dice)) assert ote.pool(dice, bonus=1).is_same(drop_lowest(1, d6, count=dice + 1)) assert ote.pool(dice, bonus=-1).is_same(drop_highest(1, d6, count=dice + 1))
def test_total(dice): """ Get the result of a roll. """ assert ote.total(dice).is_same(dice @ d6) assert ote.total(dice, bonus=0).is_same(dice @ d6) assert ote.total(dice, bonus=1).is_same( drop_lowest(1, d6, count=dice + 1).apply(sum)) assert ote.total(dice, bonus=-1).is_same( drop_highest(1, d6, count=dice + 1).apply(sum), )
def test_bad_keep_numbers(bad): """ You can't pass a negative number of dice to keep, but you can drop more dice than you have (resulting in no dice). """ with pytest.raises(ValueError): pools.keep_highest(bad, d6, d6) with pytest.raises(ValueError): pools.keep_lowest(bad, d6, d6) assert pools.drop_highest(10, d6, count=-bad).is_same(pools.pool()) assert pools.drop_lowest(10, d6, count=-bad).is_same(pools.pool())
def pool( dice: int, bonus: int = 0, *, botch: bool = False, explode: Union[bool, int] = False, unstoppable=False, ) -> DRV: """ A :obj:`~omnidice.pools.pool` with the distribution of all the values on the dice. Calling ``.apply(sum)`` on the result will produce the same as the result of :func:`total` with the same arguments. :param dice: The score of the trait rolled (excluding bonus/penalty dice). :param bonus: The number of bonus dice to roll. A negative number indicates penalty dice. :param botch: If True, use the "Botches" optional rule. A botch is indicated by :code:`pools.PlainResult(-1)`, as if a single die showed -1. :param explode: If truthy, use the "Blowing the Top Off" optional rule. As with :func:`DRV.explode() <omnidice.drv.DRV.explode>`, you can specify the max number of rerolls to allow. Specifying True means to use the default max number of rerolls. The additional exploding die is listed as a single extra die, regardless of how many 6s it rolls, so it can have a value greater than 6. :param unstoppable: If True, use the "Unstoppable Six" optional rule. Instead of showing all the dice results, the possible values of the drv returned are instances of :obj:`Unstoppable`. """ if dice == 0: raise ValueError('empty pool is not allowed') if bonus == 0: result = Pool(d6, count=dice) elif bonus > 0: result = drop_lowest(bonus, d6, count=dice + bonus) else: penalty = -bonus result = drop_highest(penalty, d6, count=dice + penalty) if botch: botched = PlainResult(*[1] * dice) result = result.apply(lambda x: PlainResult(-1) if x == botched else x) if explode: result = _add_extra(explode, result, PlainResult(*[6] * dice)) if unstoppable: return result.apply(Unstoppable) return result
def test_drop_lowest(): expected = pools.keep_highest(3, d6, count=5) assert pools.drop_lowest(2, d6, count=5).is_same(expected) assert pools.drop_lowest(2, d6, d6, d6, d6, d6).is_same(expected)