How to use d20 - 10 common examples

To help you get started, we’ve selected a few d20 examples, based on popular ways it is used in public projects.

Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.

github avrae / avrae / cogs5e / models / automation.py View on Github external
# add X critdice to the leftmost node if it's dice
                left = d20.utils.leftmost(dice_ast)
                if isinstance(left, d20.ast.Dice):
                    left.num += int(critdice)

        # -c #
        if c_arg and in_crit:
            c_ast = d20.parse(c_arg)
            dice_ast.roll = d20.ast.BinOp(dice_ast.roll, '+', c_ast.roll)

        # max
        if max_arg:
            dice_ast = d20.utils.tree_map(_max_mapper, dice_ast)

        # evaluate damage
        dmgroll = roll(dice_ast)

        # magic arg (#853)
        always = {'magical'} if (autoctx.is_spell or magic_arg) else None
        # dtype transforms/overrides (#876)
        transforms = {}
        for dtype in dtype_args:
            if '>' in dtype:
                *froms, to = dtype.split('>')
                for frm in froms:
                    transforms[frm.strip()] = to.strip()
            else:
                transforms[None] = dtype
        # display damage transforms (#1103)
        if None in transforms:
            autoctx.meta_queue(f"**Damage Type**: {transforms[None]}")
        elif transforms:
github avrae / avrae / cogs5e / models / automation.py View on Github external
if in_crit:
            dice_ast = d20.utils.tree_map(_crit_mapper, dice_ast)
            if critdice and not autoctx.is_spell:
                # add X critdice to the leftmost node if it's dice
                left = d20.utils.leftmost(dice_ast)
                if isinstance(left, d20.ast.Dice):
                    left.num += int(critdice)

        # -c #
        if c_arg and in_crit:
            c_ast = d20.parse(c_arg)
            dice_ast.roll = d20.ast.BinOp(dice_ast.roll, '+', c_ast.roll)

        # max
        if max_arg:
            dice_ast = d20.utils.tree_map(_max_mapper, dice_ast)

        # evaluate damage
        dmgroll = roll(dice_ast)

        # magic arg (#853)
        always = {'magical'} if (autoctx.is_spell or magic_arg) else None
        # dtype transforms/overrides (#876)
        transforms = {}
        for dtype in dtype_args:
            if '>' in dtype:
                *froms, to = dtype.split('>')
                for frm in froms:
                    transforms[frm.strip()] = to.strip()
            else:
                transforms[None] = dtype
        # display damage transforms (#1103)
