PyRC Diceroller Tutorial: Build Custom Dice Rolls for RPGs

Extend PyRC Diceroller: Scripting Advanced Roll Mechanics

PyRC Diceroller is a compact Python library for simulating dice rolls commonly used in tabletop RPGs. This article shows practical ways to extend its capabilities with scripts for advanced roll mechanics: custom dice, rerolls, exploding dice, conditional modifiers, pooled results, and logging. Examples assume a minimal PyRC-style API: a roll(expression) function returning integers or lists; adapt names to your actual library.

1. Design goals and approach

  • Keep extensions small and composable (pure functions where possible).
  • Accept standard dice notation (e.g., 3d6+2) and add operators for advanced mechanics.
  • Provide both one-off helper functions and a small scriptable framework for rulesets.

2. Parsing extended notation

Extend the parser to recognize extra operators:

  • ! or !> — explode on maximum (e.g., 1d6!).
  • rX — reroll values ≤ X (e.g., 4d6r1 reroll 1s).
  • khN / klN — keep highest/lowest N (e.g., 4d6kh3).
  • pN — pool top N results from multiple rolls.
  • >N / — count successes (e.g., 10d10>7). Use a lightweight regex-based tokenizer to split core dice terms and modifiers, then apply modifiers in a deterministic order: roll → reroll → explode → keep/drop → modifiers → tally.

Example parser outline (pseudocode):

tokenize(expression)for each token: if token is NdM: base_rolls = roll_ndm(N,M) apply reroll rules to base_rolls apply explode rules (append new rolls when triggered) apply keep/drop (kh/kl) apply arithmetic modifiers (+, -,, /) if success-count operator present, convert to countsreturn final result (value and breakdown)

3. Implementing core mechanics

  • Exploding dice

    • After rolling a die, if it equals the explosion threshold (usually the die maximum), roll another die and add it; repeat while explosions occur.
    • Protect against infinite loops by limiting recursion depth or total additional rolls.
  • Rerolls

    • Reroll specific values once or until above a threshold. Support r1 (reroll ones once) and ro1 (reroll ones until not one).
    • Decide whether original values count if reroll yields same value.
  • Keep/Drop highest/lowest

    • After all rolls complete, sort and slice to keep required number, returning both kept and dropped lists for transparency.
  • Success counting / Target numbers

    • Convert each die result to ⁄0 by comparing to a target (e.g., >= or >), then sum successes. Allow exploding successes (each max also adds an extra success roll).
  • Conditional modifiers

    • Apply context-based modifiers, e.g., add +2 if a particular roll in a pool exceeds a threshold.

4. Example helper functions (Python-style pseudocode)

  • Explode:
def explode_rolls(rolls, die_max, cap=100): i = 0 while i < len(rolls) and len(rolls) < cap: if rolls[i] == die_max: rolls.append(randint(1, die_max)) i += 1 return rolls
  • Reroll once:
def reroll_once(rolls, target_values): return [randint(1, die_max) if v in target_values else v for v in rolls]
  • Keep highest N:
def keep_highest(rolls, n): kept = sorted(rolls, reverse=True)[:n] dropped = rolls.copy() for v in kept: dropped.remove(v) return kept, dropped
  • Success counting:
def count_successes(rolls, threshold, inclusive=True): if inclusive: return sum(1 for r in rolls if r >= threshold) return sum(1 for r in rolls if r > threshold)

5. Composable rule pipeline

Create a Rule class and apply a pipeline so users can combine behaviors:

class Rule: def apply(self, rolls, die_max): …pipeline = [RerollRule(…), ExplodeRule(…), KeepRule(…), SuccessRule(…)]for rule in pipeline: rolls = rule.apply(rolls, die_max)

This makes adding new mechanics easy and keeps logic testable.

6. Scripting examples

  • 4d6kh3 with reroll ones (r1) and explode on 6:

    • Roll 4d6 → reroll ones once → explode sixes → keep highest 3 → sum.
  • Pooling for skill checks: roll 10d10>7, keep top 3 successes (p3):

    • Roll 10 dice → count successes per die (≥8) → if pooled, choose the top 3 individual dice results to assign special bonuses

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *