Editorial Workflows

Roll (OL)

public workflow

Install Workflow...

This workflow contains at least one Python script. Only use it if you trust the person who shared this with you, and if you know exactly what it does.

I understand, install the workflow!

This is a workflow for Editorial, a Markdown and plain text editor for iOS. To download it, you need to view this page on a device that has the app installed.

Description: Follows Sidekick dice specification format, but only supports items needed for Open Legend -- no modifiers, exploding dice, keeping high or low rolls pre-explosion.

Shared by: Roll Dice (Open Legend)

Comments: Comment Feed (RSS)

There are no comments yet.

+ Add Comment

Workflow Preview
Selected Text ?
Entire Line(s)
Empty Selection Output
  • No Output
  • All Text
  • Closest Word
Folded Text
  • Include
  • Replace with:
Run Python Script ?
Source Code
#coding: utf-8
import workflow
import re
import random

rollstring = workflow.get_input()

def zero_width_split(pattern, string):
    Split a string on a regex that only matches zero-width strings
    :param pattern: Regex pattern that matches zero-width strings
    :param string: String to split on.
    :return: Split array
    splits = list((m.start(), m.end()) for m in re.finditer(pattern, string, re.VERBOSE))
    starts = [0] + [i[1] for i in splits]
    ends = [i[0] for i in splits] + [len(string)]
    return [string[start:end] for start, end in zip(starts, ends)]
def roll_group(group):
    Rolls a group of dice in 2d6, 3d10, d12, etc. format
    :param group: String of dice group
    :return: Array of results
    group = re.match(r'^(\d*)d(\d+)$', group, re.IGNORECASE).groups()
    num_of_dice = int(group[0]) if group[1] != '' else 1
    type_of_dice = int(group[1])
    assert num_of_dice > 0

    result = []
    for i in range(num_of_dice):
        result.append(random.randint(1, type_of_dice))
    return result

rollparse = re.sub(r'(?<=d)%', '100', rollstring, re.IGNORECASE)
rollparse = rollparse.replace('^', '**')
rollgroups = zero_width_split(r'((?<=[\(\),%^\/+*-])(?=.))|((?<=.)(?=[\(\),%^\/+*-]))', rollparse)  # Split the string on the boundary between operators and other chars

rollResults = []
rollTotal = 0

for group in rollgroups:
    if (re.match(r'\d+d\d+', group)): # Only roll numeric
        exploding = re.match(r'\d*d\d+!', group, re.IGNORECASE)
        keeping = re.match(r'^((?:\d*)d\d+!?)([Hh])(\d*)$', group, re.IGNORECASE)
        dropping = re.match(r'^((?:\d*)d\d+!?)([Ll])(\d*)$', group, re.IGNORECASE)
        coreRoll = re.match(r'^(\d*d\d+)', group).group(0)
        rolls = roll_group(coreRoll)
        if keeping:
            keepCount = int(re.split(r'[Hh]', group)[1])
            keepIndexPoint = len(rolls) - keepCount
            sortedRolls = sorted(rolls)
            rolls = sortedRolls[keepIndexPoint:]

        if dropping:
            dropCount = int(re.split(r'[Ll]', group)[1])
            dropIndexPoint = len(rolls) - dropCount
            sortedRolls = sorted(rolls)
            rolls = sortedRolls[:dropCount]                        
        if exploding:
            groupMax = re.match(r'\d+d(\d+)', group, re.IGNORECASE).group(1)
            addedRolls = []
            for roll in rolls:
            	    if (int(roll) == int(groupMax)):
            	        while 1 == 1:
            	            newRollString = "1d" + str(groupMax)
            	            newRoll = roll_group(newRollString)
            	            if (int(newRoll[0]) < int(groupMax)):
            rolls = rolls + addedRolls
        rollTotal = rollTotal + sum(rolls)
action_out = " -- " + str(rollTotal) + " -- " + str(rollResults)
Move Caret ?
  • Backward
  • Forward
  • Start/End of Document
  • Start/End of Line
  • Number of Characters:
Replace Selected Text ?
Replacement Text