dice

package
v5.19.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 24, 2024 License: BSD-3-Clause Imports: 16 Imported by: 0

Documentation

Overview

Package dice provides a general facility for generating random numbers in fantasy role-playing games.

The preferred usage model is to use the higher-level abstraction provided by DieRoller, which rolls dice as described by strings. For example:

label, results, err := Roll("d20+16 | c")
label, result, err := RollOnce("15d6 + 15 fire + 1 acid")

If you need to keep the die roller itself around after the dice are rolled, to query its status, or to produce a repeatable string of die rolls given a custom seed or number generator, create a new DieRoller value and reuse that as needed:

dr, err := NewDieRoller()
label, results, err := dr.DoRoll("d20+16 | c")
label, result, err := dr.DoRollOnce("15d6 + 15 fire + 1 acid")

There is also a lower-level abstraction of dice available via the Dice type, created by the New function, if for some reason the DieRoller interface won't provide what is needed.

NEW in version 5.3: The die-roll expressions now honor the usual algebraic order of operations instead of simply evaluating left-to-right. Parentheses (round brackets) can be used for grouping in the usual sense for math expressions.

Index

Constants

View Source
const MaximumSupportedDieRollPresetFileFormat = 2
View Source
const MinimumSupportedDieRollPresetFileFormat = 1

Variables

This section is empty.

Functions

func ByDescription

func ByDescription(desc string) func(*Dice) error

ByDescription sets up a Dice value based on the text description given. This is the preferred way to make a low-level Dice value, since it is a flexible human-readable specification which likely came from the user anyway. (Although using DieRoller instead of Dice is even better.)

This text description may contain any number of integer constants and/or die‐roll expressions separated by the basic math operators “+”, “−”, “*”, and “//” which respectively add, subtract, multiply, and divide the total value so far with the value that follows the operator. Division performed with the “//” operator is integer‐only (results are immediately truncated by discarding any fractional part). Standard algebraic order of operations is followed (unary + and - are performed first, then multiplication and division, and then addition and subtraction, reading from left to right, and parentheses (brackets) ‘(’ and ‘)’ are used to enclose sub-expressions; strictly speaking, unary '+' is ignored and is actually dropped out of the expression by the parser). Generally, whitespace is insignificant in the description string.

Additionally, a pair of operators are available to constrain values within given limits. The expression x<=y will have the value of x as long as it is less than or equal to y; if x is greater than y, then y will be the value taken. Likewise with x>=y but this means to take the value of x as long as it is greater than or equal to y. These operators have the highest precedence other than unary minus.

On fully Unicode‐aware implementations (e.g., the Go version of this package), the character “×” (U+00D7) may be used in place of “*”, “÷” (U+00F7) in place of “//”, “≤” (U+2264) in place of "<=", and “≥” (U+2265) in place of ">=". (Internally, these operators are converted to the non-ASCII Unicode runes, so ‘//‘ will appear as ‘÷’ in any output details about the die roll.)

Each die‐roll expression has the general form

[>] [<n>[/<div>]] d <sides> [best|worst of <r>] [<label>]

This calls for <n> dice with the given number of <sides> (which may be a number or the character “%” which means percentile dice or d100). The optional <div> part of the expression allows a fractional number of dice: the expression “1/2d20” rolls half of a d20 (in other words, it rolls 1d20 and divides the result by 2, truncating the result). The optional qualifier “best of <r>” will cause the dice to be rolled <r> times, keeping the best result. (You may also use the word worst in place of best to take the lowest of the rolls.)

Arbitrary text (<label>) may appear at the end of the expression. It is simply reported back in the result as a label to describe that value (e.g. “1d10 + 1d6 fire + 2d6 sneak”.) If the expression begins with the character “>”, then the first die in the set is maximized: in the expression “>3d6”, the first d6 is assumed to have the maximum value (6), and the remaining two dice are rolled to produce random values.

The entire die roll expression may be followed by one or both of the following global modifiers, separated from the expression and each other by vertical bars (“|”): “min <a>” or “max <b>”.

These force the final result to be no smaller than <a> and/or no larger than <b>, where <a> and <b> are integer values. For example:

2d6 + 1d4 | min 6

which rolls 2d6 and 1d4 to get a random value between 3 and 16, but if the result is less than 6, it will return 6 anyway.

For example:

