forge/blade/action/tree.py (53 lines of code) (raw):

class ActionNode: def edges(self, world, entity): pass class ActionLeaf(ActionNode): def __call__(self, world, entity, *args): if type(args) == EmptyArgs: args = [] class Args: isEmpty = False isSet = False isDiscrete = False def __init__(self, value=None): self.value = value class Arg(Args): pass class SetArgs(Args): isSet = True def __init__(self): self.setValue = set() def add(self, value): self.setValue.add(value) def toList(self): return list(self.setValue) @property def empty(self): return len(self.toList()) == 0 class DiscreteArgs(SetArgs): isDiscrete = True class EmptyArgs(Args): isEmpty = True class ActionTree: def __init__(self, world, entity, rootVersion): self.world, self.entity = world, entity self.root, self.args = rootVersion(), None @property def n(self): return sum([a.nArgs() for a in self.action.edges()]) def flat(self): rets = [] for action in self.root.edges(None, None): for args in action.args(None, None): rets.append((action, args)) return rets def actions(self): return self.root.edges(None, None) def rand(self): nodes = self.flat() ind = np.random.randint(0, len(nodes)) return nodes[ind] def actionArgPair(self): assert self.action is not None and self.args is not None if type(self.args) not in (list, tuple): self.args = [self.args] return type(self.action), self.args