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 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
def d20_expr(self): """ :rtype: d20.Die """ return d20.Die(self.size, values=[d20.Literal(self.die_value)])