d, err := New(ByDescription("3d6 + 12"))

func ByDieType

func ByDieType(qty, sides, bonus int) func(*Dice) error

ByDieType sets the Dice up by discrete values which determine the number of dice to roll, how many sides they each have, and a bonus to add to their sum.

For example, to create a Dice value for "3d6+10", you could do:

d, err := New(ByDieType(3, 6, 10))

func LoadDieRollPresetFile

func LoadDieRollPresetFile(input io.Reader) ([]DieRollPreset, DieRollPresetMetaData, error)

LoadDieRollPresetFile reads in and returns a slice of die-roll presets from an open stream.

func ReadDieRollPresetFile

func ReadDieRollPresetFile(path string) ([]DieRollPreset, DieRollPresetMetaData, error)

ReadDieRollPresetFile reads in and returns a slice of die-roll presets from the named file.

func SaveDieRollPresetFile

func SaveDieRollPresetFile(output io.Writer, presets []DieRollPreset, meta DieRollPresetMetaData) error

SaveDieRollPresetFile writes a slice of presets to an open stream.

func WithAutoSF

func WithAutoSF(enabled bool, successMessage, failureMessage string) func(*sdrOptions)

WithAutoSF augments the operation of a StructuredDescribeRoll call by indicating that a natural 1 indicates failure regardless of the modified result's value, and a natural maximum roll similarly indicates success.

In case an automatic success is indicated, the provided successMessage string will be included in the structured description; likewise with failureMessage in case of automatic failure.

This behavior is enabled if the enabled parameter is true. Otherwise no automatic success or failure interpretation will be made.

func WithDieBonus

func WithDieBonus(n int) func(*Dice) error

WithDieBonus adds a per-die bonus of n which will be added to every single die rolled.

func WithDiv deprecated

func WithDiv(n int) func(*Dice) error

WithDiv causes the total die-roll to be divided by n (as an integer division, truncated toward zero).

Deprecated: use WithDescription("... // n") or WithDescription("... ÷ n") instead.

func WithFactor deprecated

func WithFactor(n int) func(*Dice) error

WithFactor causes the total die-roll to be multiplied by n.

Deprecated: use WithDescription("... * n") or WithDescription("... × n") instead.

func WithGenerator

func WithGenerator(source rand.Source) func(*Dice) error

WithGenerator sets up the Dice value to use a random number generator created by the caller and passed in to this option.

func WithNoResults added in v5.2.0

func WithNoResults() func(*sdrOptions)

WithNoResults tells StructuredDescribeRoll to assume that no actual die roll was made, and report only the request itself, ignoring results.

func WithRollBonus

func WithRollBonus(bonus int) func(*sdrOptions)

WithRollBonus augments the operation of a StructuredDescribeRoll call by indicating that this roll included an extra bonus (not indicated by the user).

This is not done if the bonus is 0 (zero).

func WithSeed

func WithSeed(s int64) func(*Dice) error

WithSeed sets up the Dice value to use a random number generator with the given seed value. (Per rand, this generator will not be safe for concurrent use by multiple goroutines.)

func WriteDieRollPresetFile

func WriteDieRollPresetFile(path string, presets []DieRollPreset, meta DieRollPresetMetaData) error

WriteDieRollPresetFile writes a slice of presets to the named file.

Types

type Dice

type Dice struct {
	// Have we actually rolled the dice yet to get a result?
	Rolled bool

	// Constrained minimum and maximum values for the roll.
	// Specify 0 if there should be no minimum and/or maximum.
	MinValue int
	MaxValue int

	// The result of the last roll of this die. LastValue has a value
	// that can be used if Rolled is true.
	LastValue int
	// contains filtered or unexported fields
}

Dice is an abstraction of the real-world concept of a set of dice. When constructing a new Dice value, specify the number of dice and number of sides.

This is a low-level representation of dice.

See the DieRoller type for a higher-level abstraction which is the recommended type to use instead of this one, for most purposes.

func New

func New(options ...func(*Dice) error) (*Dice, error)

New creates a new set of dice (using the low-level representation Dice type; for a more user-friendly interface use NewDieRoller instead).

By default, this creates a d20 you can roll. For other kinds of die rolls, pass the option(s) ByDescription(description), ByDieType(qty, sides, bonus), WithDieBonus(n), WithDiv(n), WithFactor(n), WithGenerator(source), and/or WithSeed(s).

For example,

d, err := New()
d, err := New(ByDescription("15d6 + 12"))
d, err := New(ByDieType(15, 6, 12))

func (*Dice) Description

func (d *Dice) Description() (desc string)

Description produces a human-readable description of the die roll specification represented by the Dice object.

func (*Dice) MaxRoll

func (d *Dice) MaxRoll() (int, error)

MaxRoll is an alternative to Roll where instead of rolling the dice, it just assumes they all came up at their maximum possible values. This does NOT set up for subsequent critical rolls.

func (*Dice) MaxRollToConfirm

func (d *Dice) MaxRollToConfirm(bonus int) (int, error)

MaxRollToConfirm is the analog to RollToConfirm but just assumes all dice come up with their maximum values rather than rolling anything.

func (*Dice) Roll

func (d *Dice) Roll() (int, error)

Roll rolls the dice which this Dice instance represents. The result is returned as an integer value. Each time this is called, the dice are rerolled to get a new result. The Dice value’s internal state reflects the last call to this method.

func (*Dice) RollToConfirm

func (d *Dice) RollToConfirm(confirm bool, threat int, bonus int) (int, error)

RollToConfirm rolls the dice specified in the Dice value, with support for making critical confirmation rolls.

If confirm is true, we're rolling to confirm a critical threat. In this case, the previous-rolled value is checked against the provided threat value. If that previous roll is less than the threat value, nothing further is done, and 0 is returned.

If the previous roll was ≥ threat, then we make another roll, adding the provided bonus modifier to that roll. This roll's total is returned, and becomes the new most-recent roll for this Dice value.

If threat is less than or equal to zero, the default threat of a natural maximum roll (e.g., 20 on a d20, or 10 on a d10) is used.

Calling d.RollToConfirm(false, 0, 0) is equivalent to calling d.Roll(). Confirm a critical roll by rolling again against the normal to-hit target.

func (*Dice) StructuredDescribeRoll

func (d *Dice) StructuredDescribeRoll(options ...func(*sdrOptions)) ([]StructuredDescription, error)

StructuredDescribeRoll produces a detailed structured description of the result of rolling the Dice, in a way that a caller can format as they see fit.

If you wish to interpret the die roll in light of a rule which allows for a natural 1 to indicate automatic failure and a natural maximum die face (e.g., natural 20 on a d20) to indicate automatic success, then add a WithAutoSF option function call to the end of the argument list.

If this die roll included a bonus added to it for some reason (e.g., a confirmation bonus on dice rolled to confirm a critical threat), then add a WithRollBonus function call to the end of the argument list.

type DieRollPreset

type DieRollPreset struct {
	// The name by which this die-roll preset is identified to the user.
	// This must be unique among that user's presets.
	//
	// Clients typically
	// sort these names before displaying them.
	// Note that if a vertical bar ("|") appears in the name, all text
	// up to and including the bar are suppressed from display. This allows
	// for the displayed names to be forced into a particular order on-screen,
	// and allow a set of presets to appear to have the same name from the user's
	// point of view.
	Name string

	// A text description of the purpose for this die-roll specification.
	Description string `json:",omitempty"`

	// The die-roll specification to send to the server. This must be in a
	// form acceptable to the dice.Roll function.
	DieRollSpec string
}

DieRollPreset describes each die-roll specification the user has stored on the server or in a file as a ready-to-go preset value which will be used often, and needs to be persistent across gaming sessions.

type DieRollPresetMetaData

type DieRollPresetMetaData struct {
	Timestamp   int64  `json:",omitempty"`
	DateTime    string `json:",omitempty"`
	Comment     string `json:",omitempty"`
	FileVersion uint   `json:"-"`
}

type DieRoller

type DieRoller struct {
	Confirm bool // Are we supposed to confirm potential critical rolls?
	DoMax   bool // Maximize all die rolls?

	// If we need to repeatedly roll dice, we will either do so RepeatFor
	// times (if > 0), or until the result meets or exceeds RepeatUntil
	// (again, if > 0)
	RepeatUntil int
	RepeatFor   int

	// If PctChance ≥ 0 then our target to be "successful" is a score
	// or at least PctChance on a percentile die roll. In that case
	// we can also set a label in PctLabel for that roll.
	PctChance int

	// If DC > 0 we're trying to meet a difficulty class for the
	// roll to be "successful".
	DC int

	// User-defined label for this entire die-roll specification, such as
	// "Knowledge Skill Check".
	LabelText string

	// Messages to report if the roll can be categorized as "successful" or "failed".
	SuccessMessage string
	FailMessage    string

	// Template for permuted roll pattern substitution.
	Template string

	// Label to use if PctChance is in effect.
	PctLabel string

	// Values to be substituted into the Template
	Permutations [][]any

	// Postfix expression(s) generated by the most recent roll
	Postfix []string
	// contains filtered or unexported fields
}

The DieRoller type provides a higher-level view of die-roll generation, and should be generally preferred instead of the lower-level Dice type.

This allows the caller to deal with die rolls in a friendly but expressive syntax as a string of characters such as "2d12 + 5 bonus - 1 size | dc 12" which game players are more accustomed to using, and then simply roll that die-roll expression as needed.

Note that it is not expected for the user to set or query these structures directly. Use the provided functions instead.

func NewDieRoller

func NewDieRoller(options ...func(*Dice) error) (*DieRoller, error)

NewDieRoller creates a new DieRoller value, which provides the recommended higher-level interface for rolling dice. This value can then be used for as many die rolls as needed by calling its DoRoll or DoRollOnce methods.

You may pass zero or more option specifiers to this function as already described for the New constructor, although the only ones which apply here are WithSeed(s) and WithGenerator(s).

Initially it is set up to roll a single d20, but this can be changed with each DoRoll call.

func (*DieRoller) DoRoll

func (d *DieRoller) DoRoll(spec string) (string, []StructuredResult, error)

DoRoll rolls dice as described by the specification string. If this string is empty, it re-rolls the previously-used specification. Initially, "1d20" is assumed.

Returns the user-specified die-roll label (if any), the result of the roll, and an error if one occurred.

In this more comprehensive interface, the spec string is a string of the form

[<title>=] <expression> [|<options>...]

or

[<title>=] <chance>% [<success>[/<fail>]] [|<options>...]

where []s indicate optional parameters, the given words in angle brackets (<title>, etc) represent values to be placed into the string, and the other characters are to be taken literally.

The <title> (which, if given, is separated from the rest of the spec with an equals sign (“=”)) is optional and will be included as a comment in the result list to indicate what the purpose of the die roll was for.

Note that this module does not interpret the <title> value further, but by convention two special characters are significant to some clients:

‖ (U+2016) separates multiple titles in the <title> string
≡ (U+2261) separates the title text on the left with a color on the right.

This means that a <title> string of "monster≡blue‖damage≡red" will display a title for the die roll as two separate title values, "monster" in blue and "damage" in red.

<expression> can be anything that can be given as the description string to the New constructor (q.v.). At the end of the spec string there may be zero or more options, each beginning with a vertical bar (“|”).

These options may be any of the following:

| min <n>

The result will be at least <n>.

| max <n>

The result will be no more than <n>.

| c[<t>[±<b>]]

This indicates that the roll may need a critical confirmation roll to follow it. This will appear as an additional result in the list of results returned from the DoRoll and DoRollOnce methods. If the <t> parameter is given, a natural roll equal to or greater than <t> is assumed to be a critical threat. If a plus or minus sign followed by a number <b> is appended to the option, then this value is added to the confirmation die roll as a confirmation bonus. (The notation "±" here means either a "-" or "+" may appear at that position in the string.)

| dc <n>

This is a roll against a known difficulty class <n>. If the result is at least <n>, the roll is "successful".

| sf [<success>[/<fail>]]

Auto-success/fail: the roll, which must involve only a single die, will be considered successful if it's a natural maximum value (e.g., 20 on a d20 before modifiers are applied), or a failure if a natural 1 was rolled. Optionally, messages to report to the user to indicate what success and failure mean may be specified. Suitable defaults will be used or derived if one or both of those strings is not given.

| until <n>

Continue making die rolls, adding their results to the returned output, until a result of at least <n> is obtained.

| repeat <n>

Make <n> die rolls, reporting their results.

| maximized

Assume all dice roll at their maximum possible values. For example, the spec "3d6 | maximized" will always return the result 18, as if all three dice rolled sixes.

To prevent getting caught in an infinite loop, a maximum of 100 rolls will be made regardless of repeat and until options.

Anywhere in the string you may introduce a combination specifier in curly braces as “{<a>/<b>/<c>/...}”. This will repeat the overall die roll expression once for each of the values <a>, <b>, <c>, etc., substituting each in turn for the braced list. If multiple specifiers appear, they’ll all repeat so you get the Cartesian product of all the sets of values. This allows, for example, multiple attack rolls in a single click. For example, “Attack=d20+{17/12/7}” would roll three attack rolls: d20+17, d20+12, and d20+7.

In the second form for the spec string, <chance> gives the percentage chance of something occurring, causing percentile dice to be rolled. The result will be a the integer value 1 if the d100 roll was less than or equal to <chance>, or 0 otherwise. By default, the result is reported in the detailed description as “success” or “fail”. If a success label is given in the die‐roll string, that is reported in case of a successful roll, and “did not <success>” otherwise. If an explicit fail label is also given, that is used for unsuccessful rolls instead. As a special case, if <success> is “miss” then <fail> is assumed to be “hit” and vice versa.

For percentile rolls, only the until, repeat, and maximized global options may be used. Permutations (“{...}”) are also disallowed with percentile rolls.

This method returns values title, resultSet, and error representing the results of rolling the dice. The title is the title specified in the dice string, or an empty string if one was not given. The resultSet is a slice of StructuredResult structures, one for each roll of the dice that was performed.

Example die-roll specifications:

"d20"             Roll 1d20.
"3d6"             Roll 3d6 (3 six-sided dice, adding their values).
"15d6+15"         Roll 15d6, add 15 to their sum.
"1d10+5*10"       Roll 1d10, add 5, then multiply the result by 10.
"1/2 d6"          Roll 1d6, divide result by 2 (truncating toward zero).
"2d10+3d6+12"     Roll 2d10, 3d6, add their results and add 12 to the sum.
"d20+15|c"        Roll d20+15, automatically rolling to confirm on a natural 20.
"d20+15|c19+2"    Roll d20+15, rolling to confirm on natural 19 or 20 with +2 bonus.
"d%"              Roll percentile dice, giving result 1-100.
"40%"             Roll percentile dice, giving result 1 with 40% probability.
"d20+12|max20"    Roll d20+12 but any result > 20 is capped at 20.
"d20 best of 2"   Roll d20 twice, discarding the worse result.
"d20+4|dc 10"     Roll d20+4, signalling success if the result is 10 or greater.
"3d6 fire+1d4 acid+2 bonus"
                  Roll 3d6+1d4+2. In the structured results, it will show the values
                  rolled for the 3d6 fire, 1d4 acid, and 2 bonus individually.
"40% hit"         Reports success ("hit") with a 40% probability; otherwise reports
                  failure ("miss").
"13% red/blue"    Reports success ("red") with a 13% probability; otherwise reports
                  failure ("blue").
"2d10+3|until 19" Repeatedly rolls 2d10+3, adding each result to the set of die rolls
                  returned, until a roll totals at least 19.

func (*DieRoller) DoRollOnce

func (d *DieRoller) DoRollOnce(spec string) (string, StructuredResult, error)

DoRollOnce is just like the DoRoll method but adds the constraint that there may only be one result returned, in the same way the RollOnce function differs from the Roll() function.

func (*DieRoller) ExplainSecretRoll added in v5.2.0

func (d *DieRoller) ExplainSecretRoll(spec, notice string) (string, StructuredResult, error)

ExplainSecretRoll takes a dieroll spec as DoRoll does, along with a string explaining why the roll is secret. It returns the same result data as DoRoll, including a broken-out description of the dieroll spec, except that no actual die roll is made and no results are reported.

The ResultSuppressed field of the returned StructuredResult value is set to true to indicate that there is no actual result contained in the returned data.

This is used to send a "receipt" back to the requester of a die roll that their request for the roll was sent on to another party (typically the GM) who will be the only person to see the actual results (which must be obtained by a separate roll to the DoRoll method).

func (*DieRoller) IsNatural1

func (d *DieRoller) IsNatural1() (result bool)

IsNatural1 returns true if the DieRoller has been rolled already, and contains but a single die in its specification, and that die was rolled as a natural 1.

It returns false if that was not true, even if that was for reasons that it could not possibly be true (no die was rolled, the die-roll spec contained multiple dice, etc.)

func (*DieRoller) IsNaturalMax

func (d *DieRoller) IsNaturalMax() (result bool)

IsNaturalMax returns true if the DieRoller has been rolled already, and contains but a single die in its specification, and that die was rolled to the maximum possible value (i.e., a 20 on a d20).

It returns false if that was not true, even if that was for reasons that it could not possibly be true (no die was rolled, the die-roll spec contained multiple dice, etc.)

func (*DieRoller) RandFloat64

func (d *DieRoller) RandFloat64() float64

RandFloat64 generates a pseudorandom number in the range [0.0, 1.0) using the same random number generator as used for die rolls. This means that it affects the outcome of subsequent die rolls just as other die rolls do.

func (*DieRoller) RandIntn

func (d *DieRoller) RandIntn(n int) int

RandIntn generates a pseudorandom integer in the range [0, n) using the same random number generator as used for die rolls. This means that it affects the outcome of subsequent die rolls just as other die rolls do.

type StructuredDescription

type StructuredDescription struct {
	// A text label describing what the value means in the context
	// of the die-roll result. Typical type labels are documented
	// in dice(3).
	Type string

	// The value (as a string, since the intent here is just to report
	// these values to a human with various kinds of formatting) for this
	// part of the description.
	Value string
}

StructuredDescription values are used to report die-roll results as a structured description list.

type StructuredDescriptionSet

type StructuredDescriptionSet []StructuredDescription

A StructuredDescriptionSet is simply a collection of StructuredDescriptions.

func (StructuredDescriptionSet) Text

func (sr StructuredDescriptionSet) Text() (string, error)

Text produces a simple plain-text rendering of the information in a StructuredDescription slice. This is useful for showing the full details of a die roll to a human, or a log file, etc., if fancier formatting isn't needed.

type StructuredResult

type StructuredResult struct {
	// True if there is no actual result generated (and the Result field should be ignored)
	ResultSuppressed bool `json:",omitempty"`

	// True if the die-roll request was invalid.
	InvalidRequest bool `json:",omitempty"`

	// Total final result of the expression.
	Result int

	// Breakdown of how the result was obtained.
	Details StructuredDescriptionSet
}

StructuredResult provides a full, detailed report of the die-roll operation. See the documentation in dice(3) for full details.

For example, making a die roll such as Roll("1d20+3|min 5|c") might result in the following StructuredResult slice, which contains a fully-described breakdown of how those results were arrived at:

 []StructuredResult{{
   Result: 23,
   Details: StructuredDescriptionSet{
     {Type: "result",    Value: "23"},
     {Type: "success",   Value: "HIT"},
     {Type: "separator", Value: "="},
     {Type: "diespec",   Value: "1d20"},
     {Type: "roll",      Value: "20"},
     {Type: "operator",  Value: "+"},
     {Type: "constant",  Value: "3"},
     {Type: "moddelim",  Value: "|"},
     {Type: "min",       Value: "5"},
     {Type: "moddelim",  Value: "|"},
     {Type: "critspec",  Value: "c"},
   }
  }, {
   Result: 13,
   Details: StructuredDescriptionSet{
     {Type: "critlabel", Value: "Confirm:"},
     {Type: "result",    Value: "13"},
     {Type: "separator", Value: "="},
     {Type: "diespec",   Value: "1d20"},
     {Type: "roll",      Value: "10"},
     {Type: "operator",  Value: "+"},
     {Type: "constant",  Value: "3"},
     {Type: "moddelim",  Value: "|"},
     {Type: "min",       Value: "5"},
  }
}}

func Roll

func Roll(spec string) (string, []StructuredResult, error)

Roll rolls the dice specified by the specification string, without requiring a separate step to create a DieRoller first.

Calling Roll(spec) is equivalent to the sequence

dr = NewDieRoller()
dr.DoRoll(spec)

func RollOnce

func RollOnce(spec string) (string, StructuredResult, error)

RollOnce is just like Roll but adds the constraint that there may only be one result returned (no confirmation rolls, no repeated rolls, etc., although multiple dice such as "3d6+4d10" or "best of N" kinds of things are allowed). It is an error if the die roll spec generates multiple results.

The return value differs from Roll in that only a single StructuredResult is returned rather than a slice of them.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL