Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from collections import namedtuple, defaultdict
- import re
- class Table(object):
- def __init__(self, name, column):
- self.name = name
- self.column = column
- self.value = defaultdict(set)
- def match(self, head, tail, ref):
- res = [head]
- for t,r in zip(tail, ref):
- if r == None or r == t:
- res.append(t)
- else:
- return None
- return self.column(*res)
- def add(self, pattern):
- self.value[pattern[0]].add(pattern[1:])
- def remove(self, pattern):
- self.value[pattern[0]].remove(pattern[1:])
- def query(self, pattern):
- if pattern[0] == None:
- for k,v in self.value.items():
- for c in v:
- m = self.match(k, c, pattern[1:])
- if m: yield m
- else:
- v = self.value[pattern[0]]
- for c in v:
- m = self.match(pattern[0], c, pattern[1:])
- if m: yield m
- class Pattern(object):
- def __init__(self):
- pass
- class Entity(object):
- def __init__(self, name):
- self.name = name
- def __repr__(self):
- return '<%s>' % self.name
- Query = namedtuple('Query', 'sign table binds')
- tables = { }
- entities = { }
- commands = defaultdict(list)
- autocmd = []
- def add_table(name, names):
- tables[name] = Table(name, namedtuple(name.rstrip('!') + '_col', names))
- def do_query(query, binds):
- pat = tuple(binds[b] for b in query.binds)
- if query.sign:
- for res in tables[query.table].query(pat):
- temp = binds.copy()
- for b,r in zip(query.binds, res):
- temp[b] = r
- yield temp
- else:
- if any(tables[query.table].query(pat)): return
- yield binds
- def do_queries(queries, binds):
- if not queries:
- for b in binds.values():
- if not b: return
- yield binds
- else:
- for qbind in do_query(queries[0], binds):
- for qq in do_queries(queries[1:], qbind):
- yield qq
- class Command(object):
- def __init__(self, name, opts):
- self.name = name
- self.binds = { 'Player' }
- self.queries = []
- self.opts = opts
- self.printline = ''
- self.do_break = False
- self.add = []
- self.remove = []
- self.set = []
- def match_options(self, binds = { }):
- temp = { b: binds.get(b) for b in self.binds }
- for q in do_queries(self.queries, temp):
- yield q
- def print_line(self, binds):
- def fmt(v):
- if isinstance(v, Entity):
- return next(tables['name'].query((v, None)), (None, v.name))[1]
- else:
- return v
- f = {k: fmt(v) for k,v in binds.items()}
- return self.printline.format(**f)
- def do(c, opts):
- if len(opts) == len(c.opts):
- binds = { b: o for b,o in zip(c.opts, opts) }
- binds['Player'] = entities['Player']
- for m in c.match_options(binds):
- print c.print_line(m)
- for a in c.add:
- row = tuple(m[bb] for bb in a[1:])
- tables[a[0]].add(row)
- for r in c.remove:
- row = tuple(m[bb] for bb in r[1:])
- tables[r[0]].remove(row)
- if c.do_break:
- return True
- return False
- TEST = '''
- : open self
- : lock self key_type
- : key self key_type
- : has self thing
- : name self name
- : desc self desc
- : seen self thing
- : room self room
- : ground self ground
- : alcohol self
- : likes_but_cant_handle_beer self
- : drop_all! self
- : holdable self
- : fear_tag self tag
- : tag self tag
- : has_been_scared_by self thing
- ! Spider
- name 'Spider'
- desc 'Eight legs'
- ! Tile
- desc 'A beautiful tiling pattern'
- ! Entrance
- name 'Entrance'
- desc 'The lobby of the T-building'
- ground Tile
- ! Guild
- name 'Kiltis'
- desc 'Stuff happens here'
- ground Tile
- ! MasterKeyType
- name 'master key'
- desc 'A key that can open any kind of door'
- ! Key
- key MasterKeyType
- name 'Key'
- desc 'A prized posession given only to the guild elders'
- room Entrance
- holdable
- ! Door
- lock MasterKeyType
- name 'Door'
- desc 'A sturdy door that guards the guild room'
- room Entrance
- room Guild
- ! Window
- name 'Window'
- desc 'Just a window on the wall'
- room Entrance
- ! Player
- room Entrance
- ! Guard
- name 'Guard'
- desc 'A scary looking dude'
- room Entrance
- has Key
- likes_but_cant_handle_beer
- fear_tag Spider
- ! Beer
- name 'Beer'
- desc 'A can of beer'
- room Entrance
- alcohol
- holdable
- >
- fear_tag Self Tag
- room Self Room
- room Scary Room
- tag Scary Tag
- not has_been_scared_by Self Scary
- print: '{Self} gets scared by {Scary}'
- add: has_been_scared_by Self Scary
- add: drop_all! Self
- break!
- >
- likes_but_cant_handle_beer Dude
- has Dude Beer
- alcohol Beer
- print: '{Dude} drinks {Beer} and fumbles'
- remove: has Dude Beer
- add: drop_all! Dude
- break!
- >
- drop_all! Dude
- has Dude Thing
- print: '{Dude} drops {Thing}'
- remove: has Dude Thing
- break!
- > inspect T
- name T Name
- desc T Desc
- print: '{Name}: {Desc}'
- > inspect Lock
- lock Lock Type
- print: 'It has a lock that can be opened with {Type}'
- > inspect Key
- key Key Type
- print: 'Works on locks that require a {Type}'
- > inspect Room
- ground Room Ground
- desc Ground Desc
- print: 'Ground: {Desc}'
- > inspect Thing
- has Someone Thing
- print: 'Held by {Someone}'
- > inspect Person
- has Person Thing
- print: 'Holds {Thing}'
- > inspect T
- likes_but_cant_handle_beer T
- print: 'Likes alcohol but cannot deal with it'
- > inventory
- has Player Thing
- desc Thing Desc
- print: '-> {Thing}: {Desc}'
- > look
- room Player Room
- room Thing Room
- desc Thing Desc
- print: '-> {Thing}: {Desc}'
- > open Lock
- lock Lock Type
- has Player Key
- key Key Type
- print: 'You open {Lock} with {Key}'
- break!
- > open Lock
- lock Lock Type
- print: 'You need to have {Type} to open {Lock}'
- break!
- > take Thing
- has Player Thing
- print: 'You are already holding {Thing}!'
- break!
- > take Thing
- has Someone Thing
- print: '{Someone} is already holding {Thing}!'
- break!
- > take Thing
- holdable Thing
- print: 'You pick up {Thing}'
- add: has Player Thing
- break!
- > take Thing
- print: 'You cannot pick up {Thing}'
- break!
- > drop Thing
- has Player Thing
- print: 'You drop {Thing}'
- remove: has Player Thing
- break!
- > drop Thing
- print: 'You are not holding {Thing}!'
- break!
- > give Someone Thing
- has Player Thing
- print: 'You give {Thing} to {Someone}'
- remove: has Player Thing
- add: has Someone Thing
- break!
- '''
- TEST = '''
- : name self name
- : desc self desc
- : look self flavor
- : room self room
- : part self room
- : tag self tag
- ! Hangover
- desc 'Hangover, had a little too many yesterday'
- ! Somewhere
- desc 'This is for sure not my apartment, no idea how I ended up here'
- look 'An unknown small cell apartment'
- ! Window
- desc 'A window pointing south'
- look 'Morning light shines through a [window] in a blinding fashion'
- room Somewhere
- ! Player
- desc 'Me!'
- room Somewhere
- tag Hangover
- > look
- room Player Room
- look Room Desc
- print: '{Desc}'
- > look
- room Player Room
- room Thing Room
- look Thing Desc
- print: '{Desc}'
- > inspect {Thing}
- desc Thing Desc
- print: '{Desc}'
- > inspect {Thing}
- tag Thing Tag
- desc Tag Desc
- print: '{Desc}'
- '''
- token_re = re.compile(r'(([a-zA-Z:>\-!_]+)|(\'[^\']+\'))')
- def parse(s):
- global entities
- global tables
- ent = None
- cmd = None
- def resolve(e):
- if e.startswith("'"):
- return e[1:-1]
- else:
- return entities[e]
- for l in s.split('\n'):
- s = [m[0] for m in token_re.findall(l)]
- if not s: continue
- if s[0] == ':':
- ent = cmd = None
- add_table(s[1], s[2:])
- elif s[0] == '!':
- ent = cmd = None
- ent = Entity(s[1])
- entities[s[1]] = ent
- elif s[0] == '>':
- ent = cmd = None
- if len(s) > 1:
- cmd = Command(s[1], s[2:])
- cmd.binds.update(s[2:])
- commands[s[1]].append(cmd)
- else:
- cmd = Command('autocmd', ())
- autocmd.append(cmd)
- elif ent:
- tables[s[0]].add((ent,) + tuple(resolve(e) for e in s[1:]))
- elif cmd:
- if s[0] == 'print:':
- cmd.printline = resolve(s[1])
- elif s[0] == 'add:':
- cmd.add.append(s[1:])
- elif s[0] == 'remove:':
- cmd.remove.append(s[1:])
- elif s[0] == 'set:':
- cmd.set.append(s[1:])
- elif s[0] == 'break!':
- cmd.do_break = True
- elif s[0] == 'not':
- cmd.binds.update(s[2:])
- cmd.queries.append(Query(False, s[1], s[2:]))
- else:
- cmd.binds.update(s[1:])
- cmd.queries.append(Query(True, s[0], s[1:]))
- parse(TEST)
- def resolve(e):
- if e == '?':
- return None
- else:
- return entities[e]
- def run(line):
- split = line.split()
- if not split: return
- if split[0] == '/query':
- q = tuple(resolve(e) for e in split[2:])
- print '\n'.join(repr(s) for s in tables[split[1]].query(q))
- elif split[0] == '/add':
- q = tuple(resolve(e) for e in split[2:])
- tables[split[1]].add(q)
- elif split[0] in commands:
- cmd = commands[split[0]]
- opts = tuple(resolve(e) for e in split[1:])
- for c in cmd:
- if c.do(opts): return
- while True:
- line = raw_input('> ')
- run(line)
- for i in range(10):
- for a in autocmd:
- a.do(())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement