{"id":17034148,"url":"https://github.com/lordnull/dice.js","last_synced_at":"2025-10-04T14:40:33.393Z","repository":{"id":8136308,"uuid":"9554397","full_name":"lordnull/dice.js","owner":"lordnull","description":"Generic RPG dice string parser and roller","archived":false,"fork":false,"pushed_at":"2021-12-23T06:59:34.000Z","size":5950,"stargazers_count":30,"open_issues_count":1,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-26T07:36:31.493Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lordnull.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-04-19T20:53:10.000Z","updated_at":"2024-12-24T13:08:52.000Z","dependencies_parsed_at":"2022-08-23T22:40:56.586Z","dependency_job_id":null,"html_url":"https://github.com/lordnull/dice.js","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lordnull%2Fdice.js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lordnull%2Fdice.js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lordnull%2Fdice.js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lordnull%2Fdice.js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lordnull","download_url":"https://codeload.github.com/lordnull/dice.js/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248571586,"owners_count":21126519,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-14T08:37:32.947Z","updated_at":"2025-10-04T14:40:28.331Z","avatar_url":"https://github.com/lordnull.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Makefile CI](https://github.com/lordnull/dice.js/actions/workflows/makefile.yml/badge.svg)](https://github.com/lordnull/dice.js/actions/workflows/makefile.yml)\n\ndice.js\n=======\n\nA Generic Dice syntax parser and evaluator for javascript.\n\nThis tool is oriented more for those who wish to implement game systems or\ncharacter management systems. This means the read me can be a bit difficult\nto follow you're not a coder. However, the usage section should be enough\nto allow an end user to write useful rolling strings.\n\nDependency\n==========\n\nNode's npm can be used to fetch the build and test dependencies. There are\nno run-time dependencies.\n\nBuild\n=====\n\nAn already built version for use in browsers is included under build; if\nyou build manually, this will be overwritten.\n\nTo do a build that generates both uncompressed and minified versions,\nsimply use make. 'make compile' only generates the uncompressed version.\nBoth versions are placed in './build'.\n\nSimply include either dice.js or dice.min.js in a script tag, and you're\noff.\n\nFor use with node and installed with npm, you should only need to do the usual\n`var dice = require(\"./src/dice.js\");`.\n\nTesting\n=======\n\nTests are run using jasmine. To do a single test run for both the browser, use\n`make test`. To run only browser tests, use `make browser_test`. To\nrun only the node tests, use `make node_test`. To leave a browser used\nfor testing running for debugging purposes, use `make dbgtest`. Jasmine will\ntell you what page you need to browse to the test to actually run; but by\ndefault it's `http://localhost:8888`.\n\nUsage\n=====\n\nDice.js is a tool to roll dice and fill in certain values based on a given\nscope. In short:\n\n    var res = dice.roll(diceString, scopeObject);\n    console.log(+res);\n    console.log(dice.stringify(res));\n\nThe res is a number that can be used like any other. It has operations\nattached which allow it to be examined to determine how the total was\nachieved (thus why it is coerced into a primitive when logged above).\nThe easiest way to analyze it is to have dice.js stringify it.\n\nThe `diceString` uses a simple-ish syntax to specify what dice to roll, how\nto roll them, and the sum of the rolls. While each individual part is simple,\npresenting it all at once can be overwhelming.\n\nBasic Rolls\n-----------\n\nIf you familiar with Dungeons and Dragons, the following should be\nfamiliar:\n\n    1d20 + 10\n\nThat is a valid statement for a dice roll. The 'd' separator is case insensitive:\n\n    1D20 + 10\n\nYou could simplify it a bit, in fact:\n\n    d20 + 10\n    D20 + 10\n\nThere are times when you would need to roll multiple sets of dice:\n\n    3d6 + d8 + 5\n\nOr maybe you have a penalty:\n\n    d20 - 5\n\nIn some systems, there may be a minimum for the roll; in DnD, some weapons\nallow one to re-roll all ones:\n\n    3d2..6\n\nThis can be combined with the above statements:\n\n    3d2..6 + 5\n    \nFor players of Fudge or Fate, negative numbers can be used for the \nminimum and maximum too, and in any order.\n\n    4d-1..1 + 1\n    4d1..-1 + 3\n    \nYou may have noticed that in the Fudge examples, the -1 and 1 are reversed.\nThis is because the numbers on either side of the `..` are not a minimum\nand maximum, but a range. `-1..1` and `1..-1` represent the same range. The\nDnD example of the minimum attack could be expressed as:\n\n    3d6..2\n\n\nIf you have played Star Wars d6, using a wild die is supported as well:\n\n    3d6 + 1w6\n    3D6 + 1W6\n\nUsing `w` instead of `d` means that die will be re-rolled and added to the\nresult if it comes up as a the value to the right of the `..`. All the\nrepeat rolls will show up as a single roll in the `rolls` property of the\nreturned object.\n\nNote that the `xwn..m` syntax will always reroll when the result is `m`. This\nmeans that `3w2..6` is *not* the same as `3w6..2`. The former explodes the\ndice on a 6, while the latter explodes it on a 2.\n\nScopes\n------\n\nAs you can see, the strings to define a roll are very similar to what\nplayers have been using for years with a minor addition to support minimum\nnumbers. There is another feature, however, that makes this system even more\npowerful: scopes.\n\nLet's take a very simplified DnD character, using only the ability\nmodifiers:\n\n    var character = {\n        name: 'Code Monkey',\n        Strength: -2,\n        Dexterity: -1,\n        Constitution: 0,\n        Charisma: 3,\n        Wisdom: 3,\n        Intelligence: 5\n    };\n\nUsing the rules above, we can write a roll for a strength check:\n\n    var roll = \"d20 - 2\";\n\nNow if our character puts in effort to increase the stat:\n\n    character.Strength++;\n\nUsing the rules above we need to re-write the roll:\n\n    roll = \"d20 - 1\";\n\nBut what if we could just use the information in the character object?\nturns you, you can:\n\n    roll = \"d20 + [Strength]\";\n\nWhen the roll is evaluated with the scope of the character, `[Strength]` is\nreplaced with the Strength property of the character. The previous two\nexamples are equivalent, with the bonus that if the character changes, new\nevaluations will use the updated properties.\n\n    dice.roll(roll, character);\n\nThe replacement works anywhere an integer can go:\n\n    3d8 + [Enhancement Bonus]d12\n    2d[Weapon Die]\n    3d2..[Weapon Die]\n    [Character Level]d6\n\nNote how we allow spaces in the name. The only characters explicitly disallowed\nare `[` and `]`.\n\nIf the scope contains values that are not integers, like 1.5, You can use one of\nthe built-in rounding functions. Preface the variable box with `f` for round\ndown (floor), `c` for round up (ceiling), or `r` for round to nearest.\n\n    1d20 + f[Half Level]\n\nIf the Half level was used without the `f` tag, an exception would be\nthrown.\n\nFor more advanced usage, scopes can be nested.\n\n    var scope = {\n        'takes.priority': 3,\n        'takes':{\n            'priority': 5\n        },\n        'nested'{\n            'value': 7\n        }\n    };\n    var result = dice.roll(\"[takes.priority] + [nested.value]\", scope);\n    result == 10; // because we look for an exact match of property name first\n\nSub-expressions\n---------------\n\nThe Usual `+`, `-`, `*` and `/` are supported, with order of operations being\nobserved: `*` and `/` done in order, then `+` and `-`.\n\nIf this is not desired, or you want to do some math where an integer would go,\nyou can use a parenthesis expression. As with scopes, we can prepend them with\nthe rounding flags `f`, `c`, and `r`. The rounding is required when using a\nsub-expression where an integer is expected.\n\nFor example, the half level from the scope example above could be re-written\nwithout needing an explicit half level on the scope.\n\n    1d20 + f([Level] / 2)\n\nOr if you need to roll half your level in d6's:\n\n    c([Level] / 2)d6\n\nRoll Modifiers\n--------------\n\nMany DnD players are familiar with the \"4 dice, drop lowest\" method of rolling\ncharacter attributes. While this can be achieved in JavaScript with some code\nand inspecting the results, the goal is to allow many rolls to be written\nwithout needing to know how to code. This is where roll modifiers come in.\n\nAfter any dice roll expression, you can add some rules to modify the result.\n\n    4d6{ drop lowest }\n    4d6{ keep highest 3 }\n    3d6{ reroll } // 3 dice, reroll 1's once.\n    3d6{ reroll \u003c3 } // 3 dice, reroll 1's and 2's once.\n    3d6{ reroll 2x } // 3 dice, reroll 1's up to 2 times.\n    3d6{ reroll \u003c3 2x } // 3 dice, reroll 1's and 2's up to 2 times.\n\nMultiple modifiers can be used. Seperate them with a `;`. They modifier the\nresult of the rolls in the order by are listed.\n\n    4d6{ reroll ; drop lowest } // 4 dice, reroll 1's once, then drop lowest\n\nSome modifiers also have a short form. When using the short form, only one\nmodifier can be used.\n\n    4d6:dl // same as 4d6{ drop lowest }\n    4d6:k3 // same as 4d6{ keep highest 3 }\n\nThere are 4 modifiers: keep, drop, reroll, and explode. Each as a short form of\nsome kind.\n\n### Keep\n\nKeep a certain number of the highest or lowest of a roll.\n\n    'keep' which_type how_many\n\n* `which_type`: either \"highest\" or \"lowest\". If omitted, this defaults to\n\"highest\".\n* `how_many`: How many dice to keep. If omitted, defaults to 1.\n\nThis also has several short forms, which are case-insensitive. Any of the short\nforms can have a number appended (no space before the number) to change it from\na single die to that number. As usual, you can put a scope or rounded value in.\n\n* `:k`: Keep the single highest roll.\n* `:h`: Keep the single highest roll.\n* `:kh`: Keep the single highest roll.\n* `:kl`: Keep the single lowest roll.\n\n### Drop\n\nThe inverse of keep, drop a number of the highest or lowest dice.\n\n    'drop' which_type how_many\n\n* `which_type`: either \"highest\" or \"lowest\". If omitted, this defaults to\n\"lowest\".\n* `how_many`: How many dice to drop. If omitted, defaults to 1.\n\nThis also has several short forms, which are case-insensitive. Any of the short\nforms can have a number appended (no space before the number) to change it from\na single die to that number. As usual, you can put a scope or rounded value in.\n\n* `:d`: Drop the single lowest roll.\n* `:l`: Drop the single lowest roll.\n* `:dh`: Drop the single highest roll.\n* `:dl`: Drop the single lowest roll.\n\n### Reroll\n\nGiven some condition, reroll dice a limited number of times. Note that unlimited\nre-rolling is not supported. If you need to always re-roll ones on a six-sided\ndice, just define `d2..6`.\n\n    'reroll' condition limit\n\nA condition is a number (the comparitor) optionally preceded by any one of the\nfollowing:\n* `=`: the roll is exactly the comparitor.\n* `!=`: the roll is anything _but_ the comparitor.\n* `\u003e`: the roll is greater than the comparitor.\n* `\u003e=`: the roll is greater than or equal to the comparitor.\n* `\u003c`: the roll is less than the comparitor.\n* `\u003c=`: the roll is less than or equal to the comparitor.\n\nThe condition is optional. If left out, it defaults to equal to the left value\nof a dice roll's range.\n\nThe limit is a number followed by the letter 'x'. The 'x' is there so we know\nit's always a limit. If the limit is omitted, it defaults to `1`.\n\nReroll has a short form. `:rr` is the same as `{reroll}`.\n\n### Explode\n\nExploding dice a rolled again when certain number is rolled, with the new result\nbeing added to the result set (and thus total). When more than one die is rolled,\nany that meet the condition explode, and will continue until either the condition\nis not met, or the limit is met.\n\nThe long form is similar to reroll.\n\nA condition is a number (the comparitor) optionally preceded by any one of the\nfollowing:\n* `=`: the roll is exactly the comparitor.\n* `!=`: the roll is anything _but_ the comparitor.\n* `\u003e`: the roll is greater than the comparitor.\n* `\u003e=`: the roll is greater than or equal to the comparitor.\n* `\u003c`: the roll is less than the comparitor.\n* `\u003c=`: the roll is less than or equal to the comparitor.\n\nThe condition is optional. If left out, it defaults to equal to the right value\nof a dice roll's range.\n\nThe limit is a number followed by the letter 'x'. The 'x' is there so we know\nit's the limit. If the limit is omitted, it defaults to 10000.\n\nThere is a short form. Exploding dice were explained in the basic rolls section\nas using `w` instead of `d`; that's the short form. It is the same as using\n`{ explode =[max] }` where `[max]` is the right side of the dice range.\n\nStatistics\n==========\n\nIf you want some analysis for your rolls, you can get a result set created with\nsome basic stats tagged in.\n\nUsing `dice.statistics(rollString, scope, samples)` returns an object:\n\n```javascript\n    {\n        'results': [dice_roll_result], // The result set generated\n        'mean': number,                // The average of result set generated\n        'min': number,                 // The smallest value in the result set\n        'max': number,                 // The largest value in the result set\n        'min_possible': number,        // The smallest value that could have\n                                       // been generated.\n        'max_possible': number,        // The largest value that could have\n                                       // been generated.\n    }\n```\n\nCurrently the only roll modifiers considered during the statistics are the keep\nand drop modifiers.\n\nContributing\n============\n\nFork and make a pull request with relevant tests. Opening issues is also\nwelcome.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flordnull%2Fdice.js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flordnull%2Fdice.js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flordnull%2Fdice.js/lists"}