github avrae / avrae / cogs5e / models / sheet / resistance.py View on Github external
Note that any neutrals in the resistances will be explicitly ignored.

    :type damage_expr: d20.Expression
    :type resistances: Resistances
    :param always: If passed, damage is always this type in addition to whatever it's annotated as.
    :type always: set[str]
    :param transforms: a dict representing damage type transforms. If None is a key, all damage types become that.
    :type transforms: dict[str or None, str]
    """
    if always is None:
        always = set()
    if transforms is None:
        transforms = {}

    # simplify damage types
    d20.utils.simplify_expr_annotations(damage_expr.roll, ambig_inherit='left')

    # depth first visit expression nodes: if it has an annotation, add the appropriate binops and move to the next
    def do_visit(node):
        if node.annotation:
            # handle transforms
            if None in transforms:
                tokens = _resist_tokenize(transforms[None])
            else:
                tokens = []
                for t in _resist_tokenize(node.annotation.lower()):
                    tokens.extend(_resist_tokenize(transforms.get(t, t)))
            original_annotation = node.annotation
            dtype = f"{' '.join(always)} {' '.join(tokens)}".strip()
            node.annotation = f"[{dtype}]"

            # handle tree modification
github avrae / avrae / cogs5e / models / sheet / resistance.py View on Github external
# handle tree modification
            ann = set(tokens) | always

            if any(n.applies_to(ann) for n in resistances.neutral):  # neutral overrides all
                return node

            if any(v.applies_to(ann) for v in resistances.vuln):
                node = d20.BinOp(d20.Parenthetical(node), '*', d20.Literal(2))

            if original_annotation.startswith('[^') or original_annotation.endswith('^]'):
                node.annotation = original_annotation
                # break here - don't handle resist/immune
                return node

            if any(r.applies_to(ann) for r in resistances.resist):
                node = d20.BinOp(d20.Parenthetical(node), '/', d20.Literal(2))

            if any(im.applies_to(ann) for im in resistances.immune):
                node = d20.BinOp(d20.Parenthetical(node), '*', d20.Literal(0))

            return node

        for i, child in enumerate(node.children):
            replacement = do_visit(child)
            if replacement and replacement is not child:
                node.set_child(i, replacement)
        return None
github avrae / avrae / cogs5e / models / sheet / resistance.py View on Github external
if any(n.applies_to(ann) for n in resistances.neutral):  # neutral overrides all
                return node

            if any(v.applies_to(ann) for v in resistances.vuln):
                node = d20.BinOp(d20.Parenthetical(node), '*', d20.Literal(2))

            if original_annotation.startswith('[^') or original_annotation.endswith('^]'):
                node.annotation = original_annotation
                # break here - don't handle resist/immune
                return node

            if any(r.applies_to(ann) for r in resistances.resist):
                node = d20.BinOp(d20.Parenthetical(node), '/', d20.Literal(2))

            if any(im.applies_to(ann) for im in resistances.immune):
                node = d20.BinOp(d20.Parenthetical(node), '*', d20.Literal(0))

            return node

        for i, child in enumerate(node.children):
            replacement = do_visit(child)
            if replacement and replacement is not child:
                node.set_child(i, replacement)
        return None
github avrae / avrae / cogs5e / models / sheet / resistance.py View on Github external
else:
                tokens = []
                for t in _resist_tokenize(node.annotation.lower()):
                    tokens.extend(_resist_tokenize(transforms.get(t, t)))
            original_annotation = node.annotation
            dtype = f"{' '.join(always)} {' '.join(tokens)}".strip()
            node.annotation = f"[{dtype}]"

            # handle tree modification
            ann = set(tokens) | always

            if any(n.applies_to(ann) for n in resistances.neutral):  # neutral overrides all
                return node

            if any(v.applies_to(ann) for v in resistances.vuln):
                node = d20.BinOp(d20.Parenthetical(node), '*', d20.Literal(2))

            if original_annotation.startswith('[^') or original_annotation.endswith('^]'):
                node.annotation = original_annotation
                # break here - don't handle resist/immune
                return node

            if any(r.applies_to(ann) for r in resistances.resist):
                node = d20.BinOp(d20.Parenthetical(node), '/', d20.Literal(2))

            if any(im.applies_to(ann) for im in resistances.immune):
                node = d20.BinOp(d20.Parenthetical(node), '*', d20.Literal(0))

            return node

        for i, child in enumerate(node.children):
            replacement = do_visit(child)
github avrae / avrae / cogs5e / dice.py View on Github external
mi/ma (min/max result)
        e (explode dice of value)
        ra (reroll and add)
        __Supported Selectors__
        X (literal X)
        lX (lowest X)
        hX (highest X)
        >X (greater than X)
         1999:
            out = f"{ctx.author.mention}  :game_die:\n" \
                  f"{str(res)[:100]}...\n" \
                  f"**Total:** {res.total}"

        await try_delete(ctx.message)
        await ctx.send(out)
        await Stats.increase_stat(ctx, "dice_rolled_life")
github avrae / avrae / cogs5e / funcs / scripting / combat.py View on Github external
:param str ability: The type of save ("str", "dexterity", etc).
        :param bool adv: Whether to roll the save with advantage. Rolls with advantage if ``True``, disadvantage if ``False``, or normally if ``None``.
        :returns: A SimpleRollResult describing the rolled save.
        :rtype: :class:`~cogs5e.funcs.scripting.functions.SimpleRollResult`
        """
        try:
            save = self._combatant.saves.get(ability)
        except ValueError:
            raise InvalidSaveType

        sb = self._combatant.active_effects('sb')
        saveroll = save.d20(base_adv=adv)
        if sb:
            saveroll = f'{saveroll}+{"+".join(sb)}'

        save_roll = roll(saveroll)
        return SimpleRollResult(save_roll)
github avrae / avrae / cogs5e / models / automation.py View on Github external
save.lower() in s.lower())
        except StopIteration:
            raise InvalidSaveType()

        autoctx.meta_queue(f"**DC**: {dc}")
        if not autoctx.target.is_simple:
            save_blurb = f'{save_skill[:3].upper()} Save'
            if auto_pass:
                is_success = True
                autoctx.queue(f"**{save_blurb}:** Automatic success!")
            elif auto_fail:
                is_success = False
                autoctx.queue(f"**{save_blurb}:** Automatic failure!")
            else:
                saveroll = autoctx.target.get_save_dice(save_skill, adv=autoctx.args.adv(boolwise=True))
                save_roll = roll(saveroll)
                is_success = save_roll.total >= dc
                success_str = ("; Success!" if is_success else "; Failure!")
                out = f"**{save_blurb}**: {save_roll.result}{success_str}"
                if not hide:
                    autoctx.queue(out)
                else:
                    autoctx.add_pm(str(autoctx.ctx.author.id), out)
                    autoctx.queue(f"**{save_blurb}**: 1d20...{success_str}")
        else:
            autoctx.meta_queue('{} Save'.format(save_skill[:3].upper()))
            is_success = False

        if is_success:
            damage = self.on_success(autoctx)
        else:
            damage = self.on_fail(autoctx)
github avrae / avrae / cogs5e / initTracker.py View on Github external
return await ctx.send("You must pass in a positive, nonzero HP with the -hp tag.")
        if args.last('ac'):
            ac = args.last('ac', type_=int)

        for k in ('resist', 'immune', 'vuln'):
            resists[k] = args.get(k)

        combat = await Combat.from_ctx(ctx)

        if combat.get_combatant(name) is not None:
            await ctx.send("Combatant already exists.")
            return

        if not place:
            init_skill = Skill(modifier, adv=adv)
            init_roll = roll(init_skill.d20())
            init = init_roll.total
            init_roll_skeleton = init_roll.result
        else:
            init_skill = Skill(0, adv=adv)
            init = place
            init_roll_skeleton = str(init)

        me = Combatant.new(name, controller, init, init_skill, hp, ac, private, Resistances.from_dict(resists), ctx,
                           combat)

        # -thp (#1142)
        if thp and thp > 0:
            me.temp_hp = thp

        if group is None:
            combat.add_combatant(me)