X-Git-Url: https://git.yukkurigames.com/?p=python-bulletml.git;a=blobdiff_plain;f=bulletml%2Fexpr.py;h=a00c99eefa4c27f1b9f14d9751d5784f491e5135;hp=80224760f2039f66397fa0a62d2eb53ac34bf606;hb=70d25195d561d8b5d3126c6bbac0ecad2a502f06;hpb=2e1e64f1f8076dd21a5ea1e7f8af6dbb74946d57 diff --git a/bulletml/expr.py b/bulletml/expr.py index 8022476..a00c99e 100644 --- a/bulletml/expr.py +++ b/bulletml/expr.py @@ -29,36 +29,52 @@ class NumberDef(object): (2+$1)*0.3 """ + + GLOBALS = dict(random=random.random, __builtins__={}) + def __init__(self, expr): try: - expr = expr.__original + expr = expr.string except AttributeError: pass - self.__original = expr + self.string = expr = str(expr) repl = lambda match: "params[%d]" % (int(match.group()[1:]) - 1) expr = re.sub(r"\$\d+", repl, expr.lower()) - self.__expr = expr.replace("$rand", "rand").replace("$rank", "rank") + self.__expr = expr.replace("$rand", "random()").replace("$rank", "rank") try: try: - self.__value = eval(self.__expr, dict(__builtins__={})) + self._value = eval(self.__expr, dict(__builtins__={})) except NameError: - fake = [0] * 99 - variables = dict(rand=1, rank=1, params=fake, __builtins__={}) - value = eval(self.__expr, variables) + variables = dict(rank=1, params=[0] * 99) + value = eval(self.__expr, self.GLOBALS, variables) if not isinstance(value, (int, float)): raise TypeError(expr) - self.__value = None + self._value = None + self.expr = self.string + else: + self.expr = self._value except Exception: raise ExprError(expr) self.__expr = compile(self.__expr, __file__, "eval") def __call__(self, params, rank): """Evaluate the expression and return its value.""" - if self.__value is not None: - return self.__value - rand = random.random() - variables = dict(rand=rand, rank=rank, params=params) - return eval(self.__expr, variables) + if self._value is not None: + return self._value + variables = { 'rank': rank, 'params': params } + return eval(self.__expr, self.GLOBALS, variables) def __repr__(self): - return "%s(%r)" % (type(self).__name__, self.__original) + return "%s(%r)" % (type(self).__name__, self.expr) + +class INumberDef(NumberDef): + """A NumberDef, but returns rounded integer results.""" + def __init__(self, expr): + super(INumberDef, self).__init__(expr) + if self._value is not None: + self._value = int(round(self._value)) + + def __call__(self, params, rank): + if self._value is not None: + return self._value + return int(round(super(INumberDef, self).__call__(params, rank)))