Permalink
Browse files

Move the Fireplace DSL logic into fireplace.dsl module

  • Loading branch information...
jleclanche committed Jul 22, 2015
1 parent 5435a70 commit 9236776a6dbd1fd011d4b19be987cbbcaf89e916
Showing with 168 additions and 163 deletions.
  1. +1 −163 fireplace/actions.py
  2. +1 −0 fireplace/cards/utils.py
  3. +3 −0 fireplace/dsl/__init__.py
  4. +61 −0 fireplace/dsl/evaluator.py
  5. +60 −0 fireplace/dsl/lazynum.py
  6. +42 −0 fireplace/dsl/picker.py
@@ -1,173 +1,11 @@
import logging
import operator
import random
from itertools import chain
from .dsl import RandomCardGenerator, Copy, LazyNum
from .enums import CardType, PowSubType, Zone
from .entity import Entity
from .targeting import Selector
class RandomCardGenerator(object):
"""
Store filters and generate a random card matching the filters on pick()
"""
def __init__(self, **filters):
self.filters = filters
self._cards = None
@property
def cards(self):
if self._cards is None:
from . import cards
self._cards = cards.filter(**self.filters)
return self._cards
def pick(self, source) -> str:
return random.choice(self.cards)
class LazyNum:
def evaluate(self, source) -> int:
raise NotImplementedError
def _cmp(op):
def func(self, other):
if isinstance(other, int):
# When comparing a LazyNum with an int, turn it into an
# Evaluator that compares the int to the result of the LazyNum
return LazyNumEvaluator(self, other, getattr(operator, op))
return getattr(super(), "__%s__" % (op))(other)
return func
__ge__ = _cmp("ge")
__le__ = _cmp("le")
class Count(LazyNum):
"""
Lazily count the matches in a selector
"""
def __init__(self, selector):
super().__init__()
self.selector = selector
def evaluate(self, source):
return len(self.selector.eval(source.game, source))
class Attr(LazyNum):
"""
Lazily evaluate the sum of all tags in a selector
"""
def __init__(self, selector, tag):
super().__init__()
self.selector = selector
self.tag = tag
def evaluate(self, source):
entities = self.selector.eval(source.game, source)
if isinstance(self.tag, str):
return sum(getattr(e, self.tag) for e in entities)
else:
return sum(e.tags[self.tag] for e in entities)
class Evaluator:
"""
Lazily evaluate a condition at runtime.
"""
def __init__(self):
self._if = None
self._else = None
def __and__(self, action):
self._if = action
return self
def __or__(self, action):
self._else = action
return self
def get_actions(self, source):
ret = self.evaluate(source)
if ret:
if self._if:
if isinstance(self._if, Action):
return [self._if]
return self._if
elif self._else:
if isinstance(self._else, Action):
return [self._else]
return [self._else]
return []
def trigger(self, source):
for action in self.get_actions(source):
action.trigger(source)
class LazyNumEvaluator(Evaluator):
def __init__(self, num, other, cmp):
super().__init__()
self.num = num
self.other = other
self.cmp = cmp
def evaluate(self, source):
num = self.num.evaluate(source)
return self.cmp(num, self.other)
class Dead(Evaluator):
"""
Evaluates to True if every target in \a selector is dead
"""
def __init__(self, selector):
super().__init__()
self.selector = selector
def evaluate(self, source):
for target in self.selector.eval(source.game, source):
if not target.dead:
return False
return True
class Find(Evaluator):
"""
Evaluates to True if \a selector has a match.
"""
def __init__(self, selector, count=1):
super().__init__()
self.selector = selector
self.count = count
def evaluate(self, source):
return len(self.selector.eval(source.game, source)) >= self.count
class Copy(object):
"""
Lazily return a list of copies of the target
"""
def __init__(self, selector):
self.selector = selector
self.fallback = None
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self.selector)
def __or__(self, other):
self.fallback = other
return self
def pick(self, source) -> [str]:
ret = self.selector.eval(source.game, source)
if not ret and self.fallback:
return [self.fallback]
return ret
def _eval_card(source, card):
"""
Return a Card instance from \a card
@@ -1,5 +1,6 @@
import random
from ..actions import *
from ..dsl import *
from ..enums import CardClass, CardType, GameTag, Race, Rarity, Zone
from ..events import *
from ..targeting import *
@@ -0,0 +1,3 @@
from .evaluator import *
from .lazynum import *
from .picker import *
@@ -0,0 +1,61 @@
class Evaluator:
"""
Lazily evaluate a condition at runtime.
"""
def __init__(self):
self._if = None
self._else = None
def __and__(self, action):
self._if = action
return self
def __or__(self, action):
self._else = action
return self
def get_actions(self, source):
from ..actions import Action
ret = self.evaluate(source)
if ret:
if self._if:
if isinstance(self._if, Action):
return [self._if]
return self._if
elif self._else:
if isinstance(self._else, Action):
return [self._else]
return [self._else]
return []
def trigger(self, source):
for action in self.get_actions(source):
action.trigger(source)
class Dead(Evaluator):
"""
Evaluates to True if every target in \a selector is dead
"""
def __init__(self, selector):
super().__init__()
self.selector = selector
def evaluate(self, source):
for target in self.selector.eval(source.game, source):
if not target.dead:
return False
return True
class Find(Evaluator):
"""
Evaluates to True if \a selector has a match.
"""
def __init__(self, selector, count=1):
super().__init__()
self.selector = selector
self.count = count
def evaluate(self, source):
return len(self.selector.eval(source.game, source)) >= self.count
@@ -0,0 +1,60 @@
import operator
from .evaluator import Evaluator
class LazyNum:
def evaluate(self, source) -> int:
raise NotImplementedError
def _cmp(op):
def func(self, other):
if isinstance(other, int):
# When comparing a LazyNum with an int, turn it into an
# Evaluator that compares the int to the result of the LazyNum
return LazyNumEvaluator(self, other, getattr(operator, op))
return getattr(super(), "__%s__" % (op))(other)
return func
__ge__ = _cmp("ge")
__le__ = _cmp("le")
class LazyNumEvaluator(Evaluator):
def __init__(self, num, other, cmp):
super().__init__()
self.num = num
self.other = other
self.cmp = cmp
def evaluate(self, source):
num = self.num.evaluate(source)
return self.cmp(num, self.other)
class Count(LazyNum):
"""
Lazily count the matches in a selector
"""
def __init__(self, selector):
super().__init__()
self.selector = selector
def evaluate(self, source):
return len(self.selector.eval(source.game, source))
class Attr(LazyNum):
"""
Lazily evaluate the sum of all tags in a selector
"""
def __init__(self, selector, tag):
super().__init__()
self.selector = selector
self.tag = tag
def evaluate(self, source):
entities = self.selector.eval(source.game, source)
if isinstance(self.tag, str):
return sum(getattr(e, self.tag) for e in entities)
else:
return sum(e.tags[self.tag] for e in entities)
@@ -0,0 +1,42 @@
import random
class RandomCardGenerator(object):
"""
Store filters and generate a random card matching the filters on pick()
"""
def __init__(self, **filters):
self.filters = filters
self._cards = None
@property
def cards(self):
if self._cards is None:
from .. import cards
self._cards = cards.filter(**self.filters)
return self._cards
def pick(self, source) -> str:
return random.choice(self.cards)
class Copy(object):
"""
Lazily return a list of copies of the target
"""
def __init__(self, selector):
self.selector = selector
self.fallback = None
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self.selector)
def __or__(self, other):
self.fallback = other
return self
def pick(self, source) -> [str]:
ret = self.selector.eval(source.game, source)
if not ret and self.fallback:
return [self.fallback]
return ret

0 comments on commit 9236776

Please sign in to comment.