### Install d20 via pip Source: https://github.com/avrae/d20/blob/master/README.md Use this command to install the d20 library in your Python environment. ```bash python3 -m pip install -U d20 ``` -------------------------------- ### Dice Selection Selectors Source: https://context7.com/avrae/d20/llms.txt Examples of using keep (k) and drop (p) selectors to filter dice results. ```python result = d20.roll("5d20kl2") # Keep lowest 2 print(str(result)) ``` ```python result = d20.roll("6d6k>3") # Keep dice greater than 3 print(str(result)) ``` ```python result = d20.roll("6d6p<3") # Drop dice less than 3 print(str(result)) ``` ```python result = d20.roll("4d6ro1kh3") print(str(result)) ``` -------------------------------- ### Execute complex dice expressions Source: https://github.com/avrae/d20/blob/master/README.md Examples of using advanced dice syntax including keep-highest, reroll-once, minimum values, and set operations. ```python >>> from d20 import roll >>> r = roll("4d6kh3") # highest 3 of 4 6-sided dice >>> r.total 14 >>> str(r) '4d6kh3 (4, 4, **6**, ~~3~~) = `14`' >>> r = roll("2d6ro<3") # roll 2d6s, then reroll any 1s or 2s once >>> r.total 9 >>> str(r) '2d6ro<3 (**~~1~~**, 3, **6**) = `9`' >>> r = roll("8d6mi2") # roll 8d6s, with each die having a minimum roll of 2 >>> r.total 33 >>> str(r) '8d6mi2 (1 -> 2, **6**, 4, 2, **6**, 2, 5, **6**) = `33`' >>> r = roll("(1d4 + 1, 3, 2d6kl1)kh1") # the highest of 1d4+1, 3, and the lower of 2 d6s >>> r.total 3 >>> str(r) '(1d4 (2) + 1, ~~3~~, ~~2d6kl1 (2, 5)~~)kh1 = `3`' ``` -------------------------------- ### Perform basic dice rolls Source: https://github.com/avrae/d20/blob/master/README.md Demonstrates basic usage of the d20 library to roll dice and inspect the result. ```python >>> import d20 >>> result = d20.roll("1d20+5") >>> str(result) '1d20 (10) + 5 = `15`' >>> result.total 15 >>> result.crit >>> str(result.ast) '1d20 + 5' ``` -------------------------------- ### Benchmark d20 performance with caching Source: https://github.com/avrae/d20/blob/master/README.md Measures execution time for various dice expressions using the default LFU caching mechanism. ```bash $ python3 -m timeit -s "from d20 import roll" "roll('1d20')" 10000 loops, best of 5: 21.6 usec per loop $ python3 -m timeit -s "from d20 import roll" "roll('100d20')" 500 loops, best of 5: 572 usec per loop $ python3 -m timeit -s "from d20 import roll; expr='1d20+'*50+'1d20'" "roll(expr)" 500 loops, best of 5: 732 usec per loop $ python3 -m timeit -s "from d20 import roll" "roll('10d20rr<20')" 1000 loops, best of 5: 1.13 msec per loop ``` -------------------------------- ### d20.BinOp Object Source: https://github.com/avrae/d20/blob/master/docs/expression.rst Represents a binary operation within the expression tree. ```APIDOC ## d20.BinOp ### Description Represents a binary operation (e.g., addition, subtraction) in the expression tree. ### Attributes - **op** (str): The binary operation symbol. - **left** (d20.Number): The left operand. - **right** (d20.Number): The right operand. ``` -------------------------------- ### d20.ast.Node Source: https://github.com/avrae/d20/blob/master/docs/ast.rst Base class for all nodes in the Abstract Syntax Tree. ```APIDOC ## d20.ast.Node ### Description Base class for all nodes within the Abstract Syntax Tree. ### Inheritance Inherits from: (Implicitly, as it's a base class) ``` -------------------------------- ### Manage Sets and Parenthetical Expressions Source: https://context7.com/avrae/d20/llms.txt Group expressions using parentheses or define sets for complex mechanics. ```python import d20 # Simple parenthetical (no comma = just grouping) result = d20.roll("(1d6 + 2) * 2") print(str(result)) # Set with single element (trailing comma required) result = d20.roll("(1d6,)") print(str(result)) # Treated as a set ``` -------------------------------- ### d20.ast.BinOp Source: https://github.com/avrae/d20/blob/master/docs/ast.rst Represents a binary operation in the expression. ```APIDOC ## d20.ast.BinOp ### Description Represents a binary operation applied to two operands. ### Inheritance Inherits from: `d20.ast.Node` ### Attributes #### `op` - **Type**: `str` - **Description**: The string identifier for the binary operation (e.g., '+', '-', '*', '/'). #### `left` - **Type**: `d20.ast.Node` - **Description**: The AST node representing the left operand. #### `right` - **Type**: `d20.ast.Node` - **Description**: The AST node representing the right operand. ``` -------------------------------- ### d20.ast.ChildMixin Source: https://github.com/avrae/d20/blob/master/docs/ast.rst Mixin for AST nodes that have children, providing methods for tree traversal. ```APIDOC ## d20.ast.ChildMixin ### Description A mixin class for AST nodes that possess children, facilitating tree traversal. ### Methods #### `children` (property) - **Description**: (read-only) Returns the children of this object, typically used for traversing a tree. - **Returns**: `list[Node]` #### `left` (property) - **Description**: Returns the leftmost child of this object, usually used for traversing a tree. - **Returns**: `Node` #### `right` (property) - **Description**: Returns the rightmost child of this object, usually used for traversing a tree. - **Returns**: `Node` ### Methods #### `set_child` - **Description**: Sets a child node for this object. ``` -------------------------------- ### Simplify and Transform Expressions Source: https://context7.com/avrae/d20/llms.txt Use the utils module to manipulate expression trees, simplify annotations, and apply advantage or disadvantage modifiers. ```python import d20 from d20 import utils # Simplify annotations - bubble up damage types roll_expr = d20.roll("1d20[attack] + 3").expr utils.simplify_expr_annotations(roll_expr.roll) print(d20.SimpleStringifier().stringify(roll_expr)) # Full expression simplification - collapse to final values by annotation damage_roll = d20.roll("2d6[fire] + 1d4[cold] + 3[fire]").expr utils.simplify_expr(damage_roll) print(d20.SimpleStringifier().stringify(damage_roll)) # Output shows fire and cold damage separated # ambig_inherit controls how unannotated children inherit types roll_expr = d20.roll("1d6[fire] + 2").expr utils.simplify_expr_annotations(roll_expr.roll, ambig_inherit='left') # The '2' inherits 'fire' annotation # AST advantage copy - transform 1d20 to advantage/disadvantage parsed = d20.parse("1d20 + 5") adv_ast = utils.ast_adv_copy(parsed, d20.AdvType.ADV) print(str(adv_ast)) # '2d20kh1 + 5' dis_ast = utils.ast_adv_copy(parsed, d20.AdvType.DIS) print(str(dis_ast)) # '2d20kl1 + 5' ``` -------------------------------- ### Benchmark d20 performance without caching Source: https://github.com/avrae/d20/blob/master/README.md Measures execution time for various dice expressions when caching is disabled. ```bash $ python3 -m timeit -s "from d20 import roll" "roll('1d20')" 5000 loops, best of 5: 61.6 usec per loop $ python3 -m timeit -s "from d20 import roll" "roll('100d20')" 500 loops, best of 5: 620 usec per loop $ python3 -m timeit -s "from d20 import roll; expr='1d20+'*50+'1d20'" "roll(expr)" 500 loops, best of 5: 2.1 msec per loop $ python3 -m timeit -s "from d20 import roll" "roll('10d20rr<20')" 1000 loops, best of 5: 1.26 msec per loop ``` -------------------------------- ### Use Annotations and Comments Source: https://github.com/avrae/d20/blob/master/README.md Add visual tags to dice rolls using brackets, or enable comments with the allow_comments parameter. ```python >>> from d20 import roll >>> str(roll("3d6 [fire] + 1d4 [piercing]")) '3d6 (3, 2, 2) [fire] + 1d4 (3) [piercing] = `10`' >>> str(roll("-(1d8 + 3) [healing]")) '-(1d8 (7) + 3) [healing] = `-10`' >>> str(roll("(1 [one], 2 [two], 3 [three])")) '(1 [one], 2 [two], 3 [three]) = `6`' ``` ```python >>> from d20 import roll >>> result = roll("1d20 I rolled a d20", allow_comments=True) >>> str(result) '1d20 (13) = `13`' >>> result.comment 'I rolled a d20' ``` -------------------------------- ### Customize Dice Stringification Source: https://github.com/avrae/d20/blob/master/README.md Implement a custom stringifier by subclassing d20.SimpleStringifier and passing it to the roll function. ```python >>> import d20 >>> class MyStringifier(d20.SimpleStringifier): ... def _stringify(self, node): ... if not node.kept: ... return 'X' ... return super()._stringify(node) ... ... def _str_expression(self, node): ... return f"The result of the roll {self._stringify(node.roll)} was {int(node.total)}" >>> result = d20.roll("4d6e6kh3", stringifier=MyStringifier()) >>> str(result) 'The result of the roll 4d6e6kh3 (X, 5, 6!, 6!, X, X) was 17' ``` -------------------------------- ### d20.Stringifier Class Source: https://github.com/avrae/d20/blob/master/docs/api.rst Handles the conversion of expressions into string representations. ```APIDOC ## Class d20.Stringifier ### Description Base class for converting dice expressions into strings. Includes methods for stringifying various AST nodes. ### Methods - **stringify** - Converts the expression to a string. - **_stringify** - Internal stringification method. - **_str_expression** - Stringifies an expression node. - **_str_literal** - Stringifies a literal node. - **_str_unop** - Stringifies a unary operation. - **_str_binop** - Stringifies a binary operation. - **_str_dice** - Stringifies a dice node. ``` -------------------------------- ### d20.Set Object Source: https://github.com/avrae/d20/blob/master/docs/expression.rst Represents a set of numbers, potentially with associated operations. ```APIDOC ## d20.Set ### Description Represents a set of numbers, often resulting from dice rolls. ### Attributes - **values** (list[d20.Number]): The numbers within the set. - **operations** (list[d20.SetOperation]): Operations to be performed on the set. ``` -------------------------------- ### d20.UnOp Object Source: https://github.com/avrae/d20/blob/master/docs/expression.rst Represents a unary operation within the expression tree. ```APIDOC ## d20.UnOp ### Description Represents a unary operation (e.g., negation) in the expression tree. ### Attributes - **op** (str): The unary operation symbol. - **value** (d20.Number): The operand for the operation. ``` -------------------------------- ### Find Operands and Search Nodes Source: https://github.com/avrae/d20/blob/master/README.md Use tree traversal or utility functions to find specific nodes within the expression tree. ```python >>> from d20 import roll >>> binop = roll("1 + 2 + 3 + 4") >>> left = binop.expr >>> while left.children: ... left = left.children[0] >>> left >>> right = binop.expr >>> while right.children: ... right = right.children[-1] >>> right >>> from d20 import utils # these patterns are available in the utils submodule: >>> utils.leftmost(binop.expr) >>> utils.rightmost(binop.expr) ``` ```python >>> from d20 import roll, Dice, SimpleStringifier, utils >>> mixed = roll("-1d8 + 4 - (3, 1d4)kh1") >>> str(mixed) '-1d8 (**8**) + 4 - (3, ~~1d4 (3)~~)kh1 = `-7`' >>> root = mixed.expr >>> result = utils.dfs(root, lambda node: isinstance(node, Dice) and node.num == 1 and node.size == 4) >>> result ]>] operations=[]> >>> SimpleStringifier().stringify(result) '1d4 (3)' ``` -------------------------------- ### Configure Roll Context and Limits Source: https://context7.com/avrae/d20/llms.txt Control the maximum number of dice rolls allowed in a context to prevent infinite loops or excessive resource usage. ```python # Default context allows 1000 rolls roller = d20.Roller() result = roller.roll("100d20") # Works fine # Custom context with lower limit strict_context = d20.RollContext(max_rolls=100) strict_roller = d20.Roller(context=strict_context) try: result = strict_roller.roll("200d20") # Would need 200 rolls except d20.TooManyRolls as e: print(f"Error: {e}") # 'Too many dice rolled.' # Reroll operations count towards the limit try: # Could theoretically roll forever result = strict_roller.roll("10d20rr<20") except d20.TooManyRolls: print("Reroll limit exceeded") # Exploding dice also count try: result = strict_roller.roll("50d6e6") # Each 6 adds another roll except d20.TooManyRolls: print("Explode limit exceeded") # Context is reset between rolls result1 = strict_roller.roll("50d20") # Uses 50 rolls result2 = strict_roller.roll("50d20") # Fresh 50 rolls, not cumulative ``` -------------------------------- ### d20.Parenthetical Object Source: https://github.com/avrae/d20/blob/master/docs/expression.rst Represents a sub-expression enclosed in parentheses. ```APIDOC ## d20.Parenthetical ### Description Represents a sub-expression enclosed in parentheses. ### Attributes - **value** (d20.Number): The expression within the parentheses. - **operations** (list[d20.SetOperation]): Operations to apply if the parenthetical contains a Set. ``` -------------------------------- ### d20.ast.NumberSet Source: https://github.com/avrae/d20/blob/master/docs/ast.rst Represents a set of numbers. ```APIDOC ## d20.ast.NumberSet ### Description Represents a collection of numbers, potentially structured as a set. ### Inheritance Inherits from: `d20.ast.Node` ### Attributes #### `values` - **Type**: `list[d20.ast.NumberSet]` - **Description**: A list containing the elements of the number set. Note: The type hint suggests recursive structure. ``` -------------------------------- ### d20.ast.Parenthetical Source: https://github.com/avrae/d20/blob/master/docs/ast.rst Represents a sub-expression enclosed in parentheses. ```APIDOC ## d20.ast.Parenthetical ### Description Represents a part of the expression that is enclosed in parentheses. ### Inheritance Inherits from: `d20.ast.Node` ### Attributes #### `value` - **Type**: `d20.ast.Node` - **Description**: The AST node representing the expression contained within the parentheses. ``` -------------------------------- ### d20.ast.UnOp Source: https://github.com/avrae/d20/blob/master/docs/ast.rst Represents a unary operation in the expression. ```APIDOC ## d20.ast.UnOp ### Description Represents a unary operation applied to a single operand. ### Inheritance Inherits from: `d20.ast.Node` ### Attributes #### `op` - **Type**: `str` - **Description**: The string identifier for the unary operation (e.g., '+', '-'). #### `value` - **Type**: `d20.ast.Node` - **Description**: The AST node representing the operand to which the operation is applied. ``` -------------------------------- ### d20.SetSelector Object Source: https://github.com/avrae/d20/blob/master/docs/expression.rst Defines criteria for selecting elements within a set. ```APIDOC ## d20.SetSelector ### Description Defines the criteria for selecting elements from a set. ### Attributes - **cat** (Optional[str]): The category of selection (e.g., 'lowest', 'highest', 'literal'). - **num** (int): The number associated with the selection criteria (e.g., the N in 'lowest N'). ### Methods - **select(set)**: Selects elements from a set based on the selector's criteria. ``` -------------------------------- ### d20.roll - Quick Dice Rolling Source: https://context7.com/avrae/d20/llms.txt The primary entry point for rolling dice. Takes a dice expression string and returns a RollResult object containing the total, individual die values, and a formatted string representation. ```APIDOC ## d20.roll - Quick Dice Rolling ### Description The primary entry point for rolling dice. Takes a dice expression string and returns a RollResult object containing the total, individual die values, and a formatted string representation. ### Method POST (conceptual, as it's a function call) ### Endpoint N/A (Python function) ### Parameters #### Query Parameters - **expression** (string) - Required - The dice expression string (e.g., "1d20+5"). - **allow_comments** (boolean) - Optional - If true, parses text after the expression as a comment. ### Request Example ```python import d20 # Basic roll with modifier result = d20.roll("1d20+5") print(str(result)) # '1d20 (10) + 5 = `15`' print(result.total) # 15 print(result.crit) # CritType.NORMAL (0), CritType.CRIT (1), or CritType.FAIL (2) # Multiple dice with keep highest result = d20.roll("4d6kh3") print(str(result)) # '4d6kh3 (4, 4, **6**, ~~3~~) = `14`' # Complex expression with sets result = d20.roll("(1d4 + 1, 3, 2d6kl1)kh1") print(str(result)) # '(1d4 (2) + 1, ~~3~~, ~~2d6kl1 (2, 5)~~)kh1 = `3`' # Roll with annotations for damage types result = d20.roll("3d6 [fire] + 1d4 [piercing]") print(str(result)) # '3d6 (3, 2, 2) [fire] + 1d4 (3) [piercing] = `10`' # Roll with comments (parses text after expression) result = d20.roll("1d20 I rolled a d20", allow_comments=True) print(str(result)) # '1d20 (13) = `13`' print(result.comment) # 'I rolled a d20' ``` ### Response #### Success Response (200) - **RollResult** (object) - Contains the results of the dice roll. - **total** (integer) - The sum of the dice roll. - **crit** (CritType enum) - Indicates critical success, failure, or normal. - **comment** (string, optional) - The comment parsed from the expression if `allow_comments` is true. #### Response Example ```json { "total": 15, "crit": "NORMAL", "comment": null } ``` ``` -------------------------------- ### Expression Tree Traversal Source: https://context7.com/avrae/d20/llms.txt Access and manipulate the expression tree to analyze components or modify roll results programmatically. ```python import d20 from d20 import utils, Dice, SimpleStringifier # Access the expression tree result = d20.roll("3d6 + 1d4 + 3") print(result.expr) # comment=None> # Find leftmost and rightmost nodes binop = d20.roll("1 + 2 + 3 + 4") left = utils.leftmost(binop.expr) right = utils.rightmost(binop.expr) print(left) # print(right) # # Manual tree traversal expr = d20.roll("1 + 2 + 3").expr node = expr while node.children: print(f"Node: {node}, Children: {len(node.children)}") node = node.children[0] # Search for specific dice using depth-first search mixed = d20.roll("-1d8 + 4 - (3, 1d4)kh1") d4 = utils.dfs(mixed.expr, lambda node: isinstance(node, Dice) and node.num == 1 and node.size == 4) print(SimpleStringifier().stringify(d4)) # '1d4 (3)' # Tree mapping - transform all nodes def double_literals(node): if isinstance(node, d20.Literal): node.values[-1] *= 2 return node parsed = d20.parse("1d20 + 5") # Note: tree_map works on AST nodes, not expression nodes ``` -------------------------------- ### Roll nested sets Source: https://context7.com/avrae/d20/llms.txt Demonstrates nesting sets to perform hierarchical dice operations. ```python result = d20.roll("((1d4, 1d6)kh1, 1d8)kh1") print(str(result)) ``` -------------------------------- ### Configure Dice Roller Behavior Source: https://context7.com/avrae/d20/llms.txt The Roller class allows for custom roll contexts, such as setting maximum roll limits or handling advantage/disadvantage, and supports reusing parsed ASTs. ```python import d20 # Create a roller with custom roll limits context = d20.RollContext(max_rolls=500) roller = d20.Roller(context=context) # Roll with the configured roller result = roller.roll("10d20") print(result.total) # Parse expression separately for reuse parsed_ast = roller.parse("2d6+3") print(str(parsed_ast)) # '2d6 + 3' # Roll a pre-parsed AST multiple times for _ in range(3): result = roller.roll(parsed_ast) print(result.total) # Roll with advantage (changes 1d20 to 2d20kh1) result = roller.roll("1d20+5", advantage=d20.AdvType.ADV) print(str(result)) # '2d20kh1 (12, **17**) + 5 = `22`' # Roll with disadvantage (changes 1d20 to 2d20kl1) result = roller.roll("1d20+5", advantage=d20.AdvType.DIS) print(str(result)) # '2d20kl1 (**8**, 15) + 5 = `13`' ``` -------------------------------- ### d20.Die Object Source: https://github.com/avrae/d20/blob/master/docs/expression.rst Represents a single die with a specific number of sides. ```APIDOC ## d20.Die ### Description Represents a single die. ### Attributes - **size** (int): The number of sides on the die. - **values** (list[d20.Literal]): The history of values rolled by this die. ``` -------------------------------- ### d20.ast.Literal Source: https://github.com/avrae/d20/blob/master/docs/ast.rst Represents a literal numerical value. ```APIDOC ## d20.ast.Literal ### Description Represents a literal numerical value within the expression. ### Inheritance Inherits from: `d20.ast.Node` ### Attributes #### `value` - **Type**: `Union[int, float]` - **Description**: The actual numerical value (integer or float). ``` -------------------------------- ### d20.ast.SetSelector Source: https://github.com/avrae/d20/blob/master/docs/ast.rst Specifies criteria for selecting elements from a set. ```APIDOC ## d20.ast.SetSelector ### Description Defines the criteria for selecting elements from a set, used by `SetOperator`. ### Attributes #### `cat` - **Type**: `Optional[str]` - **Description**: The category of selection (e.g., 'lowest', 'highest', 'literal'). #### `num` - **Type**: `int` - **Description**: The number associated with the selection criteria (e.g., the 'N' in 'lowest N', or the literal value). ``` -------------------------------- ### d20.Expression Object Source: https://github.com/avrae/d20/blob/master/docs/expression.rst The root object representing a parsed dice expression. ```APIDOC ## d20.Expression ### Description Represents the overall parsed dice expression. ### Attributes - **roll** (d20.Number): The primary roll result of the expression. - **comment** (Optional[str]): An optional comment associated with the expression. ``` -------------------------------- ### d20.Number Object Source: https://github.com/avrae/d20/blob/master/docs/expression.rst Represents a number within the expression tree, potentially with tracking for kept/dropped values and annotations. ```APIDOC ## d20.Number ### Description Represents a numerical value within the expression tree. It tracks whether the number was kept or dropped in a calculation and can have an associated annotation. ### Attributes - **number** (int/float): The numerical value. - **total** (int/float): The total value, considering operations. - **set** (bool): Indicates if this number is part of a set. - **keptset** (bool): Indicates if this number was kept within a set operation. - **drop** (bool): Indicates if this number was dropped within a set operation. - **kept** (bool): Whether this Number was kept or dropped in the final calculation. - **annotation** (Optional[str]): The annotation on this Number, if any. ### Properties - **children** (list[Number]): (read-only) The children of this Number, used for traversing the expression tree. - **left** (Number): The leftmost child of this Number. - **right** (Number): The rightmost child of this Number. ### Methods - **set_child(child)**: Sets a child for this Number. ``` -------------------------------- ### Custom Stringifiers for Output Formatting Source: https://context7.com/avrae/d20/llms.txt Implement custom stringifiers to control how roll results are displayed, such as hiding dropped dice or generating HTML. ```python import d20 # Built-in SimpleStringifier (plain text) result = d20.roll("2d6+3", stringifier=d20.SimpleStringifier()) print(str(result)) # '2d6 (3, 5) + 3 = 11' # Built-in MarkdownStringifier (default, with bold crits and strikethrough drops) result = d20.roll("4d6kh3", stringifier=d20.MarkdownStringifier()) print(str(result)) # '4d6kh3 (4, **6**, 5, ~~2~~) = `15`' # Custom stringifier that hides dropped dice class HideDroppedStringifier(d20.SimpleStringifier): def _stringify(self, node): if not node.kept: return 'X' return super()._stringify(node) def _str_expression(self, node): return f"Result: {self._stringify(node.roll)} = {int(node.total)}" result = d20.roll("4d6kh3", stringifier=HideDroppedStringifier()) print(str(result)) # 'Result: 4d6kh3 (4, 5, 6, X) = 15' # Custom stringifier for HTML output class HTMLStringifier(d20.SimpleStringifier): def _stringify(self, node): if not node.kept: return f'{super()._stringify(node)}' return super()._stringify(node) def _str_expression(self, node): return f'{self._stringify(node.roll)} = {int(node.total)}' def _str_die(self, node): the_rolls = [] for val in node.values: inside = self._stringify(val) if val.number == 1 or val.number == node.size: inside = f'{inside}' the_rolls.append(inside) return ', '.join(the_rolls) result = d20.roll("2d20kh1+5", stringifier=HTMLStringifier()) print(str(result)) ``` -------------------------------- ### Perform Arithmetic and Comparison Operations Source: https://context7.com/avrae/d20/llms.txt Execute standard math and comparison operators on dice expressions, respecting operator precedence. ```python import d20 # Arithmetic operations print(d20.roll("2d6 + 3").total) # Addition print(d20.roll("2d6 - 2").total) # Subtraction print(d20.roll("2d6 * 2").total) # Multiplication (crits!) print(d20.roll("10 / 2").total) # Division (returns float internally) print(d20.roll("10 // 3").total) # Integer division print(d20.roll("10 % 3").total) # Modulo # Comparison operations (return 1 for true, 0 for false) print(d20.roll("1d20 > 10").total) # Greater than print(d20.roll("1d20 < 10").total) # Less than print(d20.roll("1d20 >= 10").total) # Greater or equal print(d20.roll("1d20 <= 10").total) # Less or equal print(d20.roll("1d20 == 15").total) # Equality print(d20.roll("1d20 != 1").total) # Inequality # Unary operations print(d20.roll("-1d6").total) # Negative (for healing as damage) print(d20.roll("+1d6").total) # Positive (no-op) # Complex expressions with proper precedence print(d20.roll("2d6 + 3 * 2").total) # Multiplication before addition print(d20.roll("(2d6 + 3) * 2").total) # Parentheses for grouping ``` -------------------------------- ### Apply keep-highest and keep-lowest modifiers Source: https://context7.com/avrae/d20/llms.txt Uses kh (keep highest) and kl (keep lowest) modifiers to select specific results from a set of expressions. ```python result = d20.roll("(1d4 + 1, 3, 2d6kl1)kh1") print(str(result)) # Keeps the highest of the three options ``` ```python result = d20.roll("(1d20, 1d20)kl1") # Another way to do disadvantage print(str(result)) ``` ```python result = d20.roll("(1d6, 2d4, 3)kh2") # Keep highest 2 values print(str(result)) ``` -------------------------------- ### Roll sets with multiple elements Source: https://context7.com/avrae/d20/llms.txt Calculates the sum of all elements provided within a set. ```python result = d20.roll("(1, 2, 3)") print(result.total) # 6 (sum of all) ``` -------------------------------- ### d20.Literal Object Source: https://github.com/avrae/d20/blob/master/docs/expression.rst Represents a literal numerical value within the expression tree. ```APIDOC ## d20.Literal ### Description Represents a literal numerical value in the expression tree. ### Attributes - **values** (list[Union[int, float]]): The history of numbers this literal has represented. - **exploded** (bool): Whether this literal was part of a Die that exploded. ### Methods - **explode()**: Marks that this literal was part of an exploding Die. - **update(value)**: Changes the literal value this literal represents. - **value** (Union[int, float]): The new value. ``` -------------------------------- ### d20.ast.OperatedSet Source: https://github.com/avrae/d20/blob/master/docs/ast.rst Represents a set of numbers with operations applied to it. ```APIDOC ## d20.ast.OperatedSet ### Description Represents a set of numbers upon which various operations are performed. ### Inheritance Inherits from: `d20.ast.Node` ### Attributes #### `value` - **Type**: `d20.ast.NumberSet` - **Description**: The `NumberSet` object that the operations are applied to. #### `operations` - **Type**: `list[d20.SetOperation]` - **Description**: A list of set operations to be executed on the `value`. ``` -------------------------------- ### d20.ast.AnnotatedNumber Source: https://github.com/avrae/d20/blob/master/docs/ast.rst Represents a number with associated annotations. ```APIDOC ## d20.ast.AnnotatedNumber ### Description Represents a numerical value that has been annotated. ### Inheritance Inherits from: `d20.ast.Node` ### Attributes #### `value` - **Type**: `d20.ast.Node` - **Description**: The subtree representing the annotated numerical value. #### `annotations` - **Type**: `list[str]` - **Description**: A list of string annotations applied to the value. ``` -------------------------------- ### d20.Dice Object Source: https://github.com/avrae/d20/blob/master/docs/expression.rst Represents a collection of dice of the same size. ```APIDOC ## d20.Dice ### Description Represents a collection of dice of the same size. ### Attributes - **num** (int): The number of dice in the collection. - **size** (int): The number of sides on each die. - **values** (list[d20.Die]): The individual Die objects in the collection. - **operations** (list[d20.SetOperation]): Operations to be performed on the set of dice. ### Methods - **roll_another()**: Rolls another Die of the appropriate size and adds it to this set. ``` -------------------------------- ### Perform Quick Dice Rolls Source: https://context7.com/avrae/d20/llms.txt Use d20.roll to evaluate dice strings directly. This method returns a RollResult object containing the total, individual die values, and a formatted string. ```python import d20 # Basic roll with modifier result = d20.roll("1d20+5") print(str(result)) # '1d20 (10) + 5 = `15`' print(result.total) # 15 print(result.crit) # CritType.NORMAL (0), CritType.CRIT (1), or CritType.FAIL (2) # Multiple dice with keep highest result = d20.roll("4d6kh3") print(str(result)) # '4d6kh3 (4, 4, **6**, ~~3~~) = `14`' # Complex expression with sets result = d20.roll("(1d4 + 1, 3, 2d6kl1)kh1") print(str(result)) # '(1d4 (2) + 1, ~~3~~, ~~2d6kl1 (2, 5)~~)kh1 = `3`' # Roll with annotations for damage types result = d20.roll("3d6 [fire] + 1d4 [piercing]") print(str(result)) # '3d6 (3, 2, 2) [fire] + 1d4 (3) [piercing] = `10`' # Roll with comments (parses text after expression) result = d20.roll("1d20 I rolled a d20", allow_comments=True) print(str(result)) # '1d20 (13) = `13`' print(result.comment) # 'I rolled a d20' ``` -------------------------------- ### d20.SetOperator Object Source: https://github.com/avrae/d20/blob/master/docs/expression.rst Defines an operation to be performed on a set. ```APIDOC ## d20.SetOperator ### Description Defines a set operation, including the type of operation and how to select operands. ### Attributes - **op** (str): The type of operation (e.g., 'lowest', 'highest'). - **sels** (list[d20.SetSelector]): The selectors used to choose operands for the operation. ### Methods - **select(set)**: Selects operands from a set based on the defined selectors. - **operate(set)**: Performs the defined operation on the selected operands of a set. ``` -------------------------------- ### RollContext Execution Limits Source: https://context7.com/avrae/d20/llms.txt Use RollContext to prevent resource exhaustion by limiting the number of dice rolled. ```python import d20 ``` -------------------------------- ### d20.ast.SetOperator Source: https://github.com/avrae/d20/blob/master/docs/ast.rst Defines an operation to be performed on a set. ```APIDOC ## d20.ast.SetOperator ### Description Defines a specific operation to be applied to elements selected from a set. ### Attributes #### `op` - **Type**: `str` - **Description**: The type of operation (e.g., 'lowest', 'highest'). #### `sels` - **Type**: `list[d20.SetSelector]` - **Description**: A list of selectors that determine which elements from the set are used for the operation. ``` -------------------------------- ### Handle Roll Exceptions Source: https://context7.com/avrae/d20/llms.txt Catch specific exceptions like syntax errors, value errors, and execution limits during dice evaluation. ```python import d20 # RollSyntaxError - invalid dice syntax try: result = d20.roll("1d20 + + 5") except d20.RollSyntaxError as e: print(f"Syntax error at line {e.line}, col {e.col}") print(f"Got: {e.got}, Expected: {e.expected}") # RollValueError - invalid values during evaluation try: result = d20.roll("1d0") # Can't roll 0-sided die except d20.RollValueError as e: print(f"Value error: {e}") # 'Cannot roll a 0-sided die.' try: result = d20.roll("10 / 0") except d20.RollValueError as e: print(f"Value error: {e}") # 'Cannot divide by zero.' # TooManyRolls - execution limit exceeded context = d20.RollContext(max_rolls=10) roller = d20.Roller(context=context) try: result = roller.roll("100d20") except d20.TooManyRolls as e: print(f"Limit error: {e}") # 'Too many dice rolled.' # Generic RollError - base class for all errors try: result = d20.roll("invalid") except d20.RollError as e: print(f"Some roll error occurred: {e}") ``` -------------------------------- ### d20.ast.Dice Source: https://github.com/avrae/d20/blob/master/docs/ast.rst Represents a standard dice roll (e.g., 2d6). ```APIDOC ## d20.ast.Dice ### Description Represents a standard dice roll, specifying the number of dice and their size. ### Inheritance Inherits from: `d20.ast.Node` ### Attributes #### `num` - **Type**: `int` - **Description**: The number of dice to roll. #### `size` - **Type**: `int` - **Description**: The number of sides on each die. ``` -------------------------------- ### Dice Operators - Keep, Drop, Reroll, Explode Source: https://context7.com/avrae/d20/llms.txt d20 supports a comprehensive set of operators for manipulating dice rolls, including keeping/dropping dice, rerolling, exploding, and setting min/max values. ```APIDOC ## Dice Operators - Keep, Drop, Reroll, Explode ### Description d20 supports a comprehensive set of operators for manipulating dice rolls, including keeping/dropping dice, rerolling, exploding, and setting min/max values. ### Method POST (conceptual, as it's function calls) ### Endpoint N/A (Python function calls) ### Parameters These operators are part of the dice expression string passed to `d20.roll` or `roller.roll`. - **Keep Highest (kh)**: `NdXkhY` - Keeps the Y highest dice from N dice of X sides. - **Keep Lowest (kl)**: `NdXklY` - Keeps the Y lowest dice from N dice of X sides. - **Drop Highest (ph)**: `NdXphY` - Drops the Y highest dice from N dice of X sides. - **Drop Lowest (pl)**: `NdXplY` - Drops the Y lowest dice from N dice of X sides. - **Reroll Less Than (rr<)**: `NdXrr 2, **6**, 4, 2, **6**, 2, 5, **6**) = `33`' # Set maximum value of 3 per die result = d20.roll("4d6ma3") print(str(result)) # '4d6ma3 (3, 5 -> 3, 2, **6** -> 3) = `11`' # Reroll and add (explode once) result = d20.roll("1d6ra6") print(str(result)) # '1d6ra6 (6!, 3) = `9`' ``` ### Response #### Success Response (200) - **RollResult** (object) - The result of the dice roll, with operators applied. #### Response Example ```json { "total": 14, "crit": "NORMAL", "comment": null } ``` ``` -------------------------------- ### d20.Roller - Configurable Dice Roller Source: https://context7.com/avrae/d20/llms.txt The Roller class provides full control over dice rolling behavior, including custom roll contexts for limiting dice operations and reusable parsing. ```APIDOC ## d20.Roller - Configurable Dice Roller ### Description The Roller class provides full control over dice rolling behavior, including custom roll contexts for limiting dice operations and reusable parsing. ### Method POST (conceptual, as it's a class instantiation and method calls) ### Endpoint N/A (Python class) ### Parameters #### Initialization Parameters - **context** (RollContext, optional) - A RollContext object to configure rolling behavior (e.g., max rolls). #### Methods - **roll(expression | AST, advantage=None)**: Rolls dice based on the provided expression string or parsed AST. Can apply advantage/disadvantage. - **parse(expression)**: Parses a dice expression string into an Abstract Syntax Tree (AST). ### Request Example ```python import d20 # Create a roller with custom roll limits context = d20.RollContext(max_rolls=500) roller = d20.Roller(context=context) # Roll with the configured roller result = roller.roll("10d20") print(result.total) # Parse expression separately for reuse parsed_ast = roller.parse("2d6+3") print(str(parsed_ast)) # '2d6 + 3' # Roll a pre-parsed AST multiple times for _ in range(3): result = roller.roll(parsed_ast) print(result.total) # Roll with advantage (changes 1d20 to 2d20kh1) result = roller.roll("1d20+5", advantage=d20.AdvType.ADV) print(str(result)) # '2d20kh1 (12, **17**) + 5 = `22`' # Roll with disadvantage (changes 1d20 to 2d20kl1) result = roller.roll("1d20+5", advantage=d20.AdvType.DIS) print(str(result)) # '2d20kl1 (**8**, 15) + 5 = `13`' ``` ### Response #### Success Response (200) - **RollResult** (object) - The result of the dice roll, similar to `d20.roll`. #### Response Example ```json { "total": 22, "crit": "NORMAL", "comment": null } ``` ```