def hit_with(self, creature, weapon): if not self.is_nearby(creature): r = ProximityFailure(creature.full_name()) elif not self.in_inventory(weapon): r = OwnershipFailure(weapon.full_name()) else: if not creature.traits.hostile: creature.become_hostile() attack_difficulty = random.randint(0, 100) if weapon.accuracy < attack_difficulty: r = Failure("Your attack misses!") else: creature.health -= weapon.damage if creature.is_alive(): r = Success( "You hit the {}. It reels from your attack!".format( creature.full_name())) else: r = Success(( "You deal the {} a fatal blow. It falls to the ground dead, " + "and its body dissolves into the hungry earth").format( creature.full_name())) for item_id in creature.inventory.items: item = self.game.vocabulary.lookup_noun(item_id) creature.inventory.remove_item(item) self.location.add_item(item) self.location.remove_item(creature, force=True) creature.location = None return r
def get(self, item): if not item.traits.portable: r = Failure("You can't carry around the {}!".format( item.full_name())) elif self.in_inventory(item): r = Failure("You already have the {}!".format(item.full_name())) elif not self.is_nearby(item): container = self.nearby_container_having(item) creature = self.nearby_creature_having(item) if container: r = self.get_from(item, container) elif creature: r = self.ask_for(creature, item) else: r = ProximityFailure(item.full_name()) else: r1 = self.location.remove_item(item) if r1.success: r2 = self.inventory.add_item(item) if r2.success: r = Success("You take the " + item.full_name()) else: self.location.add_item(item) r = Failure( "Your load is too heavy to pick up the {}".format( item.full_name())) return r
def put_in(self, item, container): if not self.is_nearby(container): r = ProximityFailure(container.full_name()) else: if not self.is_nearby(item): r = ProximityFailure(item.full_name()) else: if container == item: r = Failure("You can't put the {} {} itself!".format( container.full_name(), container.put_preposition)) else: if self.in_inventory(item): source = self.inventory else: source = self.location r1 = source.remove_item(item) if r1.success: r2 = container.add_item(item) if r2.success: r = Success("The {} {} now {} the {}".format( item.full_name(), item.existential(), container.put_preposition, container.full_name())) else: source.add_item(item) r = r2 else: r = r1 return r
def history(self): r = Success("Recent command history: \n") if len(self.command_history) > 0: for c in self.command_history: r.append("\n|" + self.prompt + c.input_text) else: r.append("(no commands yet entered)") r.append("\n") return r
def close(self, closeable): if self.is_nearby(closeable): if closeable.traits.closed: r = Failure("The {} is already closed".format( closeable.full_name())) else: closeable.traits.closed = True r = Success("You close the {}".format(closeable.full_name())) else: r = ProximityFailure(closeable.full_name()) return r
def drop(self, item): r1 = self.inventory.remove_item(item) if r1.success: r2 = self.location.add_item(item) if r2.success: r = Success("You drop the " + item.full_name()) else: r = Failure("You can't drop the " + item.full_name() + "here!") else: r = OwnershipFailure(item.full_name()) return r
def go(self, game, creature): if self.condition(game, creature): location = self.vocab.lookup_noun(self.location) destination = self.vocab.lookup_noun(self.destination) game.move_creature(creature, location, destination) r = Success("Creature moved from {} to {}".format(location.name, destination.name)) if self.after: r = self.after(game, creature, location, destination) else: r = self.fail_result return r
def consume(self, edible, adjective, verb): if not self.is_nearby(edible): r = ProximityFailure(edible.full_name()) else: self.health += edible.healing if self.in_inventory(edible): edible.consume_from(self.inventory) else: edible.consume_from(self.location) r = Success("You {} the {} {}".format(verb, adjective, edible.full_name())) return r
def remove_item(self, item, force=False): if not force and self.traits.closed: result = Failure("The " + self.full_name() + " is closed") else: if item.id in self.items: self.items.remove(item.id) result = Success("You remove the " + item.name + " from the " + self.full_name()) else: result = Failure("The {} {}n't {} the {}!".format( item.full_name(), item.existential(), self.put_preposition, self.full_name())) return result
def list_inventory(self): if len(self.inventory.items) > 0: r = Success("You are carrying:") for item_id in self.inventory.items: item = self.vocab.lookup_noun(item_id) r.append("\n\t" + item.description) else: r = Success("You're not carrying anything") return r
def open(self, openable): if self.is_nearby(openable): if openable.traits.closed: if openable.traits.locked: r = Failure( "You try to open the {}, but it is firmly locked". format(openable.full_name())) else: openable.traits.closed = False if isinstance(openable, Container): container = openable item_count = container.item_count() if item_count == 0: r = Success( "You open the {}, which is empty".format( container.full_name())) elif item_count == 1: r = Success("Opening the {} reveals a {}".format( container.full_name(), self.vocab.lookup_noun( container.items[0]).full_name())) else: r = Success("Opening the {} reveals: ".format( container.full_name())) for item_id in container.items: item = self.vocab.lookup_noun(item_id) r.append("\n\t" + item.description) else: r = Success("You open the {}".format( openable.full_name())) else: r = Failure("The {} is already open".format( openable.full_name())) else: r = ProximityFailure(openable.full_name()) return r
def lock_with(self, lockable, key): if self.is_nearby(lockable): if lockable.traits.locked: r = Failure("The {} is already locked".format( lockable.full_name())) else: if key.can_lock(lockable): lockable.traits.locked = True r = Success("The {} is now locked".format( lockable.full_name())) else: r = Failure("The {} cannot be locked with the {}!".format( lockable.full_name(), key.full_name())) else: r = ProximityFailure(lockable.full_name()) return r
def add_item(self, item, force=False): if not force and self.traits.closed: result = Failure("The " + self.full_name() + " is closed") else: if item.id in self.items: result = Failure("The {} {} already {} the {}".format( item.full_name(), item.existential(), self.put_preposition, self.full_name())) elif item.size > self.remaining_capacity(): result = Failure("Sorry, the {} won't fit {} the {}".format( item.full_name(), self.put_preposition, self.full_name())) else: self.items.append(item.id) result = Success("Okay, the {} {} now {} the {}".format( item.full_name(), item.existential(), self.put_preposition, self.full_name())) return result
def unlock_with(self, lockable, key): if self.is_nearby(lockable) or self.nearby_container_having(lockable): if not lockable.traits.locked: r = Failure("The {} is already unlocked".format( lockable.full_name())) else: if key.can_lock(lockable): lockable.traits.locked = False r = Success("The {} is now unlocked".format( lockable.full_name())) else: r = Failure( "The {} cannot be unlocked with the {}!".format( lockable.full_name(), key.full_name())) else: r = ProximityFailure(lockable.full_name()) return r
def is_valid_schema(self, schema): r = None missing_roles = set() for role in Role.values: if role in self.unassigned_roles and schema.get_role(role): r = NotUnderstoodFailure() break elif role in self.required_roles: if schema.get_role(role) is None: missing_roles.add(role) else: role_value = schema.get_role(role) if not (role in self.permissive_roles or role_value.is_valid_for_role(role, self)): r = Failure(self.role_messages[role].format( role_value.full_name())) break if r is None: # TODO: Add heuristic to guess identity of missing words, if possible if len(missing_roles) > 0: preposition = None for k, v in self.preposition_roles.items(): if v in missing_roles: preposition = k if Role.PATIENT in missing_roles: if preposition: r = Failure("What do you want to {} {}?".format( self.name, preposition)) else: r = Failure("What do you want to {}?".format( self.name)) elif Role.THEME in missing_roles or Role.INSTRUMENT in missing_roles: if preposition: r = Failure("What do you want to {} the {} {}?".format( self.name, schema[Role.PATIENT].full_name(), preposition)) else: r = Failure("What do you want to {} the {}?".format( self.name, schema[Role.PATIENT].full_name())) else: r = NotUnderstoodFailure() else: r = Success("Success") return r
def get_from(self, item, container): if isinstance(container, Creature): r = self.ask_for(container, item) else: if not self.is_nearby(container): r = ProximityFailure(container.full_name()) else: r1 = container.remove_item(item) if r1.success: r2 = self.inventory.add_item(item) if r2.success: r = Success("You take the {} from the {}".format( item.full_name(), container.full_name())) else: container.add_item(item) r = r2 else: r = r1 return r
def give_to(self, item, creature): if not self.is_nearby(creature): r = ProximityFailure(creature.full_name()) elif not self.in_inventory(item): r = OwnershipFailure(item.full_name()) elif item in creature.wanted_items: r1 = self.inventory.remove_item(item) if r1.success: r2 = creature.inventory.add_item(item) if r2.success: creature.become_friendly() r = Success("The {} gratefully accepts the {}".format( creature.full_name(), item.full_name())) else: self.inventory.add_item(item) r = r2 else: r = r1 else: r = Failure("The {} politely declines to take the {}".format( creature.full_name(), item.full_name())) return r
def create(cls, game, name, callback=lambda schema: Success("Done"), preposition_roles=None, direct_object_role=None, indirect_object_role=None, required_roles=None, permissive_roles=None, aliases=None, role_scopes=None, role_messages=None): if not preposition_roles: preposition_roles = {} if not required_roles: required_roles = {Role.AGENT} if not permissive_roles: permissive_roles = {} a = Action(game, name, callback, preposition_roles, direct_object_role, indirect_object_role, required_roles, permissive_roles, aliases, role_scopes, role_messages) game.vocabulary.register_verb(a) return a
def ask_for(self, creature, item): if not self.is_nearby(creature): r = ProximityFailure(creature.full_name()) elif not creature.in_inventory(item): r = Failure("The {} doesn't have the {}".format( creature.full_name(), item.full_name())) elif not creature.traits.friendly or item in creature.wanted_items: r = Failure("The {} is unwilling to part with the {}".format( creature.full_name(), item.full_name())) else: r1 = creature.inventory.remove_item(item) if r1.success: r2 = self.inventory.add_item(item) if r2.success: r = Success( "The {} gladly hands over the {} to you".format( creature.full_name(), item.full_name())) else: creature.inventory.add_item(item) r = r2 else: r = r1 return r
def help(self): r = Success("Available commands are: \n") r.append(', '.join(self.vocabulary.get_valid_verbs())) return r
def describe(self): return Success(self.description)
def setup_actions(self, game): Action.create( game, name='history', callback=lambda schema: schema[Role.AGENT].game.history()) Action.create(game, name='help', callback=lambda schema: schema[Role.AGENT].game.help()) Action.create(game, name='status', aliases=['score'], callback=lambda schema: schema[Role.AGENT].game.status()) Action.create(game, name='exit', aliases=['quit', 'end', 'done'], callback=lambda schema: game.exit_game()) Action.create(game, name='diagnose', callback=lambda schema: schema[Role.AGENT].diagnose()) Action.create(game, name='wait', callback=lambda schema: Success("Time passes...")) Action.create( game, name='inventory', aliases=['i'], callback=lambda schema: schema[Role.AGENT].list_inventory()) Action.create(game, name='look', aliases=['l'], direct_object_role=Role.THEME, preposition_roles={ 'at': Role.THEME, 'in': Role.THEME, 'on': Role.THEME }, callback=lambda schema: schema[Role.AGENT].look(schema[ Role.THEME])) def process_get(schema): if schema[Role.PATIENT]: r = schema[Role.AGENT].get_from(schema[Role.THEME], schema[Role.PATIENT]) else: theme = schema[Role.THEME] if isinstance(theme, Creature) and not theme.traits.portable: r = Failure( "You are unable to subdue and capture the {}!".format( theme.full_name())) elif not theme.traits.portable: r = Failure( "The {} is solidly anchored and cannot be removed". format(theme.full_name())) else: r = schema[Role.AGENT].get(schema[Role.THEME]) return r Action.create( game, name='get', aliases=['take'], required_roles={Role.AGENT}, direct_object_role=Role.THEME, preposition_roles={'from': Role.PATIENT}, role_scopes={ Role.THEME: Scope.EXTERNAL, Role.PATIENT: Scope.EXTERNAL }, role_messages={ Role.THEME: "Admire the {} all you want, you can't take it with you." }, callback=process_get) Action.create(game, name='drop', aliases=['leave'], direct_object_role=Role.THEME, required_roles={Role.AGENT, Role.THEME}, role_scopes={Role.THEME: Scope.INVENTORY}, callback=lambda schema: schema[Role.AGENT].drop(schema[ Role.THEME])) Action.create( game, name='go', aliases=['walk'], required_roles={Role.AGENT, Role.GOAL}, direct_object_role=Role.GOAL, role_messages={Role.GOAL: "That's not a direction!"}, callback=lambda schema: schema[Role.AGENT].go(schema[Role.GOAL])) Action.create(game, name='open', required_roles={Role.AGENT, Role.PATIENT}, direct_object_role=Role.PATIENT, callback=lambda schema: schema[Role.AGENT].open(schema[ Role.PATIENT])) Action.create(game, name='close', required_roles={Role.AGENT, Role.PATIENT}, direct_object_role=Role.PATIENT, callback=lambda schema: schema[Role.AGENT].close(schema[ Role.PATIENT])) Action.create( game, name='lock', required_roles={Role.AGENT, Role.PATIENT, Role.INSTRUMENT}, direct_object_role=Role.PATIENT, preposition_roles={'with': Role.INSTRUMENT}, callback=lambda schema: schema[Role.AGENT].lock_with( schema[Role.PATIENT], schema[Role.INSTRUMENT])) Action.create( game, name='unlock', required_roles={Role.AGENT, Role.PATIENT, Role.INSTRUMENT}, direct_object_role=Role.PATIENT, preposition_roles={'with': Role.INSTRUMENT}, callback=lambda schema: schema[Role.AGENT].unlock_with( schema[Role.PATIENT], schema[Role.INSTRUMENT])) Action.create(game, name='put', required_roles={Role.AGENT, Role.PATIENT, Role.THEME}, direct_object_role=Role.THEME, preposition_roles={ 'in': Role.PATIENT, 'into': Role.PATIENT, 'on': Role.PATIENT }, callback=lambda schema: schema[Role.AGENT].put_in( schema[Role.THEME], schema[Role.PATIENT])) Action.create( game, name='eat', required_roles={Role.AGENT, Role.THEME}, direct_object_role=Role.THEME, role_messages={ Role.THEME: "I don't think the {} would agree with you." }, callback=lambda schema: schema[Role.AGENT].eat(schema[Role.THEME])) Action.create(game, name='drink', required_roles={Role.AGENT, Role.THEME}, direct_object_role=Role.THEME, role_messages={ Role.THEME: "I don't think the {} would agree with you." }, callback=lambda schema: schema[Role.AGENT].drink(schema[ Role.THEME])) Action.create(game, name='greet', required_roles={Role.AGENT, Role.PATIENT}, direct_object_role=Role.PATIENT, callback=lambda schema: schema[Role.AGENT].greet(schema[ Role.PATIENT])) Action.create(game, name='smile', required_roles={Role.AGENT, Role.PATIENT}, preposition_roles={'at': Role.PATIENT}, callback=lambda schema: schema[Role.AGENT].greet(schema[ Role.PATIENT])) Action.create(game, name='wave', required_roles={Role.AGENT, Role.PATIENT}, preposition_roles={ 'at': Role.PATIENT, 'to': Role.PATIENT }, callback=lambda schema: schema[Role.AGENT].greet(schema[ Role.PATIENT])) Action.create(game, name='give', aliases=['offer'], required_roles={Role.AGENT, Role.PATIENT, Role.THEME}, direct_object_role=Role.THEME, indirect_object_role=Role.PATIENT, preposition_roles={'to': Role.PATIENT}, callback=lambda schema: schema[Role.AGENT].give_to( schema[Role.THEME], schema[Role.PATIENT])) Action.create(game, name='ask', required_roles={Role.AGENT, Role.PATIENT, Role.THEME}, direct_object_role=Role.PATIENT, preposition_roles={'for': Role.THEME}, callback=lambda schema: schema[Role.AGENT].ask_for( schema[Role.PATIENT], schema[Role.THEME])) Action.create( game, name='kill', aliases=['attack', 'fight', 'hit'], required_roles={Role.AGENT, Role.PATIENT, Role.INSTRUMENT}, direct_object_role=Role.PATIENT, preposition_roles={'with': Role.INSTRUMENT}, role_messages={ Role.INSTRUMENT: "The {} proves an ineffective choice of weapon" }, callback=lambda schema: schema[Role.AGENT].hit_with( schema[Role.PATIENT], schema[Role.INSTRUMENT])) def process_throw(schema): if schema[Role.GOAL]: r = schema[Role.AGENT].throw(schema[Role.THEME], schema[Role.GOAL]) else: r = schema[Role.AGENT].throw(schema[Role.THEME]) return r Action.create( game, name='throw', aliases=['toss', 'pitch', 'fling', 'lob'], required_roles={Role.AGENT, Role.THEME}, direct_object_role=Role.THEME, role_scopes={ Role.THEME: Scope.INVENTORY, Role.PATIENT: Scope.EXTERNAL }, preposition_roles={ 'at': Role.GOAL, 'to': Role.GOAL }, role_messages={ Role.THEME: "The {} is too unwieldy to make an effective missile", Role.GOAL: "The {} is not intended for target practice!" }, callback=lambda schema: process_throw(schema)) Action.create( game, name='smell', required_roles={Role.AGENT, Role.THEME}, direct_object_role=Role.THEME, permissive_roles={Role.THEME}, callback=lambda schema: Success("Smells like {} {} to me!".format( schema[Role.THEME].article(), schema[Role.THEME].full_name()))) Action.create(game, name='listen', required_roles={Role.AGENT, Role.THEME}, permissive_roles={Role.THEME}, preposition_roles={'to': Role.THEME}, callback=lambda schema: Success( "The {} is keeping pretty quiet right now".format( schema[Role.THEME].full_name()))) Action.create(game, name='admire', aliases=['appreciate'], direct_object_role=Role.THEME, required_roles={Role.AGENT, Role.THEME}, permissive_roles={Role.THEME}, callback=lambda schema: Success( "Breathtaking! You feel enriched by this profound " "artistic experience.")) jump_result = Success("You take a great leap into the air") jump_result.add_message("Wheeeeeee!") jump_result.add_message("Boing boing boing ...") jump_result.add_message("Up, up and away!") def process_jump(schema): return jump_result Action.create(game, name='jump', required_roles={Role.AGENT}, callback=process_jump)
def diagnose(self): return Success("Health: {}; strength: {}".format( self.health, self.strength))
def status(self): r = Success("You have a score of {} after {} turns".format( self.score, self.turns)) return r
def setup_items(self, game): # --------------- Common effects of commands def update_score(game, points): game.score += points def update_health(player, points): player.health += points def make_creature_hostile(creature): creature.become_hostile() def instant_death(player): player.health = 0 def lose_item(player, item): player.inventory.remove_item(item) def end_section(name, game, player, points): update_score(game, points) result = Result( "Congratulations! You have finished {}. ".format(name)) status = game.status() result.append(status.get_message()) return result # ---------------- Create basic locations and objects player = game.player crumbly_room = Location( game, name='Crumbly Room', description='A small storage room with crumbling plaster walls') paneled_room = Location( game, name='Wood Paneled Room', description='A large, warm room with wood-paneled walls') north_tower = Location( game, name='North Tower', description='A tower with a high ceiling and red-stained windows') balcony = Location( game, name='Balcony', description= 'A breezy, open balcony with a beautiful view of the landscape below', traits=Traits(precarious=True)) east_tower = Location( game, name='East Tower', description='The tall tower at the eastern side of the house') roof = Location( game, name='Roof', description='You are on the roof of the eastern tower. ' + 'There is a ladder leading back downwards, and to the west is an open window.', traits=Traits(precarious=True)) west_tower = Location( game, name='West Tower', description='The tall tower at the western side of the house.') master_bedroom = Location( game, 'Master Bedroom', description= 'This appears to be a former bedroom, but the bed itself is missing. ' + 'A window to the east is open.') basement = Location(game, 'Basement', description='An empty room, very drafty') garden = Location(game, 'garden', description='a lush blooming garden') patio = Location(game, 'patio', description='an empty stone patio') front_porch = Location( game, 'porch', description= 'The front porch of the house. A metal gate prevents you from leaving' ) front_porch.add_modifier('front') metal_gate = Surface( game, name='gate', description= 'An impassable metal gate with two locks: one golden and one bronze, ' + 'blocking your exit!') metal_gate.traits.closed = True metal_gate.add_modifier('metal') front_porch.add_item(metal_gate) golden_lock = Door(game, name='lock', description='a golden lock') golden_lock.add_modifier('golden') metal_gate.add_item(golden_lock, force=True) bronze_lock = Door(game, name='lock', description='a bronze lock') bronze_lock.add_modifier('bronze') metal_gate.add_item(bronze_lock, force=True) street = Location(game, 'street', description='an empty street') fancy_painting = Item( game, name='painting', description='An ornate painting of the house\'s previous owner', aliases=['portrait', 'picture'], size=15, value=100) fancy_painting.add_modifier('fancy') west_tower.add_item(fancy_painting) east_tower.add_exit(direction.west, paneled_room) crumbly_room.add_exit(direction.north, paneled_room) paneled_room.add_exit(direction.south, crumbly_room) paneled_room.add_exit(direction.north, north_tower) paneled_room.add_exit(direction.east, east_tower) paneled_room.add_exit(direction.west, west_tower) west_tower.add_exit(direction.east, paneled_room) roof.add_exit(direction.west, master_bedroom) master_bedroom.add_exit(direction.down, basement) master_bedroom.add_exit(direction.east, roof) basement.add_exit(direction.up, master_bedroom) basement.add_exit(direction.west, garden) garden.add_exit(direction.east, basement) garden.add_exit(direction.south, patio) patio.add_exit(direction.north, garden) patio.add_exit(direction.south, front_porch) front_porch.add_exit(direction.north, patio) front_porch.add_exit( direction.south, street, condition=lambda g, p: not metal_gate.traits.closed, after=lambda g, p, l, d: end_section("section one", g, p, 50), fail_result=Failure("The metal gate blocks your way")) def too_small_check(g, p): return p.inventory.used_capacity() <= 25 too_small_result = Failure( "Your load is too large to fit through the small hole") east_tower.add_exit( direction.up, roof, description='A ladder leads up to a hole in the ceiling far above', condition=too_small_check, fail_result=too_small_result) roof.add_exit( direction.down, east_tower, description="There is a hole here leading down to the tower below", condition=too_small_check, fail_result=too_small_result) sturdy_door = Door( game, name='door', description= 'A sturdy door leading out to the balcony above the tower') sturdy_door.add_modifier('sturdy') silver_key = Key(game, name='key', description='A brilliant silver key') silver_key.add_modifier('silver') steel_key = Key(game, name='key', description='A small steel key') steel_key.add_modifier('steel') steel_key.set_lockable(sturdy_door) roof.add_item(steel_key) north_tower.add_item(sturdy_door) north_tower.add_exit(direction.south, paneled_room) north_tower.add_exit( direction.up, balcony, description="Stairs lead up to a door high above", condition=lambda g, p: not sturdy_door.traits.closed, fail_result=Failure("A sturdy door blocks the way")) balcony.add_exit(direction.down, north_tower) light_thing = Item( game, name='thing', description='An easily carried thing, light as a feather', size=0) light_thing.add_modifier('light') fragile_thing = Item(game, name='thing', description='An easily breakable, delicate thing', traits=Traits(fragile=True), size=15) fragile_thing.add_modifier('fragile') heavy_thing = Item( game, name='thing', description='A heavy block of some unknown material', size=45) heavy_thing.add_modifier('heavy') trunk = Container(game, name='trunk', description='An old wooden trunk', aliases=['chest', 'box'], size=75, value=5, capacity=90) trunk.add_modifier('wooden') sword = Weapon(game, name='sword', description='A serviceable iron sword', size=15, value=15, damage=50, defense=10, accuracy=80) sword.add_modifier('iron') trunk.add_item(sword, force=True) diamond = Item(game, name='diamond', aliases=['gem', 'jewel'], size=5, value=100, description='A brilliant diamond') apple = Edible(game, name='apple', description='A delicious, juicy red apple', size=15, value=5) small_table = Surface(game, name='table', description='A small table', size=20, capacity=15) small_table.add_modifier('small') small_table.add_item(apple, force=True) large_table = Surface(game, name='table', description='A large table', size=75, capacity=100) large_table.add_modifier('large') large_table.add_item(heavy_thing, force=True) large_table.add_item(light_thing, force=True) large_table.add_item(fragile_thing, force=True) bread = Edible(game, name='bread', description='A loaf of crusty brown bread', size=20, value=5, healing=10) puddle = Drinkable(game, name='puddle', aliases=['water'], description='A puddle of refreshing water', size=25, value=5, healing=15) mouse = Item( game, name='mouse', description='A small mouse scampers back and forth across the ' + 'room here, searching for food. It is carrying something ' 'shiny in its mouth.', traits=Traits(compelling=True), size=0, value=0) mouse.add_modifier('brown') west_tower.add_item(mouse) core = Item(game, name='core', description='The core of an eaten apple', size=5, value=0) core.add_modifier('apple') apple.add_consumed(core) crumbs = Edible(game, name='crumbs', description='A small pile of leftover bread crumbs', aliases=['pile'], traits=Traits(composite=True, plural=True), size=5, value=0, healing=0) bread.add_consumed(crumbs) mud = Item(game, name='mud', description='A clump of soggy wet mud', traits=Traits(composite=True), size=15, value=1) puddle.add_consumed(mud) vase = Container(game, name='flowerpot', description='a patterned flowerpot', aliases=['flowerpot', 'pot', 'vase'], traits=Traits(closed=False, fragile=True), size=5, value=10, capacity=3) flower = Item(game, name='flower', description='a beautiful, fragrant sunflower', size=3, value=5) crumbly_room.add_item(small_table) crumbly_room.add_item(large_table) paneled_room.add_item(trunk) paneled_room.add_item(puddle) vase.add_item(flower) balcony.add_item(vase) villager = Creature( game, name='villager', traits=Traits(mobile=True), aliases=['farmer'], description="A stout but simple villager in farming garb", health=75, strength=25, dexterity=65, location=paneled_room) villager.add_wanted_item(apple) villager.add_item(diamond) golden_key = Key(game, name='key', description='A fashionable golden key') golden_key.add_modifier('golden') golden_key.set_lockable(golden_lock) red_fox = Creature(game, name='fox', traits=Traits(hostile=True, mobile=False), description="a bloodthirsty red fox", health=65, strength=15, dexterity=50, location=front_porch) red_fox.add_modifier('red') red_fox.add_item(golden_key) bronze_key = Key(game, name='key', description='A dull bronze key') bronze_key.add_modifier('bronze') bronze_key.set_lockable(bronze_lock) brown_fox = Creature(game, name='fox', traits=Traits(hostile=True, mobile=False), description="a vicious brown fox", health=65, strength=25, dexterity=50, location=front_porch) brown_fox.add_modifier('brown') red_fox.add_item(bronze_key) townsfolk = Creature( game, name='townsfolk', traits=Traits(mobile=True), description='A short, well-dressed man with a stubbly beard', aliases=['folk', 'man'], health=75, strength=30, dexterity=65, location=north_tower) townsfolk.add_wanted_item(diamond) townsfolk.add_item(bread) def shadow_action(game, player): player.health -= 5 return Result("A dark shadow looms ominously in the corner") shadow = Creature( game, name='shadow', traits=Traits(hostile=False, mobile=True, evident=False), description= 'You attempt to examine the shadow, but your vision blurs as you try to focus ' 'on its constantly shifting shape, preventing you from forming ' 'any clear impression', health=9001, strength=20, dexterity=90, location=east_tower) shadow.add_modifier('dark') shadow.entry_action = lambda g, p: Result( "A dark shadow enters. The temperature in the room drops " "several degrees, as does your blood") shadow.exit_action = lambda g, p: Result( "The shadow leaves the room, and you once again find " "you can breathe freely") shadow.present_action = shadow_action # -------- Consequences: game milestones and achievements, and special results vocabulary = game.vocabulary open = vocabulary.lookup_verb_by_name('open') get = vocabulary.lookup_verb_by_name('get') ask = vocabulary.lookup_verb_by_name('ask') smell = vocabulary.lookup_verb_by_name('smell') jump = vocabulary.lookup_verb_by_name('jump') drop = vocabulary.lookup_verb_by_name('drop') throw = vocabulary.lookup_verb_by_name('throw') kill = vocabulary.lookup_verb_by_name('kill') unlock = vocabulary.lookup_verb_by_name('unlock') # Trying to pick up creatures turns them hostile for creature in vocabulary.get_objects_of_class(Creature): get.add_consequence(schema=Schema(roles={ Role.AGENT: player, Role.THEME: creature }), necessary_result=result.GENERIC_FAILURE, effect=lambda schema: make_creature_hostile( schema[Role.THEME])) # Be careful in precarious places! for room in vocabulary.get_objects_of_class(Location): if room.traits.precarious: jump.add_consequence( schema=Schema(roles={Role.AGENT: player}), necessary_result=result.GENERIC_SUCCESS, necessary_location=room, effect=lambda schema: instant_death(player), consequent_result=Success( "In your excitement, you slip and fall to the hard ground far below!\n" + "You should probably be more careful where you do your jumping." )) # TODO: Some kind of pattern-matching logic here. This configures for _no_ theme, not _any_ theme ... throw.add_consequence( schema=Schema(roles={Role.AGENT: player}), necessary_result=result.GENERIC_FAILURE, necessary_location=room, effect=lambda schema: lose_item(player, schema[Role.THEME] ), consequent_result=Failure( "You toss it carelessly, and it sails over the edge and out of sight" )) # The mouse is too fast to catch or kill, but it's hungry def fed_mouse(crumbs): west_tower.remove_item(mouse) west_tower.remove_item(crumbs) west_tower.add_item(silver_key) get.add_consequence( schema=Schema(roles={ Role.AGENT: player, Role.THEME: mouse }), necessary_result=result.GENERIC_SUCCESS, necessary_location=west_tower, effect=lambda schema: player.drop(mouse), consequent_result=Failure( "You try, but the mouse is far too small and fast for you to catch!" )) drop.add_consequence(schema=Schema(roles={ Role.AGENT: player, Role.THEME: crumbs }), necessary_result=result.GENERIC_SUCCESS, necessary_location=west_tower, effect=lambda schema: update_score(game, 20)) drop.add_consequence( schema=Schema(roles={ Role.AGENT: player, Role.THEME: crumbs }), necessary_result=result.GENERIC_SUCCESS, necessary_location=west_tower, effect=lambda schema: fed_mouse(crumbs), consequent_result=Success( "The mouse devours the crumbs, dropping something shiny to the floor in the " "process. It then returns to its hole, well-fed and content")) # Foxes work cooperatively! def killed_fox(dead_fox, other_fox, key): dead_fox.remove_item(key) if other_fox.is_alive: other_fox.add_item(key) return result.GENERIC_SUCCESS else: return result.GENERIC_FAILURE kill.add_consequence( schema=Schema(roles={ Role.AGENT: player, Role.THEME: red_fox }), necessary_result=result.GENERIC_SUCCESS, effect=killed_fox(red_fox, brown_fox, golden_key), consequent_result=Success( "As the red fox falls dead to the ground, its brother retrieves " "the golden key from its lifeless form")) kill.add_consequence( schema=Schema(roles={ Role.AGENT: player, Role.THEME: brown_fox }), necessary_result=result.GENERIC_SUCCESS, effect=killed_fox(brown_fox, red_fox, bronze_key), consequent_result=Success( "As the brown fox falls dead to the ground, its brother retrieves " "the bronze key from its lifeless form")) # Achievement: unlock and open the sturdy door open.add_consequence(schema=Schema(roles={ Role.AGENT: player, Role.PATIENT: sturdy_door }), necessary_result=result.GENERIC_SUCCESS, effect=lambda schema: update_score(game, 10)) # Achievement: get the diamond from the villager ask.add_consequence( schema=Schema(roles={ Role.AGENT: player, Role.PATIENT: villager, Role.THEME: diamond }), necessary_result=result.GENERIC_SUCCESS, effect=lambda schema: update_score(game, 20)) get.add_consequence(schema=Schema(roles={ Role.AGENT: player, Role.THEME: diamond }), necessary_result=result.GENERIC_SUCCESS, effect=lambda schema: update_score(game, 20)) get.add_consequence( schema=Schema(roles={ Role.AGENT: player, Role.PATIENT: villager, Role.THEME: diamond }), necessary_result=result.GENERIC_SUCCESS, effect=lambda schema: update_score(game, 20)) # Health bonus: smell the sunflower smell.add_consequence( schema=Schema(roles={ Role.AGENT: player, Role.THEME: flower }), necessary_result=result.GENERIC_SUCCESS, effect=lambda schema: update_health(player, 10), consequent_result=Success( "You feel revived by the bloom's invigorating fragrance")) def unlock_gate(this_lock, other_lock): this_lock.traits.locked = False if other_lock.traits.locked: return result.GENERIC_FAILURE else: update_score(game, 50) metal_gate.traits.closed = False return result.GENERIC_SUCCESS unlock.add_consequence( schema=Schema( roles={ Role.AGENT: player, Role.THEME: golden_lock, Role.INSTRUMENT: golden_key }), necessary_result=result.GENERIC_SUCCESS, effect=lambda schema: unlock_gate(golden_lock, bronze_lock), consequent_result=WON_GAME) unlock.add_consequence( schema=Schema( roles={ Role.AGENT: player, Role.THEME: golden_lock, Role.INSTRUMENT: golden_key }), necessary_result=result.GENERIC_SUCCESS, effect=lambda schema: unlock_gate(golden_lock, bronze_lock), consequent_result=WON_GAME) # Start game in crumbly room return crumbly_room