-
-
Save mtensor/9fb4c5370be62579623e14d4aaf5c944 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#worldmodel.py | |
class CommandError(Exception): | |
pass | |
class QueryError(Exception): | |
pass | |
class FancyDefaultDict(dict): | |
def __init__(self, fn): | |
super(FancyDefaultDict, self).__init__() | |
self.fn = fn | |
def __missing__(self, key): | |
res = self[key] = self.fn(key) | |
return res | |
class PlacesEnv: | |
def __init__(self): | |
self.locations = FancyDefaultDict( lambda locName: Location(locName) ) | |
self.objects = FancyDefaultDict( lambda objName: Obj(objName) ) | |
self.people = FancyDefaultDict( lambda personName: Person(personName) ) | |
self.commands = [] | |
def reset(self): | |
self.locations = FancyDefaultDict( lambda locName: Location(locName) ) | |
self.objects = FancyDefaultDict( lambda objName: Obj(objName) ) | |
self.people = FancyDefaultDict( lambda personName: Person(personName) ) | |
def go(self, personName, locName): | |
person = self.people[personName] | |
loc = self.locations[locName] | |
person.go(loc) | |
def pickup(self, personName, objName): | |
obj = self.objects[objName] | |
assert obj.holder is None #TODO change to homegrown error | |
person = self.people[personName] | |
person.pickup(obj) | |
def drop(self, personName, objName): | |
obj = self.objects[objName] | |
person = self.people[personName] | |
#assert person.loc is not None #TODO change to homegrown error | |
person.drop(obj) | |
def queryObjLoc(self, objName): | |
obj = self.objects[objName] | |
return obj.loc.name | |
def queryInventoryCount(self, personName): | |
person = self.people[personName] | |
n = len(person.inventory) | |
return ['none', 'one', 'two', 'three', 'four'][n] | |
def queryInventoryIdentities(self, personName): | |
person = self.people[personName] | |
return person.inventory.join(',') | |
def queryPriorLocation(self, objName, locName): | |
obj = self.objects[objName] | |
loc = self.locations[locName] | |
for i, l in reverse(obj.loc_history): | |
if loc == l: return obj.loc_history[-1 -i -1] #the thing before i | |
assert False #TODO change to homegrown error | |
def confirmPersonLoc(self, personName, locName): | |
person = self.people[personName] | |
loc = self.locations[locName] | |
return person.loc == loc #TODO return different type | |
def give(self, giverName, receiverName, objName): | |
obj = self.objects[objName] | |
giver = self.people[giverName] | |
receiverName = self.people[giverName] | |
giver.give(obj, receiver) | |
def add_unparsed_sentence(self, raw_text): | |
self.reset() | |
self.commands.append(raw_text) | |
try: | |
for command in self.commands: | |
self.parse_command(command) | |
except (AssertionError, ValueError) as e: | |
self.commands.pop() | |
self.reset() | |
raise CommandError | |
def parse_command(self, raw_text): | |
command, rest = raw_text.strip().split('(') | |
args = rest[:-1].split(', ') | |
if command == 'go': | |
self.go(args[0], args[1]) | |
elif command == 'pickup': | |
self.pickup(args[0], args[1]) | |
elif command == 'drop': | |
self.drop(args[0], args[1]) | |
else: assert False, f"unsupported command {command}" | |
return raw_text | |
def add_query(self, raw_question): | |
try: | |
return self.parse_query(raw_question) | |
except AttributeError: | |
raise QueryError | |
def parse_query(self, raw_question): | |
command, rest = raw_question.strip().split("(") | |
arg = rest[:-1] | |
if command == 'queryObjLoc': | |
return self.queryObjLoc(arg) | |
else: assert False, f"unsupported command {command}" | |
class Location: | |
def __init__(self, name): | |
self.name = name | |
def __repr__(self): return self.name | |
def __hash__(self): return hash(self.name+'42') | |
class OptionLocation: | |
pass | |
class Person: | |
def __init__(self, name): | |
self.name = name | |
self.inventory = [] | |
self.loc = None | |
def __hash__(self): return hash(self.name+'42') | |
def go(self, newLoc): | |
assert newLoc != self.loc | |
self.loc = newLoc | |
for obj in self.inventory: #TODO | |
obj.move(newLoc) | |
def pickup(self, obj): | |
assert obj.holder is None #TODO change to homegrown error | |
obj.holder = self | |
assert obj.name not in [o.name for o in self.inventory] | |
obj.loc = self.loc | |
self.inventory.append(obj) | |
def drop(self, obj): | |
obj.holder = None | |
obj.holder_history.append(self) | |
self.inventory.remove(obj) #TODO change to homegrown error | |
def give(self, obj, receiver): | |
assert obj.holder == self #TODO change to homegrown error | |
obj.holder_history.append(self) | |
self.inventory.remove(obj) #TODO change to homegrown error | |
obj.holder = receiver | |
if self.loc and receiver.loc: | |
assert self.loc == receiver.loc | |
self.inventory.remove(obj) #TODO change to homegrown error | |
receiver.inventory.append(obj) | |
class Obj: | |
def __init__(self, name): | |
self.name = name | |
self.loc = None | |
self.loc_history = [] | |
self.holder = None | |
self.holder_history = [] | |
def __hash__(self): return hash(self.name+'42') | |
def move(self, loc): | |
if self.loc is not None: | |
self.loc_history.append(self.loc) | |
self.loc = loc | |
if __name__ == '__main__': | |
e = PlacesEnv() | |
e.go('Max', 'office') | |
e.go('Eric', 'roof') | |
e.pickup('Max', 'apple') | |
e.pickup('Eric', 'milk') | |
e.go('Max', 'basement') | |
e.pickup('Max', 'football') | |
e.drop('Max', 'apple') | |
print(e.queryObjLoc('apple')) | |
print(e.queryObjLoc('milk')) | |
print(e.queryObjLoc('football')) | |
print(Person("max") == Person("max")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment