selfsame / mud.tilde.town

a python mud influenced by Inform7
53 stars 10 forks source link

component action composition #20

Closed selfsame closed 9 years ago

selfsame commented 9 years ago

component.action functions are lacking some important compositions:

overriding, where an action handler can prevent earlier handlers from firing.

before/after/check co-functions, maybe python decorators can provide this?

@after
go_entity(e, n):
  send_room(n, "an entity enters.")

@before
go_entity(e, n):
  send_room(n, "the entity gets up and leaves to the "+n['id'])

@instead
@after
go_human(e,n):
  send_room(n, "A human wanders in.")
selfsame commented 9 years ago

Some experiments with decoraters turned out well. The decorators register functions based on their lifecycle decorator, verb, arity, and argument types.

@before
@given(human, animal)
def interact(a, b):
    print name(a), "pets the", name(b)

is converted to a tree:

{"interact": #string verb function name
  {2: #arity
    {"before": #lifecycle       
       #a tuple of predicate fns must return true when applied to the args
       (<fn human>, <fn animal>) : 
       <fn interact> #the original function we had decorated 
}}}}

The data for each function is merged into the registry with ordered dicts.

When a verb function is invoked, it pulls all relevant entries for it's verb, arity, etc., which it calls in order of lifecycle (only one fn per lifecycle will be called).

The predicate type dispatch is pretty fun, predicate functions are easy to compose

def a(*args):
  def f(e):
    if not isinstance(e, dict): return False
    for spec in args:
      if string(spec):
        if spec not in e: return False
      elif function(spec):
        if not spec(e): return False
      else: return False
    return True
  return f

def isnot(posf):
  def negf(x):
    return not posf(x)
  return negf

human = a('human')
animal = a('entity', isnot(human))
object = isnot( a('entity'))
elder = a(human, 'male', old)

@after
@given(elder, a('room'))
def enter(e, b):
    print name(a), "hobbles into", name(b)
selfsame commented 9 years ago

Totally composable and described here https://github.com/selfsame/mud.tilde.town/wiki/actions