Advertisement
Guest User

Untitled

a guest
Sep 26th, 2017
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.91 KB | None | 0 0
  1. from collections import namedtuple, defaultdict
  2. import re
  3.  
  4. class Table(object):
  5. def __init__(self, name, column):
  6. self.name = name
  7. self.column = column
  8. self.value = defaultdict(set)
  9.  
  10. def match(self, head, tail, ref):
  11. res = [head]
  12. for t,r in zip(tail, ref):
  13. if r == None or r == t:
  14. res.append(t)
  15. else:
  16. return None
  17. return self.column(*res)
  18.  
  19. def add(self, pattern):
  20. self.value[pattern[0]].add(pattern[1:])
  21.  
  22. def remove(self, pattern):
  23. self.value[pattern[0]].remove(pattern[1:])
  24.  
  25. def query(self, pattern):
  26. if pattern[0] == None:
  27. for k,v in self.value.items():
  28. for c in v:
  29. m = self.match(k, c, pattern[1:])
  30. if m: yield m
  31. else:
  32. v = self.value[pattern[0]]
  33. for c in v:
  34. m = self.match(pattern[0], c, pattern[1:])
  35. if m: yield m
  36.  
  37.  
  38. class Pattern(object):
  39. def __init__(self):
  40. pass
  41.  
  42. class Entity(object):
  43. def __init__(self, name):
  44. self.name = name
  45.  
  46. def __repr__(self):
  47. return '<%s>' % self.name
  48.  
  49. Query = namedtuple('Query', 'sign table binds')
  50.  
  51. tables = { }
  52. entities = { }
  53. commands = defaultdict(list)
  54. autocmd = []
  55.  
  56. def add_table(name, names):
  57. tables[name] = Table(name, namedtuple(name.rstrip('!') + '_col', names))
  58.  
  59. def do_query(query, binds):
  60. pat = tuple(binds[b] for b in query.binds)
  61. if query.sign:
  62. for res in tables[query.table].query(pat):
  63. temp = binds.copy()
  64. for b,r in zip(query.binds, res):
  65. temp[b] = r
  66. yield temp
  67. else:
  68. if any(tables[query.table].query(pat)): return
  69. yield binds
  70.  
  71. def do_queries(queries, binds):
  72. if not queries:
  73. for b in binds.values():
  74. if not b: return
  75. yield binds
  76. else:
  77. for qbind in do_query(queries[0], binds):
  78. for qq in do_queries(queries[1:], qbind):
  79. yield qq
  80.  
  81. class Command(object):
  82. def __init__(self, name, opts):
  83. self.name = name
  84. self.binds = { 'Player' }
  85. self.queries = []
  86. self.opts = opts
  87. self.printline = ''
  88. self.do_break = False
  89. self.add = []
  90. self.remove = []
  91. self.set = []
  92.  
  93. def match_options(self, binds = { }):
  94. temp = { b: binds.get(b) for b in self.binds }
  95. for q in do_queries(self.queries, temp):
  96. yield q
  97.  
  98. def print_line(self, binds):
  99. def fmt(v):
  100. if isinstance(v, Entity):
  101. return next(tables['name'].query((v, None)), (None, v.name))[1]
  102. else:
  103. return v
  104. f = {k: fmt(v) for k,v in binds.items()}
  105. return self.printline.format(**f)
  106.  
  107. def do(c, opts):
  108. if len(opts) == len(c.opts):
  109. binds = { b: o for b,o in zip(c.opts, opts) }
  110. binds['Player'] = entities['Player']
  111. for m in c.match_options(binds):
  112. print c.print_line(m)
  113.  
  114. for a in c.add:
  115. row = tuple(m[bb] for bb in a[1:])
  116. tables[a[0]].add(row)
  117.  
  118. for r in c.remove:
  119. row = tuple(m[bb] for bb in r[1:])
  120. tables[r[0]].remove(row)
  121.  
  122. if c.do_break:
  123. return True
  124. return False
  125.  
  126. TEST = '''
  127. : open self
  128. : lock self key_type
  129. : key self key_type
  130. : has self thing
  131. : name self name
  132. : desc self desc
  133. : seen self thing
  134. : room self room
  135. : ground self ground
  136. : alcohol self
  137. : likes_but_cant_handle_beer self
  138. : drop_all! self
  139. : holdable self
  140. : fear_tag self tag
  141. : tag self tag
  142. : has_been_scared_by self thing
  143.  
  144. ! Spider
  145. name 'Spider'
  146. desc 'Eight legs'
  147.  
  148. ! Tile
  149. desc 'A beautiful tiling pattern'
  150.  
  151. ! Entrance
  152. name 'Entrance'
  153. desc 'The lobby of the T-building'
  154. ground Tile
  155.  
  156. ! Guild
  157. name 'Kiltis'
  158. desc 'Stuff happens here'
  159. ground Tile
  160.  
  161. ! MasterKeyType
  162. name 'master key'
  163. desc 'A key that can open any kind of door'
  164.  
  165. ! Key
  166. key MasterKeyType
  167. name 'Key'
  168. desc 'A prized posession given only to the guild elders'
  169. room Entrance
  170. holdable
  171.  
  172. ! Door
  173. lock MasterKeyType
  174. name 'Door'
  175. desc 'A sturdy door that guards the guild room'
  176. room Entrance
  177. room Guild
  178.  
  179. ! Window
  180. name 'Window'
  181. desc 'Just a window on the wall'
  182. room Entrance
  183.  
  184. ! Player
  185. room Entrance
  186.  
  187. ! Guard
  188. name 'Guard'
  189. desc 'A scary looking dude'
  190. room Entrance
  191. has Key
  192. likes_but_cant_handle_beer
  193. fear_tag Spider
  194.  
  195. ! Beer
  196. name 'Beer'
  197. desc 'A can of beer'
  198. room Entrance
  199. alcohol
  200. holdable
  201.  
  202. >
  203. fear_tag Self Tag
  204. room Self Room
  205. room Scary Room
  206. tag Scary Tag
  207. not has_been_scared_by Self Scary
  208.  
  209. print: '{Self} gets scared by {Scary}'
  210. add: has_been_scared_by Self Scary
  211. add: drop_all! Self
  212. break!
  213.  
  214. >
  215. likes_but_cant_handle_beer Dude
  216. has Dude Beer
  217. alcohol Beer
  218.  
  219. print: '{Dude} drinks {Beer} and fumbles'
  220. remove: has Dude Beer
  221. add: drop_all! Dude
  222. break!
  223.  
  224. >
  225. drop_all! Dude
  226. has Dude Thing
  227. print: '{Dude} drops {Thing}'
  228. remove: has Dude Thing
  229. break!
  230.  
  231. > inspect T
  232. name T Name
  233. desc T Desc
  234.  
  235. print: '{Name}: {Desc}'
  236.  
  237. > inspect Lock
  238. lock Lock Type
  239.  
  240. print: 'It has a lock that can be opened with {Type}'
  241.  
  242. > inspect Key
  243. key Key Type
  244.  
  245. print: 'Works on locks that require a {Type}'
  246.  
  247. > inspect Room
  248. ground Room Ground
  249. desc Ground Desc
  250.  
  251. print: 'Ground: {Desc}'
  252.  
  253. > inspect Thing
  254. has Someone Thing
  255.  
  256. print: 'Held by {Someone}'
  257.  
  258. > inspect Person
  259. has Person Thing
  260.  
  261. print: 'Holds {Thing}'
  262.  
  263. > inspect T
  264. likes_but_cant_handle_beer T
  265.  
  266. print: 'Likes alcohol but cannot deal with it'
  267.  
  268. > inventory
  269. has Player Thing
  270. desc Thing Desc
  271.  
  272. print: '-> {Thing}: {Desc}'
  273.  
  274. > look
  275. room Player Room
  276. room Thing Room
  277. desc Thing Desc
  278.  
  279. print: '-> {Thing}: {Desc}'
  280.  
  281. > open Lock
  282. lock Lock Type
  283. has Player Key
  284. key Key Type
  285.  
  286. print: 'You open {Lock} with {Key}'
  287. break!
  288.  
  289. > open Lock
  290. lock Lock Type
  291.  
  292. print: 'You need to have {Type} to open {Lock}'
  293. break!
  294.  
  295. > take Thing
  296. has Player Thing
  297.  
  298. print: 'You are already holding {Thing}!'
  299. break!
  300.  
  301. > take Thing
  302. has Someone Thing
  303.  
  304. print: '{Someone} is already holding {Thing}!'
  305. break!
  306.  
  307. > take Thing
  308. holdable Thing
  309.  
  310. print: 'You pick up {Thing}'
  311. add: has Player Thing
  312. break!
  313.  
  314. > take Thing
  315.  
  316. print: 'You cannot pick up {Thing}'
  317. break!
  318.  
  319. > drop Thing
  320. has Player Thing
  321.  
  322. print: 'You drop {Thing}'
  323. remove: has Player Thing
  324. break!
  325.  
  326. > drop Thing
  327.  
  328. print: 'You are not holding {Thing}!'
  329. break!
  330.  
  331. > give Someone Thing
  332. has Player Thing
  333.  
  334. print: 'You give {Thing} to {Someone}'
  335. remove: has Player Thing
  336. add: has Someone Thing
  337. break!
  338.  
  339. '''
  340.  
  341. TEST = '''
  342.  
  343. : name self name
  344. : desc self desc
  345. : look self flavor
  346. : room self room
  347. : part self room
  348. : tag self tag
  349.  
  350. ! Hangover
  351. desc 'Hangover, had a little too many yesterday'
  352.  
  353. ! Somewhere
  354. desc 'This is for sure not my apartment, no idea how I ended up here'
  355. look 'An unknown small cell apartment'
  356.  
  357. ! Window
  358. desc 'A window pointing south'
  359. look 'Morning light shines through a [window] in a blinding fashion'
  360. room Somewhere
  361.  
  362. ! Player
  363. desc 'Me!'
  364. room Somewhere
  365. tag Hangover
  366.  
  367. > look
  368. room Player Room
  369. look Room Desc
  370. print: '{Desc}'
  371.  
  372. > look
  373. room Player Room
  374. room Thing Room
  375. look Thing Desc
  376. print: '{Desc}'
  377.  
  378. > inspect {Thing}
  379. desc Thing Desc
  380. print: '{Desc}'
  381.  
  382. > inspect {Thing}
  383. tag Thing Tag
  384. desc Tag Desc
  385. print: '{Desc}'
  386.  
  387. '''
  388.  
  389. token_re = re.compile(r'(([a-zA-Z:>\-!_]+)|(\'[^\']+\'))')
  390.  
  391. def parse(s):
  392. global entities
  393. global tables
  394. ent = None
  395. cmd = None
  396.  
  397. def resolve(e):
  398. if e.startswith("'"):
  399. return e[1:-1]
  400. else:
  401. return entities[e]
  402.  
  403. for l in s.split('\n'):
  404. s = [m[0] for m in token_re.findall(l)]
  405. if not s: continue
  406. if s[0] == ':':
  407. ent = cmd = None
  408. add_table(s[1], s[2:])
  409. elif s[0] == '!':
  410. ent = cmd = None
  411. ent = Entity(s[1])
  412. entities[s[1]] = ent
  413. elif s[0] == '>':
  414. ent = cmd = None
  415. if len(s) > 1:
  416. cmd = Command(s[1], s[2:])
  417. cmd.binds.update(s[2:])
  418. commands[s[1]].append(cmd)
  419. else:
  420. cmd = Command('autocmd', ())
  421. autocmd.append(cmd)
  422. elif ent:
  423. tables[s[0]].add((ent,) + tuple(resolve(e) for e in s[1:]))
  424. elif cmd:
  425. if s[0] == 'print:':
  426. cmd.printline = resolve(s[1])
  427. elif s[0] == 'add:':
  428. cmd.add.append(s[1:])
  429. elif s[0] == 'remove:':
  430. cmd.remove.append(s[1:])
  431. elif s[0] == 'set:':
  432. cmd.set.append(s[1:])
  433. elif s[0] == 'break!':
  434. cmd.do_break = True
  435. elif s[0] == 'not':
  436. cmd.binds.update(s[2:])
  437. cmd.queries.append(Query(False, s[1], s[2:]))
  438. else:
  439. cmd.binds.update(s[1:])
  440. cmd.queries.append(Query(True, s[0], s[1:]))
  441.  
  442. parse(TEST)
  443.  
  444. def resolve(e):
  445. if e == '?':
  446. return None
  447. else:
  448. return entities[e]
  449.  
  450. def run(line):
  451. split = line.split()
  452. if not split: return
  453. if split[0] == '/query':
  454. q = tuple(resolve(e) for e in split[2:])
  455. print '\n'.join(repr(s) for s in tables[split[1]].query(q))
  456. elif split[0] == '/add':
  457. q = tuple(resolve(e) for e in split[2:])
  458. tables[split[1]].add(q)
  459. elif split[0] in commands:
  460. cmd = commands[split[0]]
  461. opts = tuple(resolve(e) for e in split[1:])
  462. for c in cmd:
  463. if c.do(opts): return
  464.  
  465.  
  466. while True:
  467. line = raw_input('> ')
  468. run(line)
  469. for i in range(10):
  470. for a in autocmd:
  471. a.do(())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement