- Deprecate
depth=None
in favor ofdepth='inf'
. - Add experimental
format_inverse()
option that formats probabilities as "1 in N".
- Add
pointwise_max
,pointwise_min
arguments to take pointwise maximum or minimum of CDFs. - Add
Die.time_to_sum()
method. - Fix identification of absorbing states in the presence of
extra_args
inmap_and_time()
. - Add
time_limit
parameter tomap()
. repeat
parameter now uses'inf'
to request the absorbing distribution rather thanNone
.
- Breaking change: outcomes with zero quantities are removed when constructing
Die
andDeck
.- Functions and methods relating to zero-quantities are removed:
align()
,align_range()
,Population.has_zero_quantities()
,Die.trim()
,Die.set_range()
,Die.set_outcomes()
. - You can use
consecutive()
orsorted_union()
to get an appropriate superset of sets of outcomes.
- Functions and methods relating to zero-quantities are removed:
- Breaking change:
MultisetEvaluator.alignment()
is renamed toMultisetEvaluator.extra_outcomes()
.MultisetEvaluator.range_alignment()
is renamed toMultisetEvaluator.consecutive()
.- The
Alignment
class is no longer public.
- Breaking change:
Deck.multiply_counts()
andPopulation.scale_quantities()
are replaced/renamed toPopulation.multiply_quantities()
etc. - Add
Deck.sequence()
andDie.sequence()
method. - Add
Population.pad_to_denominator()
method. - Move
zero()
andzero_outcome()
fromDie
toPopulation
. @
operator now sums left-to-right.- Remove old
compair
evaluation. min_outcome()
andmax_outcome()
free functions can now be called using a single iterable argument.- Forward algorithm now has a persistent cache.
- Add skip optimization for single deals with keep tuples.
- Pools now only skip dice, not outcomes. This is a bit slower in some cases but provides more consistent iteration order.
- Add shared evaluator instances for some built-in evaluator for caching.
- Simplify determination of outcome order for multiset evaluations.
- Simplify implementation of generator unbinding.
- Fix
extra_args
expansion formap_and_time
.
- Providing only a
drop
argument tolowest()
orhighest()
will now keep all other elements rather than just the first non-dropped element. depth
argument toDie.reroll()
is now mandatory.tuple
outcomes are now auto-tupleize
d again duringDie
construction.- Add
Die.stochastic_round()
method. - Add
Die.reroll_to_pool()
method. - Add
Die.keep()
method. This works asMultisetGenerator.keep()
with an implicit sum. - Add
percent
option toPopulation.probability
. - Add new
again_count
mode for handlingAgain
, which limits the total number of dice. - Improved ability to
keep
from both ends for certain types of multiset expressions. - Rename
func
parameters tofunction
. MultisetExpression.order()
is now public.- Improved sorting for
Symbols
; now compares counts in alphabetical order. - Experimental
sort_match
,maximum_match_highest
,maximum_match_lowest
expressions.sort_match
replaces thecompair
evaluations. - Experimental
all_straights_reduce_counts
andargsort
multiset evaluations. - Breaking change:
nearest
,quantity
,quantities
,probability
,probabilities
,keep_counts
no longer have separate variants for each comparison; instead, they now take a comparison argument.quantities
andprobabilities
now accept a comparison argument but no longer accept a list of outcomes.
- Rename
keep_counts
tokeep_counts_ge
. Addle
,lt
,gt
,eq
, andne
variants. - Add
count_subset
evaluation that counts how many times the right side is contained in the left. - Add
ImplicitConversionError
as subclass ofTypeError
. - Add binary multiset operators to
Deck
. - Add
modulo_counts
/%
operation on multisets. - Rebind generators and evaluate when fully bound non-generator expressions are given to an evaluator.
- Fix
Symbols
intersection. - Fix argument order in
__rfloordiv__
.
- Fix
Symbols
operator priority withPopulation
,AgainExpression
. - Added experimental
map_to_pool
andexplode_to_pool
methods. - Split
compair
intocompare_lt
etc. - Constructing a mixture of dice now effectively uses the old
lcm_joint
method, which reduces the denominator more aggressively.
- Experimental
Symbols
class representing a multiset of characters. marginals
now forwards__getattr__
to outcomes, as long as the attribute name doesn't begin with an underscore.- Operators on expressions now keep negative counts by default. The
keep_negative_counts
argument is retired. - Add unary
-
forMultisetExpression
. MultisetExpression.isdisjoint()
now raises an error for negative counts.- Small performance optimization for
Vector
. Population.marginals
is no longer aSequence
, since the mixins don't make sense.Mapping
s are now properly excluded fromPopulation.common_outcome_length
.- Fixed quoting in
repr
for populations.
- Add
z(n)
, which produces a die that runs from 0 ton - 1
inclusive. - Add
Population.to_one_hot()
, which converts the die or deck to a one-hot representation. - Add
Die.mean_time_to_sum()
, which computes the mean number of rolls until the cumulative sum is greater or equal to the target.
- Fix non-fully-bound case of
MultisetEvaluator.evaluate()
. - Add
default
argument tolowest(), highest(), middle()
. - Add
Population.entropy()
.
mean()
,variance()
, etc. now return an exactfractions.Fraction
when possible. (Note thatFraction
s only support float-style formatting from Python 3.12.)- Rename
disjoint_union
toadditive_union
. - Add
keep_negative_counts
keyword argument to+, -, &, |
binary operators for multiset expressions (defaultFalse
). - Symmetric difference (
^
) for multiset expressions is now a straight absolute difference of counts. - Add unary
+
operator for multiset expressions, which is the same askeep_counts(0)
.
Improve some error messages.
Fix a bug in MultisetExpression.keep_outcomes()
and drop_outcomes()
regarding unbinding variables.
MultisetExpression.map_counts()
now accepts multiple arguments.MultisetExpression.keep_outcomes()
anddrop_outcomes()
now accept an expression as an argument.MultisetExpression.highest_outcome_and_count()
now returns the min outcome if no outcomes have positive count.
highest
,lowest
, andmiddle
can now take a single iterable argument.- Add
all_straights
evaluation. all_counts
andall_straights
now output sizes in descending order.- Harmonize method and free function versions of
map
. Both now allow extra arguments and repeat. - Rename
filter_counts
tokeep_counts
. expand
evaluator now allows order to be set.- Experimental
compair
evaluation.
- Add HTML and BBCode options for population formatting.
- Renamed
apply
tomap
and the decorator version tomap_function
. - The above now uses
guess_star
. - Add default of 1 die for
Die.pool()
.
Fix mathematical bug in Die.reroll
for limited depth.
Retired implicit elementwise operations on tuples. This is now handled by a new explicit Vector
container.
cartesian_product()
is replaced by two new functions: tupleize()
and vectorize()
.
These compute the Cartesian product and produce a tuple
or Vector
respectively (or a die/deck thereof).
The Again
symbol is now used without parentheses. The name of the underlying type is now AgainExpression
.
die.zero()
now multiplies all outcomes by 0
to determine the zero-outcome rather than using the default constructor.
This allows it to work with Vector
's elementwise operations while still producing the expected result for
tuples, strings, etc.
Retired the linear algorithm for comparators for Die
. While the quadratic algorithm is slower, it allows for non-bool outputs.
die.tuple_len()
renamed to common_outcome_length
. Now applies to all sized outcome types.
- Counts type
Qs
is now invariant with more detailed typing inDeal
.
Incremented two versions because I messed up the last version number.
commonize_denominator
visible at top level.
- Rename
from_cumulative_quantities
tofrom_cumulative
and allow die inputs. - Mark
multiset_function
experimental again and note more caveats in the docstring.
- Add missing variants of
nearest
andquantities
methods. - Add optional
outcomes
argument toquantities
andprobabilities
methods.
map
and similar functions will attempt to guessstar
.- Changed
positive_only
parameter toexpression.all_counts
tofilter
. - Changed implementation of bound generators to unbind expressions rather than dynamically splitting.
- Retired
apply_sorted
and variants. - Add
outcome_function
decorator similar toapply
. - Add
map_counts
expression. Reroll
in tuple outcomes and joint evaluations causes the whole thing to be rerolled.
- Tuple outcomes can now be compared with single outcomes.
- Add
.keep, .highest, lowest, .middle
variants ofapply_sorted
. - Recommend
multiset_function
be used as a decorator, addupdate_wrapper
. - Add
keep_outcomes, drop_outcomes
methods to expressions. - Add
any
evaluation to expresions.
Comparisons on dice with tuple outcomes are now performed elementwise.
Testing GitHub workflows.
Expanded multiset processing with multiset expressions.
OutcomeCountGenerator
,OutcomeCountEvaluator
renamed toMultisetGenerator
,MultisetEvaluator
.multiset_function
is an easy way to create joint evaluators.Pool
indexing is now relative rather than absolute.- Renamed
pool.sorted_roll_counts
topool.keep
andpool.keep_tuple
. Die
versions ofsum_highest
etc. renamed to justhighest
; these always return dice.MultisetExpression
(including generators likePool
) havehighest()
returning an expression.Die
operators now does mixed vector-scalar binary operations by broadcasting the scalar.- Add
middle()
methods. - Remove
*generators
argument fromevaluator.order()
,evaluator.final_outcome()
. *generators
argument ofevaluator.alignment
replaced with the union of all generator outcomes.- Removed suits.
- Stop using
__class_getitem__
, which is intended for typing only.
Reworked built-in generators and evaluators.
- Generators now support multiset operations. These include:
- Multiset comparisons (
<, <=, >, >=, ==, !=, isdisjoint
), which produceDie[bool]
. - Multiset operators (
+
,-
,|
,&
,^
) which produce wrapped generators. - A suite of chainable count adjustments, including
multiply_counts
,divide_counts
,filter_counts
, andunique
.
- Multiset comparisons (
- Rename
median_left
tomedian_low
etc. - Generators and evaluators are now paramterized by count type as well.
- Move concrete evaluators to a submodule.
- Fixed weighting bug in
__matmul__
when the left die has an outcome of 0. - Retired the names
standard
andbernoulli
. These will be justd
andcoin
respectively. apply
now acceptsPool
arguments, which will haveexpand()
called on them.- Reinstate automatic Cartesian product in
Population
construction. if_else
now runs in two stages.
- Incremental sorting for
all_matching_sets
to reduce state space. lowest()
andhighest()
now actually visible.- Improved checking for tuple outcome sortability and types.
Prepend sum_
to OutcomeCountGenerator versions of highest
and lowest
.
Expanded typing, particularly in terms of parameterizing types.
Die
andDeck
constructors now expect exactly one nesting level, e.g. a Sequence of outcomes.- Removed
Die.bool()
. **kwargs
replaced with explcitagain_depth
,again_end
. RemovedOutcomeCountEvaluator.final_kwargs()
.- Split
include_steps
version ofDie.map()
into amap_and_time
method. - Split
include_outcome
version ofbest_matching_set
andbest_straight
into separate methods. - Rename
keep_highest
andhighest
tosum_highest
; add justhighest
for taking the single highest. - Same for
lowest
. - Added
cartesian_product()
, took this functionality out of theDie
constructor for now. - Added
OutcomeCountGenerator.all_matching_sets()
.
Die.sub()
renamed toDie.map()
.Die.map()
can now include the number of steps taken until absorption.Die.reroll_until()
renamed toDie.filter()
.wilds
arguments marked experimental, pending decision on how ordering should affect them.- Only tuples get separate columns in tables and not
str
orbytes
. - Non-recursive algorithm for
Again()
handling.
- Nested lists are now allowed in the
Die()
constructor. - Single outcomes can be sent to the
Die()
constructor without wrapping them in a list. - Same for sending a die to the
Pool()
constructor. - Add
Die.probabilities_lt()
,Die.probabilities_gt()
methods. - Add
wilds
argument tocontains_subset()
andintersection_size()
methods. - Removed
extra_dice
argument fromDie.sub()
. - Added
sub()
method toDeck
, though with less features than theDie
version. sum()
method of generators now has asub
option that maps outcomes before summing.expand()
method of generators now has aunique
option that counts duplicates only once.- Forwarding of
kwargs
toDie()
replaced with explicit arguments. - Add comparators to
Again
. - Experimental absorbing Markov chain analysis for
Die.sub(depth=None)
.
- Added
one_hot
function. - Added experimental suit generator that wraps a generator and produces counts for all suits for each value.
- Retired
denominator_method
. - Renamed
max_depth
parameters to justdepth
. - Binary operators delegate to
Again
's behavior. - Only single outcomes implicity convert to
Die
. marginals
is now a Sequence, and can be iterated over, unpacked, etc.Die.sub()
now expands extra die arguments into their outcomes.
Fix contains_again
checking of sequences.
New feature: Again()
, a placeholder that allows to roll again with some modification.
**kwargs
are forwarded to the constructor of the yielded or returned die forsub
,if_else
,reduce
,accumulate
,apply
,apply_sorted
.- Add optional
final_kwargs
method to evaluators. - Rename
max_depth
parameter ofsub()
torepeat
.
- Rename
Die.reduce()
toDie.simplify()
to avoid confusion with the free functionreduce()
. - Rename
OutcomeCountEvaluator.direction()
toorder()
and add explicitly namedOrder
enums. - Add
is_in
,count
, andcount_in
methods to dice. - Add built-in evaluators as convenience functions of
OutcomeCountGenerator
.
- Fixes to
max_depth=None
case ofsub()
. - This is now marked experimental.
- Pass
star
parameter tosub()
to recursive calls.
sub()
withmax_depth=None
now handles "monotonic" transitions with finite states. Full absorbing Markov chain calculation still under consideration.sub()
no longer accept sequence input.- Some minor formatting fixes.
- Standardize outcome count of
bernoulli
/coin
and comparators. standard_pool
now accepts adict
argument.post_roll_counts
renamed again tosorted_roll_counts
.apply_sorted
can be subscripted to set thesorted_roll_counts
.- Pools are no longer resizable after creation.
Die.pool()
now has mandatory argument, now accepts a sequence argument to setsorted_roll_counts
.
More renaming, experimental sample()
methods.
- Both
Die
andDeck
now havequantities
rather thanweight
,dups
, etc. - Many
Die
methods moved to base class and are now available toDeck
. - "Eval" is now the full word "Evaluator".
- Parameter and method names are no longer prefixed with "num_".
reduce_weights
renamed back toreduce
.Deck
s can be formatted likeDie
.- Allow formatting 0-1 probability.
- Experimental
sample()
methods forOutcomeCountGenerator
andOutcomeCountEvaluator
.
Development of deck API.
- Separate
Deal
class fromDeck
, roughly analogous toPool
vs.Die
. Deal
can now output multiple hands. The counts for each hand are provided in order toeval.next_state
.comb_row
now uses iterative rather than recursive memoization. This will prevent some stack overflows.Pool
s are not permitted to be constructed using a rawDie
orDeck
argument.reduce
argument ofDie.equals()
renamed toreduce_weights
.
Significant API changes, experimental deck support.
- Experimental
Deck
class. API still very unstable. Pool
s,Deck
s, and internal Alignment now have a common base classOutcomeCountGen
.EvalPool
renamed toOutcomeCountEval
.Die
andDeck
are now properMapping
s withkeys
,values
, anditems
.- The above view types can also be accessed like sequences.
- A
Die
is now always considered notequal()
to non-Die
. die[]
now works like a dict. Usemarginals[]
to marginalize dimensions.Die
,Pool
, andDeck
now take a single sequence or mapping argument rather than a variable number of arguments.Die
,Pool
, andDeck
now all have the same name for the second argument:times
.count_dice
renamed topost_roll_counts
. No longer acceptsNone
, use[:]
instead.- Linear algorithm for comparators on
Die
. - Improvements to internal
Count
class. - Add
clear_pool_cache
function. - Forward
*extra_args
forreroll, reroll_until, explode
.
Added type hints. Now requires Python 3.10 or later.
Other changes:
- Add
apply_sorted()
method. - Add
Die.set_range()
. standard()
/d()
argument is now positional-only.
Reinstate alternate internal EvalPool
algorithm, which provides better performance in some cases.
- Added a new
EvalPool.alignment()
method. This allows to specify an iterable of outcomes that should always be seen bynext_state
even if they have zero count. - The free function
d()
is now simply an alias forstandard()
. - Removed
Die.d()
. - The
@
operator now casts the right side to aDie
like other operators. - Some internal changes to
EvalPool
algorithm.
The data of a die resulting from ==
or !=
is lazily evaluated.
This saves computation in case the caller is only interested in the truth value.
EvalPool
favors the cached direction more.
Major reworking of pool construction.
- Public constructor is now just
Pool(*dice)
. - In particular, no more
truncate_min
ortruncate_max
arguments. - Pools can be of arbitrary dice, though non-truncative sets of dice will have lower performance. There is some performance penalty overall.
apply()
called with no arguments now callsfunc
once with no arguments.
- Removed
Die.keep()
. UseDie.pool(...).sum()
. highest
/lowest
returns empty die if any of the input dice are empty.
- Free-function form of
lowest
,highest
now selects between algorithms for better performance and generality. - Removed
die.lowest,
die.highest`. die.min_outcome
,die.max_outcome
no longer take arguments beyondself
.- No more (public)
repeat_and_sum
, as this is redundant with@
anddie.keep()
. - No more public
die.keep_lowest_single()
,die.keep_highest_single()
. count_dice
arguments are now keyword-only.die.zero()
no longer reduces weights to 1.- Update PyPi classifiers.
- Removed
min_outcome
parameter from die construction. - Operations on tuple outcomes are now performed recursively, to match the fact that die expansion on construction is recursive.
- Renamed
Die.reduce()
toDie.reduce_weights()
. - Added
reduce()
andaccumulate()
functions analogous to the functions of the same name from functools/itertools. - Add CSV output.
- Renamed
Die.markdown()
toDie.format_markdown()
. - Added
star
parameter tosub
,explode
,reroll
,reroll_until
methods. If set, this unpacks outcomes before giving them to the supplied function. - Added experimental
JointEval
class for performing two evals on the same roll of a pool.
- Operators other than
[]
are performed element-wise on tuples. - Rename
DicePool
to justPool
. Merge the old factory function into the constructor.
- Fix denominator_method='reduce' in die creation.
- Fix outcomes consisting of empty tuple
()
. apply()
with no dice produces an empty die.
Retired the EmptyDie
/ ScalarDie
/ VectorDie
distinction.
- There is now only one
Die
class; it behaves similarly to howScalarDie
used to. - There is no more
ndim
. - The
[]
operator now forwards to the outcome, acting similar to whatVectorDie.dim[]
used to do. - Removed
PoolEval.bind_dice()
. It was cute, but I'm not convinced it was worth spending API on.
- This will probably be the last version with a
VectorDie
distinction. - Dice cannot have negative weights.
VectorDie
cannot be nested inside tuple outcomes.
- Die and dict arguments to
Die()
are now expanded, including when nested. - Add
Die.if_else()
method, which acts as a ternary conditional operator on outcomes. - Dice are now hashable.
==
and!=
return dice with truth values based on whether the two dice have identical outcomes and weights. ndim
now uses singletonsicepool.Scalar
andicepool.Empty
.
EvalPool.eval()
can now be provided with single rolls of a pool. This can be a dict-like mapping individual die outcomes to counts or a sequence of individual die outcomes.EvalPool.next_state()
can not expect that the outcomes it sees are consecutive, though they are guaranteed to be seen in monotonic order.FindBestRun()
no longer assumes consecutive outcomes.- Added
DicePool.sample()
. - Added
die.truncate()
. min_outcomes
,max_outcomes
(for pool definitions) renamed totruncate_min
,truncate_max
.- Removed
die.getitem()
. DicePool
is no longer iterable, since there isn't an intuitive, unambiguous way of doing so.align_range()
now only operates on scalar outcomes.
- Renamed from
hdroller
toicepool
. - Primary repository is now https://github.com/HighDiceRoller/icepool.
- Only
tuple
s becomeVectorDie
. - Weights of 10^30 or above are not shown in tables by default.
- Add
max_depth
parameter tosub()
. If set toNone
this seeks a fixed point. - Add
'reduce'
option fordenominator_method
parameters. - Cache results of
repeat_and_sum()
.
- Add
ndim
keyword argument tod()
. - Removed
hitting_time()
method; it seems too niche to commit to. - Several arguments are now keyword-only.
- Fix to
reroll_until()
for vector dice.
- Add
VectorDie.all()
andVectorDie.any()
. - More fixes to
ndim
calculation.
EmptyDie
(a die with no outcomes) is now its own class.mix()
along with its weights argument is folded into theDie()
factory.- Fixes to
ndim
calculation. apply(), EvalPool.final_outcome()
can now return dice,hdroller.Reroll
, etc.- Center
Ellipsis
when indexing a pool can now work on undersized pools, rather than being an error. - Fix
lcm_weighted
denominator method. len(die)
is now the same asdie.num_outcomes()
again.- Slicing a die now refers to (sorted) outcome indexes.
- Dimension slicing is now
VectorDie.dim[select]
.
Die()
now takes a variable number of arguments. A sequence provided as a single argument will be treated as a single outcome equal to that sequence. To have one outcome per item in the sequence, the sequence must be unpacked into multiple arguments.min_outcome
andndim
args toDie()
are now keyword-only.- Non-integers are now allowed for
count_dice
. Use at your own risk. - The third argument to a
count_dice
slice, if provided, changes the size of the pool. - Up to one
Ellipsis
(...
) may now be used incount_dice
. This allows the tuple option to adapt to differently-sized pools. VectorDie
outcomes are now unpacked when providing them to callable arguments inreroll()
,explode()
,split()
.if_else()
is now a method ofScalarDie
rather than a free function.- Fixed the invert operator.
- Rerolls in pools,
mix()
, andsub()
are now triggered by a sentinel valuehdroller.Reroll
(rather thanNone
). - Single-
int
indexes forcount_dice
and pool[]
operator now produce a die rather than a pool, in analogy to sequence indexing. However, note that this is absolute relative to the whole pool rather than relative to any previous indexing. EvalPool
can now iterate in both directions even if one ofmax_outcomes
ormin_outcomes
is given, though at lower efficiency in the disfavored direction.- Default such direction changed back to ascending.
- Re-implemented
clip()
. - The minimum outcome of
highest()
is equal to the highest minimum outcome among all input dice and likewise forlowest()
. This will prevent introducing zero-weight outcomes where they did not exist before.
- Pool
max_outcomes
ormin_outcomes
outside the range of the fundamental die is now an error. - Pools no longer automatically shrink the die to fit
max_outcomes
ormin_outcomes
. This is to guarantee a predictable iteration order. - Improved
str(die)
formatting. VectorDie
outcomes are automatically converted to tuples.ScalarDie
now hasndim='scalar'
rather thanndim=False
.- Add
standard_pool()
function for easy creation of standard pools. - Removed
reroll_lt()
, etc. as they weren't enough faster thanreroll(func)
to justify spending extra space.
- Removed
initial_state()
in favor of usingNone
as the initial state. - Added simple
pool.eval()
method. None
now rerolls inEvalPool
.- Fix
trunc
,floor
,ceil
. - Various improvements to pool algorithm.
- Add some thresholding methods for dice.
- Max/min renamed to highest/lowest.
- Improve empty die handling.
- Improved
VectorDie
string formatting. - Disabled
reverse()
.
- Faster algorithm for keeping the single highest/lowest.
- Fix
from_sweights()
.
- Fix
max()
andmin()
casting to dice.
- Capitalize
Die()
andPool()
factory methods. PoolEval
renamed toEvalPool
.- Implemented
min_outcomes
for pools. Direction is now determined byEvalPool
. - Allow dice with zero weights or zero outcomes.
BaseDie
subclasses are nowScalarDie
andVectorDie
.==
and!=
compare outcomes again. Dice are no longer hashable by the standardhash()
.- Rewored
Pool()
arguments. - Added several methods.
- Fix
weights_le()
etc. set_outcomes()
is now public.
min_outcome()
,max_outcome()
now accept multiple dice.- Fix slice range going below zero.
num_dice
is now an optional parameter forkeep*()
andpool()
. Exactly one out ofnum_dice
,min_outcomes
, andmax_outcomes
should be provided.- Removed right-side cast for
@
operator, as it leads to confusion with either other operator casting ord()
casting. - Replaced key-value sequence option for
die()
with a sequence of weight-1 outcomes. - Add
has_zero_weights()
method to dice. align()
,align_range()
are now public.
- Remove numpy install dependency.
- Use the
@
operator andd()
instead of*
for "roll the die on the left, then roll that many dice on the right and sum". *
operator now multiplies.- Add
/
operator. - Add
median_left(), median_right(), ppf(), ppf_left(), ppf_right(), sample(), cmp(), sign()
.
No longer numpy-based. Major changes:
- API completely reworked.
- Weights are Python
int
s. This decreases performance but produces all exact results. - New
MultiDie
class representing multivariate distributions. PoolScorer
classes merged to a singlePoolEval
class.
This will most likely be the last numpy-based version.
- Pool scorers skip zero-weight outcomes.
- Removed
__bool__
since zero-weight dice are no longer allowed.
- Pool scorers can now return
None
states, which drops the state from evaluation, effectively performing a full reroll. - Operations that result in no remaining weight (e.g. rerolling all outcomes) now return None.
- Dice can no longer be constructed with zero total weight.
- The
Die()
constructor now auto-trims. Die._align()
is now private and no longer makes all the dice the same weight.- Fixed
Die.explode()
weighting. - Cleaned up unused functions.
- Optimize
Pool.pops()
by immediately removing all the dice if there are no left in the mask. Die.reroll
now tracks weights properly.
- Implemented new keep/pool algorithms, which make heavy use of caching. The
keep*()
function signatures changed. Die
is now hashable.- Empty
Die
is now an error. - Removed weight normalization.
- Added
%
and//
operators toDie
. - Renamed
ccdf
tosf
followingscipy
's naming.
best_set
now queries thescore_func
to determine possible outcomes, which allows more flexibility.
Die.align()
andDie.trim()
are now public.- Optimize
keep()
algorithm by skipping to results after passing the last kept die. - Add
best_set()
method for computing sets of matching dice.
The major change in this version is a new roll-and-keep algorithm. This can keep arbitrary indexes, as well as supporting dissimilar dice as long as they share a common "prefix" of weights.
Initial version.