name: guild
aliases: [ guilds, class, classes, roles, role, sect ]
text: *content of the help topic*
import re
OMIT = set(['a', 'an', 'of', 'the', 'for', 'with', 'on', 'to', 'at', 'in',
'is', 'my', 'that', 's'])
def keyset(phrase):
non_alpha = re.compile("[^a-zA-Z]+")
words = non_alpha.split(phrase.lower())
keys = set(words) - OMIT
return keys
def lockset(name, keywords=None):
if not keywords:
keywords = []
locks = set(keywords)
locks = locks | keyset(name)
return locks
def unlock(phrase, lockset):
keys = keyset(phrase)
return bool( keys and keys <= lockset )
#!/usr/bin/env python
import re
class LockTrie(object):
omit = set(['a', 'an', 'of', 'the', 'for', 'with', 'on', 'to', 'at', 'in',
'is', 'my', 'that',])
non_alpha = re.compile("[^a-zA-Z]+")
class _Node(object):
def __init__(self):
self.nodes = {}
def has(self, char):
return self.nodes.get(char, False)
def add(self, char):
if char in self.nodes:
node = self.nodes[char]
else:
node = LockTrie._Node()
self.nodes[char] = node
return node
def __init__(self):
self.root = LockTrie._Node()
def _add_word(self, word):
node = self.root
for char in word:
node = node.add(char)
def _has_word(self, word):
node = self.root
for char in word:
node = node.has(char)
if not node:
return False
return bool(word and True)
def _split(self, phrase):
phrase = phrase.replace("\'", "") ## guard's == guards
words = set(self.non_alpha.split(phrase.lower()))
return words - self.omit
def add_phrase(self, phrase):
words = self._split(phrase)
for word in words:
self._add_word(word)
def unlock(self, phrase):
words = self._split(phrase)
if not words:
return False
for word in words:
if not self._has_word(word):
return False
return True
lock = LockTrie()
lock.add_phrase("Captain's Red Runed Battle-Axe of the Seas")
print 'A', lock.unlock("captains axe")
print 'B', lock.unlock("captain's axe")
print 'C', lock.unlock("captain axe")
print 'D', lock.unlock("red rune axe")
print 'E', lock.unlock("red runed axe")
print 'F', lock.unlock("battle-axe")
print 'G', lock.unlock("red battleaxe")
lock.add_phrase("battleaxe")
print 'H', lock.unlock("red battleaxe")
print 'I', lock.unlock("bAtTlE-aXe Of ThE sEaS")
print 'J', lock.unlock("of the")
A True
B True
C True
D True
E True
F True
G False
H True
I True
J False
take all
take gold
take an axe
take the broadsword
take 30 arrows
take 1 of everything
take hammer of might
OTOH, I'm not trying to pass the Turning test and I'm reluctant to add fields that represent extra work for designers unless there's a good reason for it.
My initial thoughts are something like this; for each object in the room:
Pass 1) test argument against the item name. If a full match, return item.
Pass 2) test argument against builder provided aliases (if any). If a full match, return item.
Pass 3) test argument against the item name again. If partial match, return item.
These don't really have to be three separate iterations, we could just do one with weighted guesses.
We kill the dragon and in his treasure vault we see:
A) Shield of Blade Turning
B) Dark Runed Claymore
C) Rune Etched Stilleto
D) Dagger of Slaying
> take shield of blade turning (full name match, no ambiguity)
> take dagger (C matches on type, D matches on type and partial name)
> take blade (B,C,D all match on type, A matches on partial name)
> take sword (B matches on type)
> take Rune (B matches on partial name, C matches better – partial name and word boundary)
Reading that over, I'm thinking that 'blade' is too vague to be a useful alias but 'sword' isn't. But what about the 'Naginata of the Last Word'? It's a kinda sword on a stick. 'Polearm' is a possible alias but I doubt someone would type it so that item probably wouldn't have an alias at all.
I've skipped specifying quantities, numeric index (get blade 3), or objects laying on objects (take book from table), but this is probably enough for the moment.
Time for more coffee.