<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://skizzerz.net/DiceRoller/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Skizzerz</id>
	<title>DiceRoller Documentation - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://skizzerz.net/DiceRoller/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Skizzerz"/>
	<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/Special:Contributions/Skizzerz"/>
	<updated>2026-05-21T00:15:35Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.34.0</generator>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig/GetRandomBytes&amp;diff=996</id>
		<title>Dice/RollerConfig/GetRandomBytes</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig/GetRandomBytes&amp;diff=996"/>
		<updated>2023-05-18T18:00:24Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: fix link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|RollerConfig.GetRandomBytes Property}}&lt;br /&gt;
Gets or sets the function used to generate random numbers.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public Action&amp;lt;byte[]&amp;gt; GetRandomBytes { get; set; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Property Value ===&lt;br /&gt;
Type: System.Action&amp;lt;byte[]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The callback delegate that is used to populate die rolls.&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
The delegate should populate the passed-in byte array with a 4-byte value. The Length of the byte array is 4. The {{cs|BitConverter.GetBytes}} overloads may be useful should you wish to transform values of other types, such as integers, into a byte array.&lt;br /&gt;
&lt;br /&gt;
If {{cs|null}}, random values will be generated via the {{cs|RNGCryptoServiceProvider.GetRandomBytes(byte[])}} method in the {{cs|System.Security.Cryptography}} namespace.&lt;br /&gt;
&lt;br /&gt;
This property is used extensively by the unit-testing suite in order to provide fixed die rolls. It is exposed to applications wishing to override the default random number generator with their own version, or to fix die results as well. For example, in a play-by-post the dice should not be rerolled each time a post is previewed or edited, provided the dice expression did not change. As such, passing in a callback here which &amp;quot;re-rolls&amp;quot; the previously rolled values is one way to accomplish this functionality.&lt;br /&gt;
&lt;br /&gt;
The number of sides to the die being rolled is not passed in as an argument to this callback, the resultant byte array is interpreted as a {{cs|uint}} and then converted into the proper range via modulus operations, and addition/subtraction. To prevent bias, this function may be called numerous times in the course of rolling a single die should the value be outside of an even range (so that the modulus does not introduce any potential bias into the final result).&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
The following example causes all dice to roll 9. After all, we can [https://assets.amuniversal.com/321a39e06d6401301d80001dd8b71c47 never be sure] about how random something truly is 😉.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Dice;&lt;br /&gt;
&lt;br /&gt;
class Sample&lt;br /&gt;
{&lt;br /&gt;
    public static void Main()&lt;br /&gt;
    {&lt;br /&gt;
        Roller.DefaultConfig.GetRandomBytes = GetRandomBytes;&lt;br /&gt;
        var result = Roller.Roll(&amp;quot;2d20&amp;quot;);&lt;br /&gt;
        Console.WriteLine(result.Value); // writes 18&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public static void GetRandomBytes(byte[] param)&lt;br /&gt;
    {&lt;br /&gt;
        // 8 instead of 9 is intentional. For normal dice, this value will be +1 to adjust the number&lt;br /&gt;
        // from 1-20 (instead of 0-19). For fudge dice, the number is transformed the other way by subtracting&lt;br /&gt;
        // (maxResult + 1). In other words, this number is NOT the number that the die will end up as.&lt;br /&gt;
        BitConverter.GetBytes((uint)8).CopyTo(param, 0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice_Reference&amp;diff=993</id>
		<title>Dice Reference</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice_Reference&amp;diff=993"/>
		<updated>2021-07-08T23:55:16Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: add implode extras&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DiceRoller supports a robust syntax to roll dice of all descriptions and modify those rolls in various ways. The most simple way to roll dice is via {{c|{{p|N}}d{{p|X}}+{{p|Y}}}}, which says to roll N dice that each have X sides, and then add Y to the total. An example would be {{c|1d20+4}}.&lt;br /&gt;
&lt;br /&gt;
In this documentation, any {{p|bold green}} text refers to placeholders, where normal text indicates symbols that should be left as-is. For example, the d in 1d20 must be left as the letter d, it is not a placeholder for something else.&lt;br /&gt;
&lt;br /&gt;
== Basic rolls ==&lt;br /&gt;
; {{c|{{p|N}}d{{p|X}}}}&lt;br /&gt;
: This will roll N dice with X sides per die (numbered from 1 to X). The dice are then added together to get the final result.&lt;br /&gt;
; {{c|{{p|N}}dF}}&lt;br /&gt;
: This will roll N fudge dice, which are dice with the numbers -1, 0, and 1.&lt;br /&gt;
; {{c|{{p|N}}dF{{p|X}}}}&lt;br /&gt;
: This will roll N fudge dice with a custom range, numbered from -X to X.&lt;br /&gt;
; {{c|{{p|N}}}}&lt;br /&gt;
: This will just result in the static number N, which is useful for when you just want to add a constant number to something or do pure math without rolling dice. N can be any decimal number, and may be negative.&lt;br /&gt;
&lt;br /&gt;
Basic rolls can be augmented with functions and extras. This guide will mark the functions and extras that can apply to basic rolls with (Basic). For example, {{c|1d20ad}} rolls 1d20 with advantage (rolls the expression twice and takes the highest result), and {{c|4d6dl1}} rolls 4d6 and then drops the lowest roll. These could also be represented as {{c|1d20.advantage()}} and {{c|4d6.droplowest(1)}}.&lt;br /&gt;
&lt;br /&gt;
== Math ==&lt;br /&gt;
Math can be performed with die rolls, with addition ({{c|+}}), subtraction ({{c|-}}), multiplication ({{c|*}}), and division ({{c|/}}) being allowed. Math expressions can be wrapped in parenthesis as well to clearly denote which expressions should be evaluated first, or to inject a math operation into any location where a number would normally be expected. Any roll expression is valid on either side of a math operator, whether that is a roll or just a number. For example, all of the following are valid rolls:&lt;br /&gt;
* {{c|1d20+4}}&lt;br /&gt;
* {{c|(1d10+2d6+2)*1.5}}&lt;br /&gt;
* {{c|(1d8)d10}} (rolls 1d8, and then rolls that many d10s, returning the sum of the d10s)&lt;br /&gt;
* {{c|10000/6}} (divides 10,000 by 6, and returns the result. In other words, rolling dice is not required)&lt;br /&gt;
&lt;br /&gt;
== Macros ==&lt;br /&gt;
Whenever a number is expected, a macro can be provided instead. The stand-alone dice roller does not define any macros, but the Play-by-Post helper utility defines some (see below for more details). Additionally, the program which uses the library may define custom macros. Macros are enclosed in square brackets, and can have any text inside of them (except for a right square bracket). An example of a macro may be something that looks up a property on a character sheet, but the possibilities are unlimited.&lt;br /&gt;
&lt;br /&gt;
Examples of macros:&lt;br /&gt;
* {{c|1d20+[WIS-mod]}} (rolls 1d20 and adds the result of the WIS-mod macro)&lt;br /&gt;
* {{c|1d10+[SneakAttack]d6}} (rolls 1d10 plus a number of d6's equal to the SneakAttack macro)&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined Macros ===&lt;br /&gt;
These macros are always defined.&lt;br /&gt;
&lt;br /&gt;
==== numDice ====&lt;br /&gt;
The numDice macro returns the number of dice rolled so far in the current roll. For example, {{c|5d4 + [numDice]}} is the same as {{c|5d4 + 5}}.&lt;br /&gt;
&lt;br /&gt;
=== Play-by-Post Macros ===&lt;br /&gt;
The following macros are pre-defined if the Play-by-Post helper is used. If dice are rolled individually (not collected in a post containing multiple rolls), these macros are not defined.&lt;br /&gt;
&lt;br /&gt;
==== roll ====&lt;br /&gt;
The roll macro allows for retrieving the value or other properties of previous dice rolls in the same post. It can be invoked in the following ways. Should an invocation be invalid, nothing happens (which means an error is likely displayed stating that the macro is invalid).&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}]}}&lt;br /&gt;
: Retrieves the value of the Xth roll in the post. The first roll in the post is X = 1. This can only be used to retrieve the value of previous rolls, it will not work if X is greater than or equal to the current roll number. If X is negative, it counts backwards from the current post (so X = -1 obtains the value of the previous post). X = 0 is invalid.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:{{p|Y}}]}}&lt;br /&gt;
: Retrieves the value of the Yth kept die roll in the Xth post. X is counted as per above. Y is counted from left-to-right in the normalized dice expression, and skips over dropped dice. Unlike X, Y cannot be negative (the first die is Y = 1).&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:critical]}}&lt;br /&gt;
: Counts the number of dice in the Xth roll that were marked as criticals.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:{{p|Y}}:critical]}}&lt;br /&gt;
: This is 1 if the Yth die in the Xth roll is critical, and 0 otherwise.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:fumble]}}&lt;br /&gt;
: Counts the number of dice in the Xth roll that were marked as fumbles.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:{{p|Y}}:fumble]}}&lt;br /&gt;
: This is 1 if the Yth die in the Xth roll is a fumble, and 0 otherwise.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:success]}}&lt;br /&gt;
: Counts the number of dice in the Xth roll that were marked as successes.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:{{p|Y}}:success]}}&lt;br /&gt;
: This is 1 if the Yth die in the Xth roll is a success, and 0 otherwise.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:failure]}}&lt;br /&gt;
: Counts the number of dice in the Xth roll that were marked as failures.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:{{p|Y}}:failure]}}&lt;br /&gt;
: This is 1 if the Yth die in the Xth roll is a failure, and 0 otherwise.&lt;br /&gt;
&lt;br /&gt;
== Grouped rolls ==&lt;br /&gt;
{{c|{{p|N}}&amp;lt;nowiki&amp;gt;{&amp;lt;/nowiki&amp;gt;{{p|roll1}}, {{p|roll2}}, {{p|...}}&amp;lt;nowiki&amp;gt;}&amp;lt;/nowiki&amp;gt;}} or {{c|&amp;lt;nowiki&amp;gt;{&amp;lt;/nowiki&amp;gt;{{p|roll1}}, {{p|roll2}}, {{p|...}}&amp;lt;nowiki&amp;gt;}&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Grouped rolls are a complex and powerful mechanism to roll groups of disparate dice and then operate on those groups. A grouped roll is made by enclosing one or more basic rolls inside of curly braces. A number N can be specified in front of the group to evaluate that group that number of times. For example, {{c|6&amp;lt;nowiki&amp;gt;{&amp;lt;/nowiki&amp;gt;4d6dl1&amp;lt;nowiki&amp;gt;}&amp;lt;/nowiki&amp;gt;}} rolls 4d6 (dropping the lowest roll) six times, and returns each result.&lt;br /&gt;
&lt;br /&gt;
Grouped rolls can be augmented with functions and extras. This guide will mark the functions and extras that can apply to grouped rolls with (Group). For example, {{c|{2d8,3d6}kh1}} rolls 2d8 and 3d6, sums each one, and then keeps the highest result. This could also be expressed as {{c|{2d8,3d6}.keephighest(1)}}.&lt;br /&gt;
&lt;br /&gt;
== Comparisons ==&lt;br /&gt;
Some extras and functions take comparisons as parameters. A comparison is '''implicit''' if it just contains a number with no leading comparison operator, or '''explicit''' if it has a leading comparison operator. Some extras and functions require explicit comparisons, while others are ok with implicit comparisons as well.&lt;br /&gt;
&lt;br /&gt;
The valid comparisons are as follows:&lt;br /&gt;
* {{c|{{p|N}}}} (implicit comparison that tests if the result is equal to N)&lt;br /&gt;
* {{c|1=={{p|N}}}}&lt;br /&gt;
* {{c|&amp;gt;{{p|N}}}}&lt;br /&gt;
* {{c|&amp;lt;{{p|N}}}}&lt;br /&gt;
* {{c|1=&amp;gt;={{p|N}}}} (tests if the result is greater than or equal to N)&lt;br /&gt;
* {{c|1=&amp;lt;={{p|N}}}} (tests if the result is less than or equal to N)&lt;br /&gt;
* {{c|1=!={{p|N}}}} or {{c|&amp;lt;&amp;gt;{{p|N}}}} (tests if the result is not equal to N)&lt;br /&gt;
&lt;br /&gt;
== Extras ==&lt;br /&gt;
Extras can be added at the end of basic or group rolls to modify their behavior. If an extra takes a comparison as its parameter, you can specify that extra multiple times in order to compare against all of them. For example, {{c|1d6rr2rr4rr6}} would roll 1d6 and re-roll any even number. Extras can be added in any order, but are always evaluated in the following order:&lt;br /&gt;
# Explode&lt;br /&gt;
# Reroll&lt;br /&gt;
# Keep/Drop/Advantage&lt;br /&gt;
# Success/Failure&lt;br /&gt;
# Critical/Fumble&lt;br /&gt;
# Sort&lt;br /&gt;
&lt;br /&gt;
If an extra is marked with (Basic) it can be used with basic rolls, and if it is marked with (Group) it can be used with group rolls. Those marked (Basic/Group) can be used with both types of rolls. If the extra takes a parameter, it will indicate if it takes a number {{p|N}}, a comparison {{p|C}}, or an explicit comparison {{p|EC}}.&lt;br /&gt;
&lt;br /&gt;
=== Explode (Basic) ===&lt;br /&gt;
; {{c|!e}}&lt;br /&gt;
: Whenever the maximum value is rolled for a die, that die is rerolled. Both the original and reroll are added to the total. This repeats until something other than the maximum value is rolled. For example, {{c|1d6!e}} would roll 1d6. If a 6 is rolled, another 1d6 is rolled, and so on. This could lead to a final roll of 6, 6, 4.&lt;br /&gt;
; {{c|!e{{p|C}}}}&lt;br /&gt;
: Whenever the comparison succeeds for a die, that die is rerolled. Both the original and reroll are added to the total. This repeats until the comparison fails.&lt;br /&gt;
; {{c|!eo}}&lt;br /&gt;
: Per {{c|!e}}, except the dice will be rerolled at most once.&lt;br /&gt;
; {{c|!eo{{p|C}}}}&lt;br /&gt;
: Per {{c|!e{{p|C}}}}, except the dice will be rerolled at most once.&lt;br /&gt;
; {{c|!c}}&lt;br /&gt;
: Per {{c|!e}}, except that the rerolled values are added to the original die result, rather than adding another die into the final result list. This is called a compounding explosion. For example, {{c|1d6!c}} would roll 1d6. If a 6 is rolled, another 1d6 is rolled, and so on. This could lead to a final roll of 6, 6, 4, which is represented by a single 6-sided die rolling a value of 16.&lt;br /&gt;
; {{c|!c{{p|C}}}}&lt;br /&gt;
: Per {{c|!c}}, except it compares the die result against the comparison C instead of using the maximum value of the die.&lt;br /&gt;
; {{c|!p}}&lt;br /&gt;
: Whenever the maximum value is rolled for a die, that die is rerolled and 1 is subtracted from the reroll. Both the original and reroll are added to the total. This repeats until something other than the maximum value is rolled. For example, {{c|1d6!e}} would roll 1d6. If a 6 is rolled, another 1d6 is rolled, and so on. This could lead to a final roll of 6, 5, 3 (assuming 6, 6, and then a 4 were rolled). This is called penetrating dice. Furthermore, a {{c|d100!p}} penetrates down to {{c|d20!p}}, and {{c|d20!p}} penetrates down to {{c|d6!p}}. This downgrade only happens once (so if {{c|1d100!p}} rolls 100, then 20, it continues to roll d20s instead of downgrading again to d6).&lt;br /&gt;
; {{c|!p{{p|C}}}}&lt;br /&gt;
: Per {{c|!p}}, except it compares the die result against the comparison C instead of using the maximum value of the die. Furthermore, the special downgrading rules are not used, so d100 will penetrate to d100, and d20 will penetrate to d20.&lt;br /&gt;
; {{c|!i}}&lt;br /&gt;
: Whenever the minimum value is rolled for a die, that die is rerolled. The original roll is added to the total but all rerolled amounts are subtracted from the total. The die will be rerolled until something other than the minimum value is rolled. For example, {{c|1d6!i}} would roll 1d6. If a 1 is rolled, another 1d6 is rolled. This could lead to a final result of 1, 1, and 4, for a total of -4 (1 - 1 - 4).&lt;br /&gt;
; {{c|!i{{p|C}}}}&lt;br /&gt;
: When the comparison succeeds for the die, it will be rerolled. Like {{c|!i}}, the original roll is added to the total and all rerolls are subtracted from the total. This repeats until the comparison fails.&lt;br /&gt;
; {{c|!io}}&lt;br /&gt;
: Per {{c|!i}}, except the dice will be rerolled at most once.&lt;br /&gt;
; {{c|!io{{p|C}}}}&lt;br /&gt;
: Per {{c|!i{{p|C}}}}, except the dice will be rerolled at most once.&lt;br /&gt;
&lt;br /&gt;
=== Reroll (Basic/Group) ===&lt;br /&gt;
; {{c|rr{{p|C}}}}&lt;br /&gt;
: Whenever the comparison succeeds, it rerolls the die, discarding the previous result. This will happen until the comparison fails.&lt;br /&gt;
; {{c|ro{{p|C}}}}&lt;br /&gt;
: If the comparison succeeds, it will reroll the die, discarding the previous result. The die is rerolled a maximum of one time, even if the comparison would succeed again.&lt;br /&gt;
&lt;br /&gt;
=== Keep/Drop (Basic/Group) ===&lt;br /&gt;
; {{c|kh{{p|N}}}}&lt;br /&gt;
: Keeps the highest N results, discarding the rest.&lt;br /&gt;
; {{c|kl{{p|N}}}}&lt;br /&gt;
: Keeps the lowest N results, discarding the rest.&lt;br /&gt;
; {{c|dh{{p|N}}}}&lt;br /&gt;
: Discards the highest N results, keeping the rest.&lt;br /&gt;
; {{c|dl{{p|N}}}}&lt;br /&gt;
: Discards the lowest N results, keeping the rest.&lt;br /&gt;
&lt;br /&gt;
If multiple keep or drop expressions are applied, they work in sequence. For example, {{c|4d6dl1dl1}} would roll 4d6, drop the lowest die, and then drop the next lowest die. In other words, it is equivalent to {{c|4d6dl2}}. A keep/drop expression cannot be combined with advantage or disadvantage.&lt;br /&gt;
&lt;br /&gt;
=== Advantage (Basic/Group) ===&lt;br /&gt;
; {{c|ad}}&lt;br /&gt;
: Gives the expression advantage, causing it to be rolled twice and then keeping the highest result.&lt;br /&gt;
; {{c|da}}&lt;br /&gt;
: Gives the expression disadvantage, causing it to be rolled twice and then keeping the lowest result.&lt;br /&gt;
&lt;br /&gt;
Advantage or disadvantage cannot be combined with keep/drop expressions.&lt;br /&gt;
&lt;br /&gt;
=== Success/Failure (Basic/Group) ===&lt;br /&gt;
; {{c|{{p|EC}}}}&lt;br /&gt;
: Each die rolled is compared against EC. If it matches, it counts as one success. If it does not match, it counts as zero successes. The result of the roll is the number of successes, rather than the sum of the dice. For example, {{c|5d10&amp;gt;6}} will roll 5d10 and count one success each time the die comes up as 7 or higher.&lt;br /&gt;
; {{c|{{p|EC}}f{{p|C}}}}&lt;br /&gt;
: Each die rolled is compared against EC. If it matches, it counts as one success. If it does not match EC, but does match C, it removes one success. Otherwise, it counts as zero successes. The result of the roll is the number of successes (which may be negative), rather than the sum of the dice.&lt;br /&gt;
&lt;br /&gt;
=== Critical/Fumble (Basic) ===&lt;br /&gt;
; {{c|cs{{p|C}}}}&lt;br /&gt;
: Each die rolled is compared against C, and marked as a critical success should it succeed.&lt;br /&gt;
; {{c|cs{{p|C}}f{{p|C}}}}&lt;br /&gt;
: Each die rolled is compared against both comparisons. The first marks it as a critical success should it succeed, and the second marks it as a fumble (critical failure) should it succeed.&lt;br /&gt;
; {{c|cf{{p|C}}}}&lt;br /&gt;
: Each die rolled is compared against C, and marked as a fumble should it succeed.&lt;br /&gt;
&lt;br /&gt;
Critical successes and fumbles do not have any mechanical function by themselves, but can be tracked via macros or functions, and are usually displayed differently. It is possible for a die to be marked as both a critical and a fumble at the same time. If a roll does not have a critical/fumble expression attached to it, then a roll of the maximum result is counted as a critical and the minimum result is counted as a fumble.&lt;br /&gt;
&lt;br /&gt;
=== Sort (Basic/Group) ===&lt;br /&gt;
; {{c|sa}}&lt;br /&gt;
: Causes each die rolled to be sorted in ascending order for display purposes.&lt;br /&gt;
; {{c|sd}}&lt;br /&gt;
: Causes each die rolled to be sorted in descending order for display purposes.&lt;br /&gt;
&lt;br /&gt;
== Global functions ==&lt;br /&gt;
Global functions can be used wherever a math expression can be used, and transform the die results in various ways. The following global functions are built-in to the library, however the program which uses the library can also define its own global functions. If the function takes a parameter, it will indicate if it takes an expression {{p|E}} (which can be any arbitrary math or roll expression), or an explicit comparison {{p|C}}.&lt;br /&gt;
&lt;br /&gt;
=== floor ===&lt;br /&gt;
{{c|floor({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
Takes the mathematical floor of the expression, truncating any decimal portion. Example: {{c|1d20+floor([Levels]/2)}}&lt;br /&gt;
&lt;br /&gt;
=== ceil ===&lt;br /&gt;
{{c|ceil({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
Takes the mathematical ceiling of the expression, causing any decimal portion to round up to the next whole number.&lt;br /&gt;
&lt;br /&gt;
=== round ===&lt;br /&gt;
{{c|round({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
Rounds the result of the expression. Decimal values greater than or equal to 0.5 are rounded away from zero, whereas decimal values less than 0.5 are rounded towards zero. For example, 1.5 and 1.6 both round to 2, 1.4 rounds to 1, -1.5 and -1.6 both round to -2, and -1.4 rounds to -1.&lt;br /&gt;
&lt;br /&gt;
=== abs ===&lt;br /&gt;
{{c|abs({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
Takes the absolute value of the expression.&lt;br /&gt;
&lt;br /&gt;
=== max ===&lt;br /&gt;
{{c|max({{p|E}}, {{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
Returns the highest Value from the two expressions. Dice rolled in the low-valued expression are all marked as dropped.&lt;br /&gt;
&lt;br /&gt;
=== min ===&lt;br /&gt;
{{c|min({{p|E}}, {{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
Returns the lowest Value from the two expressions. Dice rolled in the high-valued expression are all marked as dropped.&lt;br /&gt;
&lt;br /&gt;
=== if ===&lt;br /&gt;
; {{c|if({{p|E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;}}, {{p|C}}, {{P|E&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;}})}}&lt;br /&gt;
: If the comparison succeeds for E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;, then this returns the Value of E&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. Otherwise, this returns 0.&lt;br /&gt;
&lt;br /&gt;
; {{c|if({{p|E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;}}, {{p|C}}, {{P|E&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;}}, {{p|E&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;}})}}&lt;br /&gt;
: If the comparison succeeds for E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;, then this returns the Value of E&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. Otherwise, this returns the Value of E&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Note that all expressions in {{c|if()}} are evaluated, even if they are not returned.&lt;br /&gt;
&lt;br /&gt;
== Dice functions ==&lt;br /&gt;
Dice functions, like dice extras, are added to the end of die rolls. All dice functions must come after dice extras, but can otherwise go in any order. The following dice functions are pre-defined by the library, but the program may add more.&lt;br /&gt;
&lt;br /&gt;
If a function is marked with (Basic) it can be used with basic rolls, and if it is marked with (Group) it can be used with group rolls. Those marked (Basic/Group) can be used with both types of rolls. If the function takes a parameter, it will indicate if it takes a number {{p|N}}, an expression {{p|E}} (which can be any arbitrary math or roll expression), or an explicit comparison {{p|C}}. Should a function take a number as a parameter, it must either be a literal number or a macro, it cannot contain any rolls or math.&lt;br /&gt;
&lt;br /&gt;
=== reroll (Basic/Group) ===&lt;br /&gt;
{{c|.reroll({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|rr}} extra once for each comparison passed into the function. At least one comparison must be specified. For example, to reroll 1d6 whenever an even number comes up, you could specify {{c|1=1d6.reroll(=2, =4, =6)}}.&lt;br /&gt;
&lt;br /&gt;
=== rerollN (Basic/Group) ===&lt;br /&gt;
{{c|.rerollN({{p|N}}, {{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
Like reroll, however will only reroll at most N times before it keeps the final result (even if one of the comparisons would still succeed). At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== rerollOnce (Basic/Group) ===&lt;br /&gt;
{{c|.rerollOnce({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|ro}} extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== explode (Basic) ===&lt;br /&gt;
{{c|.explode({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|!e}} extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== compound (Basic) ===&lt;br /&gt;
{{c|.compound({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|!c}} extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== penetrate (Basic) ===&lt;br /&gt;
{{c|.penetrate({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|!p}} extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== compoundPenetrate (Basic) ===&lt;br /&gt;
{{c|.compoundPenetrate({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
Like penetrate, except all additional penetration dice rolled are added to the initial value (just like the compound function). At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== keepHighest (Basic/Group) ===&lt;br /&gt;
{{c|.keepHighest({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|kh}} extra.&lt;br /&gt;
&lt;br /&gt;
=== keepLowest (Basic/Group) ===&lt;br /&gt;
{{c|.keepLowest({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|kl}} extra.&lt;br /&gt;
&lt;br /&gt;
=== dropHighest (Basic/Group) ===&lt;br /&gt;
{{c|.dropHighest({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|dh}} extra.&lt;br /&gt;
&lt;br /&gt;
=== dropLowest (Basic/Group) ===&lt;br /&gt;
{{c|.dropLowest({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|dl}} extra.&lt;br /&gt;
&lt;br /&gt;
=== advantage (Basic/Group) ===&lt;br /&gt;
{{c|.advantage()}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|ad}} extra.&lt;br /&gt;
&lt;br /&gt;
=== disadvantage (Basic/Group) ===&lt;br /&gt;
{{c|.disadvantage()}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|da}} extra.&lt;br /&gt;
&lt;br /&gt;
=== success (Basic/Group) ===&lt;br /&gt;
{{c|.success({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the success extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== failure (Basic/Group) ===&lt;br /&gt;
{{c|.failure({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
Specifies one or more failure comparison without specifying a success comparison. At least one success comparison must be specified via other means, such as the success extra or by calling {{c|.success({{p|C}})}}.&lt;br /&gt;
&lt;br /&gt;
=== critical (Basic) ===&lt;br /&gt;
{{c|.critical({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|cs}} extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== fumble (Basic) ===&lt;br /&gt;
{{c|.fumble({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|cf}} extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== sortAsc (Basic/Group) ===&lt;br /&gt;
{{c|.sortAsc()}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|sa}} extra.&lt;br /&gt;
&lt;br /&gt;
=== sortDesc (Basic/Group) ===&lt;br /&gt;
{{c|.sortDesc()}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|sd}} extra.&lt;br /&gt;
&lt;br /&gt;
=== expand (Group) ===&lt;br /&gt;
{{c|.expand()}}&lt;br /&gt;
&lt;br /&gt;
Normally, grouped rolls display aggregated results instead of showing the value of each individual die rolled. For example, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will display (for example) {{c|(15)}} instead of {{c|(4 + 5 + 3 + 3)}}. The expand function causes it to display the value of each individual die instead, so {{c|&amp;lt;nowiki&amp;gt;{4d6}.expand()&amp;lt;/nowiki&amp;gt;}} will display (for example) {{c|(4 + 5 + 3 + 3)}}. Expand is applied before sorting, so you can sort the individual rolls of a group if you both expand and sort.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=992</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=992"/>
		<updated>2021-06-15T03:03:37Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* 4.2.0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2.0 ==&lt;br /&gt;
Backwards-incompatible changes:&lt;br /&gt;
* Some DiceAST subclasses were removed. The DiceAST class hierarchy is considered an implementation detail and not a public API for the purposes of semantic versioning. However, the change is being noted here so any library consumers incorrectly casting to or using these subclasses can audit their code.&lt;br /&gt;
&lt;br /&gt;
New user features:&lt;br /&gt;
* The rerollN() function now accepts any numerical expression for the first argument (max # of rerolls) e.g. {{c|1=1d20.rerollN(2+3, =1)}} or {{c|1=1d20.rerollN(1d6, =1)}}&lt;br /&gt;
* The rerollN() function can now be specified multiple times for fine-grained reroll control, e.g. {{c|1=1d20.rerollN(2, =1).rerollN(1, =2, =3)}} rerolls either a &amp;quot;2&amp;quot; or &amp;quot;3&amp;quot; once but rerolls a &amp;quot;1&amp;quot; twice.&lt;br /&gt;
* More informative error messages if you omit something when specifying an extra on a roll&lt;br /&gt;
* Dice expressions are no longer case sensitive. Roll 1d20 or 1D20, whichever you prefer!&lt;br /&gt;
* Defining a success condition is no longer required when all you want to do is define a failure (negative success) condition&lt;br /&gt;
* New function explodeOnce() / !eo to perform an explode operation at most once.&lt;br /&gt;
* New function implode() / !i to act as the inverse of explode; when the comparison is met a new die is rolled and subtracted from the result. This continues until the comparison fails.&lt;br /&gt;
* New function implodeOnce() / !io to perform an implode operation at most once.&lt;br /&gt;
* New function compoundImplode() to perform an implode operation with compound semantics, causing a single die to be sent as output containing the final result of the implode operation.&lt;br /&gt;
&lt;br /&gt;
New developer features:&lt;br /&gt;
* Builtin functions can be overridden by custom functions by registering a function with the same name&lt;br /&gt;
* Builtin functions can be removed&lt;br /&gt;
* Custom functions can be registered with the same timing as builtin functions&lt;br /&gt;
* Custom extras can be registered along with custom functions&lt;br /&gt;
* Custom functions can specify how multiples of the same function are executed when attached to the same roll&lt;br /&gt;
* Custom functions can specify how their arguments should look, and will be validated before being called&lt;br /&gt;
* XML documentation added to all classes, methods, and properties for better IntelliSense. Improving the XML documentation quality is still a work in progress, please leave suggestions in a new issue on GitHub!&lt;br /&gt;
&lt;br /&gt;
Bugfixes:&lt;br /&gt;
* Fixed nullability annotation for {{l|Dice.DieResult.Data|DieResult.Data}}; this string can be nullable and has always defaulted to null&lt;br /&gt;
&lt;br /&gt;
Deprecations:&lt;br /&gt;
* {{l|Dice.BuiltinFunctions}} and {{l|Dice.BuiltinMacros}} are deprecated; please use their counterparts in the Dice.Builtins namespace if you would like to directly call any of them from within your custom functions/macros. These two classes will be removed in the next major release.&lt;br /&gt;
* DiceErrorCode.InvalidSuccess is deprecated and no longer used by the library. This enum value will be removed in the next major release.&lt;br /&gt;
* Direct access to the DiceAST classes and the parser is deprecated; these will become inaccessible or transition to using a public interface instead of exposing the classes directly in the next major release. No deprecation notice is emitted while compiling for these deprecations.&lt;br /&gt;
* .NET Framework 4.5.2 support is deprecated; support will be dropped when .NET Framework 4.5.2 reaches end of support from Microsoft on April 26, 2022. Circumstances in the future may cause an earlier removal.&lt;br /&gt;
&lt;br /&gt;
== 4.1.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** None&lt;br /&gt;
* New features:&lt;br /&gt;
** The leading number denoting number of dice (before the &amp;quot;d&amp;quot;) is optional and will default to 1 if not specified.&lt;br /&gt;
** Nullability annotations have been added to public APIs, to assist developers in migrating their own applications using this library.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** None&lt;br /&gt;
&lt;br /&gt;
The package as well as Dice.dll is signed with the following digital certificate fingerprint. This signature is only available on the official download from NuGet and is separate from the Strong-Name Key found in GitHub.&lt;br /&gt;
* {{c|E5F191DB201E9E3CF85B2A9E2408352057ABD731949C986E36F812CFD90728A7}} (SHA-256)&lt;br /&gt;
* {{c|A87D3B543D551CCD330C23B31B653835A86569BC}} (SHA-1).&lt;br /&gt;
&lt;br /&gt;
== 4.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** Nested rolls are fully resolved in {{l|Dice.RollResult.ToString|RollResult.ToString()}}. For example, instead of ToString() reporting {{c|&amp;quot;(1d8)d6&amp;quot;}}, it will now report the value rolled for the d8, e.g. {{c|&amp;quot;3d6&amp;quot;}}.&lt;br /&gt;
** {{l|Dice.RollerConfig.ExecuteMacro|RollerConfig.ExecuteMacro}} was removed.&lt;br /&gt;
* New features:&lt;br /&gt;
** DiceRoller is now packaged for both .NET Standard 2.0 as well as .NET Framework 4.5.2. .NET Standard 2.0 supports .NET Framework 4.6.1+ and .NET Core 2.0.&lt;br /&gt;
** Success/failure rolls can now be decorated with critical/fumbles. A critical success (a roll that is both a critical and a success) is worth 2 successes, and a critical failure (a roll that is both a fumble and a failure) is worth -2 successes. This expands support into game systems which use success-based rolls but have varying degrees of success beyond just +1 or -1.&lt;br /&gt;
*** Unless a success/failure roll is explicitly decorated with a critical/fumble, those rolls will not be marked as criticals or fumbles even if the max or min amount is rolled. This keeps default behavior with such rolls consistent with how they worked previously.&lt;br /&gt;
** A new [[Dice Reference#numdice|{{c|[numDice]}}]] macro was added, which returns the total number of dice rolled up to this point. This macro is available in all scenarios, including the stand-alone {{l|Dice.Roller.Roll|Roller.Roll}}; using the Play-by-Post helper is not required to use this macro.&lt;br /&gt;
** A new property {{l|Dice.RollerConfig.RollDie|RollerConfig.RollDie}} was added to allow customizing the result of a die roll in a more friendly way. This property is a callback which receives the minimum and maximum value it can roll for a die, and should return a number within that range. By default, it will call {{l|Dice.RollerConfig.GetRandomBytes|RollerConfig.GetRandomBytes}} repeatedly until it gets a result it can transform into the output range without introducing any bias.&lt;br /&gt;
** New APIs {{l|Dice.Roller.Max|Roller.Max()}}, {{l|Dice.Roller.Min|Roller.Min()}}, and {{l|Dice.Roller.Average|Roller.Average()}} evaluate the dice expression and return the result as if all dice rolled their minimum, maximum, or average values.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** It is now possible to put an expression in parenthesis (a &amp;quot;nested roll&amp;quot;) everywhere a number is expected. Previously, comparisons incorrectly rejected nested rolls.&lt;br /&gt;
* Dependency updates:&lt;br /&gt;
** Updated Antlr4.Runtime.Standard from 4.7.1 to 4.7.2&lt;br /&gt;
** Updated System.ValueTuple from 4.4.0 to 4.5.0&lt;br /&gt;
* Other:&lt;br /&gt;
** The nuget package is now digitally signed with the certificate fingerprint {{c|a87d3b543d551ccd330c23b31b653835a86569bc}}. The same certificate is used to sign the .dll itself in addition to the package.&lt;br /&gt;
&lt;br /&gt;
== 3.1.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** Global functions can now show up inside math expressions without needing to wrap them in parenthesis. For example, {{c|-max(1, 2)+6}} will return 4. They still cannot show up inside of a roll expression without additional parenthesis.&lt;br /&gt;
** New API {{l|Dice.PbP.RollPost.HasDivergedFrom|RollPost.HasDivergedFrom()}} to test whether two RollPosts have Diverged. (Two RollPosts diverge when one is not a prefix of the other)&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=991</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=991"/>
		<updated>2021-06-15T03:01:27Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: add 4.2.0 changelog&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.2.0 ==&lt;br /&gt;
Backwards-incompatible changes:&lt;br /&gt;
* Some DiceAST subclasses were removed. The DiceAST class hierarchy is considered an implementation detail and not a public API for the purposes of semantic versioning. However, the change is being noted here so any library consumers incorrectly casting to or using these subclasses can audit their code.&lt;br /&gt;
&lt;br /&gt;
New user features:&lt;br /&gt;
* The rerollN() function now accepts any numerical expression for the first argument (max # of rerolls) e.g. {{c|1d20.rerollN(2+3, =1)}} or {{c|1d20.rerollN(1d6, =1)}}&lt;br /&gt;
* The rerollN() function can now be specified multiple times for fine-grained reroll control, e.g. {{c|1d20.rerollN(2, =1).rerollN(1, =2, =3)}} rerolls either a &amp;quot;2&amp;quot; or &amp;quot;3&amp;quot; once but rerolls a &amp;quot;1&amp;quot; twice.&lt;br /&gt;
* More informative error messages if you omit something when specifying an extra on a roll&lt;br /&gt;
* Dice expressions are no longer case sensitive. Roll 1d20 or 1D20, whichever you prefer!&lt;br /&gt;
* Defining a success condition is no longer required when all you want to do is define a failure (negative success) condition&lt;br /&gt;
* New function explodeOnce() / !eo to perform an explode operation at most once.&lt;br /&gt;
* New function implode() / !i to act as the inverse of explode; when the comparison is met a new die is rolled and subtracted from the result. This continues until the comparison fails.&lt;br /&gt;
* New function implodeOnce() / !io to perform an implode operation at most once.&lt;br /&gt;
* New function compoundImplode() to perform an implode operation with compound semantics, causing a single die to be sent as output containing the final result of the implode operation.&lt;br /&gt;
&lt;br /&gt;
New developer features:&lt;br /&gt;
* Builtin functions can be overridden by custom functions by registering a function with the same name&lt;br /&gt;
* Builtin functions can be removed&lt;br /&gt;
* Custom functions can be registered with the same timing as builtin functions&lt;br /&gt;
* Custom extras can be registered along with custom functions&lt;br /&gt;
* Custom functions can specify how multiples of the same function are executed when attached to the same roll&lt;br /&gt;
* Custom functions can specify how their arguments should look, and will be validated before being called&lt;br /&gt;
* XML documentation added to all classes, methods, and properties for better IntelliSense. Improving the XML documentation quality is still a work in progress, please leave suggestions in a new issue on GitHub!&lt;br /&gt;
&lt;br /&gt;
Bugfixes:&lt;br /&gt;
* Fixed nullability annotation for {{l|Dice.DieResult.Data|DieResult.Data}}; this string can be nullable and has always defaulted to null&lt;br /&gt;
&lt;br /&gt;
Deprecations:&lt;br /&gt;
* {{l|Dice.BuiltinFunctions}} and {{l|Dice.BuiltinMacros}} are deprecated; please use their counterparts in the Dice.Builtins namespace if you would like to directly call any of them from within your custom functions/macros. These two classes will be removed in the next major release.&lt;br /&gt;
* DiceErrorCode.InvalidSuccess is deprecated and no longer used by the library. This enum value will be removed in the next major release.&lt;br /&gt;
* Direct access to the DiceAST classes and the parser is deprecated; these will become inaccessible or transition to using a public interface instead of exposing the classes directly in the next major release. No deprecation notice is emitted while compiling for these deprecations.&lt;br /&gt;
* .NET Framework 4.5.2 support is deprecated; support will be dropped when .NET Framework 4.5.2 reaches end of support from Microsoft on April 26, 2022. Circumstances in the future may cause an earlier removal.&lt;br /&gt;
&lt;br /&gt;
== 4.1.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** None&lt;br /&gt;
* New features:&lt;br /&gt;
** The leading number denoting number of dice (before the &amp;quot;d&amp;quot;) is optional and will default to 1 if not specified.&lt;br /&gt;
** Nullability annotations have been added to public APIs, to assist developers in migrating their own applications using this library.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** None&lt;br /&gt;
&lt;br /&gt;
The package as well as Dice.dll is signed with the following digital certificate fingerprint. This signature is only available on the official download from NuGet and is separate from the Strong-Name Key found in GitHub.&lt;br /&gt;
* {{c|E5F191DB201E9E3CF85B2A9E2408352057ABD731949C986E36F812CFD90728A7}} (SHA-256)&lt;br /&gt;
* {{c|A87D3B543D551CCD330C23B31B653835A86569BC}} (SHA-1).&lt;br /&gt;
&lt;br /&gt;
== 4.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** Nested rolls are fully resolved in {{l|Dice.RollResult.ToString|RollResult.ToString()}}. For example, instead of ToString() reporting {{c|&amp;quot;(1d8)d6&amp;quot;}}, it will now report the value rolled for the d8, e.g. {{c|&amp;quot;3d6&amp;quot;}}.&lt;br /&gt;
** {{l|Dice.RollerConfig.ExecuteMacro|RollerConfig.ExecuteMacro}} was removed.&lt;br /&gt;
* New features:&lt;br /&gt;
** DiceRoller is now packaged for both .NET Standard 2.0 as well as .NET Framework 4.5.2. .NET Standard 2.0 supports .NET Framework 4.6.1+ and .NET Core 2.0.&lt;br /&gt;
** Success/failure rolls can now be decorated with critical/fumbles. A critical success (a roll that is both a critical and a success) is worth 2 successes, and a critical failure (a roll that is both a fumble and a failure) is worth -2 successes. This expands support into game systems which use success-based rolls but have varying degrees of success beyond just +1 or -1.&lt;br /&gt;
*** Unless a success/failure roll is explicitly decorated with a critical/fumble, those rolls will not be marked as criticals or fumbles even if the max or min amount is rolled. This keeps default behavior with such rolls consistent with how they worked previously.&lt;br /&gt;
** A new [[Dice Reference#numdice|{{c|[numDice]}}]] macro was added, which returns the total number of dice rolled up to this point. This macro is available in all scenarios, including the stand-alone {{l|Dice.Roller.Roll|Roller.Roll}}; using the Play-by-Post helper is not required to use this macro.&lt;br /&gt;
** A new property {{l|Dice.RollerConfig.RollDie|RollerConfig.RollDie}} was added to allow customizing the result of a die roll in a more friendly way. This property is a callback which receives the minimum and maximum value it can roll for a die, and should return a number within that range. By default, it will call {{l|Dice.RollerConfig.GetRandomBytes|RollerConfig.GetRandomBytes}} repeatedly until it gets a result it can transform into the output range without introducing any bias.&lt;br /&gt;
** New APIs {{l|Dice.Roller.Max|Roller.Max()}}, {{l|Dice.Roller.Min|Roller.Min()}}, and {{l|Dice.Roller.Average|Roller.Average()}} evaluate the dice expression and return the result as if all dice rolled their minimum, maximum, or average values.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** It is now possible to put an expression in parenthesis (a &amp;quot;nested roll&amp;quot;) everywhere a number is expected. Previously, comparisons incorrectly rejected nested rolls.&lt;br /&gt;
* Dependency updates:&lt;br /&gt;
** Updated Antlr4.Runtime.Standard from 4.7.1 to 4.7.2&lt;br /&gt;
** Updated System.ValueTuple from 4.4.0 to 4.5.0&lt;br /&gt;
* Other:&lt;br /&gt;
** The nuget package is now digitally signed with the certificate fingerprint {{c|a87d3b543d551ccd330c23b31b653835a86569bc}}. The same certificate is used to sign the .dll itself in addition to the package.&lt;br /&gt;
&lt;br /&gt;
== 3.1.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** Global functions can now show up inside math expressions without needing to wrap them in parenthesis. For example, {{c|-max(1, 2)+6}} will return 4. They still cannot show up inside of a roll expression without additional parenthesis.&lt;br /&gt;
** New API {{l|Dice.PbP.RollPost.HasDivergedFrom|RollPost.HasDivergedFrom()}} to test whether two RollPosts have Diverged. (Two RollPosts diverge when one is not a prefix of the other)&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Project:Copyright&amp;diff=990</id>
		<title>Project:Copyright</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Project:Copyright&amp;diff=990"/>
		<updated>2021-06-15T02:12:46Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: update copyright date&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;All content on this wiki (with exception of the full license texts reproduced below) is available under the [https://creativecommons.org/licenses/by-sa/4.0/ Creative Commons Attribution-ShareAlike 4.0 International] public license (CC-BY-SA 4.0). The full license has been reproduced below. In addition, specific pages (denoted below) are dual-licensed under the [https://opensource.org/licenses/MIT MIT license] as well. The full text of both licenses have been reproduced below.&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Dual-licensed pages ==&lt;br /&gt;
The following pages are dual-licensed under both the CC BY-SA 4.0 as well as the MIT license. You may choose to follow either or both licenses for these pages. These pages comprise the &amp;quot;associated documentation files&amp;quot; mentioned in the MIT license.&lt;br /&gt;
&lt;br /&gt;
* [[Dice]] and its [[Special:PrefixIndex/Dice/|subpages]] (API documentation)&lt;br /&gt;
* [[Dice Reference]]&lt;br /&gt;
&lt;br /&gt;
== Creative Commons Attribution-ShareAlike 4.0 International Public License ==&lt;br /&gt;
By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-ShareAlike 4.0 International Public License (&amp;quot;Public License&amp;quot;). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.&lt;br /&gt;
&lt;br /&gt;
'''Section 1 – Definitions.'''&lt;br /&gt;
&amp;lt;ol type=&amp;quot;a&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;'''Adapted Material''' means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.&lt;br /&gt;
&amp;lt;li&amp;gt;'''Adapter's License''' means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License.&lt;br /&gt;
&amp;lt;li&amp;gt;'''BY-SA Compatible License''' means a license listed at [https://creativecommons.org/compatiblelicenses creativecommons.org/compatiblelicenses], approved by Creative Commons as essentially the equivalent of this Public License.&lt;br /&gt;
&amp;lt;li&amp;gt;'''Copyright and Similar Rights''' means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.&lt;br /&gt;
&amp;lt;li&amp;gt;'''Effective Technological Measures''' means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.&lt;br /&gt;
&amp;lt;li&amp;gt;'''Exceptions and Limitations''' means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.&lt;br /&gt;
&amp;lt;li&amp;gt;'''License Elements''' means the license attributes listed in the name of a Creative Commons Public License. The License Elements of this Public License are Attribution and ShareAlike.&lt;br /&gt;
&amp;lt;li&amp;gt;'''Licensed Material''' means the artistic or literary work, database, or other material to which the Licensor applied this Public License.&lt;br /&gt;
Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.&lt;br /&gt;
&amp;lt;li&amp;gt;'''Licensor''' means the individual(s) or entity(ies) granting rights under this Public License.&lt;br /&gt;
&amp;lt;li&amp;gt;'''Share''' means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.&lt;br /&gt;
&amp;lt;li&amp;gt;'''Sui Generis Database Rights''' means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.&lt;br /&gt;
&amp;lt;li&amp;gt;'''You''' means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Section 2 – Scope.'''&lt;br /&gt;
&amp;lt;ol type=&amp;quot;a&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;'''License grant.'''&lt;br /&gt;
&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:&lt;br /&gt;
&amp;lt;ol type=&amp;quot;A&amp;quot;&amp;gt;&amp;lt;li&amp;gt;reproduce and Share the Licensed Material, in whole or in part; and&lt;br /&gt;
&amp;lt;li&amp;gt;produce, reproduce, and Share Adapted Material.&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;u&amp;gt;Exceptions and Limitations.&amp;lt;/u&amp;gt; For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;u&amp;gt;Term.&amp;lt;/u&amp;gt; The term of this Public License is specified in Section 6(a).&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;u&amp;gt;Media and formats; technical modifications allowed.&amp;lt;/u&amp;gt; The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;u&amp;gt;Downstream recipients.&amp;lt;/u&amp;gt;&lt;br /&gt;
&amp;lt;ol type=&amp;quot;A&amp;quot;&amp;gt;&amp;lt;li&amp;gt;&amp;lt;u&amp;gt;Offer from the Licensor – Licensed Material.&amp;lt;/u&amp;gt; Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;u&amp;gt;Additional offer from the Licensor – Adapted Material.&amp;lt;/u&amp;gt; Every recipient of Adapted Material from You automatically receives an offer from the Licensor to exercise the Licensed Rights in the Adapted Material under the conditions of the Adapter’s License You apply.&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;u&amp;gt;No downstream restrictions.&amp;lt;/u&amp;gt; You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;u&amp;gt;No endorsement.&amp;lt;/u&amp;gt; Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;'''Other rights.'''&lt;br /&gt;
&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.&lt;br /&gt;
&amp;lt;li&amp;gt;Patent and trademark rights are not licensed under this Public License.&lt;br /&gt;
&amp;lt;li&amp;gt;To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties.&amp;lt;/ol&amp;gt;&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Section 3 – License Conditions.'''&lt;br /&gt;
&lt;br /&gt;
Your exercise of the Licensed Rights is expressly made subject to the following conditions.&lt;br /&gt;
&amp;lt;ol type=&amp;quot;a&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;'''Attribution.'''&lt;br /&gt;
&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;If You Share the Licensed Material (including in modified form), You must:&lt;br /&gt;
&amp;lt;ol type=&amp;quot;A&amp;quot;&amp;gt;&amp;lt;li&amp;gt;retain the following if it is supplied by the Licensor with the Licensed Material:&lt;br /&gt;
&amp;lt;ol type=&amp;quot;i&amp;quot;&amp;gt;&amp;lt;li&amp;gt;identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);&lt;br /&gt;
&amp;lt;li&amp;gt;a copyright notice;&lt;br /&gt;
&amp;lt;li&amp;gt;a notice that refers to this Public License;&lt;br /&gt;
&amp;lt;li&amp;gt;a notice that refers to the disclaimer of warranties;&lt;br /&gt;
&amp;lt;li&amp;gt;a URI or hyperlink to the Licensed Material to the extent reasonably practicable;&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;indicate if You modified the Licensed Material and retain an indication of any previous modifications; and&lt;br /&gt;
&amp;lt;li&amp;gt;indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.&lt;br /&gt;
&amp;lt;li&amp;gt;If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;'''ShareAlike.'''&amp;lt;br&amp;gt;In addition to the conditions in Section 3(a), if You Share Adapted Material You produce, the following conditions also apply.&lt;br /&gt;
&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;The Adapter’s License You apply must be a Creative Commons license with the same License Elements, this version or later, or a BY-SA Compatible License.&lt;br /&gt;
&amp;lt;li&amp;gt;You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share Adapted Material.&lt;br /&gt;
&amp;lt;li&amp;gt;You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Adapted Material that restrict exercise of the rights granted under the Adapter's License You apply.&amp;lt;/ol&amp;gt;&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Section 4 – Sui Generis Database Rights.'''&lt;br /&gt;
&lt;br /&gt;
Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:&lt;br /&gt;
&amp;lt;ol type=&amp;quot;a&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database;&lt;br /&gt;
&amp;lt;li&amp;gt;if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material, including for purposes of Section 3(b); and&lt;br /&gt;
&amp;lt;li&amp;gt;You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.&lt;br /&gt;
&lt;br /&gt;
'''Section 5 – Disclaimer of Warranties and Limitation of Liability.'''&lt;br /&gt;
&amp;lt;ol type=&amp;quot;a&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li style=&amp;quot;font-weight: bold&amp;quot;&amp;gt;Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.&lt;br /&gt;
&amp;lt;li style=&amp;quot;font-weight: bold&amp;quot;&amp;gt;To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.&lt;br /&gt;
&amp;lt;li&amp;gt;The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Section 6 – Term and Termination.'''&lt;br /&gt;
&amp;lt;ol type=&amp;quot;a&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.&lt;br /&gt;
&amp;lt;li&amp;gt;Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:&lt;br /&gt;
&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or&lt;br /&gt;
&amp;lt;li&amp;gt;upon express reinstatement by the Licensor.&amp;lt;/ol&amp;gt;&lt;br /&gt;
For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.&lt;br /&gt;
&amp;lt;li&amp;gt;Sections 1, 5, 6, 7, and 8 survive termination of this Public License.&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Section 7 – Other Terms and Conditions.'''&lt;br /&gt;
&amp;lt;ol type=&amp;quot;a&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.&lt;br /&gt;
&amp;lt;li&amp;gt;Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Section 8 – Interpretation.'''&lt;br /&gt;
&amp;lt;ol type=&amp;quot;a&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.&lt;br /&gt;
&amp;lt;li&amp;gt;To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.&lt;br /&gt;
&amp;lt;li&amp;gt;No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.&lt;br /&gt;
&amp;lt;li&amp;gt;Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== MIT License ==&lt;br /&gt;
Copyright &amp;amp;copy; 2015-2021 Ryan Schmidt&lt;br /&gt;
&lt;br /&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:&lt;br /&gt;
&lt;br /&gt;
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
&lt;br /&gt;
THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Common.css&amp;diff=989</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Common.css&amp;diff=989"/>
		<updated>2020-02-22T19:25:15Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
@import url(&amp;quot;/fontawesome/css/all.css&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
.shaded {&lt;br /&gt;
    background-color: #f5f5f5;&lt;br /&gt;
    padding-left: 3px;&lt;br /&gt;
    padding-right: 3px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a {&lt;br /&gt;
    color: #0000ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.new {&lt;br /&gt;
    color: #ff0000;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.external {&lt;br /&gt;
    color: #0000ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a:visited {&lt;br /&gt;
    color: #8f00ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.new:visited {&lt;br /&gt;
    color: #800000;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.external:visited {&lt;br /&gt;
    color: #8f00ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a:hover {&lt;br /&gt;
    text-decoration: underline;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #page-namespaces, .skin-greystuff #page-tools, .skin-greystuff #header-navigation-container {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-logo, a.mw-wiki-logo {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer-banner, #footer-navigation, #f-copyrightico, #f-poweredbyico {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer, #footer-bottom {&lt;br /&gt;
    padding: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.nonumtoc .tocnumber {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Group-user.css&amp;diff=988</id>
		<title>MediaWiki:Group-user.css</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Group-user.css&amp;diff=988"/>
		<updated>2020-02-22T18:47:53Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: Created page with &amp;quot;/* CSS placed here will affect registered users only */ .skin-greystuff #header-navigation-container {     display: block; }  .skin-greystuff #page-namespaces, .skin-greystuff...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will affect registered users only */&lt;br /&gt;
.skin-greystuff #header-navigation-container {&lt;br /&gt;
    display: block;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #page-namespaces, .skin-greystuff #page-tools {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Common.css&amp;diff=987</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Common.css&amp;diff=987"/>
		<updated>2020-02-22T18:45:49Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.shaded {&lt;br /&gt;
    background-color: #f5f5f5;&lt;br /&gt;
    padding-left: 3px;&lt;br /&gt;
    padding-right: 3px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a {&lt;br /&gt;
    color: #0000ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.new {&lt;br /&gt;
    color: #ff0000;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.external {&lt;br /&gt;
    color: #0000ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a:visited {&lt;br /&gt;
    color: #8f00ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.new:visited {&lt;br /&gt;
    color: #800000;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.external:visited {&lt;br /&gt;
    color: #8f00ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a:hover {&lt;br /&gt;
    text-decoration: underline;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #page-namespaces, .skin-greystuff #page-tools, .skin-greystuff #header-navigation-container {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-logo, a.mw-wiki-logo {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer-banner, #footer-navigation, #f-copyrightico, #f-poweredbyico {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer, #footer-bottom {&lt;br /&gt;
    padding: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.nonumtoc .tocnumber {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Common.css&amp;diff=986</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Common.css&amp;diff=986"/>
		<updated>2020-02-22T18:42:10Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.shaded {&lt;br /&gt;
    background-color: #f5f5f5;&lt;br /&gt;
    padding-left: 3px;&lt;br /&gt;
    padding-right: 3px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a {&lt;br /&gt;
    color: #0000ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.new {&lt;br /&gt;
    color: #ff0000;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.external {&lt;br /&gt;
    color: #0000ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a:visited {&lt;br /&gt;
    color: #8f00ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.new:visited {&lt;br /&gt;
    color: #800000;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.external:visited {&lt;br /&gt;
    color: #8f00ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a:hover {&lt;br /&gt;
    text-decoration: underline;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-logo, a.mw-wiki-logo {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer-banner, #footer-navigation, #f-copyrightico, #f-poweredbyico {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer, #footer-bottom {&lt;br /&gt;
    padding: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.nonumtoc .tocnumber {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Common.css&amp;diff=985</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Common.css&amp;diff=985"/>
		<updated>2020-02-22T18:40:24Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.shaded {&lt;br /&gt;
    background-color: #f5f5f5;&lt;br /&gt;
    padding-left: 3px;&lt;br /&gt;
    padding-right: 3px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a {&lt;br /&gt;
    color: #0000ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.new {&lt;br /&gt;
    color: #ff0000;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.external {&lt;br /&gt;
    color: #0000ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a:visited {&lt;br /&gt;
    color: #8f00ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.new:visited {&lt;br /&gt;
    color: #800000;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.external:visited {&lt;br /&gt;
    color: #8f00ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a:hover {&lt;br /&gt;
    text-decoration: underline;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-logo, a.mw-wiki-logo {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer-banner, #footer-navigation, #f-copyrightico, #f-poweredbyico {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.nonumtoc .tocnumber {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Common.css&amp;diff=984</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Common.css&amp;diff=984"/>
		<updated>2020-02-22T18:38:52Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.shaded {&lt;br /&gt;
    background-color: #f5f5f5;&lt;br /&gt;
    padding-left: 3px;&lt;br /&gt;
    padding-right: 3px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* make links more obvious on greystuff */&lt;br /&gt;
/*&lt;br /&gt;
.skin-greystuff #mw-content-text a {&lt;br /&gt;
    color: #0000ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.new {&lt;br /&gt;
    color: #ff0000;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.external {&lt;br /&gt;
    color: #0000ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a:visited {&lt;br /&gt;
    color: #8f00ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.new:visited {&lt;br /&gt;
    color: #800000;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.external:visited {&lt;br /&gt;
    color: #8f00ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a:hover {&lt;br /&gt;
    text-decoration: underline;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff input[type=&amp;quot;submit&amp;quot;], .skin-greystuff input[type=&amp;quot;button&amp;quot;], .skin-greystuff button {&lt;br /&gt;
    color: #222222 !important;&lt;br /&gt;
}&lt;br /&gt;
*/&lt;br /&gt;
#p-logo, a.mw-wiki-logo {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer-banner, #footer-navigation, #f-copyrightico, #f-poweredbyico {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.nonumtoc .tocnumber {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Common.css&amp;diff=983</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Common.css&amp;diff=983"/>
		<updated>2020-02-22T18:37:34Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.shaded {&lt;br /&gt;
    background-color: #f5f5f5;&lt;br /&gt;
    padding-left: 3px;&lt;br /&gt;
    padding-right: 3px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* make links more obvious on greystuff */&lt;br /&gt;
/*&lt;br /&gt;
.skin-greystuff #mw-content-text a {&lt;br /&gt;
    color: #0000ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.new {&lt;br /&gt;
    color: #ff0000;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.external {&lt;br /&gt;
    color: #0000ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a:visited {&lt;br /&gt;
    color: #8f00ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.new:visited {&lt;br /&gt;
    color: #800000;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a.external:visited {&lt;br /&gt;
    color: #8f00ff;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff #mw-content-text a:hover {&lt;br /&gt;
    text-decoration: underline;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skin-greystuff input[type=&amp;quot;submit&amp;quot;], .skin-greystuff input[type=&amp;quot;button&amp;quot;], .skin-greystuff button {&lt;br /&gt;
    color: #222222 !important;&lt;br /&gt;
}&lt;br /&gt;
*/&lt;br /&gt;
#p-logo, #footer-banner, #footer-navigation, #f-copyrightico, #f-poweredbyico {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.nonumtoc .tocnumber {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Userlogin-helplink2&amp;diff=980</id>
		<title>MediaWiki:Userlogin-helplink2</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=MediaWiki:Userlogin-helplink2&amp;diff=980"/>
		<updated>2020-02-22T18:14:21Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: blank out&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=979</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=979"/>
		<updated>2019-12-26T06:06:53Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.1.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** None&lt;br /&gt;
* New features:&lt;br /&gt;
** The leading number denoting number of dice (before the &amp;quot;d&amp;quot;) is optional and will default to 1 if not specified.&lt;br /&gt;
** Nullability annotations have been added to public APIs, to assist developers in migrating their own applications using this library.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** None&lt;br /&gt;
&lt;br /&gt;
The package as well as Dice.dll is signed with the following digital certificate fingerprint. This signature is only available on the official download from NuGet and is separate from the Strong-Name Key found in GitHub.&lt;br /&gt;
* {{c|E5F191DB201E9E3CF85B2A9E2408352057ABD731949C986E36F812CFD90728A7}} (SHA-256)&lt;br /&gt;
* {{c|A87D3B543D551CCD330C23B31B653835A86569BC}} (SHA-1).&lt;br /&gt;
&lt;br /&gt;
== 4.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** Nested rolls are fully resolved in {{l|Dice.RollResult.ToString|RollResult.ToString()}}. For example, instead of ToString() reporting {{c|&amp;quot;(1d8)d6&amp;quot;}}, it will now report the value rolled for the d8, e.g. {{c|&amp;quot;3d6&amp;quot;}}.&lt;br /&gt;
** {{l|Dice.RollerConfig.ExecuteMacro|RollerConfig.ExecuteMacro}} was removed.&lt;br /&gt;
* New features:&lt;br /&gt;
** DiceRoller is now packaged for both .NET Standard 2.0 as well as .NET Framework 4.5.2. .NET Standard 2.0 supports .NET Framework 4.6.1+ and .NET Core 2.0.&lt;br /&gt;
** Success/failure rolls can now be decorated with critical/fumbles. A critical success (a roll that is both a critical and a success) is worth 2 successes, and a critical failure (a roll that is both a fumble and a failure) is worth -2 successes. This expands support into game systems which use success-based rolls but have varying degrees of success beyond just +1 or -1.&lt;br /&gt;
*** Unless a success/failure roll is explicitly decorated with a critical/fumble, those rolls will not be marked as criticals or fumbles even if the max or min amount is rolled. This keeps default behavior with such rolls consistent with how they worked previously.&lt;br /&gt;
** A new [[Dice Reference#numdice|{{c|[numDice]}}]] macro was added, which returns the total number of dice rolled up to this point. This macro is available in all scenarios, including the stand-alone {{l|Dice.Roller.Roll|Roller.Roll}}; using the Play-by-Post helper is not required to use this macro.&lt;br /&gt;
** A new property {{l|Dice.RollerConfig.RollDie|RollerConfig.RollDie}} was added to allow customizing the result of a die roll in a more friendly way. This property is a callback which receives the minimum and maximum value it can roll for a die, and should return a number within that range. By default, it will call {{l|Dice.RollerConfig.GetRandomBytes|RollerConfig.GetRandomBytes}} repeatedly until it gets a result it can transform into the output range without introducing any bias.&lt;br /&gt;
** New APIs {{l|Dice.Roller.Max|Roller.Max()}}, {{l|Dice.Roller.Min|Roller.Min()}}, and {{l|Dice.Roller.Average|Roller.Average()}} evaluate the dice expression and return the result as if all dice rolled their minimum, maximum, or average values.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** It is now possible to put an expression in parenthesis (a &amp;quot;nested roll&amp;quot;) everywhere a number is expected. Previously, comparisons incorrectly rejected nested rolls.&lt;br /&gt;
* Dependency updates:&lt;br /&gt;
** Updated Antlr4.Runtime.Standard from 4.7.1 to 4.7.2&lt;br /&gt;
** Updated System.ValueTuple from 4.4.0 to 4.5.0&lt;br /&gt;
* Other:&lt;br /&gt;
** The nuget package is now digitally signed with the certificate fingerprint {{c|a87d3b543d551ccd330c23b31b653835a86569bc}}. The same certificate is used to sign the .dll itself in addition to the package.&lt;br /&gt;
&lt;br /&gt;
== 3.1.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** Global functions can now show up inside math expressions without needing to wrap them in parenthesis. For example, {{c|-max(1, 2)+6}} will return 4. They still cannot show up inside of a roll expression without additional parenthesis.&lt;br /&gt;
** New API {{l|Dice.PbP.RollPost.HasDivergedFrom|RollPost.HasDivergedFrom()}} to test whether two RollPosts have Diverged. (Two RollPosts diverge when one is not a prefix of the other)&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=978</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=978"/>
		<updated>2019-12-26T05:51:42Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.1.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** None&lt;br /&gt;
* New features:&lt;br /&gt;
** The leading number denoting number of dice (before the &amp;quot;d&amp;quot;) is optional and will default to 1 if not specified.&lt;br /&gt;
** Nullability annotations have been added to public APIs, to assist developers in migrating their own applications using this library.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** None&lt;br /&gt;
&lt;br /&gt;
== 4.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** Nested rolls are fully resolved in {{l|Dice.RollResult.ToString|RollResult.ToString()}}. For example, instead of ToString() reporting {{c|&amp;quot;(1d8)d6&amp;quot;}}, it will now report the value rolled for the d8, e.g. {{c|&amp;quot;3d6&amp;quot;}}.&lt;br /&gt;
** {{l|Dice.RollerConfig.ExecuteMacro|RollerConfig.ExecuteMacro}} was removed.&lt;br /&gt;
* New features:&lt;br /&gt;
** DiceRoller is now packaged for both .NET Standard 2.0 as well as .NET Framework 4.5.2. .NET Standard 2.0 supports .NET Framework 4.6.1+ and .NET Core 2.0.&lt;br /&gt;
** Success/failure rolls can now be decorated with critical/fumbles. A critical success (a roll that is both a critical and a success) is worth 2 successes, and a critical failure (a roll that is both a fumble and a failure) is worth -2 successes. This expands support into game systems which use success-based rolls but have varying degrees of success beyond just +1 or -1.&lt;br /&gt;
*** Unless a success/failure roll is explicitly decorated with a critical/fumble, those rolls will not be marked as criticals or fumbles even if the max or min amount is rolled. This keeps default behavior with such rolls consistent with how they worked previously.&lt;br /&gt;
** A new [[Dice Reference#numdice|{{c|[numDice]}}]] macro was added, which returns the total number of dice rolled up to this point. This macro is available in all scenarios, including the stand-alone {{l|Dice.Roller.Roll|Roller.Roll}}; using the Play-by-Post helper is not required to use this macro.&lt;br /&gt;
** A new property {{l|Dice.RollerConfig.RollDie|RollerConfig.RollDie}} was added to allow customizing the result of a die roll in a more friendly way. This property is a callback which receives the minimum and maximum value it can roll for a die, and should return a number within that range. By default, it will call {{l|Dice.RollerConfig.GetRandomBytes|RollerConfig.GetRandomBytes}} repeatedly until it gets a result it can transform into the output range without introducing any bias.&lt;br /&gt;
** New APIs {{l|Dice.Roller.Max|Roller.Max()}}, {{l|Dice.Roller.Min|Roller.Min()}}, and {{l|Dice.Roller.Average|Roller.Average()}} evaluate the dice expression and return the result as if all dice rolled their minimum, maximum, or average values.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** It is now possible to put an expression in parenthesis (a &amp;quot;nested roll&amp;quot;) everywhere a number is expected. Previously, comparisons incorrectly rejected nested rolls.&lt;br /&gt;
* Dependency updates:&lt;br /&gt;
** Updated Antlr4.Runtime.Standard from 4.7.1 to 4.7.2&lt;br /&gt;
** Updated System.ValueTuple from 4.4.0 to 4.5.0&lt;br /&gt;
* Other:&lt;br /&gt;
** The nuget package is now digitally signed with the certificate fingerprint {{c|a87d3b543d551ccd330c23b31b653835a86569bc}}. The same certificate is used to sign the .dll itself in addition to the package.&lt;br /&gt;
&lt;br /&gt;
== 3.1.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** Global functions can now show up inside math expressions without needing to wrap them in parenthesis. For example, {{c|-max(1, 2)+6}} will return 4. They still cannot show up inside of a roll expression without additional parenthesis.&lt;br /&gt;
** New API {{l|Dice.PbP.RollPost.HasDivergedFrom|RollPost.HasDivergedFrom()}} to test whether two RollPosts have Diverged. (Two RollPosts diverge when one is not a prefix of the other)&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/Roller&amp;diff=977</id>
		<title>Dice/Roller</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/Roller&amp;diff=977"/>
		<updated>2018-12-23T20:16:01Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|Roller Class}}&lt;br /&gt;
Provides a Roll method to perform dice rolls.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Inheritance Hierarchy ==&lt;br /&gt;
System.Object&lt;br /&gt;
:Dice.Roller&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public static class Roller&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Constructors ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{static}} {{method}} || [[Dice/Roller/Roller|Roller()]] || Static constructor which initializes DefaultConfig.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{property}} || [[Dice/Roller/DefaultConfig|DefaultConfig]] || Gets or sets the default roller configuration.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Average (String)|Average(String)]] || Evaluates the string expression, using the default configuration and fixing all dice to their average value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Average (String, RollerConfig)|Average(String, RollerConfig)]] || Evaluates the string expression, using the specified configuration and fixing all dice to their average value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Average (String, RollerConfig, RollData)|Average(String, RollerConfig, RollData)]] || Evaluates the string expression, using the specified configuration and {{l|Dice.RollData|RollData}} and fixing all dice to their average value.&lt;br /&gt;
|-&lt;br /&gt;
| {{internal}} {{static}} {{method}} || [[/Parse|Parse(String, RollerConfig)]] || Parses the diceExpr into an AST without evaluating it.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Max (String)|Max(String)]] || Evaluates the string expression, using the default configuration and fixing all dice to their maximum value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Max (String, RollerConfig)|Max(String, RollerConfig)]] || Evaluates the string expression, using the specified configuration and fixing all dice to their maximum value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Max (String, RollerConfig, RollData)|Max(String, RollerConfig, RollData)]] || Evaluates the string expression, using the specified configuration and {{l|Dice.RollData|RollData}} and fixing all dice to their maximum value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Min (String)|Min(String)]] || Evaluates the string expression, using the default configuration and fixing all dice to their minimum value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Min (String, RollerConfig)|Min(String, RollerConfig)]] || Evaluates the string expression, using the specified configuration and fixing all dice to their minimum value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Min (String, RollerConfig, RollData)|Min(String, RollerConfig, RollData)]] || Evaluates the string expression, using the specified configuration and {{l|Dice.RollData|RollData}} and fixing all dice to their minimum value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Roll (String)|Roll(String)]] || Rolls dice according to the string expression, using the default configuration.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Roll (String, RollerConfig)|Roll(String, RollerConfig)]] || Rolls dice according to the string expression and configuration.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Roll (String, RollerConfig, RollData)|Roll(String, RollerConfig, RollData)]] || Rolls dice according to the string expression and configuration and with the given {{l|Dice.RollData|RollData}}.&lt;br /&gt;
|-&lt;br /&gt;
| {{internal}} {{static}} {{method}} || [[/Roll (DiceAST, RollerConfig)|Roll(DiceAST, RollerConfig)]] || Evaluates the root of the tree, returning the RollResult.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
The Roller class is the main entry point to the library, and allows you to roll dice according to a given dice expression. To customize various aspects of a roll, a configuration can be passed in.&lt;br /&gt;
&lt;br /&gt;
== Thread Safety ==&lt;br /&gt;
The DefaultConfig property is not thread safe. Calling Roll with a {{cs|null}} [[Dice/RollerConfig|RollerConfig]] will make use of the DefaultConfig property. To be thread safe, call Roll with a RollerConfig that was created just for that thread.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/Roller/Roll&amp;diff=976</id>
		<title>Dice/Roller/Roll</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/Roller/Roll&amp;diff=976"/>
		<updated>2018-12-23T20:15:03Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* Remarks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|Roller.Roll Method Overloads}}&lt;br /&gt;
&lt;br /&gt;
Rolls dice according to the string expression.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Overloads ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[../Roll (String)|Roll(String)]] || Rolls dice according to the string expression, using the default configuration.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[../Roll (String, RollerConfig)|Roll(String, RollerConfig)]] || Rolls dice according to the string expression and configuration.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[../Roll (String, RollerConfig, RollData)|Roll(String, RollerConfig, RollData)]] || Rolls dice according to the string expression and configuration and with the given {{l|Dice.RollData|RollData}}.&lt;br /&gt;
|-&lt;br /&gt;
|| {{internal}} {{static}} {{method}} || [[../Roll (DiceAST, RollerConfig)|Roll(DiceAST, RollerConfig)]] || Evaluates the root of the tree, returning the RollResult.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
{{cs|null}} can be passed as RollerConfig for the second and third overloads. This is equivalent to specifying {{cs|RollerConfig.DefaultConfig}} for those parameters. {{cs|null}} can be passed as RollData for the third overload. This is equivalent to calling the second overload and no user-defined data is associated with the roll.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/Roller/Roll&amp;diff=975</id>
		<title>Dice/Roller/Roll</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/Roller/Roll&amp;diff=975"/>
		<updated>2018-12-23T20:13:42Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|Roller.Roll Method Overloads}}&lt;br /&gt;
&lt;br /&gt;
Rolls dice according to the string expression.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Overloads ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[../Roll (String)|Roll(String)]] || Rolls dice according to the string expression, using the default configuration.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[../Roll (String, RollerConfig)|Roll(String, RollerConfig)]] || Rolls dice according to the string expression and configuration.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[../Roll (String, RollerConfig, RollData)|Roll(String, RollerConfig, RollData)]] || Rolls dice according to the string expression and configuration and with the given {{l|Dice.RollData|RollData}}.&lt;br /&gt;
|-&lt;br /&gt;
|| {{internal}} {{static}} {{method}} || [[../Roll (DiceAST, RollerConfig)|Roll(DiceAST, RollerConfig)]] || Evaluates the root of the tree, returning the RollResult.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
{{cs|null}} can be passed as RollerConfig for the second overload. This is equivalent to calling the first overload instead.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/Roller/Roll_(String,_RollerConfig)&amp;diff=974</id>
		<title>Dice/Roller/Roll (String, RollerConfig)</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/Roller/Roll_(String,_RollerConfig)&amp;diff=974"/>
		<updated>2018-12-23T20:12:58Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|Roller.Roll Method (String, RollerConfig)}}&lt;br /&gt;
Rolls dice according to the given dice expression. Please see [[Dice Reference]] for more information about dice expressions.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public static RollResult Roll(&lt;br /&gt;
    string diceExpr,&lt;br /&gt;
    RollerConfig config&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
; ''diceExpr''&lt;br /&gt;
: Type: System.String&lt;br /&gt;
: A [[Dice Reference|dice expression]].&lt;br /&gt;
; ''config''&lt;br /&gt;
: Type: [[Dice/RollerConfig|Dice.RollerConfig]]&lt;br /&gt;
: Configuration to use for this roll. If {{cs|null}}, the [[Dice/Roller/DefaultConfig|DefaultConfig]] will be used.&lt;br /&gt;
&lt;br /&gt;
=== Return value ===&lt;br /&gt;
Type: [[Dice/RollResult|Dice.RollResult]]&lt;br /&gt;
&lt;br /&gt;
The result of rolling ''diceExpr''.&lt;br /&gt;
&lt;br /&gt;
== Exceptions ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Exception !! Condition&lt;br /&gt;
|-&lt;br /&gt;
| ArgumentNullException || ''diceExpr'' is {{cs|null}}.&lt;br /&gt;
|-&lt;br /&gt;
| [[Dice/DiceException|DiceException]] || An error was detected with ''diceExpr''.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When a DiceException is thrown, the exception will contain an ErrorCode property which describes the error in more detail.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/Roller/Roll_(String,_RollerConfig,_RollData)&amp;diff=973</id>
		<title>Dice/Roller/Roll (String, RollerConfig, RollData)</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/Roller/Roll_(String,_RollerConfig,_RollData)&amp;diff=973"/>
		<updated>2018-12-23T20:12:47Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: Created page with &amp;quot;{{APIdoc|Roller.Roll Method (String, RollerConfig, RollData)}} Rolls dice according to the given dice expression and with the given RollData. Please see Dice Reference for...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|Roller.Roll Method (String, RollerConfig, RollData)}}&lt;br /&gt;
Rolls dice according to the given dice expression and with the given RollData. Please see [[Dice Reference]] for more information about dice expressions.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public static RollResult Roll(&lt;br /&gt;
    string diceExpr,&lt;br /&gt;
    RollerConfig config,&lt;br /&gt;
    RollData data&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
; ''diceExpr''&lt;br /&gt;
: Type: System.String&lt;br /&gt;
: A [[Dice Reference|dice expression]].&lt;br /&gt;
; ''config''&lt;br /&gt;
: Type: [[Dice/RollerConfig|Dice.RollerConfig]]&lt;br /&gt;
: Configuration to use for this roll. If {{cs|null}}, the [[Dice/Roller/DefaultConfig|DefaultConfig]] will be used.&lt;br /&gt;
; ''data''&lt;br /&gt;
: Type: {{l|Dice.RollData|Dice.RollData}}&lt;br /&gt;
: Additional data that is scoped to this roll.&lt;br /&gt;
&lt;br /&gt;
=== Return value ===&lt;br /&gt;
Type: [[Dice/RollResult|Dice.RollResult]]&lt;br /&gt;
&lt;br /&gt;
The result of rolling ''diceExpr''.&lt;br /&gt;
&lt;br /&gt;
== Exceptions ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Exception !! Condition&lt;br /&gt;
|-&lt;br /&gt;
| ArgumentNullException || ''diceExpr'' is {{cs|null}}.&lt;br /&gt;
|-&lt;br /&gt;
| [[Dice/DiceException|DiceException]] || An error was detected with ''diceExpr''.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When a DiceException is thrown, the exception will contain an ErrorCode property which describes the error in more detail.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/Roller&amp;diff=972</id>
		<title>Dice/Roller</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/Roller&amp;diff=972"/>
		<updated>2018-12-23T19:54:20Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|Roller Class}}&lt;br /&gt;
Provides a Roll method to perform dice rolls.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Inheritance Hierarchy ==&lt;br /&gt;
System.Object&lt;br /&gt;
:Dice.Roller&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public static class Roller&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Constructors ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{static}} {{method}} || [[Dice/Roller/Roller|Roller()]] || Static constructor which initializes DefaultConfig.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{property}} || [[Dice/Roller/DefaultConfig|DefaultConfig]] || Gets or sets the default roller configuration.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Average (String)|Roll(String)]] || Evaluates the string expression, using the default configuration and fixing all dice to their average value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Average (String, RollerConfig)|Roll(String, RollerConfig)]] || Evaluates the string expression, using the specified configuration and fixing all dice to their average value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Average (String, RollerConfig, RollData)|Roll(String, RollerConfig, RollData)]] || Evaluates the string expression, using the specified configuration and {{l|Dice.RollData|RollData}} and fixing all dice to their average value.&lt;br /&gt;
|-&lt;br /&gt;
| {{internal}} {{static}} {{method}} || [[/Parse|Parse(String, RollerConfig)]] || Parses the diceExpr into an AST without evaluating it.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Max (String)|Roll(String)]] || Evaluates the string expression, using the default configuration and fixing all dice to their maximum value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Max (String, RollerConfig)|Roll(String, RollerConfig)]] || Evaluates the string expression, using the specified configuration and fixing all dice to their maximum value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Max (String, RollerConfig, RollData)|Roll(String, RollerConfig, RollData)]] || Evaluates the string expression, using the specified configuration and {{l|Dice.RollData|RollData}} and fixing all dice to their maximum value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Min (String)|Roll(String)]] || Evaluates the string expression, using the default configuration and fixing all dice to their minimum value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Min (String, RollerConfig)|Roll(String, RollerConfig)]] || Evaluates the string expression, using the specified configuration and fixing all dice to their minimum value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Min (String, RollerConfig, RollData)|Roll(String, RollerConfig, RollData)]] || Evaluates the string expression, using the specified configuration and {{l|Dice.RollData|RollData}} and fixing all dice to their minimum value.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Roll (String)|Roll(String)]] || Rolls dice according to the string expression, using the default configuration.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Roll (String, RollerConfig)|Roll(String, RollerConfig)]] || Rolls dice according to the string expression and configuration.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Roll (String, RollerConfig, RollData)|Roll(String, RollerConfig, RollData)]] || Rolls dice according to the string expression and configuration and with the given {{l|Dice.RollData|RollData}}.&lt;br /&gt;
|-&lt;br /&gt;
| {{internal}} {{static}} {{method}} || [[/Roll (DiceAST, RollerConfig)|Roll(DiceAST, RollerConfig)]] || Evaluates the root of the tree, returning the RollResult.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
The Roller class is the main entry point to the library, and allows you to roll dice according to a given dice expression. To customize various aspects of a roll, a configuration can be passed in.&lt;br /&gt;
&lt;br /&gt;
== Thread Safety ==&lt;br /&gt;
The DefaultConfig property is not thread safe. Calling Roll with a {{cs|null}} [[Dice/RollerConfig|RollerConfig]] will make use of the DefaultConfig property. To be thread safe, call Roll with a RollerConfig that was created just for that thread.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice_Reference&amp;diff=971</id>
		<title>Dice Reference</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice_Reference&amp;diff=971"/>
		<updated>2018-12-23T18:15:58Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* Macros */ add numDice&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DiceRoller supports a robust syntax to roll dice of all descriptions and modify those rolls in various ways. The most simple way to roll dice is via {{c|{{p|N}}d{{p|X}}+{{p|Y}}}}, which says to roll N dice that each have X sides, and then add Y to the total. An example would be {{c|1d20+4}}.&lt;br /&gt;
&lt;br /&gt;
In this documentation, any {{p|bold green}} text refers to placeholders, where normal text indicates symbols that should be left as-is. For example, the d in 1d20 must be left as the letter d, it is not a placeholder for something else.&lt;br /&gt;
&lt;br /&gt;
== Basic rolls ==&lt;br /&gt;
; {{c|{{p|N}}d{{p|X}}}}&lt;br /&gt;
: This will roll N dice with X sides per die (numbered from 1 to X). The dice are then added together to get the final result.&lt;br /&gt;
; {{c|{{p|N}}dF}}&lt;br /&gt;
: This will roll N fudge dice, which are dice with the numbers -1, 0, and 1.&lt;br /&gt;
; {{c|{{p|N}}dF{{p|X}}}}&lt;br /&gt;
: This will roll N fudge dice with a custom range, numbered from -X to X.&lt;br /&gt;
; {{c|{{p|N}}}}&lt;br /&gt;
: This will just result in the static number N, which is useful for when you just want to add a constant number to something or do pure math without rolling dice. N can be any decimal number, and may be negative.&lt;br /&gt;
&lt;br /&gt;
Basic rolls can be augmented with functions and extras. This guide will mark the functions and extras that can apply to basic rolls with (Basic). For example, {{c|1d20ad}} rolls 1d20 with advantage (rolls the expression twice and takes the highest result), and {{c|4d6dl1}} rolls 4d6 and then drops the lowest roll. These could also be represented as {{c|1d20.advantage()}} and {{c|4d6.droplowest(1)}}.&lt;br /&gt;
&lt;br /&gt;
== Math ==&lt;br /&gt;
Math can be performed with die rolls, with addition ({{c|+}}), subtraction ({{c|-}}), multiplication ({{c|*}}), and division ({{c|/}}) being allowed. Math expressions can be wrapped in parenthesis as well to clearly denote which expressions should be evaluated first, or to inject a math operation into any location where a number would normally be expected. Any roll expression is valid on either side of a math operator, whether that is a roll or just a number. For example, all of the following are valid rolls:&lt;br /&gt;
* {{c|1d20+4}}&lt;br /&gt;
* {{c|(1d10+2d6+2)*1.5}}&lt;br /&gt;
* {{c|(1d8)d10}} (rolls 1d8, and then rolls that many d10s, returning the sum of the d10s)&lt;br /&gt;
* {{c|10000/6}} (divides 10,000 by 6, and returns the result. In other words, rolling dice is not required)&lt;br /&gt;
&lt;br /&gt;
== Macros ==&lt;br /&gt;
Whenever a number is expected, a macro can be provided instead. The stand-alone dice roller does not define any macros, but the Play-by-Post helper utility defines some (see below for more details). Additionally, the program which uses the library may define custom macros. Macros are enclosed in square brackets, and can have any text inside of them (except for a right square bracket). An example of a macro may be something that looks up a property on a character sheet, but the possibilities are unlimited.&lt;br /&gt;
&lt;br /&gt;
Examples of macros:&lt;br /&gt;
* {{c|1d20+[WIS-mod]}} (rolls 1d20 and adds the result of the WIS-mod macro)&lt;br /&gt;
* {{c|1d10+[SneakAttack]d6}} (rolls 1d10 plus a number of d6's equal to the SneakAttack macro)&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined Macros ===&lt;br /&gt;
These macros are always defined.&lt;br /&gt;
&lt;br /&gt;
==== numDice ====&lt;br /&gt;
The numDice macro returns the number of dice rolled so far in the current roll. For example, {{c|5d4 + [numDice]}} is the same as {{c|5d4 + 5}}.&lt;br /&gt;
&lt;br /&gt;
=== Play-by-Post Macros ===&lt;br /&gt;
The following macros are pre-defined if the Play-by-Post helper is used. If dice are rolled individually (not collected in a post containing multiple rolls), these macros are not defined.&lt;br /&gt;
&lt;br /&gt;
==== roll ====&lt;br /&gt;
The roll macro allows for retrieving the value or other properties of previous dice rolls in the same post. It can be invoked in the following ways. Should an invocation be invalid, nothing happens (which means an error is likely displayed stating that the macro is invalid).&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}]}}&lt;br /&gt;
: Retrieves the value of the Xth roll in the post. The first roll in the post is X = 1. This can only be used to retrieve the value of previous rolls, it will not work if X is greater than or equal to the current roll number. If X is negative, it counts backwards from the current post (so X = -1 obtains the value of the previous post). X = 0 is invalid.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:{{p|Y}}]}}&lt;br /&gt;
: Retrieves the value of the Yth kept die roll in the Xth post. X is counted as per above. Y is counted from left-to-right in the normalized dice expression, and skips over dropped dice. Unlike X, Y cannot be negative (the first die is Y = 1).&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:critical]}}&lt;br /&gt;
: Counts the number of dice in the Xth roll that were marked as criticals.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:{{p|Y}}:critical]}}&lt;br /&gt;
: This is 1 if the Yth die in the Xth roll is critical, and 0 otherwise.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:fumble]}}&lt;br /&gt;
: Counts the number of dice in the Xth roll that were marked as fumbles.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:{{p|Y}}:fumble]}}&lt;br /&gt;
: This is 1 if the Yth die in the Xth roll is a fumble, and 0 otherwise.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:success]}}&lt;br /&gt;
: Counts the number of dice in the Xth roll that were marked as successes.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:{{p|Y}}:success]}}&lt;br /&gt;
: This is 1 if the Yth die in the Xth roll is a success, and 0 otherwise.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:failure]}}&lt;br /&gt;
: Counts the number of dice in the Xth roll that were marked as failures.&lt;br /&gt;
&lt;br /&gt;
; {{c|[roll:{{p|X}}:{{p|Y}}:failure]}}&lt;br /&gt;
: This is 1 if the Yth die in the Xth roll is a failure, and 0 otherwise.&lt;br /&gt;
&lt;br /&gt;
== Grouped rolls ==&lt;br /&gt;
{{c|{{p|N}}&amp;lt;nowiki&amp;gt;{&amp;lt;/nowiki&amp;gt;{{p|roll1}}, {{p|roll2}}, {{p|...}}&amp;lt;nowiki&amp;gt;}&amp;lt;/nowiki&amp;gt;}} or {{c|&amp;lt;nowiki&amp;gt;{&amp;lt;/nowiki&amp;gt;{{p|roll1}}, {{p|roll2}}, {{p|...}}&amp;lt;nowiki&amp;gt;}&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
Grouped rolls are a complex and powerful mechanism to roll groups of disparate dice and then operate on those groups. A grouped roll is made by enclosing one or more basic rolls inside of curly braces. A number N can be specified in front of the group to evaluate that group that number of times. For example, {{c|6&amp;lt;nowiki&amp;gt;{&amp;lt;/nowiki&amp;gt;4d6dl1&amp;lt;nowiki&amp;gt;}&amp;lt;/nowiki&amp;gt;}} rolls 4d6 (dropping the lowest roll) six times, and returns each result.&lt;br /&gt;
&lt;br /&gt;
Grouped rolls can be augmented with functions and extras. This guide will mark the functions and extras that can apply to grouped rolls with (Group). For example, {{c|{2d8,3d6}kh1}} rolls 2d8 and 3d6, sums each one, and then keeps the highest result. This could also be expressed as {{c|{2d8,3d6}.keephighest(1)}}.&lt;br /&gt;
&lt;br /&gt;
== Comparisons ==&lt;br /&gt;
Some extras and functions take comparisons as parameters. A comparison is '''implicit''' if it just contains a number with no leading comparison operator, or '''explicit''' if it has a leading comparison operator. Some extras and functions require explicit comparisons, while others are ok with implicit comparisons as well.&lt;br /&gt;
&lt;br /&gt;
The valid comparisons are as follows:&lt;br /&gt;
* {{c|{{p|N}}}} (implicit comparison that tests if the result is equal to N)&lt;br /&gt;
* {{c|1=={{p|N}}}}&lt;br /&gt;
* {{c|&amp;gt;{{p|N}}}}&lt;br /&gt;
* {{c|&amp;lt;{{p|N}}}}&lt;br /&gt;
* {{c|1=&amp;gt;={{p|N}}}} (tests if the result is greater than or equal to N)&lt;br /&gt;
* {{c|1=&amp;lt;={{p|N}}}} (tests if the result is less than or equal to N)&lt;br /&gt;
* {{c|1=!={{p|N}}}} or {{c|&amp;lt;&amp;gt;{{p|N}}}} (tests if the result is not equal to N)&lt;br /&gt;
&lt;br /&gt;
== Extras ==&lt;br /&gt;
Extras can be added at the end of basic or group rolls to modify their behavior. If an extra takes a comparison as its parameter, you can specify that extra multiple times in order to compare against all of them. For example, {{c|1d6rr2rr4rr6}} would roll 1d6 and re-roll any even number. Extras can be added in any order, but are always evaluated in the following order:&lt;br /&gt;
# Explode&lt;br /&gt;
# Reroll&lt;br /&gt;
# Keep/Drop/Advantage&lt;br /&gt;
# Success/Failure&lt;br /&gt;
# Critical/Fumble&lt;br /&gt;
# Sort&lt;br /&gt;
&lt;br /&gt;
If an extra is marked with (Basic) it can be used with basic rolls, and if it is marked with (Group) it can be used with group rolls. Those marked (Basic/Group) can be used with both types of rolls. If the extra takes a parameter, it will indicate if it takes a number {{p|N}}, a comparison {{p|C}}, or an explicit comparison {{p|EC}}.&lt;br /&gt;
&lt;br /&gt;
=== Explode (Basic) ===&lt;br /&gt;
; {{c|!e}}&lt;br /&gt;
: Whenever the maximum value is rolled for a die, that die is rerolled. Both the original and reroll are added to the total. This repeats until something other than the maximum value is rolled. For example, {{c|1d6!e}} would roll 1d6. If a 6 is rolled, another 1d6 is rolled, and so on. This could lead to a final roll of 6, 6, 4.&lt;br /&gt;
; {{c|!e{{p|C}}}}&lt;br /&gt;
: Whenever the comparison succeeds for a die, that die is rerolled. Both the original and reroll are added to the total. This repeats until the comparison fails.&lt;br /&gt;
; {{c|!c}}&lt;br /&gt;
: Per {{c|!e}}, except that the rerolled values are added to the original die result, rather than adding another die into the final result list. This is called a compounding explosion. For example, {{c|1d6!c}} would roll 1d6. If a 6 is rolled, another 1d6 is rolled, and so on. This could lead to a final roll of 6, 6, 4, which is represented by a single 6-sided die rolling a value of 16.&lt;br /&gt;
; {{c|!c{{p|C}}}}&lt;br /&gt;
: Per {{c|!c}}, except it compares the die result against the comparison C instead of using the maximum value of the die.&lt;br /&gt;
; {{c|!p}}&lt;br /&gt;
: Whenever the maximum value is rolled for a die, that die is rerolled and 1 is subtracted from the reroll. Both the original and reroll are added to the total. This repeats until something other than the maximum value is rolled. For example, {{c|1d6!e}} would roll 1d6. If a 6 is rolled, another 1d6 is rolled, and so on. This could lead to a final roll of 6, 5, 3 (assuming 6, 6, and then a 4 were rolled). This is called penetrating dice. Furthermore, a {{c|d100!p}} penetrates down to {{c|d20!p}}, and {{c|d20!p}} penetrates down to {{c|d6!p}}. This downgrade only happens once (so if {{c|1d100!p}} rolls 100, then 20, it continues to roll d20s instead of downgrading again to d6).&lt;br /&gt;
; {{c|!p{{p|C}}}}&lt;br /&gt;
: Per {{c|!p}}, except it compares the die result against the comparison C instead of using the maximum value of the die. Furthermore, the special downgrading rules are not used, so d100 will penetrate to d100, and d20 will penetrate to d20.&lt;br /&gt;
&lt;br /&gt;
=== Reroll (Basic/Group) ===&lt;br /&gt;
; {{c|rr{{p|C}}}}&lt;br /&gt;
: Whenever the comparison succeeds, it rerolls the die, discarding the previous result. This will happen until the comparison fails.&lt;br /&gt;
; {{c|ro{{p|C}}}}&lt;br /&gt;
: If the comparison succeeds, it will reroll the die, discarding the previous result. The die is rerolled a maximum of one time, even if the comparison would succeed again.&lt;br /&gt;
&lt;br /&gt;
=== Keep/Drop (Basic/Group) ===&lt;br /&gt;
; {{c|kh{{p|N}}}}&lt;br /&gt;
: Keeps the highest N results, discarding the rest.&lt;br /&gt;
; {{c|kl{{p|N}}}}&lt;br /&gt;
: Keeps the lowest N results, discarding the rest.&lt;br /&gt;
; {{c|dh{{p|N}}}}&lt;br /&gt;
: Discards the highest N results, keeping the rest.&lt;br /&gt;
; {{c|dl{{p|N}}}}&lt;br /&gt;
: Discards the lowest N results, keeping the rest.&lt;br /&gt;
&lt;br /&gt;
If multiple keep or drop expressions are applied, they work in sequence. For example, {{c|4d6dl1dl1}} would roll 4d6, drop the lowest die, and then drop the next lowest die. In other words, it is equivalent to {{c|4d6dl2}}. A keep/drop expression cannot be combined with advantage or disadvantage.&lt;br /&gt;
&lt;br /&gt;
=== Advantage (Basic/Group) ===&lt;br /&gt;
; {{c|ad}}&lt;br /&gt;
: Gives the expression advantage, causing it to be rolled twice and then keeping the highest result.&lt;br /&gt;
; {{c|da}}&lt;br /&gt;
: Gives the expression disadvantage, causing it to be rolled twice and then keeping the lowest result.&lt;br /&gt;
&lt;br /&gt;
Advantage or disadvantage cannot be combined with keep/drop expressions.&lt;br /&gt;
&lt;br /&gt;
=== Success/Failure (Basic/Group) ===&lt;br /&gt;
; {{c|{{p|EC}}}}&lt;br /&gt;
: Each die rolled is compared against EC. If it matches, it counts as one success. If it does not match, it counts as zero successes. The result of the roll is the number of successes, rather than the sum of the dice. For example, {{c|5d10&amp;gt;6}} will roll 5d10 and count one success each time the die comes up as 7 or higher.&lt;br /&gt;
; {{c|{{p|EC}}f{{p|C}}}}&lt;br /&gt;
: Each die rolled is compared against EC. If it matches, it counts as one success. If it does not match EC, but does match C, it removes one success. Otherwise, it counts as zero successes. The result of the roll is the number of successes (which may be negative), rather than the sum of the dice.&lt;br /&gt;
&lt;br /&gt;
=== Critical/Fumble (Basic) ===&lt;br /&gt;
; {{c|cs{{p|C}}}}&lt;br /&gt;
: Each die rolled is compared against C, and marked as a critical success should it succeed.&lt;br /&gt;
; {{c|cs{{p|C}}f{{p|C}}}}&lt;br /&gt;
: Each die rolled is compared against both comparisons. The first marks it as a critical success should it succeed, and the second marks it as a fumble (critical failure) should it succeed.&lt;br /&gt;
; {{c|cf{{p|C}}}}&lt;br /&gt;
: Each die rolled is compared against C, and marked as a fumble should it succeed.&lt;br /&gt;
&lt;br /&gt;
Critical successes and fumbles do not have any mechanical function by themselves, but can be tracked via macros or functions, and are usually displayed differently. It is possible for a die to be marked as both a critical and a fumble at the same time. If a roll does not have a critical/fumble expression attached to it, then a roll of the maximum result is counted as a critical and the minimum result is counted as a fumble.&lt;br /&gt;
&lt;br /&gt;
=== Sort (Basic/Group) ===&lt;br /&gt;
; {{c|sa}}&lt;br /&gt;
: Causes each die rolled to be sorted in ascending order for display purposes.&lt;br /&gt;
; {{c|sd}}&lt;br /&gt;
: Causes each die rolled to be sorted in descending order for display purposes.&lt;br /&gt;
&lt;br /&gt;
== Global functions ==&lt;br /&gt;
Global functions can be used wherever a math expression can be used, and transform the die results in various ways. The following global functions are built-in to the library, however the program which uses the library can also define its own global functions. If the function takes a parameter, it will indicate if it takes an expression {{p|E}} (which can be any arbitrary math or roll expression), or an explicit comparison {{p|C}}.&lt;br /&gt;
&lt;br /&gt;
=== floor ===&lt;br /&gt;
{{c|floor({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
Takes the mathematical floor of the expression, truncating any decimal portion. Example: {{c|1d20+floor([Levels]/2)}}&lt;br /&gt;
&lt;br /&gt;
=== ceil ===&lt;br /&gt;
{{c|ceil({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
Takes the mathematical ceiling of the expression, causing any decimal portion to round up to the next whole number.&lt;br /&gt;
&lt;br /&gt;
=== round ===&lt;br /&gt;
{{c|round({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
Rounds the result of the expression. Decimal values greater than or equal to 0.5 are rounded away from zero, whereas decimal values less than 0.5 are rounded towards zero. For example, 1.5 and 1.6 both round to 2, 1.4 rounds to 1, -1.5 and -1.6 both round to -2, and -1.4 rounds to -1.&lt;br /&gt;
&lt;br /&gt;
=== abs ===&lt;br /&gt;
{{c|abs({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
Takes the absolute value of the expression.&lt;br /&gt;
&lt;br /&gt;
=== max ===&lt;br /&gt;
{{c|max({{p|E}}, {{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
Returns the highest Value from the two expressions. Dice rolled in the low-valued expression are all marked as dropped.&lt;br /&gt;
&lt;br /&gt;
=== min ===&lt;br /&gt;
{{c|min({{p|E}}, {{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
Returns the lowest Value from the two expressions. Dice rolled in the high-valued expression are all marked as dropped.&lt;br /&gt;
&lt;br /&gt;
=== if ===&lt;br /&gt;
; {{c|if({{p|E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;}}, {{p|C}}, {{P|E&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;}})}}&lt;br /&gt;
: If the comparison succeeds for E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;, then this returns the Value of E&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. Otherwise, this returns 0.&lt;br /&gt;
&lt;br /&gt;
; {{c|if({{p|E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;}}, {{p|C}}, {{P|E&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;}}, {{p|E&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;}})}}&lt;br /&gt;
: If the comparison succeeds for E&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;, then this returns the Value of E&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. Otherwise, this returns the Value of E&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Note that all expressions in {{c|if()}} are evaluated, even if they are not returned.&lt;br /&gt;
&lt;br /&gt;
== Dice functions ==&lt;br /&gt;
Dice functions, like dice extras, are added to the end of die rolls. All dice functions must come after dice extras, but can otherwise go in any order. The following dice functions are pre-defined by the library, but the program may add more.&lt;br /&gt;
&lt;br /&gt;
If a function is marked with (Basic) it can be used with basic rolls, and if it is marked with (Group) it can be used with group rolls. Those marked (Basic/Group) can be used with both types of rolls. If the function takes a parameter, it will indicate if it takes a number {{p|N}}, an expression {{p|E}} (which can be any arbitrary math or roll expression), or an explicit comparison {{p|C}}. Should a function take a number as a parameter, it must either be a literal number or a macro, it cannot contain any rolls or math.&lt;br /&gt;
&lt;br /&gt;
=== reroll (Basic/Group) ===&lt;br /&gt;
{{c|.reroll({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|rr}} extra once for each comparison passed into the function. At least one comparison must be specified. For example, to reroll 1d6 whenever an even number comes up, you could specify {{c|1=1d6.reroll(=2, =4, =6)}}.&lt;br /&gt;
&lt;br /&gt;
=== rerollN (Basic/Group) ===&lt;br /&gt;
{{c|.rerollN({{p|N}}, {{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
Like reroll, however will only reroll at most N times before it keeps the final result (even if one of the comparisons would still succeed). At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== rerollOnce (Basic/Group) ===&lt;br /&gt;
{{c|.rerollOnce({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|ro}} extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== explode (Basic) ===&lt;br /&gt;
{{c|.explode({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|!e}} extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== compound (Basic) ===&lt;br /&gt;
{{c|.compound({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|!c}} extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== penetrate (Basic) ===&lt;br /&gt;
{{c|.penetrate({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|!p}} extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== compoundPenetrate (Basic) ===&lt;br /&gt;
{{c|.compoundPenetrate({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
Like penetrate, except all additional penetration dice rolled are added to the initial value (just like the compound function). At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== keepHighest (Basic/Group) ===&lt;br /&gt;
{{c|.keepHighest({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|kh}} extra.&lt;br /&gt;
&lt;br /&gt;
=== keepLowest (Basic/Group) ===&lt;br /&gt;
{{c|.keepLowest({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|kl}} extra.&lt;br /&gt;
&lt;br /&gt;
=== dropHighest (Basic/Group) ===&lt;br /&gt;
{{c|.dropHighest({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|dh}} extra.&lt;br /&gt;
&lt;br /&gt;
=== dropLowest (Basic/Group) ===&lt;br /&gt;
{{c|.dropLowest({{p|E}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|dl}} extra.&lt;br /&gt;
&lt;br /&gt;
=== advantage (Basic/Group) ===&lt;br /&gt;
{{c|.advantage()}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|ad}} extra.&lt;br /&gt;
&lt;br /&gt;
=== disadvantage (Basic/Group) ===&lt;br /&gt;
{{c|.disadvantage()}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|da}} extra.&lt;br /&gt;
&lt;br /&gt;
=== success (Basic/Group) ===&lt;br /&gt;
{{c|.success({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the success extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== failure (Basic/Group) ===&lt;br /&gt;
{{c|.failure({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
Specifies one or more failure comparison without specifying a success comparison. At least one success comparison must be specified via other means, such as the success extra or by calling {{c|.success({{p|C}})}}.&lt;br /&gt;
&lt;br /&gt;
=== critical (Basic) ===&lt;br /&gt;
{{c|.critical({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|cs}} extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== fumble (Basic) ===&lt;br /&gt;
{{c|.fumble({{p|C}}, {{p|C}}, {{p|...}})}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|cf}} extra once for each comparison passed into the function. At least one comparison must be specified.&lt;br /&gt;
&lt;br /&gt;
=== sortAsc (Basic/Group) ===&lt;br /&gt;
{{c|.sortAsc()}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|sa}} extra.&lt;br /&gt;
&lt;br /&gt;
=== sortDesc (Basic/Group) ===&lt;br /&gt;
{{c|.sortDesc()}}&lt;br /&gt;
&lt;br /&gt;
This is equal to specifying the {{c|sd}} extra.&lt;br /&gt;
&lt;br /&gt;
=== expand (Group) ===&lt;br /&gt;
{{c|.expand()}}&lt;br /&gt;
&lt;br /&gt;
Normally, grouped rolls display aggregated results instead of showing the value of each individual die rolled. For example, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will display (for example) {{c|(15)}} instead of {{c|(4 + 5 + 3 + 3)}}. The expand function causes it to display the value of each individual die instead, so {{c|&amp;lt;nowiki&amp;gt;{4d6}.expand()&amp;lt;/nowiki&amp;gt;}} will display (for example) {{c|(4 + 5 + 3 + 3)}}. Expand is applied before sorting, so you can sort the individual rolls of a group if you both expand and sort.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/BuiltinMacros/NumDice&amp;diff=970</id>
		<title>Dice/BuiltinMacros/NumDice</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/BuiltinMacros/NumDice&amp;diff=970"/>
		<updated>2018-12-23T18:11:01Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: create&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|BuiltinMacros.NumDice Method (MacroContext)}}&lt;br /&gt;
Returns the number of dice rolled so far.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
[DiceMacro(&amp;quot;numDice&amp;quot;)]&lt;br /&gt;
public static void NumDice(&lt;br /&gt;
    MacroContext context&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
; ''context''&lt;br /&gt;
: Type: [[Dice/MacroContext|Dice.MacroContext]]&lt;br /&gt;
: The context of the macro invocation.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/BuiltinMacros&amp;diff=969</id>
		<title>Dice/BuiltinMacros</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/BuiltinMacros&amp;diff=969"/>
		<updated>2018-12-23T18:09:26Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: create&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|BuiltinMacros Class}}&lt;br /&gt;
Contains callbacks for all built-in macros.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Inheritance Hierarchy ==&lt;br /&gt;
System.Object&lt;br /&gt;
: Dice.BuiltinMacros&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public static class BuiltinMacros&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/NumDice|NumDice(MacroContext)]] || Returns the number of dice rolled so far.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
These macros are automatically registered whenever constructing a new [[Dice/RollerConfig|RollerConfig]] object, but can be removed from the macro registry if desired.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice&amp;diff=968</id>
		<title>Dice</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice&amp;diff=968"/>
		<updated>2018-12-23T18:04:39Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* Classes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|Dice Namespace}}&lt;br /&gt;
The Dice namespace contains the base objects interacted with in the library. It is generally not needed to make use of the [[Dice/AST|Dice.AST]] or [[Dice/Grammar|Dice.Grammar]] namespaces in the course of normal interaction. However, advanced use cases may need to directly access objects in those namespaces.&lt;br /&gt;
&lt;br /&gt;
The [[Dice/PbP|Dice.PbP]] namespace is useful if you need to keep track of multiple rolls in a play-by-post environment.&lt;br /&gt;
&lt;br /&gt;
== Classes ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Class !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{class}} || [[Dice/BuiltinFunctions|BuiltinFunctions]] || Contains callbacks for all built-in functions. These functions are automatically registered whenever constructing a new [[Dice/RollerConfig|RollerConfig]] object, but can be removed from the function registry if desired.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{class}} || [[Dice/BuiltinMacros|BuiltinMacros]] || Contains callbacks for all built-in macros. These macros are automatically registered whenever constructing a new [[Dice/RollerConfig|RollerConfig]] object, but can be removed from the macro registry if desired.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{class}} || [[Dice/DiceException|DiceException]] || The exception that is thrown whenever an error happens while evaluating a dice expression. This is used to signify an issue with the expression itself rather than any programming error.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{class}} || [[Dice/DiceFunctionAttribute|DiceFunctionAttribute]] || An attribute that can be applied to methods which denotes the method is a valid [[Dice/FunctionCallback|FunctionCallback]]. The [[Dice/FunctionRegistry/RegisterType|FunctionRegistry.RegisterType]] function can be used to register types which contain methods marked with this attribute.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{class}} || [[Dice/DiceMacroAttribute|DiceMacroAttribute]] || An attribute that can be applied to methods which denotes the method is a valid {{l|MacroCallback}}. The {{l|MacroRegistry.RegisterType}} function can be used to register types which contain methods marked with this attribute.&lt;br /&gt;
|-&lt;br /&gt;
| {{internal}} {{static}} {{class}} || [[Dice/ExtensionMethods|ExtensionMethods]] || Internal extension methods that are not useful for general consumption.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{class}} || [[Dice/FunctionContext|FunctionContext]] || Contains the context for a function call, and is passed to function callbacks.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{class}} || [[Dice/FunctionRegistry|FunctionRegistry]] || Allows the user to register callbacks for functions.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{class}} || [[/MacroRegistry|MacroRegistry]] || Allows the user to register callbacks for macros.&lt;br /&gt;
|-&lt;br /&gt;
| {{internal}} {{class}} || [[Dice/InternalContext|InternalContext]] || Opaque contextual information used when evaluating dice expressions.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{class}} || [[Dice/MacroContext|MacroContext]] || Contains the context for a macro, and is passed to macro callbacks.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{class}} || [[Dice/RollData|RollData]] || Holds data relevant to the scope of a single roll (as opposed to the global scope of RollerConfig).&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{class}} || [[Dice/Roller|Roller]] || Exposes a function to roll a dice expression.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{class}} || [[Dice/RollerConfig|RollerConfig]] || Contains the configuration for a particular roll.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{class}} || [[Dice/RollResult|RollResult]] || Contains the result of a roll expression.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Structures ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Structure !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{struct}} || [[Dice/DieResult|DieResult]] || Contains the result of an individual die.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Delegates ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Delegate !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{delegate}} || [[Dice/FunctionCallback|FunctionCallback]] || Encapsulates a method which executes function logic.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{delegate}} || [[Dice/MacroCallback|MacroCallback]] || Encapsulates a method which executes macro logic.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Enumerations ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Enumeration !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{enum}} || [[Dice/DiceErrorCode|DiceErrorCode]] || Signifies what specific error happened when a [[Dice/DiceException|DiceException]] is thrown. This can be used to deliver more user-friendly error messages to the user instead of the error messages created by DiceException without needing to resort to string parsing.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{enum}} || [[Dice/DieFlags|DieFlags]] || Metadata attached to a [[Dice/DieResult|DieResult]]. This metadata is not used internally, but may be useful to expose to the end user by changing how die results are displayed appropriately.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{enum}} || [[Dice/DieType|DieType]] || Indicates what type of die was rolled for a DieResult.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{enum}} || [[Dice/FunctionScope|FunctionScope]] || When registering a function, this indicates what scopes the function should be registered to. When a [[Dice/FunctionCallback|FunctionCallback]] is called, this will indicate the scope from which the function was called from.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{enum}} || [[Dice/FunctionTiming|FunctionTiming]] || When registering a function, this indicates when this function is called in the evaluation of extras and functions.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{enum}} || [[Dice/ResultType|ResultType]] || Indicates whether a RollResult's Value represents the total of the roll or the number of successes.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{enum}} || [[Dice/SpecialDie|SpecialDie]] || Some DieResults indicate that they are special dice rather than actual rolls. This enumeration indicates what type of special die the result is. Special dice are used as guidance for display, such as open/close parenthesis when nested math expressions are rolled so that the user can see the dice displayed in the same format as they were specified.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig&amp;diff=967</id>
		<title>Dice/RollerConfig</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig&amp;diff=967"/>
		<updated>2018-12-23T18:03:53Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* Remarks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|RollerConfig Class}}&lt;br /&gt;
Stores various configuration related to the dice roller.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Inheritance Hierarchy ==&lt;br /&gt;
System.Object&lt;br /&gt;
:Dice.RollerConfig&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public class RollerConfig&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Constructors ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{method}} || [[Dice/RollerConfig/RollerConfig|RollerConfig()]] || Constructs a new RollerConfig instance with default values.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/FunctionRegistry|FunctionRegistry]] || Gets or sets the registry of all valid function names and their callbacks.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[/MacroRegistry|MacroRegistry]] || Gets or sets the registry of all valid macro names and their callbacks.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/GetRandomBytes|GetRandomBytes]] || Gets or sets the function used to generate random numbers.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxDice|MaxDice]] || Gets or sets the maximum number of dice that may be rolled.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxRecursionDepth|MaxRecursionDepth]] || Gets or sets how deeply nested a dice expression can get.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxRerolls|MaxRerolls]] || Gets or sets the maximum number of times a single die may be rerolled.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxSides|MaxSides]] || Gets or sets the maximum number of sides a single die may have.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/NormalSidesOnly|NormalSidesOnly]] || Gets or sets whether dice expressions are limited to rolling dice with a &amp;quot;normal&amp;quot; number of sides, or if they can roll dice of any number of sides.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/RollDie|RollDie]] || Gets or sets the function used to generate results when a die is rolled.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
The default values for RollerConfig are as follows. These values are set upon constructing the object, however they can be overridden by passing in different values when creating the object (see Examples below for details).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
FunctionRegistry = new FunctionRegistry();&lt;br /&gt;
FunctionRegistry.RegisterType(typeof(BuiltinFunctions));&lt;br /&gt;
MacroRegistry = new MacroRegistry();&lt;br /&gt;
MacroRegistry.RegisterType(typeof(BuiltinMacros));&lt;br /&gt;
RollDie = null; // null makes the default implementation generate random numbers (using GetRandomBytes below) to roll dice&lt;br /&gt;
GetRandomBytes = null; // null makes use of System.Cryptography.RNGCryptoServiceProvider to generate random numbers&lt;br /&gt;
MaxDice = 1000;&lt;br /&gt;
MaxRecursionDepth = 20;&lt;br /&gt;
MaxRerolls = 100;&lt;br /&gt;
MaxSides = 10000;&lt;br /&gt;
NormalSidesOnly = false;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Thread Safety ==&lt;br /&gt;
Reading values from RollerConfig is thread safe. Writing values or manipulating the FunctionRegistry or MacroRegistry is not thread-safe. Internal functions do not write to RollerConfig. The default implementation of GetRandomBytes is thread-safe; passing your own version here may or may not be thread-safe.&lt;br /&gt;
&lt;br /&gt;
If full thread-safety is desired for RollerConfig, please open an issue on GitHub explaining your use-case.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
The following is an example of creating a custom RollerConfig which leaves most values at their default but customizes some others.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
using Dice;&lt;br /&gt;
&lt;br /&gt;
class Sample&lt;br /&gt;
{&lt;br /&gt;
    public static void Main()&lt;br /&gt;
    {&lt;br /&gt;
        var config = new RollerConfig()&lt;br /&gt;
        {&lt;br /&gt;
            MaxDice = 200&lt;br /&gt;
        };&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=966</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=966"/>
		<updated>2018-12-23T17:58:10Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* 4.0.0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** Nested rolls are fully resolved in {{l|Dice.RollResult.ToString|RollResult.ToString()}}. For example, instead of ToString() reporting {{c|&amp;quot;(1d8)d6&amp;quot;}}, it will now report the value rolled for the d8, e.g. {{c|&amp;quot;3d6&amp;quot;}}.&lt;br /&gt;
** {{l|Dice.RollerConfig.ExecuteMacro|RollerConfig.ExecuteMacro}} was removed.&lt;br /&gt;
* New features:&lt;br /&gt;
** DiceRoller is now packaged for both .NET Standard 2.0 as well as .NET Framework 4.5.2. .NET Standard 2.0 supports .NET Framework 4.6.1+ and .NET Core 2.0.&lt;br /&gt;
** Success/failure rolls can now be decorated with critical/fumbles. A critical success (a roll that is both a critical and a success) is worth 2 successes, and a critical failure (a roll that is both a fumble and a failure) is worth -2 successes. This expands support into game systems which use success-based rolls but have varying degrees of success beyond just +1 or -1.&lt;br /&gt;
*** Unless a success/failure roll is explicitly decorated with a critical/fumble, those rolls will not be marked as criticals or fumbles even if the max or min amount is rolled. This keeps default behavior with such rolls consistent with how they worked previously.&lt;br /&gt;
** A new [[Dice Reference#numdice|{{c|[numDice]}}]] macro was added, which returns the total number of dice rolled up to this point. This macro is available in all scenarios, including the stand-alone {{l|Dice.Roller.Roll|Roller.Roll}}; using the Play-by-Post helper is not required to use this macro.&lt;br /&gt;
** A new property {{l|Dice.RollerConfig.RollDie|RollerConfig.RollDie}} was added to allow customizing the result of a die roll in a more friendly way. This property is a callback which receives the minimum and maximum value it can roll for a die, and should return a number within that range. By default, it will call {{l|Dice.RollerConfig.GetRandomBytes|RollerConfig.GetRandomBytes}} repeatedly until it gets a result it can transform into the output range without introducing any bias.&lt;br /&gt;
** New APIs {{l|Dice.Roller.Max|Roller.Max()}}, {{l|Dice.Roller.Min|Roller.Min()}}, and {{l|Dice.Roller.Average|Roller.Average()}} evaluate the dice expression and return the result as if all dice rolled their minimum, maximum, or average values.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** It is now possible to put an expression in parenthesis (a &amp;quot;nested roll&amp;quot;) everywhere a number is expected. Previously, comparisons incorrectly rejected nested rolls.&lt;br /&gt;
* Dependency updates:&lt;br /&gt;
** Updated Antlr4.Runtime.Standard from 4.7.1 to 4.7.2&lt;br /&gt;
** Updated System.ValueTuple from 4.4.0 to 4.5.0&lt;br /&gt;
* Other:&lt;br /&gt;
** The nuget package is now digitally signed with the certificate fingerprint {{c|a87d3b543d551ccd330c23b31b653835a86569bc}}. The same certificate is used to sign the .dll itself in addition to the package.&lt;br /&gt;
&lt;br /&gt;
== 3.1.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** Global functions can now show up inside math expressions without needing to wrap them in parenthesis. For example, {{c|-max(1, 2)+6}} will return 4. They still cannot show up inside of a roll expression without additional parenthesis.&lt;br /&gt;
** New API {{l|Dice.PbP.RollPost.HasDivergedFrom|RollPost.HasDivergedFrom()}} to test whether two RollPosts have Diverged. (Two RollPosts diverge when one is not a prefix of the other)&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=965</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=965"/>
		<updated>2018-12-23T17:54:31Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* 4.0.0 */ update&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** Nested rolls are fully resolved in {{l|Dice.RollResult.ToString|RollResult.ToString()}}. For example, instead of ToString() reporting {{c|&amp;quot;(1d8)d6&amp;quot;}}, it will now report the value rolled for the d8, e.g. {{c|&amp;quot;3d6&amp;quot;}}.&lt;br /&gt;
** {{l|Dice.RollerConfig.ExecuteMacro|RollerConfig.ExecuteMacro}} was removed.&lt;br /&gt;
* New features:&lt;br /&gt;
** DiceRoller is now packaged for both .NET Standard 2.0 as well as .NET Framework 4.5.2. .NET Standard 2.0 supports .NET Framework 4.6.1+ and .NET Core 2.0.&lt;br /&gt;
** Success/failure rolls can now be decorated with critical/fumbles. A critical success (a roll that is both a critical and a success) is worth 2 successes, and a critical failure (a roll that is both a fumble and a failure) is worth -2 successes. This expands support into game systems which use success-based rolls but have varying degrees of success beyond just +1 or -1.&lt;br /&gt;
*** Unless a success/failure roll is explicitly decorated with a critical/fumble, those rolls will not be marked as criticals or fumbles even if the max or min amount is rolled. This keeps default behavior with such rolls consistent with how they worked previously.&lt;br /&gt;
** A new [[Dice Reference#numdice|{{c|[numDice]}}]] macro was added, which returns the total number of dice rolled up to this point. This macro is available in all scenarios, including the stand-alone {{l|Dice.Roller.Roll|Roller.Roll}}; using the Play-by-Post helper is not required to use this macro.&lt;br /&gt;
** A new property {{l|Dice.RollerConfig.RollDie|RollerConfig.RollDie}} was added to allow customizing the result of a die roll in a more friendly way. This property is a callback which receives the minimum and maximum value it can roll for a die, and should return a number within that range. By default, it will call {{l|Dice.RollerConfig.GetRandomBytes|RollerConfig.GetRandomBytes}} repeatedly until it gets a result it can transform into the output range without introducing any bias.&lt;br /&gt;
** New APIs {{l|Dice.Roller.Max|Roller.Max()}}, {{l|Dice.Roller.Min|Roller.Min()}}, and {{l|Dice.Roller.Average|Roller.Average()}} evaluate the dice expression and return the result as if all dice rolled their minimum, maximum, or average values.&lt;br /&gt;
* Dependency updates:&lt;br /&gt;
** Updated Antlr4.Runtime.Standard from 4.7.1 to 4.7.2&lt;br /&gt;
** Updated System.ValueTuple from 4.4.0 to 4.5.0&lt;br /&gt;
* Other:&lt;br /&gt;
** The nuget package is now digitally signed with the certificate fingerprint {{c|a87d3b543d551ccd330c23b31b653835a86569bc}}. The same certificate is used to sign the .dll itself in addition to the package.&lt;br /&gt;
&lt;br /&gt;
== 3.1.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** Global functions can now show up inside math expressions without needing to wrap them in parenthesis. For example, {{c|-max(1, 2)+6}} will return 4. They still cannot show up inside of a roll expression without additional parenthesis.&lt;br /&gt;
** New API {{l|Dice.PbP.RollPost.HasDivergedFrom|RollPost.HasDivergedFrom()}} to test whether two RollPosts have Diverged. (Two RollPosts diverge when one is not a prefix of the other)&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig/RollDie&amp;diff=964</id>
		<title>Dice/RollerConfig/RollDie</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig/RollDie&amp;diff=964"/>
		<updated>2018-12-23T17:50:33Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|RollerConfig.RollDie Property}}&lt;br /&gt;
Gets or sets the function used to generate results when a die is rolled.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public Func&amp;lt;int, int, int&amp;gt; RollDie { get; set; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Property Value ===&lt;br /&gt;
Type: System.Func&amp;lt;System.Int32, System.Int32, System.Int32&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The callback delegate that is used to populate die rolls.&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
The delegate should take in the minimum and maximum amount to be rolled (both inclusive) and return an integer within that range.&lt;br /&gt;
&lt;br /&gt;
If {{cs|null}}, the default implementation will call {{l|Dice.RollerConfig.GetRandomBytes|GetRandomBytes}} repeatedly until a non-biased answer is given, and use that as the result.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
The following example causes all dice to roll their maximum result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Dice;&lt;br /&gt;
&lt;br /&gt;
class Sample&lt;br /&gt;
{&lt;br /&gt;
    public static void Main()&lt;br /&gt;
    {&lt;br /&gt;
        Roller.DefaultConfig.RollDie = RollDie;&lt;br /&gt;
        var result = Roller.Roll(&amp;quot;2d20&amp;quot;);&lt;br /&gt;
        Console.WriteLine(result.Value); // writes 40&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public static int RollDie(int min, int max)&lt;br /&gt;
    {&lt;br /&gt;
        return max;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig/RollDie&amp;diff=963</id>
		<title>Dice/RollerConfig/RollDie</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig/RollDie&amp;diff=963"/>
		<updated>2018-12-23T17:50:16Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: Created page with &amp;quot;{{APIdoc|RollerConfig.RollDie Property}} Gets or sets the function used to generate results when a die is rolled.  {{ns}}  == Syntax == &amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt; public Func...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|RollerConfig.RollDie Property}}&lt;br /&gt;
Gets or sets the function used to generate results when a die is rolled.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public Func&amp;lt;int, int, int&amp;gt; RollDie { get; set; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Property Value ===&lt;br /&gt;
Type: System.Func&amp;lt;System.Int32, System.Int32, System.Int32&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The callback delegate that is used to populate die rolls.&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
The delegate should take in the minimum and maximum amount to be rolled (both inclusive) and return an integer within that range.&lt;br /&gt;
&lt;br /&gt;
If {{cs|null}}, the default implementation will call {{l|Dice.RollerConfig.GetRandomBytes|GetRandomBytes}} repeatedly until a non-biased answer is given, and use that as the result.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
The following example causes all dice to their maximum result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Dice;&lt;br /&gt;
&lt;br /&gt;
class Sample&lt;br /&gt;
{&lt;br /&gt;
    public static void Main()&lt;br /&gt;
    {&lt;br /&gt;
        Roller.DefaultConfig.RollDie = RollDie;&lt;br /&gt;
        var result = Roller.Roll(&amp;quot;2d20&amp;quot;);&lt;br /&gt;
        Console.WriteLine(result.Value); // writes 40&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public static int RollDie(int min, int max)&lt;br /&gt;
    {&lt;br /&gt;
        return max;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig&amp;diff=962</id>
		<title>Dice/RollerConfig</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig&amp;diff=962"/>
		<updated>2018-12-23T17:45:11Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* Remarks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|RollerConfig Class}}&lt;br /&gt;
Stores various configuration related to the dice roller.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Inheritance Hierarchy ==&lt;br /&gt;
System.Object&lt;br /&gt;
:Dice.RollerConfig&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public class RollerConfig&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Constructors ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{method}} || [[Dice/RollerConfig/RollerConfig|RollerConfig()]] || Constructs a new RollerConfig instance with default values.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/FunctionRegistry|FunctionRegistry]] || Gets or sets the registry of all valid function names and their callbacks.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[/MacroRegistry|MacroRegistry]] || Gets or sets the registry of all valid macro names and their callbacks.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/GetRandomBytes|GetRandomBytes]] || Gets or sets the function used to generate random numbers.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxDice|MaxDice]] || Gets or sets the maximum number of dice that may be rolled.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxRecursionDepth|MaxRecursionDepth]] || Gets or sets how deeply nested a dice expression can get.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxRerolls|MaxRerolls]] || Gets or sets the maximum number of times a single die may be rerolled.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxSides|MaxSides]] || Gets or sets the maximum number of sides a single die may have.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/NormalSidesOnly|NormalSidesOnly]] || Gets or sets whether dice expressions are limited to rolling dice with a &amp;quot;normal&amp;quot; number of sides, or if they can roll dice of any number of sides.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/RollDie|RollDie]] || Gets or sets the function used to generate results when a die is rolled.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
The default values for RollerConfig are as follows. These values are set upon constructing the object, however they can be overridden by passing in different values when creating the object (see Examples below for details).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
FunctionRegistry = new FunctionRegistry();&lt;br /&gt;
FunctionRegistry.RegisterType(typeof(BuiltinFunctions));&lt;br /&gt;
MacroRegistry = new MacroRegistry();&lt;br /&gt;
RollDie = null; // null makes the default implementation generate random numbers (using GetRandomBytes below) to roll dice&lt;br /&gt;
GetRandomBytes = null; // null makes use of System.Cryptography.RNGCryptoServiceProvider to generate random numbers&lt;br /&gt;
MaxDice = 1000;&lt;br /&gt;
MaxRecursionDepth = 20;&lt;br /&gt;
MaxRerolls = 100;&lt;br /&gt;
MaxSides = 10000;&lt;br /&gt;
NormalSidesOnly = false;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Thread Safety ==&lt;br /&gt;
Reading values from RollerConfig is thread safe. Writing values or manipulating the FunctionRegistry or MacroRegistry is not thread-safe. Internal functions do not write to RollerConfig. The default implementation of GetRandomBytes is thread-safe; passing your own version here may or may not be thread-safe.&lt;br /&gt;
&lt;br /&gt;
If full thread-safety is desired for RollerConfig, please open an issue on GitHub explaining your use-case.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
The following is an example of creating a custom RollerConfig which leaves most values at their default but customizes some others.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
using Dice;&lt;br /&gt;
&lt;br /&gt;
class Sample&lt;br /&gt;
{&lt;br /&gt;
    public static void Main()&lt;br /&gt;
    {&lt;br /&gt;
        var config = new RollerConfig()&lt;br /&gt;
        {&lt;br /&gt;
            MaxDice = 200&lt;br /&gt;
        };&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig&amp;diff=961</id>
		<title>Dice/RollerConfig</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig&amp;diff=961"/>
		<updated>2018-12-23T17:44:27Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* Properties */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|RollerConfig Class}}&lt;br /&gt;
Stores various configuration related to the dice roller.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Inheritance Hierarchy ==&lt;br /&gt;
System.Object&lt;br /&gt;
:Dice.RollerConfig&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public class RollerConfig&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Constructors ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{method}} || [[Dice/RollerConfig/RollerConfig|RollerConfig()]] || Constructs a new RollerConfig instance with default values.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/FunctionRegistry|FunctionRegistry]] || Gets or sets the registry of all valid function names and their callbacks.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[/MacroRegistry|MacroRegistry]] || Gets or sets the registry of all valid macro names and their callbacks.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/GetRandomBytes|GetRandomBytes]] || Gets or sets the function used to generate random numbers.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxDice|MaxDice]] || Gets or sets the maximum number of dice that may be rolled.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxRecursionDepth|MaxRecursionDepth]] || Gets or sets how deeply nested a dice expression can get.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxRerolls|MaxRerolls]] || Gets or sets the maximum number of times a single die may be rerolled.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxSides|MaxSides]] || Gets or sets the maximum number of sides a single die may have.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/NormalSidesOnly|NormalSidesOnly]] || Gets or sets whether dice expressions are limited to rolling dice with a &amp;quot;normal&amp;quot; number of sides, or if they can roll dice of any number of sides.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/RollDie|RollDie]] || Gets or sets the function used to generate results when a die is rolled.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
The default values for RollerConfig are as follows. These values are set upon constructing the object, however they can be overridden by passing in different values when creating the object (see Examples below for details).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
FunctionRegistry = new FunctionRegistry();&lt;br /&gt;
FunctionRegistry.RegisterType(typeof(BuiltinFunctions));&lt;br /&gt;
MacroRegistry = new MacroRegistry();&lt;br /&gt;
GetRandomBytes = null; // null makes use of System.Cryptography.RNGCryptoServiceProvider to generate random numbers&lt;br /&gt;
MaxDice = 1000;&lt;br /&gt;
MaxRecursionDepth = 20;&lt;br /&gt;
MaxRerolls = 100;&lt;br /&gt;
MaxSides = 10000;&lt;br /&gt;
NormalSidesOnly = false;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Thread Safety ==&lt;br /&gt;
Reading values from RollerConfig is thread safe. Writing values or manipulating the FunctionRegistry or MacroRegistry is not thread-safe. Internal functions do not write to RollerConfig. The default implementation of GetRandomBytes is thread-safe; passing your own version here may or may not be thread-safe.&lt;br /&gt;
&lt;br /&gt;
If full thread-safety is desired for RollerConfig, please open an issue on GitHub explaining your use-case.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
The following is an example of creating a custom RollerConfig which leaves most values at their default but customizes some others.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
using Dice;&lt;br /&gt;
&lt;br /&gt;
class Sample&lt;br /&gt;
{&lt;br /&gt;
    public static void Main()&lt;br /&gt;
    {&lt;br /&gt;
        var config = new RollerConfig()&lt;br /&gt;
        {&lt;br /&gt;
            MaxDice = 200&lt;br /&gt;
        };&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=DiceRoller&amp;diff=960</id>
		<title>DiceRoller</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=DiceRoller&amp;diff=960"/>
		<updated>2018-12-23T05:08:35Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: strip version mention&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DiceRoller is a library for .NET which enables rolling dice. It supports a robust syntax with lots of features, as well as customization to add additional features beyond what is offered in the library itself in the form of custom functions and macros.&lt;br /&gt;
&lt;br /&gt;
If you're curious on how to format dice expressions with the library, check out the [[Dice Reference]].&lt;br /&gt;
&lt;br /&gt;
If you are a developer and want to use this library in your own project, grab the [https://www.nuget.org/packages/DiceRoller/ DiceRoller package] from NuGet via {{c|Install-Package DiceRoller}} and then see the [[API]] documentation (or check the [[Dice]] namespace reference as a starting point). You can also grab the source code from [https://github.com/skizzerz/DiceRoller GitHub].&lt;br /&gt;
&lt;br /&gt;
For version history, check the [[Changelog]].&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/AST/DiceAST/ToString&amp;diff=959</id>
		<title>Dice/AST/DiceAST/ToString</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/AST/DiceAST/ToString&amp;diff=959"/>
		<updated>2018-12-23T05:04:23Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* Remarks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|DiceAST.ToString Method ()}}&lt;br /&gt;
Retrieves a normalized representation of the dice expression.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public abstract override string ToString()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Return Value ===&lt;br /&gt;
Type: System.String&lt;br /&gt;
&lt;br /&gt;
Normalized representation of the dice expression. This may differ from the exact string that was typed in by the user.&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
The normalized representation of the expression represents all extras in their function form, and re-orders functions so that they go left-to-right in the order of their FunctionTiming. Casing is additionally normalized to the function casing used when registering the function. If there are nested rolls, these are fully evaluated and their results placed into the appropriate spot.&lt;br /&gt;
&lt;br /&gt;
For example, if {{c|a()}} was registered as a roll function with FunctionTiming.First and {{c|b()}} and {{c|c()}} were both registered with FunctionTiming.Last, the dice expression {{c|1d20rr&amp;lt;2rr&amp;gt;19.c().a().b()}} would have the following string value: {{c|1d20.a().reroll(&amp;lt;2, &amp;gt;19).c().b()}}.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig&amp;diff=958</id>
		<title>Dice/RollerConfig</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig&amp;diff=958"/>
		<updated>2018-12-23T05:03:06Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: rm ExecuteMacro, no longer exists&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|RollerConfig Class}}&lt;br /&gt;
Stores various configuration related to the dice roller.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Inheritance Hierarchy ==&lt;br /&gt;
System.Object&lt;br /&gt;
:Dice.RollerConfig&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public class RollerConfig&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Constructors ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{method}} || [[Dice/RollerConfig/RollerConfig|RollerConfig()]] || Constructs a new RollerConfig instance with default values.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/FunctionRegistry|FunctionRegistry]] || Gets or sets the registry of all valid function names and their callbacks.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[/MacroRegistry|MacroRegistry]] || Gets or sets the registry of all valid macro names and their callbacks.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/GetRandomBytes|GetRandomBytes]] || Gets or sets the function used to generate random numbers.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxDice|MaxDice]] || Gets or sets the maximum number of dice that may be rolled.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxRecursionDepth|MaxRecursionDepth]] || Gets or sets how deeply nested a dice expression can get.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxRerolls|MaxRerolls]] || Gets or sets the maximum number of times a single die may be rerolled.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/MaxSides|MaxSides]] || Gets or sets the maximum number of sides a single die may have.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[Dice/RollerConfig/NormalSidesOnly|NormalSidesOnly]] || Gets or sets whether dice expressions are limited to rolling dice with a &amp;quot;normal&amp;quot; number of sides, or if they can roll dice of any number of sides.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
The default values for RollerConfig are as follows. These values are set upon constructing the object, however they can be overridden by passing in different values when creating the object (see Examples below for details).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
FunctionRegistry = new FunctionRegistry();&lt;br /&gt;
FunctionRegistry.RegisterType(typeof(BuiltinFunctions));&lt;br /&gt;
MacroRegistry = new MacroRegistry();&lt;br /&gt;
GetRandomBytes = null; // null makes use of System.Cryptography.RNGCryptoServiceProvider to generate random numbers&lt;br /&gt;
MaxDice = 1000;&lt;br /&gt;
MaxRecursionDepth = 20;&lt;br /&gt;
MaxRerolls = 100;&lt;br /&gt;
MaxSides = 10000;&lt;br /&gt;
NormalSidesOnly = false;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Thread Safety ==&lt;br /&gt;
Reading values from RollerConfig is thread safe. Writing values or manipulating the FunctionRegistry or MacroRegistry is not thread-safe. Internal functions do not write to RollerConfig. The default implementation of GetRandomBytes is thread-safe; passing your own version here may or may not be thread-safe.&lt;br /&gt;
&lt;br /&gt;
If full thread-safety is desired for RollerConfig, please open an issue on GitHub explaining your use-case.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
The following is an example of creating a custom RollerConfig which leaves most values at their default but customizes some others.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
using Dice;&lt;br /&gt;
&lt;br /&gt;
class Sample&lt;br /&gt;
{&lt;br /&gt;
    public static void Main()&lt;br /&gt;
    {&lt;br /&gt;
        var config = new RollerConfig()&lt;br /&gt;
        {&lt;br /&gt;
            MaxDice = 200&lt;br /&gt;
        };&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig/ExecuteMacro&amp;diff=957</id>
		<title>Dice/RollerConfig/ExecuteMacro</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/RollerConfig/ExecuteMacro&amp;diff=957"/>
		<updated>2018-12-23T05:02:40Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|RollerConfig.ExecuteMacro Property}}&lt;br /&gt;
Gets or sets the function used to execute macros.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Deprecated ==&lt;br /&gt;
{{deprecated}} This API was marked deprecated in version 3.0.0 and removed in version 4.0.0. See [[../MacroRegistry|MacroRegistry]] for an alternative.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
[Obsolete]&lt;br /&gt;
public MacroCallback ExecuteMacro { get; set; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Property Value ===&lt;br /&gt;
Type: [[Dice/MacroCallback|Dice.MacroCallback]]&lt;br /&gt;
&lt;br /&gt;
The callback delegate which is executed whenever a macro is encountered in the dice expression.&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
If ExecuteMacro is not {{cs|null}}, the callbacks will be called for '''every''' macro executed. As the MacroCallback type is a delegate, multiple callback functions can be registered, and all of them will be invoked in sequence when a macro is encountered. Use [[../MacroRegistry|MacroRegistry]] to tie macro callbacks to specific names. Calling {{l|MacroRegistry.RegisterGlobalMacro}} modifies this property.&lt;br /&gt;
&lt;br /&gt;
The callback should modify the Value of the passed-in [[Dice/MacroContext|MacroContext]] to indicate that the macro was run successfully. If the Value field is not modified by any callback, a DiceException will be thrown with ErrorCode DiceErrorCode.InvalidMacro.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
The following example registers two callbacks to handle macro executions.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
using Dice;&lt;br /&gt;
&lt;br /&gt;
class Sample&lt;br /&gt;
{&lt;br /&gt;
    public static void Main()&lt;br /&gt;
    {&lt;br /&gt;
        Roller.DefaultConfig.ExecuteMacro += MacroCallback1;&lt;br /&gt;
        Roller.DefaultConfig.ExecuteMacro += MacroCallback2;&lt;br /&gt;
        var result1 = Roller.Roll(&amp;quot;1d20+[WIS-mod]&amp;quot;); // rolls 1d20+2&lt;br /&gt;
        var result2 = Roller.Roll(&amp;quot;1d20+[proficiency]&amp;quot;); // throws DiceException with DiceErrorCode.InvalidMacro&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public static void MacroCallback1(MacroContext context)&lt;br /&gt;
    {&lt;br /&gt;
        switch (context.Param)&lt;br /&gt;
        {&lt;br /&gt;
            case &amp;quot;STR-mod&amp;quot;:&lt;br /&gt;
                context.Value = 0;&lt;br /&gt;
                break;&lt;br /&gt;
            case &amp;quot;DEX-mod&amp;quot;:&lt;br /&gt;
                context.Value = 3;&lt;br /&gt;
                break;&lt;br /&gt;
            case &amp;quot;CON-mod&amp;quot;:&lt;br /&gt;
                context.Value = -1;&lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public static void MacroCallback2(MacroContext context)&lt;br /&gt;
    {&lt;br /&gt;
        switch (context.Param)&lt;br /&gt;
        {&lt;br /&gt;
            case &amp;quot;INT-mod&amp;quot;:&lt;br /&gt;
                context.Value = -1;&lt;br /&gt;
                break;&lt;br /&gt;
            case &amp;quot;WIS-mod&amp;quot;:&lt;br /&gt;
                context.Value = 2;&lt;br /&gt;
                break;&lt;br /&gt;
            case &amp;quot;CHA-mod&amp;quot;:&lt;br /&gt;
                context.Value = 0;&lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=956</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=956"/>
		<updated>2018-12-23T05:02:06Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 4.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** Nested rolls are fully resolved in {{l|Dice.RollResult.ToString|RollResult.ToString()}}. For example, instead of ToString() reporting {{c|&amp;quot;(1d8)d6&amp;quot;}}, it will now report the value rolled for the d8, e.g. {{c|&amp;quot;3d6&amp;quot;}}.&lt;br /&gt;
** {{l|Dice.RollerConfig.ExecuteMacro|RollerConfig.ExecuteMacro}} was removed.&lt;br /&gt;
* New features:&lt;br /&gt;
** DiceRoller is now packaged for both .NET Standard 2.0 as well as .NET Framework 4.5.2. .NET Standard 2.0 supports .NET Framework 4.6.1+ and .NET Core 2.0.&lt;br /&gt;
** Success/failure rolls can now be decorated with critical/fumbles. A critical success (a roll that is both a critical and a success) is worth 2 successes, and a critical failure (a roll that is both a fumble and a failure) is worth -2 successes. This expands support into game systems which use success-based rolls but have varying degrees of success beyond just +1 or -1.&lt;br /&gt;
*** Unless a success/failure roll is explicitly decorated with a critical/fumble, those rolls will not be marked as criticals or fumbles even if the max or min amount is rolled. This keeps default behavior with such rolls consistent with how they worked previously.&lt;br /&gt;
** A new [[Dice Reference#numdice|{{c|[numDice]}}]] macro was added, which returns the total number of dice rolled up to this point.&lt;br /&gt;
** New APIs {{l|Dice.Roller.Max|Roller.Max()}}, {{l|Dice.Roller.Min|Roller.Min()}}, and {{l|Dice.Roller.Average|Roller.Average()}} evaluate the dice expression and return the maximum, minimum, or average result.&lt;br /&gt;
* Dependency updates:&lt;br /&gt;
** Updated Antlr4.Runtime.Standard from 4.7.1 to 4.7.2&lt;br /&gt;
** Updated System.ValueTuple from 4.4.0 to 4.5.0&lt;br /&gt;
* Other:&lt;br /&gt;
** The nuget package is now digitally signed with the certificate fingerprint {{c|a87d3b543d551ccd330c23b31b653835a86569bc}}. The same certificate is used to sign the .dll itself in addition to the package.&lt;br /&gt;
&lt;br /&gt;
== 3.1.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** Global functions can now show up inside math expressions without needing to wrap them in parenthesis. For example, {{c|-max(1, 2)+6}} will return 4. They still cannot show up inside of a roll expression without additional parenthesis.&lt;br /&gt;
** New API {{l|Dice.PbP.RollPost.HasDivergedFrom|RollPost.HasDivergedFrom()}} to test whether two RollPosts have Diverged. (Two RollPosts diverge when one is not a prefix of the other)&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=955</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=955"/>
		<updated>2018-12-23T01:54:19Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** DiceRoller is now packaged for both .NET Standard 2.0 as well as .NET Framework 4.5.2. .NET Standard 2.0 supports .NET Framework 4.6.1+ and .NET Core 2.0.&lt;br /&gt;
** Success/failure rolls can now be decorated with critical/fumbles. A critical success (a roll that is both a critical and a success) is worth 2 successes, and a critical failure (a roll that is both a fumble and a failure) is worth -2 successes. This expands support into game systems which use success-based rolls but have varying degrees of success beyond just +1 or -1.&lt;br /&gt;
*** Unless a success/failure roll is explicitly decorated with a critical/fumble, those rolls will not be marked as criticals or fumbles even if the max or min amount is rolled. This keeps default behavior with such rolls consistent with how they worked previously.&lt;br /&gt;
** A new [[Dice Reference#numdice|{{c|[numDice]}}]] macro was added, which returns the total number of dice rolled up to this point.&lt;br /&gt;
** New APIs {{l|Dice.Roller.Max|Roller.Max()}}, {{l|Dice.Roller.Min|Roller.Min()}}, and {{l|Dice.Roller.Average|Roller.Average()}} evaluate the dice expression and return the maximum, minimum, or average result.&lt;br /&gt;
* Dependency updates:&lt;br /&gt;
** Updated Antlr4.Runtime.Standard from 4.7.1 to 4.7.2&lt;br /&gt;
** Updated System.ValueTuple from 4.4.0 to 4.5.0&lt;br /&gt;
* Other:&lt;br /&gt;
** The nuget package is now digitally signed with the certificate fingerprint {{c|a87d3b543d551ccd330c23b31b653835a86569bc}}. The same certificate is used to sign the .dll itself in addition to the package.&lt;br /&gt;
&lt;br /&gt;
== 3.1.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** Global functions can now show up inside math expressions without needing to wrap them in parenthesis. For example, {{c|-max(1, 2)+6}} will return 4. They still cannot show up inside of a roll expression without additional parenthesis.&lt;br /&gt;
** New API {{l|Dice.PbP.RollPost.HasDivergedFrom|RollPost.HasDivergedFrom()}} to test whether two RollPosts have Diverged. (Two RollPosts diverge when one is not a prefix of the other)&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=954</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=954"/>
		<updated>2018-03-26T16:56:51Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* 3.2.0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** DiceRoller is now packaged for both .NET Standard 2.0 as well as .NET Framework 4.5.2. .NET Standard 2.0 supports .NET Framework 4.6.1+ and .NET Core 2.0.&lt;br /&gt;
** Success/failure rolls can now be decorated with critical/fumbles. A critical success (a roll that is both a critical and a success) is worth 2 successes, and a critical failure (a roll that is both a fumble and a failure) is worth -2 successes. This expands support into game systems which use success-based rolls but have varying degrees of success beyond just +1 or -1.&lt;br /&gt;
*** Unless a success/failure roll is explicitly decorated with a critical/fumble, those rolls will not be marked as criticals or fumbles even if the max or min amount is rolled. This keeps default behavior with such rolls consistent with how they worked previously.&lt;br /&gt;
** A new [[Dice Reference#numdice|{{c|[numDice]}}]] macro was added, which returns the total number of dice rolled up to this point.&lt;br /&gt;
** New APIs {{l|Dice.Roller.Max|Roller.Max()}}, {{l|Dice.Roller.Min|Roller.Min()}}, and {{l|Dice.Roller.Average|Roller.Average()}} evaluate the dice expression and return the maximum, minimum, or average result.&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.1 to 4.7.1.1&lt;br /&gt;
&lt;br /&gt;
== 3.1.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** Global functions can now show up inside math expressions without needing to wrap them in parenthesis. For example, {{c|-max(1, 2)+6}} will return 4. They still cannot show up inside of a roll expression without additional parenthesis.&lt;br /&gt;
** New API {{l|Dice.PbP.RollPost.HasDivergedFrom|RollPost.HasDivergedFrom()}} to test whether two RollPosts have Diverged. (Two RollPosts diverge when one is not a prefix of the other)&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=953</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=953"/>
		<updated>2018-03-23T20:41:03Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** DiceRoller is now packaged for both .NET Standard 2.0 as well as .NET Framework 4.5.2. .NET Standard 2.0 supports .NET Framework 4.6.1+ and .NET Core 2.0.&lt;br /&gt;
** Success/failure rolls can now be decorated with critical/fumbles. A critical success (a roll that is both a critical and a success) is worth 2 successes, and a critical failure (a roll that is both a fumble and a failure) is worth -2 successes. This expands support into game systems which use success-based rolls but have varying degrees of success beyond just +1 or -1.&lt;br /&gt;
*** Unless a success/failure roll is explicitly decorated with a critical/fumble, those rolls will not be marked as criticals or fumbles even if the max or min amount is rolled. This keeps default behavior with such rolls consistent with how they worked previously.&lt;br /&gt;
** A new [[Dice Reference#numdice|{{c|[numDice]}}]] macro was added, which returns the total number of dice rolled up to this point.&lt;br /&gt;
** A new property {{l|Dice.RollerConfig.RollDie|RollerConfig.RollDie}} was added to allow customizing the result of a die roll in a more friendly way. This property is a callback which receives the minimum and maximum value it can roll for a die, and should return a number within that range. By default, it will call RollerConfig.GetRandomBytes repeatedly until it gets a result it can transform into the output range without introducing any bias.&lt;br /&gt;
** New APIs {{l|Dice.Roller.Max|Roller.Max()}}, {{l|Dice.Roller.Min|Roller.Min()}}, and {{l|Dice.Roller.Average|Roller.Average()}} evaluate the dice expression and return the maximum, minimum, or average result.&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.1 to 4.7.1.1&lt;br /&gt;
&lt;br /&gt;
== 3.1.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** Global functions can now show up inside math expressions without needing to wrap them in parenthesis. For example, {{c|-max(1, 2)+6}} will return 4. They still cannot show up inside of a roll expression without additional parenthesis.&lt;br /&gt;
** New API {{l|Dice.PbP.RollPost.HasDivergedFrom|RollPost.HasDivergedFrom()}} to test whether two RollPosts have Diverged. (Two RollPosts diverge when one is not a prefix of the other)&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=952</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=952"/>
		<updated>2018-03-23T20:29:59Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* 3.2.0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** DiceRoller is now packaged for both .NET Standard 2.0 as well as .NET Framework 4.5.2. .NET Standard 2.0 supports .NET Framework 4.6.1+ and .NET Core 2.0.&lt;br /&gt;
** Success/failure rolls can now be decorated with critical/fumbles. A critical success (a roll that is both a critical and a success) is worth 2 successes, and a critical failure (a roll that is both a fumble and a failure) is worth -2 successes. This expands support into game systems which use success-based rolls but have varying degrees of success beyond just +1 or -1.&lt;br /&gt;
*** Unless a success/failure roll is explicitly decorated with a critical/fumble, those rolls will not be marked as criticals or fumbles even if the max or min amount is rolled. This keeps default behavior with such rolls consistent with how they worked previously.&lt;br /&gt;
** A new [[Dice Reference#numdice|{{c|[numDice]}}]] macro was added, which returns the number of dice rolled in the most recent dice expression before it.&lt;br /&gt;
** A new property {{l|Dice.RollerConfig.RollDie|RollerConfig.RollDie}} was added to allow customizing the result of a die roll in a more friendly way. This property is a callback which receives the minimum and maximum value it can roll for a die, and should return a number within that range. By default, it will call RollerConfig.GetRandomBytes repeatedly until it gets a result it can transform into the output range without introducing any bias.&lt;br /&gt;
** New APIs {{l|Dice.Roller.Max|Roller.Max()}}, {{l|Dice.Roller.Min|Roller.Min()}}, and {{l|Dice.Roller.Average|Roller.Average()}} evaluate the dice expression and return the maximum, minimum, or average result.&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.1 to 4.7.1.1&lt;br /&gt;
&lt;br /&gt;
== 3.1.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** Global functions can now show up inside math expressions without needing to wrap them in parenthesis. For example, {{c|-max(1, 2)+6}} will return 4. They still cannot show up inside of a roll expression without additional parenthesis.&lt;br /&gt;
** New API {{l|Dice.PbP.RollPost.HasDivergedFrom|RollPost.HasDivergedFrom()}} to test whether two RollPosts have Diverged. (Two RollPosts diverge when one is not a prefix of the other)&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=951</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=951"/>
		<updated>2018-03-23T20:27:11Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.2.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** DiceRoller is now packaged for both .NET Standard 2.0 as well as .NET Framework 4.5.2. .NET Standard 2.0 supports .NET Framework 4.6.1+ and .NET Core 2.0.&lt;br /&gt;
** Success/failure rolls can now be decorated with critical/fumbles. A critical success (a roll that is both a critical and a success) is worth 2 successes, and a critical failure (a roll that is both a fumble and a failure) is worth -2 successes. This expands support into game systems which use success-based rolls but have varying degrees of success beyond just +1 or -1.&lt;br /&gt;
*** Unless a success/failure roll is explicitly decorated with a critical/fumble, those rolls will not be marked as criticals or fumbles even if the max or min amount is rolled. This keeps default behavior with such rolls consistent with how they worked previously.&lt;br /&gt;
** A new [[Dice Reference#numdice|{{c|[numDice]}}]] macro was added, which returns the number of dice rolled in the most recent dice expression before it.&lt;br /&gt;
** A new property {{l|Dice.RollerConfig.RollDie|RollerConfig.RollDie}} was added to allow customizing the result of a die roll in a more friendly way. This property is a callback which receives the minimum and maximum value it can roll for a die, and should return a number within that range. By default, it will call RollerConfig.GetRandomBytes repeatedly until it gets a result it can transform into the output range without introducing any bias.&lt;br /&gt;
** New APIs {{l|Dice.Roller.Max|Roller.Max}}, {{l|Dice.Roller.Min|Roller.Min}}, and {{l|Dice.Roller.Average|Roller.Average}} evaluate the dice expression and return the maximum, minimum, or average result.&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.1 to 4.7.1.1&lt;br /&gt;
&lt;br /&gt;
== 3.1.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** Global functions can now show up inside math expressions without needing to wrap them in parenthesis. For example, {{c|-max(1, 2)+6}} will return 4. They still cannot show up inside of a roll expression without additional parenthesis.&lt;br /&gt;
** New API {{l|Dice.PbP.RollPost.HasDivergedFrom|RollPost.HasDivergedFrom()}} to test whether two RollPosts have Diverged. (Two RollPosts diverge when one is not a prefix of the other)&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=DiceRoller&amp;diff=950</id>
		<title>DiceRoller</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=DiceRoller&amp;diff=950"/>
		<updated>2017-10-06T00:53:03Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DiceRoller is a library for .NET 4.5 and above which enables rolling dice. It supports a robust syntax with lots of features, as well as customization to add additional features beyond what is offered in the library itself in the form of custom functions and macros.&lt;br /&gt;
&lt;br /&gt;
If you're curious on how to format dice expressions with the library, check out the [[Dice Reference]].&lt;br /&gt;
&lt;br /&gt;
If you are a developer and want to use this library in your own project, grab the [https://www.nuget.org/packages/DiceRoller/ DiceRoller package] from NuGet via {{c|Install-Package DiceRoller}} and then see the [[API]] documentation (or check the [[Dice]] namespace reference as a starting point). You can also grab the source code from [https://github.com/skizzerz/DiceRoller GitHub].&lt;br /&gt;
&lt;br /&gt;
For version history, check the [[Changelog]].&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/PbP/RollPost/HasDivergedFrom&amp;diff=949</id>
		<title>Dice/PbP/RollPost/HasDivergedFrom</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/PbP/RollPost/HasDivergedFrom&amp;diff=949"/>
		<updated>2017-10-06T00:51:59Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: Created page with &amp;quot;{{APIdoc|RollPost.HasDivergedFrom Method (RollPost)}} Test if two RollPosts have diverged.  {{ns}}  == Syntax == &amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt; public virtual bool HasDivergedFro...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|RollPost.HasDivergedFrom Method (RollPost)}}&lt;br /&gt;
Test if two RollPosts have diverged.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public virtual bool HasDivergedFrom(&lt;br /&gt;
    RollPost other&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
; ''other''&lt;br /&gt;
: Type: {{l|Dice.PbP.RollPost}}&lt;br /&gt;
: RollPost to check against&lt;br /&gt;
&lt;br /&gt;
=== Return Value ===&lt;br /&gt;
Type: System.Boolean&lt;br /&gt;
&lt;br /&gt;
Returns {{cs|true}} if the two RollPosts have diverged and {{cs|false}} if they have not.&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
Much like [[../Validate|Validate]], two RollPosts are considered to be divergent if one is not a prefix of the other. The logic to check this mirrors what is used in Validate, however it does not call Validate. Therefore, classes which extend RollPost should override both Validate and HasDivergedFrom in order to ensure that the logic between the two is consistent.&lt;br /&gt;
&lt;br /&gt;
Unlike Validate, HasDivergedFrom has no side effects.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/PbP/RollPost&amp;diff=948</id>
		<title>Dice/PbP/RollPost</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/PbP/RollPost&amp;diff=948"/>
		<updated>2017-10-06T00:48:25Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|RollPost Class}}&lt;br /&gt;
Contains information about all of the rolls on a post, including basic anti-cheat detection.&lt;br /&gt;
&lt;br /&gt;
{{ns|PbP}}&lt;br /&gt;
&lt;br /&gt;
== Inheritance Hierarchy ==&lt;br /&gt;
System.Object&lt;br /&gt;
:Dice.PbP.RollPost&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
[Serializable]&lt;br /&gt;
public class RollPost : ISerializable, IDeserializationCallback&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Constructors ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{method}} || [[/RollPost ()|RollPost()]] || Constructs a new, empty RollPost.&lt;br /&gt;
|-&lt;br /&gt;
| {{protected}} {{method}} || [[/RollPost (SerializationInfo, StreamingContext)|RollPost(SerializationInfo, StreamingContext)]] || Constructs a new RollPost using serialized data.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{method}} || [[/AddRoll (String)|AddRoll(String)]] || Adds a new roll to the post using the DefaultConfig if the roll needs to be evaluated.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{method}} || [[/AddRoll (String, RollerConfig)|AddRoll(String, RollerConfig)]] || Adds a new roll to the post using the given config if the roll needs to be evaluated.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{static}} {{method}} || [[/Deserialize|Deserialize(Stream)]] || Deserializes a serialized RollPost.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{method}} || [[/GetObjectData|GetObjectData(SerializationInfo, StreamingContext)]] || Serializes a RollPost. This method should not be directly called.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{method}} || [[/HasDivergedFrom|HasDivergedFrom(RollPost)]] || Test if two RollPosts have diverged.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{method}} || [[/OnDeserialization|OnDeserialization(Object)]] || Completes deserialization of the RollPost once the entire object graph has been deserialized. This method should not be directly called.&lt;br /&gt;
|-&lt;br /&gt;
| {{private}} {{method}} || [[/PostMacros|PostMacros(MacroContext)]] || Executes PbP-specific macros, which are documented on in the [[Dice Reference#Play-by-Post Macros|dice reference]].&lt;br /&gt;
|-&lt;br /&gt;
| {{private}} {{method}} || [[/RollMacro|RollMacro(MacroContext, String[])]] || Contains the logic for the {{c|[roll]}} macro.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{method}} || [[/Serialize|Serialize(Stream)]] || Serializes a RollPost, for saving to the database.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{method}} || [[/Validate|Validate()]] || Checks if Current has diverged from Pristine.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Properties ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[/Current|Current]] || Gets the current version of the post (the one being checked).&lt;br /&gt;
|-&lt;br /&gt;
| {{protected}} {{property}} || [[/CurrentList|CurrentList]] || Gets the mutable version of Current.&lt;br /&gt;
|-&lt;br /&gt;
| {{internal}} {{property}} || [[/Diverged|Diverged]] || Gets how diverged Current is from Pristine.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[/Pristine|Pristine]] || Gets the &amp;quot;pristine&amp;quot; version of the post.&lt;br /&gt;
|-&lt;br /&gt;
| {{protected}} {{property}} || [[/PristineList|PristineList]] || Gets the mutable version of Pristine.&lt;br /&gt;
|-&lt;br /&gt;
| {{public}} {{property}} || [[/Stored|Stored]] || Gets the most recent saved version of the post.&lt;br /&gt;
|-&lt;br /&gt;
| {{protected}} {{property}} || [[/StoredList|StoredList]] || Gets the mutable version of Stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Fields ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;width: 5em&amp;quot; |&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| {{private}} {{field}} || [[/_current|_current]] || The current version of the post.&lt;br /&gt;
|-&lt;br /&gt;
| {{private}} {{field}} || [[/_diverged|_diverged]] || How many levels has Current diverged from Pristine at the moment.&lt;br /&gt;
|-&lt;br /&gt;
| {{private}} {{field}} || [[/_pristine|_pristine]] || The pristine version of the post.&lt;br /&gt;
|-&lt;br /&gt;
| {{private}} {{field}} || [[/_stored|_stored]] || The stored version of the post.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
When a new post is made, a new RollPost instance should be constructed and stored along with that post in the database (using the [[/Serialize|Serialize()]] method, it is recommended that a DeflateStream is passed or some other compression stream). The AddPost() method is used to add rolls to the post, and Validate() is used to determine if the post has been modified in a way that indicates cheating. Even if you do not care about the cheating detection, '''Validate() must be called before serializing a RollPost.''' If you do not do this, the Pristine version of the roll will not be updated, which can cause issues down the line for future edits causing expressions to be rerolled instead of taking on their prior values.&lt;br /&gt;
&lt;br /&gt;
When processing an existing post, deserialize the stored RollPost via [[/Deserialize|RollPost.Deserialize()]], then call AddRoll() again for all rolls in the post. RollPost will re-use previously rolled values for those rolls if possible, otherwise it will reroll them. After all rolls have been added via AddRoll(), Validate() should be called to determine whether or not cheating happened and to update some internal state, and then you can iterate over Current to retrieve all of the individual [[Dice/RollResult|RollResults]].&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
The following example simulates creating and saving a new post, and then later loading it to inspect the rolled values.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.IO;&lt;br /&gt;
using System.IO.Compression;&lt;br /&gt;
&lt;br /&gt;
using Dice;&lt;br /&gt;
using Dice.PbP;&lt;br /&gt;
&lt;br /&gt;
class Sample&lt;br /&gt;
{&lt;br /&gt;
    public static void Main()&lt;br /&gt;
    {&lt;br /&gt;
        MemoryStream stream = new MemoryStream();&lt;br /&gt;
&lt;br /&gt;
        // pretend our post had 2 rolls: 1d20+4 and 2d6+3/4d6+6&lt;br /&gt;
        RollPost post = new RollPost();&lt;br /&gt;
        post.AddRoll(&amp;quot;1d20+4&amp;quot;);&lt;br /&gt;
        post.AddRoll(&amp;quot;if([roll:1:critical], &amp;gt;0, 4d6+6, 2d6+3)&amp;quot;);&lt;br /&gt;
        post.Validate(); // must be called every time, including on initial post&lt;br /&gt;
&lt;br /&gt;
        // passing true as 3rd param leaves stream open, otherwise DeflateStream closes it&lt;br /&gt;
        // when disposing. Data is not written to stream until deflate is disposed.&lt;br /&gt;
        using (var deflate = new DeflateStream(stream, CompressionLevel.Optimal, true))&lt;br /&gt;
        {&lt;br /&gt;
            post.Serialize(deflate);&lt;br /&gt;
        }&lt;br /&gt;
        // save contents of stream along with the post to the database...&lt;br /&gt;
        // for this example we just rewind the stream&lt;br /&gt;
        stream.Seek(0, SeekOrigin.Begin);&lt;br /&gt;
&lt;br /&gt;
        // later: retrieve serialized post from database, store it in stream...&lt;br /&gt;
        using (var deflate = new DeflateStream(stream, CompressionMode.Decompress))&lt;br /&gt;
        {&lt;br /&gt;
            post = RollPost.Deserialize(deflate);&lt;br /&gt;
        }&lt;br /&gt;
        // need to re-add the rolls on the current version of the post,&lt;br /&gt;
        // even if they didn't change&lt;br /&gt;
        post.AddRoll(&amp;quot;1d20+4&amp;quot;);&lt;br /&gt;
        post.AddRoll(&amp;quot;if([roll:1:critical], &amp;gt;0, 4d6+6, 2d6+3)&amp;quot;);&lt;br /&gt;
        if (!post.Validate())&lt;br /&gt;
        {&lt;br /&gt;
            // if post.Validate() returns false, this indicates that the rolls were&lt;br /&gt;
            // tampered with. Highlight this somehow on the post (perhaps with a scary&lt;br /&gt;
            // warning sign in the post background).&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // iterate over the results so we can display them&lt;br /&gt;
        foreach (RollResult result in post.Current)&lt;br /&gt;
        {&lt;br /&gt;
            Console.WriteLine(result.ToString());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=947</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=947"/>
		<updated>2017-10-06T00:46:46Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.1.0 ==&lt;br /&gt;
* New features:&lt;br /&gt;
** Global functions can now show up inside math expressions without needing to wrap them in parenthesis. For example, {{c|-max(1, 2)+6}} will return 4. They still cannot show up inside of a roll expression without additional parenthesis.&lt;br /&gt;
** New API {{l|Dice.PbP.RollPost.HasDivergedFrom|RollPost.HasDivergedFrom()}} to test whether two RollPosts have Diverged. (Two RollPosts diverge when one is not a prefix of the other)&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Dice/PbP/RollPost/Serialize&amp;diff=946</id>
		<title>Dice/PbP/RollPost/Serialize</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Dice/PbP/RollPost/Serialize&amp;diff=946"/>
		<updated>2017-10-05T16:59:31Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: /* Remarks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{APIdoc|RollPost.Serialize Method (Stream)}}&lt;br /&gt;
Serializes a RollPost, for saving to the database.&lt;br /&gt;
&lt;br /&gt;
{{ns}}&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C#&amp;quot;&amp;gt;&lt;br /&gt;
public void Serialize(&lt;br /&gt;
    Stream serializationStream&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
; ''serializationStream''&lt;br /&gt;
: Type: System.IO.Stream&lt;br /&gt;
: The stream to write serialized data to.&lt;br /&gt;
&lt;br /&gt;
== Remarks ==&lt;br /&gt;
This method should be used whenever serializing a RollPost for persistent storage. It will serialize Pristine and Stored, but leave Current empty (note that Current is written into Stored when [[../Validate|Validate()]] is called).&lt;br /&gt;
&lt;br /&gt;
As a result of this, Validate() must be called on a RollPost before Serialize is called, or else it will not serialize anything (or will serialize old data).&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
The [[../|RollPost class documentation]] contains an example using Serialize() to store data into a database.&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=945</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=945"/>
		<updated>2017-09-29T18:24:02Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the last set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=944</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=944"/>
		<updated>2017-09-29T18:23:49Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.0.2 ==&lt;br /&gt;
* Updates:&lt;br /&gt;
** Updated ANTLR runtime version from 4.7.0 to 4.7.1&lt;br /&gt;
&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** New installations will now properly install the correction version of dependencies. Before, a fresh install would install System.ValueTuple 4.3.0 when 4.3.1+ was required.&lt;br /&gt;
** The .expand() function on multiplied group rolls, e.g. {{c|2{3d6}.expand()}}, would show the first set of rolled dice each time instead of showing each set.&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
	<entry>
		<id>https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=943</id>
		<title>Changelog</title>
		<link rel="alternate" type="text/html" href="https://skizzerz.net/DiceRoller/index.php?title=Changelog&amp;diff=943"/>
		<updated>2017-09-23T17:59:38Z</updated>

		<summary type="html">&lt;p&gt;Skizzerz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;nonumtoc&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 3.0.1 ==&lt;br /&gt;
* Bug fixes:&lt;br /&gt;
** Using {{l|DieResult}} methods to drop dice, mark as failures/successes, etc. stripped the {{l|DieResult.Data|Data property}}. The Data property is now retained in such cases.&lt;br /&gt;
&lt;br /&gt;
== 3.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** DiceAST subclasses have their RollerConfig parameters swapped with RollData. This change is only breaking if you have implemented custom AST nodes. If you have not implemented custom AST nodes, no code changes need to be made to your project.&lt;br /&gt;
** Grouped rolls now always aggregate their values. In other words, {{c|&amp;lt;nowiki&amp;gt;{4d6}&amp;lt;/nowiki&amp;gt;}} will return a single number such as 20 rather than list all 4 individual die rolls. It is no longer necessary to nest groups in order to accomplish this. If you want all individual dice listed, either do not use a grouped roll, or use the new expand() function.&lt;br /&gt;
&lt;br /&gt;
* New features:&lt;br /&gt;
** {{l|RollerConfig.MacroRegistry}} can be used to associate macro callbacks to specific names instead of registering a global handler.&lt;br /&gt;
** A new &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;[[Dice/DiceMacroAttribute|DiceMacro]]&amp;lt;nowiki&amp;gt;]&amp;lt;/nowiki&amp;gt; attribute is added to be used in conjunction with {{l|MacroRegistry.RegisterType}}.&lt;br /&gt;
** Roller.Roll can now take an optional RollData object as a 3rd parameter. This can be used to add in custom functions or macros only valid for that roll (as opposed to global across multiple rolls as is the case for RollerConfig). Functions or macros defined here with the same name as global ones override the global ones.&lt;br /&gt;
** A Metadata object can be passed as part of RollData and is passed as-is to the RollResult. This allows you to attach additional data to RollResults when serializing them to the database, which can be useful when reconstructing something pulled from the database.&lt;br /&gt;
** A new expand function can be applied to grouped rolls which expands each group result into the individual dice rolled.&lt;br /&gt;
&lt;br /&gt;
* Deprecated:&lt;br /&gt;
** {{l|RollerConfig.ExecuteMacro}} is deprecated and will be removed in a future version. Use RollerConfig.MacroRegistry instead.&lt;br /&gt;
&lt;br /&gt;
== 2.0.2 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Invalid dice expressions are now tracked in RollPost, so that fixing these expressions in an edit does not invalidate rolls that took place afterwards.&lt;br /&gt;
** Turning a previously-rolled result into an invalid expression is now marked as a modified post.&lt;br /&gt;
&lt;br /&gt;
== 2.0.1 ==&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Errors when lexing the dice expression now throw an error instead of being silently ignored.&lt;br /&gt;
&lt;br /&gt;
== 2.0.0 ==&lt;br /&gt;
* Backwards-incompatible changes:&lt;br /&gt;
** RollPost now roundtrips when serializing using default BinaryFormatter (so it is usable in .NET remoting now). A new serialization format has been added (exposed via Serialize and Deserialize convenience methods) for RollPost, RollResult, and DieResult that is meant for persistence. This still uses BinaryFormatter behind the scenes, it is recommended that you compress the output before storing in the database.&lt;br /&gt;
** Unary negations cannot be stacked on a number. Previously an expression {{c|----1}} was valid (and evaluated to positive 1). Now, such an expression is no longer valid. This hides the implementation detail of negation being implemented as an operator rather than part of a number. To get the same result, parenthesis are now needed {{c|-(-(-(-1)))}}. Existing rolls using the old method will now throw parse errors.&lt;br /&gt;
** When evaluating macros, leading/trailing spaces are trimmed, and the Param string is exploded along the colon character as Name and Arguments. A future version will expose the ability to register a macro callback with a specific name, rather than having a handler listen to every macro.&lt;br /&gt;
* Allow subclasses of DiceAST outside of Dice.dll to override [[Dice/AST/DiceAST/UnderlyingRollNode|UnderlyingRollNode]] in preparation for the ability for outside assemblies to extend the parser (planned for a later 2.x version).&lt;br /&gt;
* Additional documentation comments, and fixing some inaccuracies in existing comments.&lt;br /&gt;
* Additional unit tests.&lt;br /&gt;
* Bugfixes:&lt;br /&gt;
** Throw more informational exceptions rather than having an internal detail throw an exception (ArgumentNullException instead of NullReferenceException, InvalidOperationException with a more meaningful error message rather than ArgumentException on Dictionary.Add, etc.).&lt;br /&gt;
** Fix roll macro argument parsing.&lt;br /&gt;
** Expose [[Dice/Grammar/DiceErrorListener|Dice.Grammar.DiceErrorListener]] (was documented as public but not marked as such in the code).&lt;br /&gt;
&lt;br /&gt;
== 1.1.0 ==&lt;br /&gt;
* New Play-by-Post helper class [[Dice/PbP/RollPost|RollPost]], found in the [[Dice/PbP|Dice.PbP]] namespace.&lt;br /&gt;
** Rolls can be serialized and saved to a database (or somewhere else, I don't judge) so that rolls within a post remain fixed between previews/edits.&lt;br /&gt;
** Contains the ability to detect tampering of roll expressions within a post (deleting/modifying rolls). Adding new rolls at the end is ok, everything else causes validation errors.&lt;br /&gt;
** A new {{c|[roll]}} macro which can be used to obtain results of previous rolls in the same post.&lt;br /&gt;
* DieResult and RollResult are now Serializable and Equatable.&lt;br /&gt;
* Group rolls can now be rerolled.&lt;br /&gt;
* New {{c|if()}} global function, which lets you test an expression against a comparison, and return one of two expressions depending on whether or not the comparison succeeded.&lt;br /&gt;
&lt;br /&gt;
== 1.0.0 ==&lt;br /&gt;
* Initial version&lt;/div&gt;</summary>
		<author><name>Skizzerz</name></author>
		
	</entry>
</feed>