{"id":43011170,"url":"https://github.com/pknull/rpg-dice","last_synced_at":"2026-01-31T05:10:59.136Z","repository":{"id":295937470,"uuid":"77520703","full_name":"pknull/rpg-dice","owner":"pknull","description":"A simple RPG dice roller","archived":false,"fork":false,"pushed_at":"2026-01-17T02:00:13.000Z","size":95,"stargazers_count":1,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-17T14:32:27.064Z","etag":null,"topics":["dice","dice-notation","dice-roller","rpg"],"latest_commit_sha":null,"homepage":null,"language":"Python","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/pknull.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2016-12-28T09:30:31.000Z","updated_at":"2026-01-17T02:00:17.000Z","dependencies_parsed_at":"2026-01-17T04:01:39.899Z","dependency_job_id":null,"html_url":"https://github.com/pknull/rpg-dice","commit_stats":null,"previous_names":["pknull/rpg-dice"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/pknull/rpg-dice","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pknull%2Frpg-dice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pknull%2Frpg-dice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pknull%2Frpg-dice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pknull%2Frpg-dice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pknull","download_url":"https://codeload.github.com/pknull/rpg-dice/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pknull%2Frpg-dice/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28929866,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-31T04:05:25.756Z","status":"ssl_error","status_checked_at":"2026-01-31T04:02:35.005Z","response_time":128,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["dice","dice-notation","dice-roller","rpg"],"created_at":"2026-01-31T05:10:58.431Z","updated_at":"2026-01-31T05:10:59.129Z","avatar_url":"https://github.com/pknull.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rpg-dice\n\nA simple RPG dice roller\n\n\u003e This project is partially managed by [Asha](https://github.com/pknull/asha), a Claude Code framework.\n\n## Quick start\n\n1. Install the dependencies:\n\n   ```bash\n   pip install -r requirements.txt\n   ```\n\n2. Use the `DiceThrower` class to roll dice:\n\n   ```python\n   from dice_roller.DiceThrower import DiceThrower\n   dice = DiceThrower()\n   result = dice.throw('2d6')\n   print(result)\n   ```\n\n## More about our classes\n\nTBCL\n\n## Explain the roll format\n\nThe dice roller can perform several different types of rolls based on the roll tokens. A quick summary\nis as follows (spaces for readablity only).\n\nThis is our core roll.\n\n```\n          N   d   N   (+|-)N   =(+|-)N   cmpN   McmpN\n         ─┬─ ─┬─ ─┬─ ─┬────── ─┬─────── ─┬──── ─┬─────\n# of Dice ┘   │   │   │        │         │      │\nPlace Holder ─┘   │   │        │         │      │\nNumber of Sides ──┘   │        │         │      │\nPer-Die Modifier ─────┘        │         │      │\nTotal Modifier ────────────────┘         │      │\nSuccess Handler ─────────────────────────┘      │\nModifiers (x, kh, f, t, etc.) ─────────────────┘\n```\n\nThe above order is specific and important. Not following the above format can lead to failure\nexecuting your roll. The core structure (dice, per-die modifier, total modifier, success handler)\nmust follow this order. However, the method modifiers (M) such as `f`, `x`, `xx`, `kh`, `r`, `t`,\netc. may be placed in any order relative to each other.\n\n### Quick Reference: The Three Modifiers\n\nThese look similar but do very different things:\n\n| Syntax | Name | What it does | Example |\n|--------|------|--------------|---------|\n| `+N` | Per-Die Modifier | Adds N to each die | `2d6+5` → [3,4] becomes [8,9] |\n| `=+N` | Total Modifier | Adds N to final total | `2d6=+5` → [3,4] total 7+5=12 |\n| `\u003e=N` | Success Threshold | Counts dice meeting condition | `2d6\u003e=5` → [3,6] = 1 success |\n\n**Combined example:** `5d10+5=+5\u003e=10`\n- Roll 5d10: [4, 8, 7, 9, 6]\n- `+5` each die: [9, 13, 12, 14, 11]\n- `\u003e=10` count successes: 4 (the 13, 12, 14, 11)\n- `=+5` add to total: 59 + 5 = 64\n\nResult: `{success: '4', total: '64', ...}`\n\n### Subrolls (Dice as Values)\n\nAnywhere you see `N` (a number), you can use a dice expression instead. The dice is rolled first and its result replaces the value.\n\n| Position | Static | With Subroll |\n|----------|--------|--------------|\n| Total Modifier | `=+5` | `=+1d4` |\n| Total Modifier Chain | `=+10=-3` | `=+1d6=-1d4` |\n| Success Threshold | `\u003e=5` | `\u003e=1d6` |\n| Method Value | `kh3` | `kh1d4` |\n| Explode Threshold | `x\u003e=5` | `x\u003e=1d3` |\n| Reroll Threshold | `r\u003c=2` | `r\u003c=1d2` |\n\n**Example:** `1d20=+1d4t\u003e=15`\n- Roll 1d20: 12\n- Roll subroll 1d4: 3\n- Add to total: 12 + 3 = 15\n- Check t\u003e=15: pass!\n\n**Chained subrolls:** `3d6=+1d4=-1d2`\n- Roll 3d6: [4, 3, 5] = 12\n- Roll 1d4: 3, Roll 1d2: 1\n- Total: 12 + 3 - 1 = 14\n\n### Quick Reference: Success vs Pass\n\n| Field | Syntax | Question Answered |\n|-------|--------|-------------------|\n| `success` | `\u003e=N` | How many dice meet the threshold? |\n| `pass` | `t\u003e=N` | Does the total meet the target? |\n\n**Example:** `5d10\u003e=8t\u003e=30` answers both \"how many hits?\" and \"did I beat the DC?\"\n\n---\n\nCode wise, you'll just need to import the dice roller module, create an instance of the class\nand wham-o, you can start rolling dice!\n\n ```\nfrom dice_roller.DiceThrower import DiceThrower\ndice = DiceThrower()\ndice.throw('10d6')\n{'natural': [5, 4, 5, 1, 3, 1, 2, 6, 4, 6], 'roll': '10d6', 'modified': [5, 4, 5, 1, 3, 1, 2, 6, 4, 6], 'success': '2', 'total': '37'}\n```\n\n### I need examples and more explanation please.\n\nThis is a base example roll\n\n```\n10d6\n```\n\nThis is how it would be executed.\n\n```\nfrom dice_roller.DiceThrower import DiceThrower\ndice = DiceThrower()\ndice.throw('10d6')\n{'natural': [5, 4, 5, 1, 3, 1, 2, 6, 4, 6], 'roll': '10d6', 'modified': [5, 4, 5, 1, 3, 1, 2, 6, 4, 6], 'success': '2', 'total': '37'}\n\n```\n\nBreaking the roll up into it's components it works like this\n\n#### The first integer is the number of dice to roll (required)\n\n```\n10\n```\n\n#### Sides, or the set dN (required)\n\nThe second segment is the number of sides, with the token of dN\n\n```\nd6\n```\n\nThis would constitute a 6 sided dice. You can also replace the number with a list in curly brackets dice. Note any additional modifiers are ignored if the list contains any strings.\n\n```\n10d{a,b,c}\n```\n\n---\n\n### PER-DIE MODIFIER\n\nAdd a bonus to each individual die result. Place the modifier directly after the sides.\n\n```\ndice.throw('2d6+4')\n{'natural': [4, 2], 'roll': '2d6+4', 'modified': [8, 6], 'success': '1', 'total': '14'}\n```\n\nEach die gets +4: natural 4 becomes 8, natural 2 becomes 6.\n\n---\n\n### COUNTERS\n\nThe following two methods allow us to provide rules for counting successes and failures. Successes are\nautomatically assumed to be the highest face. You can adjust it by providing another number. Failures\ncan just be flagged with a default counter of the lowest face. You can also provide comparators for\nadvanced counters.\n\n#### Successes N\n\nTo count successes instead of totals, add a comparator after the sides and any boost modifiers.\n\n```\ndice.throw('10d6\u003e=5')\n{'natural': [6, 1, 3, 1, 2, 4, 2, 6, 5, 2], 'roll': '10d6\u003e=5', 'modified': [6, 1, 3, 1, 2, 4, 2, 6, 5, 2], 'success': '3', 'total': '32'}\n\ndice.throw('2d6+4\u003e5')\n{'natural': [3, 6], 'roll': '2d6+4\u003e5', 'modified': [7, 10], 'success': '2', 'total': '17'}\n```\n\n#### Failures fN\n\nTo count failures, use the fN token with a comparator or just the side\n\n```\ndice.throw('10d6f\u003c2')\n{'natural': [5, 5, 4, 3, 2, 3, 4, 6, 6, 4], 'success': '2', 'fail': '0', 'total': '42', 'roll': '10d6f\u003c2', 'modified': [5, 5, 4, 3, 2, 3, 4, 6, 6, 4]}\n```\n\n#### Naturals nsN/nsF\n\nIf you'd like to count success and fails before modifiers, you can add ns and nf to your roll. A\ntypical DnD roll might look like. Do note that successes are automatically tallied for the highest\nand lowest values for the dice.\n\n```\ndice.throw('1d20\u003e15ns20nf1')\n{'natural': [8], 'success': '0', 'ns': '0', 'nf': '0', 'total': '8', 'roll': '1d20\u003e15ns20nf1', 'modified': [8]}\n```\n\nSo technically you could do this (the f token is to count fails)\n\n```\n dice.throw('1d20f')\n{'natural': [20], 'success': '1', 'fail': '0', 'total': '20', 'roll': '1d20f', 'modified': [20]}\n\ndice.throw('1d20f')\n{'natural': [1], 'success': '0', 'fail': '1', 'total': '1', 'roll': '1d20f', 'modified': [1]}\n```\n\n---\n\n### ROLL MODIFIERS\n\nRoll modifiers are complicated in that they stack. You must at least have exploding. Then you can\noptionally add compounding, penetrating, or both. Highest face\nis assumed unless otherwise provided. You may provide a comparator for advanced usage. Note that\ndice boost modifiers are applied BEFORE additional modifiers.\n\n#### Exploding Dice xN\n\nExploding dice roll an additional die when the comparator, on that die, is rolled.\n\n```\n dice.throw('10d6x\u003e=5')\n{'natural': [1, 1, 1, 2, 5, 5, 1, 6, 4, 3], 'roll': '10d6x\u003e=5', 'modified': [1, 1, 1, 2, 5, 4, 5, 1, 1, 6, 6, 2, 4, 3], 'success': '2', 'total': '42'}\n```\n\nThis would explode any dice equal or greater than 5 in our roll.\n\nWith subroll threshold:\n\n```\ndice.throw('10d6x\u003e=1d3')\n# 1d3 rolls 2, so explode on \u003e= 2\n```\n\n#### Compounding Dice xxN\n\nSometimes, you may want the exploded dice rolls to be added together under the same, original roll.\nThis can lead to large singular dice rolls.\n\n```\ndice.throw('10d6xx\u003e=5')\n{'natural': [5, 2, 2, 4, 5, 4, 5, 2, 4, 2], 'roll': '10d6xx\u003e=5', 'modified': [7, 2, 2, 4, 7, 4, 8, 2, 4, 2], 'success': '0', 'total': '42'}\n```\n\n#### Penetrating Dice xpN/xxpN\n\nSimply put, any exploded dice are recorded as one less (after exploding if applicable)\n\n```\ndice.throw('10d6xp\u003e=5')\n{'natural': [2, 5, 2, 1, 4, 4, 6, 2, 4, 6], 'roll': '10d6xp\u003e=5', 'modified': [2, 5, 5, 1, 2, 1, 4, 4, 6, 2, 2, 4, 6, 5, 4, 5, 1], 'success': '2', 'total': '59'}\n```\n\nNote you can occasionally get dice with a value of 0 here.\n\n---\n\n### ADDITIONAL ROLL MODIFIERS\n\nSome systems may let you reroll those failures. Same as before, defaults to lowest with no input, can\nuse comparators and numbers for more advanced usage.\n\n#### Reroll rN\n\nIf the dice matches, reroll. Defaults to lowest. Rerolls until it no longer matches.\n\n```\ndice.throw('10d6r\u003c3')\n{'natural': [1, 1, 4, 2, 4, 5, 2, 1, 5, 2], 'roll': '10d6r\u003c3', 'modified': [3, 5, 4, 5, 4, 5, 6, 3, 5, 6], 'success': '2', 'total': '46'}\n```\n\nWith subroll threshold:\n\n```\ndice.throw('10d6r\u003c=1d2')\n# 1d2 rolls 2, so reroll any dice \u003c= 2\n```\n\n#### Reroll Once roN\n\nIf the dice matches, reroll. Defaults to lowest. Reroll only once.\n\n```\ndice.throw('10d6ro\u003c3')\n{'natural': [6, 2, 5, 1, 1, 6, 3, 1, 2, 5], 'roll': '10d6ro\u003c3', 'modified': [6, 3, 5, 1, 3, 6, 3, 6, 6, 5], 'success': '4', 'total': '44'}\n```\n\nNote the 1, bad luck there...\n\n---\n\n### RESULT POOL MODIFIERS\n\nYou didn't want all those results anyways. Keep or drop dice of any amount specified. Note the\nsystem will keep dice first, then drop (if you do both for some reason)\n\n#### Keep and Drop khN/klN/dhN/dlN\n\nSimple, keep high, keep low, drop high, drop low, of the specified number. Easy.\n\n```\ndice.throw('10d6kh5')\n{'natural': [2, 5, 3, 1, 6, 3, 4, 2, 5, 3], 'roll': '10d6kh5', 'modified': [6, 5, 5, 4, 3], 'success': '1', 'total': '23'}\n```\n\nCan't believe a 3 made it there...\n\n```\ndice.throw('10d6kl5')\n{'natural': [5, 3, 6, 5, 1, 4, 5, 2, 6, 2], 'roll': '10d6kl5', 'modified': [1, 2, 2, 3, 4], 'success': '0', 'total': '12'}\n```\n\nWith subroll count (keep a random number of dice):\n\n```\ndice.throw('10d6kh1d4')\n# 1d4 rolls 3, so keep highest 3\n```\n\n---\n\n### TOTAL MODIFIER\n\nAdd a bonus to the final total (not individual dice). Use `=+N` or `=-N` syntax.\n\n```\ndice.throw('5d10=+5')\n{'natural': [3, 7, 2, 8, 4], 'roll': '5d10=+5', 'modified': [3, 7, 2, 8, 4], 'total': '29', 'success': '1'}\n```\n\nThe dice stay unchanged; only the total is modified (24 + 5 = 29).\n\n#### Combining Per-Die and Total Modifiers\n\nYou can use both in the same roll:\n\n```\ndice.throw('2d6+2=+5')\n{'natural': [3, 4], 'roll': '2d6+2=+5', 'modified': [5, 6], 'total': '16', 'success': '0'}\n```\n\nEach die gets +2 (modified: 5, 6), then +5 to total (11 + 5 = 16).\n\n#### Chained Total Modifiers\n\nYou can chain multiple total modifiers:\n\n```\ndice.throw('3d6=+10=-3')\n{'natural': [4, 3, 5], 'roll': '3d6=+10=-3', 'modified': [4, 3, 5], 'total': '19', 'success': '0'}\n```\n\nThe modifiers accumulate: +10 - 3 = +7, so 12 + 7 = 19.\n\n#### Subrolls in Total Modifiers\n\nUse dice expressions instead of static numbers:\n\n```\ndice.throw('3d6=+1d4=-1d2')\n# 1d4 rolls 3, 1d2 rolls 1\n{'natural': [4, 3, 5], 'roll': '3d6=+1d4=-1d2', 'modified': [4, 3, 5], 'total': '14', 'success': '0'}\n```\n\n---\n\n### TOTAL CHECK\n\nCheck if the final total meets a condition. Use `t` followed by a comparator and target value.\nReturns `pass: '1'` if the condition is met, `pass: '0'` otherwise.\n\n```\ndice.throw('2d10t\u003e=15')\n{'natural': [8, 9], 'roll': '2d10t\u003e=15', 'modified': [8, 9], 'total': '17', 'success': '0', 'pass': '1'}\n```\n\nThe total (17) is \u003e= 15, so pass is '1'.\n\n#### Combining with Total Modifier\n\nTotal check evaluates after total modifiers are applied:\n\n```\ndice.throw('2d6=+5t\u003e=15')\n{'natural': [4, 5], 'roll': '2d6=+5t\u003e=15', 'modified': [4, 5], 'total': '14', 'success': '0', 'pass': '0'}\n```\n\nEach die stays natural, +5 to total (9 + 5 = 14), then check if 14 \u003e= 15 (fails).\n\n#### Other Comparators\n\n```\ndice.throw('2d6t=7')    # Exact match - pass if total equals 7\ndice.throw('2d6t\u003e10')   # Greater than - pass if total \u003e 10\ndice.throw('2d6t\u003c=5')   # Less than or equal - pass if total \u003c= 5\n```\n\n#### Combining with Success Counting\n\nUse success counting and total check together to answer \"how many hits?\" and \"did I beat the DC?\" in one roll:\n\n```\ndice.throw('5d10\u003e=8t\u003e=25')\n{'natural': [6, 4, 10, 8, 8], 'roll': '5d10\u003e=8t\u003e=25', 'modified': [6, 4, 10, 8, 8], 'total': '36', 'success': '3', 'pass': '1'}\n```\n\n- `\u003e=8` counts successes (3 dice rolled 8 or higher)\n- `t\u003e=25` checks if total meets target (36 \u003e= 25, passes)\n\n#### Full Combined Example\n\nAll modifiers can work together:\n\n```\ndice.throw('5d10+2\u003e=10t\u003e=40')\n{'natural': [7, 9, 3, 8, 6], 'roll': '5d10+2\u003e=10t\u003e=40', 'modified': [9, 11, 5, 10, 8], 'total': '43', 'success': '2', 'pass': '1'}\n```\n\n- `+2` adds 2 to each die\n- `\u003e=10` counts modified dice \u003e= 10 (2 successes)\n- `t\u003e=40` checks if total \u003e= 40 (43 \u003e= 40, passes)\n\n---\n\n### Conclusion\n\nOnce you get the main dice roll down ```2d5``` you can add on the tokens above for some very\nexpressive (and meaningless) dice rolls.\n\n```\ndice.throw('10d6+0\u003e=5f\u003c=2xxp\u003e=5ro=1dl5+4')\n{'natural': [1, 3, 1, 2, 3, 4, 5, 5, 3, 1], 'success': '3', 'fail': '0', 'total': '51', 'roll': '10d6+0\u003e=5f\u003c=2xxp\u003e=5ro=1dl5+4', 'modified': [20, 11, 8, 4, 4]}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpknull%2Frpg-dice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpknull%2Frpg-dice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpknull%2Frpg-dice/lists"}