Module realm_api.rpc.roll
Dice roller RPC module
Sub-modules
realm_api.rpc.roll.parse
-
Parse segments from roll command arguments
Global variables
var explode_regex
-
Regex for exploding die extra
var keep_hilow_regex
-
Regex for keep highest/lowest extras
Functions
async def roll_handler(formula: str) ‑> realm_schema.dice_rolls.BatchResults
-
Expand source code
async def roll_handler(formula: str) -> BatchResults: """Roll them bones.""" results = BatchResults(results=[]) try: batches = parse_segments(formula) for segments in batches: results.results.append( RollResults(results=[roll_segment(s) for s in segments]) ) except Exception as ex: logger.warning(ex) return BatchResults(results=[]) return results
Roll them bones.
def roll_segment(segment: realm_schema.dice_rolls.RollSegment) ‑> realm_schema.dice_rolls.SegmentResult
-
Expand source code
def roll_segment(segment: RollSegment) -> SegmentResult: """Calculate the results of an individual RollSegment instance.""" if isinstance(segment, ConstantModifier): return SegmentResult( segment=segment, total=segment.number * (-1 if segment.negative else 1), ) if isinstance(segment, DiceRoll): limit = 0 exploding = False result = SegmentResult(segment=segment, rolls=[], work="") assert result.rolls is not None assert result.work is not None if segment.extra and segment.extra[0] == "!": exploding = True # explosion limit if len(segment.extra) > 1: explode_limit_match = explode_regex.match(segment.extra) assert explode_limit_match limit = int(explode_limit_match.groupdict()["num"]) # roll dice for _ in range(segment.dice): roll = randint(1, segment.faces) exploded = 0 # exploding die while ( exploding and roll == segment.faces and (limit == 0 or exploded < limit) ): exploded += 1 result.rolls.append(roll) result.total += roll roll = randint(1, segment.faces) result.rolls.append(roll) result.total += roll # keep methods if segment.extra and segment.extra.startswith("k"): ord_rolls = sorted(result.rolls) args_match = keep_hilow_regex.match(segment.extra) assert args_match args = args_match.groupdict() fun = args["fun"] keep = int(args["num"]) if args["num"] else 1 assert keep < segment.dice and keep > 0 drop = range(segment.dice - keep) # keep highest if fun == "kh": for i in drop: result.total -= ord_rolls[i] # keep lowest elif fun == "kl": for i in drop: result.total -= ord_rolls[-(i + 1)] rolls = [ f"**{roll}**" if roll == segment.faces else f"{roll}" for roll in result.rolls ] result.work = "".join( [ f"[{', '.join(rolls)}] = ", f"**{'-' if segment.negative else ''}{result.total}**", ] ) if segment.negative: result.total *= -1 return result raise NotImplementedError()
Calculate the results of an individual RollSegment instance.